[rust_crates] Add trust-dns-[proto,resolver]

Bug: 43449, 43467, 20808
Change-Id: Ibfcc06d37401193afa061a9afdd6c7ceadb063cc
diff --git a/third_party/rust_crates/Cargo.lock b/third_party/rust_crates/Cargo.lock
index c83e479..f28dae0 100644
--- a/third_party/rust_crates/Cargo.lock
+++ b/third_party/rust_crates/Cargo.lock
@@ -54,7 +54,7 @@
 
 [[package]]
 name = "async-trait"
-version = "0.1.11"
+version = "0.1.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -84,21 +84,21 @@
 
 [[package]]
 name = "backtrace"
-version = "0.3.13"
+version = "0.3.42"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "backtrace-sys 0.1.28",
+ "backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.8",
 ]
 
 [[package]]
 name = "backtrace-sys"
-version = "0.1.28"
+version = "0.1.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
+ "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -545,11 +545,22 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
+name = "enum-as-inner"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "error-chain"
 version = "0.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "backtrace 0.3.42 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -642,7 +653,7 @@
 version = "0.1.0"
 dependencies = [
  "anyhow 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "async-trait 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "async-trait 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "bincode 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitfield 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -766,6 +777,8 @@
  "tracing 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "tracing-futures 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "tracing-subscriber 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "trust-dns-proto 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "trust-dns-resolver 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "unic-char-range 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "unic-ucd-block 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1194,6 +1207,11 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
+name = "linked-hash-map"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "lipsum"
 version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1235,6 +1253,14 @@
 ]
 
 [[package]]
+name = "lru-cache"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "maplit"
 version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2493,6 +2519,11 @@
 ]
 
 [[package]]
+name = "smallvec"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "snowflake"
 version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2978,6 +3009,40 @@
 ]
 
 [[package]]
+name = "trust-dns-proto"
+version = "0.19.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "async-trait 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "backtrace 0.3.42 (registry+https://github.com/rust-lang/crates.io-index)",
+ "enum-as-inner 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "trust-dns-resolver"
+version = "0.19.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "backtrace 0.3.42 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "trust-dns-proto 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "try-lock"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3352,6 +3417,10 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[patch.unused]]
+name = "backtrace-sys"
+version = "0.1.28"
+
+[[patch.unused]]
 name = "cmake"
 version = "0.1.99"
 
@@ -3368,11 +3437,12 @@
 "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee"
 "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71"
 "checksum ascii 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "97be891acc47ca214468e09425d02cef3af2c94d0d82081cd02061f996802f14"
-"checksum async-trait 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "153d1add2273943aef00490c3a43cf078478c7f6be623a5a8254c775fd6f987d"
+"checksum async-trait 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "c8df72488e87761e772f14ae0c2480396810e51b2c2ade912f97f0f7e5b95e3c"
 "checksum atom 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3c86699c3f02778ec07158376991c8f783dd1f2f95c579ffaf0738dc984b2fe2"
 "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
 "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799"
-"checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5"
+"checksum backtrace 0.3.42 (registry+https://github.com/rust-lang/crates.io-index)" = "b4b1549d804b6c73f4817df2ba073709e96e426f12987127c48e6745568c350b"
+"checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491"
 "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
 "checksum base64 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c4a342b450b268e1be8036311e2c613d7f8a7ed31214dff1cc3b60852a3168d"
 "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643"
@@ -3426,6 +3496,7 @@
 "checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90"
 "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0"
 "checksum encode_unicode 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "90b2c9496c001e8cb61827acdefad780795c42264c137744cae6f7d9e3450abd"
+"checksum enum-as-inner 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "900a6c7fbe523f4c2884eaf26b57b81bb69b6810a01a236390a7ac021d09492e"
 "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02"
 "checksum euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d1a7698bdda3d7444a79d33bdc96e8b518d44ea3ff101d8492a6ca1207b886ea"
 "checksum euclid_macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdcb84c18ea5037a1c5a23039b4ff29403abce2e0d6b1daa11cf0bde2b30be15"
@@ -3482,11 +3553,13 @@
 "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
 "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
 "checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
+"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83"
 "checksum lipsum 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "58e4464067d52ca040073c04dfd9185658ec8a32236b857b5e1577f9d19f9d5a"
 "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c"
 "checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc"
 "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
 "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
+"checksum lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c"
 "checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43"
 "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
 "checksum maybe-owned 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "006ac35c23dc00cd88083b27297224aedc893d628aff7374352b4f3d57315fa9"
@@ -3623,6 +3696,7 @@
 "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac"
 "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
 "checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6"
+"checksum smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44e59e0c9fa00817912ae6e4e6e3c4fe04455e75699d06eedc7d85917ed8e8f4"
 "checksum snowflake 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "27207bb65232eda1f588cf46db2fee75c0808d557f6b3cf19a75f5d6d7c94df1"
 "checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
 "checksum splines 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "19661e5f61c8c7e5e980737a63cab7281efdb68ca0de6172d4be86658c7d7114"
@@ -3671,6 +3745,8 @@
 "checksum tracing-futures 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "107ae59580d2a1d994b6b965b16fe94c969fe86d3f7fd2572a1ee243bcaf7f09"
 "checksum tracing-log 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e0f8c7178e13481ff6765bd169b33e8d554c5d2bbede5e32c356194be02b9b9"
 "checksum tracing-subscriber 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "192ca16595cdd0661ce319e8eede9c975f227cdaabc4faaefdc256f43d852e45"
+"checksum trust-dns-proto 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)" = "da8316d3a7fa285971a602e42ec6d31639cc3744e77694d89fea42152968063b"
+"checksum trust-dns-resolver 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4b1d87b791540d243a84329cc922a76daf9b89680053f947873ca89078a14a77"
 "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382"
 "checksum twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1"
 "checksum typed-arena 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c6c06a92aef38bb4dc5b0df00d68496fc31307c5344c867bb61678c6e1671ec5"
diff --git a/third_party/rust_crates/Cargo.toml b/third_party/rust_crates/Cargo.toml
index f1f0258..1cd9a9a 100644
--- a/third_party/rust_crates/Cargo.toml
+++ b/third_party/rust_crates/Cargo.toml
@@ -151,8 +151,10 @@
 smallvec = "0.6"
 static_assertions = "0.3.1"
 textwrap = "0.11.0"
-tokio-rustls = "0.10.2" # For its async server TlsAcceptor/TlsStream types. Not actually using tokio.
 time = "0.1"
+tokio-rustls = "0.10.2" # For its async server TlsAcceptor/TlsStream types. Not actually using tokio.
+trust-dns-proto = { version = "0.19.2", default-features = false, features = ["testing"] }
+trust-dns-resolver = { version = "0.19.2", default-features = false, features = ["testing"] }
 unicode-normalization = "0.1"
 unicode-segmentation = "1.0"
 unicode-width = "0.1.3"
diff --git a/third_party/rust_crates/crate_map.json b/third_party/rust_crates/crate_map.json
index 39af228..e39a7b8 100644
--- a/third_party/rust_crates/crate_map.json
+++ b/third_party/rust_crates/crate_map.json
@@ -576,6 +576,16 @@
             "package_name": "tracing-subscriber"
         },
         {
+            "crate_name": "trust_dns_proto",
+            "crate_type": "lib",
+            "package_name": "trust-dns-proto"
+        },
+        {
+            "crate_name": "trust_dns_resolver",
+            "crate_type": "lib",
+            "package_name": "trust-dns-resolver"
+        },
+        {
             "crate_name": "unic_char_range",
             "crate_type": "lib",
             "package_name": "unic-char-range"
diff --git a/third_party/rust_crates/vendor/async-trait/.cargo-checksum.json b/third_party/rust_crates/vendor/async-trait/.cargo-checksum.json
index 9017be0..16f2fa5 100644
--- a/third_party/rust_crates/vendor/async-trait/.cargo-checksum.json
+++ b/third_party/rust_crates/vendor/async-trait/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"242c3c03d903bd81819a5cfc2c0a04d831b24e3b56754e4f87e80821e2884f5d","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"3b1489162aff8c301abdefc89bb045608b86cfda682545905ba91a1e84d30068","src/args.rs":"6eed5497db91752b3aae597943c39e769f60406b37055304e69e4699f1f87b15","src/expand.rs":"8e97ab9e9ba5c886fec8ce6a1d77a41f33c541346d94fbbc1cb78770d02d1584","src/lib.rs":"9f560866bd00689559e871c038ecce0836eb073af1c7a907fbdc0121811a2ea4","src/lifetime.rs":"b238ae402d7bfba2fdf6b7e6b17fd60587a35af79f56c306cde4a52569bd45d8","src/parse.rs":"fdb82b80f74505d7967e7c2608023e4649d8b4ef26183b7a19da90558b947a39","src/receiver.rs":"7a2f50021c99134aafdedc4eff984fd73ee123df008554b984e91778eef2ed76","tests/test.rs":"fc985c8125cd6ae51c1856690a1c8f60e2802dd835ae7044d5d33dbb0b1351bf"},"package":"153d1add2273943aef00490c3a43cf078478c7f6be623a5a8254c775fd6f987d"}
\ No newline at end of file
+{"files":{"Cargo.toml":"895561e50ac299f8d10f624d587411ff22c6ecc393d0b82b2788cc0312349be5","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"f3bff9f787cb295496915cd37aaf3f80e08edebdd9604cbd6bcdaa8028e28d33","src/args.rs":"6eed5497db91752b3aae597943c39e769f60406b37055304e69e4699f1f87b15","src/expand.rs":"32000834ae9f6b34cc7d77e0c422332f65256863cc4fee348ce9e80d9df3588e","src/lib.rs":"23614cbb72bc3854038a4bd0572dfb80ff31c7707edc1525ecc2b5a08b8e428d","src/lifetime.rs":"25e559c34ff468c46f5587b70f7d62952b2a3d27594403a06e979d8dcc305b02","src/parse.rs":"2d99893d58a50391c9ae470bf924f23fa284f5eb99482119e3bcc4e781a82cf8","src/receiver.rs":"82974aa1eccb3c353eeb3d1ab405d5454fb6ce6ca060256949cc9c42754a3e9e","tests/compiletest.rs":"0a52a44786aea1c299c695bf948b2ed2081e4cc344e5c2cadceab4eb03d0010d","tests/executor/mod.rs":"620975b33cc2a494efb6bce230cf285a462b85e5fe12d71561b5bacd9d507b28","tests/test.rs":"12dacb2d21064f3273437eb29ca6eee93c9127c74986eb5647cb707c8c07de2f","tests/ui/send-not-implemented.rs":"5f1dd26f4eb34c653048e9658fbf6b41e2930d6222869b397ca4d8d7113a2809","tests/ui/send-not-implemented.stderr":"01f7df5b0efb3fa890cc4e26be520fb3fe59bb9ea9be349c7b971b6cde9d2308","tests/ui/unsupported-self.rs":"f7855bc39dab1fd2f533fb2e873a27c3757dcb9fb57001e4b19f58d3dda36d01","tests/ui/unsupported-self.stderr":"2b30517b790c666ea85442afc1c701ddc235d091372e175009aa084bd57b7070"},"package":"c8df72488e87761e772f14ae0c2480396810e51b2c2ade912f97f0f7e5b95e3c"}
\ No newline at end of file
diff --git a/third_party/rust_crates/vendor/async-trait/Cargo.toml b/third_party/rust_crates/vendor/async-trait/Cargo.toml
index 3df4ac3..128db64 100644
--- a/third_party/rust_crates/vendor/async-trait/Cargo.toml
+++ b/third_party/rust_crates/vendor/async-trait/Cargo.toml
@@ -13,7 +13,7 @@
 [package]
 edition = "2018"
 name = "async-trait"
-version = "0.1.11"
+version = "0.1.22"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 description = "Type erasure for async trait methods"
 documentation = "https://docs.rs/async-trait"
@@ -32,6 +32,14 @@
 [dependencies.syn]
 version = "1.0"
 features = ["full", "visit-mut"]
+[dev-dependencies.rustversion]
+version = "1.0"
+
+[dev-dependencies.trybuild]
+version = "1.0.19"
+features = ["diff"]
 
 [features]
 support_old_nightly = []
+[badges.travis-ci]
+repository = "dtolnay/async-trait"
diff --git a/third_party/rust_crates/vendor/async-trait/README.md b/third_party/rust_crates/vendor/async-trait/README.md
index e093065..026e24a 100644
--- a/third_party/rust_crates/vendor/async-trait/README.md
+++ b/third_party/rust_crates/vendor/async-trait/README.md
@@ -6,7 +6,7 @@
 [![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/async-trait)
 
 The async/await language feature is on track for an initial round of
-stabilizations in Rust 1.38 (tracking issue: [rust-lang/rust#62149]), but this
+stabilizations in Rust 1.39 (tracking issue: [rust-lang/rust#62149]), but this
 does not include support for async fn in traits. Trying to include an async fn
 in a trait produces the following error:
 
@@ -28,6 +28,12 @@
 
 This crate provides an attribute macro to make async fn in traits work.
 
+Please refer to [*why async fn in traits are hard*][hard] for a deeper analysis
+of how this implementation differs from what the compiler and language hope to
+deliver in the future.
+
+[hard]: https://smallcultfollowing.com/babysteps/blog/2019/10/26/async-fn-in-traits-are-hard/
+
 <br>
 
 ## Example
@@ -116,7 +122,7 @@
             /* the original method body */
         }
 
-        Pin::from(Box::new(run(self)))
+        Box::pin(run(self))
     }
 }
 ```
diff --git a/third_party/rust_crates/vendor/async-trait/src/expand.rs b/third_party/rust_crates/vendor/async-trait/src/expand.rs
index f93dd04..7cc57222 100644
--- a/third_party/rust_crates/vendor/async-trait/src/expand.rs
+++ b/third_party/rust_crates/vendor/async-trait/src/expand.rs
@@ -1,8 +1,10 @@
 use crate::lifetime::{has_async_lifetime, CollectLifetimes};
 use crate::parse::Item;
-use crate::receiver::{has_self_in_block, has_self_in_sig, ReplaceReceiver};
+use crate::receiver::{
+    has_self_in_block, has_self_in_sig, has_self_in_where_predicate, ReplaceReceiver,
+};
 use proc_macro2::{Span, TokenStream};
-use quote::{format_ident, quote, ToTokens};
+use quote::{format_ident, quote, quote_spanned, ToTokens};
 use std::mem;
 use syn::punctuated::Punctuated;
 use syn::visit_mut::VisitMut;
@@ -35,6 +37,22 @@
     },
 }
 
+impl Context<'_> {
+    fn lifetimes<'a>(&'a self, used: &'a [Lifetime]) -> impl Iterator<Item = &'a GenericParam> {
+        let generics = match self {
+            Context::Trait { generics, .. } => generics,
+            Context::Impl { impl_generics, .. } => impl_generics,
+        };
+        generics.params.iter().filter(move |param| {
+            if let GenericParam::Lifetime(param) = param {
+                used.contains(&param.lifetime)
+            } else {
+                false
+            }
+        })
+    }
+}
+
 type Supertraits = Punctuated<TypeParamBound, Token![+]>;
 
 pub fn expand(input: &mut Item, is_local: bool) {
@@ -109,72 +127,69 @@
         ReturnType::Type(_, ret) => quote!(#ret),
     };
 
-    let mut elided = CollectLifetimes::new();
+    let mut lifetimes = CollectLifetimes::new();
     for arg in sig.inputs.iter_mut() {
         match arg {
-            FnArg::Receiver(arg) => elided.visit_receiver_mut(arg),
-            FnArg::Typed(arg) => elided.visit_type_mut(&mut arg.ty),
+            FnArg::Receiver(arg) => lifetimes.visit_receiver_mut(arg),
+            FnArg::Typed(arg) => lifetimes.visit_type_mut(&mut arg.ty),
         }
     }
 
-    let lifetime: Lifetime;
-    if !sig.generics.params.is_empty() || !elided.lifetimes.is_empty() || has_self {
-        lifetime = parse_quote!('async_trait);
-        let where_clause = sig
-            .generics
-            .where_clause
-            .get_or_insert_with(|| WhereClause {
-                where_token: Default::default(),
-                predicates: Punctuated::new(),
-            });
-        for param in &sig.generics.params {
-            match param {
-                GenericParam::Type(param) => {
-                    let param = &param.ident;
-                    where_clause
-                        .predicates
-                        .push(parse_quote!(#param: #lifetime));
-                }
-                GenericParam::Lifetime(param) => {
-                    let param = &param.lifetime;
-                    where_clause
-                        .predicates
-                        .push(parse_quote!(#param: #lifetime));
-                }
-                GenericParam::Const(_) => {}
+    let where_clause = sig
+        .generics
+        .where_clause
+        .get_or_insert_with(|| WhereClause {
+            where_token: Default::default(),
+            predicates: Punctuated::new(),
+        });
+    for param in sig
+        .generics
+        .params
+        .iter()
+        .chain(context.lifetimes(&lifetimes.explicit))
+    {
+        match param {
+            GenericParam::Type(param) => {
+                let param = &param.ident;
+                where_clause
+                    .predicates
+                    .push(parse_quote!(#param: 'async_trait));
             }
+            GenericParam::Lifetime(param) => {
+                let param = &param.lifetime;
+                where_clause
+                    .predicates
+                    .push(parse_quote!(#param: 'async_trait));
+            }
+            GenericParam::Const(_) => {}
         }
-        for elided in elided.lifetimes {
-            sig.generics.params.push(parse_quote!(#elided));
-            where_clause
-                .predicates
-                .push(parse_quote!(#elided: #lifetime));
-        }
-        sig.generics.params.push(parse_quote!(#lifetime));
-        if has_self {
-            let bound: Ident = match sig.inputs.iter().next() {
-                Some(FnArg::Receiver(Receiver {
-                    reference: Some(_),
-                    mutability: None,
-                    ..
-                })) => parse_quote!(Sync),
-                _ => parse_quote!(Send),
-            };
-            let assume_bound = match context {
-                Context::Trait { supertraits, .. } => {
-                    !has_default || has_bound(supertraits, &bound)
-                }
-                Context::Impl { .. } => true,
-            };
-            where_clause.predicates.push(if assume_bound || is_local {
-                parse_quote!(Self: #lifetime)
-            } else {
-                parse_quote!(Self: core::marker::#bound + #lifetime)
-            });
-        }
-    } else {
-        lifetime = parse_quote!('static);
-    };
+    }
+    for elided in lifetimes.elided {
+        sig.generics.params.push(parse_quote!(#elided));
+        where_clause
+            .predicates
+            .push(parse_quote!(#elided: 'async_trait));
+    }
+    sig.generics.params.push(parse_quote!('async_trait));
+    if has_self {
+        let bound: Ident = match sig.inputs.iter().next() {
+            Some(FnArg::Receiver(Receiver {
+                reference: Some(_),
+                mutability: None,
+                ..
+            })) => parse_quote!(Sync),
+            _ => parse_quote!(Send),
+        };
+        let assume_bound = match context {
+            Context::Trait { supertraits, .. } => !has_default || has_bound(supertraits, &bound),
+            Context::Impl { .. } => true,
+        };
+        where_clause.predicates.push(if assume_bound || is_local {
+            parse_quote!(Self: 'async_trait)
+        } else {
+            parse_quote!(Self: ::core::marker::#bound + 'async_trait)
+        });
+    }
 
     for (i, arg) in sig.inputs.iter_mut().enumerate() {
         match arg {
@@ -195,14 +210,14 @@
     }
 
     let bounds = if is_local {
-        quote!(#lifetime)
+        quote!('async_trait)
     } else {
-        quote!(core::marker::Send + #lifetime)
+        quote!(::core::marker::Send + 'async_trait)
     };
 
     sig.output = parse_quote! {
-        -> core::pin::Pin<Box<
-            dyn core::future::Future<Output = #ret> + #bounds
+        -> ::core::pin::Pin<Box<
+            dyn ::core::future::Future<Output = #ret> + #bounds
         >>
     };
 }
@@ -216,7 +231,7 @@
 //     async fn f<T, AsyncTrait>(_self: &AsyncTrait, x: &T) -> Ret {
 //         _self + x
 //     }
-//     Pin::from(Box::new(async_trait_method::<T, Self>(self, x)))
+//     Box::pin(async_trait_method::<T, Self>(self, x))
 fn transform_block(
     context: Context,
     sig: &mut Signature,
@@ -227,7 +242,7 @@
     if cfg!(feature = "support_old_nightly") {
         let brace = block.brace_token;
         *block = parse_quote!({
-            core::pin::Pin::from(Box::new(async move #block))
+            Box::pin(async move #block)
         });
         block.brace_token = brace;
         return;
@@ -248,11 +263,30 @@
     let mut standalone = sig.clone();
     standalone.ident = inner.clone();
 
-    let outer_generics = match context {
+    let generics = match context {
         Context::Trait { generics, .. } => generics,
         Context::Impl { impl_generics, .. } => impl_generics,
     };
-    let fn_generics = mem::replace(&mut standalone.generics, outer_generics.clone());
+
+    let mut outer_generics = generics.clone();
+    if !has_self {
+        if let Some(mut where_clause) = outer_generics.where_clause {
+            where_clause.predicates = where_clause
+                .predicates
+                .into_iter()
+                .filter_map(|mut pred| {
+                    if has_self_in_where_predicate(&mut pred) {
+                        None
+                    } else {
+                        Some(pred)
+                    }
+                })
+                .collect();
+            outer_generics.where_clause = Some(where_clause);
+        }
+    }
+
+    let fn_generics = mem::replace(&mut standalone.generics, outer_generics);
     standalone.generics.params.extend(fn_generics.params);
     if let Some(where_clause) = fn_generics.where_clause {
         standalone
@@ -292,8 +326,8 @@
             match context {
                 Context::Trait { .. } => {
                     self_bound = Some(match mutability {
-                        Some(_) => parse_quote!(core::marker::Send),
-                        None => parse_quote!(core::marker::Sync),
+                        Some(_) => parse_quote!(::core::marker::Send),
+                        None => parse_quote!(::core::marker::Sync),
                     });
                     *arg = parse_quote! {
                         #under_self: &#lifetime #mutability AsyncTrait
@@ -318,7 +352,7 @@
             let under_self = Ident::new("_self", self_token.span);
             match context {
                 Context::Trait { .. } => {
-                    self_bound = Some(parse_quote!(core::marker::Send));
+                    self_bound = Some(parse_quote!(::core::marker::Send));
                     *arg = parse_quote! {
                         #mutability #under_self: AsyncTrait
                     };
@@ -371,12 +405,23 @@
     replace.visit_signature_mut(&mut standalone);
     replace.visit_block_mut(block);
 
+    let mut generics = types;
+    let consts = standalone
+        .generics
+        .const_params()
+        .map(|param| param.ident.clone());
+    generics.extend(consts);
+
     let brace = block.brace_token;
-    *block = parse_quote!({
-        #[allow(clippy::used_underscore_binding)]
+    let box_pin = quote_spanned!(brace.span=> {
+        #[allow(
+            clippy::missing_docs_in_private_items,
+            clippy::used_underscore_binding,
+        )]
         #standalone #block
-        core::pin::Pin::from(Box::new(#inner::<#(#types),*>(#(#args),*)))
+        Box::pin(#inner::<#(#generics),*>(#(#args),*))
     });
+    *block = parse_quote!(#box_pin);
     block.brace_token = brace;
 }
 
diff --git a/third_party/rust_crates/vendor/async-trait/src/lib.rs b/third_party/rust_crates/vendor/async-trait/src/lib.rs
index 8ccbea8..20af33e 100644
--- a/third_party/rust_crates/vendor/async-trait/src/lib.rs
+++ b/third_party/rust_crates/vendor/async-trait/src/lib.rs
@@ -1,7 +1,7 @@
 //! <h5>Type erasure for async trait methods</h5>
 //!
 //! The async/await language feature is on track for an initial round of
-//! stabilizations in Rust 1.38 (tracking issue: [rust-lang/rust#62149]), but
+//! stabilizations in Rust 1.39 (tracking issue: [rust-lang/rust#62149]), but
 //! this does not include support for async fn in traits. Trying to include an
 //! async fn in a trait produces the following error:
 //!
@@ -23,6 +23,12 @@
 //!
 //! This crate provides an attribute macro to make async fn in traits work.
 //!
+//! Please refer to [*why async fn in traits are hard*][hard] for a deeper
+//! analysis of how this implementation differs from what the compiler and
+//! language hope to deliver in the future.
+//!
+//! [hard]: https://smallcultfollowing.com/babysteps/blog/2019/10/26/async-fn-in-traits-are-hard/
+//!
 //! <br>
 //!
 //! # Example
@@ -125,7 +131,7 @@
 //!             /* the original method body */
 //!         }
 //!
-//!         Pin::from(Box::new(run(self)))
+//!         Box::pin(run(self))
 //!     }
 //! }
 //! # };
diff --git a/third_party/rust_crates/vendor/async-trait/src/lifetime.rs b/third_party/rust_crates/vendor/async-trait/src/lifetime.rs
index b11cec0..d15a4fc 100644
--- a/third_party/rust_crates/vendor/async-trait/src/lifetime.rs
+++ b/third_party/rust_crates/vendor/async-trait/src/lifetime.rs
@@ -22,13 +22,15 @@
 }
 
 pub struct CollectLifetimes {
-    pub lifetimes: Vec<Lifetime>,
+    pub elided: Vec<Lifetime>,
+    pub explicit: Vec<Lifetime>,
 }
 
 impl CollectLifetimes {
     pub fn new() -> Self {
         CollectLifetimes {
-            lifetimes: Vec::new(),
+            elided: Vec::new(),
+            explicit: Vec::new(),
         }
     }
 
@@ -42,13 +44,15 @@
     fn visit_lifetime(&mut self, lifetime: &mut Lifetime) {
         if lifetime.ident == "_" {
             *lifetime = self.next_lifetime();
+        } else {
+            self.explicit.push(lifetime.clone());
         }
     }
 
     fn next_lifetime(&mut self) -> Lifetime {
-        let name = format!("'life{}", self.lifetimes.len());
+        let name = format!("'life{}", self.elided.len());
         let life = Lifetime::new(&name, Span::call_site());
-        self.lifetimes.push(life.clone());
+        self.elided.push(life.clone());
         life
     }
 }
diff --git a/third_party/rust_crates/vendor/async-trait/src/parse.rs b/third_party/rust_crates/vendor/async-trait/src/parse.rs
index d5f5b80..957e714 100644
--- a/third_party/rust_crates/vendor/async-trait/src/parse.rs
+++ b/third_party/rust_crates/vendor/async-trait/src/parse.rs
@@ -18,7 +18,12 @@
 impl Parse for Item {
     fn parse(input: ParseStream) -> Result<Self> {
         let attrs = input.call(Attribute::parse_outer)?;
-        let lookahead = input.lookahead1();
+        let mut lookahead = input.lookahead1();
+        if lookahead.peek(Token![unsafe]) {
+            let ahead = input.fork();
+            ahead.parse::<Token![unsafe]>()?;
+            lookahead = ahead.lookahead1();
+        }
         if lookahead.peek(Token![pub]) || lookahead.peek(Token![trait]) {
             let mut item: ItemTrait = input.parse()?;
             item.attrs = attrs;
diff --git a/third_party/rust_crates/vendor/async-trait/src/receiver.rs b/third_party/rust_crates/vendor/async-trait/src/receiver.rs
index 29c610a8..a444106 100644
--- a/third_party/rust_crates/vendor/async-trait/src/receiver.rs
+++ b/third_party/rust_crates/vendor/async-trait/src/receiver.rs
@@ -2,7 +2,10 @@
 use std::mem;
 use syn::punctuated::Punctuated;
 use syn::visit_mut::{self, VisitMut};
-use syn::{Block, ExprPath, Ident, Item, Macro, Path, QSelf, Receiver, Signature, Type, TypePath};
+use syn::{
+    parse_quote, Block, Error, ExprPath, ExprStruct, Ident, Item, Macro, Path, PathArguments,
+    QSelf, Receiver, Signature, Type, TypePath, WherePredicate,
+};
 
 pub fn has_self_in_sig(sig: &mut Signature) -> bool {
     let mut visitor = HasSelf(false);
@@ -10,6 +13,12 @@
     visitor.0
 }
 
+pub fn has_self_in_where_predicate(where_predicate: &mut WherePredicate) -> bool {
+    let mut visitor = HasSelf(false);
+    visitor.visit_where_predicate_mut(where_predicate);
+    visitor.0
+}
+
 pub fn has_self_in_block(block: &mut Block) -> bool {
     let mut visitor = HasSelf(false);
     visitor.visit_block_mut(block);
@@ -19,6 +28,11 @@
 struct HasSelf(bool);
 
 impl VisitMut for HasSelf {
+    fn visit_expr_path_mut(&mut self, expr: &mut ExprPath) {
+        self.0 |= expr.path.segments[0].ident == "Self";
+        visit_mut::visit_expr_path_mut(self, expr);
+    }
+
     fn visit_type_path_mut(&mut self, ty: &mut TypePath) {
         self.0 |= ty.path.segments[0].ident == "Self";
         visit_mut::visit_type_path_mut(self, ty);
@@ -54,11 +68,13 @@
     }
 
     fn self_to_qself_type(&self, qself: &mut Option<QSelf>, path: &mut Path) {
-        self.self_to_qself(qself, path, true);
+        let include_as_trait = true;
+        self.self_to_qself(qself, path, include_as_trait);
     }
 
     fn self_to_qself_expr(&self, qself: &mut Option<QSelf>, path: &mut Path) {
-        self.self_to_qself(qself, path, false);
+        let include_as_trait = false;
+        self.self_to_qself(qself, path, include_as_trait);
     }
 
     fn self_to_qself(&self, qself: &mut Option<QSelf>, path: &mut Path, include_as_trait: bool) {
@@ -71,6 +87,11 @@
             return;
         }
 
+        if path.segments.len() == 1 {
+            self.self_to_expr_path(path);
+            return;
+        }
+
         *qself = Some(QSelf {
             lt_token: Default::default(),
             ty: Box::new(self.with.clone()),
@@ -94,6 +115,24 @@
             path.segments = segments.into_pairs().skip(1).collect();
         }
     }
+
+    fn self_to_expr_path(&self, path: &mut Path) {
+        if let Type::Path(with) = &self.with {
+            *path = with.path.clone();
+            for segment in &mut path.segments {
+                if let PathArguments::AngleBracketed(bracketed) = &mut segment.arguments {
+                    if bracketed.colon2_token.is_none() && !bracketed.args.is_empty() {
+                        bracketed.colon2_token = Some(Default::default());
+                    }
+                }
+            }
+        } else {
+            let span = path.segments[0].ident.span();
+            let msg = "Self type of this impl is unsupported in expression position";
+            let error = Error::new(span, msg).to_compile_error();
+            *path = parse_quote!(::core::marker::PhantomData::<#error>);
+        }
+    }
 }
 
 impl VisitMut for ReplaceReceiver {
@@ -127,6 +166,13 @@
         visit_mut::visit_expr_path_mut(self, expr);
     }
 
+    fn visit_expr_struct_mut(&mut self, expr: &mut ExprStruct) {
+        if expr.path.is_ident("Self") {
+            self.self_to_expr_path(&mut expr.path);
+        }
+        visit_mut::visit_expr_struct_mut(self, expr);
+    }
+
     fn visit_item_mut(&mut self, _: &mut Item) {
         // Do not recurse into nested items.
     }
diff --git a/third_party/rust_crates/vendor/async-trait/tests/compiletest.rs b/third_party/rust_crates/vendor/async-trait/tests/compiletest.rs
new file mode 100644
index 0000000..f9aea23
--- /dev/null
+++ b/third_party/rust_crates/vendor/async-trait/tests/compiletest.rs
@@ -0,0 +1,6 @@
+#[rustversion::attr(not(nightly), ignore)]
+#[test]
+fn ui() {
+    let t = trybuild::TestCases::new();
+    t.compile_fail("tests/ui/*.rs");
+}
diff --git a/third_party/rust_crates/vendor/async-trait/tests/executor/mod.rs b/third_party/rust_crates/vendor/async-trait/tests/executor/mod.rs
new file mode 100644
index 0000000..f48b348
--- /dev/null
+++ b/third_party/rust_crates/vendor/async-trait/tests/executor/mod.rs
@@ -0,0 +1,35 @@
+use std::future::Future;
+use std::pin::Pin;
+use std::ptr;
+use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
+
+// Executor for a future that resolves immediately (test only).
+pub fn block_on_simple<F: Future>(mut fut: F) -> F::Output {
+    unsafe fn clone(_null: *const ()) -> RawWaker {
+        unimplemented!()
+    }
+
+    unsafe fn wake(_null: *const ()) {
+        unimplemented!()
+    }
+
+    unsafe fn wake_by_ref(_null: *const ()) {
+        unimplemented!()
+    }
+
+    unsafe fn drop(_null: *const ()) {}
+
+    let data = ptr::null();
+    let vtable = &RawWakerVTable::new(clone, wake, wake_by_ref, drop);
+    let raw_waker = RawWaker::new(data, vtable);
+    let waker = unsafe { Waker::from_raw(raw_waker) };
+    let mut cx = Context::from_waker(&waker);
+
+    // fut does not move until it gets dropped.
+    let fut = unsafe { Pin::new_unchecked(&mut fut) };
+
+    match fut.poll(&mut cx) {
+        Poll::Ready(output) => output,
+        Poll::Pending => panic!("future did not resolve immediately"),
+    }
+}
diff --git a/third_party/rust_crates/vendor/async-trait/tests/test.rs b/third_party/rust_crates/vendor/async-trait/tests/test.rs
index 6b5cd63d..db065a9c 100644
--- a/third_party/rust_crates/vendor/async-trait/tests/test.rs
+++ b/third_party/rust_crates/vendor/async-trait/tests/test.rs
@@ -1,5 +1,12 @@
+#![cfg_attr(async_trait_nightly_testing, feature(specialization, const_generics))]
+
 use async_trait::async_trait;
 
+pub mod executor;
+
+// Dummy module to check that the expansion refer to rust's core crate
+mod core {}
+
 #[async_trait]
 trait Trait {
     type Assoc;
@@ -129,8 +136,20 @@
     object.f().await;
 }
 
+#[async_trait]
+pub unsafe trait UnsafeTrait {}
+
+#[async_trait]
+unsafe impl UnsafeTrait for () {}
+
+#[async_trait]
+pub(crate) unsafe trait UnsafeTraitPubCrate {}
+
+#[async_trait]
+unsafe trait UnsafeTraitPrivate {}
+
 // https://github.com/dtolnay/async-trait/issues/1
-mod issue1 {
+pub mod issue1 {
     use async_trait::async_trait;
 
     #[async_trait]
@@ -145,7 +164,7 @@
 }
 
 // https://github.com/dtolnay/async-trait/issues/2
-mod issue2 {
+pub mod issue2 {
     use async_trait::async_trait;
     use std::future::Future;
 
@@ -163,7 +182,7 @@
 }
 
 // https://github.com/dtolnay/async-trait/issues/9
-mod issue9 {
+pub mod issue9 {
     use async_trait::async_trait;
 
     #[async_trait]
@@ -173,7 +192,7 @@
 }
 
 // https://github.com/dtolnay/async-trait/issues/11
-mod issue11 {
+pub mod issue11 {
     use async_trait::async_trait;
     use std::sync::Arc;
 
@@ -191,7 +210,7 @@
 }
 
 // https://github.com/dtolnay/async-trait/issues/15
-mod issue15 {
+pub mod issue15 {
     use async_trait::async_trait;
     use std::marker::PhantomData;
 
@@ -204,7 +223,7 @@
 }
 
 // https://github.com/dtolnay/async-trait/issues/17
-mod issue17 {
+pub mod issue17 {
     use async_trait::async_trait;
 
     #[async_trait]
@@ -225,7 +244,7 @@
 }
 
 // https://github.com/dtolnay/async-trait/issues/23
-mod issue23 {
+pub mod issue23 {
     use async_trait::async_trait;
 
     #[async_trait]
@@ -251,3 +270,235 @@
 
     fn do_something<T>(_: &mut T) {}
 }
+
+// https://github.com/dtolnay/async-trait/issues/25
+#[cfg(async_trait_nightly_testing)]
+pub mod issue25 {
+    use crate::executor;
+    use async_trait::async_trait;
+    use std::fmt::{Display, Write};
+
+    #[async_trait]
+    trait AsyncToString {
+        async fn async_to_string(&self) -> String;
+    }
+
+    #[async_trait]
+    impl AsyncToString for String {
+        async fn async_to_string(&self) -> String {
+            "special".to_owned()
+        }
+    }
+
+    macro_rules! hide_from_stable_parser {
+        ($($tt:tt)*) => {
+            $($tt)*
+        };
+    }
+
+    hide_from_stable_parser! {
+        #[async_trait]
+        impl<T: ?Sized + Display + Sync> AsyncToString for T {
+            default async fn async_to_string(&self) -> String {
+                let mut buf = String::new();
+                buf.write_fmt(format_args!("{}", self)).unwrap();
+                buf
+            }
+        }
+    }
+
+    #[test]
+    fn test() {
+        let fut = true.async_to_string();
+        assert_eq!(executor::block_on_simple(fut), "true");
+
+        let string = String::new();
+        let fut = string.async_to_string();
+        assert_eq!(executor::block_on_simple(fut), "special");
+    }
+}
+
+// https://github.com/dtolnay/async-trait/issues/28
+pub mod issue28 {
+    use async_trait::async_trait;
+
+    struct Str<'a>(&'a str);
+
+    #[async_trait]
+    trait Trait1<'a> {
+        async fn f(x: Str<'a>) -> &'a str;
+        async fn g(x: Str<'a>) -> &'a str {
+            x.0
+        }
+    }
+
+    #[async_trait]
+    impl<'a> Trait1<'a> for str {
+        async fn f(x: Str<'a>) -> &'a str {
+            x.0
+        }
+    }
+
+    #[async_trait]
+    trait Trait2 {
+        async fn f();
+    }
+
+    #[async_trait]
+    impl<'a> Trait2 for &'a () {
+        async fn f() {}
+    }
+
+    #[async_trait]
+    trait Trait3<'a, 'b> {
+        async fn f(_: &'a &'b ()); // chain 'a and 'b
+        async fn g(_: &'b ()); // chain 'b only
+        async fn h(); // do not chain
+    }
+}
+
+// https://github.com/dtolnay/async-trait/issues/31
+pub mod issue31 {
+    use async_trait::async_trait;
+
+    pub struct Struct<'a> {
+        pub name: &'a str,
+    }
+
+    #[async_trait]
+    pub trait Trait<'a> {
+        async fn hello(thing: Struct<'a>) -> String;
+        async fn hello_twice(one: Struct<'a>, two: Struct<'a>) -> String {
+            let str1 = Self::hello(one).await;
+            let str2 = Self::hello(two).await;
+            str1 + &str2
+        }
+    }
+}
+
+// https://github.com/dtolnay/async-trait/issues/42
+pub mod issue42 {
+    use async_trait::async_trait;
+
+    #[async_trait]
+    pub trait Context: Sized {
+        async fn from_parts() -> Self;
+    }
+
+    pub struct TokenContext;
+
+    #[async_trait]
+    impl Context for TokenContext {
+        async fn from_parts() -> TokenContext {
+            TokenContext
+        }
+    }
+}
+
+// https://github.com/dtolnay/async-trait/issues/44
+pub mod issue44 {
+    use async_trait::async_trait;
+
+    #[async_trait]
+    pub trait StaticWithWhereSelf
+    where
+        Box<Self>: Sized,
+        Self: Sized + Send,
+    {
+        async fn get_one() -> u8 {
+            1
+        }
+    }
+
+    pub struct Struct;
+
+    #[async_trait]
+    impl StaticWithWhereSelf for Struct {}
+}
+
+// https://github.com/dtolnay/async-trait/issues/46
+pub mod issue46 {
+    use async_trait::async_trait;
+
+    macro_rules! implement_commands {
+        ($tyargs:tt : $ty:tt) => {
+            #[async_trait]
+            pub trait AsyncCommands: Sized {
+                async fn f<$tyargs: $ty>(&mut self, x: $tyargs) {
+                    self.f(x).await
+                }
+            }
+        };
+    }
+
+    implement_commands!(K: Send);
+}
+
+// https://github.com/dtolnay/async-trait/issues/53
+pub mod issue53 {
+    use async_trait::async_trait;
+
+    pub struct Unit;
+    pub struct Tuple(u8);
+    pub struct Struct {
+        pub x: u8,
+    }
+
+    #[async_trait]
+    pub trait Trait {
+        async fn method();
+    }
+
+    #[async_trait]
+    impl Trait for Unit {
+        async fn method() {
+            let _ = Self;
+        }
+    }
+
+    #[async_trait]
+    impl Trait for Tuple {
+        async fn method() {
+            let _ = Self(0);
+        }
+    }
+
+    #[async_trait]
+    impl Trait for Struct {
+        async fn method() {
+            let _ = Self { x: 0 };
+        }
+    }
+
+    #[async_trait]
+    impl Trait for std::marker::PhantomData<Struct> {
+        async fn method() {
+            let _ = Self;
+        }
+    }
+}
+
+// https://github.com/dtolnay/async-trait/issues/57
+#[cfg(async_trait_nightly_testing)]
+pub mod issue57 {
+    use crate::executor;
+    use async_trait::async_trait;
+
+    #[async_trait]
+    trait Trait {
+        async fn const_generic<T: Send, const C: usize>(_: [T; C]) {}
+    }
+
+    struct Struct;
+
+    #[async_trait]
+    impl Trait for Struct {
+        async fn const_generic<T: Send, const C: usize>(_: [T; C]) {}
+    }
+
+    #[test]
+    fn test() {
+        let fut = Struct::const_generic([0; 10]);
+        executor::block_on_simple(fut);
+    }
+}
diff --git a/third_party/rust_crates/vendor/async-trait/tests/ui/send-not-implemented.rs b/third_party/rust_crates/vendor/async-trait/tests/ui/send-not-implemented.rs
new file mode 100644
index 0000000..a3e3856
--- /dev/null
+++ b/third_party/rust_crates/vendor/async-trait/tests/ui/send-not-implemented.rs
@@ -0,0 +1,15 @@
+use async_trait::async_trait;
+use std::sync::Mutex;
+
+async fn f() {}
+
+#[async_trait]
+trait Test {
+    async fn test(&self) {
+        let mutex = Mutex::new(());
+        let _guard = mutex.lock().unwrap();
+        f().await;
+    }
+}
+
+fn main() {}
diff --git a/third_party/rust_crates/vendor/async-trait/tests/ui/send-not-implemented.stderr b/third_party/rust_crates/vendor/async-trait/tests/ui/send-not-implemented.stderr
new file mode 100644
index 0000000..4fad3a95
--- /dev/null
+++ b/third_party/rust_crates/vendor/async-trait/tests/ui/send-not-implemented.stderr
@@ -0,0 +1,22 @@
+error: future cannot be sent between threads safely
+  --> $DIR/send-not-implemented.rs:8:26
+   |
+8  |       async fn test(&self) {
+   |  __________________________^
+9  | |         let mutex = Mutex::new(());
+10 | |         let _guard = mutex.lock().unwrap();
+11 | |         f().await;
+12 | |     }
+   | |_____^ future returned by `__test` is not `Send`
+   |
+   = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::sync::MutexGuard<'_, ()>`
+note: future is not `Send` as this value is used across an await
+  --> $DIR/send-not-implemented.rs:11:9
+   |
+10 |         let _guard = mutex.lock().unwrap();
+   |             ------ has type `std::sync::MutexGuard<'_, ()>`
+11 |         f().await;
+   |         ^^^^^^^^^ await occurs here, with `_guard` maybe used later
+12 |     }
+   |     - `_guard` is later dropped here
+   = note: required for the cast to the object type `dyn std::future::Future<Output = ()> + std::marker::Send`
diff --git a/third_party/rust_crates/vendor/async-trait/tests/ui/unsupported-self.rs b/third_party/rust_crates/vendor/async-trait/tests/ui/unsupported-self.rs
new file mode 100644
index 0000000..5868c61
--- /dev/null
+++ b/third_party/rust_crates/vendor/async-trait/tests/ui/unsupported-self.rs
@@ -0,0 +1,15 @@
+use async_trait::async_trait;
+
+#[async_trait]
+pub trait Trait {
+    async fn method();
+}
+
+#[async_trait]
+impl Trait for &'static str {
+    async fn method() {
+        let _ = Self;
+    }
+}
+
+fn main() {}
diff --git a/third_party/rust_crates/vendor/async-trait/tests/ui/unsupported-self.stderr b/third_party/rust_crates/vendor/async-trait/tests/ui/unsupported-self.stderr
new file mode 100644
index 0000000..c1ea955
--- /dev/null
+++ b/third_party/rust_crates/vendor/async-trait/tests/ui/unsupported-self.stderr
@@ -0,0 +1,5 @@
+error: Self type of this impl is unsupported in expression position
+  --> $DIR/unsupported-self.rs:11:17
+   |
+11 |         let _ = Self;
+   |                 ^^^^
diff --git a/third_party/rust_crates/vendor/backtrace-sys/.cargo-checksum.json b/third_party/rust_crates/vendor/backtrace-sys/.cargo-checksum.json
new file mode 100644
index 0000000..0402f21
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"df39822caf0fd2b9b001e5834db300fa9dc731060649195f10f34b0ffe912542","build.rs":"d0803fc2f1fa92b567df1188efceb7f9158b1422fc2227e7d0c779821a509e2e","src/android-api.c":"b75f16de578451464f49b83dc817b76aa9a0be0d86ea71d1659cc78f99e94fbd","src/lib.rs":"ccd15703f469cb10d620a30a1accd8834e8012abab5b626f925777275d6d2b02","src/libbacktrace/LICENSE":"ef8a9b3247488f8901ca60de9b17b745d7bd67e5ec1e622f80d62364572200d8","src/libbacktrace/Makefile.am":"5353e0ce3a4732b42ccf031c474f7234336992cb23ba76cbfda3aa5262e69988","src/libbacktrace/Makefile.in":"1802d55fa8ef616a407c69311b3fa4e579093d124a215c834149ab1c50b4f3ad","src/libbacktrace/Mark.Twain-Tom.Sawyer.txt":"461eb7cb2d57d293fc680c836464c9125e4382be3596f7d415093ae9db8fcb0e","src/libbacktrace/README.md":"3b27ca2f7ddaf464ad81366a278ed4d34ad513de3766b330a51464828fa3131f","src/libbacktrace/acinclude.m4":"7f1d64805039b0e41d4c4106265618a6f8921d3cf091d64ab31fa7b900dc892f","src/libbacktrace/aclocal.m4":"4899cfe70722ba1de2b42b4e9965c1db1b173b5d6d4522cdc785becd5a5c212c","src/libbacktrace/alloc.c":"33891bbaf755c050058f8fd7dd3708e6062ef65245a0717216af45b78bab0fd0","src/libbacktrace/atomic.c":"82fd23c7ee7154d1ce4fc823637ede9cfa0e469f4073f38fff4dd9081070f1aa","src/libbacktrace/backtrace-supported.h.in":"42277f3c383386b6cfa3d3d889336e92303fac0ae1a9fb8a6a56737245dfb8f3","src/libbacktrace/backtrace.c":"837ea7b781a737d1ed37e4d03c463bcbe1432b2dc3b79b37344b21013cdfcca4","src/libbacktrace/backtrace.h":"9f035b3830c1c6000259c8ecf0bf53144f7c2e6064dfc95975b89f7f612ebf0e","src/libbacktrace/btest.c":"41c774496d58177e408b1dc33d6a792d0940634885978eed73fb192f732cafc5","src/libbacktrace/config.guess":"9be3de218833c076786b919dc34aab691611f4cd73316e7705f2673e2c41921b","src/libbacktrace/config.h.in":"b5002d9f96f6a26f54317f9d23a5ffff71fa3ee520fd8993810891d43b9a9bf7","src/libbacktrace/config.sub":"c8e70ab53f04d2f2b0280aa0e8a5432e90a902bfa2af7b0854168eb1fb3a84c0","src/libbacktrace/config/libtool.m4":"644ce34d5e9fcc544f3ef5c707f4cb29add798bbfc24e29932b55fb251e50353","src/libbacktrace/config/ltoptions.m4":"9d294950c4d97e2c891d472933113f397d410ef2a8ed875d714f81761626bbd8","src/libbacktrace/config/ltsugar.m4":"2c6618a04aa6389a2a528cde2e69ed5de55acc6c50892b486ea3e56e4e5b2c3b","src/libbacktrace/config/ltversion.m4":"8d129a46367fadad9f202dac50e708696d4d628313d01745127388e9c736e996","src/libbacktrace/config/lt~obsolete.m4":"c6c668594337aafef7d59f585bce7010436153815fe341461d81301a2235b959","src/libbacktrace/configure":"59763fc255248b54fba5d0761d61093a73d51fa4cb400b0df1b5f339b9c2f48a","src/libbacktrace/configure.ac":"b9292548330eb4d2cb014e9d9e6cd4df656aed982917365896a8f2534e9732e5","src/libbacktrace/dwarf.c":"c2103af5f94dd135e5df2a98dfc28ef2cbe0f3d56783d21e1487b9f314bfcbbc","src/libbacktrace/edtest.c":"947b9878ae45f6ba95d3b949bb080e9feed4ffdb27536cf5602b81ce79556ccf","src/libbacktrace/edtest2.c":"964bb0bb510a19013fb1cb56552929ed15cf55787eba4369d5820b74be07d249","src/libbacktrace/elf.c":"fe3e10d33c0c0965f016381302128ce82d664071095ad5077932377e3a789679","src/libbacktrace/fileline.c":"7b3b92044648f45becc498d4ed41ddc8ec08f0d11f6491cc05cfccd8a4d7627a","src/libbacktrace/filenames.h":"2c23cde7dd12dd9e0343cb37b5066036112deca703b61178f07c01f3e01398c9","src/libbacktrace/filetype.awk":"aa38776487a77dc13c93efa2a861204b384c3c4333501ed9bdb4ccbde2a784c0","src/libbacktrace/install-sh":"e7064b5e01a8d173409749c337966698fa04661cde1e3ef1a93be250eec0d2c3","src/libbacktrace/internal.h":"88c63ad6acc7e68330df3028675be4d4e3374bd787255fe22dd3febbbbc438b6","src/libbacktrace/ltmain.sh":"873bdcbc8690bd90c0f3632aac40027e880fd95ea45fb5a02ed901fea4afa4fe","src/libbacktrace/macho.c":"9a8864901eede4c34305b05bb6e815b25b76f04b59caf74381ca9dfbe8f1a8c4","src/libbacktrace/missing":"300bea3fb273b763eca2e4bb1576c663605d9b49de385fd375f82be8d912f506","src/libbacktrace/mmap.c":"5be917f3e9eba1fe49eb1bb391e28609e8377b4ce4593cace6012bf17434a33c","src/libbacktrace/mmapio.c":"be5719c4f92e70045fe6014a0493a5b4adc165ecde42c20130ea6e9da1ce978f","src/libbacktrace/move-if-change":"689762b92d23003926ba729acf98b9a109abf46de0698c09ddfa0d20490d8af5","src/libbacktrace/nounwind.c":"5eee9cc7298b7d0d2aea68eef62175541f34f88acf17736e0612056c5bb7318d","src/libbacktrace/pecoff.c":"bb536ae71a1a1c4dad5508d26032e7e81860df6d8ddfc8d696378ebefbc513b1","src/libbacktrace/posix.c":"f5e0ff701a1a1e29a25462ea49f174b049dafc6c25e040ee0eb77dd189353277","src/libbacktrace/print.c":"2d446406c8e2d9a1258d46d119be1c563bd86b6a4039cbf773b6de09c541390d","src/libbacktrace/read.c":"d0d4007f681f265a6c31e27ded45f4007502c90464eefdb4e80b69e4ae2ede28","src/libbacktrace/simple.c":"b0f767d3740195015aeadaa67e84bf6eb255a730f258485ca86bdbe02b066eca","src/libbacktrace/sort.c":"a82f911fc826a353ea5616379748dfa318ad4e57e20791af7ead853f7e73583d","src/libbacktrace/state.c":"a45abbe4077a47d17fb9687057c40828e633df12d21b8ed40b71a78d86918100","src/libbacktrace/stest.c":"7443fe435f1ee5ce49a3e634faf81a4137d66a057577fe88a211cfa819ddb2e2","src/libbacktrace/testlib.c":"a7e096e895b36db7f997a6673ce48f92a032046876511e813a8a52de6079b29a","src/libbacktrace/testlib.h":"02e02404dc89dd4f3dd82635f794a927541dd78d490d777bedf8a5424e5033fc","src/libbacktrace/ttest.c":"380f3b2be164bd6770768181fa05f1778cee8f0322434896d19724ae7cd105df","src/libbacktrace/unknown.c":"d2d148ea045dcad96ba1c5528b7036b000eeb8439ae397bca01deb0d8b287972","src/libbacktrace/xcoff.c":"e70ed97743306f71ea6132a058d68f1bb7be1380a2d38725b5dc877f5e07905d","src/libbacktrace/ztest.c":"7ad8277664e596aecb6af25818b7671e199ef6002ec2c38d9288179c5cad2082"},"package":"5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491"}
\ No newline at end of file
diff --git a/third_party/rust_crates/vendor/backtrace-sys/Cargo.toml b/third_party/rust_crates/vendor/backtrace-sys/Cargo.toml
new file mode 100644
index 0000000..4e724a7
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/Cargo.toml
@@ -0,0 +1,39 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "backtrace-sys"
+version = "0.1.32"
+authors = ["Alex Crichton <alex@alexcrichton.com>"]
+build = "build.rs"
+description = "Bindings to the libbacktrace gcc library\n"
+homepage = "https://github.com/alexcrichton/backtrace-rs"
+documentation = "http://alexcrichton.com/backtrace-rs"
+license = "MIT/Apache-2.0"
+repository = "https://github.com/alexcrichton/backtrace-rs"
+[dependencies.compiler_builtins]
+version = "0.1.2"
+optional = true
+
+[dependencies.core]
+version = "1.0.0"
+optional = true
+package = "rustc-std-workspace-core"
+
+[dependencies.libc]
+version = "0.2"
+default-features = false
+[build-dependencies.cc]
+version = "1.0.37"
+
+[features]
+rustc-dep-of-std = ["core", "compiler_builtins"]
diff --git a/third_party/rust_crates/vendor/backtrace-sys/LICENSE b/third_party/rust_crates/vendor/backtrace-sys/LICENSE
new file mode 100644
index 0000000..ddde1bd
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/LICENSE
@@ -0,0 +1,231 @@
+https://raw.githubusercontent.com/alexcrichton/backtrace-rs/master/LICENSE-APACHE:
+
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+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.
+========================================
+https://raw.githubusercontent.com/alexcrichton/backtrace-rs/master/LICENSE-MIT:
+
+Copyright (c) 2014 Alex Crichton
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/third_party/rust_crates/vendor/backtrace-sys/build.rs b/third_party/rust_crates/vendor/backtrace-sys/build.rs
new file mode 100644
index 0000000..9e4dff5
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/build.rs
@@ -0,0 +1,155 @@
+extern crate cc;
+
+use std::env;
+use std::fs::File;
+use std::path::PathBuf;
+
+fn main() {
+    let target = env::var("TARGET").unwrap();
+
+    if target.contains("msvc") || // libbacktrace isn't used on MSVC windows
+        target.contains("emscripten") || // no way this will ever compile for emscripten
+        target.contains("cloudabi") ||
+        target.contains("wasm32") ||
+        target.contains("fuchsia")
+    // fuchsia uses external out-of-process symbolization
+    {
+        println!("cargo:rustc-cfg=empty");
+        return;
+    }
+
+    let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
+
+    let mut build = cc::Build::new();
+    build
+        .include("src/libbacktrace")
+        .include(&out_dir)
+        .warnings(false)
+        .file("src/libbacktrace/alloc.c")
+        .file("src/libbacktrace/dwarf.c")
+        .file("src/libbacktrace/fileline.c")
+        .file("src/libbacktrace/posix.c")
+        .file("src/libbacktrace/read.c")
+        .file("src/libbacktrace/sort.c")
+        .file("src/libbacktrace/state.c");
+
+    // No need to have any symbols reexported form shared objects
+    build.flag("-fvisibility=hidden");
+
+    if target.contains("darwin") {
+        build.file("src/libbacktrace/macho.c");
+    } else if target.contains("windows") {
+        build.file("src/libbacktrace/pecoff.c");
+    } else {
+        build.file("src/libbacktrace/elf.c");
+
+        let pointer_width = env::var("CARGO_CFG_TARGET_POINTER_WIDTH").unwrap();
+        if pointer_width == "64" {
+            build.define("BACKTRACE_ELF_SIZE", "64");
+        } else {
+            build.define("BACKTRACE_ELF_SIZE", "32");
+        }
+    }
+
+    File::create(out_dir.join("backtrace-supported.h")).unwrap();
+    build.define("BACKTRACE_SUPPORTED", "1");
+    build.define("BACKTRACE_USES_MALLOC", "1");
+    build.define("BACKTRACE_SUPPORTS_THREADS", "0");
+    build.define("BACKTRACE_SUPPORTS_DATA", "0");
+
+    File::create(out_dir.join("config.h")).unwrap();
+    if target.contains("android") {
+        maybe_enable_dl_iterate_phdr_android(&mut build);
+    } else if !target.contains("apple-ios")
+        && !target.contains("solaris")
+        && !target.contains("redox")
+        && !target.contains("haiku")
+        && !target.contains("vxworks")
+    {
+        build.define("HAVE_DL_ITERATE_PHDR", "1");
+    }
+    build.define("_GNU_SOURCE", "1");
+    build.define("_LARGE_FILES", "1");
+
+    // When we're built as part of the Rust compiler, this is used to enable
+    // debug information in libbacktrace itself.
+    let any_debug = env::var("RUSTC_DEBUGINFO").unwrap_or_default() == "true"
+        || env::var("RUSTC_DEBUGINFO_LINES").unwrap_or_default() == "true";
+    build.debug(any_debug);
+
+    let syms = [
+        "backtrace_full",
+        "backtrace_dwarf_add",
+        "backtrace_initialize",
+        "backtrace_pcinfo",
+        "backtrace_syminfo",
+        "backtrace_get_view",
+        "backtrace_release_view",
+        "backtrace_alloc",
+        "backtrace_free",
+        "backtrace_vector_finish",
+        "backtrace_vector_grow",
+        "backtrace_vector_release",
+        "backtrace_close",
+        "backtrace_open",
+        "backtrace_print",
+        "backtrace_simple",
+        "backtrace_qsort",
+        "backtrace_create_state",
+        "backtrace_uncompress_zdebug",
+        // These should be `static` in C, but they aren't...
+        "macho_get_view",
+        "macho_symbol_type_relevant",
+        "macho_get_commands",
+        "macho_try_dsym",
+        "macho_try_dwarf",
+        "macho_get_addr_range",
+        "macho_get_uuid",
+        "macho_add",
+        "macho_add_symtab",
+        "macho_file_to_host_u64",
+        "macho_file_to_host_u32",
+        "macho_file_to_host_u16",
+    ];
+    let prefix = if cfg!(feature = "rustc-dep-of-std") {
+        println!("cargo:rustc-cfg=rdos");
+        "__rdos_"
+    } else {
+        println!("cargo:rustc-cfg=rbt");
+        "__rbt_"
+    };
+    for sym in syms.iter() {
+        build.define(sym, &format!("{}{}", prefix, sym)[..]);
+    }
+
+    build.compile("backtrace");
+}
+
+// The `dl_iterate_phdr` API was added in Android API 21+ (according to #227),
+// so if we can dynamically detect an appropriately configured C compiler for
+// that then let's enable the `dl_iterate_phdr` API, otherwise Android just
+// won't have any information.
+fn maybe_enable_dl_iterate_phdr_android(build: &mut cc::Build) {
+    let expansion = cc::Build::new().file("src/android-api.c").expand();
+    let expansion = match std::str::from_utf8(&expansion) {
+        Ok(s) => s,
+        Err(_) => return,
+    };
+    println!("expanded android version detection:\n{}", expansion);
+    let marker = "APIVERSION";
+    let i = match expansion.find(marker) {
+        Some(i) => i,
+        None => return,
+    };
+    let version = match expansion[i + marker.len() + 1..].split_whitespace().next() {
+        Some(s) => s,
+        None => return,
+    };
+    let version = match version.parse::<u32>() {
+        Ok(n) => n,
+        Err(_) => return,
+    };
+    if version >= 21 {
+        build.define("HAVE_DL_ITERATE_PHDR", "1");
+    }
+}
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/android-api.c b/third_party/rust_crates/vendor/backtrace-sys/src/android-api.c
new file mode 100644
index 0000000..1bfeadf
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/android-api.c
@@ -0,0 +1,4 @@
+// Used from the build script to detect the value of the `__ANDROID_API__`
+// builtin #define
+
+APIVERSION __ANDROID_API__
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/lib.rs b/third_party/rust_crates/vendor/backtrace-sys/src/lib.rs
new file mode 100644
index 0000000..98a54c3
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/lib.rs
@@ -0,0 +1,58 @@
+#![allow(bad_style)]
+#![no_std]
+
+extern crate libc;
+
+#[cfg(not(empty))]
+pub use self::bindings::*;
+#[cfg(not(empty))]
+mod bindings {
+    use libc::{c_char, c_int, c_void, uintptr_t};
+
+    pub type backtrace_syminfo_callback = extern "C" fn(
+        data: *mut c_void,
+        pc: uintptr_t,
+        symname: *const c_char,
+        symval: uintptr_t,
+        symsize: uintptr_t,
+    );
+    pub type backtrace_full_callback = extern "C" fn(
+        data: *mut c_void,
+        pc: uintptr_t,
+        filename: *const c_char,
+        lineno: c_int,
+        function: *const c_char,
+    ) -> c_int;
+    pub type backtrace_error_callback =
+        extern "C" fn(data: *mut c_void, msg: *const c_char, errnum: c_int);
+    pub enum backtrace_state {}
+
+    extern "C" {
+        #[cfg_attr(rdos, link_name = "__rdos_backtrace_create_state")]
+        #[cfg_attr(rbt, link_name = "__rbt_backtrace_create_state")]
+        pub fn backtrace_create_state(
+            filename: *const c_char,
+            threaded: c_int,
+            error: backtrace_error_callback,
+            data: *mut c_void,
+        ) -> *mut backtrace_state;
+        #[cfg_attr(rdos, link_name = "__rdos_backtrace_syminfo")]
+        #[cfg_attr(rbt, link_name = "__rbt_backtrace_syminfo")]
+        pub fn backtrace_syminfo(
+            state: *mut backtrace_state,
+            addr: uintptr_t,
+            cb: backtrace_syminfo_callback,
+            error: backtrace_error_callback,
+            data: *mut c_void,
+        ) -> c_int;
+        #[cfg_attr(rdos, link_name = "__rdos_backtrace_pcinfo")]
+        #[cfg_attr(rbt, link_name = "__rbt_backtrace_pcinfo")]
+        pub fn backtrace_pcinfo(
+            state: *mut backtrace_state,
+            addr: uintptr_t,
+            cb: backtrace_full_callback,
+            error: backtrace_error_callback,
+            data: *mut c_void,
+        ) -> c_int;
+    }
+}
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/LICENSE b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/LICENSE
new file mode 100644
index 0000000..097d277
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/LICENSE
@@ -0,0 +1,29 @@
+# Copyright (C) 2012-2016 Free Software Foundation, Inc.
+
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+
+#     (1) Redistributions of source code must retain the above copyright
+#     notice, this list of conditions and the following disclaimer. 
+
+#     (2) Redistributions in binary form must reproduce the above copyright
+#     notice, this list of conditions and the following disclaimer in
+#     the documentation and/or other materials provided with the
+#     distribution.  
+    
+#     (3) The name of the author may not be used to
+#     endorse or promote products derived from this software without
+#     specific prior written permission.
+
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/Makefile.am b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/Makefile.am
new file mode 100644
index 0000000..56a3d1b
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/Makefile.am
@@ -0,0 +1,206 @@
+# Makefile.am -- Backtrace Makefile.
+# Copyright (C) 2012-2018 Free Software Foundation, Inc.
+
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+
+#     (1) Redistributions of source code must retain the above copyright
+#     notice, this list of conditions and the following disclaimer.
+
+#     (2) Redistributions in binary form must reproduce the above copyright
+#     notice, this list of conditions and the following disclaimer in
+#     the documentation and/or other materials provided with the
+#     distribution.
+
+#     (3) The name of the author may not be used to
+#     endorse or promote products derived from this software without
+#     specific prior written permission.
+
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+ACLOCAL_AMFLAGS = -I config
+
+AM_CFLAGS = $(EXTRA_FLAGS) $(WARN_FLAGS) $(PIC_FLAG)
+
+include_HEADERS = backtrace.h backtrace-supported.h
+
+lib_LTLIBRARIES = libbacktrace.la
+
+libbacktrace_la_SOURCES = \
+	backtrace.h \
+	atomic.c \
+	dwarf.c \
+	fileline.c \
+	internal.h \
+	posix.c \
+	print.c \
+	sort.c \
+	state.c
+
+BACKTRACE_FILES = \
+	backtrace.c \
+	simple.c \
+	nounwind.c
+
+FORMAT_FILES = \
+	elf.c \
+	pecoff.c \
+	unknown.c \
+	xcoff.c
+
+VIEW_FILES = \
+	read.c \
+	mmapio.c
+
+ALLOC_FILES = \
+	alloc.c \
+	mmap.c
+
+EXTRA_libbacktrace_la_SOURCES = \
+	$(BACKTRACE_FILES) \
+	$(FORMAT_FILES) \
+	$(VIEW_FILES) \
+	$(ALLOC_FILES)
+
+libbacktrace_la_LIBADD = \
+	$(BACKTRACE_FILE) \
+	$(FORMAT_FILE) \
+	$(VIEW_FILE) \
+	$(ALLOC_FILE)
+
+libbacktrace_la_DEPENDENCIES = $(libbacktrace_la_LIBADD)
+
+# Testsuite.
+
+check_PROGRAMS =
+CLEANFILES =
+
+TESTS = $(check_PROGRAMS)
+
+if NATIVE
+
+btest_SOURCES = btest.c testlib.c
+btest_CFLAGS = $(AM_CFLAGS) -g -O
+btest_LDADD = libbacktrace.la
+
+check_PROGRAMS += btest
+
+btest_static_SOURCES = btest.c testlib.c
+btest_static_CFLAGS = $(AM_CFLAGS) -g -O
+btest_static_LDADD = libbacktrace.la
+btest_static_LDFLAGS = -static-libtool-libs
+
+check_PROGRAMS += btest_static
+
+stest_SOURCES = stest.c
+stest_LDADD = libbacktrace.la
+
+check_PROGRAMS += stest
+
+ztest_SOURCES = ztest.c testlib.c
+ztest_CFLAGS = -DSRCDIR=\"$(srcdir)\"
+ztest_LDADD = libbacktrace.la
+
+if HAVE_ZLIB
+ztest_LDADD += -lz
+endif
+ztest_LDADD += $(CLOCK_GETTIME_LINK)
+
+check_PROGRAMS += ztest
+
+edtest_SOURCES = edtest.c edtest2_build.c testlib.c
+edtest_LDADD = libbacktrace.la
+
+check_PROGRAMS += edtest
+
+edtest2_build.c: gen_edtest2_build; @true
+gen_edtest2_build: $(srcdir)/edtest2.c
+	cat $(srcdir)/edtest2.c > tmp-edtest2_build.c
+	$(SHELL) $(srcdir)/move-if-change tmp-edtest2_build.c edtest2_build.c
+	echo timestamp > $@
+
+CLEANFILES += edtest2_build.c gen_edtest2_build
+
+if HAVE_PTHREAD
+
+check_PROGRAMS += ttest
+
+ttest_SOURCES = ttest.c testlib.c
+ttest_CFLAGS = $(AM_CFLAGS) -pthread
+ttest_LDADD = libbacktrace.la
+
+endif HAVE_PTHREAD
+
+if HAVE_OBJCOPY_DEBUGLINK
+
+TESTS += dtest
+
+dtest: btest_static
+	$(OBJCOPY) --only-keep-debug btest_static btest.debug
+	$(OBJCOPY) --strip-debug --add-gnu-debuglink=btest.debug btest_static dtest
+
+CLEANFILES += dtest btest.debug
+
+endif HAVE_OBJCOPY_DEBUGLINK
+
+if HAVE_COMPRESSED_DEBUG
+
+ctestg_SOURCES = btest.c testlib.c
+ctestg_CFLAGS = $(AM_CFLAGS) -g
+ctestg_LDFLAGS = -Wl,--compress-debug-sections=zlib-gnu
+ctestg_LDADD = libbacktrace.la
+
+ctesta_SOURCES = btest.c testlib.c
+ctesta_CFLAGS = $(AM_CFLAGS) -g
+ctesta_LDFLAGS = -Wl,--compress-debug-sections=zlib-gabi
+ctesta_LDADD = libbacktrace.la
+
+check_PROGRAMS += ctestg ctesta
+
+endif
+
+endif NATIVE
+
+# We can't use automake's automatic dependency tracking, because it
+# breaks when using bootstrap-lean.  Automatic dependency tracking
+# with GCC bootstrap will cause some of the objects to depend on
+# header files in prev-gcc/include, e.g., stddef.h and stdarg.h.  When
+# using bootstrap-lean, prev-gcc is removed after each stage.  When
+# running "make install", those header files will be gone, causing the
+# library to be rebuilt at install time.  That may not succeed.
+
+# These manual dependencies do not include dependencies on unwind.h,
+# even though that is part of GCC, because where to find it depends on
+# whether we are being built as a host library or a target library.
+
+alloc.lo: config.h backtrace.h internal.h
+backtrace.lo: config.h backtrace.h internal.h
+btest.lo:  backtrace.h backtrace-supported.h filenames.h
+dwarf.lo: config.h filenames.h backtrace.h internal.h
+elf.lo: config.h backtrace.h internal.h
+fileline.lo: config.h backtrace.h internal.h
+mmap.lo: config.h backtrace.h internal.h
+mmapio.lo: config.h backtrace.h internal.h
+nounwind.lo: config.h internal.h
+pecoff.lo: config.h backtrace.h internal.h
+posix.lo: config.h backtrace.h internal.h
+print.lo: config.h backtrace.h internal.h
+read.lo: config.h backtrace.h internal.h
+simple.lo: config.h backtrace.h internal.h
+sort.lo: config.h backtrace.h internal.h
+stest.lo: config.h backtrace.h internal.h
+state.lo: config.h backtrace.h backtrace-supported.h internal.h
+unknown.lo: config.h backtrace.h internal.h
+xcoff.lo: config.h backtrace.h internal.h
+
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/Makefile.in b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/Makefile.in
new file mode 100644
index 0000000..498f7fb
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/Makefile.in
@@ -0,0 +1,1021 @@
+# Makefile.in generated by automake 1.11.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Makefile.am -- Backtrace Makefile.
+# Copyright (C) 2012-2018 Free Software Foundation, Inc.
+
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+
+#     (1) Redistributions of source code must retain the above copyright
+#     notice, this list of conditions and the following disclaimer.
+
+#     (2) Redistributions in binary form must reproduce the above copyright
+#     notice, this list of conditions and the following disclaimer in
+#     the documentation and/or other materials provided with the
+#     distribution.
+
+#     (3) The name of the author may not be used to
+#     endorse or promote products derived from this software without
+#     specific prior written permission.
+
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+
+VPATH = @srcdir@
+am__make_dryrun = \
+  { \
+    am__dry=no; \
+    case $$MAKEFLAGS in \
+      *\\[\ \	]*) \
+        echo 'am--echo: ; @echo "AM"  OK' | $(MAKE) -f - 2>/dev/null \
+          | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+      *) \
+        for am__flg in $$MAKEFLAGS; do \
+          case $$am__flg in \
+            *=*|--*) ;; \
+            *n*) am__dry=yes; break;; \
+          esac; \
+        done;; \
+    esac; \
+    test $$am__dry = yes; \
+  }
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3)
+@NATIVE_TRUE@am__append_1 = btest btest_static stest ztest edtest
+@HAVE_ZLIB_TRUE@@NATIVE_TRUE@am__append_2 = -lz
+@NATIVE_TRUE@am__append_3 = edtest2_build.c gen_edtest2_build
+@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@am__append_4 = ttest
+@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@am__append_5 = dtest
+@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@am__append_6 = dtest btest.debug
+@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@am__append_7 = ctestg ctesta
+subdir = .
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+	$(top_srcdir)/configure $(am__configure_deps) \
+	$(srcdir)/config.h.in $(srcdir)/backtrace-supported.h.in \
+	$(include_HEADERS)
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/config/libtool.m4 \
+	$(top_srcdir)/config/ltoptions.m4 \
+	$(top_srcdir)/config/ltsugar.m4 \
+	$(top_srcdir)/config/ltversion.m4 \
+	$(top_srcdir)/config/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES = backtrace-supported.h
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         $(am__cd) "$$dir" && rm -f $$files; }; \
+  }
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+am_libbacktrace_la_OBJECTS = atomic.lo dwarf.lo fileline.lo posix.lo \
+	print.lo sort.lo state.lo
+libbacktrace_la_OBJECTS = $(am_libbacktrace_la_OBJECTS)
+@NATIVE_TRUE@am__EXEEXT_1 = btest$(EXEEXT) btest_static$(EXEEXT) \
+@NATIVE_TRUE@	stest$(EXEEXT) ztest$(EXEEXT) edtest$(EXEEXT)
+@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@am__EXEEXT_2 = ttest$(EXEEXT)
+@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@am__EXEEXT_3 =  \
+@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@	ctestg$(EXEEXT) \
+@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@	ctesta$(EXEEXT)
+@NATIVE_TRUE@am_btest_OBJECTS = btest-btest.$(OBJEXT) \
+@NATIVE_TRUE@	btest-testlib.$(OBJEXT)
+btest_OBJECTS = $(am_btest_OBJECTS)
+@NATIVE_TRUE@btest_DEPENDENCIES = libbacktrace.la
+btest_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CCLD) $(btest_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+@NATIVE_TRUE@am_btest_static_OBJECTS = btest_static-btest.$(OBJEXT) \
+@NATIVE_TRUE@	btest_static-testlib.$(OBJEXT)
+btest_static_OBJECTS = $(am_btest_static_OBJECTS)
+@NATIVE_TRUE@btest_static_DEPENDENCIES = libbacktrace.la
+btest_static_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(btest_static_CFLAGS) \
+	$(CFLAGS) $(btest_static_LDFLAGS) $(LDFLAGS) -o $@
+@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@am_ctesta_OBJECTS = ctesta-btest.$(OBJEXT) \
+@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@	ctesta-testlib.$(OBJEXT)
+ctesta_OBJECTS = $(am_ctesta_OBJECTS)
+@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@ctesta_DEPENDENCIES =  \
+@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@	libbacktrace.la
+ctesta_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CCLD) $(ctesta_CFLAGS) $(CFLAGS) \
+	$(ctesta_LDFLAGS) $(LDFLAGS) -o $@
+@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@am_ctestg_OBJECTS = ctestg-btest.$(OBJEXT) \
+@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@	ctestg-testlib.$(OBJEXT)
+ctestg_OBJECTS = $(am_ctestg_OBJECTS)
+@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@ctestg_DEPENDENCIES =  \
+@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@	libbacktrace.la
+ctestg_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CCLD) $(ctestg_CFLAGS) $(CFLAGS) \
+	$(ctestg_LDFLAGS) $(LDFLAGS) -o $@
+@NATIVE_TRUE@am_edtest_OBJECTS = edtest.$(OBJEXT) \
+@NATIVE_TRUE@	edtest2_build.$(OBJEXT) testlib.$(OBJEXT)
+edtest_OBJECTS = $(am_edtest_OBJECTS)
+@NATIVE_TRUE@edtest_DEPENDENCIES = libbacktrace.la
+@NATIVE_TRUE@am_stest_OBJECTS = stest.$(OBJEXT)
+stest_OBJECTS = $(am_stest_OBJECTS)
+@NATIVE_TRUE@stest_DEPENDENCIES = libbacktrace.la
+@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@am_ttest_OBJECTS =  \
+@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@	ttest-ttest.$(OBJEXT) \
+@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@	ttest-testlib.$(OBJEXT)
+ttest_OBJECTS = $(am_ttest_OBJECTS)
+@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@ttest_DEPENDENCIES = libbacktrace.la
+ttest_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CCLD) $(ttest_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+@NATIVE_TRUE@am_ztest_OBJECTS = ztest-ztest.$(OBJEXT) \
+@NATIVE_TRUE@	ztest-testlib.$(OBJEXT)
+ztest_OBJECTS = $(am_ztest_OBJECTS)
+@NATIVE_TRUE@ztest_DEPENDENCIES = libbacktrace.la \
+@NATIVE_TRUE@	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+ztest_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CCLD) $(ztest_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@
+depcomp =
+am__depfiles_maybe =
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+SOURCES = $(libbacktrace_la_SOURCES) $(EXTRA_libbacktrace_la_SOURCES) \
+	$(btest_SOURCES) $(btest_static_SOURCES) $(ctesta_SOURCES) \
+	$(ctestg_SOURCES) $(edtest_SOURCES) $(stest_SOURCES) \
+	$(ttest_SOURCES) $(ztest_SOURCES)
+MULTISRCTOP = 
+MULTIBUILDTOP = 
+MULTIDIRS = 
+MULTISUBDIR = 
+MULTIDO = true
+MULTICLEAN = true
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+HEADERS = $(include_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+am__tty_colors = \
+red=; grn=; lgn=; blu=; std=
+ACLOCAL = @ACLOCAL@
+ALLOC_FILE = @ALLOC_FILE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BACKTRACE_FILE = @BACKTRACE_FILE@
+BACKTRACE_SUPPORTED = @BACKTRACE_SUPPORTED@
+BACKTRACE_SUPPORTS_DATA = @BACKTRACE_SUPPORTS_DATA@
+BACKTRACE_SUPPORTS_THREADS = @BACKTRACE_SUPPORTS_THREADS@
+BACKTRACE_USES_MALLOC = @BACKTRACE_USES_MALLOC@
+CC = @CC@
+CFLAGS = @CFLAGS@
+CLOCK_GETTIME_LINK = @CLOCK_GETTIME_LINK@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXTRA_FLAGS = @EXTRA_FLAGS@
+FGREP = @FGREP@
+FORMAT_FILE = @FORMAT_FILE@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJCOPY = @OBJCOPY@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PIC_FLAG = @PIC_FLAG@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+VIEW_FILE = @VIEW_FILE@
+WARN_FLAGS = @WARN_FLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__leading_dot = @am__leading_dot@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libtool_VERSION = @libtool_VERSION@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+multi_basedir = @multi_basedir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+ACLOCAL_AMFLAGS = -I config
+AM_CFLAGS = $(EXTRA_FLAGS) $(WARN_FLAGS) $(PIC_FLAG)
+include_HEADERS = backtrace.h backtrace-supported.h
+lib_LTLIBRARIES = libbacktrace.la
+libbacktrace_la_SOURCES = \
+	backtrace.h \
+	atomic.c \
+	dwarf.c \
+	fileline.c \
+	internal.h \
+	posix.c \
+	print.c \
+	sort.c \
+	state.c
+
+BACKTRACE_FILES = \
+	backtrace.c \
+	simple.c \
+	nounwind.c
+
+FORMAT_FILES = \
+	elf.c \
+	pecoff.c \
+	unknown.c \
+	xcoff.c
+
+VIEW_FILES = \
+	read.c \
+	mmapio.c
+
+ALLOC_FILES = \
+	alloc.c \
+	mmap.c
+
+EXTRA_libbacktrace_la_SOURCES = \
+	$(BACKTRACE_FILES) \
+	$(FORMAT_FILES) \
+	$(VIEW_FILES) \
+	$(ALLOC_FILES)
+
+libbacktrace_la_LIBADD = \
+	$(BACKTRACE_FILE) \
+	$(FORMAT_FILE) \
+	$(VIEW_FILE) \
+	$(ALLOC_FILE)
+
+libbacktrace_la_DEPENDENCIES = $(libbacktrace_la_LIBADD)
+CLEANFILES = $(am__append_3) $(am__append_6)
+TESTS = $(check_PROGRAMS) $(am__append_5)
+@NATIVE_TRUE@btest_SOURCES = btest.c testlib.c
+@NATIVE_TRUE@btest_CFLAGS = $(AM_CFLAGS) -g -O
+@NATIVE_TRUE@btest_LDADD = libbacktrace.la
+@NATIVE_TRUE@btest_static_SOURCES = btest.c testlib.c
+@NATIVE_TRUE@btest_static_CFLAGS = $(AM_CFLAGS) -g -O
+@NATIVE_TRUE@btest_static_LDADD = libbacktrace.la
+@NATIVE_TRUE@btest_static_LDFLAGS = -static-libtool-libs
+@NATIVE_TRUE@stest_SOURCES = stest.c
+@NATIVE_TRUE@stest_LDADD = libbacktrace.la
+@NATIVE_TRUE@ztest_SOURCES = ztest.c testlib.c
+@NATIVE_TRUE@ztest_CFLAGS = -DSRCDIR=\"$(srcdir)\"
+@NATIVE_TRUE@ztest_LDADD = libbacktrace.la $(am__append_2) \
+@NATIVE_TRUE@	$(CLOCK_GETTIME_LINK)
+@NATIVE_TRUE@edtest_SOURCES = edtest.c edtest2_build.c testlib.c
+@NATIVE_TRUE@edtest_LDADD = libbacktrace.la
+@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@ttest_SOURCES = ttest.c testlib.c
+@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@ttest_CFLAGS = $(AM_CFLAGS) -pthread
+@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@ttest_LDADD = libbacktrace.la
+@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@ctestg_SOURCES = btest.c testlib.c
+@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@ctestg_CFLAGS = $(AM_CFLAGS) -g
+@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@ctestg_LDFLAGS = -Wl,--compress-debug-sections=zlib-gnu
+@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@ctestg_LDADD = libbacktrace.la
+@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@ctesta_SOURCES = btest.c testlib.c
+@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@ctesta_CFLAGS = $(AM_CFLAGS) -g
+@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@ctesta_LDFLAGS = -Wl,--compress-debug-sections=zlib-gabi
+@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@ctesta_LDADD = libbacktrace.la
+all: config.h
+	$(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+am--refresh: Makefile
+	@:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      echo ' cd $(srcdir) && $(AUTOMAKE) --foreign --ignore-deps'; \
+	      $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign --ignore-deps \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign --ignore-deps Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign --ignore-deps Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    echo ' $(SHELL) ./config.status'; \
+	    $(SHELL) ./config.status;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	$(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	$(am__cd) $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+$(am__aclocal_m4_deps):
+
+config.h: stamp-h1
+	@if test ! -f $@; then rm -f stamp-h1; else :; fi
+	@if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi
+
+stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
+	@rm -f stamp-h1
+	cd $(top_builddir) && $(SHELL) ./config.status config.h
+$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) 
+	($(am__cd) $(top_srcdir) && $(AUTOHEADER))
+	rm -f stamp-h1
+	touch $@
+
+distclean-hdr:
+	-rm -f config.h stamp-h1
+backtrace-supported.h: $(top_builddir)/config.status $(srcdir)/backtrace-supported.h.in
+	cd $(top_builddir) && $(SHELL) ./config.status $@
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+	@$(NORMAL_INSTALL)
+	@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+	list2=; for p in $$list; do \
+	  if test -f $$p; then \
+	    list2="$$list2 $$p"; \
+	  else :; fi; \
+	done; \
+	test -z "$$list2" || { \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+	}
+
+uninstall-libLTLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+	for p in $$list; do \
+	  $(am__strip_dir) \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+	done
+
+clean-libLTLIBRARIES:
+	-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+	@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+	  dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+	  test "$$dir" != "$$p" || dir=.; \
+	  echo "rm -f \"$${dir}/so_locations\""; \
+	  rm -f "$${dir}/so_locations"; \
+	done
+libbacktrace.la: $(libbacktrace_la_OBJECTS) $(libbacktrace_la_DEPENDENCIES) $(EXTRA_libbacktrace_la_DEPENDENCIES) 
+	$(LINK) -rpath $(libdir) $(libbacktrace_la_OBJECTS) $(libbacktrace_la_LIBADD) $(LIBS)
+
+clean-checkPROGRAMS:
+	@list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \
+	echo " rm -f" $$list; \
+	rm -f $$list || exit $$?; \
+	test -n "$(EXEEXT)" || exit 0; \
+	list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+	echo " rm -f" $$list; \
+	rm -f $$list
+btest$(EXEEXT): $(btest_OBJECTS) $(btest_DEPENDENCIES) $(EXTRA_btest_DEPENDENCIES) 
+	@rm -f btest$(EXEEXT)
+	$(btest_LINK) $(btest_OBJECTS) $(btest_LDADD) $(LIBS)
+btest_static$(EXEEXT): $(btest_static_OBJECTS) $(btest_static_DEPENDENCIES) $(EXTRA_btest_static_DEPENDENCIES) 
+	@rm -f btest_static$(EXEEXT)
+	$(btest_static_LINK) $(btest_static_OBJECTS) $(btest_static_LDADD) $(LIBS)
+ctesta$(EXEEXT): $(ctesta_OBJECTS) $(ctesta_DEPENDENCIES) $(EXTRA_ctesta_DEPENDENCIES) 
+	@rm -f ctesta$(EXEEXT)
+	$(ctesta_LINK) $(ctesta_OBJECTS) $(ctesta_LDADD) $(LIBS)
+ctestg$(EXEEXT): $(ctestg_OBJECTS) $(ctestg_DEPENDENCIES) $(EXTRA_ctestg_DEPENDENCIES) 
+	@rm -f ctestg$(EXEEXT)
+	$(ctestg_LINK) $(ctestg_OBJECTS) $(ctestg_LDADD) $(LIBS)
+edtest$(EXEEXT): $(edtest_OBJECTS) $(edtest_DEPENDENCIES) $(EXTRA_edtest_DEPENDENCIES) 
+	@rm -f edtest$(EXEEXT)
+	$(LINK) $(edtest_OBJECTS) $(edtest_LDADD) $(LIBS)
+stest$(EXEEXT): $(stest_OBJECTS) $(stest_DEPENDENCIES) $(EXTRA_stest_DEPENDENCIES) 
+	@rm -f stest$(EXEEXT)
+	$(LINK) $(stest_OBJECTS) $(stest_LDADD) $(LIBS)
+ttest$(EXEEXT): $(ttest_OBJECTS) $(ttest_DEPENDENCIES) $(EXTRA_ttest_DEPENDENCIES) 
+	@rm -f ttest$(EXEEXT)
+	$(ttest_LINK) $(ttest_OBJECTS) $(ttest_LDADD) $(LIBS)
+ztest$(EXEEXT): $(ztest_OBJECTS) $(ztest_DEPENDENCIES) $(EXTRA_ztest_DEPENDENCIES) 
+	@rm -f ztest$(EXEEXT)
+	$(ztest_LINK) $(ztest_OBJECTS) $(ztest_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+.c.o:
+	$(COMPILE) -c $<
+
+.c.obj:
+	$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+	$(LTCOMPILE) -c -o $@ $<
+
+btest-btest.o: btest.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(btest_CFLAGS) $(CFLAGS) -c -o btest-btest.o `test -f 'btest.c' || echo '$(srcdir)/'`btest.c
+
+btest-btest.obj: btest.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(btest_CFLAGS) $(CFLAGS) -c -o btest-btest.obj `if test -f 'btest.c'; then $(CYGPATH_W) 'btest.c'; else $(CYGPATH_W) '$(srcdir)/btest.c'; fi`
+
+btest-testlib.o: testlib.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(btest_CFLAGS) $(CFLAGS) -c -o btest-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c
+
+btest-testlib.obj: testlib.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(btest_CFLAGS) $(CFLAGS) -c -o btest-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`
+
+btest_static-btest.o: btest.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(btest_static_CFLAGS) $(CFLAGS) -c -o btest_static-btest.o `test -f 'btest.c' || echo '$(srcdir)/'`btest.c
+
+btest_static-btest.obj: btest.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(btest_static_CFLAGS) $(CFLAGS) -c -o btest_static-btest.obj `if test -f 'btest.c'; then $(CYGPATH_W) 'btest.c'; else $(CYGPATH_W) '$(srcdir)/btest.c'; fi`
+
+btest_static-testlib.o: testlib.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(btest_static_CFLAGS) $(CFLAGS) -c -o btest_static-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c
+
+btest_static-testlib.obj: testlib.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(btest_static_CFLAGS) $(CFLAGS) -c -o btest_static-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`
+
+ctesta-btest.o: btest.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctesta_CFLAGS) $(CFLAGS) -c -o ctesta-btest.o `test -f 'btest.c' || echo '$(srcdir)/'`btest.c
+
+ctesta-btest.obj: btest.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctesta_CFLAGS) $(CFLAGS) -c -o ctesta-btest.obj `if test -f 'btest.c'; then $(CYGPATH_W) 'btest.c'; else $(CYGPATH_W) '$(srcdir)/btest.c'; fi`
+
+ctesta-testlib.o: testlib.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctesta_CFLAGS) $(CFLAGS) -c -o ctesta-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c
+
+ctesta-testlib.obj: testlib.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctesta_CFLAGS) $(CFLAGS) -c -o ctesta-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`
+
+ctestg-btest.o: btest.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctestg_CFLAGS) $(CFLAGS) -c -o ctestg-btest.o `test -f 'btest.c' || echo '$(srcdir)/'`btest.c
+
+ctestg-btest.obj: btest.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctestg_CFLAGS) $(CFLAGS) -c -o ctestg-btest.obj `if test -f 'btest.c'; then $(CYGPATH_W) 'btest.c'; else $(CYGPATH_W) '$(srcdir)/btest.c'; fi`
+
+ctestg-testlib.o: testlib.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctestg_CFLAGS) $(CFLAGS) -c -o ctestg-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c
+
+ctestg-testlib.obj: testlib.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctestg_CFLAGS) $(CFLAGS) -c -o ctestg-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`
+
+ttest-ttest.o: ttest.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ttest_CFLAGS) $(CFLAGS) -c -o ttest-ttest.o `test -f 'ttest.c' || echo '$(srcdir)/'`ttest.c
+
+ttest-ttest.obj: ttest.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ttest_CFLAGS) $(CFLAGS) -c -o ttest-ttest.obj `if test -f 'ttest.c'; then $(CYGPATH_W) 'ttest.c'; else $(CYGPATH_W) '$(srcdir)/ttest.c'; fi`
+
+ttest-testlib.o: testlib.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ttest_CFLAGS) $(CFLAGS) -c -o ttest-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c
+
+ttest-testlib.obj: testlib.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ttest_CFLAGS) $(CFLAGS) -c -o ttest-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`
+
+ztest-ztest.o: ztest.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ztest_CFLAGS) $(CFLAGS) -c -o ztest-ztest.o `test -f 'ztest.c' || echo '$(srcdir)/'`ztest.c
+
+ztest-ztest.obj: ztest.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ztest_CFLAGS) $(CFLAGS) -c -o ztest-ztest.obj `if test -f 'ztest.c'; then $(CYGPATH_W) 'ztest.c'; else $(CYGPATH_W) '$(srcdir)/ztest.c'; fi`
+
+ztest-testlib.o: testlib.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ztest_CFLAGS) $(CFLAGS) -c -o ztest-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c
+
+ztest-testlib.obj: testlib.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ztest_CFLAGS) $(CFLAGS) -c -o ztest-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+	-rm -f libtool config.lt
+
+# GNU Make needs to see an explicit $(MAKE) variable in the command it
+# runs to enable its job server during parallel builds.  Hence the
+# comments below.
+all-multi:
+	$(MULTIDO) $(AM_MAKEFLAGS) DO=all multi-do # $(MAKE)
+install-multi:
+	$(MULTIDO) $(AM_MAKEFLAGS) DO=install multi-do # $(MAKE)
+
+mostlyclean-multi:
+	$(MULTICLEAN) $(AM_MAKEFLAGS) DO=mostlyclean multi-clean # $(MAKE)
+clean-multi:
+	$(MULTICLEAN) $(AM_MAKEFLAGS) DO=clean multi-clean # $(MAKE)
+distclean-multi:
+	$(MULTICLEAN) $(AM_MAKEFLAGS) DO=distclean multi-clean # $(MAKE)
+maintainer-clean-multi:
+	$(MULTICLEAN) $(AM_MAKEFLAGS) DO=maintainer-clean multi-clean # $(MAKE)
+install-includeHEADERS: $(include_HEADERS)
+	@$(NORMAL_INSTALL)
+	@list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \
+	fi; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \
+	  $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \
+	done
+
+uninstall-includeHEADERS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir)
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	set x; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+check-TESTS: $(TESTS)
+	@failed=0; all=0; xfail=0; xpass=0; skip=0; \
+	srcdir=$(srcdir); export srcdir; \
+	list=' $(TESTS) '; \
+	$(am__tty_colors); \
+	if test -n "$$list"; then \
+	  for tst in $$list; do \
+	    if test -f ./$$tst; then dir=./; \
+	    elif test -f $$tst; then dir=; \
+	    else dir="$(srcdir)/"; fi; \
+	    if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
+	      all=`expr $$all + 1`; \
+	      case " $(XFAIL_TESTS) " in \
+	      *[\ \	]$$tst[\ \	]*) \
+		xpass=`expr $$xpass + 1`; \
+		failed=`expr $$failed + 1`; \
+		col=$$red; res=XPASS; \
+	      ;; \
+	      *) \
+		col=$$grn; res=PASS; \
+	      ;; \
+	      esac; \
+	    elif test $$? -ne 77; then \
+	      all=`expr $$all + 1`; \
+	      case " $(XFAIL_TESTS) " in \
+	      *[\ \	]$$tst[\ \	]*) \
+		xfail=`expr $$xfail + 1`; \
+		col=$$lgn; res=XFAIL; \
+	      ;; \
+	      *) \
+		failed=`expr $$failed + 1`; \
+		col=$$red; res=FAIL; \
+	      ;; \
+	      esac; \
+	    else \
+	      skip=`expr $$skip + 1`; \
+	      col=$$blu; res=SKIP; \
+	    fi; \
+	    echo "$${col}$$res$${std}: $$tst"; \
+	  done; \
+	  if test "$$all" -eq 1; then \
+	    tests="test"; \
+	    All=""; \
+	  else \
+	    tests="tests"; \
+	    All="All "; \
+	  fi; \
+	  if test "$$failed" -eq 0; then \
+	    if test "$$xfail" -eq 0; then \
+	      banner="$$All$$all $$tests passed"; \
+	    else \
+	      if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
+	      banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
+	    fi; \
+	  else \
+	    if test "$$xpass" -eq 0; then \
+	      banner="$$failed of $$all $$tests failed"; \
+	    else \
+	      if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
+	      banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
+	    fi; \
+	  fi; \
+	  dashes="$$banner"; \
+	  skipped=""; \
+	  if test "$$skip" -ne 0; then \
+	    if test "$$skip" -eq 1; then \
+	      skipped="($$skip test was not run)"; \
+	    else \
+	      skipped="($$skip tests were not run)"; \
+	    fi; \
+	    test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+	      dashes="$$skipped"; \
+	  fi; \
+	  report=""; \
+	  if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+	    report="Please report to $(PACKAGE_BUGREPORT)"; \
+	    test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+	      dashes="$$report"; \
+	  fi; \
+	  dashes=`echo "$$dashes" | sed s/./=/g`; \
+	  if test "$$failed" -eq 0; then \
+	    col="$$grn"; \
+	  else \
+	    col="$$red"; \
+	  fi; \
+	  echo "$${col}$$dashes$${std}"; \
+	  echo "$${col}$$banner$${std}"; \
+	  test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \
+	  test -z "$$report" || echo "$${col}$$report$${std}"; \
+	  echo "$${col}$$dashes$${std}"; \
+	  test "$$failed" -eq 0; \
+	else :; fi
+check-am: all-am
+	$(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
+	$(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile $(LTLIBRARIES) all-multi $(HEADERS) config.h
+installdirs:
+	for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	if test -z '$(STRIP)'; then \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	      install; \
+	else \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+	fi
+mostlyclean-generic:
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am clean-multi
+
+clean-am: clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \
+	clean-libtool mostlyclean-am
+
+distclean: distclean-am distclean-multi
+	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-hdr distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-includeHEADERS
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-libLTLIBRARIES install-multi
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am maintainer-clean-multi
+	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
+	-rm -rf $(top_srcdir)/autom4te.cache
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am mostlyclean-multi
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-includeHEADERS uninstall-libLTLIBRARIES
+
+.MAKE: all all-multi check-am clean-multi distclean-multi install-am \
+	install-multi install-strip maintainer-clean-multi \
+	mostlyclean-multi
+
+.PHONY: CTAGS GTAGS all all-am all-multi am--refresh check check-TESTS \
+	check-am clean clean-checkPROGRAMS clean-generic \
+	clean-libLTLIBRARIES clean-libtool clean-multi ctags distclean \
+	distclean-compile distclean-generic distclean-hdr \
+	distclean-libtool distclean-multi distclean-tags dvi dvi-am \
+	html html-am info info-am install install-am install-data \
+	install-data-am install-dvi install-dvi-am install-exec \
+	install-exec-am install-html install-html-am \
+	install-includeHEADERS install-info install-info-am \
+	install-libLTLIBRARIES install-man install-multi install-pdf \
+	install-pdf-am install-ps install-ps-am install-strip \
+	installcheck installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic maintainer-clean-multi mostlyclean \
+	mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+	mostlyclean-multi pdf pdf-am ps ps-am tags uninstall \
+	uninstall-am uninstall-includeHEADERS uninstall-libLTLIBRARIES
+
+
+@NATIVE_TRUE@edtest2_build.c: gen_edtest2_build; @true
+@NATIVE_TRUE@gen_edtest2_build: $(srcdir)/edtest2.c
+@NATIVE_TRUE@	cat $(srcdir)/edtest2.c > tmp-edtest2_build.c
+@NATIVE_TRUE@	$(SHELL) $(srcdir)/move-if-change tmp-edtest2_build.c edtest2_build.c
+@NATIVE_TRUE@	echo timestamp > $@
+
+@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@dtest: btest_static
+@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@	$(OBJCOPY) --only-keep-debug btest_static btest.debug
+@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@	$(OBJCOPY) --strip-debug --add-gnu-debuglink=btest.debug btest_static dtest
+
+# We can't use automake's automatic dependency tracking, because it
+# breaks when using bootstrap-lean.  Automatic dependency tracking
+# with GCC bootstrap will cause some of the objects to depend on
+# header files in prev-gcc/include, e.g., stddef.h and stdarg.h.  When
+# using bootstrap-lean, prev-gcc is removed after each stage.  When
+# running "make install", those header files will be gone, causing the
+# library to be rebuilt at install time.  That may not succeed.
+
+# These manual dependencies do not include dependencies on unwind.h,
+# even though that is part of GCC, because where to find it depends on
+# whether we are being built as a host library or a target library.
+
+alloc.lo: config.h backtrace.h internal.h
+backtrace.lo: config.h backtrace.h internal.h
+btest.lo:  backtrace.h backtrace-supported.h filenames.h
+dwarf.lo: config.h filenames.h backtrace.h internal.h
+elf.lo: config.h backtrace.h internal.h
+fileline.lo: config.h backtrace.h internal.h
+mmap.lo: config.h backtrace.h internal.h
+mmapio.lo: config.h backtrace.h internal.h
+nounwind.lo: config.h internal.h
+pecoff.lo: config.h backtrace.h internal.h
+posix.lo: config.h backtrace.h internal.h
+print.lo: config.h backtrace.h internal.h
+read.lo: config.h backtrace.h internal.h
+simple.lo: config.h backtrace.h internal.h
+sort.lo: config.h backtrace.h internal.h
+stest.lo: config.h backtrace.h internal.h
+state.lo: config.h backtrace.h backtrace-supported.h internal.h
+unknown.lo: config.h backtrace.h internal.h
+xcoff.lo: config.h backtrace.h internal.h
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/Mark.Twain-Tom.Sawyer.txt b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/Mark.Twain-Tom.Sawyer.txt
new file mode 100644
index 0000000..c9106fd
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/Mark.Twain-Tom.Sawyer.txt
@@ -0,0 +1,8465 @@
+Produced by David Widger. The previous edition was updated by Jose
+Menendez.
+
+
+
+
+
+                   THE ADVENTURES OF TOM SAWYER
+                                BY
+                            MARK TWAIN
+                     (Samuel Langhorne Clemens)
+
+
+
+
+                           P R E F A C E
+
+MOST of the adventures recorded in this book really occurred; one or
+two were experiences of my own, the rest those of boys who were
+schoolmates of mine. Huck Finn is drawn from life; Tom Sawyer also, but
+not from an individual--he is a combination of the characteristics of
+three boys whom I knew, and therefore belongs to the composite order of
+architecture.
+
+The odd superstitions touched upon were all prevalent among children
+and slaves in the West at the period of this story--that is to say,
+thirty or forty years ago.
+
+Although my book is intended mainly for the entertainment of boys and
+girls, I hope it will not be shunned by men and women on that account,
+for part of my plan has been to try to pleasantly remind adults of what
+they once were themselves, and of how they felt and thought and talked,
+and what queer enterprises they sometimes engaged in.
+
+                                                            THE AUTHOR.
+
+HARTFORD, 1876.
+
+
+
+                          T O M   S A W Y E R
+
+
+
+CHAPTER I
+
+"TOM!"
+
+No answer.
+
+"TOM!"
+
+No answer.
+
+"What's gone with that boy,  I wonder? You TOM!"
+
+No answer.
+
+The old lady pulled her spectacles down and looked over them about the
+room; then she put them up and looked out under them. She seldom or
+never looked THROUGH them for so small a thing as a boy; they were her
+state pair, the pride of her heart, and were built for "style," not
+service--she could have seen through a pair of stove-lids just as well.
+She looked perplexed for a moment, and then said, not fiercely, but
+still loud enough for the furniture to hear:
+
+"Well, I lay if I get hold of you I'll--"
+
+She did not finish, for by this time she was bending down and punching
+under the bed with the broom, and so she needed breath to punctuate the
+punches with. She resurrected nothing but the cat.
+
+"I never did see the beat of that boy!"
+
+She went to the open door and stood in it and looked out among the
+tomato vines and "jimpson" weeds that constituted the garden. No Tom.
+So she lifted up her voice at an angle calculated for distance and
+shouted:
+
+"Y-o-u-u TOM!"
+
+There was a slight noise behind her and she turned just in time to
+seize a small boy by the slack of his roundabout and arrest his flight.
+
+"There! I might 'a' thought of that closet. What you been doing in
+there?"
+
+"Nothing."
+
+"Nothing! Look at your hands. And look at your mouth. What IS that
+truck?"
+
+"I don't know, aunt."
+
+"Well, I know. It's jam--that's what it is. Forty times I've said if
+you didn't let that jam alone I'd skin you. Hand me that switch."
+
+The switch hovered in the air--the peril was desperate--
+
+"My! Look behind you, aunt!"
+
+The old lady whirled round, and snatched her skirts out of danger. The
+lad fled on the instant, scrambled up the high board-fence, and
+disappeared over it.
+
+His aunt Polly stood surprised a moment, and then broke into a gentle
+laugh.
+
+"Hang the boy, can't I never learn anything? Ain't he played me tricks
+enough like that for me to be looking out for him by this time? But old
+fools is the biggest fools there is. Can't learn an old dog new tricks,
+as the saying is. But my goodness, he never plays them alike, two days,
+and how is a body to know what's coming? He 'pears to know just how
+long he can torment me before I get my dander up, and he knows if he
+can make out to put me off for a minute or make me laugh, it's all down
+again and I can't hit him a lick. I ain't doing my duty by that boy,
+and that's the Lord's truth, goodness knows. Spare the rod and spile
+the child, as the Good Book says. I'm a laying up sin and suffering for
+us both, I know. He's full of the Old Scratch, but laws-a-me! he's my
+own dead sister's boy, poor thing, and I ain't got the heart to lash
+him, somehow. Every time I let him off, my conscience does hurt me so,
+and every time I hit him my old heart most breaks. Well-a-well, man
+that is born of woman is of few days and full of trouble, as the
+Scripture says, and I reckon it's so. He'll play hookey this evening, *
+and [* Southwestern for "afternoon"] I'll just be obleeged to make him
+work, to-morrow, to punish him. It's mighty hard to make him work
+Saturdays, when all the boys is having holiday, but he hates work more
+than he hates anything else, and I've GOT to do some of my duty by him,
+or I'll be the ruination of the child."
+
+Tom did play hookey, and he had a very good time. He got back home
+barely in season to help Jim, the small colored boy, saw next-day's
+wood and split the kindlings before supper--at least he was there in
+time to tell his adventures to Jim while Jim did three-fourths of the
+work. Tom's younger brother (or rather half-brother) Sid was already
+through with his part of the work (picking up chips), for he was a
+quiet boy, and had no adventurous, troublesome ways.
+
+While Tom was eating his supper, and stealing sugar as opportunity
+offered, Aunt Polly asked him questions that were full of guile, and
+very deep--for she wanted to trap him into damaging revealments. Like
+many other simple-hearted souls, it was her pet vanity to believe she
+was endowed with a talent for dark and mysterious diplomacy, and she
+loved to contemplate her most transparent devices as marvels of low
+cunning. Said she:
+
+"Tom, it was middling warm in school, warn't it?"
+
+"Yes'm."
+
+"Powerful warm, warn't it?"
+
+"Yes'm."
+
+"Didn't you want to go in a-swimming, Tom?"
+
+A bit of a scare shot through Tom--a touch of uncomfortable suspicion.
+He searched Aunt Polly's face, but it told him nothing. So he said:
+
+"No'm--well, not very much."
+
+The old lady reached out her hand and felt Tom's shirt, and said:
+
+"But you ain't too warm now, though." And it flattered her to reflect
+that she had discovered that the shirt was dry without anybody knowing
+that that was what she had in her mind. But in spite of her, Tom knew
+where the wind lay, now. So he forestalled what might be the next move:
+
+"Some of us pumped on our heads--mine's damp yet. See?"
+
+Aunt Polly was vexed to think she had overlooked that bit of
+circumstantial evidence, and missed a trick. Then she had a new
+inspiration:
+
+"Tom, you didn't have to undo your shirt collar where I sewed it, to
+pump on your head, did you? Unbutton your jacket!"
+
+The trouble vanished out of Tom's face. He opened his jacket. His
+shirt collar was securely sewed.
+
+"Bother! Well, go 'long with you. I'd made sure you'd played hookey
+and been a-swimming. But I forgive ye, Tom. I reckon you're a kind of a
+singed cat, as the saying is--better'n you look. THIS time."
+
+She was half sorry her sagacity had miscarried, and half glad that Tom
+had stumbled into obedient conduct for once.
+
+But Sidney said:
+
+"Well, now, if I didn't think you sewed his collar with white thread,
+but it's black."
+
+"Why, I did sew it with white! Tom!"
+
+But Tom did not wait for the rest. As he went out at the door he said:
+
+"Siddy, I'll lick you for that."
+
+In a safe place Tom examined two large needles which were thrust into
+the lapels of his jacket, and had thread bound about them--one needle
+carried white thread and the other black. He said:
+
+"She'd never noticed if it hadn't been for Sid. Confound it! sometimes
+she sews it with white, and sometimes she sews it with black. I wish to
+geeminy she'd stick to one or t'other--I can't keep the run of 'em. But
+I bet you I'll lam Sid for that. I'll learn him!"
+
+He was not the Model Boy of the village. He knew the model boy very
+well though--and loathed him.
+
+Within two minutes, or even less, he had forgotten all his troubles.
+Not because his troubles were one whit less heavy and bitter to him
+than a man's are to a man, but because a new and powerful interest bore
+them down and drove them out of his mind for the time--just as men's
+misfortunes are forgotten in the excitement of new enterprises. This
+new interest was a valued novelty in whistling, which he had just
+acquired from a negro, and he was suffering to practise it undisturbed.
+It consisted in a peculiar bird-like turn, a sort of liquid warble,
+produced by touching the tongue to the roof of the mouth at short
+intervals in the midst of the music--the reader probably remembers how
+to do it, if he has ever been a boy. Diligence and attention soon gave
+him the knack of it, and he strode down the street with his mouth full
+of harmony and his soul full of gratitude. He felt much as an
+astronomer feels who has discovered a new planet--no doubt, as far as
+strong, deep, unalloyed pleasure is concerned, the advantage was with
+the boy, not the astronomer.
+
+The summer evenings were long. It was not dark, yet. Presently Tom
+checked his whistle. A stranger was before him--a boy a shade larger
+than himself. A new-comer of any age or either sex was an impressive
+curiosity in the poor little shabby village of St. Petersburg. This boy
+was well dressed, too--well dressed on a week-day. This was simply
+astounding. His cap was a dainty thing, his close-buttoned blue cloth
+roundabout was new and natty, and so were his pantaloons. He had shoes
+on--and it was only Friday. He even wore a necktie, a bright bit of
+ribbon. He had a citified air about him that ate into Tom's vitals. The
+more Tom stared at the splendid marvel, the higher he turned up his
+nose at his finery and the shabbier and shabbier his own outfit seemed
+to him to grow. Neither boy spoke. If one moved, the other moved--but
+only sidewise, in a circle; they kept face to face and eye to eye all
+the time. Finally Tom said:
+
+"I can lick you!"
+
+"I'd like to see you try it."
+
+"Well, I can do it."
+
+"No you can't, either."
+
+"Yes I can."
+
+"No you can't."
+
+"I can."
+
+"You can't."
+
+"Can!"
+
+"Can't!"
+
+An uncomfortable pause. Then Tom said:
+
+"What's your name?"
+
+"'Tisn't any of your business, maybe."
+
+"Well I 'low I'll MAKE it my business."
+
+"Well why don't you?"
+
+"If you say much, I will."
+
+"Much--much--MUCH. There now."
+
+"Oh, you think you're mighty smart, DON'T you? I could lick you with
+one hand tied behind me, if I wanted to."
+
+"Well why don't you DO it? You SAY you can do it."
+
+"Well I WILL, if you fool with me."
+
+"Oh yes--I've seen whole families in the same fix."
+
+"Smarty! You think you're SOME, now, DON'T you? Oh, what a hat!"
+
+"You can lump that hat if you don't like it. I dare you to knock it
+off--and anybody that'll take a dare will suck eggs."
+
+"You're a liar!"
+
+"You're another."
+
+"You're a fighting liar and dasn't take it up."
+
+"Aw--take a walk!"
+
+"Say--if you give me much more of your sass I'll take and bounce a
+rock off'n your head."
+
+"Oh, of COURSE you will."
+
+"Well I WILL."
+
+"Well why don't you DO it then? What do you keep SAYING you will for?
+Why don't you DO it? It's because you're afraid."
+
+"I AIN'T afraid."
+
+"You are."
+
+"I ain't."
+
+"You are."
+
+Another pause, and more eying and sidling around each other. Presently
+they were shoulder to shoulder. Tom said:
+
+"Get away from here!"
+
+"Go away yourself!"
+
+"I won't."
+
+"I won't either."
+
+So they stood, each with a foot placed at an angle as a brace, and
+both shoving with might and main, and glowering at each other with
+hate. But neither could get an advantage. After struggling till both
+were hot and flushed, each relaxed his strain with watchful caution,
+and Tom said:
+
+"You're a coward and a pup. I'll tell my big brother on you, and he
+can thrash you with his little finger, and I'll make him do it, too."
+
+"What do I care for your big brother? I've got a brother that's bigger
+than he is--and what's more, he can throw him over that fence, too."
+[Both brothers were imaginary.]
+
+"That's a lie."
+
+"YOUR saying so don't make it so."
+
+Tom drew a line in the dust with his big toe, and said:
+
+"I dare you to step over that, and I'll lick you till you can't stand
+up. Anybody that'll take a dare will steal sheep."
+
+The new boy stepped over promptly, and said:
+
+"Now you said you'd do it, now let's see you do it."
+
+"Don't you crowd me now; you better look out."
+
+"Well, you SAID you'd do it--why don't you do it?"
+
+"By jingo! for two cents I WILL do it."
+
+The new boy took two broad coppers out of his pocket and held them out
+with derision. Tom struck them to the ground. In an instant both boys
+were rolling and tumbling in the dirt, gripped together like cats; and
+for the space of a minute they tugged and tore at each other's hair and
+clothes, punched and scratched each other's nose, and covered
+themselves with dust and glory. Presently the confusion took form, and
+through the fog of battle Tom appeared, seated astride the new boy, and
+pounding him with his fists. "Holler 'nuff!" said he.
+
+The boy only struggled to free himself. He was crying--mainly from rage.
+
+"Holler 'nuff!"--and the pounding went on.
+
+At last the stranger got out a smothered "'Nuff!" and Tom let him up
+and said:
+
+"Now that'll learn you. Better look out who you're fooling with next
+time."
+
+The new boy went off brushing the dust from his clothes, sobbing,
+snuffling, and occasionally looking back and shaking his head and
+threatening what he would do to Tom the "next time he caught him out."
+To which Tom responded with jeers, and started off in high feather, and
+as soon as his back was turned the new boy snatched up a stone, threw
+it and hit him between the shoulders and then turned tail and ran like
+an antelope. Tom chased the traitor home, and thus found out where he
+lived. He then held a position at the gate for some time, daring the
+enemy to come outside, but the enemy only made faces at him through the
+window and declined. At last the enemy's mother appeared, and called
+Tom a bad, vicious, vulgar child, and ordered him away. So he went
+away; but he said he "'lowed" to "lay" for that boy.
+
+He got home pretty late that night, and when he climbed cautiously in
+at the window, he uncovered an ambuscade, in the person of his aunt;
+and when she saw the state his clothes were in her resolution to turn
+his Saturday holiday into captivity at hard labor became adamantine in
+its firmness.
+
+
+
+CHAPTER II
+
+SATURDAY morning was come, and all the summer world was bright and
+fresh, and brimming with life. There was a song in every heart; and if
+the heart was young the music issued at the lips. There was cheer in
+every face and a spring in every step. The locust-trees were in bloom
+and the fragrance of the blossoms filled the air. Cardiff Hill, beyond
+the village and above it, was green with vegetation and it lay just far
+enough away to seem a Delectable Land, dreamy, reposeful, and inviting.
+
+Tom appeared on the sidewalk with a bucket of whitewash and a
+long-handled brush. He surveyed the fence, and all gladness left him and
+a deep melancholy settled down upon his spirit. Thirty yards of board
+fence nine feet high. Life to him seemed hollow, and existence but a
+burden. Sighing, he dipped his brush and passed it along the topmost
+plank; repeated the operation; did it again; compared the insignificant
+whitewashed streak with the far-reaching continent of unwhitewashed
+fence, and sat down on a tree-box discouraged. Jim came skipping out at
+the gate with a tin pail, and singing Buffalo Gals. Bringing water from
+the town pump had always been hateful work in Tom's eyes, before, but
+now it did not strike him so. He remembered that there was company at
+the pump. White, mulatto, and negro boys and girls were always there
+waiting their turns, resting, trading playthings, quarrelling,
+fighting, skylarking. And he remembered that although the pump was only
+a hundred and fifty yards off, Jim never got back with a bucket of
+water under an hour--and even then somebody generally had to go after
+him. Tom said:
+
+"Say, Jim, I'll fetch the water if you'll whitewash some."
+
+Jim shook his head and said:
+
+"Can't, Mars Tom. Ole missis, she tole me I got to go an' git dis
+water an' not stop foolin' roun' wid anybody. She say she spec' Mars
+Tom gwine to ax me to whitewash, an' so she tole me go 'long an' 'tend
+to my own business--she 'lowed SHE'D 'tend to de whitewashin'."
+
+"Oh, never you mind what she said, Jim. That's the way she always
+talks. Gimme the bucket--I won't be gone only a a minute. SHE won't
+ever know."
+
+"Oh, I dasn't, Mars Tom. Ole missis she'd take an' tar de head off'n
+me. 'Deed she would."
+
+"SHE! She never licks anybody--whacks 'em over the head with her
+thimble--and who cares for that, I'd like to know. She talks awful, but
+talk don't hurt--anyways it don't if she don't cry. Jim, I'll give you
+a marvel. I'll give you a white alley!"
+
+Jim began to waver.
+
+"White alley, Jim! And it's a bully taw."
+
+"My! Dat's a mighty gay marvel, I tell you! But Mars Tom I's powerful
+'fraid ole missis--"
+
+"And besides, if you will I'll show you my sore toe."
+
+Jim was only human--this attraction was too much for him. He put down
+his pail, took the white alley, and bent over the toe with absorbing
+interest while the bandage was being unwound. In another moment he was
+flying down the street with his pail and a tingling rear, Tom was
+whitewashing with vigor, and Aunt Polly was retiring from the field
+with a slipper in her hand and triumph in her eye.
+
+But Tom's energy did not last. He began to think of the fun he had
+planned for this day, and his sorrows multiplied. Soon the free boys
+would come tripping along on all sorts of delicious expeditions, and
+they would make a world of fun of him for having to work--the very
+thought of it burnt him like fire. He got out his worldly wealth and
+examined it--bits of toys, marbles, and trash; enough to buy an
+exchange of WORK, maybe, but not half enough to buy so much as half an
+hour of pure freedom. So he returned his straitened means to his
+pocket, and gave up the idea of trying to buy the boys. At this dark
+and hopeless moment an inspiration burst upon him! Nothing less than a
+great, magnificent inspiration.
+
+He took up his brush and went tranquilly to work. Ben Rogers hove in
+sight presently--the very boy, of all boys, whose ridicule he had been
+dreading. Ben's gait was the hop-skip-and-jump--proof enough that his
+heart was light and his anticipations high. He was eating an apple, and
+giving a long, melodious whoop, at intervals, followed by a deep-toned
+ding-dong-dong, ding-dong-dong, for he was personating a steamboat. As
+he drew near, he slackened speed, took the middle of the street, leaned
+far over to starboard and rounded to ponderously and with laborious
+pomp and circumstance--for he was personating the Big Missouri, and
+considered himself to be drawing nine feet of water. He was boat and
+captain and engine-bells combined, so he had to imagine himself
+standing on his own hurricane-deck giving the orders and executing them:
+
+"Stop her, sir! Ting-a-ling-ling!" The headway ran almost out, and he
+drew up slowly toward the sidewalk.
+
+"Ship up to back! Ting-a-ling-ling!" His arms straightened and
+stiffened down his sides.
+
+"Set her back on the stabboard! Ting-a-ling-ling! Chow! ch-chow-wow!
+Chow!" His right hand, meantime, describing stately circles--for it was
+representing a forty-foot wheel.
+
+"Let her go back on the labboard! Ting-a-lingling! Chow-ch-chow-chow!"
+The left hand began to describe circles.
+
+"Stop the stabboard! Ting-a-ling-ling! Stop the labboard! Come ahead
+on the stabboard! Stop her! Let your outside turn over slow!
+Ting-a-ling-ling! Chow-ow-ow! Get out that head-line! LIVELY now!
+Come--out with your spring-line--what're you about there! Take a turn
+round that stump with the bight of it! Stand by that stage, now--let her
+go! Done with the engines, sir! Ting-a-ling-ling! SH'T! S'H'T! SH'T!"
+(trying the gauge-cocks).
+
+Tom went on whitewashing--paid no attention to the steamboat. Ben
+stared a moment and then said: "Hi-YI! YOU'RE up a stump, ain't you!"
+
+No answer. Tom surveyed his last touch with the eye of an artist, then
+he gave his brush another gentle sweep and surveyed the result, as
+before. Ben ranged up alongside of him. Tom's mouth watered for the
+apple, but he stuck to his work. Ben said:
+
+"Hello, old chap, you got to work, hey?"
+
+Tom wheeled suddenly and said:
+
+"Why, it's you, Ben! I warn't noticing."
+
+"Say--I'm going in a-swimming, I am. Don't you wish you could? But of
+course you'd druther WORK--wouldn't you? Course you would!"
+
+Tom contemplated the boy a bit, and said:
+
+"What do you call work?"
+
+"Why, ain't THAT work?"
+
+Tom resumed his whitewashing, and answered carelessly:
+
+"Well, maybe it is, and maybe it ain't. All I know, is, it suits Tom
+Sawyer."
+
+"Oh come, now, you don't mean to let on that you LIKE it?"
+
+The brush continued to move.
+
+"Like it? Well, I don't see why I oughtn't to like it. Does a boy get
+a chance to whitewash a fence every day?"
+
+That put the thing in a new light. Ben stopped nibbling his apple. Tom
+swept his brush daintily back and forth--stepped back to note the
+effect--added a touch here and there--criticised the effect again--Ben
+watching every move and getting more and more interested, more and more
+absorbed. Presently he said:
+
+"Say, Tom, let ME whitewash a little."
+
+Tom considered, was about to consent; but he altered his mind:
+
+"No--no--I reckon it wouldn't hardly do, Ben. You see, Aunt Polly's
+awful particular about this fence--right here on the street, you know
+--but if it was the back fence I wouldn't mind and SHE wouldn't. Yes,
+she's awful particular about this fence; it's got to be done very
+careful; I reckon there ain't one boy in a thousand, maybe two
+thousand, that can do it the way it's got to be done."
+
+"No--is that so? Oh come, now--lemme just try. Only just a little--I'd
+let YOU, if you was me, Tom."
+
+"Ben, I'd like to, honest injun; but Aunt Polly--well, Jim wanted to
+do it, but she wouldn't let him; Sid wanted to do it, and she wouldn't
+let Sid. Now don't you see how I'm fixed? If you was to tackle this
+fence and anything was to happen to it--"
+
+"Oh, shucks, I'll be just as careful. Now lemme try. Say--I'll give
+you the core of my apple."
+
+"Well, here--No, Ben, now don't. I'm afeard--"
+
+"I'll give you ALL of it!"
+
+Tom gave up the brush with reluctance in his face, but alacrity in his
+heart. And while the late steamer Big Missouri worked and sweated in
+the sun, the retired artist sat on a barrel in the shade close by,
+dangled his legs, munched his apple, and planned the slaughter of more
+innocents. There was no lack of material; boys happened along every
+little while; they came to jeer, but remained to whitewash. By the time
+Ben was fagged out, Tom had traded the next chance to Billy Fisher for
+a kite, in good repair; and when he played out, Johnny Miller bought in
+for a dead rat and a string to swing it with--and so on, and so on,
+hour after hour. And when the middle of the afternoon came, from being
+a poor poverty-stricken boy in the morning, Tom was literally rolling
+in wealth. He had besides the things before mentioned, twelve marbles,
+part of a jews-harp, a piece of blue bottle-glass to look through, a
+spool cannon, a key that wouldn't unlock anything, a fragment of chalk,
+a glass stopper of a decanter, a tin soldier, a couple of tadpoles, six
+fire-crackers, a kitten with only one eye, a brass doorknob, a
+dog-collar--but no dog--the handle of a knife, four pieces of
+orange-peel, and a dilapidated old window sash.
+
+He had had a nice, good, idle time all the while--plenty of company
+--and the fence had three coats of whitewash on it! If he hadn't run out
+of whitewash he would have bankrupted every boy in the village.
+
+Tom said to himself that it was not such a hollow world, after all. He
+had discovered a great law of human action, without knowing it--namely,
+that in order to make a man or a boy covet a thing, it is only
+necessary to make the thing difficult to attain. If he had been a great
+and wise philosopher, like the writer of this book, he would now have
+comprehended that Work consists of whatever a body is OBLIGED to do,
+and that Play consists of whatever a body is not obliged to do. And
+this would help him to understand why constructing artificial flowers
+or performing on a tread-mill is work, while rolling ten-pins or
+climbing Mont Blanc is only amusement. There are wealthy gentlemen in
+England who drive four-horse passenger-coaches twenty or thirty miles
+on a daily line, in the summer, because the privilege costs them
+considerable money; but if they were offered wages for the service,
+that would turn it into work and then they would resign.
+
+The boy mused awhile over the substantial change which had taken place
+in his worldly circumstances, and then wended toward headquarters to
+report.
+
+
+
+CHAPTER III
+
+TOM presented himself before Aunt Polly, who was sitting by an open
+window in a pleasant rearward apartment, which was bedroom,
+breakfast-room, dining-room, and library, combined. The balmy summer
+air, the restful quiet, the odor of the flowers, and the drowsing murmur
+of the bees had had their effect, and she was nodding over her knitting
+--for she had no company but the cat, and it was asleep in her lap. Her
+spectacles were propped up on her gray head for safety. She had thought
+that of course Tom had deserted long ago, and she wondered at seeing him
+place himself in her power again in this intrepid way. He said: "Mayn't
+I go and play now, aunt?"
+
+"What, a'ready? How much have you done?"
+
+"It's all done, aunt."
+
+"Tom, don't lie to me--I can't bear it."
+
+"I ain't, aunt; it IS all done."
+
+Aunt Polly placed small trust in such evidence. She went out to see
+for herself; and she would have been content to find twenty per cent.
+of Tom's statement true. When she found the entire fence whitewashed,
+and not only whitewashed but elaborately coated and recoated, and even
+a streak added to the ground, her astonishment was almost unspeakable.
+She said:
+
+"Well, I never! There's no getting round it, you can work when you're
+a mind to, Tom." And then she diluted the compliment by adding, "But
+it's powerful seldom you're a mind to, I'm bound to say. Well, go 'long
+and play; but mind you get back some time in a week, or I'll tan you."
+
+She was so overcome by the splendor of his achievement that she took
+him into the closet and selected a choice apple and delivered it to
+him, along with an improving lecture upon the added value and flavor a
+treat took to itself when it came without sin through virtuous effort.
+And while she closed with a happy Scriptural flourish, he "hooked" a
+doughnut.
+
+Then he skipped out, and saw Sid just starting up the outside stairway
+that led to the back rooms on the second floor. Clods were handy and
+the air was full of them in a twinkling. They raged around Sid like a
+hail-storm; and before Aunt Polly could collect her surprised faculties
+and sally to the rescue, six or seven clods had taken personal effect,
+and Tom was over the fence and gone. There was a gate, but as a general
+thing he was too crowded for time to make use of it. His soul was at
+peace, now that he had settled with Sid for calling attention to his
+black thread and getting him into trouble.
+
+Tom skirted the block, and came round into a muddy alley that led by
+the back of his aunt's cow-stable. He presently got safely beyond the
+reach of capture and punishment, and hastened toward the public square
+of the village, where two "military" companies of boys had met for
+conflict, according to previous appointment. Tom was General of one of
+these armies, Joe Harper (a bosom friend) General of the other. These
+two great commanders did not condescend to fight in person--that being
+better suited to the still smaller fry--but sat together on an eminence
+and conducted the field operations by orders delivered through
+aides-de-camp. Tom's army won a great victory, after a long and
+hard-fought battle. Then the dead were counted, prisoners exchanged,
+the terms of the next disagreement agreed upon, and the day for the
+necessary battle appointed; after which the armies fell into line and
+marched away, and Tom turned homeward alone.
+
+As he was passing by the house where Jeff Thatcher lived, he saw a new
+girl in the garden--a lovely little blue-eyed creature with yellow hair
+plaited into two long-tails, white summer frock and embroidered
+pantalettes. The fresh-crowned hero fell without firing a shot. A
+certain Amy Lawrence vanished out of his heart and left not even a
+memory of herself behind. He had thought he loved her to distraction;
+he had regarded his passion as adoration; and behold it was only a poor
+little evanescent partiality. He had been months winning her; she had
+confessed hardly a week ago; he had been the happiest and the proudest
+boy in the world only seven short days, and here in one instant of time
+she had gone out of his heart like a casual stranger whose visit is
+done.
+
+He worshipped this new angel with furtive eye, till he saw that she
+had discovered him; then he pretended he did not know she was present,
+and began to "show off" in all sorts of absurd boyish ways, in order to
+win her admiration. He kept up this grotesque foolishness for some
+time; but by-and-by, while he was in the midst of some dangerous
+gymnastic performances, he glanced aside and saw that the little girl
+was wending her way toward the house. Tom came up to the fence and
+leaned on it, grieving, and hoping she would tarry yet awhile longer.
+She halted a moment on the steps and then moved toward the door. Tom
+heaved a great sigh as she put her foot on the threshold. But his face
+lit up, right away, for she tossed a pansy over the fence a moment
+before she disappeared.
+
+The boy ran around and stopped within a foot or two of the flower, and
+then shaded his eyes with his hand and began to look down street as if
+he had discovered something of interest going on in that direction.
+Presently he picked up a straw and began trying to balance it on his
+nose, with his head tilted far back; and as he moved from side to side,
+in his efforts, he edged nearer and nearer toward the pansy; finally
+his bare foot rested upon it, his pliant toes closed upon it, and he
+hopped away with the treasure and disappeared round the corner. But
+only for a minute--only while he could button the flower inside his
+jacket, next his heart--or next his stomach, possibly, for he was not
+much posted in anatomy, and not hypercritical, anyway.
+
+He returned, now, and hung about the fence till nightfall, "showing
+off," as before; but the girl never exhibited herself again, though Tom
+comforted himself a little with the hope that she had been near some
+window, meantime, and been aware of his attentions. Finally he strode
+home reluctantly, with his poor head full of visions.
+
+All through supper his spirits were so high that his aunt wondered
+"what had got into the child." He took a good scolding about clodding
+Sid, and did not seem to mind it in the least. He tried to steal sugar
+under his aunt's very nose, and got his knuckles rapped for it. He said:
+
+"Aunt, you don't whack Sid when he takes it."
+
+"Well, Sid don't torment a body the way you do. You'd be always into
+that sugar if I warn't watching you."
+
+Presently she stepped into the kitchen, and Sid, happy in his
+immunity, reached for the sugar-bowl--a sort of glorying over Tom which
+was wellnigh unbearable. But Sid's fingers slipped and the bowl dropped
+and broke. Tom was in ecstasies. In such ecstasies that he even
+controlled his tongue and was silent. He said to himself that he would
+not speak a word, even when his aunt came in, but would sit perfectly
+still till she asked who did the mischief; and then he would tell, and
+there would be nothing so good in the world as to see that pet model
+"catch it." He was so brimful of exultation that he could hardly hold
+himself when the old lady came back and stood above the wreck
+discharging lightnings of wrath from over her spectacles. He said to
+himself, "Now it's coming!" And the next instant he was sprawling on
+the floor! The potent palm was uplifted to strike again when Tom cried
+out:
+
+"Hold on, now, what 'er you belting ME for?--Sid broke it!"
+
+Aunt Polly paused, perplexed, and Tom looked for healing pity. But
+when she got her tongue again, she only said:
+
+"Umf! Well, you didn't get a lick amiss, I reckon. You been into some
+other audacious mischief when I wasn't around, like enough."
+
+Then her conscience reproached her, and she yearned to say something
+kind and loving; but she judged that this would be construed into a
+confession that she had been in the wrong, and discipline forbade that.
+So she kept silence, and went about her affairs with a troubled heart.
+Tom sulked in a corner and exalted his woes. He knew that in her heart
+his aunt was on her knees to him, and he was morosely gratified by the
+consciousness of it. He would hang out no signals, he would take notice
+of none. He knew that a yearning glance fell upon him, now and then,
+through a film of tears, but he refused recognition of it. He pictured
+himself lying sick unto death and his aunt bending over him beseeching
+one little forgiving word, but he would turn his face to the wall, and
+die with that word unsaid. Ah, how would she feel then? And he pictured
+himself brought home from the river, dead, with his curls all wet, and
+his sore heart at rest. How she would throw herself upon him, and how
+her tears would fall like rain, and her lips pray God to give her back
+her boy and she would never, never abuse him any more! But he would lie
+there cold and white and make no sign--a poor little sufferer, whose
+griefs were at an end. He so worked upon his feelings with the pathos
+of these dreams, that he had to keep swallowing, he was so like to
+choke; and his eyes swam in a blur of water, which overflowed when he
+winked, and ran down and trickled from the end of his nose. And such a
+luxury to him was this petting of his sorrows, that he could not bear
+to have any worldly cheeriness or any grating delight intrude upon it;
+it was too sacred for such contact; and so, presently, when his cousin
+Mary danced in, all alive with the joy of seeing home again after an
+age-long visit of one week to the country, he got up and moved in
+clouds and darkness out at one door as she brought song and sunshine in
+at the other.
+
+He wandered far from the accustomed haunts of boys, and sought
+desolate places that were in harmony with his spirit. A log raft in the
+river invited him, and he seated himself on its outer edge and
+contemplated the dreary vastness of the stream, wishing, the while,
+that he could only be drowned, all at once and unconsciously, without
+undergoing the uncomfortable routine devised by nature. Then he thought
+of his flower. He got it out, rumpled and wilted, and it mightily
+increased his dismal felicity. He wondered if she would pity him if she
+knew? Would she cry, and wish that she had a right to put her arms
+around his neck and comfort him? Or would she turn coldly away like all
+the hollow world? This picture brought such an agony of pleasurable
+suffering that he worked it over and over again in his mind and set it
+up in new and varied lights, till he wore it threadbare. At last he
+rose up sighing and departed in the darkness.
+
+About half-past nine or ten o'clock he came along the deserted street
+to where the Adored Unknown lived; he paused a moment; no sound fell
+upon his listening ear; a candle was casting a dull glow upon the
+curtain of a second-story window. Was the sacred presence there? He
+climbed the fence, threaded his stealthy way through the plants, till
+he stood under that window; he looked up at it long, and with emotion;
+then he laid him down on the ground under it, disposing himself upon
+his back, with his hands clasped upon his breast and holding his poor
+wilted flower. And thus he would die--out in the cold world, with no
+shelter over his homeless head, no friendly hand to wipe the
+death-damps from his brow, no loving face to bend pityingly over him
+when the great agony came. And thus SHE would see him when she looked
+out upon the glad morning, and oh! would she drop one little tear upon
+his poor, lifeless form, would she heave one little sigh to see a bright
+young life so rudely blighted, so untimely cut down?
+
+The window went up, a maid-servant's discordant voice profaned the
+holy calm, and a deluge of water drenched the prone martyr's remains!
+
+The strangling hero sprang up with a relieving snort. There was a whiz
+as of a missile in the air, mingled with the murmur of a curse, a sound
+as of shivering glass followed, and a small, vague form went over the
+fence and shot away in the gloom.
+
+Not long after, as Tom, all undressed for bed, was surveying his
+drenched garments by the light of a tallow dip, Sid woke up; but if he
+had any dim idea of making any "references to allusions," he thought
+better of it and held his peace, for there was danger in Tom's eye.
+
+Tom turned in without the added vexation of prayers, and Sid made
+mental note of the omission.
+
+
+
+CHAPTER IV
+
+THE sun rose upon a tranquil world, and beamed down upon the peaceful
+village like a benediction. Breakfast over, Aunt Polly had family
+worship: it began with a prayer built from the ground up of solid
+courses of Scriptural quotations, welded together with a thin mortar of
+originality; and from the summit of this she delivered a grim chapter
+of the Mosaic Law, as from Sinai.
+
+Then Tom girded up his loins, so to speak, and went to work to "get
+his verses." Sid had learned his lesson days before. Tom bent all his
+energies to the memorizing of five verses, and he chose part of the
+Sermon on the Mount, because he could find no verses that were shorter.
+At the end of half an hour Tom had a vague general idea of his lesson,
+but no more, for his mind was traversing the whole field of human
+thought, and his hands were busy with distracting recreations. Mary
+took his book to hear him recite, and he tried to find his way through
+the fog:
+
+"Blessed are the--a--a--"
+
+"Poor"--
+
+"Yes--poor; blessed are the poor--a--a--"
+
+"In spirit--"
+
+"In spirit; blessed are the poor in spirit, for they--they--"
+
+"THEIRS--"
+
+"For THEIRS. Blessed are the poor in spirit, for theirs is the kingdom
+of heaven. Blessed are they that mourn, for they--they--"
+
+"Sh--"
+
+"For they--a--"
+
+"S, H, A--"
+
+"For they S, H--Oh, I don't know what it is!"
+
+"SHALL!"
+
+"Oh, SHALL! for they shall--for they shall--a--a--shall mourn--a--a--
+blessed are they that shall--they that--a--they that shall mourn, for
+they shall--a--shall WHAT? Why don't you tell me, Mary?--what do you
+want to be so mean for?"
+
+"Oh, Tom, you poor thick-headed thing, I'm not teasing you. I wouldn't
+do that. You must go and learn it again. Don't you be discouraged, Tom,
+you'll manage it--and if you do, I'll give you something ever so nice.
+There, now, that's a good boy."
+
+"All right! What is it, Mary, tell me what it is."
+
+"Never you mind, Tom. You know if I say it's nice, it is nice."
+
+"You bet you that's so, Mary. All right, I'll tackle it again."
+
+And he did "tackle it again"--and under the double pressure of
+curiosity and prospective gain he did it with such spirit that he
+accomplished a shining success. Mary gave him a brand-new "Barlow"
+knife worth twelve and a half cents; and the convulsion of delight that
+swept his system shook him to his foundations. True, the knife would
+not cut anything, but it was a "sure-enough" Barlow, and there was
+inconceivable grandeur in that--though where the Western boys ever got
+the idea that such a weapon could possibly be counterfeited to its
+injury is an imposing mystery and will always remain so, perhaps. Tom
+contrived to scarify the cupboard with it, and was arranging to begin
+on the bureau, when he was called off to dress for Sunday-school.
+
+Mary gave him a tin basin of water and a piece of soap, and he went
+outside the door and set the basin on a little bench there; then he
+dipped the soap in the water and laid it down; turned up his sleeves;
+poured out the water on the ground, gently, and then entered the
+kitchen and began to wipe his face diligently on the towel behind the
+door. But Mary removed the towel and said:
+
+"Now ain't you ashamed, Tom. You mustn't be so bad. Water won't hurt
+you."
+
+Tom was a trifle disconcerted. The basin was refilled, and this time
+he stood over it a little while, gathering resolution; took in a big
+breath and began. When he entered the kitchen presently, with both eyes
+shut and groping for the towel with his hands, an honorable testimony
+of suds and water was dripping from his face. But when he emerged from
+the towel, he was not yet satisfactory, for the clean territory stopped
+short at his chin and his jaws, like a mask; below and beyond this line
+there was a dark expanse of unirrigated soil that spread downward in
+front and backward around his neck. Mary took him in hand, and when she
+was done with him he was a man and a brother, without distinction of
+color, and his saturated hair was neatly brushed, and its short curls
+wrought into a dainty and symmetrical general effect. [He privately
+smoothed out the curls, with labor and difficulty, and plastered his
+hair close down to his head; for he held curls to be effeminate, and
+his own filled his life with bitterness.] Then Mary got out a suit of
+his clothing that had been used only on Sundays during two years--they
+were simply called his "other clothes"--and so by that we know the
+size of his wardrobe. The girl "put him to rights" after he had dressed
+himself; she buttoned his neat roundabout up to his chin, turned his
+vast shirt collar down over his shoulders, brushed him off and crowned
+him with his speckled straw hat. He now looked exceedingly improved and
+uncomfortable. He was fully as uncomfortable as he looked; for there
+was a restraint about whole clothes and cleanliness that galled him. He
+hoped that Mary would forget his shoes, but the hope was blighted; she
+coated them thoroughly with tallow, as was the custom, and brought them
+out. He lost his temper and said he was always being made to do
+everything he didn't want to do. But Mary said, persuasively:
+
+"Please, Tom--that's a good boy."
+
+So he got into the shoes snarling. Mary was soon ready, and the three
+children set out for Sunday-school--a place that Tom hated with his
+whole heart; but Sid and Mary were fond of it.
+
+Sabbath-school hours were from nine to half-past ten; and then church
+service. Two of the children always remained for the sermon
+voluntarily, and the other always remained too--for stronger reasons.
+The church's high-backed, uncushioned pews would seat about three
+hundred persons; the edifice was but a small, plain affair, with a sort
+of pine board tree-box on top of it for a steeple. At the door Tom
+dropped back a step and accosted a Sunday-dressed comrade:
+
+"Say, Billy, got a yaller ticket?"
+
+"Yes."
+
+"What'll you take for her?"
+
+"What'll you give?"
+
+"Piece of lickrish and a fish-hook."
+
+"Less see 'em."
+
+Tom exhibited. They were satisfactory, and the property changed hands.
+Then Tom traded a couple of white alleys for three red tickets, and
+some small trifle or other for a couple of blue ones. He waylaid other
+boys as they came, and went on buying tickets of various colors ten or
+fifteen minutes longer. He entered the church, now, with a swarm of
+clean and noisy boys and girls, proceeded to his seat and started a
+quarrel with the first boy that came handy. The teacher, a grave,
+elderly man, interfered; then turned his back a moment and Tom pulled a
+boy's hair in the next bench, and was absorbed in his book when the boy
+turned around; stuck a pin in another boy, presently, in order to hear
+him say "Ouch!" and got a new reprimand from his teacher. Tom's whole
+class were of a pattern--restless, noisy, and troublesome. When they
+came to recite their lessons, not one of them knew his verses
+perfectly, but had to be prompted all along. However, they worried
+through, and each got his reward--in small blue tickets, each with a
+passage of Scripture on it; each blue ticket was pay for two verses of
+the recitation. Ten blue tickets equalled a red one, and could be
+exchanged for it; ten red tickets equalled a yellow one; for ten yellow
+tickets the superintendent gave a very plainly bound Bible (worth forty
+cents in those easy times) to the pupil. How many of my readers would
+have the industry and application to memorize two thousand verses, even
+for a Dore Bible? And yet Mary had acquired two Bibles in this way--it
+was the patient work of two years--and a boy of German parentage had
+won four or five. He once recited three thousand verses without
+stopping; but the strain upon his mental faculties was too great, and
+he was little better than an idiot from that day forth--a grievous
+misfortune for the school, for on great occasions, before company, the
+superintendent (as Tom expressed it) had always made this boy come out
+and "spread himself." Only the older pupils managed to keep their
+tickets and stick to their tedious work long enough to get a Bible, and
+so the delivery of one of these prizes was a rare and noteworthy
+circumstance; the successful pupil was so great and conspicuous for
+that day that on the spot every scholar's heart was fired with a fresh
+ambition that often lasted a couple of weeks. It is possible that Tom's
+mental stomach had never really hungered for one of those prizes, but
+unquestionably his entire being had for many a day longed for the glory
+and the eclat that came with it.
+
+In due course the superintendent stood up in front of the pulpit, with
+a closed hymn-book in his hand and his forefinger inserted between its
+leaves, and commanded attention. When a Sunday-school superintendent
+makes his customary little speech, a hymn-book in the hand is as
+necessary as is the inevitable sheet of music in the hand of a singer
+who stands forward on the platform and sings a solo at a concert
+--though why, is a mystery: for neither the hymn-book nor the sheet of
+music is ever referred to by the sufferer. This superintendent was a
+slim creature of thirty-five, with a sandy goatee and short sandy hair;
+he wore a stiff standing-collar whose upper edge almost reached his
+ears and whose sharp points curved forward abreast the corners of his
+mouth--a fence that compelled a straight lookout ahead, and a turning
+of the whole body when a side view was required; his chin was propped
+on a spreading cravat which was as broad and as long as a bank-note,
+and had fringed ends; his boot toes were turned sharply up, in the
+fashion of the day, like sleigh-runners--an effect patiently and
+laboriously produced by the young men by sitting with their toes
+pressed against a wall for hours together. Mr. Walters was very earnest
+of mien, and very sincere and honest at heart; and he held sacred
+things and places in such reverence, and so separated them from worldly
+matters, that unconsciously to himself his Sunday-school voice had
+acquired a peculiar intonation which was wholly absent on week-days. He
+began after this fashion:
+
+"Now, children, I want you all to sit up just as straight and pretty
+as you can and give me all your attention for a minute or two. There
+--that is it. That is the way good little boys and girls should do. I see
+one little girl who is looking out of the window--I am afraid she
+thinks I am out there somewhere--perhaps up in one of the trees making
+a speech to the little birds. [Applausive titter.] I want to tell you
+how good it makes me feel to see so many bright, clean little faces
+assembled in a place like this, learning to do right and be good." And
+so forth and so on. It is not necessary to set down the rest of the
+oration. It was of a pattern which does not vary, and so it is familiar
+to us all.
+
+The latter third of the speech was marred by the resumption of fights
+and other recreations among certain of the bad boys, and by fidgetings
+and whisperings that extended far and wide, washing even to the bases
+of isolated and incorruptible rocks like Sid and Mary. But now every
+sound ceased suddenly, with the subsidence of Mr. Walters' voice, and
+the conclusion of the speech was received with a burst of silent
+gratitude.
+
+A good part of the whispering had been occasioned by an event which
+was more or less rare--the entrance of visitors: lawyer Thatcher,
+accompanied by a very feeble and aged man; a fine, portly, middle-aged
+gentleman with iron-gray hair; and a dignified lady who was doubtless
+the latter's wife. The lady was leading a child. Tom had been restless
+and full of chafings and repinings; conscience-smitten, too--he could
+not meet Amy Lawrence's eye, he could not brook her loving gaze. But
+when he saw this small new-comer his soul was all ablaze with bliss in
+a moment. The next moment he was "showing off" with all his might
+--cuffing boys, pulling hair, making faces--in a word, using every art
+that seemed likely to fascinate a girl and win her applause. His
+exaltation had but one alloy--the memory of his humiliation in this
+angel's garden--and that record in sand was fast washing out, under
+the waves of happiness that were sweeping over it now.
+
+The visitors were given the highest seat of honor, and as soon as Mr.
+Walters' speech was finished, he introduced them to the school. The
+middle-aged man turned out to be a prodigious personage--no less a one
+than the county judge--altogether the most august creation these
+children had ever looked upon--and they wondered what kind of material
+he was made of--and they half wanted to hear him roar, and were half
+afraid he might, too. He was from Constantinople, twelve miles away--so
+he had travelled, and seen the world--these very eyes had looked upon
+the county court-house--which was said to have a tin roof. The awe
+which these reflections inspired was attested by the impressive silence
+and the ranks of staring eyes. This was the great Judge Thatcher,
+brother of their own lawyer. Jeff Thatcher immediately went forward, to
+be familiar with the great man and be envied by the school. It would
+have been music to his soul to hear the whisperings:
+
+"Look at him, Jim! He's a going up there. Say--look! he's a going to
+shake hands with him--he IS shaking hands with him! By jings, don't you
+wish you was Jeff?"
+
+Mr. Walters fell to "showing off," with all sorts of official
+bustlings and activities, giving orders, delivering judgments,
+discharging directions here, there, everywhere that he could find a
+target. The librarian "showed off"--running hither and thither with his
+arms full of books and making a deal of the splutter and fuss that
+insect authority delights in. The young lady teachers "showed off"
+--bending sweetly over pupils that were lately being boxed, lifting
+pretty warning fingers at bad little boys and patting good ones
+lovingly. The young gentlemen teachers "showed off" with small
+scoldings and other little displays of authority and fine attention to
+discipline--and most of the teachers, of both sexes, found business up
+at the library, by the pulpit; and it was business that frequently had
+to be done over again two or three times (with much seeming vexation).
+The little girls "showed off" in various ways, and the little boys
+"showed off" with such diligence that the air was thick with paper wads
+and the murmur of scufflings. And above it all the great man sat and
+beamed a majestic judicial smile upon all the house, and warmed himself
+in the sun of his own grandeur--for he was "showing off," too.
+
+There was only one thing wanting to make Mr. Walters' ecstasy
+complete, and that was a chance to deliver a Bible-prize and exhibit a
+prodigy. Several pupils had a few yellow tickets, but none had enough
+--he had been around among the star pupils inquiring. He would have given
+worlds, now, to have that German lad back again with a sound mind.
+
+And now at this moment, when hope was dead, Tom Sawyer came forward
+with nine yellow tickets, nine red tickets, and ten blue ones, and
+demanded a Bible. This was a thunderbolt out of a clear sky. Walters
+was not expecting an application from this source for the next ten
+years. But there was no getting around it--here were the certified
+checks, and they were good for their face. Tom was therefore elevated
+to a place with the Judge and the other elect, and the great news was
+announced from headquarters. It was the most stunning surprise of the
+decade, and so profound was the sensation that it lifted the new hero
+up to the judicial one's altitude, and the school had two marvels to
+gaze upon in place of one. The boys were all eaten up with envy--but
+those that suffered the bitterest pangs were those who perceived too
+late that they themselves had contributed to this hated splendor by
+trading tickets to Tom for the wealth he had amassed in selling
+whitewashing privileges. These despised themselves, as being the dupes
+of a wily fraud, a guileful snake in the grass.
+
+The prize was delivered to Tom with as much effusion as the
+superintendent could pump up under the circumstances; but it lacked
+somewhat of the true gush, for the poor fellow's instinct taught him
+that there was a mystery here that could not well bear the light,
+perhaps; it was simply preposterous that this boy had warehoused two
+thousand sheaves of Scriptural wisdom on his premises--a dozen would
+strain his capacity, without a doubt.
+
+Amy Lawrence was proud and glad, and she tried to make Tom see it in
+her face--but he wouldn't look. She wondered; then she was just a grain
+troubled; next a dim suspicion came and went--came again; she watched;
+a furtive glance told her worlds--and then her heart broke, and she was
+jealous, and angry, and the tears came and she hated everybody. Tom
+most of all (she thought).
+
+Tom was introduced to the Judge; but his tongue was tied, his breath
+would hardly come, his heart quaked--partly because of the awful
+greatness of the man, but mainly because he was her parent. He would
+have liked to fall down and worship him, if it were in the dark. The
+Judge put his hand on Tom's head and called him a fine little man, and
+asked him what his name was. The boy stammered, gasped, and got it out:
+
+"Tom."
+
+"Oh, no, not Tom--it is--"
+
+"Thomas."
+
+"Ah, that's it. I thought there was more to it, maybe. That's very
+well. But you've another one I daresay, and you'll tell it to me, won't
+you?"
+
+"Tell the gentleman your other name, Thomas," said Walters, "and say
+sir. You mustn't forget your manners."
+
+"Thomas Sawyer--sir."
+
+"That's it! That's a good boy. Fine boy. Fine, manly little fellow.
+Two thousand verses is a great many--very, very great many. And you
+never can be sorry for the trouble you took to learn them; for
+knowledge is worth more than anything there is in the world; it's what
+makes great men and good men; you'll be a great man and a good man
+yourself, some day, Thomas, and then you'll look back and say, It's all
+owing to the precious Sunday-school privileges of my boyhood--it's all
+owing to my dear teachers that taught me to learn--it's all owing to
+the good superintendent, who encouraged me, and watched over me, and
+gave me a beautiful Bible--a splendid elegant Bible--to keep and have
+it all for my own, always--it's all owing to right bringing up! That is
+what you will say, Thomas--and you wouldn't take any money for those
+two thousand verses--no indeed you wouldn't. And now you wouldn't mind
+telling me and this lady some of the things you've learned--no, I know
+you wouldn't--for we are proud of little boys that learn. Now, no
+doubt you know the names of all the twelve disciples. Won't you tell us
+the names of the first two that were appointed?"
+
+Tom was tugging at a button-hole and looking sheepish. He blushed,
+now, and his eyes fell. Mr. Walters' heart sank within him. He said to
+himself, it is not possible that the boy can answer the simplest
+question--why DID the Judge ask him? Yet he felt obliged to speak up
+and say:
+
+"Answer the gentleman, Thomas--don't be afraid."
+
+Tom still hung fire.
+
+"Now I know you'll tell me," said the lady. "The names of the first
+two disciples were--"
+
+"DAVID AND GOLIAH!"
+
+Let us draw the curtain of charity over the rest of the scene.
+
+
+
+CHAPTER V
+
+ABOUT half-past ten the cracked bell of the small church began to
+ring, and presently the people began to gather for the morning sermon.
+The Sunday-school children distributed themselves about the house and
+occupied pews with their parents, so as to be under supervision. Aunt
+Polly came, and Tom and Sid and Mary sat with her--Tom being placed
+next the aisle, in order that he might be as far away from the open
+window and the seductive outside summer scenes as possible. The crowd
+filed up the aisles: the aged and needy postmaster, who had seen better
+days; the mayor and his wife--for they had a mayor there, among other
+unnecessaries; the justice of the peace; the widow Douglass, fair,
+smart, and forty, a generous, good-hearted soul and well-to-do, her
+hill mansion the only palace in the town, and the most hospitable and
+much the most lavish in the matter of festivities that St. Petersburg
+could boast; the bent and venerable Major and Mrs. Ward; lawyer
+Riverson, the new notable from a distance; next the belle of the
+village, followed by a troop of lawn-clad and ribbon-decked young
+heart-breakers; then all the young clerks in town in a body--for they
+had stood in the vestibule sucking their cane-heads, a circling wall of
+oiled and simpering admirers, till the last girl had run their gantlet;
+and last of all came the Model Boy, Willie Mufferson, taking as heedful
+care of his mother as if she were cut glass. He always brought his
+mother to church, and was the pride of all the matrons. The boys all
+hated him, he was so good. And besides, he had been "thrown up to them"
+so much. His white handkerchief was hanging out of his pocket behind, as
+usual on Sundays--accidentally. Tom had no handkerchief, and he looked
+upon boys who had as snobs.
+
+The congregation being fully assembled, now, the bell rang once more,
+to warn laggards and stragglers, and then a solemn hush fell upon the
+church which was only broken by the tittering and whispering of the
+choir in the gallery. The choir always tittered and whispered all
+through service. There was once a church choir that was not ill-bred,
+but I have forgotten where it was, now. It was a great many years ago,
+and I can scarcely remember anything about it, but I think it was in
+some foreign country.
+
+The minister gave out the hymn, and read it through with a relish, in
+a peculiar style which was much admired in that part of the country.
+His voice began on a medium key and climbed steadily up till it reached
+a certain point, where it bore with strong emphasis upon the topmost
+word and then plunged down as if from a spring-board:
+
+  Shall I be car-ri-ed toe the skies, on flow'ry BEDS of ease,
+
+  Whilst others fight to win the prize, and sail thro' BLOODY seas?
+
+He was regarded as a wonderful reader. At church "sociables" he was
+always called upon to read poetry; and when he was through, the ladies
+would lift up their hands and let them fall helplessly in their laps,
+and "wall" their eyes, and shake their heads, as much as to say, "Words
+cannot express it; it is too beautiful, TOO beautiful for this mortal
+earth."
+
+After the hymn had been sung, the Rev. Mr. Sprague turned himself into
+a bulletin-board, and read off "notices" of meetings and societies and
+things till it seemed that the list would stretch out to the crack of
+doom--a queer custom which is still kept up in America, even in cities,
+away here in this age of abundant newspapers. Often, the less there is
+to justify a traditional custom, the harder it is to get rid of it.
+
+And now the minister prayed. A good, generous prayer it was, and went
+into details: it pleaded for the church, and the little children of the
+church; for the other churches of the village; for the village itself;
+for the county; for the State; for the State officers; for the United
+States; for the churches of the United States; for Congress; for the
+President; for the officers of the Government; for poor sailors, tossed
+by stormy seas; for the oppressed millions groaning under the heel of
+European monarchies and Oriental despotisms; for such as have the light
+and the good tidings, and yet have not eyes to see nor ears to hear
+withal; for the heathen in the far islands of the sea; and closed with
+a supplication that the words he was about to speak might find grace
+and favor, and be as seed sown in fertile ground, yielding in time a
+grateful harvest of good. Amen.
+
+There was a rustling of dresses, and the standing congregation sat
+down. The boy whose history this book relates did not enjoy the prayer,
+he only endured it--if he even did that much. He was restive all
+through it; he kept tally of the details of the prayer, unconsciously
+--for he was not listening, but he knew the ground of old, and the
+clergyman's regular route over it--and when a little trifle of new
+matter was interlarded, his ear detected it and his whole nature
+resented it; he considered additions unfair, and scoundrelly. In the
+midst of the prayer a fly had lit on the back of the pew in front of
+him and tortured his spirit by calmly rubbing its hands together,
+embracing its head with its arms, and polishing it so vigorously that
+it seemed to almost part company with the body, and the slender thread
+of a neck was exposed to view; scraping its wings with its hind legs
+and smoothing them to its body as if they had been coat-tails; going
+through its whole toilet as tranquilly as if it knew it was perfectly
+safe. As indeed it was; for as sorely as Tom's hands itched to grab for
+it they did not dare--he believed his soul would be instantly destroyed
+if he did such a thing while the prayer was going on. But with the
+closing sentence his hand began to curve and steal forward; and the
+instant the "Amen" was out the fly was a prisoner of war. His aunt
+detected the act and made him let it go.
+
+The minister gave out his text and droned along monotonously through
+an argument that was so prosy that many a head by and by began to nod
+--and yet it was an argument that dealt in limitless fire and brimstone
+and thinned the predestined elect down to a company so small as to be
+hardly worth the saving. Tom counted the pages of the sermon; after
+church he always knew how many pages there had been, but he seldom knew
+anything else about the discourse. However, this time he was really
+interested for a little while. The minister made a grand and moving
+picture of the assembling together of the world's hosts at the
+millennium when the lion and the lamb should lie down together and a
+little child should lead them. But the pathos, the lesson, the moral of
+the great spectacle were lost upon the boy; he only thought of the
+conspicuousness of the principal character before the on-looking
+nations; his face lit with the thought, and he said to himself that he
+wished he could be that child, if it was a tame lion.
+
+Now he lapsed into suffering again, as the dry argument was resumed.
+Presently he bethought him of a treasure he had and got it out. It was
+a large black beetle with formidable jaws--a "pinchbug," he called it.
+It was in a percussion-cap box. The first thing the beetle did was to
+take him by the finger. A natural fillip followed, the beetle went
+floundering into the aisle and lit on its back, and the hurt finger
+went into the boy's mouth. The beetle lay there working its helpless
+legs, unable to turn over. Tom eyed it, and longed for it; but it was
+safe out of his reach. Other people uninterested in the sermon found
+relief in the beetle, and they eyed it too. Presently a vagrant poodle
+dog came idling along, sad at heart, lazy with the summer softness and
+the quiet, weary of captivity, sighing for change. He spied the beetle;
+the drooping tail lifted and wagged. He surveyed the prize; walked
+around it; smelt at it from a safe distance; walked around it again;
+grew bolder, and took a closer smell; then lifted his lip and made a
+gingerly snatch at it, just missing it; made another, and another;
+began to enjoy the diversion; subsided to his stomach with the beetle
+between his paws, and continued his experiments; grew weary at last,
+and then indifferent and absent-minded. His head nodded, and little by
+little his chin descended and touched the enemy, who seized it. There
+was a sharp yelp, a flirt of the poodle's head, and the beetle fell a
+couple of yards away, and lit on its back once more. The neighboring
+spectators shook with a gentle inward joy, several faces went behind
+fans and handkerchiefs, and Tom was entirely happy. The dog looked
+foolish, and probably felt so; but there was resentment in his heart,
+too, and a craving for revenge. So he went to the beetle and began a
+wary attack on it again; jumping at it from every point of a circle,
+lighting with his fore-paws within an inch of the creature, making even
+closer snatches at it with his teeth, and jerking his head till his
+ears flapped again. But he grew tired once more, after a while; tried
+to amuse himself with a fly but found no relief; followed an ant
+around, with his nose close to the floor, and quickly wearied of that;
+yawned, sighed, forgot the beetle entirely, and sat down on it. Then
+there was a wild yelp of agony and the poodle went sailing up the
+aisle; the yelps continued, and so did the dog; he crossed the house in
+front of the altar; he flew down the other aisle; he crossed before the
+doors; he clamored up the home-stretch; his anguish grew with his
+progress, till presently he was but a woolly comet moving in its orbit
+with the gleam and the speed of light. At last the frantic sufferer
+sheered from its course, and sprang into its master's lap; he flung it
+out of the window, and the voice of distress quickly thinned away and
+died in the distance.
+
+By this time the whole church was red-faced and suffocating with
+suppressed laughter, and the sermon had come to a dead standstill. The
+discourse was resumed presently, but it went lame and halting, all
+possibility of impressiveness being at an end; for even the gravest
+sentiments were constantly being received with a smothered burst of
+unholy mirth, under cover of some remote pew-back, as if the poor
+parson had said a rarely facetious thing. It was a genuine relief to
+the whole congregation when the ordeal was over and the benediction
+pronounced.
+
+Tom Sawyer went home quite cheerful, thinking to himself that there
+was some satisfaction about divine service when there was a bit of
+variety in it. He had but one marring thought; he was willing that the
+dog should play with his pinchbug, but he did not think it was upright
+in him to carry it off.
+
+
+
+CHAPTER VI
+
+MONDAY morning found Tom Sawyer miserable. Monday morning always found
+him so--because it began another week's slow suffering in school. He
+generally began that day with wishing he had had no intervening
+holiday, it made the going into captivity and fetters again so much
+more odious.
+
+Tom lay thinking. Presently it occurred to him that he wished he was
+sick; then he could stay home from school. Here was a vague
+possibility. He canvassed his system. No ailment was found, and he
+investigated again. This time he thought he could detect colicky
+symptoms, and he began to encourage them with considerable hope. But
+they soon grew feeble, and presently died wholly away. He reflected
+further. Suddenly he discovered something. One of his upper front teeth
+was loose. This was lucky; he was about to begin to groan, as a
+"starter," as he called it, when it occurred to him that if he came
+into court with that argument, his aunt would pull it out, and that
+would hurt. So he thought he would hold the tooth in reserve for the
+present, and seek further. Nothing offered for some little time, and
+then he remembered hearing the doctor tell about a certain thing that
+laid up a patient for two or three weeks and threatened to make him
+lose a finger. So the boy eagerly drew his sore toe from under the
+sheet and held it up for inspection. But now he did not know the
+necessary symptoms. However, it seemed well worth while to chance it,
+so he fell to groaning with considerable spirit.
+
+But Sid slept on unconscious.
+
+Tom groaned louder, and fancied that he began to feel pain in the toe.
+
+No result from Sid.
+
+Tom was panting with his exertions by this time. He took a rest and
+then swelled himself up and fetched a succession of admirable groans.
+
+Sid snored on.
+
+Tom was aggravated. He said, "Sid, Sid!" and shook him. This course
+worked well, and Tom began to groan again. Sid yawned, stretched, then
+brought himself up on his elbow with a snort, and began to stare at
+Tom. Tom went on groaning. Sid said:
+
+"Tom! Say, Tom!" [No response.] "Here, Tom! TOM! What is the matter,
+Tom?" And he shook him and looked in his face anxiously.
+
+Tom moaned out:
+
+"Oh, don't, Sid. Don't joggle me."
+
+"Why, what's the matter, Tom? I must call auntie."
+
+"No--never mind. It'll be over by and by, maybe. Don't call anybody."
+
+"But I must! DON'T groan so, Tom, it's awful. How long you been this
+way?"
+
+"Hours. Ouch! Oh, don't stir so, Sid, you'll kill me."
+
+"Tom, why didn't you wake me sooner? Oh, Tom, DON'T! It makes my
+flesh crawl to hear you. Tom, what is the matter?"
+
+"I forgive you everything, Sid. [Groan.] Everything you've ever done
+to me. When I'm gone--"
+
+"Oh, Tom, you ain't dying, are you? Don't, Tom--oh, don't. Maybe--"
+
+"I forgive everybody, Sid. [Groan.] Tell 'em so, Sid. And Sid, you
+give my window-sash and my cat with one eye to that new girl that's
+come to town, and tell her--"
+
+But Sid had snatched his clothes and gone. Tom was suffering in
+reality, now, so handsomely was his imagination working, and so his
+groans had gathered quite a genuine tone.
+
+Sid flew down-stairs and said:
+
+"Oh, Aunt Polly, come! Tom's dying!"
+
+"Dying!"
+
+"Yes'm. Don't wait--come quick!"
+
+"Rubbage! I don't believe it!"
+
+But she fled up-stairs, nevertheless, with Sid and Mary at her heels.
+And her face grew white, too, and her lip trembled. When she reached
+the bedside she gasped out:
+
+"You, Tom! Tom, what's the matter with you?"
+
+"Oh, auntie, I'm--"
+
+"What's the matter with you--what is the matter with you, child?"
+
+"Oh, auntie, my sore toe's mortified!"
+
+The old lady sank down into a chair and laughed a little, then cried a
+little, then did both together. This restored her and she said:
+
+"Tom, what a turn you did give me. Now you shut up that nonsense and
+climb out of this."
+
+The groans ceased and the pain vanished from the toe. The boy felt a
+little foolish, and he said:
+
+"Aunt Polly, it SEEMED mortified, and it hurt so I never minded my
+tooth at all."
+
+"Your tooth, indeed! What's the matter with your tooth?"
+
+"One of them's loose, and it aches perfectly awful."
+
+"There, there, now, don't begin that groaning again. Open your mouth.
+Well--your tooth IS loose, but you're not going to die about that.
+Mary, get me a silk thread, and a chunk of fire out of the kitchen."
+
+Tom said:
+
+"Oh, please, auntie, don't pull it out. It don't hurt any more. I wish
+I may never stir if it does. Please don't, auntie. I don't want to stay
+home from school."
+
+"Oh, you don't, don't you? So all this row was because you thought
+you'd get to stay home from school and go a-fishing? Tom, Tom, I love
+you so, and you seem to try every way you can to break my old heart
+with your outrageousness." By this time the dental instruments were
+ready. The old lady made one end of the silk thread fast to Tom's tooth
+with a loop and tied the other to the bedpost. Then she seized the
+chunk of fire and suddenly thrust it almost into the boy's face. The
+tooth hung dangling by the bedpost, now.
+
+But all trials bring their compensations. As Tom wended to school
+after breakfast, he was the envy of every boy he met because the gap in
+his upper row of teeth enabled him to expectorate in a new and
+admirable way. He gathered quite a following of lads interested in the
+exhibition; and one that had cut his finger and had been a centre of
+fascination and homage up to this time, now found himself suddenly
+without an adherent, and shorn of his glory. His heart was heavy, and
+he said with a disdain which he did not feel that it wasn't anything to
+spit like Tom Sawyer; but another boy said, "Sour grapes!" and he
+wandered away a dismantled hero.
+
+Shortly Tom came upon the juvenile pariah of the village, Huckleberry
+Finn, son of the town drunkard. Huckleberry was cordially hated and
+dreaded by all the mothers of the town, because he was idle and lawless
+and vulgar and bad--and because all their children admired him so, and
+delighted in his forbidden society, and wished they dared to be like
+him. Tom was like the rest of the respectable boys, in that he envied
+Huckleberry his gaudy outcast condition, and was under strict orders
+not to play with him. So he played with him every time he got a chance.
+Huckleberry was always dressed in the cast-off clothes of full-grown
+men, and they were in perennial bloom and fluttering with rags. His hat
+was a vast ruin with a wide crescent lopped out of its brim; his coat,
+when he wore one, hung nearly to his heels and had the rearward buttons
+far down the back; but one suspender supported his trousers; the seat
+of the trousers bagged low and contained nothing, the fringed legs
+dragged in the dirt when not rolled up.
+
+Huckleberry came and went, at his own free will. He slept on doorsteps
+in fine weather and in empty hogsheads in wet; he did not have to go to
+school or to church, or call any being master or obey anybody; he could
+go fishing or swimming when and where he chose, and stay as long as it
+suited him; nobody forbade him to fight; he could sit up as late as he
+pleased; he was always the first boy that went barefoot in the spring
+and the last to resume leather in the fall; he never had to wash, nor
+put on clean clothes; he could swear wonderfully. In a word, everything
+that goes to make life precious that boy had. So thought every
+harassed, hampered, respectable boy in St. Petersburg.
+
+Tom hailed the romantic outcast:
+
+"Hello, Huckleberry!"
+
+"Hello yourself, and see how you like it."
+
+"What's that you got?"
+
+"Dead cat."
+
+"Lemme see him, Huck. My, he's pretty stiff. Where'd you get him?"
+
+"Bought him off'n a boy."
+
+"What did you give?"
+
+"I give a blue ticket and a bladder that I got at the slaughter-house."
+
+"Where'd you get the blue ticket?"
+
+"Bought it off'n Ben Rogers two weeks ago for a hoop-stick."
+
+"Say--what is dead cats good for, Huck?"
+
+"Good for? Cure warts with."
+
+"No! Is that so? I know something that's better."
+
+"I bet you don't. What is it?"
+
+"Why, spunk-water."
+
+"Spunk-water! I wouldn't give a dern for spunk-water."
+
+"You wouldn't, wouldn't you? D'you ever try it?"
+
+"No, I hain't. But Bob Tanner did."
+
+"Who told you so!"
+
+"Why, he told Jeff Thatcher, and Jeff told Johnny Baker, and Johnny
+told Jim Hollis, and Jim told Ben Rogers, and Ben told a nigger, and
+the nigger told me. There now!"
+
+"Well, what of it? They'll all lie. Leastways all but the nigger. I
+don't know HIM. But I never see a nigger that WOULDN'T lie. Shucks! Now
+you tell me how Bob Tanner done it, Huck."
+
+"Why, he took and dipped his hand in a rotten stump where the
+rain-water was."
+
+"In the daytime?"
+
+"Certainly."
+
+"With his face to the stump?"
+
+"Yes. Least I reckon so."
+
+"Did he say anything?"
+
+"I don't reckon he did. I don't know."
+
+"Aha! Talk about trying to cure warts with spunk-water such a blame
+fool way as that! Why, that ain't a-going to do any good. You got to go
+all by yourself, to the middle of the woods, where you know there's a
+spunk-water stump, and just as it's midnight you back up against the
+stump and jam your hand in and say:
+
+  'Barley-corn, barley-corn, injun-meal shorts,
+   Spunk-water, spunk-water, swaller these warts,'
+
+and then walk away quick, eleven steps, with your eyes shut, and then
+turn around three times and walk home without speaking to anybody.
+Because if you speak the charm's busted."
+
+"Well, that sounds like a good way; but that ain't the way Bob Tanner
+done."
+
+"No, sir, you can bet he didn't, becuz he's the wartiest boy in this
+town; and he wouldn't have a wart on him if he'd knowed how to work
+spunk-water. I've took off thousands of warts off of my hands that way,
+Huck. I play with frogs so much that I've always got considerable many
+warts. Sometimes I take 'em off with a bean."
+
+"Yes, bean's good. I've done that."
+
+"Have you? What's your way?"
+
+"You take and split the bean, and cut the wart so as to get some
+blood, and then you put the blood on one piece of the bean and take and
+dig a hole and bury it 'bout midnight at the crossroads in the dark of
+the moon, and then you burn up the rest of the bean. You see that piece
+that's got the blood on it will keep drawing and drawing, trying to
+fetch the other piece to it, and so that helps the blood to draw the
+wart, and pretty soon off she comes."
+
+"Yes, that's it, Huck--that's it; though when you're burying it if you
+say 'Down bean; off wart; come no more to bother me!' it's better.
+That's the way Joe Harper does, and he's been nearly to Coonville and
+most everywheres. But say--how do you cure 'em with dead cats?"
+
+"Why, you take your cat and go and get in the graveyard 'long about
+midnight when somebody that was wicked has been buried; and when it's
+midnight a devil will come, or maybe two or three, but you can't see
+'em, you can only hear something like the wind, or maybe hear 'em talk;
+and when they're taking that feller away, you heave your cat after 'em
+and say, 'Devil follow corpse, cat follow devil, warts follow cat, I'm
+done with ye!' That'll fetch ANY wart."
+
+"Sounds right. D'you ever try it, Huck?"
+
+"No, but old Mother Hopkins told me."
+
+"Well, I reckon it's so, then. Becuz they say she's a witch."
+
+"Say! Why, Tom, I KNOW she is. She witched pap. Pap says so his own
+self. He come along one day, and he see she was a-witching him, so he
+took up a rock, and if she hadn't dodged, he'd a got her. Well, that
+very night he rolled off'n a shed wher' he was a layin drunk, and broke
+his arm."
+
+"Why, that's awful. How did he know she was a-witching him?"
+
+"Lord, pap can tell, easy. Pap says when they keep looking at you
+right stiddy, they're a-witching you. Specially if they mumble. Becuz
+when they mumble they're saying the Lord's Prayer backards."
+
+"Say, Hucky, when you going to try the cat?"
+
+"To-night. I reckon they'll come after old Hoss Williams to-night."
+
+"But they buried him Saturday. Didn't they get him Saturday night?"
+
+"Why, how you talk! How could their charms work till midnight?--and
+THEN it's Sunday. Devils don't slosh around much of a Sunday, I don't
+reckon."
+
+"I never thought of that. That's so. Lemme go with you?"
+
+"Of course--if you ain't afeard."
+
+"Afeard! 'Tain't likely. Will you meow?"
+
+"Yes--and you meow back, if you get a chance. Last time, you kep' me
+a-meowing around till old Hays went to throwing rocks at me and says
+'Dern that cat!' and so I hove a brick through his window--but don't
+you tell."
+
+"I won't. I couldn't meow that night, becuz auntie was watching me,
+but I'll meow this time. Say--what's that?"
+
+"Nothing but a tick."
+
+"Where'd you get him?"
+
+"Out in the woods."
+
+"What'll you take for him?"
+
+"I don't know. I don't want to sell him."
+
+"All right. It's a mighty small tick, anyway."
+
+"Oh, anybody can run a tick down that don't belong to them. I'm
+satisfied with it. It's a good enough tick for me."
+
+"Sho, there's ticks a plenty. I could have a thousand of 'em if I
+wanted to."
+
+"Well, why don't you? Becuz you know mighty well you can't. This is a
+pretty early tick, I reckon. It's the first one I've seen this year."
+
+"Say, Huck--I'll give you my tooth for him."
+
+"Less see it."
+
+Tom got out a bit of paper and carefully unrolled it. Huckleberry
+viewed it wistfully. The temptation was very strong. At last he said:
+
+"Is it genuwyne?"
+
+Tom lifted his lip and showed the vacancy.
+
+"Well, all right," said Huckleberry, "it's a trade."
+
+Tom enclosed the tick in the percussion-cap box that had lately been
+the pinchbug's prison, and the boys separated, each feeling wealthier
+than before.
+
+When Tom reached the little isolated frame schoolhouse, he strode in
+briskly, with the manner of one who had come with all honest speed.
+He hung his hat on a peg and flung himself into his seat with
+business-like alacrity. The master, throned on high in his great
+splint-bottom arm-chair, was dozing, lulled by the drowsy hum of study.
+The interruption roused him.
+
+"Thomas Sawyer!"
+
+Tom knew that when his name was pronounced in full, it meant trouble.
+
+"Sir!"
+
+"Come up here. Now, sir, why are you late again, as usual?"
+
+Tom was about to take refuge in a lie, when he saw two long tails of
+yellow hair hanging down a back that he recognized by the electric
+sympathy of love; and by that form was THE ONLY VACANT PLACE on the
+girls' side of the schoolhouse. He instantly said:
+
+"I STOPPED TO TALK WITH HUCKLEBERRY FINN!"
+
+The master's pulse stood still, and he stared helplessly. The buzz of
+study ceased. The pupils wondered if this foolhardy boy had lost his
+mind. The master said:
+
+"You--you did what?"
+
+"Stopped to talk with Huckleberry Finn."
+
+There was no mistaking the words.
+
+"Thomas Sawyer, this is the most astounding confession I have ever
+listened to. No mere ferule will answer for this offence. Take off your
+jacket."
+
+The master's arm performed until it was tired and the stock of
+switches notably diminished. Then the order followed:
+
+"Now, sir, go and sit with the girls! And let this be a warning to you."
+
+The titter that rippled around the room appeared to abash the boy, but
+in reality that result was caused rather more by his worshipful awe of
+his unknown idol and the dread pleasure that lay in his high good
+fortune. He sat down upon the end of the pine bench and the girl
+hitched herself away from him with a toss of her head. Nudges and winks
+and whispers traversed the room, but Tom sat still, with his arms upon
+the long, low desk before him, and seemed to study his book.
+
+By and by attention ceased from him, and the accustomed school murmur
+rose upon the dull air once more. Presently the boy began to steal
+furtive glances at the girl. She observed it, "made a mouth" at him and
+gave him the back of her head for the space of a minute. When she
+cautiously faced around again, a peach lay before her. She thrust it
+away. Tom gently put it back. She thrust it away again, but with less
+animosity. Tom patiently returned it to its place. Then she let it
+remain. Tom scrawled on his slate, "Please take it--I got more." The
+girl glanced at the words, but made no sign. Now the boy began to draw
+something on the slate, hiding his work with his left hand. For a time
+the girl refused to notice; but her human curiosity presently began to
+manifest itself by hardly perceptible signs. The boy worked on,
+apparently unconscious. The girl made a sort of noncommittal attempt to
+see, but the boy did not betray that he was aware of it. At last she
+gave in and hesitatingly whispered:
+
+"Let me see it."
+
+Tom partly uncovered a dismal caricature of a house with two gable
+ends to it and a corkscrew of smoke issuing from the chimney. Then the
+girl's interest began to fasten itself upon the work and she forgot
+everything else. When it was finished, she gazed a moment, then
+whispered:
+
+"It's nice--make a man."
+
+The artist erected a man in the front yard, that resembled a derrick.
+He could have stepped over the house; but the girl was not
+hypercritical; she was satisfied with the monster, and whispered:
+
+"It's a beautiful man--now make me coming along."
+
+Tom drew an hour-glass with a full moon and straw limbs to it and
+armed the spreading fingers with a portentous fan. The girl said:
+
+"It's ever so nice--I wish I could draw."
+
+"It's easy," whispered Tom, "I'll learn you."
+
+"Oh, will you? When?"
+
+"At noon. Do you go home to dinner?"
+
+"I'll stay if you will."
+
+"Good--that's a whack. What's your name?"
+
+"Becky Thatcher. What's yours? Oh, I know. It's Thomas Sawyer."
+
+"That's the name they lick me by. I'm Tom when I'm good. You call me
+Tom, will you?"
+
+"Yes."
+
+Now Tom began to scrawl something on the slate, hiding the words from
+the girl. But she was not backward this time. She begged to see. Tom
+said:
+
+"Oh, it ain't anything."
+
+"Yes it is."
+
+"No it ain't. You don't want to see."
+
+"Yes I do, indeed I do. Please let me."
+
+"You'll tell."
+
+"No I won't--deed and deed and double deed won't."
+
+"You won't tell anybody at all? Ever, as long as you live?"
+
+"No, I won't ever tell ANYbody. Now let me."
+
+"Oh, YOU don't want to see!"
+
+"Now that you treat me so, I WILL see." And she put her small hand
+upon his and a little scuffle ensued, Tom pretending to resist in
+earnest but letting his hand slip by degrees till these words were
+revealed: "I LOVE YOU."
+
+"Oh, you bad thing!" And she hit his hand a smart rap, but reddened
+and looked pleased, nevertheless.
+
+Just at this juncture the boy felt a slow, fateful grip closing on his
+ear, and a steady lifting impulse. In that wise he was borne across the
+house and deposited in his own seat, under a peppering fire of giggles
+from the whole school. Then the master stood over him during a few
+awful moments, and finally moved away to his throne without saying a
+word. But although Tom's ear tingled, his heart was jubilant.
+
+As the school quieted down Tom made an honest effort to study, but the
+turmoil within him was too great. In turn he took his place in the
+reading class and made a botch of it; then in the geography class and
+turned lakes into mountains, mountains into rivers, and rivers into
+continents, till chaos was come again; then in the spelling class, and
+got "turned down," by a succession of mere baby words, till he brought
+up at the foot and yielded up the pewter medal which he had worn with
+ostentation for months.
+
+
+
+CHAPTER VII
+
+THE harder Tom tried to fasten his mind on his book, the more his
+ideas wandered. So at last, with a sigh and a yawn, he gave it up. It
+seemed to him that the noon recess would never come. The air was
+utterly dead. There was not a breath stirring. It was the sleepiest of
+sleepy days. The drowsing murmur of the five and twenty studying
+scholars soothed the soul like the spell that is in the murmur of bees.
+Away off in the flaming sunshine, Cardiff Hill lifted its soft green
+sides through a shimmering veil of heat, tinted with the purple of
+distance; a few birds floated on lazy wing high in the air; no other
+living thing was visible but some cows, and they were asleep. Tom's
+heart ached to be free, or else to have something of interest to do to
+pass the dreary time. His hand wandered into his pocket and his face
+lit up with a glow of gratitude that was prayer, though he did not know
+it. Then furtively the percussion-cap box came out. He released the
+tick and put him on the long flat desk. The creature probably glowed
+with a gratitude that amounted to prayer, too, at this moment, but it
+was premature: for when he started thankfully to travel off, Tom turned
+him aside with a pin and made him take a new direction.
+
+Tom's bosom friend sat next him, suffering just as Tom had been, and
+now he was deeply and gratefully interested in this entertainment in an
+instant. This bosom friend was Joe Harper. The two boys were sworn
+friends all the week, and embattled enemies on Saturdays. Joe took a
+pin out of his lapel and began to assist in exercising the prisoner.
+The sport grew in interest momently. Soon Tom said that they were
+interfering with each other, and neither getting the fullest benefit of
+the tick. So he put Joe's slate on the desk and drew a line down the
+middle of it from top to bottom.
+
+"Now," said he, "as long as he is on your side you can stir him up and
+I'll let him alone; but if you let him get away and get on my side,
+you're to leave him alone as long as I can keep him from crossing over."
+
+"All right, go ahead; start him up."
+
+The tick escaped from Tom, presently, and crossed the equator. Joe
+harassed him awhile, and then he got away and crossed back again. This
+change of base occurred often. While one boy was worrying the tick with
+absorbing interest, the other would look on with interest as strong,
+the two heads bowed together over the slate, and the two souls dead to
+all things else. At last luck seemed to settle and abide with Joe. The
+tick tried this, that, and the other course, and got as excited and as
+anxious as the boys themselves, but time and again just as he would
+have victory in his very grasp, so to speak, and Tom's fingers would be
+twitching to begin, Joe's pin would deftly head him off, and keep
+possession. At last Tom could stand it no longer. The temptation was
+too strong. So he reached out and lent a hand with his pin. Joe was
+angry in a moment. Said he:
+
+"Tom, you let him alone."
+
+"I only just want to stir him up a little, Joe."
+
+"No, sir, it ain't fair; you just let him alone."
+
+"Blame it, I ain't going to stir him much."
+
+"Let him alone, I tell you."
+
+"I won't!"
+
+"You shall--he's on my side of the line."
+
+"Look here, Joe Harper, whose is that tick?"
+
+"I don't care whose tick he is--he's on my side of the line, and you
+sha'n't touch him."
+
+"Well, I'll just bet I will, though. He's my tick and I'll do what I
+blame please with him, or die!"
+
+A tremendous whack came down on Tom's shoulders, and its duplicate on
+Joe's; and for the space of two minutes the dust continued to fly from
+the two jackets and the whole school to enjoy it. The boys had been too
+absorbed to notice the hush that had stolen upon the school awhile
+before when the master came tiptoeing down the room and stood over
+them. He had contemplated a good part of the performance before he
+contributed his bit of variety to it.
+
+When school broke up at noon, Tom flew to Becky Thatcher, and
+whispered in her ear:
+
+"Put on your bonnet and let on you're going home; and when you get to
+the corner, give the rest of 'em the slip, and turn down through the
+lane and come back. I'll go the other way and come it over 'em the same
+way."
+
+So the one went off with one group of scholars, and the other with
+another. In a little while the two met at the bottom of the lane, and
+when they reached the school they had it all to themselves. Then they
+sat together, with a slate before them, and Tom gave Becky the pencil
+and held her hand in his, guiding it, and so created another surprising
+house. When the interest in art began to wane, the two fell to talking.
+Tom was swimming in bliss. He said:
+
+"Do you love rats?"
+
+"No! I hate them!"
+
+"Well, I do, too--LIVE ones. But I mean dead ones, to swing round your
+head with a string."
+
+"No, I don't care for rats much, anyway. What I like is chewing-gum."
+
+"Oh, I should say so! I wish I had some now."
+
+"Do you? I've got some. I'll let you chew it awhile, but you must give
+it back to me."
+
+That was agreeable, so they chewed it turn about, and dangled their
+legs against the bench in excess of contentment.
+
+"Was you ever at a circus?" said Tom.
+
+"Yes, and my pa's going to take me again some time, if I'm good."
+
+"I been to the circus three or four times--lots of times. Church ain't
+shucks to a circus. There's things going on at a circus all the time.
+I'm going to be a clown in a circus when I grow up."
+
+"Oh, are you! That will be nice. They're so lovely, all spotted up."
+
+"Yes, that's so. And they get slathers of money--most a dollar a day,
+Ben Rogers says. Say, Becky, was you ever engaged?"
+
+"What's that?"
+
+"Why, engaged to be married."
+
+"No."
+
+"Would you like to?"
+
+"I reckon so. I don't know. What is it like?"
+
+"Like? Why it ain't like anything. You only just tell a boy you won't
+ever have anybody but him, ever ever ever, and then you kiss and that's
+all. Anybody can do it."
+
+"Kiss? What do you kiss for?"
+
+"Why, that, you know, is to--well, they always do that."
+
+"Everybody?"
+
+"Why, yes, everybody that's in love with each other. Do you remember
+what I wrote on the slate?"
+
+"Ye--yes."
+
+"What was it?"
+
+"I sha'n't tell you."
+
+"Shall I tell YOU?"
+
+"Ye--yes--but some other time."
+
+"No, now."
+
+"No, not now--to-morrow."
+
+"Oh, no, NOW. Please, Becky--I'll whisper it, I'll whisper it ever so
+easy."
+
+Becky hesitating, Tom took silence for consent, and passed his arm
+about her waist and whispered the tale ever so softly, with his mouth
+close to her ear. And then he added:
+
+"Now you whisper it to me--just the same."
+
+She resisted, for a while, and then said:
+
+"You turn your face away so you can't see, and then I will. But you
+mustn't ever tell anybody--WILL you, Tom? Now you won't, WILL you?"
+
+"No, indeed, indeed I won't. Now, Becky."
+
+He turned his face away. She bent timidly around till her breath
+stirred his curls and whispered, "I--love--you!"
+
+Then she sprang away and ran around and around the desks and benches,
+with Tom after her, and took refuge in a corner at last, with her
+little white apron to her face. Tom clasped her about her neck and
+pleaded:
+
+"Now, Becky, it's all done--all over but the kiss. Don't you be afraid
+of that--it ain't anything at all. Please, Becky." And he tugged at her
+apron and the hands.
+
+By and by she gave up, and let her hands drop; her face, all glowing
+with the struggle, came up and submitted. Tom kissed the red lips and
+said:
+
+"Now it's all done, Becky. And always after this, you know, you ain't
+ever to love anybody but me, and you ain't ever to marry anybody but
+me, ever never and forever. Will you?"
+
+"No, I'll never love anybody but you, Tom, and I'll never marry
+anybody but you--and you ain't to ever marry anybody but me, either."
+
+"Certainly. Of course. That's PART of it. And always coming to school
+or when we're going home, you're to walk with me, when there ain't
+anybody looking--and you choose me and I choose you at parties, because
+that's the way you do when you're engaged."
+
+"It's so nice. I never heard of it before."
+
+"Oh, it's ever so gay! Why, me and Amy Lawrence--"
+
+The big eyes told Tom his blunder and he stopped, confused.
+
+"Oh, Tom! Then I ain't the first you've ever been engaged to!"
+
+The child began to cry. Tom said:
+
+"Oh, don't cry, Becky, I don't care for her any more."
+
+"Yes, you do, Tom--you know you do."
+
+Tom tried to put his arm about her neck, but she pushed him away and
+turned her face to the wall, and went on crying. Tom tried again, with
+soothing words in his mouth, and was repulsed again. Then his pride was
+up, and he strode away and went outside. He stood about, restless and
+uneasy, for a while, glancing at the door, every now and then, hoping
+she would repent and come to find him. But she did not. Then he began
+to feel badly and fear that he was in the wrong. It was a hard struggle
+with him to make new advances, now, but he nerved himself to it and
+entered. She was still standing back there in the corner, sobbing, with
+her face to the wall. Tom's heart smote him. He went to her and stood a
+moment, not knowing exactly how to proceed. Then he said hesitatingly:
+
+"Becky, I--I don't care for anybody but you."
+
+No reply--but sobs.
+
+"Becky"--pleadingly. "Becky, won't you say something?"
+
+More sobs.
+
+Tom got out his chiefest jewel, a brass knob from the top of an
+andiron, and passed it around her so that she could see it, and said:
+
+"Please, Becky, won't you take it?"
+
+She struck it to the floor. Then Tom marched out of the house and over
+the hills and far away, to return to school no more that day. Presently
+Becky began to suspect. She ran to the door; he was not in sight; she
+flew around to the play-yard; he was not there. Then she called:
+
+"Tom! Come back, Tom!"
+
+She listened intently, but there was no answer. She had no companions
+but silence and loneliness. So she sat down to cry again and upbraid
+herself; and by this time the scholars began to gather again, and she
+had to hide her griefs and still her broken heart and take up the cross
+of a long, dreary, aching afternoon, with none among the strangers
+about her to exchange sorrows with.
+
+
+
+CHAPTER VIII
+
+TOM dodged hither and thither through lanes until he was well out of
+the track of returning scholars, and then fell into a moody jog. He
+crossed a small "branch" two or three times, because of a prevailing
+juvenile superstition that to cross water baffled pursuit. Half an hour
+later he was disappearing behind the Douglas mansion on the summit of
+Cardiff Hill, and the schoolhouse was hardly distinguishable away off
+in the valley behind him. He entered a dense wood, picked his pathless
+way to the centre of it, and sat down on a mossy spot under a spreading
+oak. There was not even a zephyr stirring; the dead noonday heat had
+even stilled the songs of the birds; nature lay in a trance that was
+broken by no sound but the occasional far-off hammering of a
+woodpecker, and this seemed to render the pervading silence and sense
+of loneliness the more profound. The boy's soul was steeped in
+melancholy; his feelings were in happy accord with his surroundings. He
+sat long with his elbows on his knees and his chin in his hands,
+meditating. It seemed to him that life was but a trouble, at best, and
+he more than half envied Jimmy Hodges, so lately released; it must be
+very peaceful, he thought, to lie and slumber and dream forever and
+ever, with the wind whispering through the trees and caressing the
+grass and the flowers over the grave, and nothing to bother and grieve
+about, ever any more. If he only had a clean Sunday-school record he
+could be willing to go, and be done with it all. Now as to this girl.
+What had he done? Nothing. He had meant the best in the world, and been
+treated like a dog--like a very dog. She would be sorry some day--maybe
+when it was too late. Ah, if he could only die TEMPORARILY!
+
+But the elastic heart of youth cannot be compressed into one
+constrained shape long at a time. Tom presently began to drift
+insensibly back into the concerns of this life again. What if he turned
+his back, now, and disappeared mysteriously? What if he went away--ever
+so far away, into unknown countries beyond the seas--and never came
+back any more! How would she feel then! The idea of being a clown
+recurred to him now, only to fill him with disgust. For frivolity and
+jokes and spotted tights were an offense, when they intruded themselves
+upon a spirit that was exalted into the vague august realm of the
+romantic. No, he would be a soldier, and return after long years, all
+war-worn and illustrious. No--better still, he would join the Indians,
+and hunt buffaloes and go on the warpath in the mountain ranges and the
+trackless great plains of the Far West, and away in the future come
+back a great chief, bristling with feathers, hideous with paint, and
+prance into Sunday-school, some drowsy summer morning, with a
+bloodcurdling war-whoop, and sear the eyeballs of all his companions
+with unappeasable envy. But no, there was something gaudier even than
+this. He would be a pirate! That was it! NOW his future lay plain
+before him, and glowing with unimaginable splendor. How his name would
+fill the world, and make people shudder! How gloriously he would go
+plowing the dancing seas, in his long, low, black-hulled racer, the
+Spirit of the Storm, with his grisly flag flying at the fore! And at
+the zenith of his fame, how he would suddenly appear at the old village
+and stalk into church, brown and weather-beaten, in his black velvet
+doublet and trunks, his great jack-boots, his crimson sash, his belt
+bristling with horse-pistols, his crime-rusted cutlass at his side, his
+slouch hat with waving plumes, his black flag unfurled, with the skull
+and crossbones on it, and hear with swelling ecstasy the whisperings,
+"It's Tom Sawyer the Pirate!--the Black Avenger of the Spanish Main!"
+
+Yes, it was settled; his career was determined. He would run away from
+home and enter upon it. He would start the very next morning. Therefore
+he must now begin to get ready. He would collect his resources
+together. He went to a rotten log near at hand and began to dig under
+one end of it with his Barlow knife. He soon struck wood that sounded
+hollow. He put his hand there and uttered this incantation impressively:
+
+"What hasn't come here, come! What's here, stay here!"
+
+Then he scraped away the dirt, and exposed a pine shingle. He took it
+up and disclosed a shapely little treasure-house whose bottom and sides
+were of shingles. In it lay a marble. Tom's astonishment was boundless!
+He scratched his head with a perplexed air, and said:
+
+"Well, that beats anything!"
+
+Then he tossed the marble away pettishly, and stood cogitating. The
+truth was, that a superstition of his had failed, here, which he and
+all his comrades had always looked upon as infallible. If you buried a
+marble with certain necessary incantations, and left it alone a
+fortnight, and then opened the place with the incantation he had just
+used, you would find that all the marbles you had ever lost had
+gathered themselves together there, meantime, no matter how widely they
+had been separated. But now, this thing had actually and unquestionably
+failed. Tom's whole structure of faith was shaken to its foundations.
+He had many a time heard of this thing succeeding but never of its
+failing before. It did not occur to him that he had tried it several
+times before, himself, but could never find the hiding-places
+afterward. He puzzled over the matter some time, and finally decided
+that some witch had interfered and broken the charm. He thought he
+would satisfy himself on that point; so he searched around till he
+found a small sandy spot with a little funnel-shaped depression in it.
+He laid himself down and put his mouth close to this depression and
+called--
+
+"Doodle-bug, doodle-bug, tell me what I want to know! Doodle-bug,
+doodle-bug, tell me what I want to know!"
+
+The sand began to work, and presently a small black bug appeared for a
+second and then darted under again in a fright.
+
+"He dasn't tell! So it WAS a witch that done it. I just knowed it."
+
+He well knew the futility of trying to contend against witches, so he
+gave up discouraged. But it occurred to him that he might as well have
+the marble he had just thrown away, and therefore he went and made a
+patient search for it. But he could not find it. Now he went back to
+his treasure-house and carefully placed himself just as he had been
+standing when he tossed the marble away; then he took another marble
+from his pocket and tossed it in the same way, saying:
+
+"Brother, go find your brother!"
+
+He watched where it stopped, and went there and looked. But it must
+have fallen short or gone too far; so he tried twice more. The last
+repetition was successful. The two marbles lay within a foot of each
+other.
+
+Just here the blast of a toy tin trumpet came faintly down the green
+aisles of the forest. Tom flung off his jacket and trousers, turned a
+suspender into a belt, raked away some brush behind the rotten log,
+disclosing a rude bow and arrow, a lath sword and a tin trumpet, and in
+a moment had seized these things and bounded away, barelegged, with
+fluttering shirt. He presently halted under a great elm, blew an
+answering blast, and then began to tiptoe and look warily out, this way
+and that. He said cautiously--to an imaginary company:
+
+"Hold, my merry men! Keep hid till I blow."
+
+Now appeared Joe Harper, as airily clad and elaborately armed as Tom.
+Tom called:
+
+"Hold! Who comes here into Sherwood Forest without my pass?"
+
+"Guy of Guisborne wants no man's pass. Who art thou that--that--"
+
+"Dares to hold such language," said Tom, prompting--for they talked
+"by the book," from memory.
+
+"Who art thou that dares to hold such language?"
+
+"I, indeed! I am Robin Hood, as thy caitiff carcase soon shall know."
+
+"Then art thou indeed that famous outlaw? Right gladly will I dispute
+with thee the passes of the merry wood. Have at thee!"
+
+They took their lath swords, dumped their other traps on the ground,
+struck a fencing attitude, foot to foot, and began a grave, careful
+combat, "two up and two down." Presently Tom said:
+
+"Now, if you've got the hang, go it lively!"
+
+So they "went it lively," panting and perspiring with the work. By and
+by Tom shouted:
+
+"Fall! fall! Why don't you fall?"
+
+"I sha'n't! Why don't you fall yourself? You're getting the worst of
+it."
+
+"Why, that ain't anything. I can't fall; that ain't the way it is in
+the book. The book says, 'Then with one back-handed stroke he slew poor
+Guy of Guisborne.' You're to turn around and let me hit you in the
+back."
+
+There was no getting around the authorities, so Joe turned, received
+the whack and fell.
+
+"Now," said Joe, getting up, "you got to let me kill YOU. That's fair."
+
+"Why, I can't do that, it ain't in the book."
+
+"Well, it's blamed mean--that's all."
+
+"Well, say, Joe, you can be Friar Tuck or Much the miller's son, and
+lam me with a quarter-staff; or I'll be the Sheriff of Nottingham and
+you be Robin Hood a little while and kill me."
+
+This was satisfactory, and so these adventures were carried out. Then
+Tom became Robin Hood again, and was allowed by the treacherous nun to
+bleed his strength away through his neglected wound. And at last Joe,
+representing a whole tribe of weeping outlaws, dragged him sadly forth,
+gave his bow into his feeble hands, and Tom said, "Where this arrow
+falls, there bury poor Robin Hood under the greenwood tree." Then he
+shot the arrow and fell back and would have died, but he lit on a
+nettle and sprang up too gaily for a corpse.
+
+The boys dressed themselves, hid their accoutrements, and went off
+grieving that there were no outlaws any more, and wondering what modern
+civilization could claim to have done to compensate for their loss.
+They said they would rather be outlaws a year in Sherwood Forest than
+President of the United States forever.
+
+
+
+CHAPTER IX
+
+AT half-past nine, that night, Tom and Sid were sent to bed, as usual.
+They said their prayers, and Sid was soon asleep. Tom lay awake and
+waited, in restless impatience. When it seemed to him that it must be
+nearly daylight, he heard the clock strike ten! This was despair. He
+would have tossed and fidgeted, as his nerves demanded, but he was
+afraid he might wake Sid. So he lay still, and stared up into the dark.
+Everything was dismally still. By and by, out of the stillness, little,
+scarcely perceptible noises began to emphasize themselves. The ticking
+of the clock began to bring itself into notice. Old beams began to
+crack mysteriously. The stairs creaked faintly. Evidently spirits were
+abroad. A measured, muffled snore issued from Aunt Polly's chamber. And
+now the tiresome chirping of a cricket that no human ingenuity could
+locate, began. Next the ghastly ticking of a deathwatch in the wall at
+the bed's head made Tom shudder--it meant that somebody's days were
+numbered. Then the howl of a far-off dog rose on the night air, and was
+answered by a fainter howl from a remoter distance. Tom was in an
+agony. At last he was satisfied that time had ceased and eternity
+begun; he began to doze, in spite of himself; the clock chimed eleven,
+but he did not hear it. And then there came, mingling with his
+half-formed dreams, a most melancholy caterwauling. The raising of a
+neighboring window disturbed him. A cry of "Scat! you devil!" and the
+crash of an empty bottle against the back of his aunt's woodshed
+brought him wide awake, and a single minute later he was dressed and
+out of the window and creeping along the roof of the "ell" on all
+fours. He "meow'd" with caution once or twice, as he went; then jumped
+to the roof of the woodshed and thence to the ground. Huckleberry Finn
+was there, with his dead cat. The boys moved off and disappeared in the
+gloom. At the end of half an hour they were wading through the tall
+grass of the graveyard.
+
+It was a graveyard of the old-fashioned Western kind. It was on a
+hill, about a mile and a half from the village. It had a crazy board
+fence around it, which leaned inward in places, and outward the rest of
+the time, but stood upright nowhere. Grass and weeds grew rank over the
+whole cemetery. All the old graves were sunken in, there was not a
+tombstone on the place; round-topped, worm-eaten boards staggered over
+the graves, leaning for support and finding none. "Sacred to the memory
+of" So-and-So had been painted on them once, but it could no longer
+have been read, on the most of them, now, even if there had been light.
+
+A faint wind moaned through the trees, and Tom feared it might be the
+spirits of the dead, complaining at being disturbed. The boys talked
+little, and only under their breath, for the time and the place and the
+pervading solemnity and silence oppressed their spirits. They found the
+sharp new heap they were seeking, and ensconced themselves within the
+protection of three great elms that grew in a bunch within a few feet
+of the grave.
+
+Then they waited in silence for what seemed a long time. The hooting
+of a distant owl was all the sound that troubled the dead stillness.
+Tom's reflections grew oppressive. He must force some talk. So he said
+in a whisper:
+
+"Hucky, do you believe the dead people like it for us to be here?"
+
+Huckleberry whispered:
+
+"I wisht I knowed. It's awful solemn like, AIN'T it?"
+
+"I bet it is."
+
+There was a considerable pause, while the boys canvassed this matter
+inwardly. Then Tom whispered:
+
+"Say, Hucky--do you reckon Hoss Williams hears us talking?"
+
+"O' course he does. Least his sperrit does."
+
+Tom, after a pause:
+
+"I wish I'd said Mister Williams. But I never meant any harm.
+Everybody calls him Hoss."
+
+"A body can't be too partic'lar how they talk 'bout these-yer dead
+people, Tom."
+
+This was a damper, and conversation died again.
+
+Presently Tom seized his comrade's arm and said:
+
+"Sh!"
+
+"What is it, Tom?" And the two clung together with beating hearts.
+
+"Sh! There 'tis again! Didn't you hear it?"
+
+"I--"
+
+"There! Now you hear it."
+
+"Lord, Tom, they're coming! They're coming, sure. What'll we do?"
+
+"I dono. Think they'll see us?"
+
+"Oh, Tom, they can see in the dark, same as cats. I wisht I hadn't
+come."
+
+"Oh, don't be afeard. I don't believe they'll bother us. We ain't
+doing any harm. If we keep perfectly still, maybe they won't notice us
+at all."
+
+"I'll try to, Tom, but, Lord, I'm all of a shiver."
+
+"Listen!"
+
+The boys bent their heads together and scarcely breathed. A muffled
+sound of voices floated up from the far end of the graveyard.
+
+"Look! See there!" whispered Tom. "What is it?"
+
+"It's devil-fire. Oh, Tom, this is awful."
+
+Some vague figures approached through the gloom, swinging an
+old-fashioned tin lantern that freckled the ground with innumerable
+little spangles of light. Presently Huckleberry whispered with a
+shudder:
+
+"It's the devils sure enough. Three of 'em! Lordy, Tom, we're goners!
+Can you pray?"
+
+"I'll try, but don't you be afeard. They ain't going to hurt us. 'Now
+I lay me down to sleep, I--'"
+
+"Sh!"
+
+"What is it, Huck?"
+
+"They're HUMANS! One of 'em is, anyway. One of 'em's old Muff Potter's
+voice."
+
+"No--'tain't so, is it?"
+
+"I bet I know it. Don't you stir nor budge. He ain't sharp enough to
+notice us. Drunk, the same as usual, likely--blamed old rip!"
+
+"All right, I'll keep still. Now they're stuck. Can't find it. Here
+they come again. Now they're hot. Cold again. Hot again. Red hot!
+They're p'inted right, this time. Say, Huck, I know another o' them
+voices; it's Injun Joe."
+
+"That's so--that murderin' half-breed! I'd druther they was devils a
+dern sight. What kin they be up to?"
+
+The whisper died wholly out, now, for the three men had reached the
+grave and stood within a few feet of the boys' hiding-place.
+
+"Here it is," said the third voice; and the owner of it held the
+lantern up and revealed the face of young Doctor Robinson.
+
+Potter and Injun Joe were carrying a handbarrow with a rope and a
+couple of shovels on it. They cast down their load and began to open
+the grave. The doctor put the lantern at the head of the grave and came
+and sat down with his back against one of the elm trees. He was so
+close the boys could have touched him.
+
+"Hurry, men!" he said, in a low voice; "the moon might come out at any
+moment."
+
+They growled a response and went on digging. For some time there was
+no noise but the grating sound of the spades discharging their freight
+of mould and gravel. It was very monotonous. Finally a spade struck
+upon the coffin with a dull woody accent, and within another minute or
+two the men had hoisted it out on the ground. They pried off the lid
+with their shovels, got out the body and dumped it rudely on the
+ground. The moon drifted from behind the clouds and exposed the pallid
+face. The barrow was got ready and the corpse placed on it, covered
+with a blanket, and bound to its place with the rope. Potter took out a
+large spring-knife and cut off the dangling end of the rope and then
+said:
+
+"Now the cussed thing's ready, Sawbones, and you'll just out with
+another five, or here she stays."
+
+"That's the talk!" said Injun Joe.
+
+"Look here, what does this mean?" said the doctor. "You required your
+pay in advance, and I've paid you."
+
+"Yes, and you done more than that," said Injun Joe, approaching the
+doctor, who was now standing. "Five years ago you drove me away from
+your father's kitchen one night, when I come to ask for something to
+eat, and you said I warn't there for any good; and when I swore I'd get
+even with you if it took a hundred years, your father had me jailed for
+a vagrant. Did you think I'd forget? The Injun blood ain't in me for
+nothing. And now I've GOT you, and you got to SETTLE, you know!"
+
+He was threatening the doctor, with his fist in his face, by this
+time. The doctor struck out suddenly and stretched the ruffian on the
+ground. Potter dropped his knife, and exclaimed:
+
+"Here, now, don't you hit my pard!" and the next moment he had
+grappled with the doctor and the two were struggling with might and
+main, trampling the grass and tearing the ground with their heels.
+Injun Joe sprang to his feet, his eyes flaming with passion, snatched
+up Potter's knife, and went creeping, catlike and stooping, round and
+round about the combatants, seeking an opportunity. All at once the
+doctor flung himself free, seized the heavy headboard of Williams'
+grave and felled Potter to the earth with it--and in the same instant
+the half-breed saw his chance and drove the knife to the hilt in the
+young man's breast. He reeled and fell partly upon Potter, flooding him
+with his blood, and in the same moment the clouds blotted out the
+dreadful spectacle and the two frightened boys went speeding away in
+the dark.
+
+Presently, when the moon emerged again, Injun Joe was standing over
+the two forms, contemplating them. The doctor murmured inarticulately,
+gave a long gasp or two and was still. The half-breed muttered:
+
+"THAT score is settled--damn you."
+
+Then he robbed the body. After which he put the fatal knife in
+Potter's open right hand, and sat down on the dismantled coffin. Three
+--four--five minutes passed, and then Potter began to stir and moan. His
+hand closed upon the knife; he raised it, glanced at it, and let it
+fall, with a shudder. Then he sat up, pushing the body from him, and
+gazed at it, and then around him, confusedly. His eyes met Joe's.
+
+"Lord, how is this, Joe?" he said.
+
+"It's a dirty business," said Joe, without moving.
+
+"What did you do it for?"
+
+"I! I never done it!"
+
+"Look here! That kind of talk won't wash."
+
+Potter trembled and grew white.
+
+"I thought I'd got sober. I'd no business to drink to-night. But it's
+in my head yet--worse'n when we started here. I'm all in a muddle;
+can't recollect anything of it, hardly. Tell me, Joe--HONEST, now, old
+feller--did I do it? Joe, I never meant to--'pon my soul and honor, I
+never meant to, Joe. Tell me how it was, Joe. Oh, it's awful--and him
+so young and promising."
+
+"Why, you two was scuffling, and he fetched you one with the headboard
+and you fell flat; and then up you come, all reeling and staggering
+like, and snatched the knife and jammed it into him, just as he fetched
+you another awful clip--and here you've laid, as dead as a wedge til
+now."
+
+"Oh, I didn't know what I was a-doing. I wish I may die this minute if
+I did. It was all on account of the whiskey and the excitement, I
+reckon. I never used a weepon in my life before, Joe. I've fought, but
+never with weepons. They'll all say that. Joe, don't tell! Say you
+won't tell, Joe--that's a good feller. I always liked you, Joe, and
+stood up for you, too. Don't you remember? You WON'T tell, WILL you,
+Joe?" And the poor creature dropped on his knees before the stolid
+murderer, and clasped his appealing hands.
+
+"No, you've always been fair and square with me, Muff Potter, and I
+won't go back on you. There, now, that's as fair as a man can say."
+
+"Oh, Joe, you're an angel. I'll bless you for this the longest day I
+live." And Potter began to cry.
+
+"Come, now, that's enough of that. This ain't any time for blubbering.
+You be off yonder way and I'll go this. Move, now, and don't leave any
+tracks behind you."
+
+Potter started on a trot that quickly increased to a run. The
+half-breed stood looking after him. He muttered:
+
+"If he's as much stunned with the lick and fuddled with the rum as he
+had the look of being, he won't think of the knife till he's gone so
+far he'll be afraid to come back after it to such a place by himself
+--chicken-heart!"
+
+Two or three minutes later the murdered man, the blanketed corpse, the
+lidless coffin, and the open grave were under no inspection but the
+moon's. The stillness was complete again, too.
+
+
+
+CHAPTER X
+
+THE two boys flew on and on, toward the village, speechless with
+horror. They glanced backward over their shoulders from time to time,
+apprehensively, as if they feared they might be followed. Every stump
+that started up in their path seemed a man and an enemy, and made them
+catch their breath; and as they sped by some outlying cottages that lay
+near the village, the barking of the aroused watch-dogs seemed to give
+wings to their feet.
+
+"If we can only get to the old tannery before we break down!"
+whispered Tom, in short catches between breaths. "I can't stand it much
+longer."
+
+Huckleberry's hard pantings were his only reply, and the boys fixed
+their eyes on the goal of their hopes and bent to their work to win it.
+They gained steadily on it, and at last, breast to breast, they burst
+through the open door and fell grateful and exhausted in the sheltering
+shadows beyond. By and by their pulses slowed down, and Tom whispered:
+
+"Huckleberry, what do you reckon'll come of this?"
+
+"If Doctor Robinson dies, I reckon hanging'll come of it."
+
+"Do you though?"
+
+"Why, I KNOW it, Tom."
+
+Tom thought a while, then he said:
+
+"Who'll tell? We?"
+
+"What are you talking about? S'pose something happened and Injun Joe
+DIDN'T hang? Why, he'd kill us some time or other, just as dead sure as
+we're a laying here."
+
+"That's just what I was thinking to myself, Huck."
+
+"If anybody tells, let Muff Potter do it, if he's fool enough. He's
+generally drunk enough."
+
+Tom said nothing--went on thinking. Presently he whispered:
+
+"Huck, Muff Potter don't know it. How can he tell?"
+
+"What's the reason he don't know it?"
+
+"Because he'd just got that whack when Injun Joe done it. D'you reckon
+he could see anything? D'you reckon he knowed anything?"
+
+"By hokey, that's so, Tom!"
+
+"And besides, look-a-here--maybe that whack done for HIM!"
+
+"No, 'taint likely, Tom. He had liquor in him; I could see that; and
+besides, he always has. Well, when pap's full, you might take and belt
+him over the head with a church and you couldn't phase him. He says so,
+his own self. So it's the same with Muff Potter, of course. But if a
+man was dead sober, I reckon maybe that whack might fetch him; I dono."
+
+After another reflective silence, Tom said:
+
+"Hucky, you sure you can keep mum?"
+
+"Tom, we GOT to keep mum. You know that. That Injun devil wouldn't
+make any more of drownding us than a couple of cats, if we was to
+squeak 'bout this and they didn't hang him. Now, look-a-here, Tom, less
+take and swear to one another--that's what we got to do--swear to keep
+mum."
+
+"I'm agreed. It's the best thing. Would you just hold hands and swear
+that we--"
+
+"Oh no, that wouldn't do for this. That's good enough for little
+rubbishy common things--specially with gals, cuz THEY go back on you
+anyway, and blab if they get in a huff--but there orter be writing
+'bout a big thing like this. And blood."
+
+Tom's whole being applauded this idea. It was deep, and dark, and
+awful; the hour, the circumstances, the surroundings, were in keeping
+with it. He picked up a clean pine shingle that lay in the moonlight,
+took a little fragment of "red keel" out of his pocket, got the moon on
+his work, and painfully scrawled these lines, emphasizing each slow
+down-stroke by clamping his tongue between his teeth, and letting up
+the pressure on the up-strokes. [See next page.]
+
+   "Huck Finn and
+    Tom Sawyer swears
+    they will keep mum
+    about This and They
+    wish They may Drop
+    down dead in Their
+    Tracks if They ever
+    Tell and Rot."
+
+Huckleberry was filled with admiration of Tom's facility in writing,
+and the sublimity of his language. He at once took a pin from his lapel
+and was going to prick his flesh, but Tom said:
+
+"Hold on! Don't do that. A pin's brass. It might have verdigrease on
+it."
+
+"What's verdigrease?"
+
+"It's p'ison. That's what it is. You just swaller some of it once
+--you'll see."
+
+So Tom unwound the thread from one of his needles, and each boy
+pricked the ball of his thumb and squeezed out a drop of blood. In
+time, after many squeezes, Tom managed to sign his initials, using the
+ball of his little finger for a pen. Then he showed Huckleberry how to
+make an H and an F, and the oath was complete. They buried the shingle
+close to the wall, with some dismal ceremonies and incantations, and
+the fetters that bound their tongues were considered to be locked and
+the key thrown away.
+
+A figure crept stealthily through a break in the other end of the
+ruined building, now, but they did not notice it.
+
+"Tom," whispered Huckleberry, "does this keep us from EVER telling
+--ALWAYS?"
+
+"Of course it does. It don't make any difference WHAT happens, we got
+to keep mum. We'd drop down dead--don't YOU know that?"
+
+"Yes, I reckon that's so."
+
+They continued to whisper for some little time. Presently a dog set up
+a long, lugubrious howl just outside--within ten feet of them. The boys
+clasped each other suddenly, in an agony of fright.
+
+"Which of us does he mean?" gasped Huckleberry.
+
+"I dono--peep through the crack. Quick!"
+
+"No, YOU, Tom!"
+
+"I can't--I can't DO it, Huck!"
+
+"Please, Tom. There 'tis again!"
+
+"Oh, lordy, I'm thankful!" whispered Tom. "I know his voice. It's Bull
+Harbison." *
+
+[* If Mr. Harbison owned a slave named Bull, Tom would have spoken of
+him as "Harbison's Bull," but a son or a dog of that name was "Bull
+Harbison."]
+
+"Oh, that's good--I tell you, Tom, I was most scared to death; I'd a
+bet anything it was a STRAY dog."
+
+The dog howled again. The boys' hearts sank once more.
+
+"Oh, my! that ain't no Bull Harbison!" whispered Huckleberry. "DO, Tom!"
+
+Tom, quaking with fear, yielded, and put his eye to the crack. His
+whisper was hardly audible when he said:
+
+"Oh, Huck, IT S A STRAY DOG!"
+
+"Quick, Tom, quick! Who does he mean?"
+
+"Huck, he must mean us both--we're right together."
+
+"Oh, Tom, I reckon we're goners. I reckon there ain't no mistake 'bout
+where I'LL go to. I been so wicked."
+
+"Dad fetch it! This comes of playing hookey and doing everything a
+feller's told NOT to do. I might a been good, like Sid, if I'd a tried
+--but no, I wouldn't, of course. But if ever I get off this time, I lay
+I'll just WALLER in Sunday-schools!" And Tom began to snuffle a little.
+
+"YOU bad!" and Huckleberry began to snuffle too. "Consound it, Tom
+Sawyer, you're just old pie, 'longside o' what I am. Oh, LORDY, lordy,
+lordy, I wisht I only had half your chance."
+
+Tom choked off and whispered:
+
+"Look, Hucky, look! He's got his BACK to us!"
+
+Hucky looked, with joy in his heart.
+
+"Well, he has, by jingoes! Did he before?"
+
+"Yes, he did. But I, like a fool, never thought. Oh, this is bully,
+you know. NOW who can he mean?"
+
+The howling stopped. Tom pricked up his ears.
+
+"Sh! What's that?" he whispered.
+
+"Sounds like--like hogs grunting. No--it's somebody snoring, Tom."
+
+"That IS it! Where 'bouts is it, Huck?"
+
+"I bleeve it's down at 'tother end. Sounds so, anyway. Pap used to
+sleep there, sometimes, 'long with the hogs, but laws bless you, he
+just lifts things when HE snores. Besides, I reckon he ain't ever
+coming back to this town any more."
+
+The spirit of adventure rose in the boys' souls once more.
+
+"Hucky, do you das't to go if I lead?"
+
+"I don't like to, much. Tom, s'pose it's Injun Joe!"
+
+Tom quailed. But presently the temptation rose up strong again and the
+boys agreed to try, with the understanding that they would take to
+their heels if the snoring stopped. So they went tiptoeing stealthily
+down, the one behind the other. When they had got to within five steps
+of the snorer, Tom stepped on a stick, and it broke with a sharp snap.
+The man moaned, writhed a little, and his face came into the moonlight.
+It was Muff Potter. The boys' hearts had stood still, and their hopes
+too, when the man moved, but their fears passed away now. They tiptoed
+out, through the broken weather-boarding, and stopped at a little
+distance to exchange a parting word. That long, lugubrious howl rose on
+the night air again! They turned and saw the strange dog standing
+within a few feet of where Potter was lying, and FACING Potter, with
+his nose pointing heavenward.
+
+"Oh, geeminy, it's HIM!" exclaimed both boys, in a breath.
+
+"Say, Tom--they say a stray dog come howling around Johnny Miller's
+house, 'bout midnight, as much as two weeks ago; and a whippoorwill
+come in and lit on the banisters and sung, the very same evening; and
+there ain't anybody dead there yet."
+
+"Well, I know that. And suppose there ain't. Didn't Gracie Miller fall
+in the kitchen fire and burn herself terrible the very next Saturday?"
+
+"Yes, but she ain't DEAD. And what's more, she's getting better, too."
+
+"All right, you wait and see. She's a goner, just as dead sure as Muff
+Potter's a goner. That's what the niggers say, and they know all about
+these kind of things, Huck."
+
+Then they separated, cogitating. When Tom crept in at his bedroom
+window the night was almost spent. He undressed with excessive caution,
+and fell asleep congratulating himself that nobody knew of his
+escapade. He was not aware that the gently-snoring Sid was awake, and
+had been so for an hour.
+
+When Tom awoke, Sid was dressed and gone. There was a late look in the
+light, a late sense in the atmosphere. He was startled. Why had he not
+been called--persecuted till he was up, as usual? The thought filled
+him with bodings. Within five minutes he was dressed and down-stairs,
+feeling sore and drowsy. The family were still at table, but they had
+finished breakfast. There was no voice of rebuke; but there were
+averted eyes; there was a silence and an air of solemnity that struck a
+chill to the culprit's heart. He sat down and tried to seem gay, but it
+was up-hill work; it roused no smile, no response, and he lapsed into
+silence and let his heart sink down to the depths.
+
+After breakfast his aunt took him aside, and Tom almost brightened in
+the hope that he was going to be flogged; but it was not so. His aunt
+wept over him and asked him how he could go and break her old heart so;
+and finally told him to go on, and ruin himself and bring her gray
+hairs with sorrow to the grave, for it was no use for her to try any
+more. This was worse than a thousand whippings, and Tom's heart was
+sorer now than his body. He cried, he pleaded for forgiveness, promised
+to reform over and over again, and then received his dismissal, feeling
+that he had won but an imperfect forgiveness and established but a
+feeble confidence.
+
+He left the presence too miserable to even feel revengeful toward Sid;
+and so the latter's prompt retreat through the back gate was
+unnecessary. He moped to school gloomy and sad, and took his flogging,
+along with Joe Harper, for playing hookey the day before, with the air
+of one whose heart was busy with heavier woes and wholly dead to
+trifles. Then he betook himself to his seat, rested his elbows on his
+desk and his jaws in his hands, and stared at the wall with the stony
+stare of suffering that has reached the limit and can no further go.
+His elbow was pressing against some hard substance. After a long time
+he slowly and sadly changed his position, and took up this object with
+a sigh. It was in a paper. He unrolled it. A long, lingering, colossal
+sigh followed, and his heart broke. It was his brass andiron knob!
+
+This final feather broke the camel's back.
+
+
+
+CHAPTER XI
+
+CLOSE upon the hour of noon the whole village was suddenly electrified
+with the ghastly news. No need of the as yet undreamed-of telegraph;
+the tale flew from man to man, from group to group, from house to
+house, with little less than telegraphic speed. Of course the
+schoolmaster gave holiday for that afternoon; the town would have
+thought strangely of him if he had not.
+
+A gory knife had been found close to the murdered man, and it had been
+recognized by somebody as belonging to Muff Potter--so the story ran.
+And it was said that a belated citizen had come upon Potter washing
+himself in the "branch" about one or two o'clock in the morning, and
+that Potter had at once sneaked off--suspicious circumstances,
+especially the washing which was not a habit with Potter. It was also
+said that the town had been ransacked for this "murderer" (the public
+are not slow in the matter of sifting evidence and arriving at a
+verdict), but that he could not be found. Horsemen had departed down
+all the roads in every direction, and the Sheriff "was confident" that
+he would be captured before night.
+
+All the town was drifting toward the graveyard. Tom's heartbreak
+vanished and he joined the procession, not because he would not a
+thousand times rather go anywhere else, but because an awful,
+unaccountable fascination drew him on. Arrived at the dreadful place,
+he wormed his small body through the crowd and saw the dismal
+spectacle. It seemed to him an age since he was there before. Somebody
+pinched his arm. He turned, and his eyes met Huckleberry's. Then both
+looked elsewhere at once, and wondered if anybody had noticed anything
+in their mutual glance. But everybody was talking, and intent upon the
+grisly spectacle before them.
+
+"Poor fellow!" "Poor young fellow!" "This ought to be a lesson to
+grave robbers!" "Muff Potter'll hang for this if they catch him!" This
+was the drift of remark; and the minister said, "It was a judgment; His
+hand is here."
+
+Now Tom shivered from head to heel; for his eye fell upon the stolid
+face of Injun Joe. At this moment the crowd began to sway and struggle,
+and voices shouted, "It's him! it's him! he's coming himself!"
+
+"Who? Who?" from twenty voices.
+
+"Muff Potter!"
+
+"Hallo, he's stopped!--Look out, he's turning! Don't let him get away!"
+
+People in the branches of the trees over Tom's head said he wasn't
+trying to get away--he only looked doubtful and perplexed.
+
+"Infernal impudence!" said a bystander; "wanted to come and take a
+quiet look at his work, I reckon--didn't expect any company."
+
+The crowd fell apart, now, and the Sheriff came through,
+ostentatiously leading Potter by the arm. The poor fellow's face was
+haggard, and his eyes showed the fear that was upon him. When he stood
+before the murdered man, he shook as with a palsy, and he put his face
+in his hands and burst into tears.
+
+"I didn't do it, friends," he sobbed; "'pon my word and honor I never
+done it."
+
+"Who's accused you?" shouted a voice.
+
+This shot seemed to carry home. Potter lifted his face and looked
+around him with a pathetic hopelessness in his eyes. He saw Injun Joe,
+and exclaimed:
+
+"Oh, Injun Joe, you promised me you'd never--"
+
+"Is that your knife?" and it was thrust before him by the Sheriff.
+
+Potter would have fallen if they had not caught him and eased him to
+the ground. Then he said:
+
+"Something told me 't if I didn't come back and get--" He shuddered;
+then waved his nerveless hand with a vanquished gesture and said, "Tell
+'em, Joe, tell 'em--it ain't any use any more."
+
+Then Huckleberry and Tom stood dumb and staring, and heard the
+stony-hearted liar reel off his serene statement, they expecting every
+moment that the clear sky would deliver God's lightnings upon his head,
+and wondering to see how long the stroke was delayed. And when he had
+finished and still stood alive and whole, their wavering impulse to
+break their oath and save the poor betrayed prisoner's life faded and
+vanished away, for plainly this miscreant had sold himself to Satan and
+it would be fatal to meddle with the property of such a power as that.
+
+"Why didn't you leave? What did you want to come here for?" somebody
+said.
+
+"I couldn't help it--I couldn't help it," Potter moaned. "I wanted to
+run away, but I couldn't seem to come anywhere but here." And he fell
+to sobbing again.
+
+Injun Joe repeated his statement, just as calmly, a few minutes
+afterward on the inquest, under oath; and the boys, seeing that the
+lightnings were still withheld, were confirmed in their belief that Joe
+had sold himself to the devil. He was now become, to them, the most
+balefully interesting object they had ever looked upon, and they could
+not take their fascinated eyes from his face.
+
+They inwardly resolved to watch him nights, when opportunity should
+offer, in the hope of getting a glimpse of his dread master.
+
+Injun Joe helped to raise the body of the murdered man and put it in a
+wagon for removal; and it was whispered through the shuddering crowd
+that the wound bled a little! The boys thought that this happy
+circumstance would turn suspicion in the right direction; but they were
+disappointed, for more than one villager remarked:
+
+"It was within three feet of Muff Potter when it done it."
+
+Tom's fearful secret and gnawing conscience disturbed his sleep for as
+much as a week after this; and at breakfast one morning Sid said:
+
+"Tom, you pitch around and talk in your sleep so much that you keep me
+awake half the time."
+
+Tom blanched and dropped his eyes.
+
+"It's a bad sign," said Aunt Polly, gravely. "What you got on your
+mind, Tom?"
+
+"Nothing. Nothing 't I know of." But the boy's hand shook so that he
+spilled his coffee.
+
+"And you do talk such stuff," Sid said. "Last night you said, 'It's
+blood, it's blood, that's what it is!' You said that over and over. And
+you said, 'Don't torment me so--I'll tell!' Tell WHAT? What is it
+you'll tell?"
+
+Everything was swimming before Tom. There is no telling what might
+have happened, now, but luckily the concern passed out of Aunt Polly's
+face and she came to Tom's relief without knowing it. She said:
+
+"Sho! It's that dreadful murder. I dream about it most every night
+myself. Sometimes I dream it's me that done it."
+
+Mary said she had been affected much the same way. Sid seemed
+satisfied. Tom got out of the presence as quick as he plausibly could,
+and after that he complained of toothache for a week, and tied up his
+jaws every night. He never knew that Sid lay nightly watching, and
+frequently slipped the bandage free and then leaned on his elbow
+listening a good while at a time, and afterward slipped the bandage
+back to its place again. Tom's distress of mind wore off gradually and
+the toothache grew irksome and was discarded. If Sid really managed to
+make anything out of Tom's disjointed mutterings, he kept it to himself.
+
+It seemed to Tom that his schoolmates never would get done holding
+inquests on dead cats, and thus keeping his trouble present to his
+mind. Sid noticed that Tom never was coroner at one of these inquiries,
+though it had been his habit to take the lead in all new enterprises;
+he noticed, too, that Tom never acted as a witness--and that was
+strange; and Sid did not overlook the fact that Tom even showed a
+marked aversion to these inquests, and always avoided them when he
+could. Sid marvelled, but said nothing. However, even inquests went out
+of vogue at last, and ceased to torture Tom's conscience.
+
+Every day or two, during this time of sorrow, Tom watched his
+opportunity and went to the little grated jail-window and smuggled such
+small comforts through to the "murderer" as he could get hold of. The
+jail was a trifling little brick den that stood in a marsh at the edge
+of the village, and no guards were afforded for it; indeed, it was
+seldom occupied. These offerings greatly helped to ease Tom's
+conscience.
+
+The villagers had a strong desire to tar-and-feather Injun Joe and
+ride him on a rail, for body-snatching, but so formidable was his
+character that nobody could be found who was willing to take the lead
+in the matter, so it was dropped. He had been careful to begin both of
+his inquest-statements with the fight, without confessing the
+grave-robbery that preceded it; therefore it was deemed wisest not
+to try the case in the courts at present.
+
+
+
+CHAPTER XII
+
+ONE of the reasons why Tom's mind had drifted away from its secret
+troubles was, that it had found a new and weighty matter to interest
+itself about. Becky Thatcher had stopped coming to school. Tom had
+struggled with his pride a few days, and tried to "whistle her down the
+wind," but failed. He began to find himself hanging around her father's
+house, nights, and feeling very miserable. She was ill. What if she
+should die! There was distraction in the thought. He no longer took an
+interest in war, nor even in piracy. The charm of life was gone; there
+was nothing but dreariness left. He put his hoop away, and his bat;
+there was no joy in them any more. His aunt was concerned. She began to
+try all manner of remedies on him. She was one of those people who are
+infatuated with patent medicines and all new-fangled methods of
+producing health or mending it. She was an inveterate experimenter in
+these things. When something fresh in this line came out she was in a
+fever, right away, to try it; not on herself, for she was never ailing,
+but on anybody else that came handy. She was a subscriber for all the
+"Health" periodicals and phrenological frauds; and the solemn ignorance
+they were inflated with was breath to her nostrils. All the "rot" they
+contained about ventilation, and how to go to bed, and how to get up,
+and what to eat, and what to drink, and how much exercise to take, and
+what frame of mind to keep one's self in, and what sort of clothing to
+wear, was all gospel to her, and she never observed that her
+health-journals of the current month customarily upset everything they
+had recommended the month before. She was as simple-hearted and honest
+as the day was long, and so she was an easy victim. She gathered
+together her quack periodicals and her quack medicines, and thus armed
+with death, went about on her pale horse, metaphorically speaking, with
+"hell following after." But she never suspected that she was not an
+angel of healing and the balm of Gilead in disguise, to the suffering
+neighbors.
+
+The water treatment was new, now, and Tom's low condition was a
+windfall to her. She had him out at daylight every morning, stood him
+up in the woodshed and drowned him with a deluge of cold water; then
+she scrubbed him down with a towel like a file, and so brought him to;
+then she rolled him up in a wet sheet and put him away under blankets
+till she sweated his soul clean and "the yellow stains of it came
+through his pores"--as Tom said.
+
+Yet notwithstanding all this, the boy grew more and more melancholy
+and pale and dejected. She added hot baths, sitz baths, shower baths,
+and plunges. The boy remained as dismal as a hearse. She began to
+assist the water with a slim oatmeal diet and blister-plasters. She
+calculated his capacity as she would a jug's, and filled him up every
+day with quack cure-alls.
+
+Tom had become indifferent to persecution by this time. This phase
+filled the old lady's heart with consternation. This indifference must
+be broken up at any cost. Now she heard of Pain-killer for the first
+time. She ordered a lot at once. She tasted it and was filled with
+gratitude. It was simply fire in a liquid form. She dropped the water
+treatment and everything else, and pinned her faith to Pain-killer. She
+gave Tom a teaspoonful and watched with the deepest anxiety for the
+result. Her troubles were instantly at rest, her soul at peace again;
+for the "indifference" was broken up. The boy could not have shown a
+wilder, heartier interest, if she had built a fire under him.
+
+Tom felt that it was time to wake up; this sort of life might be
+romantic enough, in his blighted condition, but it was getting to have
+too little sentiment and too much distracting variety about it. So he
+thought over various plans for relief, and finally hit pon that of
+professing to be fond of Pain-killer. He asked for it so often that he
+became a nuisance, and his aunt ended by telling him to help himself
+and quit bothering her. If it had been Sid, she would have had no
+misgivings to alloy her delight; but since it was Tom, she watched the
+bottle clandestinely. She found that the medicine did really diminish,
+but it did not occur to her that the boy was mending the health of a
+crack in the sitting-room floor with it.
+
+One day Tom was in the act of dosing the crack when his aunt's yellow
+cat came along, purring, eying the teaspoon avariciously, and begging
+for a taste. Tom said:
+
+"Don't ask for it unless you want it, Peter."
+
+But Peter signified that he did want it.
+
+"You better make sure."
+
+Peter was sure.
+
+"Now you've asked for it, and I'll give it to you, because there ain't
+anything mean about me; but if you find you don't like it, you mustn't
+blame anybody but your own self."
+
+Peter was agreeable. So Tom pried his mouth open and poured down the
+Pain-killer. Peter sprang a couple of yards in the air, and then
+delivered a war-whoop and set off round and round the room, banging
+against furniture, upsetting flower-pots, and making general havoc.
+Next he rose on his hind feet and pranced around, in a frenzy of
+enjoyment, with his head over his shoulder and his voice proclaiming
+his unappeasable happiness. Then he went tearing around the house again
+spreading chaos and destruction in his path. Aunt Polly entered in time
+to see him throw a few double summersets, deliver a final mighty
+hurrah, and sail through the open window, carrying the rest of the
+flower-pots with him. The old lady stood petrified with astonishment,
+peering over her glasses; Tom lay on the floor expiring with laughter.
+
+"Tom, what on earth ails that cat?"
+
+"I don't know, aunt," gasped the boy.
+
+"Why, I never see anything like it. What did make him act so?"
+
+"Deed I don't know, Aunt Polly; cats always act so when they're having
+a good time."
+
+"They do, do they?" There was something in the tone that made Tom
+apprehensive.
+
+"Yes'm. That is, I believe they do."
+
+"You DO?"
+
+"Yes'm."
+
+The old lady was bending down, Tom watching, with interest emphasized
+by anxiety. Too late he divined her "drift." The handle of the telltale
+teaspoon was visible under the bed-valance. Aunt Polly took it, held it
+up. Tom winced, and dropped his eyes. Aunt Polly raised him by the
+usual handle--his ear--and cracked his head soundly with her thimble.
+
+"Now, sir, what did you want to treat that poor dumb beast so, for?"
+
+"I done it out of pity for him--because he hadn't any aunt."
+
+"Hadn't any aunt!--you numskull. What has that got to do with it?"
+
+"Heaps. Because if he'd had one she'd a burnt him out herself! She'd a
+roasted his bowels out of him 'thout any more feeling than if he was a
+human!"
+
+Aunt Polly felt a sudden pang of remorse. This was putting the thing
+in a new light; what was cruelty to a cat MIGHT be cruelty to a boy,
+too. She began to soften; she felt sorry. Her eyes watered a little,
+and she put her hand on Tom's head and said gently:
+
+"I was meaning for the best, Tom. And, Tom, it DID do you good."
+
+Tom looked up in her face with just a perceptible twinkle peeping
+through his gravity.
+
+"I know you was meaning for the best, aunty, and so was I with Peter.
+It done HIM good, too. I never see him get around so since--"
+
+"Oh, go 'long with you, Tom, before you aggravate me again. And you
+try and see if you can't be a good boy, for once, and you needn't take
+any more medicine."
+
+Tom reached school ahead of time. It was noticed that this strange
+thing had been occurring every day latterly. And now, as usual of late,
+he hung about the gate of the schoolyard instead of playing with his
+comrades. He was sick, he said, and he looked it. He tried to seem to
+be looking everywhere but whither he really was looking--down the road.
+Presently Jeff Thatcher hove in sight, and Tom's face lighted; he gazed
+a moment, and then turned sorrowfully away. When Jeff arrived, Tom
+accosted him; and "led up" warily to opportunities for remark about
+Becky, but the giddy lad never could see the bait. Tom watched and
+watched, hoping whenever a frisking frock came in sight, and hating the
+owner of it as soon as he saw she was not the right one. At last frocks
+ceased to appear, and he dropped hopelessly into the dumps; he entered
+the empty schoolhouse and sat down to suffer. Then one more frock
+passed in at the gate, and Tom's heart gave a great bound. The next
+instant he was out, and "going on" like an Indian; yelling, laughing,
+chasing boys, jumping over the fence at risk of life and limb, throwing
+handsprings, standing on his head--doing all the heroic things he could
+conceive of, and keeping a furtive eye out, all the while, to see if
+Becky Thatcher was noticing. But she seemed to be unconscious of it
+all; she never looked. Could it be possible that she was not aware that
+he was there? He carried his exploits to her immediate vicinity; came
+war-whooping around, snatched a boy's cap, hurled it to the roof of the
+schoolhouse, broke through a group of boys, tumbling them in every
+direction, and fell sprawling, himself, under Becky's nose, almost
+upsetting her--and she turned, with her nose in the air, and he heard
+her say: "Mf! some people think they're mighty smart--always showing
+off!"
+
+Tom's cheeks burned. He gathered himself up and sneaked off, crushed
+and crestfallen.
+
+
+
+CHAPTER XIII
+
+TOM'S mind was made up now. He was gloomy and desperate. He was a
+forsaken, friendless boy, he said; nobody loved him; when they found
+out what they had driven him to, perhaps they would be sorry; he had
+tried to do right and get along, but they would not let him; since
+nothing would do them but to be rid of him, let it be so; and let them
+blame HIM for the consequences--why shouldn't they? What right had the
+friendless to complain? Yes, they had forced him to it at last: he
+would lead a life of crime. There was no choice.
+
+By this time he was far down Meadow Lane, and the bell for school to
+"take up" tinkled faintly upon his ear. He sobbed, now, to think he
+should never, never hear that old familiar sound any more--it was very
+hard, but it was forced on him; since he was driven out into the cold
+world, he must submit--but he forgave them. Then the sobs came thick
+and fast.
+
+Just at this point he met his soul's sworn comrade, Joe Harper
+--hard-eyed, and with evidently a great and dismal purpose in his heart.
+Plainly here were "two souls with but a single thought." Tom, wiping
+his eyes with his sleeve, began to blubber out something about a
+resolution to escape from hard usage and lack of sympathy at home by
+roaming abroad into the great world never to return; and ended by
+hoping that Joe would not forget him.
+
+But it transpired that this was a request which Joe had just been
+going to make of Tom, and had come to hunt him up for that purpose. His
+mother had whipped him for drinking some cream which he had never
+tasted and knew nothing about; it was plain that she was tired of him
+and wished him to go; if she felt that way, there was nothing for him
+to do but succumb; he hoped she would be happy, and never regret having
+driven her poor boy out into the unfeeling world to suffer and die.
+
+As the two boys walked sorrowing along, they made a new compact to
+stand by each other and be brothers and never separate till death
+relieved them of their troubles. Then they began to lay their plans.
+Joe was for being a hermit, and living on crusts in a remote cave, and
+dying, some time, of cold and want and grief; but after listening to
+Tom, he conceded that there were some conspicuous advantages about a
+life of crime, and so he consented to be a pirate.
+
+Three miles below St. Petersburg, at a point where the Mississippi
+River was a trifle over a mile wide, there was a long, narrow, wooded
+island, with a shallow bar at the head of it, and this offered well as
+a rendezvous. It was not inhabited; it lay far over toward the further
+shore, abreast a dense and almost wholly unpeopled forest. So Jackson's
+Island was chosen. Who were to be the subjects of their piracies was a
+matter that did not occur to them. Then they hunted up Huckleberry
+Finn, and he joined them promptly, for all careers were one to him; he
+was indifferent. They presently separated to meet at a lonely spot on
+the river-bank two miles above the village at the favorite hour--which
+was midnight. There was a small log raft there which they meant to
+capture. Each would bring hooks and lines, and such provision as he
+could steal in the most dark and mysterious way--as became outlaws. And
+before the afternoon was done, they had all managed to enjoy the sweet
+glory of spreading the fact that pretty soon the town would "hear
+something." All who got this vague hint were cautioned to "be mum and
+wait."
+
+About midnight Tom arrived with a boiled ham and a few trifles,
+and stopped in a dense undergrowth on a small bluff overlooking the
+meeting-place. It was starlight, and very still. The mighty river lay
+like an ocean at rest. Tom listened a moment, but no sound disturbed the
+quiet. Then he gave a low, distinct whistle. It was answered from under
+the bluff. Tom whistled twice more; these signals were answered in the
+same way. Then a guarded voice said:
+
+"Who goes there?"
+
+"Tom Sawyer, the Black Avenger of the Spanish Main. Name your names."
+
+"Huck Finn the Red-Handed, and Joe Harper the Terror of the Seas." Tom
+had furnished these titles, from his favorite literature.
+
+"'Tis well. Give the countersign."
+
+Two hoarse whispers delivered the same awful word simultaneously to
+the brooding night:
+
+"BLOOD!"
+
+Then Tom tumbled his ham over the bluff and let himself down after it,
+tearing both skin and clothes to some extent in the effort. There was
+an easy, comfortable path along the shore under the bluff, but it
+lacked the advantages of difficulty and danger so valued by a pirate.
+
+The Terror of the Seas had brought a side of bacon, and had about worn
+himself out with getting it there. Finn the Red-Handed had stolen a
+skillet and a quantity of half-cured leaf tobacco, and had also brought
+a few corn-cobs to make pipes with. But none of the pirates smoked or
+"chewed" but himself. The Black Avenger of the Spanish Main said it
+would never do to start without some fire. That was a wise thought;
+matches were hardly known there in that day. They saw a fire
+smouldering upon a great raft a hundred yards above, and they went
+stealthily thither and helped themselves to a chunk. They made an
+imposing adventure of it, saying, "Hist!" every now and then, and
+suddenly halting with finger on lip; moving with hands on imaginary
+dagger-hilts; and giving orders in dismal whispers that if "the foe"
+stirred, to "let him have it to the hilt," because "dead men tell no
+tales." They knew well enough that the raftsmen were all down at the
+village laying in stores or having a spree, but still that was no
+excuse for their conducting this thing in an unpiratical way.
+
+They shoved off, presently, Tom in command, Huck at the after oar and
+Joe at the forward. Tom stood amidships, gloomy-browed, and with folded
+arms, and gave his orders in a low, stern whisper:
+
+"Luff, and bring her to the wind!"
+
+"Aye-aye, sir!"
+
+"Steady, steady-y-y-y!"
+
+"Steady it is, sir!"
+
+"Let her go off a point!"
+
+"Point it is, sir!"
+
+As the boys steadily and monotonously drove the raft toward mid-stream
+it was no doubt understood that these orders were given only for
+"style," and were not intended to mean anything in particular.
+
+"What sail's she carrying?"
+
+"Courses, tops'ls, and flying-jib, sir."
+
+"Send the r'yals up! Lay out aloft, there, half a dozen of ye
+--foretopmaststuns'l! Lively, now!"
+
+"Aye-aye, sir!"
+
+"Shake out that maintogalans'l! Sheets and braces! NOW my hearties!"
+
+"Aye-aye, sir!"
+
+"Hellum-a-lee--hard a port! Stand by to meet her when she comes! Port,
+port! NOW, men! With a will! Stead-y-y-y!"
+
+"Steady it is, sir!"
+
+The raft drew beyond the middle of the river; the boys pointed her
+head right, and then lay on their oars. The river was not high, so
+there was not more than a two or three mile current. Hardly a word was
+said during the next three-quarters of an hour. Now the raft was
+passing before the distant town. Two or three glimmering lights showed
+where it lay, peacefully sleeping, beyond the vague vast sweep of
+star-gemmed water, unconscious of the tremendous event that was happening.
+The Black Avenger stood still with folded arms, "looking his last" upon
+the scene of his former joys and his later sufferings, and wishing
+"she" could see him now, abroad on the wild sea, facing peril and death
+with dauntless heart, going to his doom with a grim smile on his lips.
+It was but a small strain on his imagination to remove Jackson's Island
+beyond eyeshot of the village, and so he "looked his last" with a
+broken and satisfied heart. The other pirates were looking their last,
+too; and they all looked so long that they came near letting the
+current drift them out of the range of the island. But they discovered
+the danger in time, and made shift to avert it. About two o'clock in
+the morning the raft grounded on the bar two hundred yards above the
+head of the island, and they waded back and forth until they had landed
+their freight. Part of the little raft's belongings consisted of an old
+sail, and this they spread over a nook in the bushes for a tent to
+shelter their provisions; but they themselves would sleep in the open
+air in good weather, as became outlaws.
+
+They built a fire against the side of a great log twenty or thirty
+steps within the sombre depths of the forest, and then cooked some
+bacon in the frying-pan for supper, and used up half of the corn "pone"
+stock they had brought. It seemed glorious sport to be feasting in that
+wild, free way in the virgin forest of an unexplored and uninhabited
+island, far from the haunts of men, and they said they never would
+return to civilization. The climbing fire lit up their faces and threw
+its ruddy glare upon the pillared tree-trunks of their forest temple,
+and upon the varnished foliage and festooning vines.
+
+When the last crisp slice of bacon was gone, and the last allowance of
+corn pone devoured, the boys stretched themselves out on the grass,
+filled with contentment. They could have found a cooler place, but they
+would not deny themselves such a romantic feature as the roasting
+camp-fire.
+
+"AIN'T it gay?" said Joe.
+
+"It's NUTS!" said Tom. "What would the boys say if they could see us?"
+
+"Say? Well, they'd just die to be here--hey, Hucky!"
+
+"I reckon so," said Huckleberry; "anyways, I'm suited. I don't want
+nothing better'n this. I don't ever get enough to eat, gen'ally--and
+here they can't come and pick at a feller and bullyrag him so."
+
+"It's just the life for me," said Tom. "You don't have to get up,
+mornings, and you don't have to go to school, and wash, and all that
+blame foolishness. You see a pirate don't have to do ANYTHING, Joe,
+when he's ashore, but a hermit HE has to be praying considerable, and
+then he don't have any fun, anyway, all by himself that way."
+
+"Oh yes, that's so," said Joe, "but I hadn't thought much about it,
+you know. I'd a good deal rather be a pirate, now that I've tried it."
+
+"You see," said Tom, "people don't go much on hermits, nowadays, like
+they used to in old times, but a pirate's always respected. And a
+hermit's got to sleep on the hardest place he can find, and put
+sackcloth and ashes on his head, and stand out in the rain, and--"
+
+"What does he put sackcloth and ashes on his head for?" inquired Huck.
+
+"I dono. But they've GOT to do it. Hermits always do. You'd have to do
+that if you was a hermit."
+
+"Dern'd if I would," said Huck.
+
+"Well, what would you do?"
+
+"I dono. But I wouldn't do that."
+
+"Why, Huck, you'd HAVE to. How'd you get around it?"
+
+"Why, I just wouldn't stand it. I'd run away."
+
+"Run away! Well, you WOULD be a nice old slouch of a hermit. You'd be
+a disgrace."
+
+The Red-Handed made no response, being better employed. He had
+finished gouging out a cob, and now he fitted a weed stem to it, loaded
+it with tobacco, and was pressing a coal to the charge and blowing a
+cloud of fragrant smoke--he was in the full bloom of luxurious
+contentment. The other pirates envied him this majestic vice, and
+secretly resolved to acquire it shortly. Presently Huck said:
+
+"What does pirates have to do?"
+
+Tom said:
+
+"Oh, they have just a bully time--take ships and burn them, and get
+the money and bury it in awful places in their island where there's
+ghosts and things to watch it, and kill everybody in the ships--make
+'em walk a plank."
+
+"And they carry the women to the island," said Joe; "they don't kill
+the women."
+
+"No," assented Tom, "they don't kill the women--they're too noble. And
+the women's always beautiful, too.
+
+"And don't they wear the bulliest clothes! Oh no! All gold and silver
+and di'monds," said Joe, with enthusiasm.
+
+"Who?" said Huck.
+
+"Why, the pirates."
+
+Huck scanned his own clothing forlornly.
+
+"I reckon I ain't dressed fitten for a pirate," said he, with a
+regretful pathos in his voice; "but I ain't got none but these."
+
+But the other boys told him the fine clothes would come fast enough,
+after they should have begun their adventures. They made him understand
+that his poor rags would do to begin with, though it was customary for
+wealthy pirates to start with a proper wardrobe.
+
+Gradually their talk died out and drowsiness began to steal upon the
+eyelids of the little waifs. The pipe dropped from the fingers of the
+Red-Handed, and he slept the sleep of the conscience-free and the
+weary. The Terror of the Seas and the Black Avenger of the Spanish Main
+had more difficulty in getting to sleep. They said their prayers
+inwardly, and lying down, since there was nobody there with authority
+to make them kneel and recite aloud; in truth, they had a mind not to
+say them at all, but they were afraid to proceed to such lengths as
+that, lest they might call down a sudden and special thunderbolt from
+heaven. Then at once they reached and hovered upon the imminent verge
+of sleep--but an intruder came, now, that would not "down." It was
+conscience. They began to feel a vague fear that they had been doing
+wrong to run away; and next they thought of the stolen meat, and then
+the real torture came. They tried to argue it away by reminding
+conscience that they had purloined sweetmeats and apples scores of
+times; but conscience was not to be appeased by such thin
+plausibilities; it seemed to them, in the end, that there was no
+getting around the stubborn fact that taking sweetmeats was only
+"hooking," while taking bacon and hams and such valuables was plain
+simple stealing--and there was a command against that in the Bible. So
+they inwardly resolved that so long as they remained in the business,
+their piracies should not again be sullied with the crime of stealing.
+Then conscience granted a truce, and these curiously inconsistent
+pirates fell peacefully to sleep.
+
+
+
+CHAPTER XIV
+
+WHEN Tom awoke in the morning, he wondered where he was. He sat up and
+rubbed his eyes and looked around. Then he comprehended. It was the
+cool gray dawn, and there was a delicious sense of repose and peace in
+the deep pervading calm and silence of the woods. Not a leaf stirred;
+not a sound obtruded upon great Nature's meditation. Beaded dewdrops
+stood upon the leaves and grasses. A white layer of ashes covered the
+fire, and a thin blue breath of smoke rose straight into the air. Joe
+and Huck still slept.
+
+Now, far away in the woods a bird called; another answered; presently
+the hammering of a woodpecker was heard. Gradually the cool dim gray of
+the morning whitened, and as gradually sounds multiplied and life
+manifested itself. The marvel of Nature shaking off sleep and going to
+work unfolded itself to the musing boy. A little green worm came
+crawling over a dewy leaf, lifting two-thirds of his body into the air
+from time to time and "sniffing around," then proceeding again--for he
+was measuring, Tom said; and when the worm approached him, of its own
+accord, he sat as still as a stone, with his hopes rising and falling,
+by turns, as the creature still came toward him or seemed inclined to
+go elsewhere; and when at last it considered a painful moment with its
+curved body in the air and then came decisively down upon Tom's leg and
+began a journey over him, his whole heart was glad--for that meant that
+he was going to have a new suit of clothes--without the shadow of a
+doubt a gaudy piratical uniform. Now a procession of ants appeared,
+from nowhere in particular, and went about their labors; one struggled
+manfully by with a dead spider five times as big as itself in its arms,
+and lugged it straight up a tree-trunk. A brown spotted lady-bug
+climbed the dizzy height of a grass blade, and Tom bent down close to
+it and said, "Lady-bug, lady-bug, fly away home, your house is on fire,
+your children's alone," and she took wing and went off to see about it
+--which did not surprise the boy, for he knew of old that this insect was
+credulous about conflagrations, and he had practised upon its
+simplicity more than once. A tumblebug came next, heaving sturdily at
+its ball, and Tom touched the creature, to see it shut its legs against
+its body and pretend to be dead. The birds were fairly rioting by this
+time. A catbird, the Northern mocker, lit in a tree over Tom's head,
+and trilled out her imitations of her neighbors in a rapture of
+enjoyment; then a shrill jay swept down, a flash of blue flame, and
+stopped on a twig almost within the boy's reach, cocked his head to one
+side and eyed the strangers with a consuming curiosity; a gray squirrel
+and a big fellow of the "fox" kind came skurrying along, sitting up at
+intervals to inspect and chatter at the boys, for the wild things had
+probably never seen a human being before and scarcely knew whether to
+be afraid or not. All Nature was wide awake and stirring, now; long
+lances of sunlight pierced down through the dense foliage far and near,
+and a few butterflies came fluttering upon the scene.
+
+Tom stirred up the other pirates and they all clattered away with a
+shout, and in a minute or two were stripped and chasing after and
+tumbling over each other in the shallow limpid water of the white
+sandbar. They felt no longing for the little village sleeping in the
+distance beyond the majestic waste of water. A vagrant current or a
+slight rise in the river had carried off their raft, but this only
+gratified them, since its going was something like burning the bridge
+between them and civilization.
+
+They came back to camp wonderfully refreshed, glad-hearted, and
+ravenous; and they soon had the camp-fire blazing up again. Huck found
+a spring of clear cold water close by, and the boys made cups of broad
+oak or hickory leaves, and felt that water, sweetened with such a
+wildwood charm as that, would be a good enough substitute for coffee.
+While Joe was slicing bacon for breakfast, Tom and Huck asked him to
+hold on a minute; they stepped to a promising nook in the river-bank
+and threw in their lines; almost immediately they had reward. Joe had
+not had time to get impatient before they were back again with some
+handsome bass, a couple of sun-perch and a small catfish--provisions
+enough for quite a family. They fried the fish with the bacon, and were
+astonished; for no fish had ever seemed so delicious before. They did
+not know that the quicker a fresh-water fish is on the fire after he is
+caught the better he is; and they reflected little upon what a sauce
+open-air sleeping, open-air exercise, bathing, and a large ingredient
+of hunger make, too.
+
+They lay around in the shade, after breakfast, while Huck had a smoke,
+and then went off through the woods on an exploring expedition. They
+tramped gayly along, over decaying logs, through tangled underbrush,
+among solemn monarchs of the forest, hung from their crowns to the
+ground with a drooping regalia of grape-vines. Now and then they came
+upon snug nooks carpeted with grass and jeweled with flowers.
+
+They found plenty of things to be delighted with, but nothing to be
+astonished at. They discovered that the island was about three miles
+long and a quarter of a mile wide, and that the shore it lay closest to
+was only separated from it by a narrow channel hardly two hundred yards
+wide. They took a swim about every hour, so it was close upon the
+middle of the afternoon when they got back to camp. They were too
+hungry to stop to fish, but they fared sumptuously upon cold ham, and
+then threw themselves down in the shade to talk. But the talk soon
+began to drag, and then died. The stillness, the solemnity that brooded
+in the woods, and the sense of loneliness, began to tell upon the
+spirits of the boys. They fell to thinking. A sort of undefined longing
+crept upon them. This took dim shape, presently--it was budding
+homesickness. Even Finn the Red-Handed was dreaming of his doorsteps
+and empty hogsheads. But they were all ashamed of their weakness, and
+none was brave enough to speak his thought.
+
+For some time, now, the boys had been dully conscious of a peculiar
+sound in the distance, just as one sometimes is of the ticking of a
+clock which he takes no distinct note of. But now this mysterious sound
+became more pronounced, and forced a recognition. The boys started,
+glanced at each other, and then each assumed a listening attitude.
+There was a long silence, profound and unbroken; then a deep, sullen
+boom came floating down out of the distance.
+
+"What is it!" exclaimed Joe, under his breath.
+
+"I wonder," said Tom in a whisper.
+
+"'Tain't thunder," said Huckleberry, in an awed tone, "becuz thunder--"
+
+"Hark!" said Tom. "Listen--don't talk."
+
+They waited a time that seemed an age, and then the same muffled boom
+troubled the solemn hush.
+
+"Let's go and see."
+
+They sprang to their feet and hurried to the shore toward the town.
+They parted the bushes on the bank and peered out over the water. The
+little steam ferryboat was about a mile below the village, drifting
+with the current. Her broad deck seemed crowded with people. There were
+a great many skiffs rowing about or floating with the stream in the
+neighborhood of the ferryboat, but the boys could not determine what
+the men in them were doing. Presently a great jet of white smoke burst
+from the ferryboat's side, and as it expanded and rose in a lazy cloud,
+that same dull throb of sound was borne to the listeners again.
+
+"I know now!" exclaimed Tom; "somebody's drownded!"
+
+"That's it!" said Huck; "they done that last summer, when Bill Turner
+got drownded; they shoot a cannon over the water, and that makes him
+come up to the top. Yes, and they take loaves of bread and put
+quicksilver in 'em and set 'em afloat, and wherever there's anybody
+that's drownded, they'll float right there and stop."
+
+"Yes, I've heard about that," said Joe. "I wonder what makes the bread
+do that."
+
+"Oh, it ain't the bread, so much," said Tom; "I reckon it's mostly
+what they SAY over it before they start it out."
+
+"But they don't say anything over it," said Huck. "I've seen 'em and
+they don't."
+
+"Well, that's funny," said Tom. "But maybe they say it to themselves.
+Of COURSE they do. Anybody might know that."
+
+The other boys agreed that there was reason in what Tom said, because
+an ignorant lump of bread, uninstructed by an incantation, could not be
+expected to act very intelligently when set upon an errand of such
+gravity.
+
+"By jings, I wish I was over there, now," said Joe.
+
+"I do too" said Huck "I'd give heaps to know who it is."
+
+The boys still listened and watched. Presently a revealing thought
+flashed through Tom's mind, and he exclaimed:
+
+"Boys, I know who's drownded--it's us!"
+
+They felt like heroes in an instant. Here was a gorgeous triumph; they
+were missed; they were mourned; hearts were breaking on their account;
+tears were being shed; accusing memories of unkindness to these poor
+lost lads were rising up, and unavailing regrets and remorse were being
+indulged; and best of all, the departed were the talk of the whole
+town, and the envy of all the boys, as far as this dazzling notoriety
+was concerned. This was fine. It was worth while to be a pirate, after
+all.
+
+As twilight drew on, the ferryboat went back to her accustomed
+business and the skiffs disappeared. The pirates returned to camp. They
+were jubilant with vanity over their new grandeur and the illustrious
+trouble they were making. They caught fish, cooked supper and ate it,
+and then fell to guessing at what the village was thinking and saying
+about them; and the pictures they drew of the public distress on their
+account were gratifying to look upon--from their point of view. But
+when the shadows of night closed them in, they gradually ceased to
+talk, and sat gazing into the fire, with their minds evidently
+wandering elsewhere. The excitement was gone, now, and Tom and Joe
+could not keep back thoughts of certain persons at home who were not
+enjoying this fine frolic as much as they were. Misgivings came; they
+grew troubled and unhappy; a sigh or two escaped, unawares. By and by
+Joe timidly ventured upon a roundabout "feeler" as to how the others
+might look upon a return to civilization--not right now, but--
+
+Tom withered him with derision! Huck, being uncommitted as yet, joined
+in with Tom, and the waverer quickly "explained," and was glad to get
+out of the scrape with as little taint of chicken-hearted homesickness
+clinging to his garments as he could. Mutiny was effectually laid to
+rest for the moment.
+
+As the night deepened, Huck began to nod, and presently to snore. Joe
+followed next. Tom lay upon his elbow motionless, for some time,
+watching the two intently. At last he got up cautiously, on his knees,
+and went searching among the grass and the flickering reflections flung
+by the camp-fire. He picked up and inspected several large
+semi-cylinders of the thin white bark of a sycamore, and finally chose
+two which seemed to suit him. Then he knelt by the fire and painfully
+wrote something upon each of these with his "red keel"; one he rolled up
+and put in his jacket pocket, and the other he put in Joe's hat and
+removed it to a little distance from the owner. And he also put into the
+hat certain schoolboy treasures of almost inestimable value--among them
+a lump of chalk, an India-rubber ball, three fishhooks, and one of that
+kind of marbles known as a "sure 'nough crystal." Then he tiptoed his
+way cautiously among the trees till he felt that he was out of hearing,
+and straightway broke into a keen run in the direction of the sandbar.
+
+
+
+CHAPTER XV
+
+A FEW minutes later Tom was in the shoal water of the bar, wading
+toward the Illinois shore. Before the depth reached his middle he was
+half-way over; the current would permit no more wading, now, so he
+struck out confidently to swim the remaining hundred yards. He swam
+quartering upstream, but still was swept downward rather faster than he
+had expected. However, he reached the shore finally, and drifted along
+till he found a low place and drew himself out. He put his hand on his
+jacket pocket, found his piece of bark safe, and then struck through
+the woods, following the shore, with streaming garments. Shortly before
+ten o'clock he came out into an open place opposite the village, and
+saw the ferryboat lying in the shadow of the trees and the high bank.
+Everything was quiet under the blinking stars. He crept down the bank,
+watching with all his eyes, slipped into the water, swam three or four
+strokes and climbed into the skiff that did "yawl" duty at the boat's
+stern. He laid himself down under the thwarts and waited, panting.
+
+Presently the cracked bell tapped and a voice gave the order to "cast
+off." A minute or two later the skiff's head was standing high up,
+against the boat's swell, and the voyage was begun. Tom felt happy in
+his success, for he knew it was the boat's last trip for the night. At
+the end of a long twelve or fifteen minutes the wheels stopped, and Tom
+slipped overboard and swam ashore in the dusk, landing fifty yards
+downstream, out of danger of possible stragglers.
+
+He flew along unfrequented alleys, and shortly found himself at his
+aunt's back fence. He climbed over, approached the "ell," and looked in
+at the sitting-room window, for a light was burning there. There sat
+Aunt Polly, Sid, Mary, and Joe Harper's mother, grouped together,
+talking. They were by the bed, and the bed was between them and the
+door. Tom went to the door and began to softly lift the latch; then he
+pressed gently and the door yielded a crack; he continued pushing
+cautiously, and quaking every time it creaked, till he judged he might
+squeeze through on his knees; so he put his head through and began,
+warily.
+
+"What makes the candle blow so?" said Aunt Polly. Tom hurried up.
+"Why, that door's open, I believe. Why, of course it is. No end of
+strange things now. Go 'long and shut it, Sid."
+
+Tom disappeared under the bed just in time. He lay and "breathed"
+himself for a time, and then crept to where he could almost touch his
+aunt's foot.
+
+"But as I was saying," said Aunt Polly, "he warn't BAD, so to say
+--only mischEEvous. Only just giddy, and harum-scarum, you know. He
+warn't any more responsible than a colt. HE never meant any harm, and
+he was the best-hearted boy that ever was"--and she began to cry.
+
+"It was just so with my Joe--always full of his devilment, and up to
+every kind of mischief, but he was just as unselfish and kind as he
+could be--and laws bless me, to think I went and whipped him for taking
+that cream, never once recollecting that I throwed it out myself
+because it was sour, and I never to see him again in this world, never,
+never, never, poor abused boy!" And Mrs. Harper sobbed as if her heart
+would break.
+
+"I hope Tom's better off where he is," said Sid, "but if he'd been
+better in some ways--"
+
+"SID!" Tom felt the glare of the old lady's eye, though he could not
+see it. "Not a word against my Tom, now that he's gone! God'll take
+care of HIM--never you trouble YOURself, sir! Oh, Mrs. Harper, I don't
+know how to give him up! I don't know how to give him up! He was such a
+comfort to me, although he tormented my old heart out of me, 'most."
+
+"The Lord giveth and the Lord hath taken away--Blessed be the name of
+the Lord! But it's so hard--Oh, it's so hard! Only last Saturday my
+Joe busted a firecracker right under my nose and I knocked him
+sprawling. Little did I know then, how soon--Oh, if it was to do over
+again I'd hug him and bless him for it."
+
+"Yes, yes, yes, I know just how you feel, Mrs. Harper, I know just
+exactly how you feel. No longer ago than yesterday noon, my Tom took
+and filled the cat full of Pain-killer, and I did think the cretur
+would tear the house down. And God forgive me, I cracked Tom's head
+with my thimble, poor boy, poor dead boy. But he's out of all his
+troubles now. And the last words I ever heard him say was to reproach--"
+
+But this memory was too much for the old lady, and she broke entirely
+down. Tom was snuffling, now, himself--and more in pity of himself than
+anybody else. He could hear Mary crying, and putting in a kindly word
+for him from time to time. He began to have a nobler opinion of himself
+than ever before. Still, he was sufficiently touched by his aunt's
+grief to long to rush out from under the bed and overwhelm her with
+joy--and the theatrical gorgeousness of the thing appealed strongly to
+his nature, too, but he resisted and lay still.
+
+He went on listening, and gathered by odds and ends that it was
+conjectured at first that the boys had got drowned while taking a swim;
+then the small raft had been missed; next, certain boys said the
+missing lads had promised that the village should "hear something"
+soon; the wise-heads had "put this and that together" and decided that
+the lads had gone off on that raft and would turn up at the next town
+below, presently; but toward noon the raft had been found, lodged
+against the Missouri shore some five or six miles below the village
+--and then hope perished; they must be drowned, else hunger would have
+driven them home by nightfall if not sooner. It was believed that the
+search for the bodies had been a fruitless effort merely because the
+drowning must have occurred in mid-channel, since the boys, being good
+swimmers, would otherwise have escaped to shore. This was Wednesday
+night. If the bodies continued missing until Sunday, all hope would be
+given over, and the funerals would be preached on that morning. Tom
+shuddered.
+
+Mrs. Harper gave a sobbing good-night and turned to go. Then with a
+mutual impulse the two bereaved women flung themselves into each
+other's arms and had a good, consoling cry, and then parted. Aunt Polly
+was tender far beyond her wont, in her good-night to Sid and Mary. Sid
+snuffled a bit and Mary went off crying with all her heart.
+
+Aunt Polly knelt down and prayed for Tom so touchingly, so
+appealingly, and with such measureless love in her words and her old
+trembling voice, that he was weltering in tears again, long before she
+was through.
+
+He had to keep still long after she went to bed, for she kept making
+broken-hearted ejaculations from time to time, tossing unrestfully, and
+turning over. But at last she was still, only moaning a little in her
+sleep. Now the boy stole out, rose gradually by the bedside, shaded the
+candle-light with his hand, and stood regarding her. His heart was full
+of pity for her. He took out his sycamore scroll and placed it by the
+candle. But something occurred to him, and he lingered considering. His
+face lighted with a happy solution of his thought; he put the bark
+hastily in his pocket. Then he bent over and kissed the faded lips, and
+straightway made his stealthy exit, latching the door behind him.
+
+He threaded his way back to the ferry landing, found nobody at large
+there, and walked boldly on board the boat, for he knew she was
+tenantless except that there was a watchman, who always turned in and
+slept like a graven image. He untied the skiff at the stern, slipped
+into it, and was soon rowing cautiously upstream. When he had pulled a
+mile above the village, he started quartering across and bent himself
+stoutly to his work. He hit the landing on the other side neatly, for
+this was a familiar bit of work to him. He was moved to capture the
+skiff, arguing that it might be considered a ship and therefore
+legitimate prey for a pirate, but he knew a thorough search would be
+made for it and that might end in revelations. So he stepped ashore and
+entered the woods.
+
+He sat down and took a long rest, torturing himself meanwhile to keep
+awake, and then started warily down the home-stretch. The night was far
+spent. It was broad daylight before he found himself fairly abreast the
+island bar. He rested again until the sun was well up and gilding the
+great river with its splendor, and then he plunged into the stream. A
+little later he paused, dripping, upon the threshold of the camp, and
+heard Joe say:
+
+"No, Tom's true-blue, Huck, and he'll come back. He won't desert. He
+knows that would be a disgrace to a pirate, and Tom's too proud for
+that sort of thing. He's up to something or other. Now I wonder what?"
+
+"Well, the things is ours, anyway, ain't they?"
+
+"Pretty near, but not yet, Huck. The writing says they are if he ain't
+back here to breakfast."
+
+"Which he is!" exclaimed Tom, with fine dramatic effect, stepping
+grandly into camp.
+
+A sumptuous breakfast of bacon and fish was shortly provided, and as
+the boys set to work upon it, Tom recounted (and adorned) his
+adventures. They were a vain and boastful company of heroes when the
+tale was done. Then Tom hid himself away in a shady nook to sleep till
+noon, and the other pirates got ready to fish and explore.
+
+
+
+CHAPTER XVI
+
+AFTER dinner all the gang turned out to hunt for turtle eggs on the
+bar. They went about poking sticks into the sand, and when they found a
+soft place they went down on their knees and dug with their hands.
+Sometimes they would take fifty or sixty eggs out of one hole. They
+were perfectly round white things a trifle smaller than an English
+walnut. They had a famous fried-egg feast that night, and another on
+Friday morning.
+
+After breakfast they went whooping and prancing out on the bar, and
+chased each other round and round, shedding clothes as they went, until
+they were naked, and then continued the frolic far away up the shoal
+water of the bar, against the stiff current, which latter tripped their
+legs from under them from time to time and greatly increased the fun.
+And now and then they stooped in a group and splashed water in each
+other's faces with their palms, gradually approaching each other, with
+averted faces to avoid the strangling sprays, and finally gripping and
+struggling till the best man ducked his neighbor, and then they all
+went under in a tangle of white legs and arms and came up blowing,
+sputtering, laughing, and gasping for breath at one and the same time.
+
+When they were well exhausted, they would run out and sprawl on the
+dry, hot sand, and lie there and cover themselves up with it, and by
+and by break for the water again and go through the original
+performance once more. Finally it occurred to them that their naked
+skin represented flesh-colored "tights" very fairly; so they drew a
+ring in the sand and had a circus--with three clowns in it, for none
+would yield this proudest post to his neighbor.
+
+Next they got their marbles and played "knucks" and "ring-taw" and
+"keeps" till that amusement grew stale. Then Joe and Huck had another
+swim, but Tom would not venture, because he found that in kicking off
+his trousers he had kicked his string of rattlesnake rattles off his
+ankle, and he wondered how he had escaped cramp so long without the
+protection of this mysterious charm. He did not venture again until he
+had found it, and by that time the other boys were tired and ready to
+rest. They gradually wandered apart, dropped into the "dumps," and fell
+to gazing longingly across the wide river to where the village lay
+drowsing in the sun. Tom found himself writing "BECKY" in the sand with
+his big toe; he scratched it out, and was angry with himself for his
+weakness. But he wrote it again, nevertheless; he could not help it. He
+erased it once more and then took himself out of temptation by driving
+the other boys together and joining them.
+
+But Joe's spirits had gone down almost beyond resurrection. He was so
+homesick that he could hardly endure the misery of it. The tears lay
+very near the surface. Huck was melancholy, too. Tom was downhearted,
+but tried hard not to show it. He had a secret which he was not ready
+to tell, yet, but if this mutinous depression was not broken up soon,
+he would have to bring it out. He said, with a great show of
+cheerfulness:
+
+"I bet there's been pirates on this island before, boys. We'll explore
+it again. They've hid treasures here somewhere. How'd you feel to light
+on a rotten chest full of gold and silver--hey?"
+
+But it roused only faint enthusiasm, which faded out, with no reply.
+Tom tried one or two other seductions; but they failed, too. It was
+discouraging work. Joe sat poking up the sand with a stick and looking
+very gloomy. Finally he said:
+
+"Oh, boys, let's give it up. I want to go home. It's so lonesome."
+
+"Oh no, Joe, you'll feel better by and by," said Tom. "Just think of
+the fishing that's here."
+
+"I don't care for fishing. I want to go home."
+
+"But, Joe, there ain't such another swimming-place anywhere."
+
+"Swimming's no good. I don't seem to care for it, somehow, when there
+ain't anybody to say I sha'n't go in. I mean to go home."
+
+"Oh, shucks! Baby! You want to see your mother, I reckon."
+
+"Yes, I DO want to see my mother--and you would, too, if you had one.
+I ain't any more baby than you are." And Joe snuffled a little.
+
+"Well, we'll let the cry-baby go home to his mother, won't we, Huck?
+Poor thing--does it want to see its mother? And so it shall. You like
+it here, don't you, Huck? We'll stay, won't we?"
+
+Huck said, "Y-e-s"--without any heart in it.
+
+"I'll never speak to you again as long as I live," said Joe, rising.
+"There now!" And he moved moodily away and began to dress himself.
+
+"Who cares!" said Tom. "Nobody wants you to. Go 'long home and get
+laughed at. Oh, you're a nice pirate. Huck and me ain't cry-babies.
+We'll stay, won't we, Huck? Let him go if he wants to. I reckon we can
+get along without him, per'aps."
+
+But Tom was uneasy, nevertheless, and was alarmed to see Joe go
+sullenly on with his dressing. And then it was discomforting to see
+Huck eying Joe's preparations so wistfully, and keeping up such an
+ominous silence. Presently, without a parting word, Joe began to wade
+off toward the Illinois shore. Tom's heart began to sink. He glanced at
+Huck. Huck could not bear the look, and dropped his eyes. Then he said:
+
+"I want to go, too, Tom. It was getting so lonesome anyway, and now
+it'll be worse. Let's us go, too, Tom."
+
+"I won't! You can all go, if you want to. I mean to stay."
+
+"Tom, I better go."
+
+"Well, go 'long--who's hendering you."
+
+Huck began to pick up his scattered clothes. He said:
+
+"Tom, I wisht you'd come, too. Now you think it over. We'll wait for
+you when we get to shore."
+
+"Well, you'll wait a blame long time, that's all."
+
+Huck started sorrowfully away, and Tom stood looking after him, with a
+strong desire tugging at his heart to yield his pride and go along too.
+He hoped the boys would stop, but they still waded slowly on. It
+suddenly dawned on Tom that it was become very lonely and still. He
+made one final struggle with his pride, and then darted after his
+comrades, yelling:
+
+"Wait! Wait! I want to tell you something!"
+
+They presently stopped and turned around. When he got to where they
+were, he began unfolding his secret, and they listened moodily till at
+last they saw the "point" he was driving at, and then they set up a
+war-whoop of applause and said it was "splendid!" and said if he had
+told them at first, they wouldn't have started away. He made a plausible
+excuse; but his real reason had been the fear that not even the secret
+would keep them with him any very great length of time, and so he had
+meant to hold it in reserve as a last seduction.
+
+The lads came gayly back and went at their sports again with a will,
+chattering all the time about Tom's stupendous plan and admiring the
+genius of it. After a dainty egg and fish dinner, Tom said he wanted to
+learn to smoke, now. Joe caught at the idea and said he would like to
+try, too. So Huck made pipes and filled them. These novices had never
+smoked anything before but cigars made of grape-vine, and they "bit"
+the tongue, and were not considered manly anyway.
+
+Now they stretched themselves out on their elbows and began to puff,
+charily, and with slender confidence. The smoke had an unpleasant
+taste, and they gagged a little, but Tom said:
+
+"Why, it's just as easy! If I'd a knowed this was all, I'd a learnt
+long ago."
+
+"So would I," said Joe. "It's just nothing."
+
+"Why, many a time I've looked at people smoking, and thought well I
+wish I could do that; but I never thought I could," said Tom.
+
+"That's just the way with me, hain't it, Huck? You've heard me talk
+just that way--haven't you, Huck? I'll leave it to Huck if I haven't."
+
+"Yes--heaps of times," said Huck.
+
+"Well, I have too," said Tom; "oh, hundreds of times. Once down by the
+slaughter-house. Don't you remember, Huck? Bob Tanner was there, and
+Johnny Miller, and Jeff Thatcher, when I said it. Don't you remember,
+Huck, 'bout me saying that?"
+
+"Yes, that's so," said Huck. "That was the day after I lost a white
+alley. No, 'twas the day before."
+
+"There--I told you so," said Tom. "Huck recollects it."
+
+"I bleeve I could smoke this pipe all day," said Joe. "I don't feel
+sick."
+
+"Neither do I," said Tom. "I could smoke it all day. But I bet you
+Jeff Thatcher couldn't."
+
+"Jeff Thatcher! Why, he'd keel over just with two draws. Just let him
+try it once. HE'D see!"
+
+"I bet he would. And Johnny Miller--I wish could see Johnny Miller
+tackle it once."
+
+"Oh, don't I!" said Joe. "Why, I bet you Johnny Miller couldn't any
+more do this than nothing. Just one little snifter would fetch HIM."
+
+"'Deed it would, Joe. Say--I wish the boys could see us now."
+
+"So do I."
+
+"Say--boys, don't say anything about it, and some time when they're
+around, I'll come up to you and say, 'Joe, got a pipe? I want a smoke.'
+And you'll say, kind of careless like, as if it warn't anything, you'll
+say, 'Yes, I got my OLD pipe, and another one, but my tobacker ain't
+very good.' And I'll say, 'Oh, that's all right, if it's STRONG
+enough.' And then you'll out with the pipes, and we'll light up just as
+ca'm, and then just see 'em look!"
+
+"By jings, that'll be gay, Tom! I wish it was NOW!"
+
+"So do I! And when we tell 'em we learned when we was off pirating,
+won't they wish they'd been along?"
+
+"Oh, I reckon not! I'll just BET they will!"
+
+So the talk ran on. But presently it began to flag a trifle, and grow
+disjointed. The silences widened; the expectoration marvellously
+increased. Every pore inside the boys' cheeks became a spouting
+fountain; they could scarcely bail out the cellars under their tongues
+fast enough to prevent an inundation; little overflowings down their
+throats occurred in spite of all they could do, and sudden retchings
+followed every time. Both boys were looking very pale and miserable,
+now. Joe's pipe dropped from his nerveless fingers. Tom's followed.
+Both fountains were going furiously and both pumps bailing with might
+and main. Joe said feebly:
+
+"I've lost my knife. I reckon I better go and find it."
+
+Tom said, with quivering lips and halting utterance:
+
+"I'll help you. You go over that way and I'll hunt around by the
+spring. No, you needn't come, Huck--we can find it."
+
+So Huck sat down again, and waited an hour. Then he found it lonesome,
+and went to find his comrades. They were wide apart in the woods, both
+very pale, both fast asleep. But something informed him that if they
+had had any trouble they had got rid of it.
+
+They were not talkative at supper that night. They had a humble look,
+and when Huck prepared his pipe after the meal and was going to prepare
+theirs, they said no, they were not feeling very well--something they
+ate at dinner had disagreed with them.
+
+About midnight Joe awoke, and called the boys. There was a brooding
+oppressiveness in the air that seemed to bode something. The boys
+huddled themselves together and sought the friendly companionship of
+the fire, though the dull dead heat of the breathless atmosphere was
+stifling. They sat still, intent and waiting. The solemn hush
+continued. Beyond the light of the fire everything was swallowed up in
+the blackness of darkness. Presently there came a quivering glow that
+vaguely revealed the foliage for a moment and then vanished. By and by
+another came, a little stronger. Then another. Then a faint moan came
+sighing through the branches of the forest and the boys felt a fleeting
+breath upon their cheeks, and shuddered with the fancy that the Spirit
+of the Night had gone by. There was a pause. Now a weird flash turned
+night into day and showed every little grass-blade, separate and
+distinct, that grew about their feet. And it showed three white,
+startled faces, too. A deep peal of thunder went rolling and tumbling
+down the heavens and lost itself in sullen rumblings in the distance. A
+sweep of chilly air passed by, rustling all the leaves and snowing the
+flaky ashes broadcast about the fire. Another fierce glare lit up the
+forest and an instant crash followed that seemed to rend the tree-tops
+right over the boys' heads. They clung together in terror, in the thick
+gloom that followed. A few big rain-drops fell pattering upon the
+leaves.
+
+"Quick! boys, go for the tent!" exclaimed Tom.
+
+They sprang away, stumbling over roots and among vines in the dark, no
+two plunging in the same direction. A furious blast roared through the
+trees, making everything sing as it went. One blinding flash after
+another came, and peal on peal of deafening thunder. And now a
+drenching rain poured down and the rising hurricane drove it in sheets
+along the ground. The boys cried out to each other, but the roaring
+wind and the booming thunder-blasts drowned their voices utterly.
+However, one by one they straggled in at last and took shelter under
+the tent, cold, scared, and streaming with water; but to have company
+in misery seemed something to be grateful for. They could not talk, the
+old sail flapped so furiously, even if the other noises would have
+allowed them. The tempest rose higher and higher, and presently the
+sail tore loose from its fastenings and went winging away on the blast.
+The boys seized each others' hands and fled, with many tumblings and
+bruises, to the shelter of a great oak that stood upon the river-bank.
+Now the battle was at its highest. Under the ceaseless conflagration of
+lightning that flamed in the skies, everything below stood out in
+clean-cut and shadowless distinctness: the bending trees, the billowy
+river, white with foam, the driving spray of spume-flakes, the dim
+outlines of the high bluffs on the other side, glimpsed through the
+drifting cloud-rack and the slanting veil of rain. Every little while
+some giant tree yielded the fight and fell crashing through the younger
+growth; and the unflagging thunder-peals came now in ear-splitting
+explosive bursts, keen and sharp, and unspeakably appalling. The storm
+culminated in one matchless effort that seemed likely to tear the island
+to pieces, burn it up, drown it to the tree-tops, blow it away, and
+deafen every creature in it, all at one and the same moment. It was a
+wild night for homeless young heads to be out in.
+
+But at last the battle was done, and the forces retired with weaker
+and weaker threatenings and grumblings, and peace resumed her sway. The
+boys went back to camp, a good deal awed; but they found there was
+still something to be thankful for, because the great sycamore, the
+shelter of their beds, was a ruin, now, blasted by the lightnings, and
+they were not under it when the catastrophe happened.
+
+Everything in camp was drenched, the camp-fire as well; for they were
+but heedless lads, like their generation, and had made no provision
+against rain. Here was matter for dismay, for they were soaked through
+and chilled. They were eloquent in their distress; but they presently
+discovered that the fire had eaten so far up under the great log it had
+been built against (where it curved upward and separated itself from
+the ground), that a handbreadth or so of it had escaped wetting; so
+they patiently wrought until, with shreds and bark gathered from the
+under sides of sheltered logs, they coaxed the fire to burn again. Then
+they piled on great dead boughs till they had a roaring furnace, and
+were glad-hearted once more. They dried their boiled ham and had a
+feast, and after that they sat by the fire and expanded and glorified
+their midnight adventure until morning, for there was not a dry spot to
+sleep on, anywhere around.
+
+As the sun began to steal in upon the boys, drowsiness came over them,
+and they went out on the sandbar and lay down to sleep. They got
+scorched out by and by, and drearily set about getting breakfast. After
+the meal they felt rusty, and stiff-jointed, and a little homesick once
+more. Tom saw the signs, and fell to cheering up the pirates as well as
+he could. But they cared nothing for marbles, or circus, or swimming,
+or anything. He reminded them of the imposing secret, and raised a ray
+of cheer. While it lasted, he got them interested in a new device. This
+was to knock off being pirates, for a while, and be Indians for a
+change. They were attracted by this idea; so it was not long before
+they were stripped, and striped from head to heel with black mud, like
+so many zebras--all of them chiefs, of course--and then they went
+tearing through the woods to attack an English settlement.
+
+By and by they separated into three hostile tribes, and darted upon
+each other from ambush with dreadful war-whoops, and killed and scalped
+each other by thousands. It was a gory day. Consequently it was an
+extremely satisfactory one.
+
+They assembled in camp toward supper-time, hungry and happy; but now a
+difficulty arose--hostile Indians could not break the bread of
+hospitality together without first making peace, and this was a simple
+impossibility without smoking a pipe of peace. There was no other
+process that ever they had heard of. Two of the savages almost wished
+they had remained pirates. However, there was no other way; so with
+such show of cheerfulness as they could muster they called for the pipe
+and took their whiff as it passed, in due form.
+
+And behold, they were glad they had gone into savagery, for they had
+gained something; they found that they could now smoke a little without
+having to go and hunt for a lost knife; they did not get sick enough to
+be seriously uncomfortable. They were not likely to fool away this high
+promise for lack of effort. No, they practised cautiously, after
+supper, with right fair success, and so they spent a jubilant evening.
+They were prouder and happier in their new acquirement than they would
+have been in the scalping and skinning of the Six Nations. We will
+leave them to smoke and chatter and brag, since we have no further use
+for them at present.
+
+
+
+CHAPTER XVII
+
+BUT there was no hilarity in the little town that same tranquil
+Saturday afternoon. The Harpers, and Aunt Polly's family, were being
+put into mourning, with great grief and many tears. An unusual quiet
+possessed the village, although it was ordinarily quiet enough, in all
+conscience. The villagers conducted their concerns with an absent air,
+and talked little; but they sighed often. The Saturday holiday seemed a
+burden to the children. They had no heart in their sports, and
+gradually gave them up.
+
+In the afternoon Becky Thatcher found herself moping about the
+deserted schoolhouse yard, and feeling very melancholy. But she found
+nothing there to comfort her. She soliloquized:
+
+"Oh, if I only had a brass andiron-knob again! But I haven't got
+anything now to remember him by." And she choked back a little sob.
+
+Presently she stopped, and said to herself:
+
+"It was right here. Oh, if it was to do over again, I wouldn't say
+that--I wouldn't say it for the whole world. But he's gone now; I'll
+never, never, never see him any more."
+
+This thought broke her down, and she wandered away, with tears rolling
+down her cheeks. Then quite a group of boys and girls--playmates of
+Tom's and Joe's--came by, and stood looking over the paling fence and
+talking in reverent tones of how Tom did so-and-so the last time they
+saw him, and how Joe said this and that small trifle (pregnant with
+awful prophecy, as they could easily see now!)--and each speaker
+pointed out the exact spot where the lost lads stood at the time, and
+then added something like "and I was a-standing just so--just as I am
+now, and as if you was him--I was as close as that--and he smiled, just
+this way--and then something seemed to go all over me, like--awful, you
+know--and I never thought what it meant, of course, but I can see now!"
+
+Then there was a dispute about who saw the dead boys last in life, and
+many claimed that dismal distinction, and offered evidences, more or
+less tampered with by the witness; and when it was ultimately decided
+who DID see the departed last, and exchanged the last words with them,
+the lucky parties took upon themselves a sort of sacred importance, and
+were gaped at and envied by all the rest. One poor chap, who had no
+other grandeur to offer, said with tolerably manifest pride in the
+remembrance:
+
+"Well, Tom Sawyer he licked me once."
+
+But that bid for glory was a failure. Most of the boys could say that,
+and so that cheapened the distinction too much. The group loitered
+away, still recalling memories of the lost heroes, in awed voices.
+
+When the Sunday-school hour was finished, the next morning, the bell
+began to toll, instead of ringing in the usual way. It was a very still
+Sabbath, and the mournful sound seemed in keeping with the musing hush
+that lay upon nature. The villagers began to gather, loitering a moment
+in the vestibule to converse in whispers about the sad event. But there
+was no whispering in the house; only the funereal rustling of dresses
+as the women gathered to their seats disturbed the silence there. None
+could remember when the little church had been so full before. There
+was finally a waiting pause, an expectant dumbness, and then Aunt Polly
+entered, followed by Sid and Mary, and they by the Harper family, all
+in deep black, and the whole congregation, the old minister as well,
+rose reverently and stood until the mourners were seated in the front
+pew. There was another communing silence, broken at intervals by
+muffled sobs, and then the minister spread his hands abroad and prayed.
+A moving hymn was sung, and the text followed: "I am the Resurrection
+and the Life."
+
+As the service proceeded, the clergyman drew such pictures of the
+graces, the winning ways, and the rare promise of the lost lads that
+every soul there, thinking he recognized these pictures, felt a pang in
+remembering that he had persistently blinded himself to them always
+before, and had as persistently seen only faults and flaws in the poor
+boys. The minister related many a touching incident in the lives of the
+departed, too, which illustrated their sweet, generous natures, and the
+people could easily see, now, how noble and beautiful those episodes
+were, and remembered with grief that at the time they occurred they had
+seemed rank rascalities, well deserving of the cowhide. The
+congregation became more and more moved, as the pathetic tale went on,
+till at last the whole company broke down and joined the weeping
+mourners in a chorus of anguished sobs, the preacher himself giving way
+to his feelings, and crying in the pulpit.
+
+There was a rustle in the gallery, which nobody noticed; a moment
+later the church door creaked; the minister raised his streaming eyes
+above his handkerchief, and stood transfixed! First one and then
+another pair of eyes followed the minister's, and then almost with one
+impulse the congregation rose and stared while the three dead boys came
+marching up the aisle, Tom in the lead, Joe next, and Huck, a ruin of
+drooping rags, sneaking sheepishly in the rear! They had been hid in
+the unused gallery listening to their own funeral sermon!
+
+Aunt Polly, Mary, and the Harpers threw themselves upon their restored
+ones, smothered them with kisses and poured out thanksgivings, while
+poor Huck stood abashed and uncomfortable, not knowing exactly what to
+do or where to hide from so many unwelcoming eyes. He wavered, and
+started to slink away, but Tom seized him and said:
+
+"Aunt Polly, it ain't fair. Somebody's got to be glad to see Huck."
+
+"And so they shall. I'm glad to see him, poor motherless thing!" And
+the loving attentions Aunt Polly lavished upon him were the one thing
+capable of making him more uncomfortable than he was before.
+
+Suddenly the minister shouted at the top of his voice: "Praise God
+from whom all blessings flow--SING!--and put your hearts in it!"
+
+And they did. Old Hundred swelled up with a triumphant burst, and
+while it shook the rafters Tom Sawyer the Pirate looked around upon the
+envying juveniles about him and confessed in his heart that this was
+the proudest moment of his life.
+
+As the "sold" congregation trooped out they said they would almost be
+willing to be made ridiculous again to hear Old Hundred sung like that
+once more.
+
+Tom got more cuffs and kisses that day--according to Aunt Polly's
+varying moods--than he had earned before in a year; and he hardly knew
+which expressed the most gratefulness to God and affection for himself.
+
+
+
+CHAPTER XVIII
+
+THAT was Tom's great secret--the scheme to return home with his
+brother pirates and attend their own funerals. They had paddled over to
+the Missouri shore on a log, at dusk on Saturday, landing five or six
+miles below the village; they had slept in the woods at the edge of the
+town till nearly daylight, and had then crept through back lanes and
+alleys and finished their sleep in the gallery of the church among a
+chaos of invalided benches.
+
+At breakfast, Monday morning, Aunt Polly and Mary were very loving to
+Tom, and very attentive to his wants. There was an unusual amount of
+talk. In the course of it Aunt Polly said:
+
+"Well, I don't say it wasn't a fine joke, Tom, to keep everybody
+suffering 'most a week so you boys had a good time, but it is a pity
+you could be so hard-hearted as to let me suffer so. If you could come
+over on a log to go to your funeral, you could have come over and give
+me a hint some way that you warn't dead, but only run off."
+
+"Yes, you could have done that, Tom," said Mary; "and I believe you
+would if you had thought of it."
+
+"Would you, Tom?" said Aunt Polly, her face lighting wistfully. "Say,
+now, would you, if you'd thought of it?"
+
+"I--well, I don't know. 'Twould 'a' spoiled everything."
+
+"Tom, I hoped you loved me that much," said Aunt Polly, with a grieved
+tone that discomforted the boy. "It would have been something if you'd
+cared enough to THINK of it, even if you didn't DO it."
+
+"Now, auntie, that ain't any harm," pleaded Mary; "it's only Tom's
+giddy way--he is always in such a rush that he never thinks of
+anything."
+
+"More's the pity. Sid would have thought. And Sid would have come and
+DONE it, too. Tom, you'll look back, some day, when it's too late, and
+wish you'd cared a little more for me when it would have cost you so
+little."
+
+"Now, auntie, you know I do care for you," said Tom.
+
+"I'd know it better if you acted more like it."
+
+"I wish now I'd thought," said Tom, with a repentant tone; "but I
+dreamt about you, anyway. That's something, ain't it?"
+
+"It ain't much--a cat does that much--but it's better than nothing.
+What did you dream?"
+
+"Why, Wednesday night I dreamt that you was sitting over there by the
+bed, and Sid was sitting by the woodbox, and Mary next to him."
+
+"Well, so we did. So we always do. I'm glad your dreams could take
+even that much trouble about us."
+
+"And I dreamt that Joe Harper's mother was here."
+
+"Why, she was here! Did you dream any more?"
+
+"Oh, lots. But it's so dim, now."
+
+"Well, try to recollect--can't you?"
+
+"Somehow it seems to me that the wind--the wind blowed the--the--"
+
+"Try harder, Tom! The wind did blow something. Come!"
+
+Tom pressed his fingers on his forehead an anxious minute, and then
+said:
+
+"I've got it now! I've got it now! It blowed the candle!"
+
+"Mercy on us! Go on, Tom--go on!"
+
+"And it seems to me that you said, 'Why, I believe that that door--'"
+
+"Go ON, Tom!"
+
+"Just let me study a moment--just a moment. Oh, yes--you said you
+believed the door was open."
+
+"As I'm sitting here, I did! Didn't I, Mary! Go on!"
+
+"And then--and then--well I won't be certain, but it seems like as if
+you made Sid go and--and--"
+
+"Well? Well? What did I make him do, Tom? What did I make him do?"
+
+"You made him--you--Oh, you made him shut it."
+
+"Well, for the land's sake! I never heard the beat of that in all my
+days! Don't tell ME there ain't anything in dreams, any more. Sereny
+Harper shall know of this before I'm an hour older. I'd like to see her
+get around THIS with her rubbage 'bout superstition. Go on, Tom!"
+
+"Oh, it's all getting just as bright as day, now. Next you said I
+warn't BAD, only mischeevous and harum-scarum, and not any more
+responsible than--than--I think it was a colt, or something."
+
+"And so it was! Well, goodness gracious! Go on, Tom!"
+
+"And then you began to cry."
+
+"So I did. So I did. Not the first time, neither. And then--"
+
+"Then Mrs. Harper she began to cry, and said Joe was just the same,
+and she wished she hadn't whipped him for taking cream when she'd
+throwed it out her own self--"
+
+"Tom! The sperrit was upon you! You was a prophesying--that's what you
+was doing! Land alive, go on, Tom!"
+
+"Then Sid he said--he said--"
+
+"I don't think I said anything," said Sid.
+
+"Yes you did, Sid," said Mary.
+
+"Shut your heads and let Tom go on! What did he say, Tom?"
+
+"He said--I THINK he said he hoped I was better off where I was gone
+to, but if I'd been better sometimes--"
+
+"THERE, d'you hear that! It was his very words!"
+
+"And you shut him up sharp."
+
+"I lay I did! There must 'a' been an angel there. There WAS an angel
+there, somewheres!"
+
+"And Mrs. Harper told about Joe scaring her with a firecracker, and
+you told about Peter and the Painkiller--"
+
+"Just as true as I live!"
+
+"And then there was a whole lot of talk 'bout dragging the river for
+us, and 'bout having the funeral Sunday, and then you and old Miss
+Harper hugged and cried, and she went."
+
+"It happened just so! It happened just so, as sure as I'm a-sitting in
+these very tracks. Tom, you couldn't told it more like if you'd 'a'
+seen it! And then what? Go on, Tom!"
+
+"Then I thought you prayed for me--and I could see you and hear every
+word you said. And you went to bed, and I was so sorry that I took and
+wrote on a piece of sycamore bark, 'We ain't dead--we are only off
+being pirates,' and put it on the table by the candle; and then you
+looked so good, laying there asleep, that I thought I went and leaned
+over and kissed you on the lips."
+
+"Did you, Tom, DID you! I just forgive you everything for that!" And
+she seized the boy in a crushing embrace that made him feel like the
+guiltiest of villains.
+
+"It was very kind, even though it was only a--dream," Sid soliloquized
+just audibly.
+
+"Shut up, Sid! A body does just the same in a dream as he'd do if he
+was awake. Here's a big Milum apple I've been saving for you, Tom, if
+you was ever found again--now go 'long to school. I'm thankful to the
+good God and Father of us all I've got you back, that's long-suffering
+and merciful to them that believe on Him and keep His word, though
+goodness knows I'm unworthy of it, but if only the worthy ones got His
+blessings and had His hand to help them over the rough places, there's
+few enough would smile here or ever enter into His rest when the long
+night comes. Go 'long Sid, Mary, Tom--take yourselves off--you've
+hendered me long enough."
+
+The children left for school, and the old lady to call on Mrs. Harper
+and vanquish her realism with Tom's marvellous dream. Sid had better
+judgment than to utter the thought that was in his mind as he left the
+house. It was this: "Pretty thin--as long a dream as that, without any
+mistakes in it!"
+
+What a hero Tom was become, now! He did not go skipping and prancing,
+but moved with a dignified swagger as became a pirate who felt that the
+public eye was on him. And indeed it was; he tried not to seem to see
+the looks or hear the remarks as he passed along, but they were food
+and drink to him. Smaller boys than himself flocked at his heels, as
+proud to be seen with him, and tolerated by him, as if he had been the
+drummer at the head of a procession or the elephant leading a menagerie
+into town. Boys of his own size pretended not to know he had been away
+at all; but they were consuming with envy, nevertheless. They would
+have given anything to have that swarthy suntanned skin of his, and his
+glittering notoriety; and Tom would not have parted with either for a
+circus.
+
+At school the children made so much of him and of Joe, and delivered
+such eloquent admiration from their eyes, that the two heroes were not
+long in becoming insufferably "stuck-up." They began to tell their
+adventures to hungry listeners--but they only began; it was not a thing
+likely to have an end, with imaginations like theirs to furnish
+material. And finally, when they got out their pipes and went serenely
+puffing around, the very summit of glory was reached.
+
+Tom decided that he could be independent of Becky Thatcher now. Glory
+was sufficient. He would live for glory. Now that he was distinguished,
+maybe she would be wanting to "make up." Well, let her--she should see
+that he could be as indifferent as some other people. Presently she
+arrived. Tom pretended not to see her. He moved away and joined a group
+of boys and girls and began to talk. Soon he observed that she was
+tripping gayly back and forth with flushed face and dancing eyes,
+pretending to be busy chasing schoolmates, and screaming with laughter
+when she made a capture; but he noticed that she always made her
+captures in his vicinity, and that she seemed to cast a conscious eye
+in his direction at such times, too. It gratified all the vicious
+vanity that was in him; and so, instead of winning him, it only "set
+him up" the more and made him the more diligent to avoid betraying that
+he knew she was about. Presently she gave over skylarking, and moved
+irresolutely about, sighing once or twice and glancing furtively and
+wistfully toward Tom. Then she observed that now Tom was talking more
+particularly to Amy Lawrence than to any one else. She felt a sharp
+pang and grew disturbed and uneasy at once. She tried to go away, but
+her feet were treacherous, and carried her to the group instead. She
+said to a girl almost at Tom's elbow--with sham vivacity:
+
+"Why, Mary Austin! you bad girl, why didn't you come to Sunday-school?"
+
+"I did come--didn't you see me?"
+
+"Why, no! Did you? Where did you sit?"
+
+"I was in Miss Peters' class, where I always go. I saw YOU."
+
+"Did you? Why, it's funny I didn't see you. I wanted to tell you about
+the picnic."
+
+"Oh, that's jolly. Who's going to give it?"
+
+"My ma's going to let me have one."
+
+"Oh, goody; I hope she'll let ME come."
+
+"Well, she will. The picnic's for me. She'll let anybody come that I
+want, and I want you."
+
+"That's ever so nice. When is it going to be?"
+
+"By and by. Maybe about vacation."
+
+"Oh, won't it be fun! You going to have all the girls and boys?"
+
+"Yes, every one that's friends to me--or wants to be"; and she glanced
+ever so furtively at Tom, but he talked right along to Amy Lawrence
+about the terrible storm on the island, and how the lightning tore the
+great sycamore tree "all to flinders" while he was "standing within
+three feet of it."
+
+"Oh, may I come?" said Grace Miller.
+
+"Yes."
+
+"And me?" said Sally Rogers.
+
+"Yes."
+
+"And me, too?" said Susy Harper. "And Joe?"
+
+"Yes."
+
+And so on, with clapping of joyful hands till all the group had begged
+for invitations but Tom and Amy. Then Tom turned coolly away, still
+talking, and took Amy with him. Becky's lips trembled and the tears
+came to her eyes; she hid these signs with a forced gayety and went on
+chattering, but the life had gone out of the picnic, now, and out of
+everything else; she got away as soon as she could and hid herself and
+had what her sex call "a good cry." Then she sat moody, with wounded
+pride, till the bell rang. She roused up, now, with a vindictive cast
+in her eye, and gave her plaited tails a shake and said she knew what
+SHE'D do.
+
+At recess Tom continued his flirtation with Amy with jubilant
+self-satisfaction. And he kept drifting about to find Becky and lacerate
+her with the performance. At last he spied her, but there was a sudden
+falling of his mercury. She was sitting cosily on a little bench behind
+the schoolhouse looking at a picture-book with Alfred Temple--and so
+absorbed were they, and their heads so close together over the book,
+that they did not seem to be conscious of anything in the world besides.
+Jealousy ran red-hot through Tom's veins. He began to hate himself for
+throwing away the chance Becky had offered for a reconciliation. He
+called himself a fool, and all the hard names he could think of. He
+wanted to cry with vexation. Amy chatted happily along, as they walked,
+for her heart was singing, but Tom's tongue had lost its function. He
+did not hear what Amy was saying, and whenever she paused expectantly he
+could only stammer an awkward assent, which was as often misplaced as
+otherwise. He kept drifting to the rear of the schoolhouse, again and
+again, to sear his eyeballs with the hateful spectacle there. He could
+not help it. And it maddened him to see, as he thought he saw, that
+Becky Thatcher never once suspected that he was even in the land of the
+living. But she did see, nevertheless; and she knew she was winning her
+fight, too, and was glad to see him suffer as she had suffered.
+
+Amy's happy prattle became intolerable. Tom hinted at things he had to
+attend to; things that must be done; and time was fleeting. But in
+vain--the girl chirped on. Tom thought, "Oh, hang her, ain't I ever
+going to get rid of her?" At last he must be attending to those
+things--and she said artlessly that she would be "around" when school
+let out. And he hastened away, hating her for it.
+
+"Any other boy!" Tom thought, grating his teeth. "Any boy in the whole
+town but that Saint Louis smarty that thinks he dresses so fine and is
+aristocracy! Oh, all right, I licked you the first day you ever saw
+this town, mister, and I'll lick you again! You just wait till I catch
+you out! I'll just take and--"
+
+And he went through the motions of thrashing an imaginary boy
+--pummelling the air, and kicking and gouging. "Oh, you do, do you? You
+holler 'nough, do you? Now, then, let that learn you!" And so the
+imaginary flogging was finished to his satisfaction.
+
+Tom fled home at noon. His conscience could not endure any more of
+Amy's grateful happiness, and his jealousy could bear no more of the
+other distress. Becky resumed her picture inspections with Alfred, but
+as the minutes dragged along and no Tom came to suffer, her triumph
+began to cloud and she lost interest; gravity and absent-mindedness
+followed, and then melancholy; two or three times she pricked up her
+ear at a footstep, but it was a false hope; no Tom came. At last she
+grew entirely miserable and wished she hadn't carried it so far. When
+poor Alfred, seeing that he was losing her, he did not know how, kept
+exclaiming: "Oh, here's a jolly one! look at this!" she lost patience
+at last, and said, "Oh, don't bother me! I don't care for them!" and
+burst into tears, and got up and walked away.
+
+Alfred dropped alongside and was going to try to comfort her, but she
+said:
+
+"Go away and leave me alone, can't you! I hate you!"
+
+So the boy halted, wondering what he could have done--for she had said
+she would look at pictures all through the nooning--and she walked on,
+crying. Then Alfred went musing into the deserted schoolhouse. He was
+humiliated and angry. He easily guessed his way to the truth--the girl
+had simply made a convenience of him to vent her spite upon Tom Sawyer.
+He was far from hating Tom the less when this thought occurred to him.
+He wished there was some way to get that boy into trouble without much
+risk to himself. Tom's spelling-book fell under his eye. Here was his
+opportunity. He gratefully opened to the lesson for the afternoon and
+poured ink upon the page.
+
+Becky, glancing in at a window behind him at the moment, saw the act,
+and moved on, without discovering herself. She started homeward, now,
+intending to find Tom and tell him; Tom would be thankful and their
+troubles would be healed. Before she was half way home, however, she
+had changed her mind. The thought of Tom's treatment of her when she
+was talking about her picnic came scorching back and filled her with
+shame. She resolved to let him get whipped on the damaged
+spelling-book's account, and to hate him forever, into the bargain.
+
+
+
+CHAPTER XIX
+
+TOM arrived at home in a dreary mood, and the first thing his aunt
+said to him showed him that he had brought his sorrows to an
+unpromising market:
+
+"Tom, I've a notion to skin you alive!"
+
+"Auntie, what have I done?"
+
+"Well, you've done enough. Here I go over to Sereny Harper, like an
+old softy, expecting I'm going to make her believe all that rubbage
+about that dream, when lo and behold you she'd found out from Joe that
+you was over here and heard all the talk we had that night. Tom, I
+don't know what is to become of a boy that will act like that. It makes
+me feel so bad to think you could let me go to Sereny Harper and make
+such a fool of myself and never say a word."
+
+This was a new aspect of the thing. His smartness of the morning had
+seemed to Tom a good joke before, and very ingenious. It merely looked
+mean and shabby now. He hung his head and could not think of anything
+to say for a moment. Then he said:
+
+"Auntie, I wish I hadn't done it--but I didn't think."
+
+"Oh, child, you never think. You never think of anything but your own
+selfishness. You could think to come all the way over here from
+Jackson's Island in the night to laugh at our troubles, and you could
+think to fool me with a lie about a dream; but you couldn't ever think
+to pity us and save us from sorrow."
+
+"Auntie, I know now it was mean, but I didn't mean to be mean. I
+didn't, honest. And besides, I didn't come over here to laugh at you
+that night."
+
+"What did you come for, then?"
+
+"It was to tell you not to be uneasy about us, because we hadn't got
+drownded."
+
+"Tom, Tom, I would be the thankfullest soul in this world if I could
+believe you ever had as good a thought as that, but you know you never
+did--and I know it, Tom."
+
+"Indeed and 'deed I did, auntie--I wish I may never stir if I didn't."
+
+"Oh, Tom, don't lie--don't do it. It only makes things a hundred times
+worse."
+
+"It ain't a lie, auntie; it's the truth. I wanted to keep you from
+grieving--that was all that made me come."
+
+"I'd give the whole world to believe that--it would cover up a power
+of sins, Tom. I'd 'most be glad you'd run off and acted so bad. But it
+ain't reasonable; because, why didn't you tell me, child?"
+
+"Why, you see, when you got to talking about the funeral, I just got
+all full of the idea of our coming and hiding in the church, and I
+couldn't somehow bear to spoil it. So I just put the bark back in my
+pocket and kept mum."
+
+"What bark?"
+
+"The bark I had wrote on to tell you we'd gone pirating. I wish, now,
+you'd waked up when I kissed you--I do, honest."
+
+The hard lines in his aunt's face relaxed and a sudden tenderness
+dawned in her eyes.
+
+"DID you kiss me, Tom?"
+
+"Why, yes, I did."
+
+"Are you sure you did, Tom?"
+
+"Why, yes, I did, auntie--certain sure."
+
+"What did you kiss me for, Tom?"
+
+"Because I loved you so, and you laid there moaning and I was so sorry."
+
+The words sounded like truth. The old lady could not hide a tremor in
+her voice when she said:
+
+"Kiss me again, Tom!--and be off with you to school, now, and don't
+bother me any more."
+
+The moment he was gone, she ran to a closet and got out the ruin of a
+jacket which Tom had gone pirating in. Then she stopped, with it in her
+hand, and said to herself:
+
+"No, I don't dare. Poor boy, I reckon he's lied about it--but it's a
+blessed, blessed lie, there's such a comfort come from it. I hope the
+Lord--I KNOW the Lord will forgive him, because it was such
+goodheartedness in him to tell it. But I don't want to find out it's a
+lie. I won't look."
+
+She put the jacket away, and stood by musing a minute. Twice she put
+out her hand to take the garment again, and twice she refrained. Once
+more she ventured, and this time she fortified herself with the
+thought: "It's a good lie--it's a good lie--I won't let it grieve me."
+So she sought the jacket pocket. A moment later she was reading Tom's
+piece of bark through flowing tears and saying: "I could forgive the
+boy, now, if he'd committed a million sins!"
+
+
+
+CHAPTER XX
+
+THERE was something about Aunt Polly's manner, when she kissed Tom,
+that swept away his low spirits and made him lighthearted and happy
+again. He started to school and had the luck of coming upon Becky
+Thatcher at the head of Meadow Lane. His mood always determined his
+manner. Without a moment's hesitation he ran to her and said:
+
+"I acted mighty mean to-day, Becky, and I'm so sorry. I won't ever,
+ever do that way again, as long as ever I live--please make up, won't
+you?"
+
+The girl stopped and looked him scornfully in the face:
+
+"I'll thank you to keep yourself TO yourself, Mr. Thomas Sawyer. I'll
+never speak to you again."
+
+She tossed her head and passed on. Tom was so stunned that he had not
+even presence of mind enough to say "Who cares, Miss Smarty?" until the
+right time to say it had gone by. So he said nothing. But he was in a
+fine rage, nevertheless. He moped into the schoolyard wishing she were
+a boy, and imagining how he would trounce her if she were. He presently
+encountered her and delivered a stinging remark as he passed. She
+hurled one in return, and the angry breach was complete. It seemed to
+Becky, in her hot resentment, that she could hardly wait for school to
+"take in," she was so impatient to see Tom flogged for the injured
+spelling-book. If she had had any lingering notion of exposing Alfred
+Temple, Tom's offensive fling had driven it entirely away.
+
+Poor girl, she did not know how fast she was nearing trouble herself.
+The master, Mr. Dobbins, had reached middle age with an unsatisfied
+ambition. The darling of his desires was, to be a doctor, but poverty
+had decreed that he should be nothing higher than a village
+schoolmaster. Every day he took a mysterious book out of his desk and
+absorbed himself in it at times when no classes were reciting. He kept
+that book under lock and key. There was not an urchin in school but was
+perishing to have a glimpse of it, but the chance never came. Every boy
+and girl had a theory about the nature of that book; but no two
+theories were alike, and there was no way of getting at the facts in
+the case. Now, as Becky was passing by the desk, which stood near the
+door, she noticed that the key was in the lock! It was a precious
+moment. She glanced around; found herself alone, and the next instant
+she had the book in her hands. The title-page--Professor Somebody's
+ANATOMY--carried no information to her mind; so she began to turn the
+leaves. She came at once upon a handsomely engraved and colored
+frontispiece--a human figure, stark naked. At that moment a shadow fell
+on the page and Tom Sawyer stepped in at the door and caught a glimpse
+of the picture. Becky snatched at the book to close it, and had the
+hard luck to tear the pictured page half down the middle. She thrust
+the volume into the desk, turned the key, and burst out crying with
+shame and vexation.
+
+"Tom Sawyer, you are just as mean as you can be, to sneak up on a
+person and look at what they're looking at."
+
+"How could I know you was looking at anything?"
+
+"You ought to be ashamed of yourself, Tom Sawyer; you know you're
+going to tell on me, and oh, what shall I do, what shall I do! I'll be
+whipped, and I never was whipped in school."
+
+Then she stamped her little foot and said:
+
+"BE so mean if you want to! I know something that's going to happen.
+You just wait and you'll see! Hateful, hateful, hateful!"--and she
+flung out of the house with a new explosion of crying.
+
+Tom stood still, rather flustered by this onslaught. Presently he said
+to himself:
+
+"What a curious kind of a fool a girl is! Never been licked in school!
+Shucks! What's a licking! That's just like a girl--they're so
+thin-skinned and chicken-hearted. Well, of course I ain't going to tell
+old Dobbins on this little fool, because there's other ways of getting
+even on her, that ain't so mean; but what of it? Old Dobbins will ask
+who it was tore his book. Nobody'll answer. Then he'll do just the way
+he always does--ask first one and then t'other, and when he comes to the
+right girl he'll know it, without any telling. Girls' faces always tell
+on them. They ain't got any backbone. She'll get licked. Well, it's a
+kind of a tight place for Becky Thatcher, because there ain't any way
+out of it." Tom conned the thing a moment longer, and then added: "All
+right, though; she'd like to see me in just such a fix--let her sweat it
+out!"
+
+Tom joined the mob of skylarking scholars outside. In a few moments
+the master arrived and school "took in." Tom did not feel a strong
+interest in his studies. Every time he stole a glance at the girls'
+side of the room Becky's face troubled him. Considering all things, he
+did not want to pity her, and yet it was all he could do to help it. He
+could get up no exultation that was really worthy the name. Presently
+the spelling-book discovery was made, and Tom's mind was entirely full
+of his own matters for a while after that. Becky roused up from her
+lethargy of distress and showed good interest in the proceedings. She
+did not expect that Tom could get out of his trouble by denying that he
+spilt the ink on the book himself; and she was right. The denial only
+seemed to make the thing worse for Tom. Becky supposed she would be
+glad of that, and she tried to believe she was glad of it, but she
+found she was not certain. When the worst came to the worst, she had an
+impulse to get up and tell on Alfred Temple, but she made an effort and
+forced herself to keep still--because, said she to herself, "he'll tell
+about me tearing the picture sure. I wouldn't say a word, not to save
+his life!"
+
+Tom took his whipping and went back to his seat not at all
+broken-hearted, for he thought it was possible that he had unknowingly
+upset the ink on the spelling-book himself, in some skylarking bout--he
+had denied it for form's sake and because it was custom, and had stuck
+to the denial from principle.
+
+A whole hour drifted by, the master sat nodding in his throne, the air
+was drowsy with the hum of study. By and by, Mr. Dobbins straightened
+himself up, yawned, then unlocked his desk, and reached for his book,
+but seemed undecided whether to take it out or leave it. Most of the
+pupils glanced up languidly, but there were two among them that watched
+his movements with intent eyes. Mr. Dobbins fingered his book absently
+for a while, then took it out and settled himself in his chair to read!
+Tom shot a glance at Becky. He had seen a hunted and helpless rabbit
+look as she did, with a gun levelled at its head. Instantly he forgot
+his quarrel with her. Quick--something must be done! done in a flash,
+too! But the very imminence of the emergency paralyzed his invention.
+Good!--he had an inspiration! He would run and snatch the book, spring
+through the door and fly. But his resolution shook for one little
+instant, and the chance was lost--the master opened the volume. If Tom
+only had the wasted opportunity back again! Too late. There was no help
+for Becky now, he said. The next moment the master faced the school.
+Every eye sank under his gaze. There was that in it which smote even
+the innocent with fear. There was silence while one might count ten
+--the master was gathering his wrath. Then he spoke: "Who tore this book?"
+
+There was not a sound. One could have heard a pin drop. The stillness
+continued; the master searched face after face for signs of guilt.
+
+"Benjamin Rogers, did you tear this book?"
+
+A denial. Another pause.
+
+"Joseph Harper, did you?"
+
+Another denial. Tom's uneasiness grew more and more intense under the
+slow torture of these proceedings. The master scanned the ranks of
+boys--considered a while, then turned to the girls:
+
+"Amy Lawrence?"
+
+A shake of the head.
+
+"Gracie Miller?"
+
+The same sign.
+
+"Susan Harper, did you do this?"
+
+Another negative. The next girl was Becky Thatcher. Tom was trembling
+from head to foot with excitement and a sense of the hopelessness of
+the situation.
+
+"Rebecca Thatcher" [Tom glanced at her face--it was white with terror]
+--"did you tear--no, look me in the face" [her hands rose in appeal]
+--"did you tear this book?"
+
+A thought shot like lightning through Tom's brain. He sprang to his
+feet and shouted--"I done it!"
+
+The school stared in perplexity at this incredible folly. Tom stood a
+moment, to gather his dismembered faculties; and when he stepped
+forward to go to his punishment the surprise, the gratitude, the
+adoration that shone upon him out of poor Becky's eyes seemed pay
+enough for a hundred floggings. Inspired by the splendor of his own
+act, he took without an outcry the most merciless flaying that even Mr.
+Dobbins had ever administered; and also received with indifference the
+added cruelty of a command to remain two hours after school should be
+dismissed--for he knew who would wait for him outside till his
+captivity was done, and not count the tedious time as loss, either.
+
+Tom went to bed that night planning vengeance against Alfred Temple;
+for with shame and repentance Becky had told him all, not forgetting
+her own treachery; but even the longing for vengeance had to give way,
+soon, to pleasanter musings, and he fell asleep at last with Becky's
+latest words lingering dreamily in his ear--
+
+"Tom, how COULD you be so noble!"
+
+
+
+CHAPTER XXI
+
+VACATION was approaching. The schoolmaster, always severe, grew
+severer and more exacting than ever, for he wanted the school to make a
+good showing on "Examination" day. His rod and his ferule were seldom
+idle now--at least among the smaller pupils. Only the biggest boys, and
+young ladies of eighteen and twenty, escaped lashing. Mr. Dobbins'
+lashings were very vigorous ones, too; for although he carried, under
+his wig, a perfectly bald and shiny head, he had only reached middle
+age, and there was no sign of feebleness in his muscle. As the great
+day approached, all the tyranny that was in him came to the surface; he
+seemed to take a vindictive pleasure in punishing the least
+shortcomings. The consequence was, that the smaller boys spent their
+days in terror and suffering and their nights in plotting revenge. They
+threw away no opportunity to do the master a mischief. But he kept
+ahead all the time. The retribution that followed every vengeful
+success was so sweeping and majestic that the boys always retired from
+the field badly worsted. At last they conspired together and hit upon a
+plan that promised a dazzling victory. They swore in the sign-painter's
+boy, told him the scheme, and asked his help. He had his own reasons
+for being delighted, for the master boarded in his father's family and
+had given the boy ample cause to hate him. The master's wife would go
+on a visit to the country in a few days, and there would be nothing to
+interfere with the plan; the master always prepared himself for great
+occasions by getting pretty well fuddled, and the sign-painter's boy
+said that when the dominie had reached the proper condition on
+Examination Evening he would "manage the thing" while he napped in his
+chair; then he would have him awakened at the right time and hurried
+away to school.
+
+In the fulness of time the interesting occasion arrived. At eight in
+the evening the schoolhouse was brilliantly lighted, and adorned with
+wreaths and festoons of foliage and flowers. The master sat throned in
+his great chair upon a raised platform, with his blackboard behind him.
+He was looking tolerably mellow. Three rows of benches on each side and
+six rows in front of him were occupied by the dignitaries of the town
+and by the parents of the pupils. To his left, back of the rows of
+citizens, was a spacious temporary platform upon which were seated the
+scholars who were to take part in the exercises of the evening; rows of
+small boys, washed and dressed to an intolerable state of discomfort;
+rows of gawky big boys; snowbanks of girls and young ladies clad in
+lawn and muslin and conspicuously conscious of their bare arms, their
+grandmothers' ancient trinkets, their bits of pink and blue ribbon and
+the flowers in their hair. All the rest of the house was filled with
+non-participating scholars.
+
+The exercises began. A very little boy stood up and sheepishly
+recited, "You'd scarce expect one of my age to speak in public on the
+stage," etc.--accompanying himself with the painfully exact and
+spasmodic gestures which a machine might have used--supposing the
+machine to be a trifle out of order. But he got through safely, though
+cruelly scared, and got a fine round of applause when he made his
+manufactured bow and retired.
+
+A little shamefaced girl lisped, "Mary had a little lamb," etc.,
+performed a compassion-inspiring curtsy, got her meed of applause, and
+sat down flushed and happy.
+
+Tom Sawyer stepped forward with conceited confidence and soared into
+the unquenchable and indestructible "Give me liberty or give me death"
+speech, with fine fury and frantic gesticulation, and broke down in the
+middle of it. A ghastly stage-fright seized him, his legs quaked under
+him and he was like to choke. True, he had the manifest sympathy of the
+house but he had the house's silence, too, which was even worse than
+its sympathy. The master frowned, and this completed the disaster. Tom
+struggled awhile and then retired, utterly defeated. There was a weak
+attempt at applause, but it died early.
+
+"The Boy Stood on the Burning Deck" followed; also "The Assyrian Came
+Down," and other declamatory gems. Then there were reading exercises,
+and a spelling fight. The meagre Latin class recited with honor. The
+prime feature of the evening was in order, now--original "compositions"
+by the young ladies. Each in her turn stepped forward to the edge of
+the platform, cleared her throat, held up her manuscript (tied with
+dainty ribbon), and proceeded to read, with labored attention to
+"expression" and punctuation. The themes were the same that had been
+illuminated upon similar occasions by their mothers before them, their
+grandmothers, and doubtless all their ancestors in the female line
+clear back to the Crusades. "Friendship" was one; "Memories of Other
+Days"; "Religion in History"; "Dream Land"; "The Advantages of
+Culture"; "Forms of Political Government Compared and Contrasted";
+"Melancholy"; "Filial Love"; "Heart Longings," etc., etc.
+
+A prevalent feature in these compositions was a nursed and petted
+melancholy; another was a wasteful and opulent gush of "fine language";
+another was a tendency to lug in by the ears particularly prized words
+and phrases until they were worn entirely out; and a peculiarity that
+conspicuously marked and marred them was the inveterate and intolerable
+sermon that wagged its crippled tail at the end of each and every one
+of them. No matter what the subject might be, a brain-racking effort
+was made to squirm it into some aspect or other that the moral and
+religious mind could contemplate with edification. The glaring
+insincerity of these sermons was not sufficient to compass the
+banishment of the fashion from the schools, and it is not sufficient
+to-day; it never will be sufficient while the world stands, perhaps.
+There is no school in all our land where the young ladies do not feel
+obliged to close their compositions with a sermon; and you will find
+that the sermon of the most frivolous and the least religious girl in
+the school is always the longest and the most relentlessly pious. But
+enough of this. Homely truth is unpalatable.
+
+Let us return to the "Examination." The first composition that was
+read was one entitled "Is this, then, Life?" Perhaps the reader can
+endure an extract from it:
+
+  "In the common walks of life, with what delightful
+   emotions does the youthful mind look forward to some
+   anticipated scene of festivity! Imagination is busy
+   sketching rose-tinted pictures of joy. In fancy, the
+   voluptuous votary of fashion sees herself amid the
+   festive throng, 'the observed of all observers.' Her
+   graceful form, arrayed in snowy robes, is whirling
+   through the mazes of the joyous dance; her eye is
+   brightest, her step is lightest in the gay assembly.
+
+  "In such delicious fancies time quickly glides by,
+   and the welcome hour arrives for her entrance into
+   the Elysian world, of which she has had such bright
+   dreams. How fairy-like does everything appear to
+   her enchanted vision! Each new scene is more charming
+   than the last. But after a while she finds that
+   beneath this goodly exterior, all is vanity, the
+   flattery which once charmed her soul, now grates
+   harshly upon her ear; the ball-room has lost its
+   charms; and with wasted health and imbittered heart,
+   she turns away with the conviction that earthly
+   pleasures cannot satisfy the longings of the soul!"
+
+And so forth and so on. There was a buzz of gratification from time to
+time during the reading, accompanied by whispered ejaculations of "How
+sweet!" "How eloquent!" "So true!" etc., and after the thing had closed
+with a peculiarly afflicting sermon the applause was enthusiastic.
+
+Then arose a slim, melancholy girl, whose face had the "interesting"
+paleness that comes of pills and indigestion, and read a "poem." Two
+stanzas of it will do:
+
+   "A MISSOURI MAIDEN'S FAREWELL TO ALABAMA
+
+   "Alabama, good-bye! I love thee well!
+      But yet for a while do I leave thee now!
+    Sad, yes, sad thoughts of thee my heart doth swell,
+      And burning recollections throng my brow!
+    For I have wandered through thy flowery woods;
+      Have roamed and read near Tallapoosa's stream;
+    Have listened to Tallassee's warring floods,
+      And wooed on Coosa's side Aurora's beam.
+
+   "Yet shame I not to bear an o'er-full heart,
+      Nor blush to turn behind my tearful eyes;
+    'Tis from no stranger land I now must part,
+      'Tis to no strangers left I yield these sighs.
+    Welcome and home were mine within this State,
+      Whose vales I leave--whose spires fade fast from me
+    And cold must be mine eyes, and heart, and tete,
+      When, dear Alabama! they turn cold on thee!"
+
+There were very few there who knew what "tete" meant, but the poem was
+very satisfactory, nevertheless.
+
+Next appeared a dark-complexioned, black-eyed, black-haired young
+lady, who paused an impressive moment, assumed a tragic expression, and
+began to read in a measured, solemn tone:
+
+  "A VISION
+
+   "Dark and tempestuous was night. Around the
+   throne on high not a single star quivered; but
+   the deep intonations of the heavy thunder
+   constantly vibrated upon the ear; whilst the
+   terrific lightning revelled in angry mood
+   through the cloudy chambers of heaven, seeming
+   to scorn the power exerted over its terror by
+   the illustrious Franklin! Even the boisterous
+   winds unanimously came forth from their mystic
+   homes, and blustered about as if to enhance by
+   their aid the wildness of the scene.
+
+   "At such a time, so dark, so dreary, for human
+   sympathy my very spirit sighed; but instead thereof,
+
+   "'My dearest friend, my counsellor, my comforter
+   and guide--My joy in grief, my second bliss
+   in joy,' came to my side. She moved like one of
+   those bright beings pictured in the sunny walks
+   of fancy's Eden by the romantic and young, a
+   queen of beauty unadorned save by her own
+   transcendent loveliness. So soft was her step, it
+   failed to make even a sound, and but for the
+   magical thrill imparted by her genial touch, as
+   other unobtrusive beauties, she would have glided
+   away un-perceived--unsought. A strange sadness
+   rested upon her features, like icy tears upon
+   the robe of December, as she pointed to the
+   contending elements without, and bade me contemplate
+   the two beings presented."
+
+This nightmare occupied some ten pages of manuscript and wound up with
+a sermon so destructive of all hope to non-Presbyterians that it took
+the first prize. This composition was considered to be the very finest
+effort of the evening. The mayor of the village, in delivering the
+prize to the author of it, made a warm speech in which he said that it
+was by far the most "eloquent" thing he had ever listened to, and that
+Daniel Webster himself might well be proud of it.
+
+It may be remarked, in passing, that the number of compositions in
+which the word "beauteous" was over-fondled, and human experience
+referred to as "life's page," was up to the usual average.
+
+Now the master, mellow almost to the verge of geniality, put his chair
+aside, turned his back to the audience, and began to draw a map of
+America on the blackboard, to exercise the geography class upon. But he
+made a sad business of it with his unsteady hand, and a smothered
+titter rippled over the house. He knew what the matter was, and set
+himself to right it. He sponged out lines and remade them; but he only
+distorted them more than ever, and the tittering was more pronounced.
+He threw his entire attention upon his work, now, as if determined not
+to be put down by the mirth. He felt that all eyes were fastened upon
+him; he imagined he was succeeding, and yet the tittering continued; it
+even manifestly increased. And well it might. There was a garret above,
+pierced with a scuttle over his head; and down through this scuttle
+came a cat, suspended around the haunches by a string; she had a rag
+tied about her head and jaws to keep her from mewing; as she slowly
+descended she curved upward and clawed at the string, she swung
+downward and clawed at the intangible air. The tittering rose higher
+and higher--the cat was within six inches of the absorbed teacher's
+head--down, down, a little lower, and she grabbed his wig with her
+desperate claws, clung to it, and was snatched up into the garret in an
+instant with her trophy still in her possession! And how the light did
+blaze abroad from the master's bald pate--for the sign-painter's boy
+had GILDED it!
+
+That broke up the meeting. The boys were avenged. Vacation had come.
+
+   NOTE:--The pretended "compositions" quoted in
+   this chapter are taken without alteration from a
+   volume entitled "Prose and Poetry, by a Western
+   Lady"--but they are exactly and precisely after
+   the schoolgirl pattern, and hence are much
+   happier than any mere imitations could be.
+
+
+
+CHAPTER XXII
+
+TOM joined the new order of Cadets of Temperance, being attracted by
+the showy character of their "regalia." He promised to abstain from
+smoking, chewing, and profanity as long as he remained a member. Now he
+found out a new thing--namely, that to promise not to do a thing is the
+surest way in the world to make a body want to go and do that very
+thing. Tom soon found himself tormented with a desire to drink and
+swear; the desire grew to be so intense that nothing but the hope of a
+chance to display himself in his red sash kept him from withdrawing
+from the order. Fourth of July was coming; but he soon gave that up
+--gave it up before he had worn his shackles over forty-eight hours--and
+fixed his hopes upon old Judge Frazer, justice of the peace, who was
+apparently on his deathbed and would have a big public funeral, since
+he was so high an official. During three days Tom was deeply concerned
+about the Judge's condition and hungry for news of it. Sometimes his
+hopes ran high--so high that he would venture to get out his regalia
+and practise before the looking-glass. But the Judge had a most
+discouraging way of fluctuating. At last he was pronounced upon the
+mend--and then convalescent. Tom was disgusted; and felt a sense of
+injury, too. He handed in his resignation at once--and that night the
+Judge suffered a relapse and died. Tom resolved that he would never
+trust a man like that again.
+
+The funeral was a fine thing. The Cadets paraded in a style calculated
+to kill the late member with envy. Tom was a free boy again, however
+--there was something in that. He could drink and swear, now--but found
+to his surprise that he did not want to. The simple fact that he could,
+took the desire away, and the charm of it.
+
+Tom presently wondered to find that his coveted vacation was beginning
+to hang a little heavily on his hands.
+
+He attempted a diary--but nothing happened during three days, and so
+he abandoned it.
+
+The first of all the negro minstrel shows came to town, and made a
+sensation. Tom and Joe Harper got up a band of performers and were
+happy for two days.
+
+Even the Glorious Fourth was in some sense a failure, for it rained
+hard, there was no procession in consequence, and the greatest man in
+the world (as Tom supposed), Mr. Benton, an actual United States
+Senator, proved an overwhelming disappointment--for he was not
+twenty-five feet high, nor even anywhere in the neighborhood of it.
+
+A circus came. The boys played circus for three days afterward in
+tents made of rag carpeting--admission, three pins for boys, two for
+girls--and then circusing was abandoned.
+
+A phrenologist and a mesmerizer came--and went again and left the
+village duller and drearier than ever.
+
+There were some boys-and-girls' parties, but they were so few and so
+delightful that they only made the aching voids between ache the harder.
+
+Becky Thatcher was gone to her Constantinople home to stay with her
+parents during vacation--so there was no bright side to life anywhere.
+
+The dreadful secret of the murder was a chronic misery. It was a very
+cancer for permanency and pain.
+
+Then came the measles.
+
+During two long weeks Tom lay a prisoner, dead to the world and its
+happenings. He was very ill, he was interested in nothing. When he got
+upon his feet at last and moved feebly down-town, a melancholy change
+had come over everything and every creature. There had been a
+"revival," and everybody had "got religion," not only the adults, but
+even the boys and girls. Tom went about, hoping against hope for the
+sight of one blessed sinful face, but disappointment crossed him
+everywhere. He found Joe Harper studying a Testament, and turned sadly
+away from the depressing spectacle. He sought Ben Rogers, and found him
+visiting the poor with a basket of tracts. He hunted up Jim Hollis, who
+called his attention to the precious blessing of his late measles as a
+warning. Every boy he encountered added another ton to his depression;
+and when, in desperation, he flew for refuge at last to the bosom of
+Huckleberry Finn and was received with a Scriptural quotation, his
+heart broke and he crept home and to bed realizing that he alone of all
+the town was lost, forever and forever.
+
+And that night there came on a terrific storm, with driving rain,
+awful claps of thunder and blinding sheets of lightning. He covered his
+head with the bedclothes and waited in a horror of suspense for his
+doom; for he had not the shadow of a doubt that all this hubbub was
+about him. He believed he had taxed the forbearance of the powers above
+to the extremity of endurance and that this was the result. It might
+have seemed to him a waste of pomp and ammunition to kill a bug with a
+battery of artillery, but there seemed nothing incongruous about the
+getting up such an expensive thunderstorm as this to knock the turf
+from under an insect like himself.
+
+By and by the tempest spent itself and died without accomplishing its
+object. The boy's first impulse was to be grateful, and reform. His
+second was to wait--for there might not be any more storms.
+
+The next day the doctors were back; Tom had relapsed. The three weeks
+he spent on his back this time seemed an entire age. When he got abroad
+at last he was hardly grateful that he had been spared, remembering how
+lonely was his estate, how companionless and forlorn he was. He drifted
+listlessly down the street and found Jim Hollis acting as judge in a
+juvenile court that was trying a cat for murder, in the presence of her
+victim, a bird. He found Joe Harper and Huck Finn up an alley eating a
+stolen melon. Poor lads! they--like Tom--had suffered a relapse.
+
+
+
+CHAPTER XXIII
+
+AT last the sleepy atmosphere was stirred--and vigorously: the murder
+trial came on in the court. It became the absorbing topic of village
+talk immediately. Tom could not get away from it. Every reference to
+the murder sent a shudder to his heart, for his troubled conscience and
+fears almost persuaded him that these remarks were put forth in his
+hearing as "feelers"; he did not see how he could be suspected of
+knowing anything about the murder, but still he could not be
+comfortable in the midst of this gossip. It kept him in a cold shiver
+all the time. He took Huck to a lonely place to have a talk with him.
+It would be some relief to unseal his tongue for a little while; to
+divide his burden of distress with another sufferer. Moreover, he
+wanted to assure himself that Huck had remained discreet.
+
+"Huck, have you ever told anybody about--that?"
+
+"'Bout what?"
+
+"You know what."
+
+"Oh--'course I haven't."
+
+"Never a word?"
+
+"Never a solitary word, so help me. What makes you ask?"
+
+"Well, I was afeard."
+
+"Why, Tom Sawyer, we wouldn't be alive two days if that got found out.
+YOU know that."
+
+Tom felt more comfortable. After a pause:
+
+"Huck, they couldn't anybody get you to tell, could they?"
+
+"Get me to tell? Why, if I wanted that half-breed devil to drownd me
+they could get me to tell. They ain't no different way."
+
+"Well, that's all right, then. I reckon we're safe as long as we keep
+mum. But let's swear again, anyway. It's more surer."
+
+"I'm agreed."
+
+So they swore again with dread solemnities.
+
+"What is the talk around, Huck? I've heard a power of it."
+
+"Talk? Well, it's just Muff Potter, Muff Potter, Muff Potter all the
+time. It keeps me in a sweat, constant, so's I want to hide som'ers."
+
+"That's just the same way they go on round me. I reckon he's a goner.
+Don't you feel sorry for him, sometimes?"
+
+"Most always--most always. He ain't no account; but then he hain't
+ever done anything to hurt anybody. Just fishes a little, to get money
+to get drunk on--and loafs around considerable; but lord, we all do
+that--leastways most of us--preachers and such like. But he's kind of
+good--he give me half a fish, once, when there warn't enough for two;
+and lots of times he's kind of stood by me when I was out of luck."
+
+"Well, he's mended kites for me, Huck, and knitted hooks on to my
+line. I wish we could get him out of there."
+
+"My! we couldn't get him out, Tom. And besides, 'twouldn't do any
+good; they'd ketch him again."
+
+"Yes--so they would. But I hate to hear 'em abuse him so like the
+dickens when he never done--that."
+
+"I do too, Tom. Lord, I hear 'em say he's the bloodiest looking
+villain in this country, and they wonder he wasn't ever hung before."
+
+"Yes, they talk like that, all the time. I've heard 'em say that if he
+was to get free they'd lynch him."
+
+"And they'd do it, too."
+
+The boys had a long talk, but it brought them little comfort. As the
+twilight drew on, they found themselves hanging about the neighborhood
+of the little isolated jail, perhaps with an undefined hope that
+something would happen that might clear away their difficulties. But
+nothing happened; there seemed to be no angels or fairies interested in
+this luckless captive.
+
+The boys did as they had often done before--went to the cell grating
+and gave Potter some tobacco and matches. He was on the ground floor
+and there were no guards.
+
+His gratitude for their gifts had always smote their consciences
+before--it cut deeper than ever, this time. They felt cowardly and
+treacherous to the last degree when Potter said:
+
+"You've been mighty good to me, boys--better'n anybody else in this
+town. And I don't forget it, I don't. Often I says to myself, says I,
+'I used to mend all the boys' kites and things, and show 'em where the
+good fishin' places was, and befriend 'em what I could, and now they've
+all forgot old Muff when he's in trouble; but Tom don't, and Huck
+don't--THEY don't forget him, says I, 'and I don't forget them.' Well,
+boys, I done an awful thing--drunk and crazy at the time--that's the
+only way I account for it--and now I got to swing for it, and it's
+right. Right, and BEST, too, I reckon--hope so, anyway. Well, we won't
+talk about that. I don't want to make YOU feel bad; you've befriended
+me. But what I want to say, is, don't YOU ever get drunk--then you won't
+ever get here. Stand a litter furder west--so--that's it; it's a prime
+comfort to see faces that's friendly when a body's in such a muck of
+trouble, and there don't none come here but yourn. Good friendly
+faces--good friendly faces. Git up on one another's backs and let me
+touch 'em. That's it. Shake hands--yourn'll come through the bars, but
+mine's too big. Little hands, and weak--but they've helped Muff Potter
+a power, and they'd help him more if they could."
+
+Tom went home miserable, and his dreams that night were full of
+horrors. The next day and the day after, he hung about the court-room,
+drawn by an almost irresistible impulse to go in, but forcing himself
+to stay out. Huck was having the same experience. They studiously
+avoided each other. Each wandered away, from time to time, but the same
+dismal fascination always brought them back presently. Tom kept his
+ears open when idlers sauntered out of the court-room, but invariably
+heard distressing news--the toils were closing more and more
+relentlessly around poor Potter. At the end of the second day the
+village talk was to the effect that Injun Joe's evidence stood firm and
+unshaken, and that there was not the slightest question as to what the
+jury's verdict would be.
+
+Tom was out late, that night, and came to bed through the window. He
+was in a tremendous state of excitement. It was hours before he got to
+sleep. All the village flocked to the court-house the next morning, for
+this was to be the great day. Both sexes were about equally represented
+in the packed audience. After a long wait the jury filed in and took
+their places; shortly afterward, Potter, pale and haggard, timid and
+hopeless, was brought in, with chains upon him, and seated where all
+the curious eyes could stare at him; no less conspicuous was Injun Joe,
+stolid as ever. There was another pause, and then the judge arrived and
+the sheriff proclaimed the opening of the court. The usual whisperings
+among the lawyers and gathering together of papers followed. These
+details and accompanying delays worked up an atmosphere of preparation
+that was as impressive as it was fascinating.
+
+Now a witness was called who testified that he found Muff Potter
+washing in the brook, at an early hour of the morning that the murder
+was discovered, and that he immediately sneaked away. After some
+further questioning, counsel for the prosecution said:
+
+"Take the witness."
+
+The prisoner raised his eyes for a moment, but dropped them again when
+his own counsel said:
+
+"I have no questions to ask him."
+
+The next witness proved the finding of the knife near the corpse.
+Counsel for the prosecution said:
+
+"Take the witness."
+
+"I have no questions to ask him," Potter's lawyer replied.
+
+A third witness swore he had often seen the knife in Potter's
+possession.
+
+"Take the witness."
+
+Counsel for Potter declined to question him. The faces of the audience
+began to betray annoyance. Did this attorney mean to throw away his
+client's life without an effort?
+
+Several witnesses deposed concerning Potter's guilty behavior when
+brought to the scene of the murder. They were allowed to leave the
+stand without being cross-questioned.
+
+Every detail of the damaging circumstances that occurred in the
+graveyard upon that morning which all present remembered so well was
+brought out by credible witnesses, but none of them were cross-examined
+by Potter's lawyer. The perplexity and dissatisfaction of the house
+expressed itself in murmurs and provoked a reproof from the bench.
+Counsel for the prosecution now said:
+
+"By the oaths of citizens whose simple word is above suspicion, we
+have fastened this awful crime, beyond all possibility of question,
+upon the unhappy prisoner at the bar. We rest our case here."
+
+A groan escaped from poor Potter, and he put his face in his hands and
+rocked his body softly to and fro, while a painful silence reigned in
+the court-room. Many men were moved, and many women's compassion
+testified itself in tears. Counsel for the defence rose and said:
+
+"Your honor, in our remarks at the opening of this trial, we
+foreshadowed our purpose to prove that our client did this fearful deed
+while under the influence of a blind and irresponsible delirium
+produced by drink. We have changed our mind. We shall not offer that
+plea." [Then to the clerk:] "Call Thomas Sawyer!"
+
+A puzzled amazement awoke in every face in the house, not even
+excepting Potter's. Every eye fastened itself with wondering interest
+upon Tom as he rose and took his place upon the stand. The boy looked
+wild enough, for he was badly scared. The oath was administered.
+
+"Thomas Sawyer, where were you on the seventeenth of June, about the
+hour of midnight?"
+
+Tom glanced at Injun Joe's iron face and his tongue failed him. The
+audience listened breathless, but the words refused to come. After a
+few moments, however, the boy got a little of his strength back, and
+managed to put enough of it into his voice to make part of the house
+hear:
+
+"In the graveyard!"
+
+"A little bit louder, please. Don't be afraid. You were--"
+
+"In the graveyard."
+
+A contemptuous smile flitted across Injun Joe's face.
+
+"Were you anywhere near Horse Williams' grave?"
+
+"Yes, sir."
+
+"Speak up--just a trifle louder. How near were you?"
+
+"Near as I am to you."
+
+"Were you hidden, or not?"
+
+"I was hid."
+
+"Where?"
+
+"Behind the elms that's on the edge of the grave."
+
+Injun Joe gave a barely perceptible start.
+
+"Any one with you?"
+
+"Yes, sir. I went there with--"
+
+"Wait--wait a moment. Never mind mentioning your companion's name. We
+will produce him at the proper time. Did you carry anything there with
+you."
+
+Tom hesitated and looked confused.
+
+"Speak out, my boy--don't be diffident. The truth is always
+respectable. What did you take there?"
+
+"Only a--a--dead cat."
+
+There was a ripple of mirth, which the court checked.
+
+"We will produce the skeleton of that cat. Now, my boy, tell us
+everything that occurred--tell it in your own way--don't skip anything,
+and don't be afraid."
+
+Tom began--hesitatingly at first, but as he warmed to his subject his
+words flowed more and more easily; in a little while every sound ceased
+but his own voice; every eye fixed itself upon him; with parted lips
+and bated breath the audience hung upon his words, taking no note of
+time, rapt in the ghastly fascinations of the tale. The strain upon
+pent emotion reached its climax when the boy said:
+
+"--and as the doctor fetched the board around and Muff Potter fell,
+Injun Joe jumped with the knife and--"
+
+Crash! Quick as lightning the half-breed sprang for a window, tore his
+way through all opposers, and was gone!
+
+
+
+CHAPTER XXIV
+
+TOM was a glittering hero once more--the pet of the old, the envy of
+the young. His name even went into immortal print, for the village
+paper magnified him. There were some that believed he would be
+President, yet, if he escaped hanging.
+
+As usual, the fickle, unreasoning world took Muff Potter to its bosom
+and fondled him as lavishly as it had abused him before. But that sort
+of conduct is to the world's credit; therefore it is not well to find
+fault with it.
+
+Tom's days were days of splendor and exultation to him, but his nights
+were seasons of horror. Injun Joe infested all his dreams, and always
+with doom in his eye. Hardly any temptation could persuade the boy to
+stir abroad after nightfall. Poor Huck was in the same state of
+wretchedness and terror, for Tom had told the whole story to the lawyer
+the night before the great day of the trial, and Huck was sore afraid
+that his share in the business might leak out, yet, notwithstanding
+Injun Joe's flight had saved him the suffering of testifying in court.
+The poor fellow had got the attorney to promise secrecy, but what of
+that? Since Tom's harassed conscience had managed to drive him to the
+lawyer's house by night and wring a dread tale from lips that had been
+sealed with the dismalest and most formidable of oaths, Huck's
+confidence in the human race was well-nigh obliterated.
+
+Daily Muff Potter's gratitude made Tom glad he had spoken; but nightly
+he wished he had sealed up his tongue.
+
+Half the time Tom was afraid Injun Joe would never be captured; the
+other half he was afraid he would be. He felt sure he never could draw
+a safe breath again until that man was dead and he had seen the corpse.
+
+Rewards had been offered, the country had been scoured, but no Injun
+Joe was found. One of those omniscient and awe-inspiring marvels, a
+detective, came up from St. Louis, moused around, shook his head,
+looked wise, and made that sort of astounding success which members of
+that craft usually achieve. That is to say, he "found a clew." But you
+can't hang a "clew" for murder, and so after that detective had got
+through and gone home, Tom felt just as insecure as he was before.
+
+The slow days drifted on, and each left behind it a slightly lightened
+weight of apprehension.
+
+
+
+CHAPTER XXV
+
+THERE comes a time in every rightly-constructed boy's life when he has
+a raging desire to go somewhere and dig for hidden treasure. This
+desire suddenly came upon Tom one day. He sallied out to find Joe
+Harper, but failed of success. Next he sought Ben Rogers; he had gone
+fishing. Presently he stumbled upon Huck Finn the Red-Handed. Huck
+would answer. Tom took him to a private place and opened the matter to
+him confidentially. Huck was willing. Huck was always willing to take a
+hand in any enterprise that offered entertainment and required no
+capital, for he had a troublesome superabundance of that sort of time
+which is not money. "Where'll we dig?" said Huck.
+
+"Oh, most anywhere."
+
+"Why, is it hid all around?"
+
+"No, indeed it ain't. It's hid in mighty particular places, Huck
+--sometimes on islands, sometimes in rotten chests under the end of a
+limb of an old dead tree, just where the shadow falls at midnight; but
+mostly under the floor in ha'nted houses."
+
+"Who hides it?"
+
+"Why, robbers, of course--who'd you reckon? Sunday-school
+sup'rintendents?"
+
+"I don't know. If 'twas mine I wouldn't hide it; I'd spend it and have
+a good time."
+
+"So would I. But robbers don't do that way. They always hide it and
+leave it there."
+
+"Don't they come after it any more?"
+
+"No, they think they will, but they generally forget the marks, or
+else they die. Anyway, it lays there a long time and gets rusty; and by
+and by somebody finds an old yellow paper that tells how to find the
+marks--a paper that's got to be ciphered over about a week because it's
+mostly signs and hy'roglyphics."
+
+"Hyro--which?"
+
+"Hy'roglyphics--pictures and things, you know, that don't seem to mean
+anything."
+
+"Have you got one of them papers, Tom?"
+
+"No."
+
+"Well then, how you going to find the marks?"
+
+"I don't want any marks. They always bury it under a ha'nted house or
+on an island, or under a dead tree that's got one limb sticking out.
+Well, we've tried Jackson's Island a little, and we can try it again
+some time; and there's the old ha'nted house up the Still-House branch,
+and there's lots of dead-limb trees--dead loads of 'em."
+
+"Is it under all of them?"
+
+"How you talk! No!"
+
+"Then how you going to know which one to go for?"
+
+"Go for all of 'em!"
+
+"Why, Tom, it'll take all summer."
+
+"Well, what of that? Suppose you find a brass pot with a hundred
+dollars in it, all rusty and gray, or rotten chest full of di'monds.
+How's that?"
+
+Huck's eyes glowed.
+
+"That's bully. Plenty bully enough for me. Just you gimme the hundred
+dollars and I don't want no di'monds."
+
+"All right. But I bet you I ain't going to throw off on di'monds. Some
+of 'em's worth twenty dollars apiece--there ain't any, hardly, but's
+worth six bits or a dollar."
+
+"No! Is that so?"
+
+"Cert'nly--anybody'll tell you so. Hain't you ever seen one, Huck?"
+
+"Not as I remember."
+
+"Oh, kings have slathers of them."
+
+"Well, I don' know no kings, Tom."
+
+"I reckon you don't. But if you was to go to Europe you'd see a raft
+of 'em hopping around."
+
+"Do they hop?"
+
+"Hop?--your granny! No!"
+
+"Well, what did you say they did, for?"
+
+"Shucks, I only meant you'd SEE 'em--not hopping, of course--what do
+they want to hop for?--but I mean you'd just see 'em--scattered around,
+you know, in a kind of a general way. Like that old humpbacked Richard."
+
+"Richard? What's his other name?"
+
+"He didn't have any other name. Kings don't have any but a given name."
+
+"No?"
+
+"But they don't."
+
+"Well, if they like it, Tom, all right; but I don't want to be a king
+and have only just a given name, like a nigger. But say--where you
+going to dig first?"
+
+"Well, I don't know. S'pose we tackle that old dead-limb tree on the
+hill t'other side of Still-House branch?"
+
+"I'm agreed."
+
+So they got a crippled pick and a shovel, and set out on their
+three-mile tramp. They arrived hot and panting, and threw themselves
+down in the shade of a neighboring elm to rest and have a smoke.
+
+"I like this," said Tom.
+
+"So do I."
+
+"Say, Huck, if we find a treasure here, what you going to do with your
+share?"
+
+"Well, I'll have pie and a glass of soda every day, and I'll go to
+every circus that comes along. I bet I'll have a gay time."
+
+"Well, ain't you going to save any of it?"
+
+"Save it? What for?"
+
+"Why, so as to have something to live on, by and by."
+
+"Oh, that ain't any use. Pap would come back to thish-yer town some
+day and get his claws on it if I didn't hurry up, and I tell you he'd
+clean it out pretty quick. What you going to do with yourn, Tom?"
+
+"I'm going to buy a new drum, and a sure-'nough sword, and a red
+necktie and a bull pup, and get married."
+
+"Married!"
+
+"That's it."
+
+"Tom, you--why, you ain't in your right mind."
+
+"Wait--you'll see."
+
+"Well, that's the foolishest thing you could do. Look at pap and my
+mother. Fight! Why, they used to fight all the time. I remember, mighty
+well."
+
+"That ain't anything. The girl I'm going to marry won't fight."
+
+"Tom, I reckon they're all alike. They'll all comb a body. Now you
+better think 'bout this awhile. I tell you you better. What's the name
+of the gal?"
+
+"It ain't a gal at all--it's a girl."
+
+"It's all the same, I reckon; some says gal, some says girl--both's
+right, like enough. Anyway, what's her name, Tom?"
+
+"I'll tell you some time--not now."
+
+"All right--that'll do. Only if you get married I'll be more lonesomer
+than ever."
+
+"No you won't. You'll come and live with me. Now stir out of this and
+we'll go to digging."
+
+They worked and sweated for half an hour. No result. They toiled
+another half-hour. Still no result. Huck said:
+
+"Do they always bury it as deep as this?"
+
+"Sometimes--not always. Not generally. I reckon we haven't got the
+right place."
+
+So they chose a new spot and began again. The labor dragged a little,
+but still they made progress. They pegged away in silence for some
+time. Finally Huck leaned on his shovel, swabbed the beaded drops from
+his brow with his sleeve, and said:
+
+"Where you going to dig next, after we get this one?"
+
+"I reckon maybe we'll tackle the old tree that's over yonder on
+Cardiff Hill back of the widow's."
+
+"I reckon that'll be a good one. But won't the widow take it away from
+us, Tom? It's on her land."
+
+"SHE take it away! Maybe she'd like to try it once. Whoever finds one
+of these hid treasures, it belongs to him. It don't make any difference
+whose land it's on."
+
+That was satisfactory. The work went on. By and by Huck said:
+
+"Blame it, we must be in the wrong place again. What do you think?"
+
+"It is mighty curious, Huck. I don't understand it. Sometimes witches
+interfere. I reckon maybe that's what's the trouble now."
+
+"Shucks! Witches ain't got no power in the daytime."
+
+"Well, that's so. I didn't think of that. Oh, I know what the matter
+is! What a blamed lot of fools we are! You got to find out where the
+shadow of the limb falls at midnight, and that's where you dig!"
+
+"Then consound it, we've fooled away all this work for nothing. Now
+hang it all, we got to come back in the night. It's an awful long way.
+Can you get out?"
+
+"I bet I will. We've got to do it to-night, too, because if somebody
+sees these holes they'll know in a minute what's here and they'll go
+for it."
+
+"Well, I'll come around and maow to-night."
+
+"All right. Let's hide the tools in the bushes."
+
+The boys were there that night, about the appointed time. They sat in
+the shadow waiting. It was a lonely place, and an hour made solemn by
+old traditions. Spirits whispered in the rustling leaves, ghosts lurked
+in the murky nooks, the deep baying of a hound floated up out of the
+distance, an owl answered with his sepulchral note. The boys were
+subdued by these solemnities, and talked little. By and by they judged
+that twelve had come; they marked where the shadow fell, and began to
+dig. Their hopes commenced to rise. Their interest grew stronger, and
+their industry kept pace with it. The hole deepened and still deepened,
+but every time their hearts jumped to hear the pick strike upon
+something, they only suffered a new disappointment. It was only a stone
+or a chunk. At last Tom said:
+
+"It ain't any use, Huck, we're wrong again."
+
+"Well, but we CAN'T be wrong. We spotted the shadder to a dot."
+
+"I know it, but then there's another thing."
+
+"What's that?".
+
+"Why, we only guessed at the time. Like enough it was too late or too
+early."
+
+Huck dropped his shovel.
+
+"That's it," said he. "That's the very trouble. We got to give this
+one up. We can't ever tell the right time, and besides this kind of
+thing's too awful, here this time of night with witches and ghosts
+a-fluttering around so. I feel as if something's behind me all the time;
+and I'm afeard to turn around, becuz maybe there's others in front
+a-waiting for a chance. I been creeping all over, ever since I got here."
+
+"Well, I've been pretty much so, too, Huck. They most always put in a
+dead man when they bury a treasure under a tree, to look out for it."
+
+"Lordy!"
+
+"Yes, they do. I've always heard that."
+
+"Tom, I don't like to fool around much where there's dead people. A
+body's bound to get into trouble with 'em, sure."
+
+"I don't like to stir 'em up, either. S'pose this one here was to
+stick his skull out and say something!"
+
+"Don't Tom! It's awful."
+
+"Well, it just is. Huck, I don't feel comfortable a bit."
+
+"Say, Tom, let's give this place up, and try somewheres else."
+
+"All right, I reckon we better."
+
+"What'll it be?"
+
+Tom considered awhile; and then said:
+
+"The ha'nted house. That's it!"
+
+"Blame it, I don't like ha'nted houses, Tom. Why, they're a dern sight
+worse'n dead people. Dead people might talk, maybe, but they don't come
+sliding around in a shroud, when you ain't noticing, and peep over your
+shoulder all of a sudden and grit their teeth, the way a ghost does. I
+couldn't stand such a thing as that, Tom--nobody could."
+
+"Yes, but, Huck, ghosts don't travel around only at night. They won't
+hender us from digging there in the daytime."
+
+"Well, that's so. But you know mighty well people don't go about that
+ha'nted house in the day nor the night."
+
+"Well, that's mostly because they don't like to go where a man's been
+murdered, anyway--but nothing's ever been seen around that house except
+in the night--just some blue lights slipping by the windows--no regular
+ghosts."
+
+"Well, where you see one of them blue lights flickering around, Tom,
+you can bet there's a ghost mighty close behind it. It stands to
+reason. Becuz you know that they don't anybody but ghosts use 'em."
+
+"Yes, that's so. But anyway they don't come around in the daytime, so
+what's the use of our being afeard?"
+
+"Well, all right. We'll tackle the ha'nted house if you say so--but I
+reckon it's taking chances."
+
+They had started down the hill by this time. There in the middle of
+the moonlit valley below them stood the "ha'nted" house, utterly
+isolated, its fences gone long ago, rank weeds smothering the very
+doorsteps, the chimney crumbled to ruin, the window-sashes vacant, a
+corner of the roof caved in. The boys gazed awhile, half expecting to
+see a blue light flit past a window; then talking in a low tone, as
+befitted the time and the circumstances, they struck far off to the
+right, to give the haunted house a wide berth, and took their way
+homeward through the woods that adorned the rearward side of Cardiff
+Hill.
+
+
+
+CHAPTER XXVI
+
+ABOUT noon the next day the boys arrived at the dead tree; they had
+come for their tools. Tom was impatient to go to the haunted house;
+Huck was measurably so, also--but suddenly said:
+
+"Lookyhere, Tom, do you know what day it is?"
+
+Tom mentally ran over the days of the week, and then quickly lifted
+his eyes with a startled look in them--
+
+"My! I never once thought of it, Huck!"
+
+"Well, I didn't neither, but all at once it popped onto me that it was
+Friday."
+
+"Blame it, a body can't be too careful, Huck. We might 'a' got into an
+awful scrape, tackling such a thing on a Friday."
+
+"MIGHT! Better say we WOULD! There's some lucky days, maybe, but
+Friday ain't."
+
+"Any fool knows that. I don't reckon YOU was the first that found it
+out, Huck."
+
+"Well, I never said I was, did I? And Friday ain't all, neither. I had
+a rotten bad dream last night--dreampt about rats."
+
+"No! Sure sign of trouble. Did they fight?"
+
+"No."
+
+"Well, that's good, Huck. When they don't fight it's only a sign that
+there's trouble around, you know. All we got to do is to look mighty
+sharp and keep out of it. We'll drop this thing for to-day, and play.
+Do you know Robin Hood, Huck?"
+
+"No. Who's Robin Hood?"
+
+"Why, he was one of the greatest men that was ever in England--and the
+best. He was a robber."
+
+"Cracky, I wisht I was. Who did he rob?"
+
+"Only sheriffs and bishops and rich people and kings, and such like.
+But he never bothered the poor. He loved 'em. He always divided up with
+'em perfectly square."
+
+"Well, he must 'a' been a brick."
+
+"I bet you he was, Huck. Oh, he was the noblest man that ever was.
+They ain't any such men now, I can tell you. He could lick any man in
+England, with one hand tied behind him; and he could take his yew bow
+and plug a ten-cent piece every time, a mile and a half."
+
+"What's a YEW bow?"
+
+"I don't know. It's some kind of a bow, of course. And if he hit that
+dime only on the edge he would set down and cry--and curse. But we'll
+play Robin Hood--it's nobby fun. I'll learn you."
+
+"I'm agreed."
+
+So they played Robin Hood all the afternoon, now and then casting a
+yearning eye down upon the haunted house and passing a remark about the
+morrow's prospects and possibilities there. As the sun began to sink
+into the west they took their way homeward athwart the long shadows of
+the trees and soon were buried from sight in the forests of Cardiff
+Hill.
+
+On Saturday, shortly after noon, the boys were at the dead tree again.
+They had a smoke and a chat in the shade, and then dug a little in
+their last hole, not with great hope, but merely because Tom said there
+were so many cases where people had given up a treasure after getting
+down within six inches of it, and then somebody else had come along and
+turned it up with a single thrust of a shovel. The thing failed this
+time, however, so the boys shouldered their tools and went away feeling
+that they had not trifled with fortune, but had fulfilled all the
+requirements that belong to the business of treasure-hunting.
+
+When they reached the haunted house there was something so weird and
+grisly about the dead silence that reigned there under the baking sun,
+and something so depressing about the loneliness and desolation of the
+place, that they were afraid, for a moment, to venture in. Then they
+crept to the door and took a trembling peep. They saw a weed-grown,
+floorless room, unplastered, an ancient fireplace, vacant windows, a
+ruinous staircase; and here, there, and everywhere hung ragged and
+abandoned cobwebs. They presently entered, softly, with quickened
+pulses, talking in whispers, ears alert to catch the slightest sound,
+and muscles tense and ready for instant retreat.
+
+In a little while familiarity modified their fears and they gave the
+place a critical and interested examination, rather admiring their own
+boldness, and wondering at it, too. Next they wanted to look up-stairs.
+This was something like cutting off retreat, but they got to daring
+each other, and of course there could be but one result--they threw
+their tools into a corner and made the ascent. Up there were the same
+signs of decay. In one corner they found a closet that promised
+mystery, but the promise was a fraud--there was nothing in it. Their
+courage was up now and well in hand. They were about to go down and
+begin work when--
+
+"Sh!" said Tom.
+
+"What is it?" whispered Huck, blanching with fright.
+
+"Sh!... There!... Hear it?"
+
+"Yes!... Oh, my! Let's run!"
+
+"Keep still! Don't you budge! They're coming right toward the door."
+
+The boys stretched themselves upon the floor with their eyes to
+knot-holes in the planking, and lay waiting, in a misery of fear.
+
+"They've stopped.... No--coming.... Here they are. Don't whisper
+another word, Huck. My goodness, I wish I was out of this!"
+
+Two men entered. Each boy said to himself: "There's the old deaf and
+dumb Spaniard that's been about town once or twice lately--never saw
+t'other man before."
+
+"T'other" was a ragged, unkempt creature, with nothing very pleasant
+in his face. The Spaniard was wrapped in a serape; he had bushy white
+whiskers; long white hair flowed from under his sombrero, and he wore
+green goggles. When they came in, "t'other" was talking in a low voice;
+they sat down on the ground, facing the door, with their backs to the
+wall, and the speaker continued his remarks. His manner became less
+guarded and his words more distinct as he proceeded:
+
+"No," said he, "I've thought it all over, and I don't like it. It's
+dangerous."
+
+"Dangerous!" grunted the "deaf and dumb" Spaniard--to the vast
+surprise of the boys. "Milksop!"
+
+This voice made the boys gasp and quake. It was Injun Joe's! There was
+silence for some time. Then Joe said:
+
+"What's any more dangerous than that job up yonder--but nothing's come
+of it."
+
+"That's different. Away up the river so, and not another house about.
+'Twon't ever be known that we tried, anyway, long as we didn't succeed."
+
+"Well, what's more dangerous than coming here in the daytime!--anybody
+would suspicion us that saw us."
+
+"I know that. But there warn't any other place as handy after that
+fool of a job. I want to quit this shanty. I wanted to yesterday, only
+it warn't any use trying to stir out of here, with those infernal boys
+playing over there on the hill right in full view."
+
+"Those infernal boys" quaked again under the inspiration of this
+remark, and thought how lucky it was that they had remembered it was
+Friday and concluded to wait a day. They wished in their hearts they
+had waited a year.
+
+The two men got out some food and made a luncheon. After a long and
+thoughtful silence, Injun Joe said:
+
+"Look here, lad--you go back up the river where you belong. Wait there
+till you hear from me. I'll take the chances on dropping into this town
+just once more, for a look. We'll do that 'dangerous' job after I've
+spied around a little and think things look well for it. Then for
+Texas! We'll leg it together!"
+
+This was satisfactory. Both men presently fell to yawning, and Injun
+Joe said:
+
+"I'm dead for sleep! It's your turn to watch."
+
+He curled down in the weeds and soon began to snore. His comrade
+stirred him once or twice and he became quiet. Presently the watcher
+began to nod; his head drooped lower and lower, both men began to snore
+now.
+
+The boys drew a long, grateful breath. Tom whispered:
+
+"Now's our chance--come!"
+
+Huck said:
+
+"I can't--I'd die if they was to wake."
+
+Tom urged--Huck held back. At last Tom rose slowly and softly, and
+started alone. But the first step he made wrung such a hideous creak
+from the crazy floor that he sank down almost dead with fright. He
+never made a second attempt. The boys lay there counting the dragging
+moments till it seemed to them that time must be done and eternity
+growing gray; and then they were grateful to note that at last the sun
+was setting.
+
+Now one snore ceased. Injun Joe sat up, stared around--smiled grimly
+upon his comrade, whose head was drooping upon his knees--stirred him
+up with his foot and said:
+
+"Here! YOU'RE a watchman, ain't you! All right, though--nothing's
+happened."
+
+"My! have I been asleep?"
+
+"Oh, partly, partly. Nearly time for us to be moving, pard. What'll we
+do with what little swag we've got left?"
+
+"I don't know--leave it here as we've always done, I reckon. No use to
+take it away till we start south. Six hundred and fifty in silver's
+something to carry."
+
+"Well--all right--it won't matter to come here once more."
+
+"No--but I'd say come in the night as we used to do--it's better."
+
+"Yes: but look here; it may be a good while before I get the right
+chance at that job; accidents might happen; 'tain't in such a very good
+place; we'll just regularly bury it--and bury it deep."
+
+"Good idea," said the comrade, who walked across the room, knelt down,
+raised one of the rearward hearth-stones and took out a bag that
+jingled pleasantly. He subtracted from it twenty or thirty dollars for
+himself and as much for Injun Joe, and passed the bag to the latter,
+who was on his knees in the corner, now, digging with his bowie-knife.
+
+The boys forgot all their fears, all their miseries in an instant.
+With gloating eyes they watched every movement. Luck!--the splendor of
+it was beyond all imagination! Six hundred dollars was money enough to
+make half a dozen boys rich! Here was treasure-hunting under the
+happiest auspices--there would not be any bothersome uncertainty as to
+where to dig. They nudged each other every moment--eloquent nudges and
+easily understood, for they simply meant--"Oh, but ain't you glad NOW
+we're here!"
+
+Joe's knife struck upon something.
+
+"Hello!" said he.
+
+"What is it?" said his comrade.
+
+"Half-rotten plank--no, it's a box, I believe. Here--bear a hand and
+we'll see what it's here for. Never mind, I've broke a hole."
+
+He reached his hand in and drew it out--
+
+"Man, it's money!"
+
+The two men examined the handful of coins. They were gold. The boys
+above were as excited as themselves, and as delighted.
+
+Joe's comrade said:
+
+"We'll make quick work of this. There's an old rusty pick over amongst
+the weeds in the corner the other side of the fireplace--I saw it a
+minute ago."
+
+He ran and brought the boys' pick and shovel. Injun Joe took the pick,
+looked it over critically, shook his head, muttered something to
+himself, and then began to use it. The box was soon unearthed. It was
+not very large; it was iron bound and had been very strong before the
+slow years had injured it. The men contemplated the treasure awhile in
+blissful silence.
+
+"Pard, there's thousands of dollars here," said Injun Joe.
+
+"'Twas always said that Murrel's gang used to be around here one
+summer," the stranger observed.
+
+"I know it," said Injun Joe; "and this looks like it, I should say."
+
+"Now you won't need to do that job."
+
+The half-breed frowned. Said he:
+
+"You don't know me. Least you don't know all about that thing. 'Tain't
+robbery altogether--it's REVENGE!" and a wicked light flamed in his
+eyes. "I'll need your help in it. When it's finished--then Texas. Go
+home to your Nance and your kids, and stand by till you hear from me."
+
+"Well--if you say so; what'll we do with this--bury it again?"
+
+"Yes. [Ravishing delight overhead.] NO! by the great Sachem, no!
+[Profound distress overhead.] I'd nearly forgot. That pick had fresh
+earth on it! [The boys were sick with terror in a moment.] What
+business has a pick and a shovel here? What business with fresh earth
+on them? Who brought them here--and where are they gone? Have you heard
+anybody?--seen anybody? What! bury it again and leave them to come and
+see the ground disturbed? Not exactly--not exactly. We'll take it to my
+den."
+
+"Why, of course! Might have thought of that before. You mean Number
+One?"
+
+"No--Number Two--under the cross. The other place is bad--too common."
+
+"All right. It's nearly dark enough to start."
+
+Injun Joe got up and went about from window to window cautiously
+peeping out. Presently he said:
+
+"Who could have brought those tools here? Do you reckon they can be
+up-stairs?"
+
+The boys' breath forsook them. Injun Joe put his hand on his knife,
+halted a moment, undecided, and then turned toward the stairway. The
+boys thought of the closet, but their strength was gone. The steps came
+creaking up the stairs--the intolerable distress of the situation woke
+the stricken resolution of the lads--they were about to spring for the
+closet, when there was a crash of rotten timbers and Injun Joe landed
+on the ground amid the debris of the ruined stairway. He gathered
+himself up cursing, and his comrade said:
+
+"Now what's the use of all that? If it's anybody, and they're up
+there, let them STAY there--who cares? If they want to jump down, now,
+and get into trouble, who objects? It will be dark in fifteen minutes
+--and then let them follow us if they want to. I'm willing. In my
+opinion, whoever hove those things in here caught a sight of us and
+took us for ghosts or devils or something. I'll bet they're running
+yet."
+
+Joe grumbled awhile; then he agreed with his friend that what daylight
+was left ought to be economized in getting things ready for leaving.
+Shortly afterward they slipped out of the house in the deepening
+twilight, and moved toward the river with their precious box.
+
+Tom and Huck rose up, weak but vastly relieved, and stared after them
+through the chinks between the logs of the house. Follow? Not they.
+They were content to reach ground again without broken necks, and take
+the townward track over the hill. They did not talk much. They were too
+much absorbed in hating themselves--hating the ill luck that made them
+take the spade and the pick there. But for that, Injun Joe never would
+have suspected. He would have hidden the silver with the gold to wait
+there till his "revenge" was satisfied, and then he would have had the
+misfortune to find that money turn up missing. Bitter, bitter luck that
+the tools were ever brought there!
+
+They resolved to keep a lookout for that Spaniard when he should come
+to town spying out for chances to do his revengeful job, and follow him
+to "Number Two," wherever that might be. Then a ghastly thought
+occurred to Tom.
+
+"Revenge? What if he means US, Huck!"
+
+"Oh, don't!" said Huck, nearly fainting.
+
+They talked it all over, and as they entered town they agreed to
+believe that he might possibly mean somebody else--at least that he
+might at least mean nobody but Tom, since only Tom had testified.
+
+Very, very small comfort it was to Tom to be alone in danger! Company
+would be a palpable improvement, he thought.
+
+
+
+CHAPTER XXVII
+
+THE adventure of the day mightily tormented Tom's dreams that night.
+Four times he had his hands on that rich treasure and four times it
+wasted to nothingness in his fingers as sleep forsook him and
+wakefulness brought back the hard reality of his misfortune. As he lay
+in the early morning recalling the incidents of his great adventure, he
+noticed that they seemed curiously subdued and far away--somewhat as if
+they had happened in another world, or in a time long gone by. Then it
+occurred to him that the great adventure itself must be a dream! There
+was one very strong argument in favor of this idea--namely, that the
+quantity of coin he had seen was too vast to be real. He had never seen
+as much as fifty dollars in one mass before, and he was like all boys
+of his age and station in life, in that he imagined that all references
+to "hundreds" and "thousands" were mere fanciful forms of speech, and
+that no such sums really existed in the world. He never had supposed
+for a moment that so large a sum as a hundred dollars was to be found
+in actual money in any one's possession. If his notions of hidden
+treasure had been analyzed, they would have been found to consist of a
+handful of real dimes and a bushel of vague, splendid, ungraspable
+dollars.
+
+But the incidents of his adventure grew sensibly sharper and clearer
+under the attrition of thinking them over, and so he presently found
+himself leaning to the impression that the thing might not have been a
+dream, after all. This uncertainty must be swept away. He would snatch
+a hurried breakfast and go and find Huck. Huck was sitting on the
+gunwale of a flatboat, listlessly dangling his feet in the water and
+looking very melancholy. Tom concluded to let Huck lead up to the
+subject. If he did not do it, then the adventure would be proved to
+have been only a dream.
+
+"Hello, Huck!"
+
+"Hello, yourself."
+
+Silence, for a minute.
+
+"Tom, if we'd 'a' left the blame tools at the dead tree, we'd 'a' got
+the money. Oh, ain't it awful!"
+
+"'Tain't a dream, then, 'tain't a dream! Somehow I most wish it was.
+Dog'd if I don't, Huck."
+
+"What ain't a dream?"
+
+"Oh, that thing yesterday. I been half thinking it was."
+
+"Dream! If them stairs hadn't broke down you'd 'a' seen how much dream
+it was! I've had dreams enough all night--with that patch-eyed Spanish
+devil going for me all through 'em--rot him!"
+
+"No, not rot him. FIND him! Track the money!"
+
+"Tom, we'll never find him. A feller don't have only one chance for
+such a pile--and that one's lost. I'd feel mighty shaky if I was to see
+him, anyway."
+
+"Well, so'd I; but I'd like to see him, anyway--and track him out--to
+his Number Two."
+
+"Number Two--yes, that's it. I been thinking 'bout that. But I can't
+make nothing out of it. What do you reckon it is?"
+
+"I dono. It's too deep. Say, Huck--maybe it's the number of a house!"
+
+"Goody!... No, Tom, that ain't it. If it is, it ain't in this
+one-horse town. They ain't no numbers here."
+
+"Well, that's so. Lemme think a minute. Here--it's the number of a
+room--in a tavern, you know!"
+
+"Oh, that's the trick! They ain't only two taverns. We can find out
+quick."
+
+"You stay here, Huck, till I come."
+
+Tom was off at once. He did not care to have Huck's company in public
+places. He was gone half an hour. He found that in the best tavern, No.
+2 had long been occupied by a young lawyer, and was still so occupied.
+In the less ostentatious house, No. 2 was a mystery. The
+tavern-keeper's young son said it was kept locked all the time, and he
+never saw anybody go into it or come out of it except at night; he did
+not know any particular reason for this state of things; had had some
+little curiosity, but it was rather feeble; had made the most of the
+mystery by entertaining himself with the idea that that room was
+"ha'nted"; had noticed that there was a light in there the night before.
+
+"That's what I've found out, Huck. I reckon that's the very No. 2
+we're after."
+
+"I reckon it is, Tom. Now what you going to do?"
+
+"Lemme think."
+
+Tom thought a long time. Then he said:
+
+"I'll tell you. The back door of that No. 2 is the door that comes out
+into that little close alley between the tavern and the old rattle trap
+of a brick store. Now you get hold of all the door-keys you can find,
+and I'll nip all of auntie's, and the first dark night we'll go there
+and try 'em. And mind you, keep a lookout for Injun Joe, because he
+said he was going to drop into town and spy around once more for a
+chance to get his revenge. If you see him, you just follow him; and if
+he don't go to that No. 2, that ain't the place."
+
+"Lordy, I don't want to foller him by myself!"
+
+"Why, it'll be night, sure. He mightn't ever see you--and if he did,
+maybe he'd never think anything."
+
+"Well, if it's pretty dark I reckon I'll track him. I dono--I dono.
+I'll try."
+
+"You bet I'll follow him, if it's dark, Huck. Why, he might 'a' found
+out he couldn't get his revenge, and be going right after that money."
+
+"It's so, Tom, it's so. I'll foller him; I will, by jingoes!"
+
+"Now you're TALKING! Don't you ever weaken, Huck, and I won't."
+
+
+
+CHAPTER XXVIII
+
+THAT night Tom and Huck were ready for their adventure. They hung
+about the neighborhood of the tavern until after nine, one watching the
+alley at a distance and the other the tavern door. Nobody entered the
+alley or left it; nobody resembling the Spaniard entered or left the
+tavern door. The night promised to be a fair one; so Tom went home with
+the understanding that if a considerable degree of darkness came on,
+Huck was to come and "maow," whereupon he would slip out and try the
+keys. But the night remained clear, and Huck closed his watch and
+retired to bed in an empty sugar hogshead about twelve.
+
+Tuesday the boys had the same ill luck. Also Wednesday. But Thursday
+night promised better. Tom slipped out in good season with his aunt's
+old tin lantern, and a large towel to blindfold it with. He hid the
+lantern in Huck's sugar hogshead and the watch began. An hour before
+midnight the tavern closed up and its lights (the only ones
+thereabouts) were put out. No Spaniard had been seen. Nobody had
+entered or left the alley. Everything was auspicious. The blackness of
+darkness reigned, the perfect stillness was interrupted only by
+occasional mutterings of distant thunder.
+
+Tom got his lantern, lit it in the hogshead, wrapped it closely in the
+towel, and the two adventurers crept in the gloom toward the tavern.
+Huck stood sentry and Tom felt his way into the alley. Then there was a
+season of waiting anxiety that weighed upon Huck's spirits like a
+mountain. He began to wish he could see a flash from the lantern--it
+would frighten him, but it would at least tell him that Tom was alive
+yet. It seemed hours since Tom had disappeared. Surely he must have
+fainted; maybe he was dead; maybe his heart had burst under terror and
+excitement. In his uneasiness Huck found himself drawing closer and
+closer to the alley; fearing all sorts of dreadful things, and
+momentarily expecting some catastrophe to happen that would take away
+his breath. There was not much to take away, for he seemed only able to
+inhale it by thimblefuls, and his heart would soon wear itself out, the
+way it was beating. Suddenly there was a flash of light and Tom came
+tearing by him: "Run!" said he; "run, for your life!"
+
+He needn't have repeated it; once was enough; Huck was making thirty
+or forty miles an hour before the repetition was uttered. The boys
+never stopped till they reached the shed of a deserted slaughter-house
+at the lower end of the village. Just as they got within its shelter
+the storm burst and the rain poured down. As soon as Tom got his breath
+he said:
+
+"Huck, it was awful! I tried two of the keys, just as soft as I could;
+but they seemed to make such a power of racket that I couldn't hardly
+get my breath I was so scared. They wouldn't turn in the lock, either.
+Well, without noticing what I was doing, I took hold of the knob, and
+open comes the door! It warn't locked! I hopped in, and shook off the
+towel, and, GREAT CAESAR'S GHOST!"
+
+"What!--what'd you see, Tom?"
+
+"Huck, I most stepped onto Injun Joe's hand!"
+
+"No!"
+
+"Yes! He was lying there, sound asleep on the floor, with his old
+patch on his eye and his arms spread out."
+
+"Lordy, what did you do? Did he wake up?"
+
+"No, never budged. Drunk, I reckon. I just grabbed that towel and
+started!"
+
+"I'd never 'a' thought of the towel, I bet!"
+
+"Well, I would. My aunt would make me mighty sick if I lost it."
+
+"Say, Tom, did you see that box?"
+
+"Huck, I didn't wait to look around. I didn't see the box, I didn't
+see the cross. I didn't see anything but a bottle and a tin cup on the
+floor by Injun Joe; yes, I saw two barrels and lots more bottles in the
+room. Don't you see, now, what's the matter with that ha'nted room?"
+
+"How?"
+
+"Why, it's ha'nted with whiskey! Maybe ALL the Temperance Taverns have
+got a ha'nted room, hey, Huck?"
+
+"Well, I reckon maybe that's so. Who'd 'a' thought such a thing? But
+say, Tom, now's a mighty good time to get that box, if Injun Joe's
+drunk."
+
+"It is, that! You try it!"
+
+Huck shuddered.
+
+"Well, no--I reckon not."
+
+"And I reckon not, Huck. Only one bottle alongside of Injun Joe ain't
+enough. If there'd been three, he'd be drunk enough and I'd do it."
+
+There was a long pause for reflection, and then Tom said:
+
+"Lookyhere, Huck, less not try that thing any more till we know Injun
+Joe's not in there. It's too scary. Now, if we watch every night, we'll
+be dead sure to see him go out, some time or other, and then we'll
+snatch that box quicker'n lightning."
+
+"Well, I'm agreed. I'll watch the whole night long, and I'll do it
+every night, too, if you'll do the other part of the job."
+
+"All right, I will. All you got to do is to trot up Hooper Street a
+block and maow--and if I'm asleep, you throw some gravel at the window
+and that'll fetch me."
+
+"Agreed, and good as wheat!"
+
+"Now, Huck, the storm's over, and I'll go home. It'll begin to be
+daylight in a couple of hours. You go back and watch that long, will
+you?"
+
+"I said I would, Tom, and I will. I'll ha'nt that tavern every night
+for a year! I'll sleep all day and I'll stand watch all night."
+
+"That's all right. Now, where you going to sleep?"
+
+"In Ben Rogers' hayloft. He lets me, and so does his pap's nigger man,
+Uncle Jake. I tote water for Uncle Jake whenever he wants me to, and
+any time I ask him he gives me a little something to eat if he can
+spare it. That's a mighty good nigger, Tom. He likes me, becuz I don't
+ever act as if I was above him. Sometime I've set right down and eat
+WITH him. But you needn't tell that. A body's got to do things when
+he's awful hungry he wouldn't want to do as a steady thing."
+
+"Well, if I don't want you in the daytime, I'll let you sleep. I won't
+come bothering around. Any time you see something's up, in the night,
+just skip right around and maow."
+
+
+
+CHAPTER XXIX
+
+THE first thing Tom heard on Friday morning was a glad piece of news
+--Judge Thatcher's family had come back to town the night before. Both
+Injun Joe and the treasure sunk into secondary importance for a moment,
+and Becky took the chief place in the boy's interest. He saw her and
+they had an exhausting good time playing "hi-spy" and "gully-keeper"
+with a crowd of their school-mates. The day was completed and crowned
+in a peculiarly satisfactory way: Becky teased her mother to appoint
+the next day for the long-promised and long-delayed picnic, and she
+consented. The child's delight was boundless; and Tom's not more
+moderate. The invitations were sent out before sunset, and straightway
+the young folks of the village were thrown into a fever of preparation
+and pleasurable anticipation. Tom's excitement enabled him to keep
+awake until a pretty late hour, and he had good hopes of hearing Huck's
+"maow," and of having his treasure to astonish Becky and the picnickers
+with, next day; but he was disappointed. No signal came that night.
+
+Morning came, eventually, and by ten or eleven o'clock a giddy and
+rollicking company were gathered at Judge Thatcher's, and everything
+was ready for a start. It was not the custom for elderly people to mar
+the picnics with their presence. The children were considered safe
+enough under the wings of a few young ladies of eighteen and a few
+young gentlemen of twenty-three or thereabouts. The old steam ferryboat
+was chartered for the occasion; presently the gay throng filed up the
+main street laden with provision-baskets. Sid was sick and had to miss
+the fun; Mary remained at home to entertain him. The last thing Mrs.
+Thatcher said to Becky, was:
+
+"You'll not get back till late. Perhaps you'd better stay all night
+with some of the girls that live near the ferry-landing, child."
+
+"Then I'll stay with Susy Harper, mamma."
+
+"Very well. And mind and behave yourself and don't be any trouble."
+
+Presently, as they tripped along, Tom said to Becky:
+
+"Say--I'll tell you what we'll do. 'Stead of going to Joe Harper's
+we'll climb right up the hill and stop at the Widow Douglas'. She'll
+have ice-cream! She has it most every day--dead loads of it. And she'll
+be awful glad to have us."
+
+"Oh, that will be fun!"
+
+Then Becky reflected a moment and said:
+
+"But what will mamma say?"
+
+"How'll she ever know?"
+
+The girl turned the idea over in her mind, and said reluctantly:
+
+"I reckon it's wrong--but--"
+
+"But shucks! Your mother won't know, and so what's the harm? All she
+wants is that you'll be safe; and I bet you she'd 'a' said go there if
+she'd 'a' thought of it. I know she would!"
+
+The Widow Douglas' splendid hospitality was a tempting bait. It and
+Tom's persuasions presently carried the day. So it was decided to say
+nothing anybody about the night's programme. Presently it occurred to
+Tom that maybe Huck might come this very night and give the signal. The
+thought took a deal of the spirit out of his anticipations. Still he
+could not bear to give up the fun at Widow Douglas'. And why should he
+give it up, he reasoned--the signal did not come the night before, so
+why should it be any more likely to come to-night? The sure fun of the
+evening outweighed the uncertain treasure; and, boy-like, he determined
+to yield to the stronger inclination and not allow himself to think of
+the box of money another time that day.
+
+Three miles below town the ferryboat stopped at the mouth of a woody
+hollow and tied up. The crowd swarmed ashore and soon the forest
+distances and craggy heights echoed far and near with shoutings and
+laughter. All the different ways of getting hot and tired were gone
+through with, and by-and-by the rovers straggled back to camp fortified
+with responsible appetites, and then the destruction of the good things
+began. After the feast there was a refreshing season of rest and chat
+in the shade of spreading oaks. By-and-by somebody shouted:
+
+"Who's ready for the cave?"
+
+Everybody was. Bundles of candles were procured, and straightway there
+was a general scamper up the hill. The mouth of the cave was up the
+hillside--an opening shaped like a letter A. Its massive oaken door
+stood unbarred. Within was a small chamber, chilly as an ice-house, and
+walled by Nature with solid limestone that was dewy with a cold sweat.
+It was romantic and mysterious to stand here in the deep gloom and look
+out upon the green valley shining in the sun. But the impressiveness of
+the situation quickly wore off, and the romping began again. The moment
+a candle was lighted there was a general rush upon the owner of it; a
+struggle and a gallant defence followed, but the candle was soon
+knocked down or blown out, and then there was a glad clamor of laughter
+and a new chase. But all things have an end. By-and-by the procession
+went filing down the steep descent of the main avenue, the flickering
+rank of lights dimly revealing the lofty walls of rock almost to their
+point of junction sixty feet overhead. This main avenue was not more
+than eight or ten feet wide. Every few steps other lofty and still
+narrower crevices branched from it on either hand--for McDougal's cave
+was but a vast labyrinth of crooked aisles that ran into each other and
+out again and led nowhere. It was said that one might wander days and
+nights together through its intricate tangle of rifts and chasms, and
+never find the end of the cave; and that he might go down, and down,
+and still down, into the earth, and it was just the same--labyrinth
+under labyrinth, and no end to any of them. No man "knew" the cave.
+That was an impossible thing. Most of the young men knew a portion of
+it, and it was not customary to venture much beyond this known portion.
+Tom Sawyer knew as much of the cave as any one.
+
+The procession moved along the main avenue some three-quarters of a
+mile, and then groups and couples began to slip aside into branch
+avenues, fly along the dismal corridors, and take each other by
+surprise at points where the corridors joined again. Parties were able
+to elude each other for the space of half an hour without going beyond
+the "known" ground.
+
+By-and-by, one group after another came straggling back to the mouth
+of the cave, panting, hilarious, smeared from head to foot with tallow
+drippings, daubed with clay, and entirely delighted with the success of
+the day. Then they were astonished to find that they had been taking no
+note of time and that night was about at hand. The clanging bell had
+been calling for half an hour. However, this sort of close to the day's
+adventures was romantic and therefore satisfactory. When the ferryboat
+with her wild freight pushed into the stream, nobody cared sixpence for
+the wasted time but the captain of the craft.
+
+Huck was already upon his watch when the ferryboat's lights went
+glinting past the wharf. He heard no noise on board, for the young
+people were as subdued and still as people usually are who are nearly
+tired to death. He wondered what boat it was, and why she did not stop
+at the wharf--and then he dropped her out of his mind and put his
+attention upon his business. The night was growing cloudy and dark. Ten
+o'clock came, and the noise of vehicles ceased, scattered lights began
+to wink out, all straggling foot-passengers disappeared, the village
+betook itself to its slumbers and left the small watcher alone with the
+silence and the ghosts. Eleven o'clock came, and the tavern lights were
+put out; darkness everywhere, now. Huck waited what seemed a weary long
+time, but nothing happened. His faith was weakening. Was there any use?
+Was there really any use? Why not give it up and turn in?
+
+A noise fell upon his ear. He was all attention in an instant. The
+alley door closed softly. He sprang to the corner of the brick store.
+The next moment two men brushed by him, and one seemed to have
+something under his arm. It must be that box! So they were going to
+remove the treasure. Why call Tom now? It would be absurd--the men
+would get away with the box and never be found again. No, he would
+stick to their wake and follow them; he would trust to the darkness for
+security from discovery. So communing with himself, Huck stepped out
+and glided along behind the men, cat-like, with bare feet, allowing
+them to keep just far enough ahead not to be invisible.
+
+They moved up the river street three blocks, then turned to the left
+up a cross-street. They went straight ahead, then, until they came to
+the path that led up Cardiff Hill; this they took. They passed by the
+old Welshman's house, half-way up the hill, without hesitating, and
+still climbed upward. Good, thought Huck, they will bury it in the old
+quarry. But they never stopped at the quarry. They passed on, up the
+summit. They plunged into the narrow path between the tall sumach
+bushes, and were at once hidden in the gloom. Huck closed up and
+shortened his distance, now, for they would never be able to see him.
+He trotted along awhile; then slackened his pace, fearing he was
+gaining too fast; moved on a piece, then stopped altogether; listened;
+no sound; none, save that he seemed to hear the beating of his own
+heart. The hooting of an owl came over the hill--ominous sound! But no
+footsteps. Heavens, was everything lost! He was about to spring with
+winged feet, when a man cleared his throat not four feet from him!
+Huck's heart shot into his throat, but he swallowed it again; and then
+he stood there shaking as if a dozen agues had taken charge of him at
+once, and so weak that he thought he must surely fall to the ground. He
+knew where he was. He knew he was within five steps of the stile
+leading into Widow Douglas' grounds. Very well, he thought, let them
+bury it there; it won't be hard to find.
+
+Now there was a voice--a very low voice--Injun Joe's:
+
+"Damn her, maybe she's got company--there's lights, late as it is."
+
+"I can't see any."
+
+This was that stranger's voice--the stranger of the haunted house. A
+deadly chill went to Huck's heart--this, then, was the "revenge" job!
+His thought was, to fly. Then he remembered that the Widow Douglas had
+been kind to him more than once, and maybe these men were going to
+murder her. He wished he dared venture to warn her; but he knew he
+didn't dare--they might come and catch him. He thought all this and
+more in the moment that elapsed between the stranger's remark and Injun
+Joe's next--which was--
+
+"Because the bush is in your way. Now--this way--now you see, don't
+you?"
+
+"Yes. Well, there IS company there, I reckon. Better give it up."
+
+"Give it up, and I just leaving this country forever! Give it up and
+maybe never have another chance. I tell you again, as I've told you
+before, I don't care for her swag--you may have it. But her husband was
+rough on me--many times he was rough on me--and mainly he was the
+justice of the peace that jugged me for a vagrant. And that ain't all.
+It ain't a millionth part of it! He had me HORSEWHIPPED!--horsewhipped
+in front of the jail, like a nigger!--with all the town looking on!
+HORSEWHIPPED!--do you understand? He took advantage of me and died. But
+I'll take it out of HER."
+
+"Oh, don't kill her! Don't do that!"
+
+"Kill? Who said anything about killing? I would kill HIM if he was
+here; but not her. When you want to get revenge on a woman you don't
+kill her--bosh! you go for her looks. You slit her nostrils--you notch
+her ears like a sow!"
+
+"By God, that's--"
+
+"Keep your opinion to yourself! It will be safest for you. I'll tie
+her to the bed. If she bleeds to death, is that my fault? I'll not cry,
+if she does. My friend, you'll help me in this thing--for MY sake
+--that's why you're here--I mightn't be able alone. If you flinch, I'll
+kill you. Do you understand that? And if I have to kill you, I'll kill
+her--and then I reckon nobody'll ever know much about who done this
+business."
+
+"Well, if it's got to be done, let's get at it. The quicker the
+better--I'm all in a shiver."
+
+"Do it NOW? And company there? Look here--I'll get suspicious of you,
+first thing you know. No--we'll wait till the lights are out--there's
+no hurry."
+
+Huck felt that a silence was going to ensue--a thing still more awful
+than any amount of murderous talk; so he held his breath and stepped
+gingerly back; planted his foot carefully and firmly, after balancing,
+one-legged, in a precarious way and almost toppling over, first on one
+side and then on the other. He took another step back, with the same
+elaboration and the same risks; then another and another, and--a twig
+snapped under his foot! His breath stopped and he listened. There was
+no sound--the stillness was perfect. His gratitude was measureless. Now
+he turned in his tracks, between the walls of sumach bushes--turned
+himself as carefully as if he were a ship--and then stepped quickly but
+cautiously along. When he emerged at the quarry he felt secure, and so
+he picked up his nimble heels and flew. Down, down he sped, till he
+reached the Welshman's. He banged at the door, and presently the heads
+of the old man and his two stalwart sons were thrust from windows.
+
+"What's the row there? Who's banging? What do you want?"
+
+"Let me in--quick! I'll tell everything."
+
+"Why, who are you?"
+
+"Huckleberry Finn--quick, let me in!"
+
+"Huckleberry Finn, indeed! It ain't a name to open many doors, I
+judge! But let him in, lads, and let's see what's the trouble."
+
+"Please don't ever tell I told you," were Huck's first words when he
+got in. "Please don't--I'd be killed, sure--but the widow's been good
+friends to me sometimes, and I want to tell--I WILL tell if you'll
+promise you won't ever say it was me."
+
+"By George, he HAS got something to tell, or he wouldn't act so!"
+exclaimed the old man; "out with it and nobody here'll ever tell, lad."
+
+Three minutes later the old man and his sons, well armed, were up the
+hill, and just entering the sumach path on tiptoe, their weapons in
+their hands. Huck accompanied them no further. He hid behind a great
+bowlder and fell to listening. There was a lagging, anxious silence,
+and then all of a sudden there was an explosion of firearms and a cry.
+
+Huck waited for no particulars. He sprang away and sped down the hill
+as fast as his legs could carry him.
+
+
+
+CHAPTER XXX
+
+AS the earliest suspicion of dawn appeared on Sunday morning, Huck
+came groping up the hill and rapped gently at the old Welshman's door.
+The inmates were asleep, but it was a sleep that was set on a
+hair-trigger, on account of the exciting episode of the night. A call
+came from a window:
+
+"Who's there!"
+
+Huck's scared voice answered in a low tone:
+
+"Please let me in! It's only Huck Finn!"
+
+"It's a name that can open this door night or day, lad!--and welcome!"
+
+These were strange words to the vagabond boy's ears, and the
+pleasantest he had ever heard. He could not recollect that the closing
+word had ever been applied in his case before. The door was quickly
+unlocked, and he entered. Huck was given a seat and the old man and his
+brace of tall sons speedily dressed themselves.
+
+"Now, my boy, I hope you're good and hungry, because breakfast will be
+ready as soon as the sun's up, and we'll have a piping hot one, too
+--make yourself easy about that! I and the boys hoped you'd turn up and
+stop here last night."
+
+"I was awful scared," said Huck, "and I run. I took out when the
+pistols went off, and I didn't stop for three mile. I've come now becuz
+I wanted to know about it, you know; and I come before daylight becuz I
+didn't want to run across them devils, even if they was dead."
+
+"Well, poor chap, you do look as if you'd had a hard night of it--but
+there's a bed here for you when you've had your breakfast. No, they
+ain't dead, lad--we are sorry enough for that. You see we knew right
+where to put our hands on them, by your description; so we crept along
+on tiptoe till we got within fifteen feet of them--dark as a cellar
+that sumach path was--and just then I found I was going to sneeze. It
+was the meanest kind of luck! I tried to keep it back, but no use
+--'twas bound to come, and it did come! I was in the lead with my pistol
+raised, and when the sneeze started those scoundrels a-rustling to get
+out of the path, I sung out, 'Fire boys!' and blazed away at the place
+where the rustling was. So did the boys. But they were off in a jiffy,
+those villains, and we after them, down through the woods. I judge we
+never touched them. They fired a shot apiece as they started, but their
+bullets whizzed by and didn't do us any harm. As soon as we lost the
+sound of their feet we quit chasing, and went down and stirred up the
+constables. They got a posse together, and went off to guard the river
+bank, and as soon as it is light the sheriff and a gang are going to
+beat up the woods. My boys will be with them presently. I wish we had
+some sort of description of those rascals--'twould help a good deal.
+But you couldn't see what they were like, in the dark, lad, I suppose?"
+
+"Oh yes; I saw them down-town and follered them."
+
+"Splendid! Describe them--describe them, my boy!"
+
+"One's the old deaf and dumb Spaniard that's ben around here once or
+twice, and t'other's a mean-looking, ragged--"
+
+"That's enough, lad, we know the men! Happened on them in the woods
+back of the widow's one day, and they slunk away. Off with you, boys,
+and tell the sheriff--get your breakfast to-morrow morning!"
+
+The Welshman's sons departed at once. As they were leaving the room
+Huck sprang up and exclaimed:
+
+"Oh, please don't tell ANYbody it was me that blowed on them! Oh,
+please!"
+
+"All right if you say it, Huck, but you ought to have the credit of
+what you did."
+
+"Oh no, no! Please don't tell!"
+
+When the young men were gone, the old Welshman said:
+
+"They won't tell--and I won't. But why don't you want it known?"
+
+Huck would not explain, further than to say that he already knew too
+much about one of those men and would not have the man know that he
+knew anything against him for the whole world--he would be killed for
+knowing it, sure.
+
+The old man promised secrecy once more, and said:
+
+"How did you come to follow these fellows, lad? Were they looking
+suspicious?"
+
+Huck was silent while he framed a duly cautious reply. Then he said:
+
+"Well, you see, I'm a kind of a hard lot,--least everybody says so,
+and I don't see nothing agin it--and sometimes I can't sleep much, on
+account of thinking about it and sort of trying to strike out a new way
+of doing. That was the way of it last night. I couldn't sleep, and so I
+come along up-street 'bout midnight, a-turning it all over, and when I
+got to that old shackly brick store by the Temperance Tavern, I backed
+up agin the wall to have another think. Well, just then along comes
+these two chaps slipping along close by me, with something under their
+arm, and I reckoned they'd stole it. One was a-smoking, and t'other one
+wanted a light; so they stopped right before me and the cigars lit up
+their faces and I see that the big one was the deaf and dumb Spaniard,
+by his white whiskers and the patch on his eye, and t'other one was a
+rusty, ragged-looking devil."
+
+"Could you see the rags by the light of the cigars?"
+
+This staggered Huck for a moment. Then he said:
+
+"Well, I don't know--but somehow it seems as if I did."
+
+"Then they went on, and you--"
+
+"Follered 'em--yes. That was it. I wanted to see what was up--they
+sneaked along so. I dogged 'em to the widder's stile, and stood in the
+dark and heard the ragged one beg for the widder, and the Spaniard
+swear he'd spile her looks just as I told you and your two--"
+
+"What! The DEAF AND DUMB man said all that!"
+
+Huck had made another terrible mistake! He was trying his best to keep
+the old man from getting the faintest hint of who the Spaniard might
+be, and yet his tongue seemed determined to get him into trouble in
+spite of all he could do. He made several efforts to creep out of his
+scrape, but the old man's eye was upon him and he made blunder after
+blunder. Presently the Welshman said:
+
+"My boy, don't be afraid of me. I wouldn't hurt a hair of your head
+for all the world. No--I'd protect you--I'd protect you. This Spaniard
+is not deaf and dumb; you've let that slip without intending it; you
+can't cover that up now. You know something about that Spaniard that
+you want to keep dark. Now trust me--tell me what it is, and trust me
+--I won't betray you."
+
+Huck looked into the old man's honest eyes a moment, then bent over
+and whispered in his ear:
+
+"'Tain't a Spaniard--it's Injun Joe!"
+
+The Welshman almost jumped out of his chair. In a moment he said:
+
+"It's all plain enough, now. When you talked about notching ears and
+slitting noses I judged that that was your own embellishment, because
+white men don't take that sort of revenge. But an Injun! That's a
+different matter altogether."
+
+During breakfast the talk went on, and in the course of it the old man
+said that the last thing which he and his sons had done, before going
+to bed, was to get a lantern and examine the stile and its vicinity for
+marks of blood. They found none, but captured a bulky bundle of--
+
+"Of WHAT?"
+
+If the words had been lightning they could not have leaped with a more
+stunning suddenness from Huck's blanched lips. His eyes were staring
+wide, now, and his breath suspended--waiting for the answer. The
+Welshman started--stared in return--three seconds--five seconds--ten
+--then replied:
+
+"Of burglar's tools. Why, what's the MATTER with you?"
+
+Huck sank back, panting gently, but deeply, unutterably grateful. The
+Welshman eyed him gravely, curiously--and presently said:
+
+"Yes, burglar's tools. That appears to relieve you a good deal. But
+what did give you that turn? What were YOU expecting we'd found?"
+
+Huck was in a close place--the inquiring eye was upon him--he would
+have given anything for material for a plausible answer--nothing
+suggested itself--the inquiring eye was boring deeper and deeper--a
+senseless reply offered--there was no time to weigh it, so at a venture
+he uttered it--feebly:
+
+"Sunday-school books, maybe."
+
+Poor Huck was too distressed to smile, but the old man laughed loud
+and joyously, shook up the details of his anatomy from head to foot,
+and ended by saying that such a laugh was money in a-man's pocket,
+because it cut down the doctor's bill like everything. Then he added:
+
+"Poor old chap, you're white and jaded--you ain't well a bit--no
+wonder you're a little flighty and off your balance. But you'll come
+out of it. Rest and sleep will fetch you out all right, I hope."
+
+Huck was irritated to think he had been such a goose and betrayed such
+a suspicious excitement, for he had dropped the idea that the parcel
+brought from the tavern was the treasure, as soon as he had heard the
+talk at the widow's stile. He had only thought it was not the treasure,
+however--he had not known that it wasn't--and so the suggestion of a
+captured bundle was too much for his self-possession. But on the whole
+he felt glad the little episode had happened, for now he knew beyond
+all question that that bundle was not THE bundle, and so his mind was
+at rest and exceedingly comfortable. In fact, everything seemed to be
+drifting just in the right direction, now; the treasure must be still
+in No. 2, the men would be captured and jailed that day, and he and Tom
+could seize the gold that night without any trouble or any fear of
+interruption.
+
+Just as breakfast was completed there was a knock at the door. Huck
+jumped for a hiding-place, for he had no mind to be connected even
+remotely with the late event. The Welshman admitted several ladies and
+gentlemen, among them the Widow Douglas, and noticed that groups of
+citizens were climbing up the hill--to stare at the stile. So the news
+had spread. The Welshman had to tell the story of the night to the
+visitors. The widow's gratitude for her preservation was outspoken.
+
+"Don't say a word about it, madam. There's another that you're more
+beholden to than you are to me and my boys, maybe, but he don't allow
+me to tell his name. We wouldn't have been there but for him."
+
+Of course this excited a curiosity so vast that it almost belittled
+the main matter--but the Welshman allowed it to eat into the vitals of
+his visitors, and through them be transmitted to the whole town, for he
+refused to part with his secret. When all else had been learned, the
+widow said:
+
+"I went to sleep reading in bed and slept straight through all that
+noise. Why didn't you come and wake me?"
+
+"We judged it warn't worth while. Those fellows warn't likely to come
+again--they hadn't any tools left to work with, and what was the use of
+waking you up and scaring you to death? My three negro men stood guard
+at your house all the rest of the night. They've just come back."
+
+More visitors came, and the story had to be told and retold for a
+couple of hours more.
+
+There was no Sabbath-school during day-school vacation, but everybody
+was early at church. The stirring event was well canvassed. News came
+that not a sign of the two villains had been yet discovered. When the
+sermon was finished, Judge Thatcher's wife dropped alongside of Mrs.
+Harper as she moved down the aisle with the crowd and said:
+
+"Is my Becky going to sleep all day? I just expected she would be
+tired to death."
+
+"Your Becky?"
+
+"Yes," with a startled look--"didn't she stay with you last night?"
+
+"Why, no."
+
+Mrs. Thatcher turned pale, and sank into a pew, just as Aunt Polly,
+talking briskly with a friend, passed by. Aunt Polly said:
+
+"Good-morning, Mrs. Thatcher. Good-morning, Mrs. Harper. I've got a
+boy that's turned up missing. I reckon my Tom stayed at your house last
+night--one of you. And now he's afraid to come to church. I've got to
+settle with him."
+
+Mrs. Thatcher shook her head feebly and turned paler than ever.
+
+"He didn't stay with us," said Mrs. Harper, beginning to look uneasy.
+A marked anxiety came into Aunt Polly's face.
+
+"Joe Harper, have you seen my Tom this morning?"
+
+"No'm."
+
+"When did you see him last?"
+
+Joe tried to remember, but was not sure he could say. The people had
+stopped moving out of church. Whispers passed along, and a boding
+uneasiness took possession of every countenance. Children were
+anxiously questioned, and young teachers. They all said they had not
+noticed whether Tom and Becky were on board the ferryboat on the
+homeward trip; it was dark; no one thought of inquiring if any one was
+missing. One young man finally blurted out his fear that they were
+still in the cave! Mrs. Thatcher swooned away. Aunt Polly fell to
+crying and wringing her hands.
+
+The alarm swept from lip to lip, from group to group, from street to
+street, and within five minutes the bells were wildly clanging and the
+whole town was up! The Cardiff Hill episode sank into instant
+insignificance, the burglars were forgotten, horses were saddled,
+skiffs were manned, the ferryboat ordered out, and before the horror
+was half an hour old, two hundred men were pouring down highroad and
+river toward the cave.
+
+All the long afternoon the village seemed empty and dead. Many women
+visited Aunt Polly and Mrs. Thatcher and tried to comfort them. They
+cried with them, too, and that was still better than words. All the
+tedious night the town waited for news; but when the morning dawned at
+last, all the word that came was, "Send more candles--and send food."
+Mrs. Thatcher was almost crazed; and Aunt Polly, also. Judge Thatcher
+sent messages of hope and encouragement from the cave, but they
+conveyed no real cheer.
+
+The old Welshman came home toward daylight, spattered with
+candle-grease, smeared with clay, and almost worn out. He found Huck
+still in the bed that had been provided for him, and delirious with
+fever. The physicians were all at the cave, so the Widow Douglas came
+and took charge of the patient. She said she would do her best by him,
+because, whether he was good, bad, or indifferent, he was the Lord's,
+and nothing that was the Lord's was a thing to be neglected. The
+Welshman said Huck had good spots in him, and the widow said:
+
+"You can depend on it. That's the Lord's mark. He don't leave it off.
+He never does. Puts it somewhere on every creature that comes from his
+hands."
+
+Early in the forenoon parties of jaded men began to straggle into the
+village, but the strongest of the citizens continued searching. All the
+news that could be gained was that remotenesses of the cavern were
+being ransacked that had never been visited before; that every corner
+and crevice was going to be thoroughly searched; that wherever one
+wandered through the maze of passages, lights were to be seen flitting
+hither and thither in the distance, and shoutings and pistol-shots sent
+their hollow reverberations to the ear down the sombre aisles. In one
+place, far from the section usually traversed by tourists, the names
+"BECKY & TOM" had been found traced upon the rocky wall with
+candle-smoke, and near at hand a grease-soiled bit of ribbon. Mrs.
+Thatcher recognized the ribbon and cried over it. She said it was the
+last relic she should ever have of her child; and that no other memorial
+of her could ever be so precious, because this one parted latest from
+the living body before the awful death came. Some said that now and
+then, in the cave, a far-away speck of light would glimmer, and then a
+glorious shout would burst forth and a score of men go trooping down the
+echoing aisle--and then a sickening disappointment always followed; the
+children were not there; it was only a searcher's light.
+
+Three dreadful days and nights dragged their tedious hours along, and
+the village sank into a hopeless stupor. No one had heart for anything.
+The accidental discovery, just made, that the proprietor of the
+Temperance Tavern kept liquor on his premises, scarcely fluttered the
+public pulse, tremendous as the fact was. In a lucid interval, Huck
+feebly led up to the subject of taverns, and finally asked--dimly
+dreading the worst--if anything had been discovered at the Temperance
+Tavern since he had been ill.
+
+"Yes," said the widow.
+
+Huck started up in bed, wild-eyed:
+
+"What? What was it?"
+
+"Liquor!--and the place has been shut up. Lie down, child--what a turn
+you did give me!"
+
+"Only tell me just one thing--only just one--please! Was it Tom Sawyer
+that found it?"
+
+The widow burst into tears. "Hush, hush, child, hush! I've told you
+before, you must NOT talk. You are very, very sick!"
+
+Then nothing but liquor had been found; there would have been a great
+powwow if it had been the gold. So the treasure was gone forever--gone
+forever! But what could she be crying about? Curious that she should
+cry.
+
+These thoughts worked their dim way through Huck's mind, and under the
+weariness they gave him he fell asleep. The widow said to herself:
+
+"There--he's asleep, poor wreck. Tom Sawyer find it! Pity but somebody
+could find Tom Sawyer! Ah, there ain't many left, now, that's got hope
+enough, or strength enough, either, to go on searching."
+
+
+
+CHAPTER XXXI
+
+NOW to return to Tom and Becky's share in the picnic. They tripped
+along the murky aisles with the rest of the company, visiting the
+familiar wonders of the cave--wonders dubbed with rather
+over-descriptive names, such as "The Drawing-Room," "The Cathedral,"
+"Aladdin's Palace," and so on. Presently the hide-and-seek frolicking
+began, and Tom and Becky engaged in it with zeal until the exertion
+began to grow a trifle wearisome; then they wandered down a sinuous
+avenue holding their candles aloft and reading the tangled web-work of
+names, dates, post-office addresses, and mottoes with which the rocky
+walls had been frescoed (in candle-smoke). Still drifting along and
+talking, they scarcely noticed that they were now in a part of the cave
+whose walls were not frescoed. They smoked their own names under an
+overhanging shelf and moved on. Presently they came to a place where a
+little stream of water, trickling over a ledge and carrying a limestone
+sediment with it, had, in the slow-dragging ages, formed a laced and
+ruffled Niagara in gleaming and imperishable stone. Tom squeezed his
+small body behind it in order to illuminate it for Becky's
+gratification. He found that it curtained a sort of steep natural
+stairway which was enclosed between narrow walls, and at once the
+ambition to be a discoverer seized him. Becky responded to his call,
+and they made a smoke-mark for future guidance, and started upon their
+quest. They wound this way and that, far down into the secret depths of
+the cave, made another mark, and branched off in search of novelties to
+tell the upper world about. In one place they found a spacious cavern,
+from whose ceiling depended a multitude of shining stalactites of the
+length and circumference of a man's leg; they walked all about it,
+wondering and admiring, and presently left it by one of the numerous
+passages that opened into it. This shortly brought them to a bewitching
+spring, whose basin was incrusted with a frostwork of glittering
+crystals; it was in the midst of a cavern whose walls were supported by
+many fantastic pillars which had been formed by the joining of great
+stalactites and stalagmites together, the result of the ceaseless
+water-drip of centuries. Under the roof vast knots of bats had packed
+themselves together, thousands in a bunch; the lights disturbed the
+creatures and they came flocking down by hundreds, squeaking and
+darting furiously at the candles. Tom knew their ways and the danger of
+this sort of conduct. He seized Becky's hand and hurried her into the
+first corridor that offered; and none too soon, for a bat struck
+Becky's light out with its wing while she was passing out of the
+cavern. The bats chased the children a good distance; but the fugitives
+plunged into every new passage that offered, and at last got rid of the
+perilous things. Tom found a subterranean lake, shortly, which
+stretched its dim length away until its shape was lost in the shadows.
+He wanted to explore its borders, but concluded that it would be best
+to sit down and rest awhile, first. Now, for the first time, the deep
+stillness of the place laid a clammy hand upon the spirits of the
+children. Becky said:
+
+"Why, I didn't notice, but it seems ever so long since I heard any of
+the others."
+
+"Come to think, Becky, we are away down below them--and I don't know
+how far away north, or south, or east, or whichever it is. We couldn't
+hear them here."
+
+Becky grew apprehensive.
+
+"I wonder how long we've been down here, Tom? We better start back."
+
+"Yes, I reckon we better. P'raps we better."
+
+"Can you find the way, Tom? It's all a mixed-up crookedness to me."
+
+"I reckon I could find it--but then the bats. If they put our candles
+out it will be an awful fix. Let's try some other way, so as not to go
+through there."
+
+"Well. But I hope we won't get lost. It would be so awful!" and the
+girl shuddered at the thought of the dreadful possibilities.
+
+They started through a corridor, and traversed it in silence a long
+way, glancing at each new opening, to see if there was anything
+familiar about the look of it; but they were all strange. Every time
+Tom made an examination, Becky would watch his face for an encouraging
+sign, and he would say cheerily:
+
+"Oh, it's all right. This ain't the one, but we'll come to it right
+away!"
+
+But he felt less and less hopeful with each failure, and presently
+began to turn off into diverging avenues at sheer random, in desperate
+hope of finding the one that was wanted. He still said it was "all
+right," but there was such a leaden dread at his heart that the words
+had lost their ring and sounded just as if he had said, "All is lost!"
+Becky clung to his side in an anguish of fear, and tried hard to keep
+back the tears, but they would come. At last she said:
+
+"Oh, Tom, never mind the bats, let's go back that way! We seem to get
+worse and worse off all the time."
+
+"Listen!" said he.
+
+Profound silence; silence so deep that even their breathings were
+conspicuous in the hush. Tom shouted. The call went echoing down the
+empty aisles and died out in the distance in a faint sound that
+resembled a ripple of mocking laughter.
+
+"Oh, don't do it again, Tom, it is too horrid," said Becky.
+
+"It is horrid, but I better, Becky; they might hear us, you know," and
+he shouted again.
+
+The "might" was even a chillier horror than the ghostly laughter, it
+so confessed a perishing hope. The children stood still and listened;
+but there was no result. Tom turned upon the back track at once, and
+hurried his steps. It was but a little while before a certain
+indecision in his manner revealed another fearful fact to Becky--he
+could not find his way back!
+
+"Oh, Tom, you didn't make any marks!"
+
+"Becky, I was such a fool! Such a fool! I never thought we might want
+to come back! No--I can't find the way. It's all mixed up."
+
+"Tom, Tom, we're lost! we're lost! We never can get out of this awful
+place! Oh, why DID we ever leave the others!"
+
+She sank to the ground and burst into such a frenzy of crying that Tom
+was appalled with the idea that she might die, or lose her reason. He
+sat down by her and put his arms around her; she buried her face in his
+bosom, she clung to him, she poured out her terrors, her unavailing
+regrets, and the far echoes turned them all to jeering laughter. Tom
+begged her to pluck up hope again, and she said she could not. He fell
+to blaming and abusing himself for getting her into this miserable
+situation; this had a better effect. She said she would try to hope
+again, she would get up and follow wherever he might lead if only he
+would not talk like that any more. For he was no more to blame than
+she, she said.
+
+So they moved on again--aimlessly--simply at random--all they could do
+was to move, keep moving. For a little while, hope made a show of
+reviving--not with any reason to back it, but only because it is its
+nature to revive when the spring has not been taken out of it by age
+and familiarity with failure.
+
+By-and-by Tom took Becky's candle and blew it out. This economy meant
+so much! Words were not needed. Becky understood, and her hope died
+again. She knew that Tom had a whole candle and three or four pieces in
+his pockets--yet he must economize.
+
+By-and-by, fatigue began to assert its claims; the children tried to
+pay attention, for it was dreadful to think of sitting down when time
+was grown to be so precious, moving, in some direction, in any
+direction, was at least progress and might bear fruit; but to sit down
+was to invite death and shorten its pursuit.
+
+At last Becky's frail limbs refused to carry her farther. She sat
+down. Tom rested with her, and they talked of home, and the friends
+there, and the comfortable beds and, above all, the light! Becky cried,
+and Tom tried to think of some way of comforting her, but all his
+encouragements were grown threadbare with use, and sounded like
+sarcasms. Fatigue bore so heavily upon Becky that she drowsed off to
+sleep. Tom was grateful. He sat looking into her drawn face and saw it
+grow smooth and natural under the influence of pleasant dreams; and
+by-and-by a smile dawned and rested there. The peaceful face reflected
+somewhat of peace and healing into his own spirit, and his thoughts
+wandered away to bygone times and dreamy memories. While he was deep in
+his musings, Becky woke up with a breezy little laugh--but it was
+stricken dead upon her lips, and a groan followed it.
+
+"Oh, how COULD I sleep! I wish I never, never had waked! No! No, I
+don't, Tom! Don't look so! I won't say it again."
+
+"I'm glad you've slept, Becky; you'll feel rested, now, and we'll find
+the way out."
+
+"We can try, Tom; but I've seen such a beautiful country in my dream.
+I reckon we are going there."
+
+"Maybe not, maybe not. Cheer up, Becky, and let's go on trying."
+
+They rose up and wandered along, hand in hand and hopeless. They tried
+to estimate how long they had been in the cave, but all they knew was
+that it seemed days and weeks, and yet it was plain that this could not
+be, for their candles were not gone yet. A long time after this--they
+could not tell how long--Tom said they must go softly and listen for
+dripping water--they must find a spring. They found one presently, and
+Tom said it was time to rest again. Both were cruelly tired, yet Becky
+said she thought she could go a little farther. She was surprised to
+hear Tom dissent. She could not understand it. They sat down, and Tom
+fastened his candle to the wall in front of them with some clay.
+Thought was soon busy; nothing was said for some time. Then Becky broke
+the silence:
+
+"Tom, I am so hungry!"
+
+Tom took something out of his pocket.
+
+"Do you remember this?" said he.
+
+Becky almost smiled.
+
+"It's our wedding-cake, Tom."
+
+"Yes--I wish it was as big as a barrel, for it's all we've got."
+
+"I saved it from the picnic for us to dream on, Tom, the way grown-up
+people do with wedding-cake--but it'll be our--"
+
+She dropped the sentence where it was. Tom divided the cake and Becky
+ate with good appetite, while Tom nibbled at his moiety. There was
+abundance of cold water to finish the feast with. By-and-by Becky
+suggested that they move on again. Tom was silent a moment. Then he
+said:
+
+"Becky, can you bear it if I tell you something?"
+
+Becky's face paled, but she thought she could.
+
+"Well, then, Becky, we must stay here, where there's water to drink.
+That little piece is our last candle!"
+
+Becky gave loose to tears and wailings. Tom did what he could to
+comfort her, but with little effect. At length Becky said:
+
+"Tom!"
+
+"Well, Becky?"
+
+"They'll miss us and hunt for us!"
+
+"Yes, they will! Certainly they will!"
+
+"Maybe they're hunting for us now, Tom."
+
+"Why, I reckon maybe they are. I hope they are."
+
+"When would they miss us, Tom?"
+
+"When they get back to the boat, I reckon."
+
+"Tom, it might be dark then--would they notice we hadn't come?"
+
+"I don't know. But anyway, your mother would miss you as soon as they
+got home."
+
+A frightened look in Becky's face brought Tom to his senses and he saw
+that he had made a blunder. Becky was not to have gone home that night!
+The children became silent and thoughtful. In a moment a new burst of
+grief from Becky showed Tom that the thing in his mind had struck hers
+also--that the Sabbath morning might be half spent before Mrs. Thatcher
+discovered that Becky was not at Mrs. Harper's.
+
+The children fastened their eyes upon their bit of candle and watched
+it melt slowly and pitilessly away; saw the half inch of wick stand
+alone at last; saw the feeble flame rise and fall, climb the thin
+column of smoke, linger at its top a moment, and then--the horror of
+utter darkness reigned!
+
+How long afterward it was that Becky came to a slow consciousness that
+she was crying in Tom's arms, neither could tell. All that they knew
+was, that after what seemed a mighty stretch of time, both awoke out of
+a dead stupor of sleep and resumed their miseries once more. Tom said
+it might be Sunday, now--maybe Monday. He tried to get Becky to talk,
+but her sorrows were too oppressive, all her hopes were gone. Tom said
+that they must have been missed long ago, and no doubt the search was
+going on. He would shout and maybe some one would come. He tried it;
+but in the darkness the distant echoes sounded so hideously that he
+tried it no more.
+
+The hours wasted away, and hunger came to torment the captives again.
+A portion of Tom's half of the cake was left; they divided and ate it.
+But they seemed hungrier than before. The poor morsel of food only
+whetted desire.
+
+By-and-by Tom said:
+
+"SH! Did you hear that?"
+
+Both held their breath and listened. There was a sound like the
+faintest, far-off shout. Instantly Tom answered it, and leading Becky
+by the hand, started groping down the corridor in its direction.
+Presently he listened again; again the sound was heard, and apparently
+a little nearer.
+
+"It's them!" said Tom; "they're coming! Come along, Becky--we're all
+right now!"
+
+The joy of the prisoners was almost overwhelming. Their speed was
+slow, however, because pitfalls were somewhat common, and had to be
+guarded against. They shortly came to one and had to stop. It might be
+three feet deep, it might be a hundred--there was no passing it at any
+rate. Tom got down on his breast and reached as far down as he could.
+No bottom. They must stay there and wait until the searchers came. They
+listened; evidently the distant shoutings were growing more distant! a
+moment or two more and they had gone altogether. The heart-sinking
+misery of it! Tom whooped until he was hoarse, but it was of no use. He
+talked hopefully to Becky; but an age of anxious waiting passed and no
+sounds came again.
+
+The children groped their way back to the spring. The weary time
+dragged on; they slept again, and awoke famished and woe-stricken. Tom
+believed it must be Tuesday by this time.
+
+Now an idea struck him. There were some side passages near at hand. It
+would be better to explore some of these than bear the weight of the
+heavy time in idleness. He took a kite-line from his pocket, tied it to
+a projection, and he and Becky started, Tom in the lead, unwinding the
+line as he groped along. At the end of twenty steps the corridor ended
+in a "jumping-off place." Tom got down on his knees and felt below, and
+then as far around the corner as he could reach with his hands
+conveniently; he made an effort to stretch yet a little farther to the
+right, and at that moment, not twenty yards away, a human hand, holding
+a candle, appeared from behind a rock! Tom lifted up a glorious shout,
+and instantly that hand was followed by the body it belonged to--Injun
+Joe's! Tom was paralyzed; he could not move. He was vastly gratified
+the next moment, to see the "Spaniard" take to his heels and get
+himself out of sight. Tom wondered that Joe had not recognized his
+voice and come over and killed him for testifying in court. But the
+echoes must have disguised the voice. Without doubt, that was it, he
+reasoned. Tom's fright weakened every muscle in his body. He said to
+himself that if he had strength enough to get back to the spring he
+would stay there, and nothing should tempt him to run the risk of
+meeting Injun Joe again. He was careful to keep from Becky what it was
+he had seen. He told her he had only shouted "for luck."
+
+But hunger and wretchedness rise superior to fears in the long run.
+Another tedious wait at the spring and another long sleep brought
+changes. The children awoke tortured with a raging hunger. Tom believed
+that it must be Wednesday or Thursday or even Friday or Saturday, now,
+and that the search had been given over. He proposed to explore another
+passage. He felt willing to risk Injun Joe and all other terrors. But
+Becky was very weak. She had sunk into a dreary apathy and would not be
+roused. She said she would wait, now, where she was, and die--it would
+not be long. She told Tom to go with the kite-line and explore if he
+chose; but she implored him to come back every little while and speak
+to her; and she made him promise that when the awful time came, he
+would stay by her and hold her hand until all was over.
+
+Tom kissed her, with a choking sensation in his throat, and made a
+show of being confident of finding the searchers or an escape from the
+cave; then he took the kite-line in his hand and went groping down one
+of the passages on his hands and knees, distressed with hunger and sick
+with bodings of coming doom.
+
+
+
+CHAPTER XXXII
+
+TUESDAY afternoon came, and waned to the twilight. The village of St.
+Petersburg still mourned. The lost children had not been found. Public
+prayers had been offered up for them, and many and many a private
+prayer that had the petitioner's whole heart in it; but still no good
+news came from the cave. The majority of the searchers had given up the
+quest and gone back to their daily avocations, saying that it was plain
+the children could never be found. Mrs. Thatcher was very ill, and a
+great part of the time delirious. People said it was heartbreaking to
+hear her call her child, and raise her head and listen a whole minute
+at a time, then lay it wearily down again with a moan. Aunt Polly had
+drooped into a settled melancholy, and her gray hair had grown almost
+white. The village went to its rest on Tuesday night, sad and forlorn.
+
+Away in the middle of the night a wild peal burst from the village
+bells, and in a moment the streets were swarming with frantic half-clad
+people, who shouted, "Turn out! turn out! they're found! they're
+found!" Tin pans and horns were added to the din, the population massed
+itself and moved toward the river, met the children coming in an open
+carriage drawn by shouting citizens, thronged around it, joined its
+homeward march, and swept magnificently up the main street roaring
+huzzah after huzzah!
+
+The village was illuminated; nobody went to bed again; it was the
+greatest night the little town had ever seen. During the first half-hour
+a procession of villagers filed through Judge Thatcher's house, seized
+the saved ones and kissed them, squeezed Mrs. Thatcher's hand, tried to
+speak but couldn't--and drifted out raining tears all over the place.
+
+Aunt Polly's happiness was complete, and Mrs. Thatcher's nearly so. It
+would be complete, however, as soon as the messenger dispatched with
+the great news to the cave should get the word to her husband. Tom lay
+upon a sofa with an eager auditory about him and told the history of
+the wonderful adventure, putting in many striking additions to adorn it
+withal; and closed with a description of how he left Becky and went on
+an exploring expedition; how he followed two avenues as far as his
+kite-line would reach; how he followed a third to the fullest stretch of
+the kite-line, and was about to turn back when he glimpsed a far-off
+speck that looked like daylight; dropped the line and groped toward it,
+pushed his head and shoulders through a small hole, and saw the broad
+Mississippi rolling by! And if it had only happened to be night he would
+not have seen that speck of daylight and would not have explored that
+passage any more! He told how he went back for Becky and broke the good
+news and she told him not to fret her with such stuff, for she was
+tired, and knew she was going to die, and wanted to. He described how he
+labored with her and convinced her; and how she almost died for joy when
+she had groped to where she actually saw the blue speck of daylight; how
+he pushed his way out at the hole and then helped her out; how they sat
+there and cried for gladness; how some men came along in a skiff and Tom
+hailed them and told them their situation and their famished condition;
+how the men didn't believe the wild tale at first, "because," said they,
+"you are five miles down the river below the valley the cave is in"
+--then took them aboard, rowed to a house, gave them supper, made them
+rest till two or three hours after dark and then brought them home.
+
+Before day-dawn, Judge Thatcher and the handful of searchers with him
+were tracked out, in the cave, by the twine clews they had strung
+behind them, and informed of the great news.
+
+Three days and nights of toil and hunger in the cave were not to be
+shaken off at once, as Tom and Becky soon discovered. They were
+bedridden all of Wednesday and Thursday, and seemed to grow more and
+more tired and worn, all the time. Tom got about, a little, on
+Thursday, was down-town Friday, and nearly as whole as ever Saturday;
+but Becky did not leave her room until Sunday, and then she looked as
+if she had passed through a wasting illness.
+
+Tom learned of Huck's sickness and went to see him on Friday, but
+could not be admitted to the bedroom; neither could he on Saturday or
+Sunday. He was admitted daily after that, but was warned to keep still
+about his adventure and introduce no exciting topic. The Widow Douglas
+stayed by to see that he obeyed. At home Tom learned of the Cardiff
+Hill event; also that the "ragged man's" body had eventually been found
+in the river near the ferry-landing; he had been drowned while trying
+to escape, perhaps.
+
+About a fortnight after Tom's rescue from the cave, he started off to
+visit Huck, who had grown plenty strong enough, now, to hear exciting
+talk, and Tom had some that would interest him, he thought. Judge
+Thatcher's house was on Tom's way, and he stopped to see Becky. The
+Judge and some friends set Tom to talking, and some one asked him
+ironically if he wouldn't like to go to the cave again. Tom said he
+thought he wouldn't mind it. The Judge said:
+
+"Well, there are others just like you, Tom, I've not the least doubt.
+But we have taken care of that. Nobody will get lost in that cave any
+more."
+
+"Why?"
+
+"Because I had its big door sheathed with boiler iron two weeks ago,
+and triple-locked--and I've got the keys."
+
+Tom turned as white as a sheet.
+
+"What's the matter, boy! Here, run, somebody! Fetch a glass of water!"
+
+The water was brought and thrown into Tom's face.
+
+"Ah, now you're all right. What was the matter with you, Tom?"
+
+"Oh, Judge, Injun Joe's in the cave!"
+
+
+
+CHAPTER XXXIII
+
+WITHIN a few minutes the news had spread, and a dozen skiff-loads of
+men were on their way to McDougal's cave, and the ferryboat, well
+filled with passengers, soon followed. Tom Sawyer was in the skiff that
+bore Judge Thatcher.
+
+When the cave door was unlocked, a sorrowful sight presented itself in
+the dim twilight of the place. Injun Joe lay stretched upon the ground,
+dead, with his face close to the crack of the door, as if his longing
+eyes had been fixed, to the latest moment, upon the light and the cheer
+of the free world outside. Tom was touched, for he knew by his own
+experience how this wretch had suffered. His pity was moved, but
+nevertheless he felt an abounding sense of relief and security, now,
+which revealed to him in a degree which he had not fully appreciated
+before how vast a weight of dread had been lying upon him since the day
+he lifted his voice against this bloody-minded outcast.
+
+Injun Joe's bowie-knife lay close by, its blade broken in two. The
+great foundation-beam of the door had been chipped and hacked through,
+with tedious labor; useless labor, too, it was, for the native rock
+formed a sill outside it, and upon that stubborn material the knife had
+wrought no effect; the only damage done was to the knife itself. But if
+there had been no stony obstruction there the labor would have been
+useless still, for if the beam had been wholly cut away Injun Joe could
+not have squeezed his body under the door, and he knew it. So he had
+only hacked that place in order to be doing something--in order to pass
+the weary time--in order to employ his tortured faculties. Ordinarily
+one could find half a dozen bits of candle stuck around in the crevices
+of this vestibule, left there by tourists; but there were none now. The
+prisoner had searched them out and eaten them. He had also contrived to
+catch a few bats, and these, also, he had eaten, leaving only their
+claws. The poor unfortunate had starved to death. In one place, near at
+hand, a stalagmite had been slowly growing up from the ground for ages,
+builded by the water-drip from a stalactite overhead. The captive had
+broken off the stalagmite, and upon the stump had placed a stone,
+wherein he had scooped a shallow hollow to catch the precious drop
+that fell once in every three minutes with the dreary regularity of a
+clock-tick--a dessertspoonful once in four and twenty hours. That drop
+was falling when the Pyramids were new; when Troy fell; when the
+foundations of Rome were laid; when Christ was crucified; when the
+Conqueror created the British empire; when Columbus sailed; when the
+massacre at Lexington was "news." It is falling now; it will still be
+falling when all these things shall have sunk down the afternoon of
+history, and the twilight of tradition, and been swallowed up in the
+thick night of oblivion. Has everything a purpose and a mission? Did
+this drop fall patiently during five thousand years to be ready for
+this flitting human insect's need? and has it another important object
+to accomplish ten thousand years to come? No matter. It is many and
+many a year since the hapless half-breed scooped out the stone to catch
+the priceless drops, but to this day the tourist stares longest at that
+pathetic stone and that slow-dropping water when he comes to see the
+wonders of McDougal's cave. Injun Joe's cup stands first in the list of
+the cavern's marvels; even "Aladdin's Palace" cannot rival it.
+
+Injun Joe was buried near the mouth of the cave; and people flocked
+there in boats and wagons from the towns and from all the farms and
+hamlets for seven miles around; they brought their children, and all
+sorts of provisions, and confessed that they had had almost as
+satisfactory a time at the funeral as they could have had at the
+hanging.
+
+This funeral stopped the further growth of one thing--the petition to
+the governor for Injun Joe's pardon. The petition had been largely
+signed; many tearful and eloquent meetings had been held, and a
+committee of sappy women been appointed to go in deep mourning and wail
+around the governor, and implore him to be a merciful ass and trample
+his duty under foot. Injun Joe was believed to have killed five
+citizens of the village, but what of that? If he had been Satan himself
+there would have been plenty of weaklings ready to scribble their names
+to a pardon-petition, and drip a tear on it from their permanently
+impaired and leaky water-works.
+
+The morning after the funeral Tom took Huck to a private place to have
+an important talk. Huck had learned all about Tom's adventure from the
+Welshman and the Widow Douglas, by this time, but Tom said he reckoned
+there was one thing they had not told him; that thing was what he
+wanted to talk about now. Huck's face saddened. He said:
+
+"I know what it is. You got into No. 2 and never found anything but
+whiskey. Nobody told me it was you; but I just knowed it must 'a' ben
+you, soon as I heard 'bout that whiskey business; and I knowed you
+hadn't got the money becuz you'd 'a' got at me some way or other and
+told me even if you was mum to everybody else. Tom, something's always
+told me we'd never get holt of that swag."
+
+"Why, Huck, I never told on that tavern-keeper. YOU know his tavern
+was all right the Saturday I went to the picnic. Don't you remember you
+was to watch there that night?"
+
+"Oh yes! Why, it seems 'bout a year ago. It was that very night that I
+follered Injun Joe to the widder's."
+
+"YOU followed him?"
+
+"Yes--but you keep mum. I reckon Injun Joe's left friends behind him,
+and I don't want 'em souring on me and doing me mean tricks. If it
+hadn't ben for me he'd be down in Texas now, all right."
+
+Then Huck told his entire adventure in confidence to Tom, who had only
+heard of the Welshman's part of it before.
+
+"Well," said Huck, presently, coming back to the main question,
+"whoever nipped the whiskey in No. 2, nipped the money, too, I reckon
+--anyways it's a goner for us, Tom."
+
+"Huck, that money wasn't ever in No. 2!"
+
+"What!" Huck searched his comrade's face keenly. "Tom, have you got on
+the track of that money again?"
+
+"Huck, it's in the cave!"
+
+Huck's eyes blazed.
+
+"Say it again, Tom."
+
+"The money's in the cave!"
+
+"Tom--honest injun, now--is it fun, or earnest?"
+
+"Earnest, Huck--just as earnest as ever I was in my life. Will you go
+in there with me and help get it out?"
+
+"I bet I will! I will if it's where we can blaze our way to it and not
+get lost."
+
+"Huck, we can do that without the least little bit of trouble in the
+world."
+
+"Good as wheat! What makes you think the money's--"
+
+"Huck, you just wait till we get in there. If we don't find it I'll
+agree to give you my drum and every thing I've got in the world. I
+will, by jings."
+
+"All right--it's a whiz. When do you say?"
+
+"Right now, if you say it. Are you strong enough?"
+
+"Is it far in the cave? I ben on my pins a little, three or four days,
+now, but I can't walk more'n a mile, Tom--least I don't think I could."
+
+"It's about five mile into there the way anybody but me would go,
+Huck, but there's a mighty short cut that they don't anybody but me
+know about. Huck, I'll take you right to it in a skiff. I'll float the
+skiff down there, and I'll pull it back again all by myself. You
+needn't ever turn your hand over."
+
+"Less start right off, Tom."
+
+"All right. We want some bread and meat, and our pipes, and a little
+bag or two, and two or three kite-strings, and some of these
+new-fangled things they call lucifer matches. I tell you, many's
+the time I wished I had some when I was in there before."
+
+A trifle after noon the boys borrowed a small skiff from a citizen who
+was absent, and got under way at once. When they were several miles
+below "Cave Hollow," Tom said:
+
+"Now you see this bluff here looks all alike all the way down from the
+cave hollow--no houses, no wood-yards, bushes all alike. But do you see
+that white place up yonder where there's been a landslide? Well, that's
+one of my marks. We'll get ashore, now."
+
+They landed.
+
+"Now, Huck, where we're a-standing you could touch that hole I got out
+of with a fishing-pole. See if you can find it."
+
+Huck searched all the place about, and found nothing. Tom proudly
+marched into a thick clump of sumach bushes and said:
+
+"Here you are! Look at it, Huck; it's the snuggest hole in this
+country. You just keep mum about it. All along I've been wanting to be
+a robber, but I knew I'd got to have a thing like this, and where to
+run across it was the bother. We've got it now, and we'll keep it
+quiet, only we'll let Joe Harper and Ben Rogers in--because of course
+there's got to be a Gang, or else there wouldn't be any style about it.
+Tom Sawyer's Gang--it sounds splendid, don't it, Huck?"
+
+"Well, it just does, Tom. And who'll we rob?"
+
+"Oh, most anybody. Waylay people--that's mostly the way."
+
+"And kill them?"
+
+"No, not always. Hive them in the cave till they raise a ransom."
+
+"What's a ransom?"
+
+"Money. You make them raise all they can, off'n their friends; and
+after you've kept them a year, if it ain't raised then you kill them.
+That's the general way. Only you don't kill the women. You shut up the
+women, but you don't kill them. They're always beautiful and rich, and
+awfully scared. You take their watches and things, but you always take
+your hat off and talk polite. They ain't anybody as polite as robbers
+--you'll see that in any book. Well, the women get to loving you, and
+after they've been in the cave a week or two weeks they stop crying and
+after that you couldn't get them to leave. If you drove them out they'd
+turn right around and come back. It's so in all the books."
+
+"Why, it's real bully, Tom. I believe it's better'n to be a pirate."
+
+"Yes, it's better in some ways, because it's close to home and
+circuses and all that."
+
+By this time everything was ready and the boys entered the hole, Tom
+in the lead. They toiled their way to the farther end of the tunnel,
+then made their spliced kite-strings fast and moved on. A few steps
+brought them to the spring, and Tom felt a shudder quiver all through
+him. He showed Huck the fragment of candle-wick perched on a lump of
+clay against the wall, and described how he and Becky had watched the
+flame struggle and expire.
+
+The boys began to quiet down to whispers, now, for the stillness and
+gloom of the place oppressed their spirits. They went on, and presently
+entered and followed Tom's other corridor until they reached the
+"jumping-off place." The candles revealed the fact that it was not
+really a precipice, but only a steep clay hill twenty or thirty feet
+high. Tom whispered:
+
+"Now I'll show you something, Huck."
+
+He held his candle aloft and said:
+
+"Look as far around the corner as you can. Do you see that? There--on
+the big rock over yonder--done with candle-smoke."
+
+"Tom, it's a CROSS!"
+
+"NOW where's your Number Two? 'UNDER THE CROSS,' hey? Right yonder's
+where I saw Injun Joe poke up his candle, Huck!"
+
+Huck stared at the mystic sign awhile, and then said with a shaky voice:
+
+"Tom, less git out of here!"
+
+"What! and leave the treasure?"
+
+"Yes--leave it. Injun Joe's ghost is round about there, certain."
+
+"No it ain't, Huck, no it ain't. It would ha'nt the place where he
+died--away out at the mouth of the cave--five mile from here."
+
+"No, Tom, it wouldn't. It would hang round the money. I know the ways
+of ghosts, and so do you."
+
+Tom began to fear that Huck was right. Misgivings gathered in his
+mind. But presently an idea occurred to him--
+
+"Lookyhere, Huck, what fools we're making of ourselves! Injun Joe's
+ghost ain't a going to come around where there's a cross!"
+
+The point was well taken. It had its effect.
+
+"Tom, I didn't think of that. But that's so. It's luck for us, that
+cross is. I reckon we'll climb down there and have a hunt for that box."
+
+Tom went first, cutting rude steps in the clay hill as he descended.
+Huck followed. Four avenues opened out of the small cavern which the
+great rock stood in. The boys examined three of them with no result.
+They found a small recess in the one nearest the base of the rock, with
+a pallet of blankets spread down in it; also an old suspender, some
+bacon rind, and the well-gnawed bones of two or three fowls. But there
+was no money-box. The lads searched and researched this place, but in
+vain. Tom said:
+
+"He said UNDER the cross. Well, this comes nearest to being under the
+cross. It can't be under the rock itself, because that sets solid on
+the ground."
+
+They searched everywhere once more, and then sat down discouraged.
+Huck could suggest nothing. By-and-by Tom said:
+
+"Lookyhere, Huck, there's footprints and some candle-grease on the
+clay about one side of this rock, but not on the other sides. Now,
+what's that for? I bet you the money IS under the rock. I'm going to
+dig in the clay."
+
+"That ain't no bad notion, Tom!" said Huck with animation.
+
+Tom's "real Barlow" was out at once, and he had not dug four inches
+before he struck wood.
+
+"Hey, Huck!--you hear that?"
+
+Huck began to dig and scratch now. Some boards were soon uncovered and
+removed. They had concealed a natural chasm which led under the rock.
+Tom got into this and held his candle as far under the rock as he
+could, but said he could not see to the end of the rift. He proposed to
+explore. He stooped and passed under; the narrow way descended
+gradually. He followed its winding course, first to the right, then to
+the left, Huck at his heels. Tom turned a short curve, by-and-by, and
+exclaimed:
+
+"My goodness, Huck, lookyhere!"
+
+It was the treasure-box, sure enough, occupying a snug little cavern,
+along with an empty powder-keg, a couple of guns in leather cases, two
+or three pairs of old moccasins, a leather belt, and some other rubbish
+well soaked with the water-drip.
+
+"Got it at last!" said Huck, ploughing among the tarnished coins with
+his hand. "My, but we're rich, Tom!"
+
+"Huck, I always reckoned we'd get it. It's just too good to believe,
+but we HAVE got it, sure! Say--let's not fool around here. Let's snake
+it out. Lemme see if I can lift the box."
+
+It weighed about fifty pounds. Tom could lift it, after an awkward
+fashion, but could not carry it conveniently.
+
+"I thought so," he said; "THEY carried it like it was heavy, that day
+at the ha'nted house. I noticed that. I reckon I was right to think of
+fetching the little bags along."
+
+The money was soon in the bags and the boys took it up to the cross
+rock.
+
+"Now less fetch the guns and things," said Huck.
+
+"No, Huck--leave them there. They're just the tricks to have when we
+go to robbing. We'll keep them there all the time, and we'll hold our
+orgies there, too. It's an awful snug place for orgies."
+
+"What orgies?"
+
+"I dono. But robbers always have orgies, and of course we've got to
+have them, too. Come along, Huck, we've been in here a long time. It's
+getting late, I reckon. I'm hungry, too. We'll eat and smoke when we
+get to the skiff."
+
+They presently emerged into the clump of sumach bushes, looked warily
+out, found the coast clear, and were soon lunching and smoking in the
+skiff. As the sun dipped toward the horizon they pushed out and got
+under way. Tom skimmed up the shore through the long twilight, chatting
+cheerily with Huck, and landed shortly after dark.
+
+"Now, Huck," said Tom, "we'll hide the money in the loft of the
+widow's woodshed, and I'll come up in the morning and we'll count it
+and divide, and then we'll hunt up a place out in the woods for it
+where it will be safe. Just you lay quiet here and watch the stuff till
+I run and hook Benny Taylor's little wagon; I won't be gone a minute."
+
+He disappeared, and presently returned with the wagon, put the two
+small sacks into it, threw some old rags on top of them, and started
+off, dragging his cargo behind him. When the boys reached the
+Welshman's house, they stopped to rest. Just as they were about to move
+on, the Welshman stepped out and said:
+
+"Hallo, who's that?"
+
+"Huck and Tom Sawyer."
+
+"Good! Come along with me, boys, you are keeping everybody waiting.
+Here--hurry up, trot ahead--I'll haul the wagon for you. Why, it's not
+as light as it might be. Got bricks in it?--or old metal?"
+
+"Old metal," said Tom.
+
+"I judged so; the boys in this town will take more trouble and fool
+away more time hunting up six bits' worth of old iron to sell to the
+foundry than they would to make twice the money at regular work. But
+that's human nature--hurry along, hurry along!"
+
+The boys wanted to know what the hurry was about.
+
+"Never mind; you'll see, when we get to the Widow Douglas'."
+
+Huck said with some apprehension--for he was long used to being
+falsely accused:
+
+"Mr. Jones, we haven't been doing nothing."
+
+The Welshman laughed.
+
+"Well, I don't know, Huck, my boy. I don't know about that. Ain't you
+and the widow good friends?"
+
+"Yes. Well, she's ben good friends to me, anyway."
+
+"All right, then. What do you want to be afraid for?"
+
+This question was not entirely answered in Huck's slow mind before he
+found himself pushed, along with Tom, into Mrs. Douglas' drawing-room.
+Mr. Jones left the wagon near the door and followed.
+
+The place was grandly lighted, and everybody that was of any
+consequence in the village was there. The Thatchers were there, the
+Harpers, the Rogerses, Aunt Polly, Sid, Mary, the minister, the editor,
+and a great many more, and all dressed in their best. The widow
+received the boys as heartily as any one could well receive two such
+looking beings. They were covered with clay and candle-grease. Aunt
+Polly blushed crimson with humiliation, and frowned and shook her head
+at Tom. Nobody suffered half as much as the two boys did, however. Mr.
+Jones said:
+
+"Tom wasn't at home, yet, so I gave him up; but I stumbled on him and
+Huck right at my door, and so I just brought them along in a hurry."
+
+"And you did just right," said the widow. "Come with me, boys."
+
+She took them to a bedchamber and said:
+
+"Now wash and dress yourselves. Here are two new suits of clothes
+--shirts, socks, everything complete. They're Huck's--no, no thanks,
+Huck--Mr. Jones bought one and I the other. But they'll fit both of you.
+Get into them. We'll wait--come down when you are slicked up enough."
+
+Then she left.
+
+
+
+CHAPTER XXXIV
+
+HUCK said: "Tom, we can slope, if we can find a rope. The window ain't
+high from the ground."
+
+"Shucks! what do you want to slope for?"
+
+"Well, I ain't used to that kind of a crowd. I can't stand it. I ain't
+going down there, Tom."
+
+"Oh, bother! It ain't anything. I don't mind it a bit. I'll take care
+of you."
+
+Sid appeared.
+
+"Tom," said he, "auntie has been waiting for you all the afternoon.
+Mary got your Sunday clothes ready, and everybody's been fretting about
+you. Say--ain't this grease and clay, on your clothes?"
+
+"Now, Mr. Siddy, you jist 'tend to your own business. What's all this
+blow-out about, anyway?"
+
+"It's one of the widow's parties that she's always having. This time
+it's for the Welshman and his sons, on account of that scrape they
+helped her out of the other night. And say--I can tell you something,
+if you want to know."
+
+"Well, what?"
+
+"Why, old Mr. Jones is going to try to spring something on the people
+here to-night, but I overheard him tell auntie to-day about it, as a
+secret, but I reckon it's not much of a secret now. Everybody knows
+--the widow, too, for all she tries to let on she don't. Mr. Jones was
+bound Huck should be here--couldn't get along with his grand secret
+without Huck, you know!"
+
+"Secret about what, Sid?"
+
+"About Huck tracking the robbers to the widow's. I reckon Mr. Jones
+was going to make a grand time over his surprise, but I bet you it will
+drop pretty flat."
+
+Sid chuckled in a very contented and satisfied way.
+
+"Sid, was it you that told?"
+
+"Oh, never mind who it was. SOMEBODY told--that's enough."
+
+"Sid, there's only one person in this town mean enough to do that, and
+that's you. If you had been in Huck's place you'd 'a' sneaked down the
+hill and never told anybody on the robbers. You can't do any but mean
+things, and you can't bear to see anybody praised for doing good ones.
+There--no thanks, as the widow says"--and Tom cuffed Sid's ears and
+helped him to the door with several kicks. "Now go and tell auntie if
+you dare--and to-morrow you'll catch it!"
+
+Some minutes later the widow's guests were at the supper-table, and a
+dozen children were propped up at little side-tables in the same room,
+after the fashion of that country and that day. At the proper time Mr.
+Jones made his little speech, in which he thanked the widow for the
+honor she was doing himself and his sons, but said that there was
+another person whose modesty--
+
+And so forth and so on. He sprung his secret about Huck's share in the
+adventure in the finest dramatic manner he was master of, but the
+surprise it occasioned was largely counterfeit and not as clamorous and
+effusive as it might have been under happier circumstances. However,
+the widow made a pretty fair show of astonishment, and heaped so many
+compliments and so much gratitude upon Huck that he almost forgot the
+nearly intolerable discomfort of his new clothes in the entirely
+intolerable discomfort of being set up as a target for everybody's gaze
+and everybody's laudations.
+
+The widow said she meant to give Huck a home under her roof and have
+him educated; and that when she could spare the money she would start
+him in business in a modest way. Tom's chance was come. He said:
+
+"Huck don't need it. Huck's rich."
+
+Nothing but a heavy strain upon the good manners of the company kept
+back the due and proper complimentary laugh at this pleasant joke. But
+the silence was a little awkward. Tom broke it:
+
+"Huck's got money. Maybe you don't believe it, but he's got lots of
+it. Oh, you needn't smile--I reckon I can show you. You just wait a
+minute."
+
+Tom ran out of doors. The company looked at each other with a
+perplexed interest--and inquiringly at Huck, who was tongue-tied.
+
+"Sid, what ails Tom?" said Aunt Polly. "He--well, there ain't ever any
+making of that boy out. I never--"
+
+Tom entered, struggling with the weight of his sacks, and Aunt Polly
+did not finish her sentence. Tom poured the mass of yellow coin upon
+the table and said:
+
+"There--what did I tell you? Half of it's Huck's and half of it's mine!"
+
+The spectacle took the general breath away. All gazed, nobody spoke
+for a moment. Then there was a unanimous call for an explanation. Tom
+said he could furnish it, and he did. The tale was long, but brimful of
+interest. There was scarcely an interruption from any one to break the
+charm of its flow. When he had finished, Mr. Jones said:
+
+"I thought I had fixed up a little surprise for this occasion, but it
+don't amount to anything now. This one makes it sing mighty small, I'm
+willing to allow."
+
+The money was counted. The sum amounted to a little over twelve
+thousand dollars. It was more than any one present had ever seen at one
+time before, though several persons were there who were worth
+considerably more than that in property.
+
+
+
+CHAPTER XXXV
+
+THE reader may rest satisfied that Tom's and Huck's windfall made a
+mighty stir in the poor little village of St. Petersburg. So vast a
+sum, all in actual cash, seemed next to incredible. It was talked
+about, gloated over, glorified, until the reason of many of the
+citizens tottered under the strain of the unhealthy excitement. Every
+"haunted" house in St. Petersburg and the neighboring villages was
+dissected, plank by plank, and its foundations dug up and ransacked for
+hidden treasure--and not by boys, but men--pretty grave, unromantic
+men, too, some of them. Wherever Tom and Huck appeared they were
+courted, admired, stared at. The boys were not able to remember that
+their remarks had possessed weight before; but now their sayings were
+treasured and repeated; everything they did seemed somehow to be
+regarded as remarkable; they had evidently lost the power of doing and
+saying commonplace things; moreover, their past history was raked up
+and discovered to bear marks of conspicuous originality. The village
+paper published biographical sketches of the boys.
+
+The Widow Douglas put Huck's money out at six per cent., and Judge
+Thatcher did the same with Tom's at Aunt Polly's request. Each lad had
+an income, now, that was simply prodigious--a dollar for every week-day
+in the year and half of the Sundays. It was just what the minister got
+--no, it was what he was promised--he generally couldn't collect it. A
+dollar and a quarter a week would board, lodge, and school a boy in
+those old simple days--and clothe him and wash him, too, for that
+matter.
+
+Judge Thatcher had conceived a great opinion of Tom. He said that no
+commonplace boy would ever have got his daughter out of the cave. When
+Becky told her father, in strict confidence, how Tom had taken her
+whipping at school, the Judge was visibly moved; and when she pleaded
+grace for the mighty lie which Tom had told in order to shift that
+whipping from her shoulders to his own, the Judge said with a fine
+outburst that it was a noble, a generous, a magnanimous lie--a lie that
+was worthy to hold up its head and march down through history breast to
+breast with George Washington's lauded Truth about the hatchet! Becky
+thought her father had never looked so tall and so superb as when he
+walked the floor and stamped his foot and said that. She went straight
+off and told Tom about it.
+
+Judge Thatcher hoped to see Tom a great lawyer or a great soldier some
+day. He said he meant to look to it that Tom should be admitted to the
+National Military Academy and afterward trained in the best law school
+in the country, in order that he might be ready for either career or
+both.
+
+Huck Finn's wealth and the fact that he was now under the Widow
+Douglas' protection introduced him into society--no, dragged him into
+it, hurled him into it--and his sufferings were almost more than he
+could bear. The widow's servants kept him clean and neat, combed and
+brushed, and they bedded him nightly in unsympathetic sheets that had
+not one little spot or stain which he could press to his heart and know
+for a friend. He had to eat with a knife and fork; he had to use
+napkin, cup, and plate; he had to learn his book, he had to go to
+church; he had to talk so properly that speech was become insipid in
+his mouth; whithersoever he turned, the bars and shackles of
+civilization shut him in and bound him hand and foot.
+
+He bravely bore his miseries three weeks, and then one day turned up
+missing. For forty-eight hours the widow hunted for him everywhere in
+great distress. The public were profoundly concerned; they searched
+high and low, they dragged the river for his body. Early the third
+morning Tom Sawyer wisely went poking among some old empty hogsheads
+down behind the abandoned slaughter-house, and in one of them he found
+the refugee. Huck had slept there; he had just breakfasted upon some
+stolen odds and ends of food, and was lying off, now, in comfort, with
+his pipe. He was unkempt, uncombed, and clad in the same old ruin of
+rags that had made him picturesque in the days when he was free and
+happy. Tom routed him out, told him the trouble he had been causing,
+and urged him to go home. Huck's face lost its tranquil content, and
+took a melancholy cast. He said:
+
+"Don't talk about it, Tom. I've tried it, and it don't work; it don't
+work, Tom. It ain't for me; I ain't used to it. The widder's good to
+me, and friendly; but I can't stand them ways. She makes me get up just
+at the same time every morning; she makes me wash, they comb me all to
+thunder; she won't let me sleep in the woodshed; I got to wear them
+blamed clothes that just smothers me, Tom; they don't seem to any air
+git through 'em, somehow; and they're so rotten nice that I can't set
+down, nor lay down, nor roll around anywher's; I hain't slid on a
+cellar-door for--well, it 'pears to be years; I got to go to church and
+sweat and sweat--I hate them ornery sermons! I can't ketch a fly in
+there, I can't chaw. I got to wear shoes all Sunday. The widder eats by
+a bell; she goes to bed by a bell; she gits up by a bell--everything's
+so awful reg'lar a body can't stand it."
+
+"Well, everybody does that way, Huck."
+
+"Tom, it don't make no difference. I ain't everybody, and I can't
+STAND it. It's awful to be tied up so. And grub comes too easy--I don't
+take no interest in vittles, that way. I got to ask to go a-fishing; I
+got to ask to go in a-swimming--dern'd if I hain't got to ask to do
+everything. Well, I'd got to talk so nice it wasn't no comfort--I'd got
+to go up in the attic and rip out awhile, every day, to git a taste in
+my mouth, or I'd a died, Tom. The widder wouldn't let me smoke; she
+wouldn't let me yell, she wouldn't let me gape, nor stretch, nor
+scratch, before folks--" [Then with a spasm of special irritation and
+injury]--"And dad fetch it, she prayed all the time! I never see such a
+woman! I HAD to shove, Tom--I just had to. And besides, that school's
+going to open, and I'd a had to go to it--well, I wouldn't stand THAT,
+Tom. Looky here, Tom, being rich ain't what it's cracked up to be. It's
+just worry and worry, and sweat and sweat, and a-wishing you was dead
+all the time. Now these clothes suits me, and this bar'l suits me, and
+I ain't ever going to shake 'em any more. Tom, I wouldn't ever got into
+all this trouble if it hadn't 'a' ben for that money; now you just take
+my sheer of it along with your'n, and gimme a ten-center sometimes--not
+many times, becuz I don't give a dern for a thing 'thout it's tollable
+hard to git--and you go and beg off for me with the widder."
+
+"Oh, Huck, you know I can't do that. 'Tain't fair; and besides if
+you'll try this thing just a while longer you'll come to like it."
+
+"Like it! Yes--the way I'd like a hot stove if I was to set on it long
+enough. No, Tom, I won't be rich, and I won't live in them cussed
+smothery houses. I like the woods, and the river, and hogsheads, and
+I'll stick to 'em, too. Blame it all! just as we'd got guns, and a
+cave, and all just fixed to rob, here this dern foolishness has got to
+come up and spile it all!"
+
+Tom saw his opportunity--
+
+"Lookyhere, Huck, being rich ain't going to keep me back from turning
+robber."
+
+"No! Oh, good-licks; are you in real dead-wood earnest, Tom?"
+
+"Just as dead earnest as I'm sitting here. But Huck, we can't let you
+into the gang if you ain't respectable, you know."
+
+Huck's joy was quenched.
+
+"Can't let me in, Tom? Didn't you let me go for a pirate?"
+
+"Yes, but that's different. A robber is more high-toned than what a
+pirate is--as a general thing. In most countries they're awful high up
+in the nobility--dukes and such."
+
+"Now, Tom, hain't you always ben friendly to me? You wouldn't shet me
+out, would you, Tom? You wouldn't do that, now, WOULD you, Tom?"
+
+"Huck, I wouldn't want to, and I DON'T want to--but what would people
+say? Why, they'd say, 'Mph! Tom Sawyer's Gang! pretty low characters in
+it!' They'd mean you, Huck. You wouldn't like that, and I wouldn't."
+
+Huck was silent for some time, engaged in a mental struggle. Finally
+he said:
+
+"Well, I'll go back to the widder for a month and tackle it and see if
+I can come to stand it, if you'll let me b'long to the gang, Tom."
+
+"All right, Huck, it's a whiz! Come along, old chap, and I'll ask the
+widow to let up on you a little, Huck."
+
+"Will you, Tom--now will you? That's good. If she'll let up on some of
+the roughest things, I'll smoke private and cuss private, and crowd
+through or bust. When you going to start the gang and turn robbers?"
+
+"Oh, right off. We'll get the boys together and have the initiation
+to-night, maybe."
+
+"Have the which?"
+
+"Have the initiation."
+
+"What's that?"
+
+"It's to swear to stand by one another, and never tell the gang's
+secrets, even if you're chopped all to flinders, and kill anybody and
+all his family that hurts one of the gang."
+
+"That's gay--that's mighty gay, Tom, I tell you."
+
+"Well, I bet it is. And all that swearing's got to be done at
+midnight, in the lonesomest, awfulest place you can find--a ha'nted
+house is the best, but they're all ripped up now."
+
+"Well, midnight's good, anyway, Tom."
+
+"Yes, so it is. And you've got to swear on a coffin, and sign it with
+blood."
+
+"Now, that's something LIKE! Why, it's a million times bullier than
+pirating. I'll stick to the widder till I rot, Tom; and if I git to be
+a reg'lar ripper of a robber, and everybody talking 'bout it, I reckon
+she'll be proud she snaked me in out of the wet."
+
+
+
+CONCLUSION
+
+SO endeth this chronicle. It being strictly a history of a BOY, it
+must stop here; the story could not go much further without becoming
+the history of a MAN. When one writes a novel about grown people, he
+knows exactly where to stop--that is, with a marriage; but when he
+writes of juveniles, he must stop where he best can.
+
+Most of the characters that perform in this book still live, and are
+prosperous and happy. Some day it may seem worth while to take up the
+story of the younger ones again and see what sort of men and women they
+turned out to be; therefore it will be wisest not to reveal any of that
+part of their lives at present.
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/README.md b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/README.md
new file mode 100644
index 0000000..da6d966
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/README.md
@@ -0,0 +1,33 @@
+# libbacktrace
+A C library that may be linked into a C/C++ program to produce symbolic backtraces
+
+Initially written by Ian Lance Taylor <iant@golang.org>.
+
+This is version 1.0.
+It is likely that this will always be version 1.0.
+
+The libbacktrace library may be linked into a program or library and
+used to produce symbolic backtraces.
+Sample uses would be to print a detailed backtrace when an error
+occurs or to gather detailed profiling information.
+
+The libbacktrace library is provided under a BSD license.
+See the source files for the exact license text.
+
+The public functions are declared and documented in the header file
+backtrace.h, which should be #include'd by a user of the library.
+
+Building libbacktrace will generate a file backtrace-supported.h,
+which a user of the library may use to determine whether backtraces
+will work.
+See the source file backtrace-supported.h.in for the macros that it
+defines.
+
+As of January 2018, libbacktrace only supports ELF, PE/COFF, and XCOFF
+executables with DWARF debugging information.
+The library is written to make it straightforward to add support for
+other object file and debugging formats.
+
+The library relies on the C++ unwind API defined at
+https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html
+This API is provided by GCC.
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/acinclude.m4 b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/acinclude.m4
new file mode 100644
index 0000000..daa73af
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/acinclude.m4
@@ -0,0 +1,72 @@
+dnl
+dnl Check whether _Unwind_GetIPInfo is available without doing a link
+dnl test so we can use this with libstdc++-v3 and libjava.  Need to
+dnl use $target to set defaults because automatic checking is not possible
+dnl without a link test (and maybe even with a link test).
+dnl
+
+AC_DEFUN([GCC_CHECK_UNWIND_GETIPINFO], [
+  AC_ARG_WITH(system-libunwind,
+  [  --with-system-libunwind use installed libunwind])
+  # If system-libunwind was not specifically set, pick a default setting.
+  if test x$with_system_libunwind = x; then
+    case ${target} in
+      ia64-*-hpux*) with_system_libunwind=yes ;;
+      *) with_system_libunwind=no ;;
+    esac
+  fi
+  # Based on system-libunwind and target, do we have ipinfo?
+  if  test x$with_system_libunwind = xyes; then
+    case ${target} in
+      ia64-*-*) have_unwind_getipinfo=no ;;
+      *) have_unwind_getipinfo=yes ;;
+    esac
+  else
+    # Darwin before version 9 does not have _Unwind_GetIPInfo.
+    changequote(,)
+    case ${target} in
+      *-*-darwin[3-8]|*-*-darwin[3-8].*) have_unwind_getipinfo=no ;;
+      *) have_unwind_getipinfo=yes ;;
+    esac
+    changequote([,])
+  fi
+
+  if test x$have_unwind_getipinfo = xyes; then
+    AC_DEFINE(HAVE_GETIPINFO, 1, [Define if _Unwind_GetIPInfo is available.])
+  fi
+])
+
+# ACX_PROG_CC_WARNING_OPTS(WARNINGS, [VARIABLE = WARN_CFLAGS])
+#   Sets @VARIABLE@ to the subset of the given options which the
+#   compiler accepts.
+AC_DEFUN([ACX_PROG_CC_WARNING_OPTS],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_LANG_PUSH(C)
+m4_pushdef([acx_Var], [m4_default([$2], [WARN_CFLAGS])])dnl
+AC_SUBST(acx_Var)dnl
+m4_expand_once([acx_Var=
+],m4_quote(acx_Var=))dnl
+save_CFLAGS="$CFLAGS"
+for real_option in $1; do
+  # Do the check with the no- prefix removed since gcc silently
+  # accepts any -Wno-* option on purpose
+  case $real_option in
+    -Wno-*) option=-W`expr x$real_option : 'x-Wno-\(.*\)'` ;;
+    *) option=$real_option ;;
+  esac
+  AS_VAR_PUSHDEF([acx_Woption], [acx_cv_prog_cc_warning_$option])
+  AC_CACHE_CHECK([whether $CC supports $option], acx_Woption,
+    [CFLAGS="$option"
+    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])],
+      [AS_VAR_SET(acx_Woption, yes)],
+      [AS_VAR_SET(acx_Woption, no)])
+  ])
+  AS_IF([test AS_VAR_GET(acx_Woption) = yes],
+        [acx_Var="$acx_Var${acx_Var:+ }$real_option"])
+  AS_VAR_POPDEF([acx_Woption])dnl
+done
+CFLAGS="$save_CFLAGS"
+m4_popdef([acx_Var])dnl
+AC_LANG_POP(C)
+])# ACX_PROG_CC_WARNING_OPTS
+
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/aclocal.m4 b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/aclocal.m4
new file mode 100644
index 0000000..32a1811
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/aclocal.m4
@@ -0,0 +1,767 @@
+# generated automatically by aclocal 1.11.6 -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
+# Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_ifndef([AC_AUTOCONF_VERSION],
+  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.64],,
+[m4_warning([this file was generated for autoconf 2.64.
+You have another version of autoconf.  It may work, but is not guaranteed to.
+If you have problems, you may need to regenerate the build system entirely.
+To do so, use the procedure documented by the package, typically `autoreconf'.])])
+
+# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008, 2011 Free Software
+# Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 1
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+# (This private macro should not be called outside this file.)
+AC_DEFUN([AM_AUTOMAKE_VERSION],
+[am__api_version='1.11'
+dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+dnl require some minimum version.  Point them to the right macro.
+m4_if([$1], [1.11.6], [],
+      [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+])
+
+# _AM_AUTOCONF_VERSION(VERSION)
+# -----------------------------
+# aclocal traces this macro to find the Autoconf version.
+# This is a private macro too.  Using m4_define simplifies
+# the logic in aclocal, which can simply ignore this definition.
+m4_define([_AM_AUTOCONF_VERSION], [])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.11.6])dnl
+m4_ifndef([AC_AUTOCONF_VERSION],
+  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
+
+# AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-
+
+# Copyright (C) 2001, 2003, 2005, 2011 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 1
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to `$srcdir/foo'.  In other projects, it is set to
+# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory.  The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run.  This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+#    fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+#    fails if $ac_aux_dir is absolute,
+#    fails when called from a subdirectory in a VPATH build with
+#          a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir.  In an in-source build this is usually
+# harmless because $srcdir is `.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir.  That would be:
+#   am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+#   MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH.  The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+])
+
+# AM_CONDITIONAL                                            -*- Autoconf -*-
+
+# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 9
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ(2.52)dnl
+ ifelse([$1], [TRUE],  [AC_FATAL([$0: invalid condition: $1])],
+	[$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])dnl
+AC_SUBST([$1_FALSE])dnl
+_AM_SUBST_NOTMAKE([$1_TRUE])dnl
+_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+m4_define([_AM_COND_VALUE_$1], [$2])dnl
+if $2; then
+  $1_TRUE=
+  $1_FALSE='#'
+else
+  $1_TRUE='#'
+  $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+  AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# Do all the work for Automake.                             -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2008, 2009 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 16
+
+# This macro actually does too much.  Some checks are only needed if
+# your package does certain things.  But this isn't really a big deal.
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out.  PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition.  After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.62])dnl
+dnl Autoconf wants to disallow AM_ names.  We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,,
+  [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+ AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
+AM_MISSING_PROG(AUTOCONF, autoconf)
+AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
+AM_MISSING_PROG(AUTOHEADER, autoheader)
+AM_MISSING_PROG(MAKEINFO, makeinfo)
+AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
+AC_REQUIRE([AM_PROG_MKDIR_P])dnl
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+	      [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+			     [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+		  [_AM_DEPENDENCIES(CC)],
+		  [define([AC_PROG_CC],
+			  defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+		  [_AM_DEPENDENCIES(CXX)],
+		  [define([AC_PROG_CXX],
+			  defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+		  [_AM_DEPENDENCIES(OBJC)],
+		  [define([AC_PROG_OBJC],
+			  defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl
+])
+_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl
+dnl The `parallel-tests' driver may need to know about EXEEXT, so add the
+dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen.  This macro
+dnl is hooked onto _AC_COMPILER_EXEEXT early, see below.
+AC_CONFIG_COMMANDS_PRE(dnl
+[m4_provide_if([_AM_COMPILER_EXEEXT],
+  [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
+])
+
+dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion.  Do not
+dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
+dnl mangled by Autoconf and run in a shell conditional statement.
+m4_define([_AC_COMPILER_EXEEXT],
+m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
+
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated.  The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_arg=$1
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $_am_arg | $_am_arg:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001, 2003, 2005, 2008, 2011 Free Software Foundation,
+# Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 1
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+if test x"${install_sh}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+  *)
+    install_sh="\${SHELL} $am_aux_dir/install-sh"
+  esac
+fi
+AC_SUBST(install_sh)])
+
+# Copyright (C) 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot.  For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+# Add --enable-maintainer-mode option to configure.         -*- Autoconf -*-
+# From Jim Meyering
+
+# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2008,
+# 2011 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 5
+
+# AM_MAINTAINER_MODE([DEFAULT-MODE])
+# ----------------------------------
+# Control maintainer-specific portions of Makefiles.
+# Default is to disable them, unless `enable' is passed literally.
+# For symmetry, `disable' may be passed as well.  Anyway, the user
+# can override the default with the --enable/--disable switch.
+AC_DEFUN([AM_MAINTAINER_MODE],
+[m4_case(m4_default([$1], [disable]),
+       [enable], [m4_define([am_maintainer_other], [disable])],
+       [disable], [m4_define([am_maintainer_other], [enable])],
+       [m4_define([am_maintainer_other], [enable])
+        m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])])
+AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
+  dnl maintainer-mode's default is 'disable' unless 'enable' is passed
+  AC_ARG_ENABLE([maintainer-mode],
+[  --][am_maintainer_other][-maintainer-mode  am_maintainer_other make rules and dependencies not useful
+			  (and sometimes confusing) to the casual installer],
+      [USE_MAINTAINER_MODE=$enableval],
+      [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes]))
+  AC_MSG_RESULT([$USE_MAINTAINER_MODE])
+  AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes])
+  MAINT=$MAINTAINER_MODE_TRUE
+  AC_SUBST([MAINT])dnl
+]
+)
+
+AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE])
+
+# Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
+
+# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 6
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it supports --run.
+# If it does, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([missing])dnl
+if test x"${MISSING+set}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+  *)
+    MISSING="\${SHELL} $am_aux_dir/missing" ;;
+  esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+  am_missing_run="$MISSING --run "
+else
+  am_missing_run=
+  AC_MSG_WARN([`missing' script is too old or missing])
+fi
+])
+
+# Copyright (C) 2003, 2004, 2005, 2006, 2011 Free Software Foundation,
+# Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 1
+
+# AM_PROG_MKDIR_P
+# ---------------
+# Check for `mkdir -p'.
+AC_DEFUN([AM_PROG_MKDIR_P],
+[AC_PREREQ([2.60])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+dnl Automake 1.8 to 1.9.6 used to define mkdir_p.  We now use MKDIR_P,
+dnl while keeping a definition of mkdir_p for backward compatibility.
+dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile.
+dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of
+dnl Makefile.ins that do not define MKDIR_P, so we do our own
+dnl adjustment using top_builddir (which is defined more often than
+dnl MKDIR_P).
+AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl
+case $mkdir_p in
+  [[\\/$]]* | ?:[[\\/]]*) ;;
+  */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+])
+
+# Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2012
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 6
+
+# AM_ENABLE_MULTILIB([MAKEFILE], [REL-TO-TOP-SRCDIR])
+# ---------------------------------------------------
+# Add --enable-multilib to configure.
+AC_DEFUN([AM_ENABLE_MULTILIB],
+[m4_warn([obsolete], [$0 will be removed from Automake core soon.
+Files implementing the "multilib" feature are (and will remain) available
+to the 'contrib/' directory in the Automake distribution.])]dnl
+[# Default to --enable-multilib
+AC_ARG_ENABLE(multilib,
+[  --enable-multilib       build many library versions (default)],
+[case "$enableval" in
+  yes) multilib=yes ;;
+  no)  multilib=no ;;
+  *)   AC_MSG_ERROR([bad value $enableval for multilib option]) ;;
+ esac],
+	      [multilib=yes])
+
+# We may get other options which we leave undocumented:
+# --with-target-subdir, --with-multisrctop, --with-multisubdir
+# See config-ml.in if you want the gory details.
+
+if test "$srcdir" = "."; then
+  if test "$with_target_subdir" != "."; then
+    multi_basedir="$srcdir/$with_multisrctop../$2"
+  else
+    multi_basedir="$srcdir/$with_multisrctop$2"
+  fi
+else
+  multi_basedir="$srcdir/$2"
+fi
+AC_SUBST(multi_basedir)
+
+# Even if the default multilib is not a cross compilation,
+# it may be that some of the other multilibs are.
+if test $cross_compiling = no && test $multilib = yes \
+   && test "x${with_multisubdir}" != x ; then
+   cross_compiling=maybe
+fi
+
+AC_OUTPUT_COMMANDS([
+# Only add multilib support code if we just rebuilt the top-level
+# Makefile.
+case " $CONFIG_FILES " in
+ *" ]m4_default([$1],Makefile)[ "*)
+   ac_file=]m4_default([$1],Makefile)[ . ${multi_basedir}/config-ml.in
+   ;;
+esac],
+		   [
+srcdir="$srcdir"
+host="$host"
+target="$target"
+with_multisubdir="$with_multisubdir"
+with_multisrctop="$with_multisrctop"
+with_target_subdir="$with_target_subdir"
+ac_configure_args="${multilib_arg} ${ac_configure_args}"
+multi_basedir="$multi_basedir"
+CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+CC="$CC"])])dnl
+
+# Helper functions for option handling.                     -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005, 2008, 2010 Free Software
+# Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 5
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# --------------------
+# Set option NAME.  Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Check to make sure that the build environment is sane.    -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 5
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name.  Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+  *[[\\\"\#\$\&\'\`$am_lf]]*)
+    AC_MSG_ERROR([unsafe absolute working directory name]);;
+esac
+case $srcdir in
+  *[[\\\"\#\$\&\'\`$am_lf\ \	]]*)
+    AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);;
+esac
+
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+   if test "$[*]" = "X"; then
+      # -L didn't work.
+      set X `ls -t "$srcdir/configure" conftest.file`
+   fi
+   rm -f conftest.file
+   if test "$[*]" != "X $srcdir/configure conftest.file" \
+      && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      AC_MSG_ERROR([ls -t appears to fail.  Make sure there is not a broken
+alias in your environment])
+   fi
+
+   test "$[2]" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT(yes)])
+
+# Copyright (C) 2001, 2003, 2005, 2011 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 1
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor `install' (even GNU) is that you can't
+# specify the program used to strip binaries.  This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in `make install-strip', and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'.  However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
+if test "$cross_compiling" != no; then
+  AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Copyright (C) 2006, 2008, 2010 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 3
+
+# _AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
+# This macro is traced by Automake.
+AC_DEFUN([_AM_SUBST_NOTMAKE])
+
+# AM_SUBST_NOTMAKE(VARIABLE)
+# --------------------------
+# Public sister of _AM_SUBST_NOTMAKE.
+AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
+
+# Check how to create a tarball.                            -*- Autoconf -*-
+
+# Copyright (C) 2004, 2005, 2012 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of `v7', `ustar', or `pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+#     tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+#     $(am__untar) < result.tar
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.  Yes, it's still used
+# in the wild :-(  We should find a proper way to deprecate it ...
+AC_SUBST([AMTAR], ['$${TAR-tar}'])
+m4_if([$1], [v7],
+     [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'],
+     [m4_case([$1], [ustar],, [pax],,
+              [m4_fatal([Unknown tar format])])
+AC_MSG_CHECKING([how to create a $1 tar archive])
+# Loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+_am_tools=${am_cv_prog_tar_$1-$_am_tools}
+# Do not fold the above two line into one, because Tru64 sh and
+# Solaris sh will not grok spaces in the rhs of `-'.
+for _am_tool in $_am_tools
+do
+  case $_am_tool in
+  gnutar)
+    for _am_tar in tar gnutar gtar;
+    do
+      AM_RUN_LOG([$_am_tar --version]) && break
+    done
+    am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+    am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+    am__untar="$_am_tar -xf -"
+    ;;
+  plaintar)
+    # Must skip GNU tar: if it does not support --format= it doesn't create
+    # ustar tarball either.
+    (tar --version) >/dev/null 2>&1 && continue
+    am__tar='tar chf - "$$tardir"'
+    am__tar_='tar chf - "$tardir"'
+    am__untar='tar xf -'
+    ;;
+  pax)
+    am__tar='pax -L -x $1 -w "$$tardir"'
+    am__tar_='pax -L -x $1 -w "$tardir"'
+    am__untar='pax -r'
+    ;;
+  cpio)
+    am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+    am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+    am__untar='cpio -i -H $1 -d'
+    ;;
+  none)
+    am__tar=false
+    am__tar_=false
+    am__untar=false
+    ;;
+  esac
+
+  # If the value was cached, stop now.  We just wanted to have am__tar
+  # and am__untar set.
+  test -n "${am_cv_prog_tar_$1}" && break
+
+  # tar/untar a dummy directory, and stop if the command works
+  rm -rf conftest.dir
+  mkdir conftest.dir
+  echo GrepMe > conftest.dir/file
+  AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+  rm -rf conftest.dir
+  if test -s conftest.tar; then
+    AM_RUN_LOG([$am__untar <conftest.tar])
+    grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+  fi
+done
+rm -rf conftest.dir
+
+AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
+m4_include([config/libtool.m4])
+m4_include([config/ltoptions.m4])
+m4_include([config/ltsugar.m4])
+m4_include([config/ltversion.m4])
+m4_include([config/lt~obsolete.m4])
+m4_include([acinclude.m4])
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/alloc.c b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/alloc.c
new file mode 100644
index 0000000..7070afb
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/alloc.c
@@ -0,0 +1,156 @@
+/* alloc.c -- Memory allocation without mmap.
+   Copyright (C) 2012-2018 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include "backtrace.h"
+#include "internal.h"
+
+/* Allocation routines to use on systems that do not support anonymous
+   mmap.  This implementation just uses malloc, which means that the
+   backtrace functions may not be safely invoked from a signal
+   handler.  */
+
+/* Allocate memory like malloc.  If ERROR_CALLBACK is NULL, don't
+   report an error.  */
+
+void *
+backtrace_alloc (struct backtrace_state *state ATTRIBUTE_UNUSED,
+		 size_t size, backtrace_error_callback error_callback,
+		 void *data)
+{
+  void *ret;
+
+  ret = malloc (size);
+  if (ret == NULL)
+    {
+      if (error_callback)
+	error_callback (data, "malloc", errno);
+    }
+  return ret;
+}
+
+/* Free memory.  */
+
+void
+backtrace_free (struct backtrace_state *state ATTRIBUTE_UNUSED,
+		void *p, size_t size ATTRIBUTE_UNUSED,
+		backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
+		void *data ATTRIBUTE_UNUSED)
+{
+  free (p);
+}
+
+/* Grow VEC by SIZE bytes.  */
+
+void *
+backtrace_vector_grow (struct backtrace_state *state ATTRIBUTE_UNUSED,
+		       size_t size, backtrace_error_callback error_callback,
+		       void *data, struct backtrace_vector *vec)
+{
+  void *ret;
+
+  if (size > vec->alc)
+    {
+      size_t alc;
+      void *base;
+
+      if (vec->size == 0)
+	alc = 32 * size;
+      else if (vec->size >= 4096)
+	alc = vec->size + 4096;
+      else
+	alc = 2 * vec->size;
+
+      if (alc < vec->size + size)
+	alc = vec->size + size;
+
+      base = realloc (vec->base, alc);
+      if (base == NULL)
+	{
+	  error_callback (data, "realloc", errno);
+	  return NULL;
+	}
+
+      vec->base = base;
+      vec->alc = alc - vec->size;
+    }
+
+  ret = (char *) vec->base + vec->size;
+  vec->size += size;
+  vec->alc -= size;
+  return ret;
+}
+
+/* Finish the current allocation on VEC.  */
+
+void *
+backtrace_vector_finish (struct backtrace_state *state,
+			 struct backtrace_vector *vec,
+			 backtrace_error_callback error_callback,
+			 void *data)
+{
+  void *ret;
+
+  /* With this allocator we call realloc in backtrace_vector_grow,
+     which means we can't easily reuse the memory here.  So just
+     release it.  */
+  if (!backtrace_vector_release (state, vec, error_callback, data))
+    return NULL;
+  ret = vec->base;
+  vec->base = NULL;
+  vec->size = 0;
+  vec->alc = 0;
+  return ret;
+}
+
+/* Release any extra space allocated for VEC.  */
+
+int
+backtrace_vector_release (struct backtrace_state *state ATTRIBUTE_UNUSED,
+			  struct backtrace_vector *vec,
+			  backtrace_error_callback error_callback,
+			  void *data)
+{
+  vec->base = realloc (vec->base, vec->size);
+  if (vec->base == NULL)
+    {
+      error_callback (data, "realloc", errno);
+      return 0;
+    }
+  vec->alc = 0;
+  return 1;
+}
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/atomic.c b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/atomic.c
new file mode 100644
index 0000000..5ab1600
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/atomic.c
@@ -0,0 +1,113 @@
+/* atomic.c -- Support for atomic functions if not present.
+   Copyright (C) 2013-2018 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <sys/types.h>
+
+#include "backtrace.h"
+#include "backtrace-supported.h"
+#include "internal.h"
+
+/* This file holds implementations of the atomic functions that are
+   used if the host compiler has the sync functions but not the atomic
+   functions, as is true of versions of GCC before 4.7.  */
+
+#if !defined (HAVE_ATOMIC_FUNCTIONS) && defined (HAVE_SYNC_FUNCTIONS)
+
+/* Do an atomic load of a pointer.  */
+
+void *
+backtrace_atomic_load_pointer (void *arg)
+{
+  void **pp;
+  void *p;
+
+  pp = (void **) arg;
+  p = *pp;
+  while (!__sync_bool_compare_and_swap (pp, p, p))
+    p = *pp;
+  return p;
+}
+
+/* Do an atomic load of an int.  */
+
+int
+backtrace_atomic_load_int (int *p)
+{
+  int i;
+
+  i = *p;
+  while (!__sync_bool_compare_and_swap (p, i, i))
+    i = *p;
+  return i;
+}
+
+/* Do an atomic store of a pointer.  */
+
+void
+backtrace_atomic_store_pointer (void *arg, void *p)
+{
+  void **pp;
+  void *old;
+
+  pp = (void **) arg;
+  old = *pp;
+  while (!__sync_bool_compare_and_swap (pp, old, p))
+    old = *pp;
+}
+
+/* Do an atomic store of a size_t value.  */
+
+void
+backtrace_atomic_store_size_t (size_t *p, size_t v)
+{
+  size_t old;
+
+  old = *p;
+  while (!__sync_bool_compare_and_swap (p, old, v))
+    old = *p;
+}
+
+/* Do an atomic store of a int value.  */
+
+void
+backtrace_atomic_store_int (int *p, int v)
+{
+  size_t old;
+
+  old = *p;
+  while (!__sync_bool_compare_and_swap (p, old, v))
+    old = *p;
+}
+
+#endif
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/backtrace-supported.h.in b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/backtrace-supported.h.in
new file mode 100644
index 0000000..c2d03d2
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/backtrace-supported.h.in
@@ -0,0 +1,66 @@
+/* backtrace-supported.h.in -- Whether stack backtrace is supported.
+   Copyright (C) 2012-2016 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+/* The file backtrace-supported.h.in is used by configure to generate
+   the file backtrace-supported.h.  The file backtrace-supported.h may
+   be #include'd to see whether the backtrace library will be able to
+   get a backtrace and produce symbolic information.  */
+
+
+/* BACKTRACE_SUPPORTED will be #define'd as 1 if the backtrace library
+   should work, 0 if it will not.  Libraries may #include this to make
+   other arrangements.  */
+
+#define BACKTRACE_SUPPORTED @BACKTRACE_SUPPORTED@
+
+/* BACKTRACE_USES_MALLOC will be #define'd as 1 if the backtrace
+   library will call malloc as it works, 0 if it will call mmap
+   instead.  This may be used to determine whether it is safe to call
+   the backtrace functions from a signal handler.  In general this
+   only applies to calls like backtrace and backtrace_pcinfo.  It does
+   not apply to backtrace_simple, which never calls malloc.  It does
+   not apply to backtrace_print, which always calls fprintf and
+   therefore malloc.  */
+
+#define BACKTRACE_USES_MALLOC @BACKTRACE_USES_MALLOC@
+
+/* BACKTRACE_SUPPORTS_THREADS will be #define'd as 1 if the backtrace
+   library is configured with threading support, 0 if not.  If this is
+   0, the threaded parameter to backtrace_create_state must be passed
+   as 0.  */
+
+#define BACKTRACE_SUPPORTS_THREADS @BACKTRACE_SUPPORTS_THREADS@
+
+/* BACKTRACE_SUPPORTS_DATA will be #defined'd as 1 if the backtrace_syminfo
+   will work for variables.  It will always work for functions.  */
+
+#define BACKTRACE_SUPPORTS_DATA @BACKTRACE_SUPPORTS_DATA@
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/backtrace.c b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/backtrace.c
new file mode 100644
index 0000000..f8e3dc5
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/backtrace.c
@@ -0,0 +1,129 @@
+/* backtrace.c -- Entry point for stack backtrace library.
+   Copyright (C) 2012-2018 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <sys/types.h>
+
+#include "unwind.h"
+#include "backtrace.h"
+#include "internal.h"
+
+/* The main backtrace_full routine.  */
+
+/* Data passed through _Unwind_Backtrace.  */
+
+struct backtrace_data
+{
+  /* Number of frames to skip.  */
+  int skip;
+  /* Library state.  */
+  struct backtrace_state *state;
+  /* Callback routine.  */
+  backtrace_full_callback callback;
+  /* Error callback routine.  */
+  backtrace_error_callback error_callback;
+  /* Data to pass to callback routines.  */
+  void *data;
+  /* Value to return from backtrace_full.  */
+  int ret;
+  /* Whether there is any memory available.  */
+  int can_alloc;
+};
+
+/* Unwind library callback routine.  This is passed to
+   _Unwind_Backtrace.  */
+
+static _Unwind_Reason_Code
+unwind (struct _Unwind_Context *context, void *vdata)
+{
+  struct backtrace_data *bdata = (struct backtrace_data *) vdata;
+  uintptr_t pc;
+  int ip_before_insn = 0;
+
+#ifdef HAVE_GETIPINFO
+  pc = _Unwind_GetIPInfo (context, &ip_before_insn);
+#else
+  pc = _Unwind_GetIP (context);
+#endif
+
+  if (bdata->skip > 0)
+    {
+      --bdata->skip;
+      return _URC_NO_REASON;
+    }
+
+  if (!ip_before_insn)
+    --pc;
+
+  if (!bdata->can_alloc)
+    bdata->ret = bdata->callback (bdata->data, pc, NULL, 0, NULL);
+  else
+    bdata->ret = backtrace_pcinfo (bdata->state, pc, bdata->callback,
+				   bdata->error_callback, bdata->data);
+  if (bdata->ret != 0)
+    return _URC_END_OF_STACK;
+
+  return _URC_NO_REASON;
+}
+
+/* Get a stack backtrace.  */
+
+int
+backtrace_full (struct backtrace_state *state, int skip,
+		backtrace_full_callback callback,
+		backtrace_error_callback error_callback, void *data)
+{
+  struct backtrace_data bdata;
+  void *p;
+
+  bdata.skip = skip + 1;
+  bdata.state = state;
+  bdata.callback = callback;
+  bdata.error_callback = error_callback;
+  bdata.data = data;
+  bdata.ret = 0;
+
+  /* If we can't allocate any memory at all, don't try to produce
+     file/line information.  */
+  p = backtrace_alloc (state, 4096, NULL, NULL);
+  if (p == NULL)
+    bdata.can_alloc = 0;
+  else
+    {
+      backtrace_free (state, p, 4096, NULL, NULL);
+      bdata.can_alloc = 1;
+    }
+
+  _Unwind_Backtrace (unwind, &bdata);
+  return bdata.ret;
+}
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/backtrace.h b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/backtrace.h
new file mode 100644
index 0000000..17b1019
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/backtrace.h
@@ -0,0 +1,182 @@
+/* backtrace.h -- Public header file for stack backtrace library.
+   Copyright (C) 2012-2018 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#ifndef BACKTRACE_H
+#define BACKTRACE_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The backtrace state.  This struct is intentionally not defined in
+   the public interface.  */
+
+struct backtrace_state;
+
+/* The type of the error callback argument to backtrace functions.
+   This function, if not NULL, will be called for certain error cases.
+   The DATA argument is passed to the function that calls this one.
+   The MSG argument is an error message.  The ERRNUM argument, if
+   greater than 0, holds an errno value.  The MSG buffer may become
+   invalid after this function returns.
+
+   As a special case, the ERRNUM argument will be passed as -1 if no
+   debug info can be found for the executable, but the function
+   requires debug info (e.g., backtrace_full, backtrace_pcinfo).  The
+   MSG in this case will be something along the lines of "no debug
+   info".  Similarly, ERRNUM will be passed as -1 if there is no
+   symbol table, but the function requires a symbol table (e.g.,
+   backtrace_syminfo).  This may be used as a signal that some other
+   approach should be tried.  */
+
+typedef void (*backtrace_error_callback) (void *data, const char *msg,
+					  int errnum);
+
+/* Create state information for the backtrace routines.  This must be
+   called before any of the other routines, and its return value must
+   be passed to all of the other routines.  FILENAME is the path name
+   of the executable file; if it is NULL the library will try
+   system-specific path names.  If not NULL, FILENAME must point to a
+   permanent buffer.  If THREADED is non-zero the state may be
+   accessed by multiple threads simultaneously, and the library will
+   use appropriate atomic operations.  If THREADED is zero the state
+   may only be accessed by one thread at a time.  This returns a state
+   pointer on success, NULL on error.  If an error occurs, this will
+   call the ERROR_CALLBACK routine.  */
+
+extern struct backtrace_state *backtrace_create_state (
+    const char *filename, int threaded,
+    backtrace_error_callback error_callback, void *data);
+
+/* The type of the callback argument to the backtrace_full function.
+   DATA is the argument passed to backtrace_full.  PC is the program
+   counter.  FILENAME is the name of the file containing PC, or NULL
+   if not available.  LINENO is the line number in FILENAME containing
+   PC, or 0 if not available.  FUNCTION is the name of the function
+   containing PC, or NULL if not available.  This should return 0 to
+   continuing tracing.  The FILENAME and FUNCTION buffers may become
+   invalid after this function returns.  */
+
+typedef int (*backtrace_full_callback) (void *data, uintptr_t pc,
+					const char *filename, int lineno,
+					const char *function);
+
+/* Get a full stack backtrace.  SKIP is the number of frames to skip;
+   passing 0 will start the trace with the function calling
+   backtrace_full.  DATA is passed to the callback routine.  If any
+   call to CALLBACK returns a non-zero value, the stack backtrace
+   stops, and backtrace returns that value; this may be used to limit
+   the number of stack frames desired.  If all calls to CALLBACK
+   return 0, backtrace returns 0.  The backtrace_full function will
+   make at least one call to either CALLBACK or ERROR_CALLBACK.  This
+   function requires debug info for the executable.  */
+
+extern int backtrace_full (struct backtrace_state *state, int skip,
+			   backtrace_full_callback callback,
+			   backtrace_error_callback error_callback,
+			   void *data);
+
+/* The type of the callback argument to the backtrace_simple function.
+   DATA is the argument passed to simple_backtrace.  PC is the program
+   counter.  This should return 0 to continue tracing.  */
+
+typedef int (*backtrace_simple_callback) (void *data, uintptr_t pc);
+
+/* Get a simple backtrace.  SKIP is the number of frames to skip, as
+   in backtrace.  DATA is passed to the callback routine.  If any call
+   to CALLBACK returns a non-zero value, the stack backtrace stops,
+   and backtrace_simple returns that value.  Otherwise
+   backtrace_simple returns 0.  The backtrace_simple function will
+   make at least one call to either CALLBACK or ERROR_CALLBACK.  This
+   function does not require any debug info for the executable.  */
+
+extern int backtrace_simple (struct backtrace_state *state, int skip,
+			     backtrace_simple_callback callback,
+			     backtrace_error_callback error_callback,
+			     void *data);
+
+/* Print the current backtrace in a user readable format to a FILE.
+   SKIP is the number of frames to skip, as in backtrace_full.  Any
+   error messages are printed to stderr.  This function requires debug
+   info for the executable.  */
+
+extern void backtrace_print (struct backtrace_state *state, int skip, FILE *);
+
+/* Given PC, a program counter in the current program, call the
+   callback function with filename, line number, and function name
+   information.  This will normally call the callback function exactly
+   once.  However, if the PC happens to describe an inlined call, and
+   the debugging information contains the necessary information, then
+   this may call the callback function multiple times.  This will make
+   at least one call to either CALLBACK or ERROR_CALLBACK.  This
+   returns the first non-zero value returned by CALLBACK, or 0.  */
+
+extern int backtrace_pcinfo (struct backtrace_state *state, uintptr_t pc,
+			     backtrace_full_callback callback,
+			     backtrace_error_callback error_callback,
+			     void *data);
+
+/* The type of the callback argument to backtrace_syminfo.  DATA and
+   PC are the arguments passed to backtrace_syminfo.  SYMNAME is the
+   name of the symbol for the corresponding code.  SYMVAL is the
+   value and SYMSIZE is the size of the symbol.  SYMNAME will be NULL
+   if no error occurred but the symbol could not be found.  */
+
+typedef void (*backtrace_syminfo_callback) (void *data, uintptr_t pc,
+					    const char *symname,
+					    uintptr_t symval,
+					    uintptr_t symsize);
+
+/* Given ADDR, an address or program counter in the current program,
+   call the callback information with the symbol name and value
+   describing the function or variable in which ADDR may be found.
+   This will call either CALLBACK or ERROR_CALLBACK exactly once.
+   This returns 1 on success, 0 on failure.  This function requires
+   the symbol table but does not require the debug info.  Note that if
+   the symbol table is present but ADDR could not be found in the
+   table, CALLBACK will be called with a NULL SYMNAME argument.
+   Returns 1 on success, 0 on error.  */
+
+extern int backtrace_syminfo (struct backtrace_state *state, uintptr_t addr,
+			      backtrace_syminfo_callback callback,
+			      backtrace_error_callback error_callback,
+			      void *data);
+
+#ifdef __cplusplus
+} /* End extern "C".  */
+#endif
+
+#endif
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/btest.c b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/btest.c
new file mode 100644
index 0000000..1348d54
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/btest.c
@@ -0,0 +1,500 @@
+/* btest.c -- Test for libbacktrace library
+   Copyright (C) 2012-2018 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+/* This program tests the externally visible interfaces of the
+   libbacktrace library.  */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "filenames.h"
+
+#include "backtrace.h"
+#include "backtrace-supported.h"
+
+#include "testlib.h"
+
+/* Test the backtrace function with non-inlined functions.  */
+
+static int test1 (void) __attribute__ ((noinline, unused));
+static int f2 (int) __attribute__ ((noinline));
+static int f3 (int, int) __attribute__ ((noinline));
+
+static int
+test1 (void)
+{
+  /* Returning a value here and elsewhere avoids a tailcall which
+     would mess up the backtrace.  */
+  return f2 (__LINE__) + 1;
+}
+
+static int
+f2 (int f1line)
+{
+  return f3 (f1line, __LINE__) + 2;
+}
+
+static int
+f3 (int f1line, int f2line)
+{
+  struct info all[20];
+  struct bdata data;
+  int f3line;
+  int i;
+
+  data.all = &all[0];
+  data.index = 0;
+  data.max = 20;
+  data.failed = 0;
+
+  f3line = __LINE__ + 1;
+  i = backtrace_full (state, 0, callback_one, error_callback_one, &data);
+
+  if (i != 0)
+    {
+      fprintf (stderr, "test1: unexpected return value %d\n", i);
+      data.failed = 1;
+    }
+
+  if (data.index < 3)
+    {
+      fprintf (stderr,
+	       "test1: not enough frames; got %zu, expected at least 3\n",
+	       data.index);
+      data.failed = 1;
+    }
+
+  check ("test1", 0, all, f3line, "f3", "btest.c", &data.failed);
+  check ("test1", 1, all, f2line, "f2", "btest.c", &data.failed);
+  check ("test1", 2, all, f1line, "test1", "btest.c", &data.failed);
+
+  printf ("%s: backtrace_full noinline\n", data.failed ? "FAIL" : "PASS");
+
+  if (data.failed)
+    ++failures;
+
+  return failures;
+}
+
+/* Test the backtrace function with inlined functions.  */
+
+static inline int test2 (void) __attribute__ ((always_inline, unused));
+static inline int f12 (int) __attribute__ ((always_inline));
+static inline int f13 (int, int) __attribute__ ((always_inline));
+
+static inline int
+test2 (void)
+{
+  return f12 (__LINE__) + 1;
+}
+
+static inline int
+f12 (int f1line)
+{
+  return f13 (f1line, __LINE__) + 2;
+}
+
+static inline int
+f13 (int f1line, int f2line)
+{
+  struct info all[20];
+  struct bdata data;
+  int f3line;
+  int i;
+
+  data.all = &all[0];
+  data.index = 0;
+  data.max = 20;
+  data.failed = 0;
+
+  f3line = __LINE__ + 1;
+  i = backtrace_full (state, 0, callback_one, error_callback_one, &data);
+
+  if (i != 0)
+    {
+      fprintf (stderr, "test2: unexpected return value %d\n", i);
+      data.failed = 1;
+    }
+
+  check ("test2", 0, all, f3line, "f13", "btest.c", &data.failed);
+  check ("test2", 1, all, f2line, "f12", "btest.c", &data.failed);
+  check ("test2", 2, all, f1line, "test2", "btest.c", &data.failed);
+
+  printf ("%s: backtrace_full inline\n", data.failed ? "FAIL" : "PASS");
+
+  if (data.failed)
+    ++failures;
+
+  return failures;
+}
+
+/* Test the backtrace_simple function with non-inlined functions.  */
+
+static int test3 (void) __attribute__ ((noinline, unused));
+static int f22 (int) __attribute__ ((noinline));
+static int f23 (int, int) __attribute__ ((noinline));
+
+static int
+test3 (void)
+{
+  return f22 (__LINE__) + 1;
+}
+
+static int
+f22 (int f1line)
+{
+  return f23 (f1line, __LINE__) + 2;
+}
+
+static int
+f23 (int f1line, int f2line)
+{
+  uintptr_t addrs[20];
+  struct sdata data;
+  int f3line;
+  int i;
+
+  data.addrs = &addrs[0];
+  data.index = 0;
+  data.max = 20;
+  data.failed = 0;
+
+  f3line = __LINE__ + 1;
+  i = backtrace_simple (state, 0, callback_two, error_callback_two, &data);
+
+  if (i != 0)
+    {
+      fprintf (stderr, "test3: unexpected return value %d\n", i);
+      data.failed = 1;
+    }
+
+  if (!data.failed)
+    {
+      struct info all[20];
+      struct bdata bdata;
+      int j;
+
+      bdata.all = &all[0];
+      bdata.index = 0;
+      bdata.max = 20;
+      bdata.failed = 0;
+
+      for (j = 0; j < 3; ++j)
+	{
+	  i = backtrace_pcinfo (state, addrs[j], callback_one,
+				error_callback_one, &bdata);
+	  if (i != 0)
+	    {
+	      fprintf (stderr,
+		       ("test3: unexpected return value "
+			"from backtrace_pcinfo %d\n"),
+		       i);
+	      bdata.failed = 1;
+	    }
+	  if (!bdata.failed && bdata.index != (size_t) (j + 1))
+	    {
+	      fprintf (stderr,
+		       ("wrong number of calls from backtrace_pcinfo "
+			"got %u expected %d\n"),
+		       (unsigned int) bdata.index, j + 1);
+	      bdata.failed = 1;
+	    }
+	}
+
+      check ("test3", 0, all, f3line, "f23", "btest.c", &bdata.failed);
+      check ("test3", 1, all, f2line, "f22", "btest.c", &bdata.failed);
+      check ("test3", 2, all, f1line, "test3", "btest.c", &bdata.failed);
+
+      if (bdata.failed)
+	data.failed = 1;
+
+      for (j = 0; j < 3; ++j)
+	{
+	  struct symdata symdata;
+
+	  symdata.name = NULL;
+	  symdata.val = 0;
+	  symdata.size = 0;
+	  symdata.failed = 0;
+
+	  i = backtrace_syminfo (state, addrs[j], callback_three,
+				 error_callback_three, &symdata);
+	  if (i == 0)
+	    {
+	      fprintf (stderr,
+		       ("test3: [%d]: unexpected return value "
+			"from backtrace_syminfo %d\n"),
+		       j, i);
+	      symdata.failed = 1;
+	    }
+
+	  if (!symdata.failed)
+	    {
+	      const char *expected;
+
+	      switch (j)
+		{
+		case 0:
+		  expected = "f23";
+		  break;
+		case 1:
+		  expected = "f22";
+		  break;
+		case 2:
+		  expected = "test3";
+		  break;
+		default:
+		  assert (0);
+		}
+
+	      if (symdata.name == NULL)
+		{
+		  fprintf (stderr, "test3: [%d]: NULL syminfo name\n", j);
+		  symdata.failed = 1;
+		}
+	      /* Use strncmp, not strcmp, because GCC might create a
+		 clone.  */
+	      else if (strncmp (symdata.name, expected, strlen (expected))
+		       != 0)
+		{
+		  fprintf (stderr,
+			   ("test3: [%d]: unexpected syminfo name "
+			    "got %s expected %s\n"),
+			   j, symdata.name, expected);
+		  symdata.failed = 1;
+		}
+	    }
+
+	  if (symdata.failed)
+	    data.failed = 1;
+	}
+    }
+
+  printf ("%s: backtrace_simple noinline\n", data.failed ? "FAIL" : "PASS");
+
+  if (data.failed)
+    ++failures;
+
+  return failures;
+}
+
+/* Test the backtrace_simple function with inlined functions.  */
+
+static inline int test4 (void) __attribute__ ((always_inline, unused));
+static inline int f32 (int) __attribute__ ((always_inline));
+static inline int f33 (int, int) __attribute__ ((always_inline));
+
+static inline int
+test4 (void)
+{
+  return f32 (__LINE__) + 1;
+}
+
+static inline int
+f32 (int f1line)
+{
+  return f33 (f1line, __LINE__) + 2;
+}
+
+static inline int
+f33 (int f1line, int f2line)
+{
+  uintptr_t addrs[20];
+  struct sdata data;
+  int f3line;
+  int i;
+
+  data.addrs = &addrs[0];
+  data.index = 0;
+  data.max = 20;
+  data.failed = 0;
+
+  f3line = __LINE__ + 1;
+  i = backtrace_simple (state, 0, callback_two, error_callback_two, &data);
+
+  if (i != 0)
+    {
+      fprintf (stderr, "test3: unexpected return value %d\n", i);
+      data.failed = 1;
+    }
+
+  if (!data.failed)
+    {
+      struct info all[20];
+      struct bdata bdata;
+
+      bdata.all = &all[0];
+      bdata.index = 0;
+      bdata.max = 20;
+      bdata.failed = 0;
+
+      i = backtrace_pcinfo (state, addrs[0], callback_one, error_callback_one,
+			    &bdata);
+      if (i != 0)
+	{
+	  fprintf (stderr,
+		   ("test4: unexpected return value "
+		    "from backtrace_pcinfo %d\n"),
+		   i);
+	  bdata.failed = 1;
+	}
+
+      check ("test4", 0, all, f3line, "f33", "btest.c", &bdata.failed);
+      check ("test4", 1, all, f2line, "f32", "btest.c", &bdata.failed);
+      check ("test4", 2, all, f1line, "test4", "btest.c", &bdata.failed);
+
+      if (bdata.failed)
+	data.failed = 1;
+    }
+
+  printf ("%s: backtrace_simple inline\n", data.failed ? "FAIL" : "PASS");
+
+  if (data.failed)
+    ++failures;
+
+  return failures;
+}
+
+static int test5 (void) __attribute__ ((unused));
+
+int global = 1;
+
+static int
+test5 (void)
+{
+  struct symdata symdata;
+  int i;
+  uintptr_t addr = (uintptr_t) &global;
+
+  if (sizeof (global) > 1)
+    addr += 1;
+
+  symdata.name = NULL;
+  symdata.val = 0;
+  symdata.size = 0;
+  symdata.failed = 0;
+
+  i = backtrace_syminfo (state, addr, callback_three,
+			 error_callback_three, &symdata);
+  if (i == 0)
+    {
+      fprintf (stderr,
+	       "test5: unexpected return value from backtrace_syminfo %d\n",
+	       i);
+      symdata.failed = 1;
+    }
+
+  if (!symdata.failed)
+    {
+      if (symdata.name == NULL)
+	{
+	  fprintf (stderr, "test5: NULL syminfo name\n");
+	  symdata.failed = 1;
+	}
+      else if (strcmp (symdata.name, "global") != 0)
+	{
+	  fprintf (stderr,
+		   "test5: unexpected syminfo name got %s expected %s\n",
+		   symdata.name, "global");
+	  symdata.failed = 1;
+	}
+      else if (symdata.val != (uintptr_t) &global)
+	{
+	  fprintf (stderr,
+		   "test5: unexpected syminfo value got %lx expected %lx\n",
+		   (unsigned long) symdata.val,
+		   (unsigned long) (uintptr_t) &global);
+	  symdata.failed = 1;
+	}
+      else if (symdata.size != sizeof (global))
+	{
+	  fprintf (stderr,
+		   "test5: unexpected syminfo size got %lx expected %lx\n",
+		   (unsigned long) symdata.size,
+		   (unsigned long) sizeof (global));
+	  symdata.failed = 1;
+	}
+    }
+
+  printf ("%s: backtrace_syminfo variable\n",
+	  symdata.failed ? "FAIL" : "PASS");
+
+  if (symdata.failed)
+    ++failures;
+
+  return failures;
+}
+
+/* Check that are no files left open.  */
+
+static void
+check_open_files (void)
+{
+  int i;
+
+  for (i = 3; i < 10; i++)
+    {
+      if (close (i) == 0)
+	{
+	  fprintf (stderr,
+		   "ERROR: descriptor %d still open after tests complete\n",
+		   i);
+	  ++failures;
+	}
+    }
+}
+
+/* Run all the tests.  */
+
+int
+main (int argc ATTRIBUTE_UNUSED, char **argv)
+{
+  state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,
+				  error_callback_create, NULL);
+
+#if BACKTRACE_SUPPORTED
+  test1 ();
+  test2 ();
+  test3 ();
+  test4 ();
+#if BACKTRACE_SUPPORTS_DATA
+  test5 ();
+#endif
+#endif
+
+  check_open_files ();
+
+  exit (failures ? EXIT_FAILURE : EXIT_SUCCESS);
+}
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/config.guess b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/config.guess
new file mode 100755
index 0000000..d622a44
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/config.guess
@@ -0,0 +1,1530 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+#   2011, 2012 Free Software Foundation, Inc.
+
+timestamp='2012-02-10'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner.  Please send patches (context
+# diff format) to <config-patches@gnu.org> and include a ChangeLog
+# entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int x;" > $dummy.c ;
+	for c in cc gcc c89 c99 ; do
+	  if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+	     CC_FOR_BUILD="$c"; break ;
+	  fi ;
+	done ;
+	if test x"$CC_FOR_BUILD" = x ; then
+	  CC_FOR_BUILD=no_compiler_found ;
+	fi
+	;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+	PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+	# NetBSD (nbsd) targets should (where applicable) match one or
+	# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
+	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+	# switched to ELF, *-*-netbsd* would select the old
+	# object file format.  This provides both forward
+	# compatibility and a consistent mechanism for selecting the
+	# object file format.
+	#
+	# Note: NetBSD doesn't particularly care about the vendor
+	# portion of the name.  We always set it to "unknown".
+	sysctl="sysctl -n hw.machine_arch"
+	UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+	    /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+	case "${UNAME_MACHINE_ARCH}" in
+	    armeb) machine=armeb-unknown ;;
+	    arm*) machine=arm-unknown ;;
+	    sh3el) machine=shl-unknown ;;
+	    sh3eb) machine=sh-unknown ;;
+	    sh5el) machine=sh5le-unknown ;;
+	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+	esac
+	# The Operating System including object format, if it has switched
+	# to ELF recently, or will in the future.
+	case "${UNAME_MACHINE_ARCH}" in
+	    arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+		eval $set_cc_for_build
+		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+			| grep -q __ELF__
+		then
+		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+		    # Return netbsd for either.  FIX?
+		    os=netbsd
+		else
+		    os=netbsdelf
+		fi
+		;;
+	    *)
+		os=netbsd
+		;;
+	esac
+	# The OS release
+	# Debian GNU/NetBSD machines have a different userland, and
+	# thus, need a distinct triplet. However, they do not need
+	# kernel version information, so it can be replaced with a
+	# suitable tag, in the style of linux-gnu.
+	case "${UNAME_VERSION}" in
+	    Debian*)
+		release='-gnu'
+		;;
+	    *)
+		release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+		;;
+	esac
+	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+	# contains redundant information, the shorter form:
+	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+	echo "${machine}-${os}${release}"
+	exit ;;
+    *:OpenBSD:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+	echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+	exit ;;
+    *:ekkoBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+	exit ;;
+    *:SolidBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+	exit ;;
+    macppc:MirBSD:*:*)
+	echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+	exit ;;
+    *:MirBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+	exit ;;
+    alpha:OSF1:*:*)
+	case $UNAME_RELEASE in
+	*4.0)
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+		;;
+	*5.*)
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+		;;
+	esac
+	# According to Compaq, /usr/sbin/psrinfo has been available on
+	# OSF/1 and Tru64 systems produced since 1995.  I hope that
+	# covers most systems running today.  This code pipes the CPU
+	# types through head -n 1, so we only detect the type of CPU 0.
+	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+	case "$ALPHA_CPU_TYPE" in
+	    "EV4 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV4.5 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "LCA4 (21066/21068)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV5 (21164)")
+		UNAME_MACHINE="alphaev5" ;;
+	    "EV5.6 (21164A)")
+		UNAME_MACHINE="alphaev56" ;;
+	    "EV5.6 (21164PC)")
+		UNAME_MACHINE="alphapca56" ;;
+	    "EV5.7 (21164PC)")
+		UNAME_MACHINE="alphapca57" ;;
+	    "EV6 (21264)")
+		UNAME_MACHINE="alphaev6" ;;
+	    "EV6.7 (21264A)")
+		UNAME_MACHINE="alphaev67" ;;
+	    "EV6.8CB (21264C)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8AL (21264B)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8CX (21264D)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.9A (21264/EV69A)")
+		UNAME_MACHINE="alphaev69" ;;
+	    "EV7 (21364)")
+		UNAME_MACHINE="alphaev7" ;;
+	    "EV7.9 (21364A)")
+		UNAME_MACHINE="alphaev79" ;;
+	esac
+	# A Pn.n version is a patched version.
+	# A Vn.n version is a released version.
+	# A Tn.n version is a released field test version.
+	# A Xn.n version is an unreleased experimental baselevel.
+	# 1.2 uses "1.2" for uname -r.
+	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+	exitcode=$?
+	trap '' 0
+	exit $exitcode ;;
+    Alpha\ *:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# Should we change UNAME_MACHINE based on the output of uname instead
+	# of the specific Alpha model?
+	echo alpha-pc-interix
+	exit ;;
+    21064:Windows_NT:50:3)
+	echo alpha-dec-winnt3.5
+	exit ;;
+    Amiga*:UNIX_System_V:4.0:*)
+	echo m68k-unknown-sysv4
+	exit ;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-amigaos
+	exit ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-morphos
+	exit ;;
+    *:OS/390:*:*)
+	echo i370-ibm-openedition
+	exit ;;
+    *:z/VM:*:*)
+	echo s390-ibm-zvmoe
+	exit ;;
+    *:OS400:*:*)
+	echo powerpc-ibm-os400
+	exit ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+	echo arm-acorn-riscix${UNAME_RELEASE}
+	exit ;;
+    arm:riscos:*:*|arm:RISCOS:*:*)
+	echo arm-unknown-riscos
+	exit ;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+	echo hppa1.1-hitachi-hiuxmpp
+	exit ;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+	if test "`(/bin/universe) 2>/dev/null`" = att ; then
+		echo pyramid-pyramid-sysv3
+	else
+		echo pyramid-pyramid-bsd
+	fi
+	exit ;;
+    NILE*:*:*:dcosx)
+	echo pyramid-pyramid-svr4
+	exit ;;
+    DRS?6000:unix:4.0:6*)
+	echo sparc-icl-nx6
+	exit ;;
+    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+	case `/usr/bin/uname -p` in
+	    sparc) echo sparc-icl-nx7; exit ;;
+	esac ;;
+    s390x:SunOS:*:*)
+	echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4H:SunOS:5.*:*)
+	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+	echo i386-pc-auroraux${UNAME_RELEASE}
+	exit ;;
+    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+	eval $set_cc_for_build
+	SUN_ARCH="i386"
+	# If there is a compiler, see if it is configured for 64-bit objects.
+	# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+	# This test works for both compilers.
+	if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+	    if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+		(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+		grep IS_64BIT_ARCH >/dev/null
+	    then
+		SUN_ARCH="x86_64"
+	    fi
+	fi
+	echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:6*:*)
+	# According to config.sub, this is the proper way to canonicalize
+	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+	# it's likely to be more like Solaris than SunOS4.
+	echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:*:*)
+	case "`/usr/bin/arch -k`" in
+	    Series*|S4*)
+		UNAME_RELEASE=`uname -v`
+		;;
+	esac
+	# Japanese Language versions have a version number like `4.1.3-JL'.
+	echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+	exit ;;
+    sun3*:SunOS:*:*)
+	echo m68k-sun-sunos${UNAME_RELEASE}
+	exit ;;
+    sun*:*:4.2BSD:*)
+	UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+	case "`/bin/arch`" in
+	    sun3)
+		echo m68k-sun-sunos${UNAME_RELEASE}
+		;;
+	    sun4)
+		echo sparc-sun-sunos${UNAME_RELEASE}
+		;;
+	esac
+	exit ;;
+    aushp:SunOS:*:*)
+	echo sparc-auspex-sunos${UNAME_RELEASE}
+	exit ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+	echo m68k-milan-mint${UNAME_RELEASE}
+	exit ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+	echo m68k-hades-mint${UNAME_RELEASE}
+	exit ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+	echo m68k-unknown-mint${UNAME_RELEASE}
+	exit ;;
+    m68k:machten:*:*)
+	echo m68k-apple-machten${UNAME_RELEASE}
+	exit ;;
+    powerpc:machten:*:*)
+	echo powerpc-apple-machten${UNAME_RELEASE}
+	exit ;;
+    RISC*:Mach:*:*)
+	echo mips-dec-mach_bsd4.3
+	exit ;;
+    RISC*:ULTRIX:*:*)
+	echo mips-dec-ultrix${UNAME_RELEASE}
+	exit ;;
+    VAX*:ULTRIX*:*:*)
+	echo vax-dec-ultrix${UNAME_RELEASE}
+	exit ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+	echo clipper-intergraph-clix${UNAME_RELEASE}
+	exit ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+	int main (int argc, char *argv[]) {
+#else
+	int main (argc, argv) int argc; char *argv[]; {
+#endif
+	#if defined (host_mips) && defined (MIPSEB)
+	#if defined (SYSTYPE_SYSV)
+	  printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_SVR4)
+	  printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+	  printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+	#endif
+	#endif
+	  exit (-1);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c &&
+	  dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+	  SYSTEM_NAME=`$dummy $dummyarg` &&
+	    { echo "$SYSTEM_NAME"; exit; }
+	echo mips-mips-riscos${UNAME_RELEASE}
+	exit ;;
+    Motorola:PowerMAX_OS:*:*)
+	echo powerpc-motorola-powermax
+	exit ;;
+    Motorola:*:4.3:PL8-*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:Power_UNIX:*:*)
+	echo powerpc-harris-powerunix
+	exit ;;
+    m88k:CX/UX:7*:*)
+	echo m88k-harris-cxux7
+	exit ;;
+    m88k:*:4*:R4*)
+	echo m88k-motorola-sysv4
+	exit ;;
+    m88k:*:3*:R3*)
+	echo m88k-motorola-sysv3
+	exit ;;
+    AViiON:dgux:*:*)
+	# DG/UX returns AViiON for all architectures
+	UNAME_PROCESSOR=`/usr/bin/uname -p`
+	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+	then
+	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+	       [ ${TARGET_BINARY_INTERFACE}x = x ]
+	    then
+		echo m88k-dg-dgux${UNAME_RELEASE}
+	    else
+		echo m88k-dg-dguxbcs${UNAME_RELEASE}
+	    fi
+	else
+	    echo i586-dg-dgux${UNAME_RELEASE}
+	fi
+	exit ;;
+    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
+	echo m88k-dolphin-sysv3
+	exit ;;
+    M88*:*:R3*:*)
+	# Delta 88k system running SVR3
+	echo m88k-motorola-sysv3
+	exit ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+	echo m88k-tektronix-sysv3
+	exit ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+	echo m68k-tektronix-bsd
+	exit ;;
+    *:IRIX*:*:*)
+	echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+	exit ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+	echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
+	exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+	echo i386-ibm-aix
+	exit ;;
+    ia64:AIX:*:*)
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+	exit ;;
+    *:AIX:2:3)
+	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+		eval $set_cc_for_build
+		sed 's/^		//' << EOF >$dummy.c
+		#include <sys/systemcfg.h>
+
+		main()
+			{
+			if (!__power_pc())
+				exit(1);
+			puts("powerpc-ibm-aix3.2.5");
+			exit(0);
+			}
+EOF
+		if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+		then
+			echo "$SYSTEM_NAME"
+		else
+			echo rs6000-ibm-aix3.2.5
+		fi
+	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+		echo rs6000-ibm-aix3.2.4
+	else
+		echo rs6000-ibm-aix3.2
+	fi
+	exit ;;
+    *:AIX:*:[4567])
+	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+		IBM_ARCH=rs6000
+	else
+		IBM_ARCH=powerpc
+	fi
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+	exit ;;
+    *:AIX:*:*)
+	echo rs6000-ibm-aix
+	exit ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+	echo romp-ibm-bsd4.4
+	exit ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+	echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+	exit ;;                             # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+	echo rs6000-bull-bosx
+	exit ;;
+    DPX/2?00:B.O.S.:*:*)
+	echo m68k-bull-sysv3
+	exit ;;
+    9000/[34]??:4.3bsd:1.*:*)
+	echo m68k-hp-bsd
+	exit ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+	echo m68k-hp-bsd4.4
+	exit ;;
+    9000/[34678]??:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	case "${UNAME_MACHINE}" in
+	    9000/31? )            HP_ARCH=m68000 ;;
+	    9000/[34]?? )         HP_ARCH=m68k ;;
+	    9000/[678][0-9][0-9])
+		if [ -x /usr/bin/getconf ]; then
+		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+		    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+		    case "${sc_cpu_version}" in
+		      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+		      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+		      532)                      # CPU_PA_RISC2_0
+			case "${sc_kernel_bits}" in
+			  32) HP_ARCH="hppa2.0n" ;;
+			  64) HP_ARCH="hppa2.0w" ;;
+			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+			esac ;;
+		    esac
+		fi
+		if [ "${HP_ARCH}" = "" ]; then
+		    eval $set_cc_for_build
+		    sed 's/^		//' << EOF >$dummy.c
+
+		#define _HPUX_SOURCE
+		#include <stdlib.h>
+		#include <unistd.h>
+
+		int main ()
+		{
+		#if defined(_SC_KERNEL_BITS)
+		    long bits = sysconf(_SC_KERNEL_BITS);
+		#endif
+		    long cpu  = sysconf (_SC_CPU_VERSION);
+
+		    switch (cpu)
+			{
+			case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+			case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+			case CPU_PA_RISC2_0:
+		#if defined(_SC_KERNEL_BITS)
+			    switch (bits)
+				{
+				case 64: puts ("hppa2.0w"); break;
+				case 32: puts ("hppa2.0n"); break;
+				default: puts ("hppa2.0"); break;
+				} break;
+		#else  /* !defined(_SC_KERNEL_BITS) */
+			    puts ("hppa2.0"); break;
+		#endif
+			default: puts ("hppa1.0"); break;
+			}
+		    exit (0);
+		}
+EOF
+		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+		    test -z "$HP_ARCH" && HP_ARCH=hppa
+		fi ;;
+	esac
+	if [ ${HP_ARCH} = "hppa2.0w" ]
+	then
+	    eval $set_cc_for_build
+
+	    # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+	    # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
+	    # generating 64-bit code.  GNU and HP use different nomenclature:
+	    #
+	    # $ CC_FOR_BUILD=cc ./config.guess
+	    # => hppa2.0w-hp-hpux11.23
+	    # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+	    # => hppa64-hp-hpux11.23
+
+	    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+		grep -q __LP64__
+	    then
+		HP_ARCH="hppa2.0w"
+	    else
+		HP_ARCH="hppa64"
+	    fi
+	fi
+	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+	exit ;;
+    ia64:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	echo ia64-hp-hpux${HPUX_REV}
+	exit ;;
+    3050*:HI-UX:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <unistd.h>
+	int
+	main ()
+	{
+	  long cpu = sysconf (_SC_CPU_VERSION);
+	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+	     results, however.  */
+	  if (CPU_IS_PA_RISC (cpu))
+	    {
+	      switch (cpu)
+		{
+		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+		  default: puts ("hppa-hitachi-hiuxwe2"); break;
+		}
+	    }
+	  else if (CPU_IS_HP_MC68K (cpu))
+	    puts ("m68k-hitachi-hiuxwe2");
+	  else puts ("unknown-hitachi-hiuxwe2");
+	  exit (0);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+		{ echo "$SYSTEM_NAME"; exit; }
+	echo unknown-hitachi-hiuxwe2
+	exit ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+	echo hppa1.1-hp-bsd
+	exit ;;
+    9000/8??:4.3bsd:*:*)
+	echo hppa1.0-hp-bsd
+	exit ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+	echo hppa1.0-hp-mpeix
+	exit ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+	echo hppa1.1-hp-osf
+	exit ;;
+    hp8??:OSF1:*:*)
+	echo hppa1.0-hp-osf
+	exit ;;
+    i*86:OSF1:*:*)
+	if [ -x /usr/sbin/sysversion ] ; then
+	    echo ${UNAME_MACHINE}-unknown-osf1mk
+	else
+	    echo ${UNAME_MACHINE}-unknown-osf1
+	fi
+	exit ;;
+    parisc*:Lites*:*:*)
+	echo hppa1.1-hp-lites
+	exit ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+	echo c1-convex-bsd
+	exit ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+	exit ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+	echo c34-convex-bsd
+	exit ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+	echo c38-convex-bsd
+	exit ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+	echo c4-convex-bsd
+	exit ;;
+    CRAY*Y-MP:*:*:*)
+	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*[A-Z]90:*:*:*)
+	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+	      -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*TS:*:*:*)
+	echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*T3E:*:*:*)
+	echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*SV1:*:*:*)
+	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    *:UNICOS/mp:*:*)
+	echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+	FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+	echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	exit ;;
+    5000:UNIX_System_V:4.*:*)
+	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+	FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+	echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	exit ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+	exit ;;
+    sparc*:BSD/OS:*:*)
+	echo sparc-unknown-bsdi${UNAME_RELEASE}
+	exit ;;
+    *:BSD/OS:*:*)
+	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+	exit ;;
+    *:FreeBSD:*:*)
+	UNAME_PROCESSOR=`/usr/bin/uname -p`
+	case ${UNAME_PROCESSOR} in
+	    amd64)
+		echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	    *)
+		echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	esac
+	exit ;;
+    i*:CYGWIN*:*)
+	echo ${UNAME_MACHINE}-pc-cygwin
+	exit ;;
+    *:MINGW*:*)
+	echo ${UNAME_MACHINE}-pc-mingw32
+	exit ;;
+    i*:MSYS*:*)
+	echo ${UNAME_MACHINE}-pc-msys
+	exit ;;
+    i*:windows32*:*)
+	# uname -m includes "-pc" on this system.
+	echo ${UNAME_MACHINE}-mingw32
+	exit ;;
+    i*:PW*:*)
+	echo ${UNAME_MACHINE}-pc-pw32
+	exit ;;
+    *:Interix*:*)
+	case ${UNAME_MACHINE} in
+	    x86)
+		echo i586-pc-interix${UNAME_RELEASE}
+		exit ;;
+	    authenticamd | genuineintel | EM64T)
+		echo x86_64-unknown-interix${UNAME_RELEASE}
+		exit ;;
+	    IA64)
+		echo ia64-unknown-interix${UNAME_RELEASE}
+		exit ;;
+	esac ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+	echo i${UNAME_MACHINE}-pc-mks
+	exit ;;
+    8664:Windows_NT:*)
+	echo x86_64-pc-mks
+	exit ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+	# UNAME_MACHINE based on the output of uname instead of i386?
+	echo i586-pc-interix
+	exit ;;
+    i*:UWIN*:*)
+	echo ${UNAME_MACHINE}-pc-uwin
+	exit ;;
+    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+	echo x86_64-unknown-cygwin
+	exit ;;
+    p*:CYGWIN*:*)
+	echo powerpcle-unknown-cygwin
+	exit ;;
+    prep*:SunOS:5.*:*)
+	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    *:GNU:*:*)
+	# the GNU system
+	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+	exit ;;
+    *:GNU/*:*:*)
+	# other systems with GNU libc and userland
+	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+	exit ;;
+    i*86:Minix:*:*)
+	echo ${UNAME_MACHINE}-pc-minix
+	exit ;;
+    aarch64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    aarch64_be:Linux:*:*)
+	UNAME_MACHINE=aarch64_be
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    alpha:Linux:*:*)
+	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+	  EV5)   UNAME_MACHINE=alphaev5 ;;
+	  EV56)  UNAME_MACHINE=alphaev56 ;;
+	  PCA56) UNAME_MACHINE=alphapca56 ;;
+	  PCA57) UNAME_MACHINE=alphapca56 ;;
+	  EV6)   UNAME_MACHINE=alphaev6 ;;
+	  EV67)  UNAME_MACHINE=alphaev67 ;;
+	  EV68*) UNAME_MACHINE=alphaev68 ;;
+	esac
+	objdump --private-headers /bin/sh | grep -q ld.so.1
+	if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+	echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+	exit ;;
+    arm*:Linux:*:*)
+	eval $set_cc_for_build
+	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+	    | grep -q __ARM_EABI__
+	then
+	    echo ${UNAME_MACHINE}-unknown-linux-gnu
+	else
+	    if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+		| grep -q __ARM_PCS_VFP
+	    then
+		echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+	    else
+		echo ${UNAME_MACHINE}-unknown-linux-gnueabihf
+	    fi
+	fi
+	exit ;;
+    avr32*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    cris:Linux:*:*)
+	echo ${UNAME_MACHINE}-axis-linux-gnu
+	exit ;;
+    crisv32:Linux:*:*)
+	echo ${UNAME_MACHINE}-axis-linux-gnu
+	exit ;;
+    frv:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    hexagon:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    i*86:Linux:*:*)
+	LIBC=gnu
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#ifdef __dietlibc__
+	LIBC=dietlibc
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
+	echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+	exit ;;
+    ia64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    m32r*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    m68*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    mips:Linux:*:* | mips64:Linux:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#undef CPU
+	#undef ${UNAME_MACHINE}
+	#undef ${UNAME_MACHINE}el
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=${UNAME_MACHINE}el
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=${UNAME_MACHINE}
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
+	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+	;;
+    or32:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    padre:Linux:*:*)
+	echo sparc-unknown-linux-gnu
+	exit ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+	echo hppa64-unknown-linux-gnu
+	exit ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+	# Look for CPU level
+	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+	  PA7*) echo hppa1.1-unknown-linux-gnu ;;
+	  PA8*) echo hppa2.0-unknown-linux-gnu ;;
+	  *)    echo hppa-unknown-linux-gnu ;;
+	esac
+	exit ;;
+    ppc64:Linux:*:*)
+	echo powerpc64-unknown-linux-gnu
+	exit ;;
+    ppc:Linux:*:*)
+	echo powerpc-unknown-linux-gnu
+	exit ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+	echo ${UNAME_MACHINE}-ibm-linux
+	exit ;;
+    sh64*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    sh*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    tile*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    vax:Linux:*:*)
+	echo ${UNAME_MACHINE}-dec-linux-gnu
+	exit ;;
+    x86_64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    xtensa*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    i*86:DYNIX/ptx:4*:*)
+	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+	# earlier versions are messed up and put the nodename in both
+	# sysname and nodename.
+	echo i386-sequent-sysv4
+	exit ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+	# Unixware is an offshoot of SVR4, but it has its own version
+	# number series starting with 2...
+	# I am not positive that other SVR4 systems won't match this,
+	# I just have to hope.  -- rms.
+	# Use sysv4.2uw... so that sysv4* matches it.
+	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+	exit ;;
+    i*86:OS/2:*:*)
+	# If we were able to find `uname', then EMX Unix compatibility
+	# is probably installed.
+	echo ${UNAME_MACHINE}-pc-os2-emx
+	exit ;;
+    i*86:XTS-300:*:STOP)
+	echo ${UNAME_MACHINE}-unknown-stop
+	exit ;;
+    i*86:atheos:*:*)
+	echo ${UNAME_MACHINE}-unknown-atheos
+	exit ;;
+    i*86:syllable:*:*)
+	echo ${UNAME_MACHINE}-pc-syllable
+	exit ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
+	echo i386-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    i*86:*DOS:*:*)
+	echo ${UNAME_MACHINE}-pc-msdosdjgpp
+	exit ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+	UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+		echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+	else
+		echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+	fi
+	exit ;;
+    i*86:*:5:[678]*)
+	# UnixWare 7.x, OpenUNIX and OpenServer 6.
+	case `/bin/uname -X | grep "^Machine"` in
+	    *486*)	     UNAME_MACHINE=i486 ;;
+	    *Pentium)	     UNAME_MACHINE=i586 ;;
+	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+	esac
+	echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+	exit ;;
+    i*86:*:3.2:*)
+	if test -f /usr/options/cb.name; then
+		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+		echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+	elif /bin/uname -X 2>/dev/null >/dev/null ; then
+		UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+		(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+		(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+			&& UNAME_MACHINE=i586
+		(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+	else
+		echo ${UNAME_MACHINE}-pc-sysv32
+	fi
+	exit ;;
+    pc:*:*:*)
+	# Left here for compatibility:
+	# uname -m prints for DJGPP always 'pc', but it prints nothing about
+	# the processor, so we play safe by assuming i586.
+	# Note: whatever this is, it MUST be the same as what config.sub
+	# prints for the "djgpp" host, or else GDB configury will decide that
+	# this is a cross-build.
+	echo i586-pc-msdosdjgpp
+	exit ;;
+    Intel:Mach:3*:*)
+	echo i386-pc-mach3
+	exit ;;
+    paragon:*:*:*)
+	echo i860-intel-osf1
+	exit ;;
+    i860:*:4.*:*) # i860-SVR4
+	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+	  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+	else # Add other i860-SVR4 vendors below as they are discovered.
+	  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+	fi
+	exit ;;
+    mini*:CTIX:SYS*5:*)
+	# "miniframe"
+	echo m68010-convergent-sysv
+	exit ;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+	echo m68k-convergent-sysv
+	exit ;;
+    M680?0:D-NIX:5.3:*)
+	echo m68k-diab-dnix
+	exit ;;
+    M68*:*:R3V[5678]*:*)
+	test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+	OS_REL=''
+	test -r /etc/.relid \
+	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	  && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4; exit; } ;;
+    NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+	OS_REL='.3'
+	test -r /etc/.relid \
+	    && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	    && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	    && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+	    && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+	echo m68k-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    mc68030:UNIX_System_V:4.*:*)
+	echo m68k-atari-sysv4
+	exit ;;
+    TSUNAMI:LynxOS:2.*:*)
+	echo sparc-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    rs6000:LynxOS:2.*:*)
+	echo rs6000-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
+	echo powerpc-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    SM[BE]S:UNIX_SV:*:*)
+	echo mips-dde-sysv${UNAME_RELEASE}
+	exit ;;
+    RM*:ReliantUNIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    RM*:SINIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    *:SINIX-*:*:*)
+	if uname -p 2>/dev/null >/dev/null ; then
+		UNAME_MACHINE=`(uname -p) 2>/dev/null`
+		echo ${UNAME_MACHINE}-sni-sysv4
+	else
+		echo ns32k-sni-sysv
+	fi
+	exit ;;
+    PENTIUM:*:4.0*:*)	# Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+			# says <Richard.M.Bartel@ccMail.Census.GOV>
+	echo i586-unisys-sysv4
+	exit ;;
+    *:UNIX_System_V:4*:FTX*)
+	# From Gerald Hewes <hewes@openmarket.com>.
+	# How about differentiating between stratus architectures? -djm
+	echo hppa1.1-stratus-sysv4
+	exit ;;
+    *:*:*:FTX*)
+	# From seanf@swdc.stratus.com.
+	echo i860-stratus-sysv4
+	exit ;;
+    i*86:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	echo ${UNAME_MACHINE}-stratus-vos
+	exit ;;
+    *:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	echo hppa1.1-stratus-vos
+	exit ;;
+    mc68*:A/UX:*:*)
+	echo m68k-apple-aux${UNAME_RELEASE}
+	exit ;;
+    news*:NEWS-OS:6*:*)
+	echo mips-sony-newsos6
+	exit ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+	if [ -d /usr/nec ]; then
+		echo mips-nec-sysv${UNAME_RELEASE}
+	else
+		echo mips-unknown-sysv${UNAME_RELEASE}
+	fi
+	exit ;;
+    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
+	echo powerpc-be-beos
+	exit ;;
+    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
+	echo powerpc-apple-beos
+	exit ;;
+    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
+	echo i586-pc-beos
+	exit ;;
+    BePC:Haiku:*:*)	# Haiku running on Intel PC compatible.
+	echo i586-pc-haiku
+	exit ;;
+    SX-4:SUPER-UX:*:*)
+	echo sx4-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-5:SUPER-UX:*:*)
+	echo sx5-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-6:SUPER-UX:*:*)
+	echo sx6-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-7:SUPER-UX:*:*)
+	echo sx7-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-8:SUPER-UX:*:*)
+	echo sx8-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-8R:SUPER-UX:*:*)
+	echo sx8r-nec-superux${UNAME_RELEASE}
+	exit ;;
+    Power*:Rhapsody:*:*)
+	echo powerpc-apple-rhapsody${UNAME_RELEASE}
+	exit ;;
+    *:Rhapsody:*:*)
+	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+	exit ;;
+    *:Darwin:*:*)
+	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+	case $UNAME_PROCESSOR in
+	    i386)
+		eval $set_cc_for_build
+		if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+		  if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+		      (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+		      grep IS_64BIT_ARCH >/dev/null
+		  then
+		      UNAME_PROCESSOR="x86_64"
+		  fi
+		fi ;;
+	    unknown) UNAME_PROCESSOR=powerpc ;;
+	esac
+	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+	exit ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+	UNAME_PROCESSOR=`uname -p`
+	if test "$UNAME_PROCESSOR" = "x86"; then
+		UNAME_PROCESSOR=i386
+		UNAME_MACHINE=pc
+	fi
+	echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+	exit ;;
+    *:QNX:*:4*)
+	echo i386-pc-qnx
+	exit ;;
+    NEO-?:NONSTOP_KERNEL:*:*)
+	echo neo-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    NSE-?:NONSTOP_KERNEL:*:*)
+	echo nse-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    NSR-?:NONSTOP_KERNEL:*:*)
+	echo nsr-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    *:NonStop-UX:*:*)
+	echo mips-compaq-nonstopux
+	exit ;;
+    BS2000:POSIX*:*:*)
+	echo bs2000-siemens-sysv
+	exit ;;
+    DS/*:UNIX_System_V:*:*)
+	echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+	exit ;;
+    *:Plan9:*:*)
+	# "uname -m" is not consistent, so use $cputype instead. 386
+	# is converted to i386 for consistency with other x86
+	# operating systems.
+	if test "$cputype" = "386"; then
+	    UNAME_MACHINE=i386
+	else
+	    UNAME_MACHINE="$cputype"
+	fi
+	echo ${UNAME_MACHINE}-unknown-plan9
+	exit ;;
+    *:TOPS-10:*:*)
+	echo pdp10-unknown-tops10
+	exit ;;
+    *:TENEX:*:*)
+	echo pdp10-unknown-tenex
+	exit ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+	echo pdp10-dec-tops20
+	exit ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+	echo pdp10-xkl-tops20
+	exit ;;
+    *:TOPS-20:*:*)
+	echo pdp10-unknown-tops20
+	exit ;;
+    *:ITS:*:*)
+	echo pdp10-unknown-its
+	exit ;;
+    SEI:*:*:SEIUX)
+	echo mips-sei-seiux${UNAME_RELEASE}
+	exit ;;
+    *:DragonFly:*:*)
+	echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+	exit ;;
+    *:*VMS:*:*)
+	UNAME_MACHINE=`(uname -p) 2>/dev/null`
+	case "${UNAME_MACHINE}" in
+	    A*) echo alpha-dec-vms ; exit ;;
+	    I*) echo ia64-dec-vms ; exit ;;
+	    V*) echo vax-dec-vms ; exit ;;
+	esac ;;
+    *:XENIX:*:SysV)
+	echo i386-pc-xenix
+	exit ;;
+    i*86:skyos:*:*)
+	echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+	exit ;;
+    i*86:rdos:*:*)
+	echo ${UNAME_MACHINE}-pc-rdos
+	exit ;;
+    i*86:AROS:*:*)
+	echo ${UNAME_MACHINE}-pc-aros
+	exit ;;
+    x86_64:VMkernel:*:*)
+	echo ${UNAME_MACHINE}-unknown-esx
+	exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+	"4"
+#else
+	""
+#endif
+	); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+	printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+	printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+	{ echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+	echo c1-convex-bsd
+	exit ;;
+    c2*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+	exit ;;
+    c34*)
+	echo c34-convex-bsd
+	exit ;;
+    c38*)
+	echo c38-convex-bsd
+	exit ;;
+    c4*)
+	echo c4-convex-bsd
+	exit ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+and
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/config.h.in b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/config.h.in
new file mode 100644
index 0000000..76baa09
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/config.h.in
@@ -0,0 +1,149 @@
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* ELF size: 32 or 64 */
+#undef BACKTRACE_ELF_SIZE
+
+/* XCOFF size: 32 or 64 */
+#undef BACKTRACE_XCOFF_SIZE
+
+/* Define to 1 if you have the __atomic functions */
+#undef HAVE_ATOMIC_FUNCTIONS
+
+/* Define to 1 if you have the `clock_gettime' function. */
+#undef HAVE_CLOCK_GETTIME
+
+/* Define to 1 if you have the declaration of `strnlen', and to 0 if you
+   don't. */
+#undef HAVE_DECL_STRNLEN
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define if dl_iterate_phdr is available. */
+#undef HAVE_DL_ITERATE_PHDR
+
+/* Define to 1 if you have the fcntl function */
+#undef HAVE_FCNTL
+
+/* Define if getexecname is available. */
+#undef HAVE_GETEXECNAME
+
+/* Define if _Unwind_GetIPInfo is available. */
+#undef HAVE_GETIPINFO
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the `z' library (-lz). */
+#undef HAVE_LIBZ
+
+/* Define to 1 if you have the <link.h> header file. */
+#undef HAVE_LINK_H
+
+/* Define if AIX loadquery is available. */
+#undef HAVE_LOADQUERY
+
+/* Define to 1 if you have the `lstat' function. */
+#undef HAVE_LSTAT
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `readlink' function. */
+#undef HAVE_READLINK
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the __sync functions */
+#undef HAVE_SYNC_FUNCTIONS
+
+/* Define to 1 if you have the <sys/ldr.h> header file. */
+#undef HAVE_SYS_LDR_H
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#undef HAVE_SYS_MMAN_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define if -lz is available. */
+#undef HAVE_ZLIB
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+   */
+#undef LT_OBJDIR
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Enable extensions on AIX 3, Interix.  */
+#ifndef _ALL_SOURCE
+# undef _ALL_SOURCE
+#endif
+/* Enable GNU extensions on systems that have them.  */
+#ifndef _GNU_SOURCE
+# undef _GNU_SOURCE
+#endif
+/* Enable threading extensions on Solaris.  */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# undef _POSIX_PTHREAD_SEMANTICS
+#endif
+/* Enable extensions on HP NonStop.  */
+#ifndef _TANDEM_SOURCE
+# undef _TANDEM_SOURCE
+#endif
+/* Enable general extensions on Solaris.  */
+#ifndef __EXTENSIONS__
+# undef __EXTENSIONS__
+#endif
+
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
+/* Define to 1 if on MINIX. */
+#undef _MINIX
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+   this defined. */
+#undef _POSIX_1_SOURCE
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+#undef _POSIX_SOURCE
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/config.sub b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/config.sub
new file mode 100755
index 0000000..63634d9
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/config.sub
@@ -0,0 +1,1794 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+#   2011, 2012 Free Software Foundation, Inc.
+
+timestamp='2012-02-10'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine.  It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted GNU ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#	CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit ;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
+  linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+  knetbsd*-gnu* | netbsd*-gnu* | \
+  kopensolaris*-gnu* | \
+  storm-chaos* | os2-emx* | rtmk-nova*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  android-linux)
+    os=-linux-android
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+	-sun*os*)
+		# Prevent following clause from handling this invalid input.
+		;;
+	-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+	-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+	-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+	-apple | -axis | -knuth | -cray | -microblaze)
+		os=
+		basic_machine=$1
+		;;
+	-bluegene*)
+		os=-cnk
+		;;
+	-sim | -cisco | -oki | -wec | -winbond)
+		os=
+		basic_machine=$1
+		;;
+	-scout)
+		;;
+	-wrs)
+		os=-vxworks
+		basic_machine=$1
+		;;
+	-chorusos*)
+		os=-chorusos
+		basic_machine=$1
+		;;
+	-chorusrdb)
+		os=-chorusrdb
+		basic_machine=$1
+		;;
+	-hiux*)
+		os=-hiuxwe2
+		;;
+	-sco6)
+		os=-sco5v6
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco5)
+		os=-sco3.2v5
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco4)
+		os=-sco3.2v4
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2.[4-9]*)
+		os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2v[4-9]*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco5v6*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco*)
+		os=-sco3.2v2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-udk*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-isc)
+		os=-isc2.2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-clix*)
+		basic_machine=clipper-intergraph
+		;;
+	-isc*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-lynx*)
+		os=-lynxos
+		;;
+	-ptx*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+		;;
+	-windowsnt*)
+		os=`echo $os | sed -e 's/windowsnt/winnt/'`
+		;;
+	-psos*)
+		os=-psos
+		;;
+	-mint | -mint[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+	# Recognize the basic CPU types without company name.
+	# Some are omitted here because they have special meanings below.
+	1750a | 580 \
+	| a29k \
+	| aarch64 | aarch64_be \
+	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+	| am33_2.0 \
+	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+        | be32 | be64 \
+	| bfin \
+	| c4x | clipper \
+	| d10v | d30v | dlx | dsp16xx \
+	| epiphany \
+	| fido | fr30 | frv \
+	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+	| hexagon \
+	| i370 | i860 | i960 | ia16 | ia64 \
+	| ip2k | iq2000 \
+	| le32 | le64 \
+	| lm32 \
+	| m32c | m32r | m32rle | m68000 | m68k | m88k \
+	| maxq | mb | microblaze | mcore | mep | metag \
+	| mips | mipsbe | mipseb | mipsel | mipsle \
+	| mips16 \
+	| mips64 | mips64el \
+	| mips64octeon | mips64octeonel \
+	| mips64orion | mips64orionel \
+	| mips64r5900 | mips64r5900el \
+	| mips64vr | mips64vrel \
+	| mips64vr4100 | mips64vr4100el \
+	| mips64vr4300 | mips64vr4300el \
+	| mips64vr5000 | mips64vr5000el \
+	| mips64vr5900 | mips64vr5900el \
+	| mipsisa32 | mipsisa32el \
+	| mipsisa32r2 | mipsisa32r2el \
+	| mipsisa64 | mipsisa64el \
+	| mipsisa64r2 | mipsisa64r2el \
+	| mipsisa64sb1 | mipsisa64sb1el \
+	| mipsisa64sr71k | mipsisa64sr71kel \
+	| mipstx39 | mipstx39el \
+	| mn10200 | mn10300 \
+	| moxie \
+	| mt \
+	| msp430 \
+	| nds32 | nds32le | nds32be \
+	| nios | nios2 \
+	| ns16k | ns32k \
+	| open8 \
+	| or32 \
+	| pdp10 | pdp11 | pj | pjl \
+	| powerpc | powerpc64 | powerpc64le | powerpcle \
+	| pru \
+	| pyramid \
+	| rl78 | rx \
+	| score \
+	| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+	| sh64 | sh64le \
+	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+	| spu \
+	| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
+	| ubicom32 \
+	| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
+	| we32k \
+	| x86 | xc16x | xstormy16 | xtensa \
+	| z8k | z80)
+		basic_machine=$basic_machine-unknown
+		;;
+	c54x)
+		basic_machine=tic54x-unknown
+		;;
+	c55x)
+		basic_machine=tic55x-unknown
+		;;
+	c6x)
+		basic_machine=tic6x-unknown
+		;;
+	m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip)
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+		;;
+	ms1)
+		basic_machine=mt-unknown
+		;;
+
+	strongarm | thumb | xscale)
+		basic_machine=arm-unknown
+		;;
+	xgate)
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	xscaleeb)
+		basic_machine=armeb-unknown
+		;;
+
+	xscaleel)
+		basic_machine=armel-unknown
+		;;
+
+	# We use `pc' rather than `unknown'
+	# because (1) that's what they normally are, and
+	# (2) the word "unknown" tends to confuse beginning users.
+	i*86 | x86_64)
+	  basic_machine=$basic_machine-pc
+	  ;;
+	# Object if more than one company name word.
+	*-*-*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+	# Recognize the basic CPU types with company name.
+	580-* \
+	| a29k-* \
+	| aarch64-* | aarch64_be-* \
+	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
+	| avr-* | avr32-* \
+	| be32-* | be64-* \
+	| bfin-* | bs2000-* \
+	| c[123]* | c30-* | [cjt]90-* | c4x-* \
+	| clipper-* | craynv-* | cydra-* \
+	| d10v-* | d30v-* | dlx-* \
+	| elxsi-* \
+	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+	| h8300-* | h8500-* \
+	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+	| hexagon-* \
+	| i*86-* | i860-* | i960-* | ia16-* | ia64-* \
+	| ip2k-* | iq2000-* \
+	| le32-* | le64-* \
+	| lm32-* \
+	| m32c-* | m32r-* | m32rle-* \
+	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+	| m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \
+	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+	| mips16-* \
+	| mips64-* | mips64el-* \
+	| mips64octeon-* | mips64octeonel-* \
+	| mips64orion-* | mips64orionel-* \
+	| mips64r5900-* | mips64r5900el-* \
+	| mips64vr-* | mips64vrel-* \
+	| mips64vr4100-* | mips64vr4100el-* \
+	| mips64vr4300-* | mips64vr4300el-* \
+	| mips64vr5000-* | mips64vr5000el-* \
+	| mips64vr5900-* | mips64vr5900el-* \
+	| mipsisa32-* | mipsisa32el-* \
+	| mipsisa32r2-* | mipsisa32r2el-* \
+	| mipsisa64-* | mipsisa64el-* \
+	| mipsisa64r2-* | mipsisa64r2el-* \
+	| mipsisa64sb1-* | mipsisa64sb1el-* \
+	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
+	| mipstx39-* | mipstx39el-* \
+	| mmix-* \
+	| mt-* \
+	| msp430-* \
+	| nds32-* | nds32le-* | nds32be-* \
+	| nios-* | nios2-* \
+	| none-* | np1-* | ns16k-* | ns32k-* \
+	| open8-* \
+	| orion-* \
+	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
+	| pru-* \
+	| pyramid-* \
+	| rl78-* | romp-* | rs6000-* | rx-* \
+	| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+	| sparclite-* \
+	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
+	| tahoe-* \
+	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+	| tile*-* \
+	| tron-* \
+	| ubicom32-* \
+	| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
+	| vax-* \
+	| we32k-* \
+	| x86-* | x86_64-* | xc16x-* | xps100-* \
+	| xstormy16-* | xtensa*-* \
+	| ymp-* \
+	| z8k-* | z80-*)
+		;;
+	# Recognize the basic CPU types without company name, with glob match.
+	xtensa*)
+		basic_machine=$basic_machine-unknown
+		;;
+	# Recognize the various machine names and aliases which stand
+	# for a CPU type and a company and sometimes even an OS.
+	386bsd)
+		basic_machine=i386-unknown
+		os=-bsd
+		;;
+	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+		basic_machine=m68000-att
+		;;
+	3b*)
+		basic_machine=we32k-att
+		;;
+	a29khif)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	abacus)
+		basic_machine=abacus-unknown
+		;;
+	adobe68k)
+		basic_machine=m68010-adobe
+		os=-scout
+		;;
+	alliant | fx80)
+		basic_machine=fx80-alliant
+		;;
+	altos | altos3068)
+		basic_machine=m68k-altos
+		;;
+	am29k)
+		basic_machine=a29k-none
+		os=-bsd
+		;;
+	amd64)
+		basic_machine=x86_64-pc
+		;;
+	amd64-*)
+		basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	amdahl)
+		basic_machine=580-amdahl
+		os=-sysv
+		;;
+	amiga | amiga-*)
+		basic_machine=m68k-unknown
+		;;
+	amigaos | amigados)
+		basic_machine=m68k-unknown
+		os=-amigaos
+		;;
+	amigaunix | amix)
+		basic_machine=m68k-unknown
+		os=-sysv4
+		;;
+	apollo68)
+		basic_machine=m68k-apollo
+		os=-sysv
+		;;
+	apollo68bsd)
+		basic_machine=m68k-apollo
+		os=-bsd
+		;;
+	aros)
+		basic_machine=i386-pc
+		os=-aros
+		;;
+	aux)
+		basic_machine=m68k-apple
+		os=-aux
+		;;
+	balance)
+		basic_machine=ns32k-sequent
+		os=-dynix
+		;;
+	blackfin)
+		basic_machine=bfin-unknown
+		os=-linux
+		;;
+	blackfin-*)
+		basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	bluegene*)
+		basic_machine=powerpc-ibm
+		os=-cnk
+		;;
+	c54x-*)
+		basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c55x-*)
+		basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c6x-*)
+		basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c90)
+		basic_machine=c90-cray
+		os=-unicos
+		;;
+	cegcc)
+		basic_machine=arm-unknown
+		os=-cegcc
+		;;
+	convex-c1)
+		basic_machine=c1-convex
+		os=-bsd
+		;;
+	convex-c2)
+		basic_machine=c2-convex
+		os=-bsd
+		;;
+	convex-c32)
+		basic_machine=c32-convex
+		os=-bsd
+		;;
+	convex-c34)
+		basic_machine=c34-convex
+		os=-bsd
+		;;
+	convex-c38)
+		basic_machine=c38-convex
+		os=-bsd
+		;;
+	cray | j90)
+		basic_machine=j90-cray
+		os=-unicos
+		;;
+	craynv)
+		basic_machine=craynv-cray
+		os=-unicosmp
+		;;
+	cr16 | cr16-*)
+		basic_machine=cr16-unknown
+		os=-elf
+		;;
+	crds | unos)
+		basic_machine=m68k-crds
+		;;
+	crisv32 | crisv32-* | etraxfs*)
+		basic_machine=crisv32-axis
+		;;
+	cris | cris-* | etrax*)
+		basic_machine=cris-axis
+		;;
+	crx)
+		basic_machine=crx-unknown
+		os=-elf
+		;;
+	da30 | da30-*)
+		basic_machine=m68k-da30
+		;;
+	decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+		basic_machine=mips-dec
+		;;
+	decsystem10* | dec10*)
+		basic_machine=pdp10-dec
+		os=-tops10
+		;;
+	decsystem20* | dec20*)
+		basic_machine=pdp10-dec
+		os=-tops20
+		;;
+	delta | 3300 | motorola-3300 | motorola-delta \
+	      | 3300-motorola | delta-motorola)
+		basic_machine=m68k-motorola
+		;;
+	delta88)
+		basic_machine=m88k-motorola
+		os=-sysv3
+		;;
+	dicos)
+		basic_machine=i686-pc
+		os=-dicos
+		;;
+	djgpp)
+		basic_machine=i586-pc
+		os=-msdosdjgpp
+		;;
+	dpx20 | dpx20-*)
+		basic_machine=rs6000-bull
+		os=-bosx
+		;;
+	dpx2* | dpx2*-bull)
+		basic_machine=m68k-bull
+		os=-sysv3
+		;;
+	e500v[12])
+		basic_machine=powerpc-unknown
+		os=$os"spe"
+		;;
+	e500v[12]-*)
+		basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=$os"spe"
+		;;
+	ebmon29k)
+		basic_machine=a29k-amd
+		os=-ebmon
+		;;
+	elxsi)
+		basic_machine=elxsi-elxsi
+		os=-bsd
+		;;
+	encore | umax | mmax)
+		basic_machine=ns32k-encore
+		;;
+	es1800 | OSE68k | ose68k | ose | OSE)
+		basic_machine=m68k-ericsson
+		os=-ose
+		;;
+	fx2800)
+		basic_machine=i860-alliant
+		;;
+	genix)
+		basic_machine=ns32k-ns
+		;;
+	gmicro)
+		basic_machine=tron-gmicro
+		os=-sysv
+		;;
+	go32)
+		basic_machine=i386-pc
+		os=-go32
+		;;
+	h3050r* | hiux*)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	h8300hms)
+		basic_machine=h8300-hitachi
+		os=-hms
+		;;
+	h8300xray)
+		basic_machine=h8300-hitachi
+		os=-xray
+		;;
+	h8500hms)
+		basic_machine=h8500-hitachi
+		os=-hms
+		;;
+	harris)
+		basic_machine=m88k-harris
+		os=-sysv3
+		;;
+	hp300-*)
+		basic_machine=m68k-hp
+		;;
+	hp300bsd)
+		basic_machine=m68k-hp
+		os=-bsd
+		;;
+	hp300hpux)
+		basic_machine=m68k-hp
+		os=-hpux
+		;;
+	hp3k9[0-9][0-9] | hp9[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k2[0-9][0-9] | hp9k31[0-9])
+		basic_machine=m68000-hp
+		;;
+	hp9k3[2-9][0-9])
+		basic_machine=m68k-hp
+		;;
+	hp9k6[0-9][0-9] | hp6[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k7[0-79][0-9] | hp7[0-79][0-9])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k78[0-9] | hp78[0-9])
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][13679] | hp8[0-9][13679])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][0-9] | hp8[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hppa-next)
+		os=-nextstep3
+		;;
+	hppaosf)
+		basic_machine=hppa1.1-hp
+		os=-osf
+		;;
+	hppro)
+		basic_machine=hppa1.1-hp
+		os=-proelf
+		;;
+	i370-ibm* | ibm*)
+		basic_machine=i370-ibm
+		;;
+	i*86v32)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv32
+		;;
+	i*86v4*)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv4
+		;;
+	i*86v)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv
+		;;
+	i*86sol2)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-solaris2
+		;;
+	i386mach)
+		basic_machine=i386-mach
+		os=-mach
+		;;
+	i386-vsta | vsta)
+		basic_machine=i386-unknown
+		os=-vsta
+		;;
+	iris | iris4d)
+		basic_machine=mips-sgi
+		case $os in
+		    -irix*)
+			;;
+		    *)
+			os=-irix4
+			;;
+		esac
+		;;
+	isi68 | isi)
+		basic_machine=m68k-isi
+		os=-sysv
+		;;
+	m68knommu)
+		basic_machine=m68k-unknown
+		os=-linux
+		;;
+	m68knommu-*)
+		basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	m88k-omron*)
+		basic_machine=m88k-omron
+		;;
+	magnum | m3230)
+		basic_machine=mips-mips
+		os=-sysv
+		;;
+	merlin)
+		basic_machine=ns32k-utek
+		os=-sysv
+		;;
+	microblaze)
+		basic_machine=microblaze-xilinx
+		;;
+	mingw32)
+		basic_machine=i386-pc
+		os=-mingw32
+		;;
+	mingw32ce)
+		basic_machine=arm-unknown
+		os=-mingw32ce
+		;;
+	miniframe)
+		basic_machine=m68000-convergent
+		;;
+	*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+	mips3*-*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+		;;
+	mips3*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+		;;
+	monitor)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	morphos)
+		basic_machine=powerpc-unknown
+		os=-morphos
+		;;
+	msdos)
+		basic_machine=i386-pc
+		os=-msdos
+		;;
+	ms1-*)
+		basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+		;;
+	msys)
+		basic_machine=i386-pc
+		os=-msys
+		;;
+	mvs)
+		basic_machine=i370-ibm
+		os=-mvs
+		;;
+	nacl)
+		basic_machine=le32-unknown
+		os=-nacl
+		;;
+	ncr3000)
+		basic_machine=i486-ncr
+		os=-sysv4
+		;;
+	netbsd386)
+		basic_machine=i386-unknown
+		os=-netbsd
+		;;
+	netwinder)
+		basic_machine=armv4l-rebel
+		os=-linux
+		;;
+	news | news700 | news800 | news900)
+		basic_machine=m68k-sony
+		os=-newsos
+		;;
+	news1000)
+		basic_machine=m68030-sony
+		os=-newsos
+		;;
+	news-3600 | risc-news)
+		basic_machine=mips-sony
+		os=-newsos
+		;;
+	necv70)
+		basic_machine=v70-nec
+		os=-sysv
+		;;
+	next | m*-next )
+		basic_machine=m68k-next
+		case $os in
+		    -nextstep* )
+			;;
+		    -ns2*)
+		      os=-nextstep2
+			;;
+		    *)
+		      os=-nextstep3
+			;;
+		esac
+		;;
+	nh3000)
+		basic_machine=m68k-harris
+		os=-cxux
+		;;
+	nh[45]000)
+		basic_machine=m88k-harris
+		os=-cxux
+		;;
+	nindy960)
+		basic_machine=i960-intel
+		os=-nindy
+		;;
+	mon960)
+		basic_machine=i960-intel
+		os=-mon960
+		;;
+	nonstopux)
+		basic_machine=mips-compaq
+		os=-nonstopux
+		;;
+	np1)
+		basic_machine=np1-gould
+		;;
+	neo-tandem)
+		basic_machine=neo-tandem
+		;;
+	nse-tandem)
+		basic_machine=nse-tandem
+		;;
+	nsr-tandem)
+		basic_machine=nsr-tandem
+		;;
+	nsx-tandem)
+		basic_machine=nsx-tandem
+		;;
+	op50n-* | op60c-*)
+		basic_machine=hppa1.1-oki
+		os=-proelf
+		;;
+	openrisc | openrisc-*)
+		basic_machine=or32-unknown
+		;;
+	os400)
+		basic_machine=powerpc-ibm
+		os=-os400
+		;;
+	OSE68000 | ose68000)
+		basic_machine=m68000-ericsson
+		os=-ose
+		;;
+	os68k)
+		basic_machine=m68k-none
+		os=-os68k
+		;;
+	pa-hitachi)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	paragon)
+		basic_machine=i860-intel
+		os=-osf
+		;;
+	parisc)
+		basic_machine=hppa-unknown
+		os=-linux
+		;;
+	parisc-*)
+		basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	pbd)
+		basic_machine=sparc-tti
+		;;
+	pbb)
+		basic_machine=m68k-tti
+		;;
+	pc532 | pc532-*)
+		basic_machine=ns32k-pc532
+		;;
+	pc98)
+		basic_machine=i386-pc
+		;;
+	pc98-*)
+		basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium | p5 | k5 | k6 | nexgen | viac3)
+		basic_machine=i586-pc
+		;;
+	pentiumpro | p6 | 6x86 | athlon | athlon_*)
+		basic_machine=i686-pc
+		;;
+	pentiumii | pentium2 | pentiumiii | pentium3)
+		basic_machine=i686-pc
+		;;
+	pentium4)
+		basic_machine=i786-pc
+		;;
+	pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+		basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumpro-* | p6-* | 6x86-* | athlon-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium4-*)
+		basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pn)
+		basic_machine=pn-gould
+		;;
+	power)	basic_machine=power-ibm
+		;;
+	ppc | ppcbe)	basic_machine=powerpc-unknown
+		;;
+	ppc-* | ppcbe-*)
+		basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppcle | powerpclittle)
+		basic_machine=powerpcle-unknown
+		;;
+	ppcle-* | powerpclittle-*)
+		basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64)	basic_machine=powerpc64-unknown
+		;;
+	ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64le | powerpc64little)
+		basic_machine=powerpc64le-unknown
+		;;
+	ppc64le-* | powerpc64little-*)
+		basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ps2)
+		basic_machine=i386-ibm
+		;;
+	pw32)
+		basic_machine=i586-unknown
+		os=-pw32
+		;;
+	rdos)
+		basic_machine=i386-pc
+		os=-rdos
+		;;
+	rom68k)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	rm[46]00)
+		basic_machine=mips-siemens
+		;;
+	rtpc | rtpc-*)
+		basic_machine=romp-ibm
+		;;
+	s390 | s390-*)
+		basic_machine=s390-ibm
+		;;
+	s390x | s390x-*)
+		basic_machine=s390x-ibm
+		;;
+	sa29200)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	sb1)
+		basic_machine=mipsisa64sb1-unknown
+		;;
+	sb1el)
+		basic_machine=mipsisa64sb1el-unknown
+		;;
+	sde)
+		basic_machine=mipsisa32-sde
+		os=-elf
+		;;
+	sei)
+		basic_machine=mips-sei
+		os=-seiux
+		;;
+	sequent)
+		basic_machine=i386-sequent
+		;;
+	sh)
+		basic_machine=sh-hitachi
+		os=-hms
+		;;
+	sh5el)
+		basic_machine=sh5le-unknown
+		;;
+	sh64)
+		basic_machine=sh64-unknown
+		;;
+	sparclite-wrs | simso-wrs)
+		basic_machine=sparclite-wrs
+		os=-vxworks
+		;;
+	sps7)
+		basic_machine=m68k-bull
+		os=-sysv2
+		;;
+	spur)
+		basic_machine=spur-unknown
+		;;
+	st2000)
+		basic_machine=m68k-tandem
+		;;
+	stratus)
+		basic_machine=i860-stratus
+		os=-sysv4
+		;;
+	strongarm-* | thumb-*)
+		basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	sun2)
+		basic_machine=m68000-sun
+		;;
+	sun2os3)
+		basic_machine=m68000-sun
+		os=-sunos3
+		;;
+	sun2os4)
+		basic_machine=m68000-sun
+		os=-sunos4
+		;;
+	sun3os3)
+		basic_machine=m68k-sun
+		os=-sunos3
+		;;
+	sun3os4)
+		basic_machine=m68k-sun
+		os=-sunos4
+		;;
+	sun4os3)
+		basic_machine=sparc-sun
+		os=-sunos3
+		;;
+	sun4os4)
+		basic_machine=sparc-sun
+		os=-sunos4
+		;;
+	sun4sol2)
+		basic_machine=sparc-sun
+		os=-solaris2
+		;;
+	sun3 | sun3-*)
+		basic_machine=m68k-sun
+		;;
+	sun4)
+		basic_machine=sparc-sun
+		;;
+	sun386 | sun386i | roadrunner)
+		basic_machine=i386-sun
+		;;
+	sv1)
+		basic_machine=sv1-cray
+		os=-unicos
+		;;
+	symmetry)
+		basic_machine=i386-sequent
+		os=-dynix
+		;;
+	t3e)
+		basic_machine=alphaev5-cray
+		os=-unicos
+		;;
+	t90)
+		basic_machine=t90-cray
+		os=-unicos
+		;;
+	tile*)
+		basic_machine=$basic_machine-unknown
+		os=-linux-gnu
+		;;
+	tx39)
+		basic_machine=mipstx39-unknown
+		;;
+	tx39el)
+		basic_machine=mipstx39el-unknown
+		;;
+	toad1)
+		basic_machine=pdp10-xkl
+		os=-tops20
+		;;
+	tower | tower-32)
+		basic_machine=m68k-ncr
+		;;
+	tpf)
+		basic_machine=s390x-ibm
+		os=-tpf
+		;;
+	udi29k)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	ultra3)
+		basic_machine=a29k-nyu
+		os=-sym1
+		;;
+	v810 | necv810)
+		basic_machine=v810-nec
+		os=-none
+		;;
+	vaxv)
+		basic_machine=vax-dec
+		os=-sysv
+		;;
+	vms)
+		basic_machine=vax-dec
+		os=-vms
+		;;
+	vpp*|vx|vx-*)
+		basic_machine=f301-fujitsu
+		;;
+	vxworks960)
+		basic_machine=i960-wrs
+		os=-vxworks
+		;;
+	vxworks68)
+		basic_machine=m68k-wrs
+		os=-vxworks
+		;;
+	vxworks29k)
+		basic_machine=a29k-wrs
+		os=-vxworks
+		;;
+	wasm32)
+		basic_machine=wasm32-unknown
+		;;
+	w65*)
+		basic_machine=w65-wdc
+		os=-none
+		;;
+	w89k-*)
+		basic_machine=hppa1.1-winbond
+		os=-proelf
+		;;
+	xbox)
+		basic_machine=i686-pc
+		os=-mingw32
+		;;
+	xps | xps100)
+		basic_machine=xps100-honeywell
+		;;
+	xscale-* | xscalee[bl]-*)
+		basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
+		;;
+	ymp)
+		basic_machine=ymp-cray
+		os=-unicos
+		;;
+	z8k-*-coff)
+		basic_machine=z8k-unknown
+		os=-sim
+		;;
+	z80-*-coff)
+		basic_machine=z80-unknown
+		os=-sim
+		;;
+	none)
+		basic_machine=none-none
+		os=-none
+		;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+	w89k)
+		basic_machine=hppa1.1-winbond
+		;;
+	op50n)
+		basic_machine=hppa1.1-oki
+		;;
+	op60c)
+		basic_machine=hppa1.1-oki
+		;;
+	romp)
+		basic_machine=romp-ibm
+		;;
+	mmix)
+		basic_machine=mmix-knuth
+		;;
+	rs6000)
+		basic_machine=rs6000-ibm
+		;;
+	vax)
+		basic_machine=vax-dec
+		;;
+	pdp10)
+		# there are many clones, so DEC is not a safe bet
+		basic_machine=pdp10-unknown
+		;;
+	pdp11)
+		basic_machine=pdp11-dec
+		;;
+	we32k)
+		basic_machine=we32k-att
+		;;
+	sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
+		basic_machine=sh-unknown
+		;;
+	sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+		basic_machine=sparc-sun
+		;;
+	cydra)
+		basic_machine=cydra-cydrome
+		;;
+	orion)
+		basic_machine=orion-highlevel
+		;;
+	orion105)
+		basic_machine=clipper-highlevel
+		;;
+	mac | mpw | mac-mpw)
+		basic_machine=m68k-apple
+		;;
+	pmac | pmac-mpw)
+		basic_machine=powerpc-apple
+		;;
+	*-unknown)
+		# Make sure to match an already-canonicalized machine name.
+		;;
+	*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+	*-digital*)
+		basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+		;;
+	*-commodore*)
+		basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+		;;
+	*)
+		;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+	# First match some system type aliases
+	# that might get confused with valid system types.
+	# -solaris* is a basic system type, with this one exception.
+	-auroraux)
+		os=-auroraux
+		;;
+	-solaris1 | -solaris1.*)
+		os=`echo $os | sed -e 's|solaris1|sunos4|'`
+		;;
+	-solaris)
+		os=-solaris2
+		;;
+	-svr4*)
+		os=-sysv4
+		;;
+	-unixware*)
+		os=-sysv4.2uw
+		;;
+	-gnu/linux*)
+		os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+		;;
+	# First accept the basic system types.
+	# The portable systems comes first.
+	# Each alternative MUST END IN A *, to match a version number.
+	# -sysv* is not here because it comes later, after sysvr4.
+	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
+	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
+	      | -sym* | -kopensolaris* \
+	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+	      | -aos* | -aros* \
+	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+	      | -openbsd* | -solidbsd* \
+	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+	      | -chorusos* | -chorusrdb* | -cegcc* \
+	      | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+	      | -mingw32* | -linux-gnu* | -linux-android* \
+	      | -linux-newlib* | -linux-uclibc* \
+	      | -uxpv* | -beos* | -mpeix* | -udk* \
+	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
+	# Remember, each alternative MUST END IN *, to match a version number.
+		;;
+	-qnx*)
+		case $basic_machine in
+		    x86-* | i*86-*)
+			;;
+		    *)
+			os=-nto$os
+			;;
+		esac
+		;;
+	-nto-qnx*)
+		;;
+	-nto*)
+		os=`echo $os | sed -e 's|nto|nto-qnx|'`
+		;;
+	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+	      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+		;;
+	-mac*)
+		os=`echo $os | sed -e 's|mac|macos|'`
+		;;
+	-linux-dietlibc)
+		os=-linux-dietlibc
+		;;
+	-linux*)
+		os=`echo $os | sed -e 's|linux|linux-gnu|'`
+		;;
+	-sunos5*)
+		os=`echo $os | sed -e 's|sunos5|solaris2|'`
+		;;
+	-sunos6*)
+		os=`echo $os | sed -e 's|sunos6|solaris3|'`
+		;;
+	-opened*)
+		os=-openedition
+		;;
+	-os400*)
+		os=-os400
+		;;
+	-wince*)
+		os=-wince
+		;;
+	-osfrose*)
+		os=-osfrose
+		;;
+	-osf*)
+		os=-osf
+		;;
+	-utek*)
+		os=-bsd
+		;;
+	-dynix*)
+		os=-bsd
+		;;
+	-acis*)
+		os=-aos
+		;;
+	-atheos*)
+		os=-atheos
+		;;
+	-syllable*)
+		os=-syllable
+		;;
+	-386bsd)
+		os=-bsd
+		;;
+	-ctix* | -uts*)
+		os=-sysv
+		;;
+	-nova*)
+		os=-rtmk-nova
+		;;
+	-ns2 )
+		os=-nextstep2
+		;;
+	-nsk*)
+		os=-nsk
+		;;
+	# Preserve the version number of sinix5.
+	-sinix5.*)
+		os=`echo $os | sed -e 's|sinix|sysv|'`
+		;;
+	-sinix*)
+		os=-sysv4
+		;;
+	-tpf*)
+		os=-tpf
+		;;
+	-triton*)
+		os=-sysv3
+		;;
+	-oss*)
+		os=-sysv3
+		;;
+	-svr4)
+		os=-sysv4
+		;;
+	-svr3)
+		os=-sysv3
+		;;
+	-sysvr4)
+		os=-sysv4
+		;;
+	# This must come after -sysvr4.
+	-sysv*)
+		;;
+	-ose*)
+		os=-ose
+		;;
+	-es1800*)
+		os=-ose
+		;;
+	-xenix)
+		os=-xenix
+		;;
+	-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+		os=-mint
+		;;
+	-aros*)
+		os=-aros
+		;;
+	-kaos*)
+		os=-kaos
+		;;
+	-zvmoe)
+		os=-zvmoe
+		;;
+	-dicos*)
+		os=-dicos
+		;;
+	-nacl*)
+		;;
+	-ios)
+		;;
+	-none)
+		;;
+	*)
+		# Get rid of the `-' at the beginning of $os.
+		os=`echo $os | sed 's/[^-]*-//'`
+		echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+		exit 1
+		;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+	score-*)
+		os=-elf
+		;;
+	spu-*)
+		os=-elf
+		;;
+	*-acorn)
+		os=-riscix1.2
+		;;
+	arm*-rebel)
+		os=-linux
+		;;
+	arm*-semi)
+		os=-aout
+		;;
+	c4x-* | tic4x-*)
+		os=-coff
+		;;
+	tic54x-*)
+		os=-coff
+		;;
+	tic55x-*)
+		os=-coff
+		;;
+	tic6x-*)
+		os=-coff
+		;;
+	# This must come before the *-dec entry.
+	pdp10-*)
+		os=-tops20
+		;;
+	pdp11-*)
+		os=-none
+		;;
+	*-dec | vax-*)
+		os=-ultrix4.2
+		;;
+	m68*-apollo)
+		os=-domain
+		;;
+	i386-sun)
+		os=-sunos4.0.2
+		;;
+	m68000-sun)
+		os=-sunos3
+		;;
+	m68*-cisco)
+		os=-aout
+		;;
+	mep-*)
+		os=-elf
+		;;
+	mips*-cisco)
+		os=-elf
+		;;
+	mips*-*)
+		os=-elf
+		;;
+	or32-*)
+		os=-coff
+		;;
+	*-tti)	# must be before sparc entry or we get the wrong os.
+		os=-sysv3
+		;;
+	sparc-* | *-sun)
+		os=-sunos4.1.1
+		;;
+	pru-*)
+		os=-elf
+		;;
+	*-be)
+		os=-beos
+		;;
+	*-haiku)
+		os=-haiku
+		;;
+	*-ibm)
+		os=-aix
+		;;
+	*-knuth)
+		os=-mmixware
+		;;
+	*-wec)
+		os=-proelf
+		;;
+	*-winbond)
+		os=-proelf
+		;;
+	*-oki)
+		os=-proelf
+		;;
+	*-hp)
+		os=-hpux
+		;;
+	*-hitachi)
+		os=-hiux
+		;;
+	i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+		os=-sysv
+		;;
+	*-cbm)
+		os=-amigaos
+		;;
+	*-dg)
+		os=-dgux
+		;;
+	*-dolphin)
+		os=-sysv3
+		;;
+	m68k-ccur)
+		os=-rtu
+		;;
+	m88k-omron*)
+		os=-luna
+		;;
+	*-next )
+		os=-nextstep
+		;;
+	*-sequent)
+		os=-ptx
+		;;
+	*-crds)
+		os=-unos
+		;;
+	*-ns)
+		os=-genix
+		;;
+	i370-*)
+		os=-mvs
+		;;
+	*-next)
+		os=-nextstep3
+		;;
+	*-gould)
+		os=-sysv
+		;;
+	*-highlevel)
+		os=-bsd
+		;;
+	*-encore)
+		os=-bsd
+		;;
+	*-sgi)
+		os=-irix
+		;;
+	*-siemens)
+		os=-sysv4
+		;;
+	*-masscomp)
+		os=-rtu
+		;;
+	f30[01]-fujitsu | f700-fujitsu)
+		os=-uxpv
+		;;
+	*-rom68k)
+		os=-coff
+		;;
+	*-*bug)
+		os=-coff
+		;;
+	*-apple)
+		os=-macos
+		;;
+	*-atari*)
+		os=-mint
+		;;
+	*)
+		os=-none
+		;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+	*-unknown)
+		case $os in
+			-riscix*)
+				vendor=acorn
+				;;
+			-sunos*)
+				vendor=sun
+				;;
+			-cnk*|-aix*)
+				vendor=ibm
+				;;
+			-beos*)
+				vendor=be
+				;;
+			-hpux*)
+				vendor=hp
+				;;
+			-mpeix*)
+				vendor=hp
+				;;
+			-hiux*)
+				vendor=hitachi
+				;;
+			-unos*)
+				vendor=crds
+				;;
+			-dgux*)
+				vendor=dg
+				;;
+			-luna*)
+				vendor=omron
+				;;
+			-genix*)
+				vendor=ns
+				;;
+			-mvs* | -opened*)
+				vendor=ibm
+				;;
+			-os400*)
+				vendor=ibm
+				;;
+			-ptx*)
+				vendor=sequent
+				;;
+			-tpf*)
+				vendor=ibm
+				;;
+			-vxsim* | -vxworks* | -windiss*)
+				vendor=wrs
+				;;
+			-aux*)
+				vendor=apple
+				;;
+			-hms*)
+				vendor=hitachi
+				;;
+			-mpw* | -macos*)
+				vendor=apple
+				;;
+			-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+				vendor=atari
+				;;
+			-vos*)
+				vendor=stratus
+				;;
+		esac
+		basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+		;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/config/libtool.m4 b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/config/libtool.m4
new file mode 100644
index 0000000..4ceb7f1
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/config/libtool.m4
@@ -0,0 +1,7309 @@
+# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
+#
+#   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+#                 2006, 2007, 2008 Free Software Foundation, Inc.
+#   Written by Gordon Matzigkeit, 1996
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+m4_define([_LT_COPYING], [dnl
+#   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+#                 2006, 2007, 2008 Free Software Foundation, Inc.
+#   Written by Gordon Matzigkeit, 1996
+#
+#   This file is part of GNU Libtool.
+#
+# GNU Libtool is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Libtool; see the file COPYING.  If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html, or
+# obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+])
+
+# serial 56 LT_INIT
+
+
+# LT_PREREQ(VERSION)
+# ------------------
+# Complain and exit if this libtool version is less that VERSION.
+m4_defun([LT_PREREQ],
+[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1,
+       [m4_default([$3],
+		   [m4_fatal([Libtool version $1 or higher is required],
+		             63)])],
+       [$2])])
+
+
+# _LT_CHECK_BUILDDIR
+# ------------------
+# Complain if the absolute build directory name contains unusual characters
+m4_defun([_LT_CHECK_BUILDDIR],
+[case `pwd` in
+  *\ * | *\	*)
+    AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;;
+esac
+])
+
+
+# LT_INIT([OPTIONS])
+# ------------------
+AC_DEFUN([LT_INIT],
+[AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT
+AC_BEFORE([$0], [LT_LANG])dnl
+AC_BEFORE([$0], [LT_OUTPUT])dnl
+AC_BEFORE([$0], [LTDL_INIT])dnl
+m4_require([_LT_CHECK_BUILDDIR])dnl
+
+dnl Autoconf doesn't catch unexpanded LT_ macros by default:
+m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl
+m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl
+dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4
+dnl unless we require an AC_DEFUNed macro:
+AC_REQUIRE([LTOPTIONS_VERSION])dnl
+AC_REQUIRE([LTSUGAR_VERSION])dnl
+AC_REQUIRE([LTVERSION_VERSION])dnl
+AC_REQUIRE([LTOBSOLETE_VERSION])dnl
+m4_require([_LT_PROG_LTMAIN])dnl
+
+dnl Parse OPTIONS
+_LT_SET_OPTIONS([$0], [$1])
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ltmain"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)dnl
+
+_LT_SETUP
+
+# Only expand once:
+m4_define([LT_INIT])
+])# LT_INIT
+
+# Old names:
+AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT])
+AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_PROG_LIBTOOL], [])
+dnl AC_DEFUN([AM_PROG_LIBTOOL], [])
+
+
+# _LT_CC_BASENAME(CC)
+# -------------------
+# Calculate cc_basename.  Skip known compiler wrappers and cross-prefix.
+m4_defun([_LT_CC_BASENAME],
+[for cc_temp in $1""; do
+  case $cc_temp in
+    compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;;
+    distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+])
+
+
+# _LT_FILEUTILS_DEFAULTS
+# ----------------------
+# It is okay to use these file commands and assume they have been set
+# sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'.
+m4_defun([_LT_FILEUTILS_DEFAULTS],
+[: ${CP="cp -f"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+])# _LT_FILEUTILS_DEFAULTS
+
+
+# _LT_SETUP
+# ---------
+m4_defun([_LT_SETUP],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+_LT_DECL([], [host_alias], [0], [The host system])dnl
+_LT_DECL([], [host], [0])dnl
+_LT_DECL([], [host_os], [0])dnl
+dnl
+_LT_DECL([], [build_alias], [0], [The build system])dnl
+_LT_DECL([], [build], [0])dnl
+_LT_DECL([], [build_os], [0])dnl
+dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([LT_PATH_LD])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+dnl
+AC_REQUIRE([AC_PROG_LN_S])dnl
+test -z "$LN_S" && LN_S="ln -s"
+_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl
+dnl
+AC_REQUIRE([LT_CMD_MAX_LEN])dnl
+_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl
+_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl
+dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_CHECK_SHELL_FEATURES])dnl
+m4_require([_LT_CMD_RELOAD])dnl
+m4_require([_LT_CHECK_MAGIC_METHOD])dnl
+m4_require([_LT_CMD_OLD_ARCHIVE])dnl
+m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+
+_LT_CONFIG_LIBTOOL_INIT([
+# See if we are running on zsh, and set the options which allow our
+# commands through without removal of \ escapes INIT.
+if test -n "\${ZSH_VERSION+set}" ; then
+   setopt NO_GLOB_SUBST
+fi
+])
+if test -n "${ZSH_VERSION+set}" ; then
+   setopt NO_GLOB_SUBST
+fi
+
+_LT_CHECK_OBJDIR
+
+m4_require([_LT_TAG_COMPILER])dnl
+_LT_PROG_ECHO_BACKSLASH
+
+case $host_os in
+aix3*)
+  # AIX sometimes has problems with the GCC collect2 program.  For some
+  # reason, if we set the COLLECT_NAMES environment variable, the problems
+  # vanish in a puff of smoke.
+  if test "X${COLLECT_NAMES+set}" != Xset; then
+    COLLECT_NAMES=
+    export COLLECT_NAMES
+  fi
+  ;;
+esac
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='s/\([["`$\\]]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\([["`\\]]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to delay expansion of an escaped single quote.
+delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+# Global variables:
+ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$LD" && LD=ld
+test -z "$ac_objext" && ac_objext=o
+
+_LT_CC_BASENAME([$compiler])
+
+# Only perform the check for file, if the check method requires it
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+case $deplibs_check_method in
+file_magic*)
+  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+    _LT_PATH_MAGIC
+  fi
+  ;;
+esac
+
+# Use C for the default configuration in the libtool script
+LT_SUPPORTED_TAG([CC])
+_LT_LANG_C_CONFIG
+_LT_LANG_DEFAULT_CONFIG
+_LT_CONFIG_COMMANDS
+])# _LT_SETUP
+
+
+# _LT_PROG_LTMAIN
+# ---------------
+# Note that this code is called both from `configure', and `config.status'
+# now that we use AC_CONFIG_COMMANDS to generate libtool.  Notably,
+# `config.status' has no value for ac_aux_dir unless we are using Automake,
+# so we pass a copy along to make sure it has a sensible value anyway.
+m4_defun([_LT_PROG_LTMAIN],
+[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl
+_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir'])
+ltmain="$ac_aux_dir/ltmain.sh"
+])# _LT_PROG_LTMAIN
+
+
+## ------------------------------------- ##
+## Accumulate code for creating libtool. ##
+## ------------------------------------- ##
+
+# So that we can recreate a full libtool script including additional
+# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS
+# in macros and then make a single call at the end using the `libtool'
+# label.
+
+
+# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS])
+# ----------------------------------------
+# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later.
+m4_define([_LT_CONFIG_LIBTOOL_INIT],
+[m4_ifval([$1],
+          [m4_append([_LT_OUTPUT_LIBTOOL_INIT],
+                     [$1
+])])])
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_INIT])
+
+
+# _LT_CONFIG_LIBTOOL([COMMANDS])
+# ------------------------------
+# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later.
+m4_define([_LT_CONFIG_LIBTOOL],
+[m4_ifval([$1],
+          [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS],
+                     [$1
+])])])
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS])
+
+
+# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS])
+# -----------------------------------------------------
+m4_defun([_LT_CONFIG_SAVE_COMMANDS],
+[_LT_CONFIG_LIBTOOL([$1])
+_LT_CONFIG_LIBTOOL_INIT([$2])
+])
+
+
+# _LT_FORMAT_COMMENT([COMMENT])
+# -----------------------------
+# Add leading comment marks to the start of each line, and a trailing
+# full-stop to the whole comment if one is not present already.
+m4_define([_LT_FORMAT_COMMENT],
+[m4_ifval([$1], [
+m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])],
+              [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.])
+)])
+
+
+
+## ------------------------ ##
+## FIXME: Eliminate VARNAME ##
+## ------------------------ ##
+
+
+# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?])
+# -------------------------------------------------------------------
+# CONFIGNAME is the name given to the value in the libtool script.
+# VARNAME is the (base) name used in the configure script.
+# VALUE may be 0, 1 or 2 for a computed quote escaped value based on
+# VARNAME.  Any other value will be used directly.
+m4_define([_LT_DECL],
+[lt_if_append_uniq([lt_decl_varnames], [$2], [, ],
+    [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name],
+	[m4_ifval([$1], [$1], [$2])])
+    lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3])
+    m4_ifval([$4],
+	[lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])])
+    lt_dict_add_subkey([lt_decl_dict], [$2],
+	[tagged?], [m4_ifval([$5], [yes], [no])])])
+])
+
+
+# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION])
+# --------------------------------------------------------
+m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])])
+
+
+# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...])
+# ------------------------------------------------
+m4_define([lt_decl_tag_varnames],
+[_lt_decl_filter([tagged?], [yes], $@)])
+
+
+# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..])
+# ---------------------------------------------------------
+m4_define([_lt_decl_filter],
+[m4_case([$#],
+  [0], [m4_fatal([$0: too few arguments: $#])],
+  [1], [m4_fatal([$0: too few arguments: $#: $1])],
+  [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)],
+  [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)],
+  [lt_dict_filter([lt_decl_dict], $@)])[]dnl
+])
+
+
+# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...])
+# --------------------------------------------------
+m4_define([lt_decl_quote_varnames],
+[_lt_decl_filter([value], [1], $@)])
+
+
+# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...])
+# ---------------------------------------------------
+m4_define([lt_decl_dquote_varnames],
+[_lt_decl_filter([value], [2], $@)])
+
+
+# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...])
+# ---------------------------------------------------
+m4_define([lt_decl_varnames_tagged],
+[_$0(m4_quote(m4_default([$1], [[, ]])),
+     m4_quote(m4_if([$2], [],
+		     m4_quote(lt_decl_tag_varnames),
+		  m4_quote(m4_shift($@)))),
+     m4_split(m4_normalize(m4_quote(_LT_TAGS))))])
+m4_define([_lt_decl_varnames_tagged], [lt_combine([$1], [$2], [_], $3)])
+
+
+# lt_decl_all_varnames([SEPARATOR], [VARNAME1...])
+# ------------------------------------------------
+m4_define([lt_decl_all_varnames],
+[_$0(m4_quote(m4_default([$1], [[, ]])),
+     m4_if([$2], [],
+	   m4_quote(lt_decl_varnames),
+	m4_quote(m4_shift($@))))[]dnl
+])
+m4_define([_lt_decl_all_varnames],
+[lt_join($@, lt_decl_varnames_tagged([$1],
+			lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl
+])
+
+
+# _LT_CONFIG_STATUS_DECLARE([VARNAME])
+# ------------------------------------
+# Quote a variable value, and forward it to `config.status' so that its
+# declaration there will have the same value as in `configure'.  VARNAME
+# must have a single quote delimited value for this to work.
+m4_define([_LT_CONFIG_STATUS_DECLARE],
+[$1='`$ECHO "X$][$1" | $Xsed -e "$delay_single_quote_subst"`'])
+
+
+# _LT_CONFIG_STATUS_DECLARATIONS
+# ------------------------------
+# We delimit libtool config variables with single quotes, so when
+# we write them to config.status, we have to be sure to quote all
+# embedded single quotes properly.  In configure, this macro expands
+# each variable declared with _LT_DECL (and _LT_TAGDECL) into:
+#
+#    <var>='`$ECHO "X$<var>" | $Xsed -e "$delay_single_quote_subst"`'
+m4_defun([_LT_CONFIG_STATUS_DECLARATIONS],
+[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames),
+    [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])])
+
+
+# _LT_LIBTOOL_TAGS
+# ----------------
+# Output comment and list of tags supported by the script
+m4_defun([_LT_LIBTOOL_TAGS],
+[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl
+available_tags="_LT_TAGS"dnl
+])
+
+
+# _LT_LIBTOOL_DECLARE(VARNAME, [TAG])
+# -----------------------------------
+# Extract the dictionary values for VARNAME (optionally with TAG) and
+# expand to a commented shell variable setting:
+#
+#    # Some comment about what VAR is for.
+#    visible_name=$lt_internal_name
+m4_define([_LT_LIBTOOL_DECLARE],
+[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1],
+					   [description])))[]dnl
+m4_pushdef([_libtool_name],
+    m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl
+m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])),
+    [0], [_libtool_name=[$]$1],
+    [1], [_libtool_name=$lt_[]$1],
+    [2], [_libtool_name=$lt_[]$1],
+    [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl
+m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl
+])
+
+
+# _LT_LIBTOOL_CONFIG_VARS
+# -----------------------
+# Produce commented declarations of non-tagged libtool config variables
+# suitable for insertion in the LIBTOOL CONFIG section of the `libtool'
+# script.  Tagged libtool config variables (even for the LIBTOOL CONFIG
+# section) are produced by _LT_LIBTOOL_TAG_VARS.
+m4_defun([_LT_LIBTOOL_CONFIG_VARS],
+[m4_foreach([_lt_var],
+    m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)),
+    [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])])
+
+
+# _LT_LIBTOOL_TAG_VARS(TAG)
+# -------------------------
+m4_define([_LT_LIBTOOL_TAG_VARS],
+[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames),
+    [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])])
+
+
+# _LT_TAGVAR(VARNAME, [TAGNAME])
+# ------------------------------
+m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])])
+
+
+# _LT_CONFIG_COMMANDS
+# -------------------
+# Send accumulated output to $CONFIG_STATUS.  Thanks to the lists of
+# variables for single and double quote escaping we saved from calls
+# to _LT_DECL, we can put quote escaped variables declarations
+# into `config.status', and then the shell code to quote escape them in
+# for loops in `config.status'.  Finally, any additional code accumulated
+# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded.
+m4_defun([_LT_CONFIG_COMMANDS],
+[AC_PROVIDE_IFELSE([LT_OUTPUT],
+	dnl If the libtool generation code has been placed in $CONFIG_LT,
+	dnl instead of duplicating it all over again into config.status,
+	dnl then we will have config.status run $CONFIG_LT later, so it
+	dnl needs to know what name is stored there:
+        [AC_CONFIG_COMMANDS([libtool],
+            [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])],
+    dnl If the libtool generation code is destined for config.status,
+    dnl expand the accumulated commands and init code now:
+    [AC_CONFIG_COMMANDS([libtool],
+        [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])])
+])#_LT_CONFIG_COMMANDS
+
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT],
+[
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+sed_quote_subst='$sed_quote_subst'
+double_quote_subst='$double_quote_subst'
+delay_variable_subst='$delay_variable_subst'
+_LT_CONFIG_STATUS_DECLARATIONS
+LTCC='$LTCC'
+LTCFLAGS='$LTCFLAGS'
+compiler='$compiler_DEFAULT'
+
+# Quote evaled strings.
+for var in lt_decl_all_varnames([[ \
+]], lt_decl_quote_varnames); do
+    case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in
+    *[[\\\\\\\`\\"\\\$]]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+# Double-quote double-evaled strings.
+for var in lt_decl_all_varnames([[ \
+]], lt_decl_dquote_varnames); do
+    case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in
+    *[[\\\\\\\`\\"\\\$]]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+# Fix-up fallback echo if it was mangled by the above quoting rules.
+case \$lt_ECHO in
+*'\\\[$]0 --fallback-echo"')dnl "
+  lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\[$]0 --fallback-echo"\[$]/\[$]0 --fallback-echo"/'\`
+  ;;
+esac
+
+_LT_OUTPUT_LIBTOOL_INIT
+])
+
+
+# LT_OUTPUT
+# ---------
+# This macro allows early generation of the libtool script (before
+# AC_OUTPUT is called), incase it is used in configure for compilation
+# tests.
+AC_DEFUN([LT_OUTPUT],
+[: ${CONFIG_LT=./config.lt}
+AC_MSG_NOTICE([creating $CONFIG_LT])
+cat >"$CONFIG_LT" <<_LTEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate a libtool stub with the current configuration.
+
+lt_cl_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_LTEOF
+
+cat >>"$CONFIG_LT" <<\_LTEOF
+AS_SHELL_SANITIZE
+_AS_PREPARE
+
+exec AS_MESSAGE_FD>&1
+exec AS_MESSAGE_LOG_FD>>config.log
+{
+  echo
+  AS_BOX([Running $as_me.])
+} >&AS_MESSAGE_LOG_FD
+
+lt_cl_help="\
+\`$as_me' creates a local libtool stub from the current configuration,
+for use in further configure time tests before the real libtool is
+generated.
+
+Usage: $[0] [[OPTIONS]]
+
+  -h, --help      print this help, then exit
+  -V, --version   print version number, then exit
+  -q, --quiet     do not print progress messages
+  -d, --debug     don't remove temporary files
+
+Report bugs to <bug-libtool@gnu.org>."
+
+lt_cl_version="\
+m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl
+m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION])
+configured by $[0], generated by m4_PACKAGE_STRING.
+
+Copyright (C) 2008 Free Software Foundation, Inc.
+This config.lt script is free software; the Free Software Foundation
+gives unlimited permision to copy, distribute and modify it."
+
+while test $[#] != 0
+do
+  case $[1] in
+    --version | --v* | -V )
+      echo "$lt_cl_version"; exit 0 ;;
+    --help | --h* | -h )
+      echo "$lt_cl_help"; exit 0 ;;
+    --debug | --d* | -d )
+      debug=: ;;
+    --quiet | --q* | --silent | --s* | -q )
+      lt_cl_silent=: ;;
+
+    -*) AC_MSG_ERROR([unrecognized option: $[1]
+Try \`$[0] --help' for more information.]) ;;
+
+    *) AC_MSG_ERROR([unrecognized argument: $[1]
+Try \`$[0] --help' for more information.]) ;;
+  esac
+  shift
+done
+
+if $lt_cl_silent; then
+  exec AS_MESSAGE_FD>/dev/null
+fi
+_LTEOF
+
+cat >>"$CONFIG_LT" <<_LTEOF
+_LT_OUTPUT_LIBTOOL_COMMANDS_INIT
+_LTEOF
+
+cat >>"$CONFIG_LT" <<\_LTEOF
+AC_MSG_NOTICE([creating $ofile])
+_LT_OUTPUT_LIBTOOL_COMMANDS
+AS_EXIT(0)
+_LTEOF
+chmod +x "$CONFIG_LT"
+
+# configure is writing to config.log, but config.lt does its own redirection,
+# appending to config.log, which fails on DOS, as config.log is still kept
+# open by configure.  Here we exec the FD to /dev/null, effectively closing
+# config.log, so it can be properly (re)opened and appended to by config.lt.
+if test "$no_create" != yes; then
+  lt_cl_success=:
+  test "$silent" = yes &&
+    lt_config_lt_args="$lt_config_lt_args --quiet"
+  exec AS_MESSAGE_LOG_FD>/dev/null
+  $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false
+  exec AS_MESSAGE_LOG_FD>>config.log
+  $lt_cl_success || AS_EXIT(1)
+fi
+])# LT_OUTPUT
+
+
+# _LT_CONFIG(TAG)
+# ---------------
+# If TAG is the built-in tag, create an initial libtool script with a
+# default configuration from the untagged config vars.  Otherwise add code
+# to config.status for appending the configuration named by TAG from the
+# matching tagged config vars.
+m4_defun([_LT_CONFIG],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+_LT_CONFIG_SAVE_COMMANDS([
+  m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl
+  m4_if(_LT_TAG, [C], [
+    # See if we are running on zsh, and set the options which allow our
+    # commands through without removal of \ escapes.
+    if test -n "${ZSH_VERSION+set}" ; then
+      setopt NO_GLOB_SUBST
+    fi
+
+    cfgfile="${ofile}T"
+    trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+    $RM "$cfgfile"
+
+    cat <<_LT_EOF >> "$cfgfile"
+#! $SHELL
+
+# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+_LT_COPYING
+_LT_LIBTOOL_TAGS
+
+# ### BEGIN LIBTOOL CONFIG
+_LT_LIBTOOL_CONFIG_VARS
+_LT_LIBTOOL_TAG_VARS
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+  case $host_os in
+  aix3*)
+    cat <<\_LT_EOF >> "$cfgfile"
+# AIX sometimes has problems with the GCC collect2 program.  For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+  COLLECT_NAMES=
+  export COLLECT_NAMES
+fi
+_LT_EOF
+    ;;
+  esac
+
+  _LT_PROG_LTMAIN
+
+  # We use sed instead of cat because bash on DJGPP gets confused if
+  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
+  # text mode, it properly converts lines to CR/LF.  This bash problem
+  # is reportedly fixed, but why not run on old versions too?
+  sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \
+    || (rm -f "$cfgfile"; exit 1)
+
+  _LT_PROG_XSI_SHELLFNS
+
+  sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \
+    || (rm -f "$cfgfile"; exit 1)
+
+  mv -f "$cfgfile" "$ofile" ||
+    (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+  chmod +x "$ofile"
+],
+[cat <<_LT_EOF >> "$ofile"
+
+dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded
+dnl in a comment (ie after a #).
+# ### BEGIN LIBTOOL TAG CONFIG: $1
+_LT_LIBTOOL_TAG_VARS(_LT_TAG)
+# ### END LIBTOOL TAG CONFIG: $1
+_LT_EOF
+])dnl /m4_if
+],
+[m4_if([$1], [], [
+    PACKAGE='$PACKAGE'
+    VERSION='$VERSION'
+    TIMESTAMP='$TIMESTAMP'
+    RM='$RM'
+    ofile='$ofile'], [])
+])dnl /_LT_CONFIG_SAVE_COMMANDS
+])# _LT_CONFIG
+
+
+# LT_SUPPORTED_TAG(TAG)
+# ---------------------
+# Trace this macro to discover what tags are supported by the libtool
+# --tag option, using:
+#    autoconf --trace 'LT_SUPPORTED_TAG:$1'
+AC_DEFUN([LT_SUPPORTED_TAG], [])
+
+
+# C support is built-in for now
+m4_define([_LT_LANG_C_enabled], [])
+m4_define([_LT_TAGS], [])
+
+
+# LT_LANG(LANG)
+# -------------
+# Enable libtool support for the given language if not already enabled.
+AC_DEFUN([LT_LANG],
+[AC_BEFORE([$0], [LT_OUTPUT])dnl
+m4_case([$1],
+  [C],			[_LT_LANG(C)],
+  [C++],		[_LT_LANG(CXX)],
+  [Java],		[_LT_LANG(GCJ)],
+  [Fortran 77],		[_LT_LANG(F77)],
+  [Fortran],		[_LT_LANG(FC)],
+  [Windows Resource],	[_LT_LANG(RC)],
+  [m4_ifdef([_LT_LANG_]$1[_CONFIG],
+    [_LT_LANG($1)],
+    [m4_fatal([$0: unsupported language: "$1"])])])dnl
+])# LT_LANG
+
+
+# _LT_LANG(LANGNAME)
+# ------------------
+m4_defun([_LT_LANG],
+[m4_ifdef([_LT_LANG_]$1[_enabled], [],
+  [LT_SUPPORTED_TAG([$1])dnl
+  m4_append([_LT_TAGS], [$1 ])dnl
+  m4_define([_LT_LANG_]$1[_enabled], [])dnl
+  _LT_LANG_$1_CONFIG($1)])dnl
+])# _LT_LANG
+
+
+# _LT_LANG_DEFAULT_CONFIG
+# -----------------------
+m4_defun([_LT_LANG_DEFAULT_CONFIG],
+[AC_PROVIDE_IFELSE([AC_PROG_CXX],
+  [LT_LANG(CXX)],
+  [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])])
+
+AC_PROVIDE_IFELSE([AC_PROG_F77],
+  [LT_LANG(F77)],
+  [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])])
+
+AC_PROVIDE_IFELSE([AC_PROG_FC],
+  [LT_LANG(FC)],
+  [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])])
+
+dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal
+dnl pulling things in needlessly.
+AC_PROVIDE_IFELSE([AC_PROG_GCJ],
+  [LT_LANG(GCJ)],
+  [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
+    [LT_LANG(GCJ)],
+    [AC_PROVIDE_IFELSE([LT_PROG_GCJ],
+      [LT_LANG(GCJ)],
+      [m4_ifdef([AC_PROG_GCJ],
+	[m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])])
+       m4_ifdef([A][M_PROG_GCJ],
+	[m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])])
+       m4_ifdef([LT_PROG_GCJ],
+	[m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])])
+
+AC_PROVIDE_IFELSE([LT_PROG_RC],
+  [LT_LANG(RC)],
+  [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])])
+])# _LT_LANG_DEFAULT_CONFIG
+
+# Obsolete macros:
+AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)])
+AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)])
+AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)])
+AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_CXX], [])
+dnl AC_DEFUN([AC_LIBTOOL_F77], [])
+dnl AC_DEFUN([AC_LIBTOOL_FC], [])
+dnl AC_DEFUN([AC_LIBTOOL_GCJ], [])
+
+
+# _LT_TAG_COMPILER
+# ----------------
+m4_defun([_LT_TAG_COMPILER],
+[AC_REQUIRE([AC_PROG_CC])dnl
+
+_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl
+_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl
+_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl
+_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+])# _LT_TAG_COMPILER
+
+
+# _LT_COMPILER_BOILERPLATE
+# ------------------------
+# Check for compiler boilerplate output or warnings with
+# the simple compiler test code.
+m4_defun([_LT_COMPILER_BOILERPLATE],
+[m4_require([_LT_DECL_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+])# _LT_COMPILER_BOILERPLATE
+
+
+# _LT_LINKER_BOILERPLATE
+# ----------------------
+# Check for linker boilerplate output or warnings with
+# the simple link test code.
+m4_defun([_LT_LINKER_BOILERPLATE],
+[m4_require([_LT_DECL_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+])# _LT_LINKER_BOILERPLATE
+
+# _LT_REQUIRED_DARWIN_CHECKS
+# -------------------------
+m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[
+  case $host_os in
+    rhapsody* | darwin*)
+    AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:])
+    AC_CHECK_TOOL([NMEDIT], [nmedit], [:])
+    AC_CHECK_TOOL([LIPO], [lipo], [:])
+    AC_CHECK_TOOL([OTOOL], [otool], [:])
+    AC_CHECK_TOOL([OTOOL64], [otool64], [:])
+    _LT_DECL([], [DSYMUTIL], [1],
+      [Tool to manipulate archived DWARF debug symbol files on Mac OS X])
+    _LT_DECL([], [NMEDIT], [1],
+      [Tool to change global to local symbols on Mac OS X])
+    _LT_DECL([], [LIPO], [1],
+      [Tool to manipulate fat objects and archives on Mac OS X])
+    _LT_DECL([], [OTOOL], [1],
+      [ldd/readelf like tool for Mach-O binaries on Mac OS X])
+    _LT_DECL([], [OTOOL64], [1],
+      [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4])
+
+    AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod],
+      [lt_cv_apple_cc_single_mod=no
+      if test -z "${LT_MULTI_MODULE}"; then
+	# By default we will add the -single_module flag. You can override
+	# by either setting the environment variable LT_MULTI_MODULE
+	# non-empty at configure time, or by adding -multi_module to the
+	# link flags.
+	rm -rf libconftest.dylib*
+	echo "int foo(void){return 1;}" > conftest.c
+	echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD
+	$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+	  -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
+        _lt_result=$?
+	if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then
+	  lt_cv_apple_cc_single_mod=yes
+	else
+	  cat conftest.err >&AS_MESSAGE_LOG_FD
+	fi
+	rm -rf libconftest.dylib*
+	rm -f conftest.*
+      fi])
+    AC_CACHE_CHECK([for -exported_symbols_list linker flag],
+      [lt_cv_ld_exported_symbols_list],
+      [lt_cv_ld_exported_symbols_list=no
+      save_LDFLAGS=$LDFLAGS
+      echo "_main" > conftest.sym
+      LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
+      AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+	[lt_cv_ld_exported_symbols_list=yes],
+	[lt_cv_ld_exported_symbols_list=no])
+	LDFLAGS="$save_LDFLAGS"
+    ])
+    case $host_os in
+    rhapsody* | darwin1.[[012]])
+      _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
+    darwin1.*)
+      _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+    darwin*) # darwin 5.x on 
+      # if running on 10.5 or later, the deployment target defaults
+      # to the OS version, if on x86, and 10.4, the deployment
+      # target defaults to 10.4. Don't you love it? 
+      case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
+	10.0,*86*-darwin8*|10.0,*-darwin[[91]]*)
+	  _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+	10.[[012]]*)
+	  _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+	10.*)
+	  _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+      esac
+    ;;
+  esac
+    if test "$lt_cv_apple_cc_single_mod" = "yes"; then
+      _lt_dar_single_mod='$single_module'
+    fi
+    if test "$lt_cv_ld_exported_symbols_list" = "yes"; then
+      _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym'
+    else
+      _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}'
+    fi
+    if test "$DSYMUTIL" != ":"; then
+      _lt_dsymutil='~$DSYMUTIL $lib || :'
+    else
+      _lt_dsymutil=
+    fi
+    ;;
+  esac
+])
+
+
+# _LT_DARWIN_LINKER_FEATURES
+# --------------------------
+# Checks for linker and compiler features on darwin
+m4_defun([_LT_DARWIN_LINKER_FEATURES],
+[
+  m4_require([_LT_REQUIRED_DARWIN_CHECKS])
+  _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+  _LT_TAGVAR(hardcode_direct, $1)=no
+  _LT_TAGVAR(hardcode_automatic, $1)=yes
+  _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+  _LT_TAGVAR(whole_archive_flag_spec, $1)=''
+  _LT_TAGVAR(link_all_deplibs, $1)=yes
+  _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined"
+  if test "$GCC" = "yes"; then
+    output_verbose_link_cmd=echo
+    _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
+    _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
+    _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
+    _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
+    m4_if([$1], [CXX],
+[   if test "$lt_cv_apple_cc_single_mod" != "yes"; then
+      _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}"
+      _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}"
+    fi
+],[])
+  else
+  _LT_TAGVAR(ld_shlibs, $1)=no
+  fi
+])
+
+# _LT_SYS_MODULE_PATH_AIX
+# -----------------------
+# Links a minimal program and checks the executable
+# for the system default hardcoded library path. In most cases,
+# this is /usr/lib:/lib, but when the MPI compilers are used
+# the location of the communication and MPI libs are included too.
+# If we don't find anything, use the default library path according
+# to the aix ld manual.
+m4_defun([_LT_SYS_MODULE_PATH_AIX],
+[m4_require([_LT_DECL_SED])dnl
+AC_LINK_IFELSE(AC_LANG_PROGRAM,[
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+	/^0/ {
+	    s/^0  *\(.*\)$/\1/
+	    p
+	}
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi],[])
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+])# _LT_SYS_MODULE_PATH_AIX
+
+
+# _LT_SHELL_INIT(ARG)
+# -------------------
+m4_define([_LT_SHELL_INIT],
+[ifdef([AC_DIVERSION_NOTICE],
+	     [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)],
+	 [AC_DIVERT_PUSH(NOTICE)])
+$1
+AC_DIVERT_POP
+])# _LT_SHELL_INIT
+
+
+# _LT_PROG_ECHO_BACKSLASH
+# -----------------------
+# Add some code to the start of the generated configure script which
+# will find an echo command which doesn't interpret backslashes.
+m4_defun([_LT_PROG_ECHO_BACKSLASH],
+[_LT_SHELL_INIT([
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+case X$lt_ECHO in
+X*--fallback-echo)
+  # Remove one level of quotation (which was required for Make).
+  ECHO=`echo "$lt_ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','`
+  ;;
+esac
+
+ECHO=${lt_ECHO-echo}
+if test "X[$]1" = X--no-reexec; then
+  # Discard the --no-reexec flag, and continue.
+  shift
+elif test "X[$]1" = X--fallback-echo; then
+  # Avoid inline document here, it may be left over
+  :
+elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then
+  # Yippee, $ECHO works!
+  :
+else
+  # Restart under the correct shell.
+  exec $SHELL "[$]0" --no-reexec ${1+"[$]@"}
+fi
+
+if test "X[$]1" = X--fallback-echo; then
+  # used as fallback echo
+  shift
+  cat <<_LT_EOF
+[$]*
+_LT_EOF
+  exit 0
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test -z "$lt_ECHO"; then
+  if test "X${echo_test_string+set}" != Xset; then
+    # find a string as large as possible, as long as the shell can cope with it
+    for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do
+      # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+      if { echo_test_string=`eval $cmd`; } 2>/dev/null &&
+	 { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null
+      then
+        break
+      fi
+    done
+  fi
+
+  if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' &&
+     echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` &&
+     test "X$echo_testing_string" = "X$echo_test_string"; then
+    :
+  else
+    # The Solaris, AIX, and Digital Unix default echo programs unquote
+    # backslashes.  This makes it impossible to quote backslashes using
+    #   echo "$something" | sed 's/\\/\\\\/g'
+    #
+    # So, first we look for a working echo in the user's PATH.
+
+    lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+    for dir in $PATH /usr/ucb; do
+      IFS="$lt_save_ifs"
+      if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+         test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+         echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
+         test "X$echo_testing_string" = "X$echo_test_string"; then
+        ECHO="$dir/echo"
+        break
+      fi
+    done
+    IFS="$lt_save_ifs"
+
+    if test "X$ECHO" = Xecho; then
+      # We didn't find a better echo, so look for alternatives.
+      if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' &&
+         echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` &&
+         test "X$echo_testing_string" = "X$echo_test_string"; then
+        # This shell has a builtin print -r that does the trick.
+        ECHO='print -r'
+      elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } &&
+	   test "X$CONFIG_SHELL" != X/bin/ksh; then
+        # If we have ksh, try running configure again with it.
+        ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+        export ORIGINAL_CONFIG_SHELL
+        CONFIG_SHELL=/bin/ksh
+        export CONFIG_SHELL
+        exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"}
+      else
+        # Try using printf.
+        ECHO='printf %s\n'
+        if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' &&
+	   echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` &&
+	   test "X$echo_testing_string" = "X$echo_test_string"; then
+	  # Cool, printf works
+	  :
+        elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+	     test "X$echo_testing_string" = 'X\t' &&
+	     echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+	     test "X$echo_testing_string" = "X$echo_test_string"; then
+	  CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
+	  export CONFIG_SHELL
+	  SHELL="$CONFIG_SHELL"
+	  export SHELL
+	  ECHO="$CONFIG_SHELL [$]0 --fallback-echo"
+        elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+	     test "X$echo_testing_string" = 'X\t' &&
+	     echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+	     test "X$echo_testing_string" = "X$echo_test_string"; then
+	  ECHO="$CONFIG_SHELL [$]0 --fallback-echo"
+        else
+	  # maybe with a smaller string...
+	  prev=:
+
+	  for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do
+	    if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null
+	    then
+	      break
+	    fi
+	    prev="$cmd"
+	  done
+
+	  if test "$prev" != 'sed 50q "[$]0"'; then
+	    echo_test_string=`eval $prev`
+	    export echo_test_string
+	    exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"}
+	  else
+	    # Oops.  We lost completely, so just stick with echo.
+	    ECHO=echo
+	  fi
+        fi
+      fi
+    fi
+  fi
+fi
+
+# Copy echo and quote the copy suitably for passing to libtool from
+# the Makefile, instead of quoting the original, which is used later.
+lt_ECHO=$ECHO
+if test "X$lt_ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then
+   lt_ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo"
+fi
+
+AC_SUBST(lt_ECHO)
+])
+_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts])
+_LT_DECL([], [ECHO], [1],
+    [An echo program that does not interpret backslashes])
+])# _LT_PROG_ECHO_BACKSLASH
+
+
+# _LT_ENABLE_LOCK
+# ---------------
+m4_defun([_LT_ENABLE_LOCK],
+[AC_ARG_ENABLE([libtool-lock],
+  [AS_HELP_STRING([--disable-libtool-lock],
+    [avoid locking (might break parallel builds)])])
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `/usr/bin/file conftest.$ac_objext` in
+      *ELF-32*)
+	HPUX_IA64_MODE="32"
+	;;
+      *ELF-64*)
+	HPUX_IA64_MODE="64"
+	;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '[#]line __oline__ "configure"' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    if test "$lt_cv_prog_gnu_ld" = yes; then
+      case `/usr/bin/file conftest.$ac_objext` in
+	*32-bit*)
+	  LD="${LD-ld} -melf32bsmip"
+	  ;;
+	*N32*)
+	  LD="${LD-ld} -melf32bmipn32"
+	  ;;
+	*64-bit*)
+	  LD="${LD-ld} -melf64bmip"
+	;;
+      esac
+    else
+      case `/usr/bin/file conftest.$ac_objext` in
+	*32-bit*)
+	  LD="${LD-ld} -32"
+	  ;;
+	*N32*)
+	  LD="${LD-ld} -n32"
+	  ;;
+	*64-bit*)
+	  LD="${LD-ld} -64"
+	  ;;
+      esac
+    fi
+  fi
+  rm -rf conftest*
+  ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `/usr/bin/file conftest.o` in
+      *32-bit*)
+	case $host in
+	  x86_64-*kfreebsd*-gnu)
+	    LD="${LD-ld} -m elf_i386_fbsd"
+	    ;;
+	  x86_64-*linux*)
+	    LD="${LD-ld} -m elf_i386"
+	    ;;
+	  ppc64-*linux*|powerpc64-*linux*)
+	    LD="${LD-ld} -m elf32ppclinux"
+	    ;;
+	  s390x-*linux*)
+	    LD="${LD-ld} -m elf_s390"
+	    ;;
+	  sparc64-*linux*)
+	    LD="${LD-ld} -m elf32_sparc"
+	    ;;
+	esac
+	;;
+      *64-bit*)
+	case $host in
+	  x86_64-*kfreebsd*-gnu)
+	    LD="${LD-ld} -m elf_x86_64_fbsd"
+	    ;;
+	  x86_64-*linux*)
+	    LD="${LD-ld} -m elf_x86_64"
+	    ;;
+	  ppc*-*linux*|powerpc*-*linux*)
+	    LD="${LD-ld} -m elf64ppc"
+	    ;;
+	  s390*-*linux*|s390*-*tpf*)
+	    LD="${LD-ld} -m elf64_s390"
+	    ;;
+	  sparc*-*linux*)
+	    LD="${LD-ld} -m elf64_sparc"
+	    ;;
+	esac
+	;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+    [AC_LANG_PUSH(C)
+     AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
+     AC_LANG_POP])
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+sparc*-*solaris*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `/usr/bin/file conftest.o` in
+    *64-bit*)
+      case $lt_cv_prog_gnu_ld in
+      yes*) LD="${LD-ld} -m elf64_sparc" ;;
+      *)
+	if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
+	  LD="${LD-ld} -64"
+	fi
+	;;
+      esac
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+esac
+
+need_locks="$enable_libtool_lock"
+])# _LT_ENABLE_LOCK
+
+
+# _LT_CMD_OLD_ARCHIVE
+# -------------------
+m4_defun([_LT_CMD_OLD_ARCHIVE],
+[AC_CHECK_TOOL(AR, ar, false)
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+_LT_DECL([], [AR], [1], [The archiver])
+_LT_DECL([], [AR_FLAGS], [1])
+
+AC_CHECK_TOOL(STRIP, strip, :)
+test -z "$STRIP" && STRIP=:
+_LT_DECL([], [STRIP], [1], [A symbol stripping program])
+
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+test -z "$RANLIB" && RANLIB=:
+_LT_DECL([], [RANLIB], [1],
+    [Commands used to install an old-style archive])
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+  case $host_os in
+  openbsd*)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
+    ;;
+  *)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
+    ;;
+  esac
+  old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+_LT_DECL([], [old_postinstall_cmds], [2])
+_LT_DECL([], [old_postuninstall_cmds], [2])
+_LT_TAGDECL([], [old_archive_cmds], [2],
+    [Commands used to build an old-style archive])
+])# _LT_CMD_OLD_ARCHIVE
+
+
+# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+#		[OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------------------
+# Check whether the given compiler option works
+AC_DEFUN([_LT_COMPILER_OPTION],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_CACHE_CHECK([$1], [$2],
+  [$2=no
+   m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$3"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&AS_MESSAGE_LOG_FD
+   echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       $2=yes
+     fi
+   fi
+   $RM conftest*
+])
+
+if test x"[$]$2" = xyes; then
+    m4_if([$5], , :, [$5])
+else
+    m4_if([$6], , :, [$6])
+fi
+])# _LT_COMPILER_OPTION
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], [])
+
+
+# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+#                  [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------
+# Check whether the given linker option works
+AC_DEFUN([_LT_LINKER_OPTION],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_CACHE_CHECK([$1], [$2],
+  [$2=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS $3"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&AS_MESSAGE_LOG_FD
+       $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         $2=yes
+       fi
+     else
+       $2=yes
+     fi
+   fi
+   $RM -r conftest*
+   LDFLAGS="$save_LDFLAGS"
+])
+
+if test x"[$]$2" = xyes; then
+    m4_if([$4], , :, [$4])
+else
+    m4_if([$5], , :, [$5])
+fi
+])# _LT_LINKER_OPTION
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], [])
+
+
+# LT_CMD_MAX_LEN
+#---------------
+AC_DEFUN([LT_CMD_MAX_LEN],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+# find the maximum length of command line arguments
+AC_MSG_CHECKING([the maximum length of command line arguments])
+AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
+  i=0
+  teststring="ABCD"
+
+  case $build_os in
+  msdosdjgpp*)
+    # On DJGPP, this test can blow up pretty badly due to problems in libc
+    # (any single argument exceeding 2000 bytes causes a buffer overrun
+    # during glob expansion).  Even if it were fixed, the result of this
+    # check would be larger than it should be.
+    lt_cv_sys_max_cmd_len=12288;    # 12K is about right
+    ;;
+
+  gnu*)
+    # Under GNU Hurd, this test is not required because there is
+    # no limit to the length of command line arguments.
+    # Libtool will interpret -1 as no limit whatsoever
+    lt_cv_sys_max_cmd_len=-1;
+    ;;
+
+  cygwin* | mingw*)
+    # On Win9x/ME, this test blows up -- it succeeds, but takes
+    # about 5 minutes as the teststring grows exponentially.
+    # Worse, since 9x/ME are not pre-emptively multitasking,
+    # you end up with a "frozen" computer, even though with patience
+    # the test eventually succeeds (with a max line length of 256k).
+    # Instead, let's just punt: use the minimum linelength reported by
+    # all of the supported platforms: 8192 (on NT/2K/XP).
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  amigaos*)
+    # On AmigaOS with pdksh, this test takes hours, literally.
+    # So we just punt and use a minimum line length of 8192.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+    # This has been around since 386BSD, at least.  Likely further.
+    if test -x /sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+    elif test -x /usr/sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+    else
+      lt_cv_sys_max_cmd_len=65536	# usable default for all BSDs
+    fi
+    # And add a safety zone
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    ;;
+
+  interix*)
+    # We know the value 262144 and hardcode it with a safety zone (like BSD)
+    lt_cv_sys_max_cmd_len=196608
+    ;;
+
+  osf*)
+    # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+    # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+    # nice to cause kernel panics so lets avoid the loop below.
+    # First set a reasonable default.
+    lt_cv_sys_max_cmd_len=16384
+    #
+    if test -x /sbin/sysconfig; then
+      case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+        *1*) lt_cv_sys_max_cmd_len=-1 ;;
+      esac
+    fi
+    ;;
+  sco3.2v5*)
+    lt_cv_sys_max_cmd_len=102400
+    ;;
+  sysv5* | sco5v6* | sysv4.2uw2*)
+    kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+    if test -n "$kargmax"; then
+      lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[	 ]]//'`
+    else
+      lt_cv_sys_max_cmd_len=32768
+    fi
+    ;;
+  *)
+    lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+    if test -n "$lt_cv_sys_max_cmd_len"; then
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    else
+      # Make teststring a little bigger before we do anything with it.
+      # a 1K string should be a reasonable start.
+      for i in 1 2 3 4 5 6 7 8 ; do
+        teststring=$teststring$teststring
+      done
+      SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+      # If test is not a shell built-in, we'll probably end up computing a
+      # maximum length that is only half of the actual maximum length, but
+      # we can't tell.
+      while { test "X"`$SHELL [$]0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \
+	         = "XX$teststring$teststring"; } >/dev/null 2>&1 &&
+	      test $i != 17 # 1/2 MB should be enough
+      do
+        i=`expr $i + 1`
+        teststring=$teststring$teststring
+      done
+      # Only check the string length outside the loop.
+      lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
+      teststring=
+      # Add a significant safety factor because C++ compilers can tack on
+      # massive amounts of additional arguments before passing them to the
+      # linker.  It appears as though 1/2 is a usable value.
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+    fi
+    ;;
+  esac
+])
+if test -n $lt_cv_sys_max_cmd_len ; then
+  AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
+else
+  AC_MSG_RESULT(none)
+fi
+max_cmd_len=$lt_cv_sys_max_cmd_len
+_LT_DECL([], [max_cmd_len], [0],
+    [What is the maximum length of a command?])
+])# LT_CMD_MAX_LEN
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], [])
+
+
+# _LT_HEADER_DLFCN
+# ----------------
+m4_defun([_LT_HEADER_DLFCN],
+[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl
+])# _LT_HEADER_DLFCN
+
+
+# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
+#                      ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
+# ----------------------------------------------------------------
+m4_defun([_LT_TRY_DLOPEN_SELF],
+[m4_require([_LT_HEADER_DLFCN])dnl
+if test "$cross_compiling" = yes; then :
+  [$4]
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<_LT_EOF
+[#line __oline__ "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL		RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL		DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL		0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW		RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW		DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW	RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW	DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW	0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+    exit (status);
+}]
+_LT_EOF
+  if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) $1 ;;
+      x$lt_dlneed_uscore) $2 ;;
+      x$lt_dlunknown|x*) $3 ;;
+    esac
+  else :
+    # compilation failed
+    $3
+  fi
+fi
+rm -fr conftest*
+])# _LT_TRY_DLOPEN_SELF
+
+
+# LT_SYS_DLOPEN_SELF
+# ------------------
+AC_DEFUN([LT_SYS_DLOPEN_SELF],
+[m4_require([_LT_HEADER_DLFCN])dnl
+if test "x$enable_dlopen" != xyes; then
+  enable_dlopen=unknown
+  enable_dlopen_self=unknown
+  enable_dlopen_self_static=unknown
+else
+  lt_cv_dlopen=no
+  lt_cv_dlopen_libs=
+
+  case $host_os in
+  beos*)
+    lt_cv_dlopen="load_add_on"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ;;
+
+  mingw* | pw32*)
+    lt_cv_dlopen="LoadLibrary"
+    lt_cv_dlopen_libs=
+    ;;
+
+  cygwin*)
+    lt_cv_dlopen="dlopen"
+    lt_cv_dlopen_libs=
+    ;;
+
+  darwin*)
+  # if libdl is installed we need to link against it
+    AC_CHECK_LIB([dl], [dlopen],
+		[lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[
+    lt_cv_dlopen="dyld"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ])
+    ;;
+
+  *)
+    AC_CHECK_FUNC([shl_load],
+	  [lt_cv_dlopen="shl_load"],
+      [AC_CHECK_LIB([dld], [shl_load],
+	    [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"],
+	[AC_CHECK_FUNC([dlopen],
+	      [lt_cv_dlopen="dlopen"],
+	  [AC_CHECK_LIB([dl], [dlopen],
+		[lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],
+	    [AC_CHECK_LIB([svld], [dlopen],
+		  [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"],
+	      [AC_CHECK_LIB([dld], [dld_link],
+		    [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"])
+	      ])
+	    ])
+	  ])
+	])
+      ])
+    ;;
+  esac
+
+  if test "x$lt_cv_dlopen" != xno; then
+    enable_dlopen=yes
+  else
+    enable_dlopen=no
+  fi
+
+  case $lt_cv_dlopen in
+  dlopen)
+    save_CPPFLAGS="$CPPFLAGS"
+    test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+    save_LDFLAGS="$LDFLAGS"
+    wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+    save_LIBS="$LIBS"
+    LIBS="$lt_cv_dlopen_libs $LIBS"
+
+    AC_CACHE_CHECK([whether a program can dlopen itself],
+	  lt_cv_dlopen_self, [dnl
+	  _LT_TRY_DLOPEN_SELF(
+	    lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
+	    lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
+    ])
+
+    if test "x$lt_cv_dlopen_self" = xyes; then
+      wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+      AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
+	  lt_cv_dlopen_self_static, [dnl
+	  _LT_TRY_DLOPEN_SELF(
+	    lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
+	    lt_cv_dlopen_self_static=no,  lt_cv_dlopen_self_static=cross)
+      ])
+    fi
+
+    CPPFLAGS="$save_CPPFLAGS"
+    LDFLAGS="$save_LDFLAGS"
+    LIBS="$save_LIBS"
+    ;;
+  esac
+
+  case $lt_cv_dlopen_self in
+  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+  *) enable_dlopen_self=unknown ;;
+  esac
+
+  case $lt_cv_dlopen_self_static in
+  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+  *) enable_dlopen_self_static=unknown ;;
+  esac
+fi
+_LT_DECL([dlopen_support], [enable_dlopen], [0],
+	 [Whether dlopen is supported])
+_LT_DECL([dlopen_self], [enable_dlopen_self], [0],
+	 [Whether dlopen of programs is supported])
+_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0],
+	 [Whether dlopen of statically linked programs is supported])
+])# LT_SYS_DLOPEN_SELF
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], [])
+
+
+# _LT_COMPILER_C_O([TAGNAME])
+# ---------------------------
+# Check to see if options -c and -o are simultaneously supported by compiler.
+# This macro does not hard code the compiler like AC_PROG_CC_C_O.
+m4_defun([_LT_COMPILER_C_O],
+[m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
+  [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
+  [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&AS_MESSAGE_LOG_FD
+   echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+     fi
+   fi
+   chmod u+w . 2>&AS_MESSAGE_LOG_FD
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+])
+_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1],
+	[Does compiler simultaneously support -c and -o options?])
+])# _LT_COMPILER_C_O
+
+
+# _LT_COMPILER_FILE_LOCKS([TAGNAME])
+# ----------------------------------
+# Check to see if we can do hard links to lock some files if needed
+m4_defun([_LT_COMPILER_FILE_LOCKS],
+[m4_require([_LT_ENABLE_LOCK])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+_LT_COMPILER_C_O([$1])
+
+hard_links="nottested"
+if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  AC_MSG_CHECKING([if we can lock with hard links])
+  hard_links=yes
+  $RM conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  AC_MSG_RESULT([$hard_links])
+  if test "$hard_links" = no; then
+    AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe])
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?])
+])# _LT_COMPILER_FILE_LOCKS
+
+
+# _LT_CHECK_OBJDIR
+# ----------------
+m4_defun([_LT_CHECK_OBJDIR],
+[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
+[rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+  lt_cv_objdir=.libs
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null])
+objdir=$lt_cv_objdir
+_LT_DECL([], [objdir], [0],
+         [The name of the directory that contains temporary libtool files])dnl
+m4_pattern_allow([LT_OBJDIR])dnl
+AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/",
+  [Define to the sub-directory in which libtool stores uninstalled libraries.])
+])# _LT_CHECK_OBJDIR
+
+
+# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME])
+# --------------------------------------
+# Check hardcoding attributes.
+m4_defun([_LT_LINKER_HARDCODE_LIBPATH],
+[AC_MSG_CHECKING([how to hardcode library paths into programs])
+_LT_TAGVAR(hardcode_action, $1)=
+if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" ||
+   test -n "$_LT_TAGVAR(runpath_var, $1)" ||
+   test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then
+
+  # We can hardcode non-existent directories.
+  if test "$_LT_TAGVAR(hardcode_direct, $1)" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no &&
+     test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then
+    # Linking always hardcodes the temporary library directory.
+    _LT_TAGVAR(hardcode_action, $1)=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    _LT_TAGVAR(hardcode_action, $1)=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  _LT_TAGVAR(hardcode_action, $1)=unsupported
+fi
+AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)])
+
+if test "$_LT_TAGVAR(hardcode_action, $1)" = relink ||
+   test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+_LT_TAGDECL([], [hardcode_action], [0],
+    [How to hardcode a shared library path into an executable])
+])# _LT_LINKER_HARDCODE_LIBPATH
+
+
+# _LT_CMD_STRIPLIB
+# ----------------
+m4_defun([_LT_CMD_STRIPLIB],
+[m4_require([_LT_DECL_EGREP])
+striplib=
+old_striplib=
+AC_MSG_CHECKING([whether stripping libraries is possible])
+if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+  AC_MSG_RESULT([yes])
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+  case $host_os in
+  darwin*)
+    if test -n "$STRIP" ; then
+      striplib="$STRIP -x"
+      old_striplib="$STRIP -S"
+      AC_MSG_RESULT([yes])
+    else
+      AC_MSG_RESULT([no])
+    fi
+    ;;
+  *)
+    AC_MSG_RESULT([no])
+    ;;
+  esac
+fi
+_LT_DECL([], [old_striplib], [1], [Commands to strip libraries])
+_LT_DECL([], [striplib], [1])
+])# _LT_CMD_STRIPLIB
+
+
+# _LT_SYS_DYNAMIC_LINKER([TAG])
+# -----------------------------
+# PORTME Fill in your ld.so characteristics
+m4_defun([_LT_SYS_DYNAMIC_LINKER],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_MSG_CHECKING([dynamic linker characteristics])
+m4_if([$1],
+	[], [
+if test "$GCC" = yes; then
+  case $host_os in
+    darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
+    *) lt_awk_arg="/^libraries:/" ;;
+  esac
+  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+  if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then
+    # if the path contains ";" then we assume it to be the separator
+    # otherwise default to the standard path separator (i.e. ":") - it is
+    # assumed that no part of a normal pathname contains ";" but that should
+    # okay in the real world where ";" in dirpaths is itself problematic.
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'`
+  else
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
+  fi
+  # Ok, now we have the path, separated by spaces, we can step through it
+  # and add multilib dir if necessary.
+  lt_tmp_lt_search_path_spec=
+  lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+  for lt_sys_path in $lt_search_path_spec; do
+    if test -d "$lt_sys_path/$lt_multi_os_dir"; then
+      lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
+    else
+      test -d "$lt_sys_path" && \
+	lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+    fi
+  done
+  lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk '
+BEGIN {RS=" "; FS="/|\n";} {
+  lt_foo="";
+  lt_count=0;
+  for (lt_i = NF; lt_i > 0; lt_i--) {
+    if ($lt_i != "" && $lt_i != ".") {
+      if ($lt_i == "..") {
+        lt_count++;
+      } else {
+        if (lt_count == 0) {
+          lt_foo="/" $lt_i lt_foo;
+        } else {
+          lt_count--;
+        }
+      }
+    }
+  }
+  if (lt_foo != "") { lt_freq[[lt_foo]]++; }
+  if (lt_freq[[lt_foo]] == 1) { print lt_foo; }
+}'`
+  sys_lib_search_path_spec=`$ECHO $lt_search_path_spec`
+else
+  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi])
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX 3 has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}${shared_ext}$major'
+  ;;
+
+aix[[4-9]]*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  hardcode_into_libs=yes
+  if test "$host_cpu" = ia64; then
+    # AIX 5 supports IA64
+    library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line `#! .'.  This would cause the generated library to
+    # depend on `.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[[01]] | aix4.[[01]].*)
+      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+	   echo ' yes '
+	   echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then
+	:
+      else
+	can_build_shared=no
+      fi
+      ;;
+    esac
+    # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+    # soname into executable. Probably we can add versioning support to
+    # collect2, so additional links can be useful in future.
+    if test "$aix_use_runtimelinking" = yes; then
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    else
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='${libname}${release}.a $libname.a'
+      soname_spec='${libname}${release}${shared_ext}$major'
+    fi
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  case $host_cpu in
+  powerpc)
+    # Since July 2007 AmigaOS4 officially supports .so libraries.
+    # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    ;;
+  m68k)
+    library_names_spec='$libname.ixlibrary $libname.a'
+    # Create ${libname}_ixlibrary.a entries in /sys/libs.
+    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+    ;;
+  esac
+  ;;
+
+beos*)
+  library_names_spec='${libname}${shared_ext}'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi[[45]]*)
+  version_type=linux
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32*)
+  version_type=windows
+  shrext_cmds=".dll"
+  need_version=no
+  need_lib_prefix=no
+
+  case $GCC,$host_os in
+  yes,cygwin* | yes,mingw* | yes,pw32*)
+    library_names_spec='$libname.dll.a'
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname~
+      if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+        eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+      fi'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+
+    case $host_os in
+    cygwin*)
+      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+      soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+      ;;
+    mingw*)
+      # MinGW DLLs use traditional 'lib' prefix
+      soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+      if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then
+        # It is most probably a Windows format PATH printed by
+        # mingw gcc, but we are running on Cygwin. Gcc prints its search
+        # path with ; separators, and with drive letters. We can handle the
+        # drive letters (cygwin fileutils understands them), so leave them,
+        # especially as we might pass files found there to a mingw objdump,
+        # which wouldn't understand a cygwinified path. Ahh.
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+      else
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
+      fi
+      ;;
+    pw32*)
+      # pw32 DLLs use 'pw' prefix rather than 'lib'
+      library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    esac
+    ;;
+
+  *)
+    library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib'
+    ;;
+  esac
+  dynamic_linker='Win32 ld.exe'
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+  soname_spec='${libname}${release}${major}$shared_ext'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+m4_if([$1], [],[
+  sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"])
+  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+  ;;
+
+dgux*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+freebsd1*)
+  dynamic_linker=no
+  ;;
+
+freebsd* | dragonfly*)
+  # DragonFly does not have aout.  When/if they implement a new
+  # versioning mechanism, adjust this.
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[[123]]*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  freebsd3.[[01]]* | freebsdelf3.[[01]]*)
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \
+  freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  *) # from 4.6 on, and DragonFly
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  case $host_cpu in
+  ia64*)
+    shrext_cmds='.so'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.so"
+    shlibpath_var=LD_LIBRARY_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    if test "X$HPUX_IA64_MODE" = X32; then
+      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+    else
+      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+    fi
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  hppa*64*)
+    shrext_cmds='.sl'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  *)
+    shrext_cmds='.sl'
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=SHLIB_PATH
+    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    ;;
+  esac
+  # HP-UX runs *really* slowly unless shared libraries are mode 555.
+  postinstall_cmds='chmod 555 $lib'
+  ;;
+
+interix[[3-9]]*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)
+	if test "$lt_cv_prog_gnu_ld" = yes; then
+		version_type=linux
+	else
+		version_type=irix
+	fi ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+      libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+      libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  hardcode_into_libs=yes
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+  dynamic_linker=no
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  # Some binutils ld are patched to set DT_RUNPATH
+  save_LDFLAGS=$LDFLAGS
+  save_libdir=$libdir
+  eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \
+       LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\""
+  AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+    [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null],
+       [shlibpath_overrides_runpath=yes])])
+  LDFLAGS=$save_LDFLAGS
+  libdir=$save_libdir
+
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # Append ld.so.conf contents to the search path
+  if test -f /etc/ld.so.conf; then
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+  fi
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+*nto* | *qnx*)
+  version_type=qnx
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='ldqnx.so'
+  ;;
+
+openbsd*)
+  version_type=sunos
+  sys_lib_dlsearch_path_spec="/usr/lib"
+  need_lib_prefix=no
+  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+  case $host_os in
+    openbsd3.3 | openbsd3.3.*)	need_version=yes ;;
+    *)				need_version=no  ;;
+  esac
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    case $host_os in
+      openbsd2.[[89]] | openbsd2.[[89]].*)
+	shlibpath_overrides_runpath=no
+	;;
+      *)
+	shlibpath_overrides_runpath=yes
+	;;
+      esac
+  else
+    shlibpath_overrides_runpath=yes
+  fi
+  ;;
+
+os2*)
+  libname_spec='$name'
+  shrext_cmds=".dll"
+  need_lib_prefix=no
+  library_names_spec='$libname${shared_ext} $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+rdos*)
+  dynamic_linker=no
+  ;;
+
+solaris*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux
+    library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+    soname_spec='$libname${shared_ext}.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  version_type=freebsd-elf
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  if test "$with_gnu_ld" = yes; then
+    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+  else
+    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+    case $host_os in
+      sco3.2v5*)
+        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+	;;
+    esac
+  fi
+  sys_lib_dlsearch_path_spec='/usr/lib'
+  ;;
+
+tpf*)
+  # TPF is a cross-target only.  Preferred cross-host = GNU/Linux.
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_name_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+uts4*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+AC_MSG_RESULT([$dynamic_linker])
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+ 
+if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
+  sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
+fi
+if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
+  sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
+fi
+
+_LT_DECL([], [variables_saved_for_relink], [1],
+    [Variables whose values should be saved in libtool wrapper scripts and
+    restored at link time])
+_LT_DECL([], [need_lib_prefix], [0],
+    [Do we need the "lib" prefix for modules?])
+_LT_DECL([], [need_version], [0], [Do we need a version for libraries?])
+_LT_DECL([], [version_type], [0], [Library versioning type])
+_LT_DECL([], [runpath_var], [0],  [Shared library runtime path variable])
+_LT_DECL([], [shlibpath_var], [0],[Shared library path variable])
+_LT_DECL([], [shlibpath_overrides_runpath], [0],
+    [Is shlibpath searched before the hard-coded library search path?])
+_LT_DECL([], [libname_spec], [1], [Format of library name prefix])
+_LT_DECL([], [library_names_spec], [1],
+    [[List of archive names.  First name is the real one, the rest are links.
+    The last name is the one that the linker finds with -lNAME]])
+_LT_DECL([], [soname_spec], [1],
+    [[The coded name of the library, if different from the real name]])
+_LT_DECL([], [postinstall_cmds], [2],
+    [Command to use after installation of a shared archive])
+_LT_DECL([], [postuninstall_cmds], [2],
+    [Command to use after uninstallation of a shared archive])
+_LT_DECL([], [finish_cmds], [2],
+    [Commands used to finish a libtool library installation in a directory])
+_LT_DECL([], [finish_eval], [1],
+    [[As "finish_cmds", except a single script fragment to be evaled but
+    not shown]])
+_LT_DECL([], [hardcode_into_libs], [0],
+    [Whether we should hardcode library paths into libraries])
+_LT_DECL([], [sys_lib_search_path_spec], [2],
+    [Compile-time system search path for libraries])
+_LT_DECL([], [sys_lib_dlsearch_path_spec], [2],
+    [Run-time system search path for libraries])
+])# _LT_SYS_DYNAMIC_LINKER
+
+
+# _LT_PATH_TOOL_PREFIX(TOOL)
+# --------------------------
+# find a file program which can recognize shared library
+AC_DEFUN([_LT_PATH_TOOL_PREFIX],
+[m4_require([_LT_DECL_EGREP])dnl
+AC_MSG_CHECKING([for $1])
+AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
+[case $MAGIC_CMD in
+[[\\/*] |  ?:[\\/]*])
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD="$MAGIC_CMD"
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+dnl $ac_dummy forces splitting on constant user-supplied paths.
+dnl POSIX.2 word splitting is done only on the output of word expansions,
+dnl not every word.  This closes a longstanding sh security hole.
+  ac_dummy="m4_if([$2], , $PATH, [$2])"
+  for ac_dir in $ac_dummy; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$1; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/$1"
+      if test -n "$file_magic_test_file"; then
+	case $deplibs_check_method in
+	"file_magic "*)
+	  file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+	  MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+	    $EGREP "$file_magic_regex" > /dev/null; then
+	    :
+	  else
+	    cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+	  fi ;;
+	esac
+      fi
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+  MAGIC_CMD="$lt_save_MAGIC_CMD"
+  ;;
+esac])
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  AC_MSG_RESULT($MAGIC_CMD)
+else
+  AC_MSG_RESULT(no)
+fi
+_LT_DECL([], [MAGIC_CMD], [0],
+	 [Used to examine libraries when file_magic_cmd begins with "file"])dnl
+])# _LT_PATH_TOOL_PREFIX
+
+# Old name:
+AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], [])
+
+
+# _LT_PATH_MAGIC
+# --------------
+# find a file program which can recognize a shared library
+m4_defun([_LT_PATH_MAGIC],
+[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+  if test -n "$ac_tool_prefix"; then
+    _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
+  else
+    MAGIC_CMD=:
+  fi
+fi
+])# _LT_PATH_MAGIC
+
+
+# LT_PATH_LD
+# ----------
+# find the pathname to the GNU or non-GNU linker
+AC_DEFUN([LT_PATH_LD],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_DECL_EGREP])dnl
+
+AC_ARG_WITH([gnu-ld],
+    [AS_HELP_STRING([--with-gnu-ld],
+	[assume the C compiler uses GNU ld @<:@default=no@:>@])],
+    [test "$withval" = no || with_gnu_ld=yes],
+    [with_gnu_ld=no])dnl
+
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  AC_MSG_CHECKING([for ld used by $CC])
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [[\\/]]* | ?:[[\\/]]*)
+      re_direlt='/[[^/]][[^/]]*/\.\./'
+      # Canonicalize the pathname of ld
+      ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+      while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+	ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  AC_MSG_CHECKING([for GNU ld])
+else
+  AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(lt_cv_path_LD,
+[if test -z "$LD"; then
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some variants of GNU ld only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+      *GNU* | *'with BFD'*)
+	test "$with_gnu_ld" != no && break
+	;;
+      *)
+	test "$with_gnu_ld" != yes && break
+	;;
+      esac
+    fi
+  done
+  IFS="$lt_save_ifs"
+else
+  lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+  AC_MSG_RESULT($LD)
+else
+  AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+_LT_PATH_LD_GNU
+AC_SUBST([LD])
+
+_LT_TAGDECL([], [LD], [1], [The linker used to build libraries])
+])# LT_PATH_LD
+
+# Old names:
+AU_ALIAS([AM_PROG_LD], [LT_PATH_LD])
+AU_ALIAS([AC_PROG_LD], [LT_PATH_LD])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_PROG_LD], [])
+dnl AC_DEFUN([AC_PROG_LD], [])
+
+
+# _LT_PATH_LD_GNU
+#- --------------
+m4_defun([_LT_PATH_LD_GNU],
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+  lt_cv_prog_gnu_ld=yes
+  ;;
+*)
+  lt_cv_prog_gnu_ld=no
+  ;;
+esac])
+with_gnu_ld=$lt_cv_prog_gnu_ld
+])# _LT_PATH_LD_GNU
+
+
+# _LT_CMD_RELOAD
+# --------------
+# find reload flag for linker
+#   -- PORTME Some linkers may need a different reload flag.
+m4_defun([_LT_CMD_RELOAD],
+[AC_CACHE_CHECK([for $LD option to reload object files],
+  lt_cv_ld_reload_flag,
+  [lt_cv_ld_reload_flag='-r'])
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+  darwin*)
+    if test "$GCC" = yes; then
+      reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+    else
+      reload_cmds='$LD$reload_flag -o $output$reload_objs'
+    fi
+    ;;
+esac
+_LT_DECL([], [reload_flag], [1], [How to create reloadable object files])dnl
+_LT_DECL([], [reload_cmds], [2])dnl
+])# _LT_CMD_RELOAD
+
+
+# _LT_CHECK_MAGIC_METHOD
+# ----------------------
+# how to check for library dependencies
+#  -- PORTME fill in with the dynamic library characteristics
+m4_defun([_LT_CHECK_MAGIC_METHOD],
+[m4_require([_LT_DECL_EGREP])
+AC_CACHE_CHECK([how to recognize dependent libraries],
+lt_cv_deplibs_check_method,
+[lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix[[4-9]]*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+beos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+bsdi[[45]]*)
+  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
+  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  ;;
+
+cygwin*)
+  # func_win32_libid is a shell function defined in ltmain.sh
+  lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+  lt_cv_file_magic_cmd='func_win32_libid'
+  ;;
+
+mingw* | pw32*)
+  # Base MSYS/MinGW do not provide the 'file' command needed by
+  # func_win32_libid shell function, so use a weaker test based on 'objdump',
+  # unless we find 'file', for example because we are cross-compiling.
+  if ( file / ) >/dev/null 2>&1; then
+    lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+    lt_cv_file_magic_cmd='func_win32_libid'
+  else
+    lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+    lt_cv_file_magic_cmd='$OBJDUMP -f'
+  fi
+  ;;
+
+darwin* | rhapsody*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+freebsd* | dragonfly*)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    case $host_cpu in
+    i*86 )
+      # Not sure whether the presence of OpenBSD here was a mistake.
+      # Let's accept both of them until this is cleared up.
+      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
+      lt_cv_file_magic_cmd=/usr/bin/file
+      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+      ;;
+    esac
+  else
+    lt_cv_deplibs_check_method=pass_all
+  fi
+  ;;
+
+gnu*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+hpux10.20* | hpux11*)
+  lt_cv_file_magic_cmd=/usr/bin/file
+  case $host_cpu in
+  ia64*)
+    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
+    lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+    ;;
+  hppa*64*)
+    [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]']
+    lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+    ;;
+  *)
+    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library'
+    lt_cv_file_magic_test_file=/usr/lib/libc.sl
+    ;;
+  esac
+  ;;
+
+interix[[3-9]]*)
+  # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+  lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$'
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $LD in
+  *-32|*"-32 ") libmagic=32-bit;;
+  *-n32|*"-n32 ") libmagic=N32;;
+  *-64|*"-64 ") libmagic=64-bit;;
+  *) libmagic=never-match;;
+  esac
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+netbsd*)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
+  fi
+  ;;
+
+newos6*)
+  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=/usr/lib/libnls.so
+  ;;
+
+*nto* | *qnx*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+openbsd*)
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+  fi
+  ;;
+
+osf3* | osf4* | osf5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+rdos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+solaris*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv4 | sysv4.3*)
+  case $host_vendor in
+  motorola)
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
+    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+    ;;
+  ncr)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  sequent)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
+    ;;
+  sni)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
+    lt_cv_file_magic_test_file=/lib/libc.so
+    ;;
+  siemens)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  pc)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  esac
+  ;;
+
+tpf*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+esac
+])
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+_LT_DECL([], [deplibs_check_method], [1],
+    [Method to check whether dependent libraries are shared objects])
+_LT_DECL([], [file_magic_cmd], [1],
+    [Command to use when deplibs_check_method == "file_magic"])
+])# _LT_CHECK_MAGIC_METHOD
+
+
+# LT_PATH_NM
+# ----------
+# find the pathname to a BSD- or MS-compatible name lister
+AC_DEFUN([LT_PATH_NM],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM,
+[if test -n "$NM"; then
+  # Let the user override the test.
+  lt_cv_path_NM="$NM"
+else
+  lt_nm_to_check="${ac_tool_prefix}nm"
+  if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+    lt_nm_to_check="$lt_nm_to_check nm"
+  fi
+  for lt_tmp_nm in $lt_nm_to_check; do
+    lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+    for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+      IFS="$lt_save_ifs"
+      test -z "$ac_dir" && ac_dir=.
+      tmp_nm="$ac_dir/$lt_tmp_nm"
+      if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+	# Check to see if the nm accepts a BSD-compat flag.
+	# Adding the `sed 1q' prevents false positives on HP-UX, which says:
+	#   nm: unknown option "B" ignored
+	# Tru64's nm complains that /dev/null is an invalid object file
+	case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+	*/dev/null* | *'Invalid file or object type'*)
+	  lt_cv_path_NM="$tmp_nm -B"
+	  break
+	  ;;
+	*)
+	  case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+	  */dev/null*)
+	    lt_cv_path_NM="$tmp_nm -p"
+	    break
+	    ;;
+	  *)
+	    lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+	    continue # so that we can try to find one that supports BSD flags
+	    ;;
+	  esac
+	  ;;
+	esac
+      fi
+    done
+    IFS="$lt_save_ifs"
+  done
+  : ${lt_cv_path_NM=no}
+fi])
+if test "$lt_cv_path_NM" != "no"; then
+  NM="$lt_cv_path_NM"
+else
+  # Didn't find any BSD compatible name lister, look for dumpbin.
+  AC_CHECK_TOOLS(DUMPBIN, ["dumpbin -symbols" "link -dump -symbols"], :)
+  AC_SUBST([DUMPBIN])
+  if test "$DUMPBIN" != ":"; then
+    NM="$DUMPBIN"
+  fi
+fi
+test -z "$NM" && NM=nm
+AC_SUBST([NM])
+_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl
+
+AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface],
+  [lt_cv_nm_interface="BSD nm"
+  echo "int some_variable = 0;" > conftest.$ac_ext
+  (eval echo "\"\$as_me:__oline__: $ac_compile\"" >&AS_MESSAGE_LOG_FD)
+  (eval "$ac_compile" 2>conftest.err)
+  cat conftest.err >&AS_MESSAGE_LOG_FD
+  (eval echo "\"\$as_me:__oline__: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD)
+  (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
+  cat conftest.err >&AS_MESSAGE_LOG_FD
+  (eval echo "\"\$as_me:__oline__: output\"" >&AS_MESSAGE_LOG_FD)
+  cat conftest.out >&AS_MESSAGE_LOG_FD
+  if $GREP 'External.*some_variable' conftest.out > /dev/null; then
+    lt_cv_nm_interface="MS dumpbin"
+  fi
+  rm -f conftest*])
+])# LT_PATH_NM
+
+# Old names:
+AU_ALIAS([AM_PROG_NM], [LT_PATH_NM])
+AU_ALIAS([AC_PROG_NM], [LT_PATH_NM])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_PROG_NM], [])
+dnl AC_DEFUN([AC_PROG_NM], [])
+
+
+# LT_LIB_M
+# --------
+# check for math library
+AC_DEFUN([LT_LIB_M],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+LIBM=
+case $host in
+*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*)
+  # These system don't have libm, or don't need it
+  ;;
+*-ncr-sysv4.3*)
+  AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
+  AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
+  ;;
+*)
+  AC_CHECK_LIB(m, cos, LIBM="-lm")
+  ;;
+esac
+AC_SUBST([LIBM])
+])# LT_LIB_M
+
+# Old name:
+AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_CHECK_LIBM], [])
+
+
+# _LT_COMPILER_NO_RTTI([TAGNAME])
+# -------------------------------
+m4_defun([_LT_COMPILER_NO_RTTI],
+[m4_require([_LT_TAG_COMPILER])dnl
+
+_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+
+if test "$GCC" = yes; then
+  _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+
+  _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
+    lt_cv_prog_compiler_rtti_exceptions,
+    [-fno-rtti -fno-exceptions], [],
+    [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
+fi
+_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1],
+	[Compiler flag to turn off builtin functions])
+])# _LT_COMPILER_NO_RTTI
+
+
+# _LT_CMD_GLOBAL_SYMBOLS
+# ----------------------
+m4_defun([_LT_CMD_GLOBAL_SYMBOLS],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+AC_REQUIRE([LT_PATH_LD])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+AC_MSG_CHECKING([command to parse $NM output from $compiler object])
+AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
+[
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[[BCDEGRST]]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+  symcode='[[BCDT]]'
+  ;;
+cygwin* | mingw* | pw32*)
+  symcode='[[ABCDGISTW]]'
+  ;;
+hpux*)
+  if test "$host_cpu" = ia64; then
+    symcode='[[ABCDEGRST]]'
+  fi
+  ;;
+irix* | nonstopux*)
+  symcode='[[BCDEGRST]]'
+  ;;
+osf*)
+  symcode='[[BCDEGQRST]]'
+  ;;
+solaris*)
+  symcode='[[BDRT]]'
+  ;;
+sco3.2v5*)
+  symcode='[[DT]]'
+  ;;
+sysv4.2uw2*)
+  symcode='[[DT]]'
+  ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+  symcode='[[ABDT]]'
+  ;;
+sysv4)
+  symcode='[[DFNSTU]]'
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+  symcode='[[ABCDGIRSTW]]' ;;
+esac
+
+# Transform an extracted symbol line into a proper C declaration.
+# Some systems (esp. on ia64) link data and code symbols differently,
+# so use this general approach.
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/  {\"\2\", (void *) \&\2},/p'"
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\) $/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/  {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/  {\"lib\2\", (void *) \&\2},/p'"
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+  opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+  ;;
+esac
+
+# Try without a prefix underscore, then with it.
+for ac_symprfx in "" "_"; do
+
+  # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+  symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+  # Write the raw and C identifiers.
+  if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+    # Fake it for dumpbin and say T for any non-static function
+    # and D for any global variable.
+    # Also find C++ and __fastcall symbols from MSVC++,
+    # which start with @ or ?.
+    lt_cv_sys_global_symbol_pipe="$AWK ['"\
+"     {last_section=section; section=\$ 3};"\
+"     /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+"     \$ 0!~/External *\|/{next};"\
+"     / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+"     {if(hide[section]) next};"\
+"     {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\
+"     {split(\$ 0, a, /\||\r/); split(a[2], s)};"\
+"     s[1]~/^[@?]/{print s[1], s[1]; next};"\
+"     s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\
+"     ' prfx=^$ac_symprfx]"
+  else
+    lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[	 ]]\($symcode$symcode*\)[[	 ]][[	 ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+  fi
+
+  # Check to see that the pipe works correctly.
+  pipe_works=no
+
+  rm -f conftest*
+  cat > conftest.$ac_ext <<_LT_EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(void);
+void nm_test_func(void){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+_LT_EOF
+
+  if AC_TRY_EVAL(ac_compile); then
+    # Now try to grab the symbols.
+    nlist=conftest.nm
+    if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then
+      # Try sorting and uniquifying the output.
+      if sort "$nlist" | uniq > "$nlist"T; then
+	mv -f "$nlist"T "$nlist"
+      else
+	rm -f "$nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
+	if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+	  cat <<_LT_EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_LT_EOF
+	  # Now generate the symbol file.
+	  eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
+
+	  cat <<_LT_EOF >> conftest.$ac_ext
+
+/* The mapping between symbol names and symbols.  */
+const struct {
+  const char *name;
+  void       *address;
+}
+lt__PROGRAM__LTX_preloaded_symbols[[]] =
+{
+  { "@PROGRAM@", (void *) 0 },
+_LT_EOF
+	  $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/  {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
+	  cat <<\_LT_EOF >> conftest.$ac_ext
+  {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt__PROGRAM__LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+_LT_EOF
+	  # Now try linking the two files.
+	  mv conftest.$ac_objext conftstm.$ac_objext
+	  lt_save_LIBS="$LIBS"
+	  lt_save_CFLAGS="$CFLAGS"
+	  LIBS="conftstm.$ac_objext"
+	  CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
+	  if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then
+	    pipe_works=yes
+	  fi
+	  LIBS="$lt_save_LIBS"
+	  CFLAGS="$lt_save_CFLAGS"
+	else
+	  echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
+	fi
+      else
+	echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
+      fi
+    else
+      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
+    fi
+  else
+    echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
+    cat conftest.$ac_ext >&5
+  fi
+  rm -rf conftest* conftst*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test "$pipe_works" = yes; then
+    break
+  else
+    lt_cv_sys_global_symbol_pipe=
+  fi
+done
+])
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+  lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+  AC_MSG_RESULT(failed)
+else
+  AC_MSG_RESULT(ok)
+fi
+
+_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1],
+    [Take the output of nm and produce a listing of raw symbols and C names])
+_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1],
+    [Transform the output of nm in a proper C declaration])
+_LT_DECL([global_symbol_to_c_name_address],
+    [lt_cv_sys_global_symbol_to_c_name_address], [1],
+    [Transform the output of nm in a C name address pair])
+_LT_DECL([global_symbol_to_c_name_address_lib_prefix],
+    [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1],
+    [Transform the output of nm in a C name address pair when lib prefix is needed])
+]) # _LT_CMD_GLOBAL_SYMBOLS
+
+
+# _LT_COMPILER_PIC([TAGNAME])
+# ---------------------------
+m4_defun([_LT_COMPILER_PIC],
+[m4_require([_LT_TAG_COMPILER])dnl
+_LT_TAGVAR(lt_prog_compiler_wl, $1)=
+_LT_TAGVAR(lt_prog_compiler_pic, $1)=
+_LT_TAGVAR(lt_prog_compiler_static, $1)=
+
+AC_MSG_CHECKING([for $compiler option to produce PIC])
+m4_if([$1], [CXX], [
+  # C++ specific cases for pic, static, wl, etc.
+  if test "$GXX" = yes; then
+    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+    case $host_os in
+    aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+	# AIX 5 now supports IA64 processor
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+        ;;
+      m68k)
+            # FIXME: we need at least 68020 code to build shared libraries, but
+            # adding the `-m68020' flag to GCC prevents building anything better,
+            # like `-m68040'.
+            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+        ;;
+      esac
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+    mingw* | cygwin* | os2* | pw32*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      m4_if([$1], [GCJ], [],
+	[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+      ;;
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+      ;;
+    *djgpp*)
+      # DJGPP does not support shared libraries at all
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+      ;;
+    interix[[3-9]]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+      fi
+      ;;
+    hpux*)
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+	;;
+      *)
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+	;;
+      esac
+      ;;
+    *qnx* | *nto*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+      ;;
+    *)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+      ;;
+    esac
+  else
+    case $host_os in
+      aix[[4-9]]*)
+	# All AIX code is PIC.
+	if test "$host_cpu" = ia64; then
+	  # AIX 5 now supports IA64 processor
+	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	else
+	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+	fi
+	;;
+      chorus*)
+	case $cc_basename in
+	cxch68*)
+	  # Green Hills C++ Compiler
+	  # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+	  ;;
+	esac
+	;;
+      dgux*)
+	case $cc_basename in
+	  ec++*)
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	    ;;
+	  ghcx*)
+	    # Green Hills C++ Compiler
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      freebsd* | dragonfly*)
+	# FreeBSD uses GNU C++
+	;;
+      hpux9* | hpux10* | hpux11*)
+	case $cc_basename in
+	  CC*)
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+	    if test "$host_cpu" != ia64; then
+	      _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+	    fi
+	    ;;
+	  aCC*)
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+	    case $host_cpu in
+	    hppa*64*|ia64*)
+	      # +Z the default
+	      ;;
+	    *)
+	      _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+	      ;;
+	    esac
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      interix*)
+	# This is c89, which is MS Visual C++ (no shared libs)
+	# Anyone wants to do a port?
+	;;
+      irix5* | irix6* | nonstopux*)
+	case $cc_basename in
+	  CC*)
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+	    # CC pic flag -KPIC is the default.
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      linux* | k*bsd*-gnu)
+	case $cc_basename in
+	  KCC*)
+	    # KAI C++ Compiler
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+	    ;;
+	  icpc* | ecpc* )
+	    # Intel C++
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+	    ;;
+	  pgCC* | pgcpp*)
+	    # Portland Group C++ compiler
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	    ;;
+	  cxx*)
+	    # Compaq C++
+	    # Make sure the PIC flag is empty.  It appears that all Alpha
+	    # Linux and Compaq Tru64 Unix objects are PIC.
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+	    ;;
+	  xlc* | xlC*)
+	    # IBM XL 8.0 on PPC
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
+	    ;;
+	  *)
+	    case `$CC -V 2>&1 | sed 5q` in
+	    *Sun\ C*)
+	      # Sun C++ 5.9
+	      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+	      ;;
+	    esac
+	    ;;
+	esac
+	;;
+      lynxos*)
+	;;
+      m88k*)
+	;;
+      mvs*)
+	case $cc_basename in
+	  cxx*)
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      netbsd*)
+	;;
+      *qnx* | *nto*)
+        # QNX uses GNU C++, but need to define -shared option too, otherwise
+        # it will coredump.
+        _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+        ;;
+      osf3* | osf4* | osf5*)
+	case $cc_basename in
+	  KCC*)
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+	    ;;
+	  RCC*)
+	    # Rational C++ 2.4.1
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+	    ;;
+	  cxx*)
+	    # Digital/Compaq C++
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    # Make sure the PIC flag is empty.  It appears that all Alpha
+	    # Linux and Compaq Tru64 Unix objects are PIC.
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      psos*)
+	;;
+      solaris*)
+	case $cc_basename in
+	  CC*)
+	    # Sun C++ 4.2, 5.x and Centerline C++
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+	    ;;
+	  gcx*)
+	    # Green Hills C++ Compiler
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      sunos4*)
+	case $cc_basename in
+	  CC*)
+	    # Sun C++ 4.x
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	    ;;
+	  lcc*)
+	    # Lucid
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+	case $cc_basename in
+	  CC*)
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	    ;;
+	esac
+	;;
+      tandem*)
+	case $cc_basename in
+	  NCC*)
+	    # NonStop-UX NCC 3.20
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      vxworks*)
+	;;
+      *)
+	_LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+	;;
+    esac
+  fi
+],
+[
+  if test "$GCC" = yes; then
+    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+    case $host_os in
+      aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+	# AIX 5 now supports IA64 processor
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+        ;;
+      m68k)
+            # FIXME: we need at least 68020 code to build shared libraries, but
+            # adding the `-m68020' flag to GCC prevents building anything better,
+            # like `-m68040'.
+            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+        ;;
+      esac
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+
+    mingw* | cygwin* | pw32* | os2*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      m4_if([$1], [GCJ], [],
+	[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+      ;;
+
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+      ;;
+
+    hpux*)
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+	# +Z the default
+	;;
+      *)
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+	;;
+      esac
+      ;;
+
+    interix[[3-9]]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+
+    msdosdjgpp*)
+      # Just because we use GCC doesn't mean we suddenly get shared libraries
+      # on systems that don't support them.
+      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      enable_shared=no
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+      fi
+      ;;
+
+    *)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+      ;;
+    esac
+  else
+    # PORTME Check for flag to pass linker flags through the system compiler.
+    case $host_os in
+    aix*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      if test "$host_cpu" = ia64; then
+	# AIX 5 now supports IA64 processor
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      else
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+
+    mingw* | cygwin* | pw32* | os2*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      m4_if([$1], [GCJ], [],
+	[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+      ;;
+
+    hpux9* | hpux10* | hpux11*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+	# +Z the default
+	;;
+      *)
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+	;;
+      esac
+      # Is there a better lt_prog_compiler_static that works with the bundled CC?
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # PIC (with -KPIC) is the default.
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
+
+    linux* | k*bsd*-gnu)
+      case $cc_basename in
+      icc* | ecc* | ifort*)
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+        ;;
+      pgcc* | pgf77* | pgf90* | pgf95*)
+        # Portland Group compilers (*not* the Pentium gcc compiler,
+	# which looks to be a dead project)
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+        ;;
+      ccc*)
+        _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+        # All Alpha code is PIC.
+        _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+        ;;
+      xl*)
+	# IBM XL C 8.0/Fortran 10.1 on PPC
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
+	;;
+      *)
+	case `$CC -V 2>&1 | sed 5q` in
+	*Sun\ C*)
+	  # Sun C 5.9
+	  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	  _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	  ;;
+	*Sun\ F*)
+	  # Sun Fortran 8.3 passes all unrecognized flags to the linker
+	  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	  _LT_TAGVAR(lt_prog_compiler_wl, $1)=''
+	  ;;
+	esac
+	;;
+      esac
+      ;;
+
+    newsos6)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+      ;;
+
+    osf3* | osf4* | osf5*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # All OSF/1 code is PIC.
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
+
+    rdos*)
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
+
+    solaris*)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      case $cc_basename in
+      f77* | f90* | f95*)
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;
+      *)
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;
+      esac
+      ;;
+
+    sunos4*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    sysv4 | sysv4.2uw2* | sysv4.3*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec ;then
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      ;;
+
+    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    unicos*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      ;;
+
+    uts4*)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    *)
+      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      ;;
+    esac
+  fi
+])
+case $host_os in
+  # For platforms which do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+    ;;
+  *)
+    _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])"
+    ;;
+esac
+AC_MSG_RESULT([$_LT_TAGVAR(lt_prog_compiler_pic, $1)])
+_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1],
+	[How to pass a linker flag through the compiler])
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
+  _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works],
+    [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)],
+    [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [],
+    [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in
+     "" | " "*) ;;
+     *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;;
+     esac],
+    [_LT_TAGVAR(lt_prog_compiler_pic, $1)=
+     _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
+fi
+_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1],
+	[Additional compiler flags for building library objects])
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\"
+_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],
+  _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1),
+  $lt_tmp_static_flag,
+  [],
+  [_LT_TAGVAR(lt_prog_compiler_static, $1)=])
+_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1],
+	[Compiler flag to prevent dynamic linking])
+])# _LT_COMPILER_PIC
+
+
+# _LT_LINKER_SHLIBS([TAGNAME])
+# ----------------------------
+# See if the linker supports building shared libraries.
+m4_defun([_LT_LINKER_SHLIBS],
+[AC_REQUIRE([LT_PATH_LD])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+m4_if([$1], [CXX], [
+  _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  case $host_os in
+  aix[[4-9]]*)
+    # If we're using GNU nm, then we don't want the "-C" option.
+    # -C means demangle to AIX nm, but means don't demangle with GNU nm
+    if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+      _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+    else
+      _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+    fi
+    ;;
+  pw32*)
+    _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds"
+  ;;
+  cygwin* | mingw*)
+    _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
+  ;;
+  *)
+    _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  ;;
+  esac
+  _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+], [
+  runpath_var=
+  _LT_TAGVAR(allow_undefined_flag, $1)=
+  _LT_TAGVAR(always_export_symbols, $1)=no
+  _LT_TAGVAR(archive_cmds, $1)=
+  _LT_TAGVAR(archive_expsym_cmds, $1)=
+  _LT_TAGVAR(compiler_needs_object, $1)=no
+  _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+  _LT_TAGVAR(export_dynamic_flag_spec, $1)=
+  _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  _LT_TAGVAR(hardcode_automatic, $1)=no
+  _LT_TAGVAR(hardcode_direct, $1)=no
+  _LT_TAGVAR(hardcode_direct_absolute, $1)=no
+  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+  _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+  _LT_TAGVAR(hardcode_libdir_separator, $1)=
+  _LT_TAGVAR(hardcode_minus_L, $1)=no
+  _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+  _LT_TAGVAR(inherit_rpath, $1)=no
+  _LT_TAGVAR(link_all_deplibs, $1)=unknown
+  _LT_TAGVAR(module_cmds, $1)=
+  _LT_TAGVAR(module_expsym_cmds, $1)=
+  _LT_TAGVAR(old_archive_from_new_cmds, $1)=
+  _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)=
+  _LT_TAGVAR(thread_safe_flag_spec, $1)=
+  _LT_TAGVAR(whole_archive_flag_spec, $1)=
+  # include_expsyms should be a list of space-separated symbols to be *always*
+  # included in the symbol list
+  _LT_TAGVAR(include_expsyms, $1)=
+  # exclude_expsyms can be an extended regexp of symbols to exclude
+  # it will be wrapped by ` (' and `)$', so one must not match beginning or
+  # end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+  # as well as any symbol that contains `d'.
+  _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+  # platforms (ab)use it in PIC code, but their linkers get confused if
+  # the symbol is explicitly referenced.  Since portable code cannot
+  # rely on this symbol name, it's probably fine to never include it in
+  # preloaded symbol tables.
+  # Exclude shared library initialization/finalization symbols.
+dnl Note also adjust exclude_expsyms for C++ above.
+  extract_expsyms_cmds=
+
+  case $host_os in
+  cygwin* | mingw* | pw32*)
+    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    if test "$GCC" != yes; then
+      with_gnu_ld=no
+    fi
+    ;;
+  interix*)
+    # we just hope/assume this is gcc and not c89 (= MSVC++)
+    with_gnu_ld=yes
+    ;;
+  openbsd*)
+    with_gnu_ld=no
+    ;;
+  esac
+
+  _LT_TAGVAR(ld_shlibs, $1)=yes
+  if test "$with_gnu_ld" = yes; then
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    wlarc='${wl}'
+
+    # Set some defaults for GNU ld with shared library support. These
+    # are reset later if shared libraries are not supported. Putting them
+    # here allows them to be overridden if necessary.
+    runpath_var=LD_RUN_PATH
+    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
+      _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+    else
+      _LT_TAGVAR(whole_archive_flag_spec, $1)=
+    fi
+    supports_anon_versioning=no
+    case `$LD -v 2>&1` in
+      *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
+      *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+      *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+      *\ 2.11.*) ;; # other 2.11 versions
+      *) supports_anon_versioning=yes ;;
+    esac
+
+    # See if GNU ld supports shared libraries.
+    case $host_os in
+    aix[[3-9]]*)
+      # On AIX/PPC, the GNU linker is very broken
+      if test "$host_cpu" != ia64; then
+	_LT_TAGVAR(ld_shlibs, $1)=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+_LT_EOF
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+            _LT_TAGVAR(archive_expsym_cmds, $1)=''
+        ;;
+      m68k)
+            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+            _LT_TAGVAR(hardcode_minus_L, $1)=yes
+        ;;
+      esac
+      ;;
+
+    beos*)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+	# Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+	# support --undefined.  This deserves some investigation.  FIXME
+	_LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      else
+	_LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    cygwin* | mingw* | pw32*)
+      # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+      # as there is no search path for DLLs.
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_TAGVAR(always_export_symbols, $1)=no
+      _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+      _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
+
+      if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+	# If the export-symbols file already is a .def file (1st line
+	# is EXPORTS), use it as is; otherwise, prepend...
+	_LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+	  cp $export_symbols $output_objdir/$soname.def;
+	else
+	  echo EXPORTS > $output_objdir/$soname.def;
+	  cat $export_symbols >> $output_objdir/$soname.def;
+	fi~
+	$CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+      else
+	_LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    interix[[3-9]]*)
+      _LT_TAGVAR(hardcode_direct, $1)=no
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+      # Instead, shared libraries are loaded at an image base (0x10000000 by
+      # default) and relocated if they conflict, which is a slow very memory
+      # consuming and fragmenting process.  To avoid this, we pick a random,
+      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      ;;
+
+    gnu* | linux* | tpf* | k*bsd*-gnu)
+      tmp_diet=no
+      if test "$host_os" = linux-dietlibc; then
+	case $cc_basename in
+	  diet\ *) tmp_diet=yes;;	# linux-dietlibc with static linking (!diet-dyn)
+	esac
+      fi
+      if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+	 && test "$tmp_diet" = no
+      then
+	tmp_addflag=
+	tmp_sharedflag='-shared'
+	case $cc_basename,$host_cpu in
+        pgcc*)				# Portland Group C compiler
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+	  tmp_addflag=' $pic_flag'
+	  ;;
+	pgf77* | pgf90* | pgf95*)	# Portland Group f77 and f90 compilers
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+	  tmp_addflag=' $pic_flag -Mnomain' ;;
+	ecc*,ia64* | icc*,ia64*)	# Intel C compiler on ia64
+	  tmp_addflag=' -i_dynamic' ;;
+	efc*,ia64* | ifort*,ia64*)	# Intel Fortran compiler on ia64
+	  tmp_addflag=' -i_dynamic -nofor_main' ;;
+	ifc* | ifort*)			# Intel Fortran compiler
+	  tmp_addflag=' -nofor_main' ;;
+	xl[[cC]]*)			# IBM XL C 8.0 on PPC (deal with xlf below)
+	  tmp_sharedflag='-qmkshrobj'
+	  tmp_addflag= ;;
+	esac
+	case `$CC -V 2>&1 | sed 5q` in
+	*Sun\ C*)			# Sun C 5.9
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+	  _LT_TAGVAR(compiler_needs_object, $1)=yes
+	  tmp_sharedflag='-G' ;;
+	*Sun\ F*)			# Sun Fortran 8.3
+	  tmp_sharedflag='-G' ;;
+	esac
+	_LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+        if test "x$supports_anon_versioning" = xyes; then
+          _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+	    cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+	    echo "local: *; };" >> $output_objdir/$libname.ver~
+	    $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+        fi
+
+	case $cc_basename in
+	xlf*)
+	  # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive'
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+	  _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir'
+	  _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib'
+	  if test "x$supports_anon_versioning" = xyes; then
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+	      cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+	      echo "local: *; };" >> $output_objdir/$libname.ver~
+	      $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+	  fi
+	  ;;
+	esac
+      else
+        _LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    netbsd*)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+	wlarc=
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      fi
+      ;;
+
+    solaris*)
+      if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
+	_LT_TAGVAR(ld_shlibs, $1)=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+      elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+	_LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+      case `$LD -v 2>&1` in
+        *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*)
+	_LT_TAGVAR(ld_shlibs, $1)=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+	;;
+	*)
+	  # For security reasons, it is highly recommended that you always
+	  # use absolute paths for naming shared libraries, and exclude the
+	  # DT_RUNPATH tag from executables and libraries.  But doing so
+	  # requires that you compile everything twice, which is a pain.
+	  if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+	  else
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	  fi
+	;;
+      esac
+      ;;
+
+    sunos4*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      wlarc=
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    *)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+	_LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+    esac
+
+    if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then
+      runpath_var=
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)=
+      _LT_TAGVAR(whole_archive_flag_spec, $1)=
+    fi
+  else
+    # PORTME fill in a description of your system's linker (not GNU ld)
+    case $host_os in
+    aix3*)
+      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_TAGVAR(always_export_symbols, $1)=yes
+      _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+      # Note: this linker hardcodes the directories in LIBPATH if there
+      # are no directories specified by -L.
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+	# Neither direct hardcoding nor static linking is supported with a
+	# broken collect2.
+	_LT_TAGVAR(hardcode_direct, $1)=unsupported
+      fi
+      ;;
+
+    aix[[4-9]]*)
+      if test "$host_cpu" = ia64; then
+	# On IA64, the linker does run time linking by default, so we don't
+	# have to do anything special.
+	aix_use_runtimelinking=no
+	exp_sym_flag='-Bexport'
+	no_entry_flag=""
+      else
+	# If we're using GNU nm, then we don't want the "-C" option.
+	# -C means demangle to AIX nm, but means don't demangle with GNU nm
+	if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+	  _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+	else
+	  _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+	fi
+	aix_use_runtimelinking=no
+
+	# Test if we are trying to use run time linking or normal
+	# AIX style linking. If -brtl is somewhere in LDFLAGS, we
+	# need to do runtime linking.
+	case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+	  for ld_flag in $LDFLAGS; do
+	  if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+	    aix_use_runtimelinking=yes
+	    break
+	  fi
+	  done
+	  ;;
+	esac
+
+	exp_sym_flag='-bexport'
+	no_entry_flag='-bnoentry'
+      fi
+
+      # When large executables or shared objects are built, AIX ld can
+      # have problems creating the table of contents.  If linking a library
+      # or program results in "error TOC overflow" add -mminimal-toc to
+      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+      _LT_TAGVAR(archive_cmds, $1)=''
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      _LT_TAGVAR(file_list_spec, $1)='${wl}-f,'
+
+      if test "$GCC" = yes; then
+	case $host_os in aix4.[[012]]|aix4.[[012]].*)
+	# We only want to do this on AIX 4.2 and lower, the check
+	# below for broken collect2 doesn't work under 4.3+
+	  collect2name=`${CC} -print-prog-name=collect2`
+	  if test -f "$collect2name" &&
+	   strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+	  then
+	  # We have reworked collect2
+	  :
+	  else
+	  # We have old collect2
+	  _LT_TAGVAR(hardcode_direct, $1)=unsupported
+	  # It fails to find uninstalled libraries when the uninstalled
+	  # path is not listed in the libpath.  Setting hardcode_minus_L
+	  # to unsupported forces relinking
+	  _LT_TAGVAR(hardcode_minus_L, $1)=yes
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+	  _LT_TAGVAR(hardcode_libdir_separator, $1)=
+	  fi
+	  ;;
+	esac
+	shared_flag='-shared'
+	if test "$aix_use_runtimelinking" = yes; then
+	  shared_flag="$shared_flag "'${wl}-G'
+	fi
+      else
+	# not using gcc
+	if test "$host_cpu" = ia64; then
+	# VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+	# chokes on -Wl,-G. The following line is correct:
+	  shared_flag='-G'
+	else
+	  if test "$aix_use_runtimelinking" = yes; then
+	    shared_flag='${wl}-G'
+	  else
+	    shared_flag='${wl}-bM:SRE'
+	  fi
+	fi
+      fi
+
+      # It seems that -bexpall does not export symbols beginning with
+      # underscore (_), so it is better to generate a list of symbols to export.
+      _LT_TAGVAR(always_export_symbols, $1)=yes
+      if test "$aix_use_runtimelinking" = yes; then
+	# Warning - without using the other runtime loading flags (-brtl),
+	# -berok will link without error, but may produce a broken library.
+	_LT_TAGVAR(allow_undefined_flag, $1)='-berok'
+        # Determine the default libpath from the value encoded in an
+        # empty executable.
+        _LT_SYS_MODULE_PATH_AIX
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+        _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+      else
+	if test "$host_cpu" = ia64; then
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+	  _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+	  _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+	else
+	 # Determine the default libpath from the value encoded in an
+	 # empty executable.
+	 _LT_SYS_MODULE_PATH_AIX
+	 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+	  # Warning - without using the other run time loading flags,
+	  # -berok will link without error, but may produce a broken library.
+	  _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+	  _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+	  # Exported symbols can be pulled into shared objects from archives
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+	  _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+	  # This is similar to how AIX traditionally builds its shared libraries.
+	  _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+	fi
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+            _LT_TAGVAR(archive_expsym_cmds, $1)=''
+        ;;
+      m68k)
+            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+            _LT_TAGVAR(hardcode_minus_L, $1)=yes
+        ;;
+      esac
+      ;;
+
+    bsdi[[45]]*)
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
+      ;;
+
+    cygwin* | mingw* | pw32*)
+      # When not using gcc, we currently assume that we are using
+      # Microsoft Visual C++.
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+      # Tell ltmain to make .lib files, not .a files.
+      libext=lib
+      # Tell ltmain to make .dll files, not .so files.
+      shrext_cmds=".dll"
+      # FIXME: Setting linknames here is a bad hack.
+      _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames='
+      # The linker will automatically build a .lib file if we build a DLL.
+      _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+      # FIXME: Should let the user specify the lib program.
+      _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs'
+      _LT_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`'
+      _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+      ;;
+
+    darwin* | rhapsody*)
+      _LT_DARWIN_LINKER_FEATURES($1)
+      ;;
+
+    dgux*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    freebsd1*)
+      _LT_TAGVAR(ld_shlibs, $1)=no
+      ;;
+
+    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+    # support.  Future versions do this automatically, but an explicit c++rt0.o
+    # does not break anything, and helps significantly (at the cost of a little
+    # extra space).
+    freebsd2.2*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+    freebsd2*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+    freebsd* | dragonfly*)
+      _LT_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    hpux9*)
+      if test "$GCC" = yes; then
+	_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      fi
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+
+      # hardcode_minus_L: Not really in the search PATH,
+      # but as the default location of the library.
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+      ;;
+
+    hpux10*)
+      if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      if test "$with_gnu_ld" = no; then
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+	_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
+	_LT_TAGVAR(hardcode_libdir_separator, $1)=:
+	_LT_TAGVAR(hardcode_direct, $1)=yes
+	_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+	_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+	# hardcode_minus_L: Not really in the search PATH,
+	# but as the default location of the library.
+	_LT_TAGVAR(hardcode_minus_L, $1)=yes
+      fi
+      ;;
+
+    hpux11*)
+      if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+	case $host_cpu in
+	hppa*64*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	ia64*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	esac
+      else
+	case $host_cpu in
+	hppa*64*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	ia64*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	esac
+      fi
+      if test "$with_gnu_ld" = no; then
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+	_LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+	case $host_cpu in
+	hppa*64*|ia64*)
+	  _LT_TAGVAR(hardcode_direct, $1)=no
+	  _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	  ;;
+	*)
+	  _LT_TAGVAR(hardcode_direct, $1)=yes
+	  _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+	  _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+
+	  # hardcode_minus_L: Not really in the search PATH,
+	  # but as the default location of the library.
+	  _LT_TAGVAR(hardcode_minus_L, $1)=yes
+	  ;;
+	esac
+      fi
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      if test "$GCC" = yes; then
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	# Try to use the -exported_symbol ld option, if it does not
+	# work, assume that -exports_file does not work either and
+	# implicitly export all symbols.
+        save_LDFLAGS="$LDFLAGS"
+        LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
+        AC_LINK_IFELSE(int foo(void) {},
+          _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
+        )
+        LDFLAGS="$save_LDFLAGS"
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib'
+      fi
+      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_TAGVAR(inherit_rpath, $1)=yes
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      ;;
+
+    netbsd*)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+      fi
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    newsos6)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    *nto* | *qnx*)
+      ;;
+
+    openbsd*)
+      if test -f /usr/libexec/ld.so; then
+	_LT_TAGVAR(hardcode_direct, $1)=yes
+	_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+	if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	  _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	  _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+	else
+	  case $host_os in
+	   openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*)
+	     _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+	     _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+	     ;;
+	   *)
+	     _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	     _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	     ;;
+	  esac
+	fi
+      else
+	_LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    os2*)
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+      _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+      ;;
+
+    osf3*)
+      if test "$GCC" = yes; then
+	_LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+	_LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+      fi
+      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      ;;
+
+    osf4* | osf5*)	# as osf3* with the addition of -msym flag
+      if test "$GCC" = yes; then
+	_LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      else
+	_LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
+	$CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp'
+
+	# Both c and cxx compiler support -rpath directly
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+      fi
+      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      ;;
+
+    solaris*)
+      _LT_TAGVAR(no_undefined_flag, $1)=' -z defs'
+      if test "$GCC" = yes; then
+	wlarc='${wl}'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+      else
+	case `$CC -V 2>&1` in
+	*"Compilers 5.0"*)
+	  wlarc=''
+	  _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
+	  ;;
+	*)
+	  wlarc='${wl}'
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags'
+	  _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+	  ;;
+	esac
+      fi
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      case $host_os in
+      solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+      *)
+	# The compiler driver will combine and reorder linker options,
+	# but understands `-z linker_flag'.  GCC discards it without `$wl',
+	# but is careful enough not to reorder.
+	# Supported since Solaris 2.6 (maybe 2.5.1?)
+	if test "$GCC" = yes; then
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+	else
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+	fi
+	;;
+      esac
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      ;;
+
+    sunos4*)
+      if test "x$host_vendor" = xsequent; then
+	# Use $CC to link under sequent, because it throws in some extra .o
+	# files that make .init and .fini sections work.
+	_LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    sysv4)
+      case $host_vendor in
+	sni)
+	  _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true???
+	;;
+	siemens)
+	  ## LD is ld it makes a PLAMLIB
+	  ## CC just makes a GrossModule.
+	  _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+	  _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
+	  _LT_TAGVAR(hardcode_direct, $1)=no
+        ;;
+	motorola)
+	  _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
+	;;
+      esac
+      runpath_var='LD_RUN_PATH'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    sysv4.3*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	_LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	runpath_var=LD_RUN_PATH
+	hardcode_runpath_var=yes
+	_LT_TAGVAR(ld_shlibs, $1)=yes
+      fi
+      ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+      _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6*)
+      # Note: We can NOT use -z defs as we might desire, because we do not
+      # link with -lc, and that would cause any symbols used from libc to
+      # always be unresolved, which means just about no library would
+      # ever link correctly.  If we're not using GNU ld we use -z text
+      # though, which does catch some bad symbols but isn't as heavy-handed
+      # as -z defs.
+      _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+      _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
+      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    uts4*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    *)
+      _LT_TAGVAR(ld_shlibs, $1)=no
+      ;;
+    esac
+
+    if test x$host_vendor = xsni; then
+      case $host in
+      sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+	_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym'
+	;;
+      esac
+    fi
+  fi
+])
+AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
+test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld
+
+_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl
+_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl
+_LT_DECL([], [extract_expsyms_cmds], [2],
+    [The commands to extract the exported symbol list from a shared archive])
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in
+x|xyes)
+  # Assume -lc should be added
+  _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+
+  if test "$enable_shared" = yes && test "$GCC" = yes; then
+    case $_LT_TAGVAR(archive_cmds, $1) in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      AC_MSG_CHECKING([whether -lc should be explicitly linked in])
+      $RM conftest*
+      echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+      if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
+        soname=conftest
+        lib=conftest
+        libobjs=conftest.$ac_objext
+        deplibs=
+        wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1)
+	pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1)
+        compiler_flags=-v
+        linker_flags=-v
+        verstring=
+        output_objdir=.
+        libname=conftest
+        lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1)
+        _LT_TAGVAR(allow_undefined_flag, $1)=
+        if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1)
+        then
+	  _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+        else
+	  _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+        fi
+        _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
+      else
+        cat conftest.err 1>&5
+      fi
+      $RM conftest*
+      AC_MSG_RESULT([$_LT_TAGVAR(archive_cmds_need_lc, $1)])
+      ;;
+    esac
+  fi
+  ;;
+esac
+
+_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0],
+    [Whether or not to add -lc for building shared libraries])
+_LT_TAGDECL([allow_libtool_libs_with_static_runtimes],
+    [enable_shared_with_static_runtimes], [0],
+    [Whether or not to disallow shared libs when runtime libs are static])
+_LT_TAGDECL([], [export_dynamic_flag_spec], [1],
+    [Compiler flag to allow reflexive dlopens])
+_LT_TAGDECL([], [whole_archive_flag_spec], [1],
+    [Compiler flag to generate shared objects directly from archives])
+_LT_TAGDECL([], [compiler_needs_object], [1],
+    [Whether the compiler copes with passing no objects directly])
+_LT_TAGDECL([], [old_archive_from_new_cmds], [2],
+    [Create an old-style archive from a shared archive])
+_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2],
+    [Create a temporary old-style archive to link instead of a shared archive])
+_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive])
+_LT_TAGDECL([], [archive_expsym_cmds], [2])
+_LT_TAGDECL([], [module_cmds], [2],
+    [Commands used to build a loadable module if different from building
+    a shared archive.])
+_LT_TAGDECL([], [module_expsym_cmds], [2])
+_LT_TAGDECL([], [with_gnu_ld], [1],
+    [Whether we are building with GNU ld or not])
+_LT_TAGDECL([], [allow_undefined_flag], [1],
+    [Flag that allows shared libraries with undefined symbols to be built])
+_LT_TAGDECL([], [no_undefined_flag], [1],
+    [Flag that enforces no undefined symbols])
+_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1],
+    [Flag to hardcode $libdir into a binary during linking.
+    This must work even if $libdir does not exist])
+_LT_TAGDECL([], [hardcode_libdir_flag_spec_ld], [1],
+    [[If ld is used when linking, flag to hardcode $libdir into a binary
+    during linking.  This must work even if $libdir does not exist]])
+_LT_TAGDECL([], [hardcode_libdir_separator], [1],
+    [Whether we need a single "-rpath" flag with a separated argument])
+_LT_TAGDECL([], [hardcode_direct], [0],
+    [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes
+    DIR into the resulting binary])
+_LT_TAGDECL([], [hardcode_direct_absolute], [0],
+    [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes
+    DIR into the resulting binary and the resulting library dependency is
+    "absolute", i.e impossible to change by setting ${shlibpath_var} if the
+    library is relocated])
+_LT_TAGDECL([], [hardcode_minus_L], [0],
+    [Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+    into the resulting binary])
+_LT_TAGDECL([], [hardcode_shlibpath_var], [0],
+    [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+    into the resulting binary])
+_LT_TAGDECL([], [hardcode_automatic], [0],
+    [Set to "yes" if building a shared library automatically hardcodes DIR
+    into the library and all subsequent libraries and executables linked
+    against it])
+_LT_TAGDECL([], [inherit_rpath], [0],
+    [Set to yes if linker adds runtime paths of dependent libraries
+    to runtime path list])
+_LT_TAGDECL([], [link_all_deplibs], [0],
+    [Whether libtool must link a program against all its dependency libraries])
+_LT_TAGDECL([], [fix_srcfile_path], [1],
+    [Fix the shell variable $srcfile for the compiler])
+_LT_TAGDECL([], [always_export_symbols], [0],
+    [Set to "yes" if exported symbols are required])
+_LT_TAGDECL([], [export_symbols_cmds], [2],
+    [The commands to list exported symbols])
+_LT_TAGDECL([], [exclude_expsyms], [1],
+    [Symbols that should not be listed in the preloaded symbols])
+_LT_TAGDECL([], [include_expsyms], [1],
+    [Symbols that must always be exported])
+_LT_TAGDECL([], [prelink_cmds], [2],
+    [Commands necessary for linking programs (against libraries) with templates])
+_LT_TAGDECL([], [file_list_spec], [1],
+    [Specify filename containing input files])
+dnl FIXME: Not yet implemented
+dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1],
+dnl    [Compiler flag to generate thread safe objects])
+])# _LT_LINKER_SHLIBS
+
+
+# _LT_LANG_C_CONFIG([TAG])
+# ------------------------
+# Ensure that the configuration variables for a C compiler are suitably
+# defined.  These variables are subsequently used by _LT_CONFIG to write
+# the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_C_CONFIG],
+[m4_require([_LT_DECL_EGREP])dnl
+lt_save_CC="$CC"
+AC_LANG_PUSH(C)
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+_LT_TAG_COMPILER
+# Save the default compiler, since it gets overwritten when the other
+# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
+compiler_DEFAULT=$CC
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+  _LT_COMPILER_NO_RTTI($1)
+  _LT_COMPILER_PIC($1)
+  _LT_COMPILER_C_O($1)
+  _LT_COMPILER_FILE_LOCKS($1)
+  _LT_LINKER_SHLIBS($1)
+  _LT_SYS_DYNAMIC_LINKER($1)
+  _LT_LINKER_HARDCODE_LIBPATH($1)
+  LT_SYS_DLOPEN_SELF
+  _LT_CMD_STRIPLIB
+
+  # Report which library types will actually be built
+  AC_MSG_CHECKING([if libtool supports shared libraries])
+  AC_MSG_RESULT([$can_build_shared])
+
+  AC_MSG_CHECKING([whether to build shared libraries])
+  test "$can_build_shared" = "no" && enable_shared=no
+
+  # On AIX, shared libraries and static libraries use the same namespace, and
+  # are all built from PIC.
+  case $host_os in
+  aix3*)
+    test "$enable_shared" = yes && enable_static=no
+    if test -n "$RANLIB"; then
+      archive_cmds="$archive_cmds~\$RANLIB \$lib"
+      postinstall_cmds='$RANLIB $lib'
+    fi
+    ;;
+
+  aix[[4-9]]*)
+    if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+      test "$enable_shared" = yes && enable_static=no
+    fi
+    ;;
+  esac
+  AC_MSG_RESULT([$enable_shared])
+
+  AC_MSG_CHECKING([whether to build static libraries])
+  # Make sure either enable_shared or enable_static is yes.
+  test "$enable_shared" = yes || enable_static=yes
+  AC_MSG_RESULT([$enable_static])
+
+  _LT_CONFIG($1)
+fi
+AC_LANG_POP
+CC="$lt_save_CC"
+])# _LT_LANG_C_CONFIG
+
+
+# _LT_PROG_CXX
+# ------------
+# Since AC_PROG_CXX is broken, in that it returns g++ if there is no c++
+# compiler, we have our own version here.
+m4_defun([_LT_PROG_CXX],
+[
+pushdef([AC_MSG_ERROR], [_lt_caught_CXX_error=yes])
+AC_PROG_CXX
+if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+    ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+    (test "X$CXX" != "Xg++"))) ; then
+  AC_PROG_CXXCPP
+else
+  _lt_caught_CXX_error=yes
+fi
+popdef([AC_MSG_ERROR])
+])# _LT_PROG_CXX
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([_LT_PROG_CXX], [])
+
+
+# _LT_LANG_CXX_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for a C++ compiler are suitably
+# defined.  These variables are subsequently used by _LT_CONFIG to write
+# the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_CXX_CONFIG],
+[AC_REQUIRE([_LT_PROG_CXX])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_EGREP])dnl
+
+AC_LANG_PUSH(C++)
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(compiler_needs_object, $1)=no
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for C++ test sources.
+ac_ext=cpp
+
+# Object file extension for compiled C++ test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the CXX compiler isn't working.  Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test "$_lt_caught_CXX_error" != yes; then
+  # Code to be used in simple compile tests
+  lt_simple_compile_test_code="int some_variable = 0;"
+
+  # Code to be used in simple link tests
+  lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }'
+
+  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+  _LT_TAG_COMPILER
+
+  # save warnings/boilerplate of simple test code
+  _LT_COMPILER_BOILERPLATE
+  _LT_LINKER_BOILERPLATE
+
+  # Allow CC to be a program name with arguments.
+  lt_save_CC=$CC
+  lt_save_LD=$LD
+  lt_save_GCC=$GCC
+  GCC=$GXX
+  lt_save_with_gnu_ld=$with_gnu_ld
+  lt_save_path_LD=$lt_cv_path_LD
+  if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+    lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+  else
+    $as_unset lt_cv_prog_gnu_ld
+  fi
+  if test -n "${lt_cv_path_LDCXX+set}"; then
+    lt_cv_path_LD=$lt_cv_path_LDCXX
+  else
+    $as_unset lt_cv_path_LD
+  fi
+  test -z "${LDCXX+set}" || LD=$LDCXX
+  CC=${CXX-"c++"}
+  compiler=$CC
+  _LT_TAGVAR(compiler, $1)=$CC
+  _LT_CC_BASENAME([$compiler])
+
+  if test -n "$compiler"; then
+    # We don't want -fno-exception when compiling C++ code, so set the
+    # no_builtin_flag separately
+    if test "$GXX" = yes; then
+      _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+    else
+      _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+    fi
+
+    if test "$GXX" = yes; then
+      # Set up default GNU C++ configuration
+
+      LT_PATH_LD
+
+      # Check if GNU C++ uses GNU ld as the underlying linker, since the
+      # archiving commands below assume that GNU ld is being used.
+      if test "$with_gnu_ld" = yes; then
+        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+        _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+        _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+        # If archive_cmds runs LD, not CC, wlarc should be empty
+        # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+        #     investigate it a little bit more. (MM)
+        wlarc='${wl}'
+
+        # ancient GNU ld didn't support --whole-archive et. al.
+        if eval "`$CC -print-prog-name=ld` --help 2>&1" |
+	  $GREP 'no-whole-archive' > /dev/null; then
+          _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+        else
+          _LT_TAGVAR(whole_archive_flag_spec, $1)=
+        fi
+      else
+        with_gnu_ld=no
+        wlarc=
+
+        # A generic and very simple default shared library creation
+        # command for GNU C++ for the case where it uses the native
+        # linker, instead of GNU ld.  If possible, this setting should
+        # overridden to take advantage of the native linker features on
+        # the platform it is being used on.
+        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+      fi
+
+      # Commands to make compiler produce verbose output that lists
+      # what "hidden" libraries, object files and flags are used when
+      # linking a shared library.
+      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
+
+    else
+      GXX=no
+      with_gnu_ld=no
+      wlarc=
+    fi
+
+    # PORTME: fill in a description of your system's C++ link characteristics
+    AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+    _LT_TAGVAR(ld_shlibs, $1)=yes
+    case $host_os in
+      aix3*)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+      aix[[4-9]]*)
+        if test "$host_cpu" = ia64; then
+          # On IA64, the linker does run time linking by default, so we don't
+          # have to do anything special.
+          aix_use_runtimelinking=no
+          exp_sym_flag='-Bexport'
+          no_entry_flag=""
+        else
+          aix_use_runtimelinking=no
+
+          # Test if we are trying to use run time linking or normal
+          # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+          # need to do runtime linking.
+          case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+	    for ld_flag in $LDFLAGS; do
+	      case $ld_flag in
+	      *-brtl*)
+	        aix_use_runtimelinking=yes
+	        break
+	        ;;
+	      esac
+	    done
+	    ;;
+          esac
+
+          exp_sym_flag='-bexport'
+          no_entry_flag='-bnoentry'
+        fi
+
+        # When large executables or shared objects are built, AIX ld can
+        # have problems creating the table of contents.  If linking a library
+        # or program results in "error TOC overflow" add -mminimal-toc to
+        # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+        # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+        _LT_TAGVAR(archive_cmds, $1)=''
+        _LT_TAGVAR(hardcode_direct, $1)=yes
+        _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+        _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+        _LT_TAGVAR(link_all_deplibs, $1)=yes
+        _LT_TAGVAR(file_list_spec, $1)='${wl}-f,'
+
+        if test "$GXX" = yes; then
+          case $host_os in aix4.[[012]]|aix4.[[012]].*)
+          # We only want to do this on AIX 4.2 and lower, the check
+          # below for broken collect2 doesn't work under 4.3+
+	  collect2name=`${CC} -print-prog-name=collect2`
+	  if test -f "$collect2name" &&
+	     strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+	  then
+	    # We have reworked collect2
+	    :
+	  else
+	    # We have old collect2
+	    _LT_TAGVAR(hardcode_direct, $1)=unsupported
+	    # It fails to find uninstalled libraries when the uninstalled
+	    # path is not listed in the libpath.  Setting hardcode_minus_L
+	    # to unsupported forces relinking
+	    _LT_TAGVAR(hardcode_minus_L, $1)=yes
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+	    _LT_TAGVAR(hardcode_libdir_separator, $1)=
+	  fi
+          esac
+          shared_flag='-shared'
+	  if test "$aix_use_runtimelinking" = yes; then
+	    shared_flag="$shared_flag "'${wl}-G'
+	  fi
+        else
+          # not using gcc
+          if test "$host_cpu" = ia64; then
+	  # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+	  # chokes on -Wl,-G. The following line is correct:
+	  shared_flag='-G'
+          else
+	    if test "$aix_use_runtimelinking" = yes; then
+	      shared_flag='${wl}-G'
+	    else
+	      shared_flag='${wl}-bM:SRE'
+	    fi
+          fi
+        fi
+
+        # It seems that -bexpall does not export symbols beginning with
+        # underscore (_), so it is better to generate a list of symbols to
+	# export.
+        _LT_TAGVAR(always_export_symbols, $1)=yes
+        if test "$aix_use_runtimelinking" = yes; then
+          # Warning - without using the other runtime loading flags (-brtl),
+          # -berok will link without error, but may produce a broken library.
+          _LT_TAGVAR(allow_undefined_flag, $1)='-berok'
+          # Determine the default libpath from the value encoded in an empty
+          # executable.
+          _LT_SYS_MODULE_PATH_AIX
+          _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+
+          _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+        else
+          if test "$host_cpu" = ia64; then
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+	    _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+	    _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+          else
+	    # Determine the default libpath from the value encoded in an
+	    # empty executable.
+	    _LT_SYS_MODULE_PATH_AIX
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+	    # Warning - without using the other run time loading flags,
+	    # -berok will link without error, but may produce a broken library.
+	    _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+	    _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+	    # Exported symbols can be pulled into shared objects from archives
+	    _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+	    _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+	    # This is similar to how AIX traditionally builds its shared
+	    # libraries.
+	    _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+          fi
+        fi
+        ;;
+
+      beos*)
+	if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	  _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+	  # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+	  # support --undefined.  This deserves some investigation.  FIXME
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	else
+	  _LT_TAGVAR(ld_shlibs, $1)=no
+	fi
+	;;
+
+      chorus*)
+        case $cc_basename in
+          *)
+	  # FIXME: insert proper C++ library support
+	  _LT_TAGVAR(ld_shlibs, $1)=no
+	  ;;
+        esac
+        ;;
+
+      cygwin* | mingw* | pw32*)
+        # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+        # as there is no search path for DLLs.
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+        _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+        _LT_TAGVAR(always_export_symbols, $1)=no
+        _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+
+        if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+          _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+          # If the export-symbols file already is a .def file (1st line
+          # is EXPORTS), use it as is; otherwise, prepend...
+          _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+	    cp $export_symbols $output_objdir/$soname.def;
+          else
+	    echo EXPORTS > $output_objdir/$soname.def;
+	    cat $export_symbols >> $output_objdir/$soname.def;
+          fi~
+          $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+        else
+          _LT_TAGVAR(ld_shlibs, $1)=no
+        fi
+        ;;
+      darwin* | rhapsody*)
+        _LT_DARWIN_LINKER_FEATURES($1)
+	;;
+
+      dgux*)
+        case $cc_basename in
+          ec++*)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          ghcx*)
+	    # Green Hills C++ Compiler
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          *)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+        esac
+        ;;
+
+      freebsd[[12]]*)
+        # C++ shared libraries reported to be fairly broken before
+	# switch to ELF
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+
+      freebsd-elf*)
+        _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+        ;;
+
+      freebsd* | dragonfly*)
+        # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+        # conventions
+        _LT_TAGVAR(ld_shlibs, $1)=yes
+        ;;
+
+      gnu*)
+        ;;
+
+      hpux9*)
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+        _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+        _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+        _LT_TAGVAR(hardcode_direct, $1)=yes
+        _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+				             # but as the default
+				             # location of the library.
+
+        case $cc_basename in
+          CC*)
+            # FIXME: insert proper C++ library support
+            _LT_TAGVAR(ld_shlibs, $1)=no
+            ;;
+          aCC*)
+            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+            # Commands to make compiler produce verbose output that lists
+            # what "hidden" libraries, object files and flags are used when
+            # linking a shared library.
+            #
+            # There doesn't appear to be a way to prevent this compiler from
+            # explicitly linking system object files so we need to strip them
+            # from the output so that they don't get included in the library
+            # dependencies.
+            output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+            ;;
+          *)
+            if test "$GXX" = yes; then
+              _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+            else
+              # FIXME: insert proper C++ library support
+              _LT_TAGVAR(ld_shlibs, $1)=no
+            fi
+            ;;
+        esac
+        ;;
+
+      hpux10*|hpux11*)
+        if test $with_gnu_ld = no; then
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+	  _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+          case $host_cpu in
+            hppa*64*|ia64*)
+              ;;
+            *)
+	      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+              ;;
+          esac
+        fi
+        case $host_cpu in
+          hppa*64*|ia64*)
+            _LT_TAGVAR(hardcode_direct, $1)=no
+            _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+            ;;
+          *)
+            _LT_TAGVAR(hardcode_direct, $1)=yes
+            _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+            _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+					         # but as the default
+					         # location of the library.
+            ;;
+        esac
+
+        case $cc_basename in
+          CC*)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          aCC*)
+	    case $host_cpu in
+	      hppa*64*)
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	        ;;
+	      ia64*)
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	        ;;
+	      *)
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	        ;;
+	    esac
+	    # Commands to make compiler produce verbose output that lists
+	    # what "hidden" libraries, object files and flags are used when
+	    # linking a shared library.
+	    #
+	    # There doesn't appear to be a way to prevent this compiler from
+	    # explicitly linking system object files so we need to strip them
+	    # from the output so that they don't get included in the library
+	    # dependencies.
+	    output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+	    ;;
+          *)
+	    if test "$GXX" = yes; then
+	      if test $with_gnu_ld = no; then
+	        case $host_cpu in
+	          hppa*64*)
+	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	            ;;
+	          ia64*)
+	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	            ;;
+	          *)
+	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	            ;;
+	        esac
+	      fi
+	    else
+	      # FIXME: insert proper C++ library support
+	      _LT_TAGVAR(ld_shlibs, $1)=no
+	    fi
+	    ;;
+        esac
+        ;;
+
+      interix[[3-9]]*)
+	_LT_TAGVAR(hardcode_direct, $1)=no
+	_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+	# Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+	# Instead, shared libraries are loaded at an image base (0x10000000 by
+	# default) and relocated if they conflict, which is a slow very memory
+	# consuming and fragmenting process.  To avoid this, we pick a random,
+	# 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+	# time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+	;;
+      irix5* | irix6*)
+        case $cc_basename in
+          CC*)
+	    # SGI C++
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+
+	    # Archives containing C++ object files must be created using
+	    # "CC -ar", where "CC" is the IRIX C++ compiler.  This is
+	    # necessary to make sure instantiated templates are included
+	    # in the archive.
+	    _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
+	    ;;
+          *)
+	    if test "$GXX" = yes; then
+	      if test "$with_gnu_ld" = no; then
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	      else
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` -o $lib'
+	      fi
+	    fi
+	    _LT_TAGVAR(link_all_deplibs, $1)=yes
+	    ;;
+        esac
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+        _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+        _LT_TAGVAR(inherit_rpath, $1)=yes
+        ;;
+
+      linux* | k*bsd*-gnu)
+        case $cc_basename in
+          KCC*)
+	    # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+	    # KCC will only create a shared library if the output file
+	    # ends with ".so" (or ".sl" for HP-UX), so rename the library
+	    # to its proper name (with version) after linking.
+	    _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
+	    # Commands to make compiler produce verbose output that lists
+	    # what "hidden" libraries, object files and flags are used when
+	    # linking a shared library.
+	    #
+	    # There doesn't appear to be a way to prevent this compiler from
+	    # explicitly linking system object files so we need to strip them
+	    # from the output so that they don't get included in the library
+	    # dependencies.
+	    output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+	    # Archives containing C++ object files must be created using
+	    # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+	    _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+	    ;;
+	  icpc* | ecpc* )
+	    # Intel C++
+	    with_gnu_ld=yes
+	    # version 8.0 and above of icpc choke on multiply defined symbols
+	    # if we add $predep_objects and $postdep_objects, however 7.1 and
+	    # earlier do not add the objects themselves.
+	    case `$CC -V 2>&1` in
+	      *"Version 7."*)
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+		_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+		;;
+	      *)  # Version 8.0 or newer
+	        tmp_idyn=
+	        case $host_cpu in
+		  ia64*) tmp_idyn=' -i_dynamic';;
+		esac
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+		_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+		;;
+	    esac
+	    _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+	    _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+	    ;;
+          pgCC* | pgcpp*)
+            # Portland Group C++ compiler
+	    case `$CC -V` in
+	    *pgCC\ [[1-5]]* | *pgcpp\ [[1-5]]*)
+	      _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~
+		rm -rf $tpldir~
+		$CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
+		compile_command="$compile_command `find $tpldir -name \*.o | $NL2SP`"'
+	      _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~
+		rm -rf $tpldir~
+		$CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
+		$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | $NL2SP`~
+		$RANLIB $oldlib'
+	      _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~
+		rm -rf $tpldir~
+		$CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+		$CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+	      _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~
+		rm -rf $tpldir~
+		$CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+		$CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+	      ;;
+	    *) # Version 6 will use weak symbols
+	      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+	      _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+	      ;;
+	    esac
+
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+	    _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+            ;;
+	  cxx*)
+	    # Compaq C++
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname  -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
+
+	    runpath_var=LD_RUN_PATH
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+	    _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+	    # Commands to make compiler produce verbose output that lists
+	    # what "hidden" libraries, object files and flags are used when
+	    # linking a shared library.
+	    #
+	    # There doesn't appear to be a way to prevent this compiler from
+	    # explicitly linking system object files so we need to strip them
+	    # from the output so that they don't get included in the library
+	    # dependencies.
+	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+	    ;;
+	  xl*)
+	    # IBM XL 8.0 on PPC, with GNU ld
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	    if test "x$supports_anon_versioning" = xyes; then
+	      _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+		cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+		echo "local: *; };" >> $output_objdir/$libname.ver~
+		$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+	    fi
+	    ;;
+	  *)
+	    case `$CC -V 2>&1 | sed 5q` in
+	    *Sun\ C*)
+	      # Sun C++ 5.9
+	      _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+	      _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	      _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols'
+	      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+	      _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+	      _LT_TAGVAR(compiler_needs_object, $1)=yes
+
+	      # Not sure whether something based on
+	      # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
+	      # would be better.
+	      output_verbose_link_cmd='echo'
+
+	      # Archives containing C++ object files must be created using
+	      # "CC -xar", where "CC" is the Sun C++ compiler.  This is
+	      # necessary to make sure instantiated templates are included
+	      # in the archive.
+	      _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+	      ;;
+	    esac
+	    ;;
+	esac
+	;;
+
+      lynxos*)
+        # FIXME: insert proper C++ library support
+	_LT_TAGVAR(ld_shlibs, $1)=no
+	;;
+
+      m88k*)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+	;;
+
+      mvs*)
+        case $cc_basename in
+          cxx*)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+	  *)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+	esac
+	;;
+
+      netbsd*)
+        if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	  _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable  -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+	  wlarc=
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+	  _LT_TAGVAR(hardcode_direct, $1)=yes
+	  _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	fi
+	# Workaround some broken pre-1.5 toolchains
+	output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+	;;
+
+      *nto* | *qnx*)
+        _LT_TAGVAR(ld_shlibs, $1)=yes
+	;;
+
+      openbsd2*)
+        # C++ shared libraries are fairly broken
+	_LT_TAGVAR(ld_shlibs, $1)=no
+	;;
+
+      openbsd*)
+	if test -f /usr/libexec/ld.so; then
+	  _LT_TAGVAR(hardcode_direct, $1)=yes
+	  _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	  _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
+	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+	    _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+	  fi
+	  output_verbose_link_cmd=echo
+	else
+	  _LT_TAGVAR(ld_shlibs, $1)=no
+	fi
+	;;
+
+      osf3* | osf4* | osf5*)
+        case $cc_basename in
+          KCC*)
+	    # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+	    # KCC will only create a shared library if the output file
+	    # ends with ".so" (or ".sl" for HP-UX), so rename the library
+	    # to its proper name (with version) after linking.
+	    _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	    _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+	    # Archives containing C++ object files must be created using
+	    # the KAI C++ compiler.
+	    case $host in
+	      osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;;
+	      *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;;
+	    esac
+	    ;;
+          RCC*)
+	    # Rational C++ 2.4.1
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          cxx*)
+	    case $host in
+	      osf3*)
+	        _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && $ECHO "X${wl}-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+	        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+		;;
+	      *)
+	        _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+	        _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+	          echo "-hidden">> $lib.exp~
+	          $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp  `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~
+	          $RM $lib.exp'
+	        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+		;;
+	    esac
+
+	    _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+	    # Commands to make compiler produce verbose output that lists
+	    # what "hidden" libraries, object files and flags are used when
+	    # linking a shared library.
+	    #
+	    # There doesn't appear to be a way to prevent this compiler from
+	    # explicitly linking system object files so we need to strip them
+	    # from the output so that they don't get included in the library
+	    # dependencies.
+	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+	    ;;
+	  *)
+	    if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+	      _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+	      case $host in
+	        osf3*)
+	          _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+		  ;;
+	        *)
+	          _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+		  ;;
+	      esac
+
+	      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+	      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+	      # Commands to make compiler produce verbose output that lists
+	      # what "hidden" libraries, object files and flags are used when
+	      # linking a shared library.
+	      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
+
+	    else
+	      # FIXME: insert proper C++ library support
+	      _LT_TAGVAR(ld_shlibs, $1)=no
+	    fi
+	    ;;
+        esac
+        ;;
+
+      psos*)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+
+      sunos4*)
+        case $cc_basename in
+          CC*)
+	    # Sun C++ 4.x
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          lcc*)
+	    # Lucid
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          *)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+        esac
+        ;;
+
+      solaris*)
+        case $cc_basename in
+          CC*)
+	    # Sun C++ 4.2, 5.x and Centerline C++
+            _LT_TAGVAR(archive_cmds_need_lc,$1)=yes
+	    _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag}  -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	      $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+	    _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	    case $host_os in
+	      solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+	      *)
+		# The compiler driver will combine and reorder linker options,
+		# but understands `-z linker_flag'.
+	        # Supported since Solaris 2.6 (maybe 2.5.1?)
+		_LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+	        ;;
+	    esac
+	    _LT_TAGVAR(link_all_deplibs, $1)=yes
+
+	    output_verbose_link_cmd='echo'
+
+	    # Archives containing C++ object files must be created using
+	    # "CC -xar", where "CC" is the Sun C++ compiler.  This is
+	    # necessary to make sure instantiated templates are included
+	    # in the archive.
+	    _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+	    ;;
+          gcx*)
+	    # Green Hills C++ Compiler
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+
+	    # The C++ compiler must be used to create the archive.
+	    _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+	    ;;
+          *)
+	    # GNU C++ compiler with Solaris linker
+	    if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+	      _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs'
+	      if $CC --version | $GREP -v '^2\.7' > /dev/null; then
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+	        _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+		  $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+	        # Commands to make compiler produce verbose output that lists
+	        # what "hidden" libraries, object files and flags are used when
+	        # linking a shared library.
+	        output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
+	      else
+	        # g++ 2.7 appears to require `-G' NOT `-shared' on this
+	        # platform.
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+	        _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+		  $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+	        # Commands to make compiler produce verbose output that lists
+	        # what "hidden" libraries, object files and flags are used when
+	        # linking a shared library.
+	        output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
+	      fi
+
+	      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir'
+	      case $host_os in
+		solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+		*)
+		  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+		  ;;
+	      esac
+	    fi
+	    ;;
+        esac
+        ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+      _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      runpath_var='LD_RUN_PATH'
+
+      case $cc_basename in
+        CC*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+      esac
+      ;;
+
+      sysv5* | sco3.2v5* | sco5v6*)
+	# Note: We can NOT use -z defs as we might desire, because we do not
+	# link with -lc, and that would cause any symbols used from libc to
+	# always be unresolved, which means just about no library would
+	# ever link correctly.  If we're not using GNU ld we use -z text
+	# though, which does catch some bad symbols but isn't as heavy-handed
+	# as -z defs.
+	_LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+	_LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
+	_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+	_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir'
+	_LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+	_LT_TAGVAR(link_all_deplibs, $1)=yes
+	_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+	runpath_var='LD_RUN_PATH'
+
+	case $cc_basename in
+          CC*)
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	    ;;
+	  *)
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	    ;;
+	esac
+      ;;
+
+      tandem*)
+        case $cc_basename in
+          NCC*)
+	    # NonStop-UX NCC 3.20
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          *)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+        esac
+        ;;
+
+      vxworks*)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+
+      *)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+    esac
+
+    AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
+    test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+    _LT_TAGVAR(GCC, $1)="$GXX"
+    _LT_TAGVAR(LD, $1)="$LD"
+
+    ## CAVEAT EMPTOR:
+    ## There is no encapsulation within the following macros, do not change
+    ## the running order or otherwise move them around unless you know exactly
+    ## what you are doing...
+    _LT_SYS_HIDDEN_LIBDEPS($1)
+    _LT_COMPILER_PIC($1)
+    _LT_COMPILER_C_O($1)
+    _LT_COMPILER_FILE_LOCKS($1)
+    _LT_LINKER_SHLIBS($1)
+    _LT_SYS_DYNAMIC_LINKER($1)
+    _LT_LINKER_HARDCODE_LIBPATH($1)
+
+    _LT_CONFIG($1)
+  fi # test -n "$compiler"
+
+  CC=$lt_save_CC
+  LDCXX=$LD
+  LD=$lt_save_LD
+  GCC=$lt_save_GCC
+  with_gnu_ld=$lt_save_with_gnu_ld
+  lt_cv_path_LDCXX=$lt_cv_path_LD
+  lt_cv_path_LD=$lt_save_path_LD
+  lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+  lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+fi # test "$_lt_caught_CXX_error" != yes
+
+AC_LANG_POP
+])# _LT_LANG_CXX_CONFIG
+
+
+# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME])
+# ---------------------------------
+# Figure out "hidden" library dependencies from verbose
+# compiler output when linking a shared library.
+# Parse the compiler output and extract the necessary
+# objects, libraries and library flags.
+m4_defun([_LT_SYS_HIDDEN_LIBDEPS],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+# Dependencies to place before and after the object being linked:
+_LT_TAGVAR(predep_objects, $1)=
+_LT_TAGVAR(postdep_objects, $1)=
+_LT_TAGVAR(predeps, $1)=
+_LT_TAGVAR(postdeps, $1)=
+_LT_TAGVAR(compiler_lib_search_path, $1)=
+
+dnl we can't use the lt_simple_compile_test_code here,
+dnl because it contains code intended for an executable,
+dnl not a library.  It's possible we should let each
+dnl tag define a new lt_????_link_test_code variable,
+dnl but it's only used here...
+m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF
+int a;
+void foo (void) { a = 0; }
+_LT_EOF
+], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF
+class Foo
+{
+public:
+  Foo (void) { a = 0; }
+private:
+  int a;
+};
+_LT_EOF
+], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF
+      subroutine foo
+      implicit none
+      integer*4 a
+      a=0
+      return
+      end
+_LT_EOF
+], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF
+      subroutine foo
+      implicit none
+      integer a
+      a=0
+      return
+      end
+_LT_EOF
+], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF
+public class foo {
+  private int a;
+  public void bar (void) {
+    a = 0;
+  }
+};
+_LT_EOF
+])
+dnl Parse the compiler output and extract the necessary
+dnl objects, libraries and library flags.
+if AC_TRY_EVAL(ac_compile); then
+  # Parse the compiler output and extract the necessary
+  # objects, libraries and library flags.
+
+  # Sentinel used to keep track of whether or not we are before
+  # the conftest object file.
+  pre_test_object_deps_done=no
+
+  for p in `eval "$output_verbose_link_cmd"`; do
+    case $p in
+
+    -L* | -R* | -l*)
+       # Some compilers place space between "-{L,R}" and the path.
+       # Remove the space.
+       if test $p = "-L" ||
+          test $p = "-R"; then
+	 prev=$p
+	 continue
+       else
+	 prev=
+       fi
+
+       if test "$pre_test_object_deps_done" = no; then
+	 case $p in
+	 -L* | -R*)
+	   # Internal compiler library paths should come after those
+	   # provided the user.  The postdeps already come after the
+	   # user supplied libs so there is no need to process them.
+	   if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then
+	     _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}"
+	   else
+	     _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}"
+	   fi
+	   ;;
+	 # The "-l" case would never come before the object being
+	 # linked, so don't bother handling this case.
+	 esac
+       else
+	 if test -z "$_LT_TAGVAR(postdeps, $1)"; then
+	   _LT_TAGVAR(postdeps, $1)="${prev}${p}"
+	 else
+	   _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}"
+	 fi
+       fi
+       ;;
+
+    *.$objext)
+       # This assumes that the test object file only shows up
+       # once in the compiler output.
+       if test "$p" = "conftest.$objext"; then
+	 pre_test_object_deps_done=yes
+	 continue
+       fi
+
+       if test "$pre_test_object_deps_done" = no; then
+	 if test -z "$_LT_TAGVAR(predep_objects, $1)"; then
+	   _LT_TAGVAR(predep_objects, $1)="$p"
+	 else
+	   _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p"
+	 fi
+       else
+	 if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then
+	   _LT_TAGVAR(postdep_objects, $1)="$p"
+	 else
+	   _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p"
+	 fi
+       fi
+       ;;
+
+    *) ;; # Ignore the rest.
+
+    esac
+  done
+
+  # Clean up.
+  rm -f a.out a.exe
+else
+  echo "libtool.m4: error: problem compiling $1 test program"
+fi
+
+$RM -f confest.$objext
+
+# PORTME: override above test on systems where it is broken
+m4_if([$1], [CXX],
+[case $host_os in
+interix[[3-9]]*)
+  # Interix 3.5 installs completely hosed .la files for C++, so rather than
+  # hack all around it, let's just trust "g++" to DTRT.
+  _LT_TAGVAR(predep_objects,$1)=
+  _LT_TAGVAR(postdep_objects,$1)=
+  _LT_TAGVAR(postdeps,$1)=
+  ;;
+
+linux*)
+  case `$CC -V 2>&1 | sed 5q` in
+  *Sun\ C*)
+    # Sun C++ 5.9
+
+    # The more standards-conforming stlport4 library is
+    # incompatible with the Cstd library. Avoid specifying
+    # it if it's in CXXFLAGS. Ignore libCrun as
+    # -library=stlport4 depends on it.
+    case " $CXX $CXXFLAGS " in
+    *" -library=stlport4 "*)
+      solaris_use_stlport4=yes
+      ;;
+    esac
+
+    if test "$solaris_use_stlport4" != yes; then
+      _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
+    fi
+    ;;
+  esac
+  ;;
+
+solaris*)
+  case $cc_basename in
+  CC*)
+    # The more standards-conforming stlport4 library is
+    # incompatible with the Cstd library. Avoid specifying
+    # it if it's in CXXFLAGS. Ignore libCrun as
+    # -library=stlport4 depends on it.
+    case " $CXX $CXXFLAGS " in
+    *" -library=stlport4 "*)
+      solaris_use_stlport4=yes
+      ;;
+    esac
+
+    # Adding this requires a known-good setup of shared libraries for
+    # Sun compiler versions before 5.6, else PIC objects from an old
+    # archive will be linked into the output, leading to subtle bugs.
+    if test "$solaris_use_stlport4" != yes; then
+      _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
+    fi
+    ;;
+  esac
+  ;;
+esac
+])
+
+case " $_LT_TAGVAR(postdeps, $1) " in
+*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;;
+esac
+ _LT_TAGVAR(compiler_lib_search_dirs, $1)=
+if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then
+ _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'`
+fi
+_LT_TAGDECL([], [compiler_lib_search_dirs], [1],
+    [The directories searched by this compiler when creating a shared library])
+_LT_TAGDECL([], [predep_objects], [1],
+    [Dependencies to place before and after the objects being linked to
+    create a shared library])
+_LT_TAGDECL([], [postdep_objects], [1])
+_LT_TAGDECL([], [predeps], [1])
+_LT_TAGDECL([], [postdeps], [1])
+_LT_TAGDECL([], [compiler_lib_search_path], [1],
+    [The library search path used internally by the compiler when linking
+    a shared library])
+])# _LT_SYS_HIDDEN_LIBDEPS
+
+
+# _LT_PROG_F77
+# ------------
+# Since AC_PROG_F77 is broken, in that it returns the empty string
+# if there is no fortran compiler, we have our own version here.
+m4_defun([_LT_PROG_F77],
+[
+pushdef([AC_MSG_ERROR], [_lt_disable_F77=yes])
+AC_PROG_F77
+if test -z "$F77" || test "X$F77" = "Xno"; then
+  _lt_disable_F77=yes
+fi
+popdef([AC_MSG_ERROR])
+])# _LT_PROG_F77
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([_LT_PROG_F77], [])
+
+
+# _LT_LANG_F77_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for a Fortran 77 compiler are
+# suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_F77_CONFIG],
+[AC_REQUIRE([_LT_PROG_F77])dnl
+AC_LANG_PUSH(Fortran 77)
+
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for f77 test sources.
+ac_ext=f
+
+# Object file extension for compiled f77 test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the F77 compiler isn't working.  Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test "$_lt_disable_F77" != yes; then
+  # Code to be used in simple compile tests
+  lt_simple_compile_test_code="\
+      subroutine t
+      return
+      end
+"
+
+  # Code to be used in simple link tests
+  lt_simple_link_test_code="\
+      program t
+      end
+"
+
+  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+  _LT_TAG_COMPILER
+
+  # save warnings/boilerplate of simple test code
+  _LT_COMPILER_BOILERPLATE
+  _LT_LINKER_BOILERPLATE
+
+  # Allow CC to be a program name with arguments.
+  lt_save_CC="$CC"
+  lt_save_GCC=$GCC
+  CC=${F77-"f77"}
+  compiler=$CC
+  _LT_TAGVAR(compiler, $1)=$CC
+  _LT_CC_BASENAME([$compiler])
+  GCC=$G77
+  if test -n "$compiler"; then
+    AC_MSG_CHECKING([if libtool supports shared libraries])
+    AC_MSG_RESULT([$can_build_shared])
+
+    AC_MSG_CHECKING([whether to build shared libraries])
+    test "$can_build_shared" = "no" && enable_shared=no
+
+    # On AIX, shared libraries and static libraries use the same namespace, and
+    # are all built from PIC.
+    case $host_os in
+      aix3*)
+        test "$enable_shared" = yes && enable_static=no
+        if test -n "$RANLIB"; then
+          archive_cmds="$archive_cmds~\$RANLIB \$lib"
+          postinstall_cmds='$RANLIB $lib'
+        fi
+        ;;
+      aix[[4-9]]*)
+	if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+	  test "$enable_shared" = yes && enable_static=no
+	fi
+        ;;
+    esac
+    AC_MSG_RESULT([$enable_shared])
+
+    AC_MSG_CHECKING([whether to build static libraries])
+    # Make sure either enable_shared or enable_static is yes.
+    test "$enable_shared" = yes || enable_static=yes
+    AC_MSG_RESULT([$enable_static])
+
+    _LT_TAGVAR(GCC, $1)="$G77"
+    _LT_TAGVAR(LD, $1)="$LD"
+
+    ## CAVEAT EMPTOR:
+    ## There is no encapsulation within the following macros, do not change
+    ## the running order or otherwise move them around unless you know exactly
+    ## what you are doing...
+    _LT_COMPILER_PIC($1)
+    _LT_COMPILER_C_O($1)
+    _LT_COMPILER_FILE_LOCKS($1)
+    _LT_LINKER_SHLIBS($1)
+    _LT_SYS_DYNAMIC_LINKER($1)
+    _LT_LINKER_HARDCODE_LIBPATH($1)
+
+    _LT_CONFIG($1)
+  fi # test -n "$compiler"
+
+  GCC=$lt_save_GCC
+  CC="$lt_save_CC"
+fi # test "$_lt_disable_F77" != yes
+
+AC_LANG_POP
+])# _LT_LANG_F77_CONFIG
+
+
+# _LT_PROG_FC
+# -----------
+# Since AC_PROG_FC is broken, in that it returns the empty string
+# if there is no fortran compiler, we have our own version here.
+m4_defun([_LT_PROG_FC],
+[
+pushdef([AC_MSG_ERROR], [_lt_disable_FC=yes])
+AC_PROG_FC
+if test -z "$FC" || test "X$FC" = "Xno"; then
+  _lt_disable_FC=yes
+fi
+popdef([AC_MSG_ERROR])
+])# _LT_PROG_FC
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([_LT_PROG_FC], [])
+
+
+# _LT_LANG_FC_CONFIG([TAG])
+# -------------------------
+# Ensure that the configuration variables for a Fortran compiler are
+# suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_FC_CONFIG],
+[AC_REQUIRE([_LT_PROG_FC])dnl
+AC_LANG_PUSH(Fortran)
+
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for fc test sources.
+ac_ext=${ac_fc_srcext-f}
+
+# Object file extension for compiled fc test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the FC compiler isn't working.  Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test "$_lt_disable_FC" != yes; then
+  # Code to be used in simple compile tests
+  lt_simple_compile_test_code="\
+      subroutine t
+      return
+      end
+"
+
+  # Code to be used in simple link tests
+  lt_simple_link_test_code="\
+      program t
+      end
+"
+
+  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+  _LT_TAG_COMPILER
+
+  # save warnings/boilerplate of simple test code
+  _LT_COMPILER_BOILERPLATE
+  _LT_LINKER_BOILERPLATE
+
+  # Allow CC to be a program name with arguments.
+  lt_save_CC="$CC"
+  lt_save_GCC=$GCC
+  CC=${FC-"f95"}
+  compiler=$CC
+  GCC=$ac_cv_fc_compiler_gnu
+
+  _LT_TAGVAR(compiler, $1)=$CC
+  _LT_CC_BASENAME([$compiler])
+
+  if test -n "$compiler"; then
+    AC_MSG_CHECKING([if libtool supports shared libraries])
+    AC_MSG_RESULT([$can_build_shared])
+
+    AC_MSG_CHECKING([whether to build shared libraries])
+    test "$can_build_shared" = "no" && enable_shared=no
+
+    # On AIX, shared libraries and static libraries use the same namespace, and
+    # are all built from PIC.
+    case $host_os in
+      aix3*)
+        test "$enable_shared" = yes && enable_static=no
+        if test -n "$RANLIB"; then
+          archive_cmds="$archive_cmds~\$RANLIB \$lib"
+          postinstall_cmds='$RANLIB $lib'
+        fi
+        ;;
+      aix[[4-9]]*)
+	if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+	  test "$enable_shared" = yes && enable_static=no
+	fi
+        ;;
+    esac
+    AC_MSG_RESULT([$enable_shared])
+
+    AC_MSG_CHECKING([whether to build static libraries])
+    # Make sure either enable_shared or enable_static is yes.
+    test "$enable_shared" = yes || enable_static=yes
+    AC_MSG_RESULT([$enable_static])
+
+    _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu"
+    _LT_TAGVAR(LD, $1)="$LD"
+
+    ## CAVEAT EMPTOR:
+    ## There is no encapsulation within the following macros, do not change
+    ## the running order or otherwise move them around unless you know exactly
+    ## what you are doing...
+    _LT_SYS_HIDDEN_LIBDEPS($1)
+    _LT_COMPILER_PIC($1)
+    _LT_COMPILER_C_O($1)
+    _LT_COMPILER_FILE_LOCKS($1)
+    _LT_LINKER_SHLIBS($1)
+    _LT_SYS_DYNAMIC_LINKER($1)
+    _LT_LINKER_HARDCODE_LIBPATH($1)
+
+    _LT_CONFIG($1)
+  fi # test -n "$compiler"
+
+  GCC=$lt_save_GCC
+  CC="$lt_save_CC"
+fi # test "$_lt_disable_FC" != yes
+
+AC_LANG_POP
+])# _LT_LANG_FC_CONFIG
+
+
+# _LT_LANG_GCJ_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for the GNU Java Compiler compiler
+# are suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_GCJ_CONFIG],
+[AC_REQUIRE([LT_PROG_GCJ])dnl
+AC_LANG_SAVE
+
+# Source file extension for Java test sources.
+ac_ext=java
+
+# Object file extension for compiled Java test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="class foo {}"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+lt_save_GCC=$GCC
+GCC=yes
+CC=${GCJ-"gcj"}
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_TAGVAR(LD, $1)="$LD"
+_LT_CC_BASENAME([$compiler])
+
+# GCJ did not exist at the time GCC didn't implicitly link libc in.
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+  _LT_COMPILER_NO_RTTI($1)
+  _LT_COMPILER_PIC($1)
+  _LT_COMPILER_C_O($1)
+  _LT_COMPILER_FILE_LOCKS($1)
+  _LT_LINKER_SHLIBS($1)
+  _LT_LINKER_HARDCODE_LIBPATH($1)
+
+  _LT_CONFIG($1)
+fi
+
+AC_LANG_RESTORE
+
+GCC=$lt_save_GCC
+CC="$lt_save_CC"
+])# _LT_LANG_GCJ_CONFIG
+
+
+# _LT_LANG_RC_CONFIG([TAG])
+# -------------------------
+# Ensure that the configuration variables for the Windows resource compiler
+# are suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_RC_CONFIG],
+[AC_REQUIRE([LT_PROG_RC])dnl
+AC_LANG_SAVE
+
+# Source file extension for RC test sources.
+ac_ext=rc
+
+# Object file extension for compiled RC test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }'
+
+# Code to be used in simple link tests
+lt_simple_link_test_code="$lt_simple_compile_test_code"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+lt_save_GCC=$GCC
+GCC=
+CC=${RC-"windres"}
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+
+if test -n "$compiler"; then
+  :
+  _LT_CONFIG($1)
+fi
+
+GCC=$lt_save_GCC
+AC_LANG_RESTORE
+CC="$lt_save_CC"
+])# _LT_LANG_RC_CONFIG
+
+
+# LT_PROG_GCJ
+# -----------
+AC_DEFUN([LT_PROG_GCJ],
+[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ],
+  [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ],
+    [AC_CHECK_TOOL(GCJ, gcj,)
+      test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2"
+      AC_SUBST(GCJFLAGS)])])[]dnl
+])
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_GCJ], [])
+
+
+# LT_PROG_RC
+# ----------
+AC_DEFUN([LT_PROG_RC],
+[AC_CHECK_TOOL(RC, windres,)
+])
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_RC], [])
+
+
+# _LT_DECL_EGREP
+# --------------
+# If we don't have a new enough Autoconf to choose the best grep
+# available, choose the one first in the user's PATH.
+m4_defun([_LT_DECL_EGREP],
+[AC_REQUIRE([AC_PROG_EGREP])dnl
+AC_REQUIRE([AC_PROG_FGREP])dnl
+test -z "$GREP" && GREP=grep
+_LT_DECL([], [GREP], [1], [A grep program that handles long lines])
+_LT_DECL([], [EGREP], [1], [An ERE matcher])
+_LT_DECL([], [FGREP], [1], [A literal string matcher])
+dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too
+AC_SUBST([GREP])
+])
+
+
+# _LT_DECL_SED
+# ------------
+# Check for a fully-functional sed program, that truncates
+# as few characters as possible.  Prefer GNU sed if found.
+m4_defun([_LT_DECL_SED],
+[AC_PROG_SED
+test -z "$SED" && SED=sed
+Xsed="$SED -e 1s/^X//"
+_LT_DECL([], [SED], [1], [A sed program that does not truncate output])
+_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"],
+    [Sed that helps us avoid accidentally triggering echo(1) options like -n])
+])# _LT_DECL_SED
+
+m4_ifndef([AC_PROG_SED], [
+############################################################
+# NOTE: This macro has been submitted for inclusion into   #
+#  GNU Autoconf as AC_PROG_SED.  When it is available in   #
+#  a released version of Autoconf we should remove this    #
+#  macro and use it instead.                               #
+############################################################
+
+m4_defun([AC_PROG_SED],
+[AC_MSG_CHECKING([for a sed that does not truncate output])
+AC_CACHE_VAL(lt_cv_path_SED,
+[# Loop through the user's path and test for sed and gsed.
+# Then use that list of sed's as ones to test for truncation.
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for lt_ac_prog in sed gsed; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
+        lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
+      fi
+    done
+  done
+done
+IFS=$as_save_IFS
+lt_ac_max=0
+lt_ac_count=0
+# Add /usr/xpg4/bin/sed as it is typically found on Solaris
+# along with /bin/sed that truncates output.
+for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
+  test ! -f $lt_ac_sed && continue
+  cat /dev/null > conftest.in
+  lt_ac_count=0
+  echo $ECHO_N "0123456789$ECHO_C" >conftest.in
+  # Check for GNU sed and select it if it is found.
+  if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
+    lt_cv_path_SED=$lt_ac_sed
+    break
+  fi
+  while true; do
+    cat conftest.in conftest.in >conftest.tmp
+    mv conftest.tmp conftest.in
+    cp conftest.in conftest.nl
+    echo >>conftest.nl
+    $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
+    cmp -s conftest.out conftest.nl || break
+    # 10000 chars as input seems more than enough
+    test $lt_ac_count -gt 10 && break
+    lt_ac_count=`expr $lt_ac_count + 1`
+    if test $lt_ac_count -gt $lt_ac_max; then
+      lt_ac_max=$lt_ac_count
+      lt_cv_path_SED=$lt_ac_sed
+    fi
+  done
+done
+])
+SED=$lt_cv_path_SED
+AC_SUBST([SED])
+AC_MSG_RESULT([$SED])
+])#AC_PROG_SED
+])#m4_ifndef
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_SED], [])
+
+
+# _LT_CHECK_SHELL_FEATURES
+# ------------------------
+# Find out whether the shell is Bourne or XSI compatible,
+# or has some other useful features.
+m4_defun([_LT_CHECK_SHELL_FEATURES],
+[AC_MSG_CHECKING([whether the shell understands some XSI constructs])
+# Try some XSI features
+xsi_shell=no
+( _lt_dummy="a/b/c"
+  test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \
+      = c,a/b,, \
+    && eval 'test $(( 1 + 1 )) -eq 2 \
+    && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \
+  && xsi_shell=yes
+AC_MSG_RESULT([$xsi_shell])
+_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell'])
+
+AC_MSG_CHECKING([whether the shell understands "+="])
+lt_shell_append=no
+( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \
+    >/dev/null 2>&1 \
+  && lt_shell_append=yes
+AC_MSG_RESULT([$lt_shell_append])
+_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append'])
+
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  lt_unset=unset
+else
+  lt_unset=false
+fi
+_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl
+
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+    # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+  lt_SP2NL='tr \040 \012'
+  lt_NL2SP='tr \015\012 \040\040'
+  ;;
+ *) # EBCDIC based system
+  lt_SP2NL='tr \100 \n'
+  lt_NL2SP='tr \r\n \100\100'
+  ;;
+esac
+_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl
+_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl
+])# _LT_CHECK_SHELL_FEATURES
+
+
+# _LT_PROG_XSI_SHELLFNS
+# ---------------------
+# Bourne and XSI compatible variants of some useful shell functions.
+m4_defun([_LT_PROG_XSI_SHELLFNS],
+[case $xsi_shell in
+  yes)
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE.  If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+  case ${1} in
+    */*) func_dirname_result="${1%/*}${2}" ;;
+    *  ) func_dirname_result="${3}" ;;
+  esac
+}
+
+# func_basename file
+func_basename ()
+{
+  func_basename_result="${1##*/}"
+}
+
+# func_dirname_and_basename file append nondir_replacement
+# perform func_basename and func_dirname in a single function
+# call:
+#   dirname:  Compute the dirname of FILE.  If nonempty,
+#             add APPEND to the result, otherwise set result
+#             to NONDIR_REPLACEMENT.
+#             value returned in "$func_dirname_result"
+#   basename: Compute filename of FILE.
+#             value retuned in "$func_basename_result"
+# Implementation must be kept synchronized with func_dirname
+# and func_basename. For efficiency, we do not delegate to
+# those functions but instead duplicate the functionality here.
+func_dirname_and_basename ()
+{
+  case ${1} in
+    */*) func_dirname_result="${1%/*}${2}" ;;
+    *  ) func_dirname_result="${3}" ;;
+  esac
+  func_basename_result="${1##*/}"
+}
+
+# func_stripname prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+func_stripname ()
+{
+  # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
+  # positional parameters, so assign one to ordinary parameter first.
+  func_stripname_result=${3}
+  func_stripname_result=${func_stripname_result#"${1}"}
+  func_stripname_result=${func_stripname_result%"${2}"}
+}
+
+# func_opt_split
+func_opt_split ()
+{
+  func_opt_split_opt=${1%%=*}
+  func_opt_split_arg=${1#*=}
+}
+
+# func_lo2o object
+func_lo2o ()
+{
+  case ${1} in
+    *.lo) func_lo2o_result=${1%.lo}.${objext} ;;
+    *)    func_lo2o_result=${1} ;;
+  esac
+}
+
+# func_xform libobj-or-source
+func_xform ()
+{
+  func_xform_result=${1%.*}.lo
+}
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+  func_arith_result=$(( $[*] ))
+}
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+  func_len_result=${#1}
+}
+
+_LT_EOF
+    ;;
+  *) # Bourne compatible functions.
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE.  If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+  # Extract subdirectory from the argument.
+  func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"`
+  if test "X$func_dirname_result" = "X${1}"; then
+    func_dirname_result="${3}"
+  else
+    func_dirname_result="$func_dirname_result${2}"
+  fi
+}
+
+# func_basename file
+func_basename ()
+{
+  func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"`
+}
+
+dnl func_dirname_and_basename
+dnl A portable version of this function is already defined in general.m4sh
+dnl so there is no need for it here.
+
+# func_stripname prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+# func_strip_suffix prefix name
+func_stripname ()
+{
+  case ${2} in
+    .*) func_stripname_result=`$ECHO "X${3}" \
+           | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;;
+    *)  func_stripname_result=`$ECHO "X${3}" \
+           | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;;
+  esac
+}
+
+# sed scripts:
+my_sed_long_opt='1s/^\(-[[^=]]*\)=.*/\1/;q'
+my_sed_long_arg='1s/^-[[^=]]*=//'
+
+# func_opt_split
+func_opt_split ()
+{
+  func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"`
+  func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"`
+}
+
+# func_lo2o object
+func_lo2o ()
+{
+  func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"`
+}
+
+# func_xform libobj-or-source
+func_xform ()
+{
+  func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[[^.]]*$/.lo/'`
+}
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+  func_arith_result=`expr "$[@]"`
+}
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+  func_len_result=`expr "$[1]" : ".*" 2>/dev/null || echo $max_cmd_len`
+}
+
+_LT_EOF
+esac
+
+case $lt_shell_append in
+  yes)
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+  eval "$[1]+=\$[2]"
+}
+_LT_EOF
+    ;;
+  *)
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+  eval "$[1]=\$$[1]\$[2]"
+}
+
+_LT_EOF
+    ;;
+  esac
+])
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/config/ltoptions.m4 b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/config/ltoptions.m4
new file mode 100644
index 0000000..e970119
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/config/ltoptions.m4
@@ -0,0 +1,368 @@
+# Helper functions for option handling.                    -*- Autoconf -*-
+#
+#   Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
+#   Written by Gary V. Vaughan, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 6 ltoptions.m4
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
+
+
+# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)
+# ------------------------------------------
+m4_define([_LT_MANGLE_OPTION],
+[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])
+
+
+# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)
+# ---------------------------------------
+# Set option OPTION-NAME for macro MACRO-NAME, and if there is a
+# matching handler defined, dispatch to it.  Other OPTION-NAMEs are
+# saved as a flag.
+m4_define([_LT_SET_OPTION],
+[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
+m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
+        _LT_MANGLE_DEFUN([$1], [$2]),
+    [m4_warning([Unknown $1 option `$2'])])[]dnl
+])
+
+
+# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])
+# ------------------------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+m4_define([_LT_IF_OPTION],
+[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])
+
+
+# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)
+# -------------------------------------------------------
+# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME
+# are set.
+m4_define([_LT_UNLESS_OPTIONS],
+[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
+	    [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),
+		      [m4_define([$0_found])])])[]dnl
+m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3
+])[]dnl
+])
+
+
+# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)
+# ----------------------------------------
+# OPTION-LIST is a space-separated list of Libtool options associated
+# with MACRO-NAME.  If any OPTION has a matching handler declared with
+# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about
+# the unknown option and exit.
+m4_defun([_LT_SET_OPTIONS],
+[# Set options
+m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
+    [_LT_SET_OPTION([$1], _LT_Option)])
+
+m4_if([$1],[LT_INIT],[
+  dnl
+  dnl Simply set some default values (i.e off) if boolean options were not
+  dnl specified:
+  _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no
+  ])
+  _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no
+  ])
+  dnl
+  dnl If no reference was made to various pairs of opposing options, then
+  dnl we run the default mode handler for the pair.  For example, if neither
+  dnl `shared' nor `disable-shared' was passed, we enable building of shared
+  dnl archives by default:
+  _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
+  _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
+  _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
+  _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
+  		   [_LT_ENABLE_FAST_INSTALL])
+  ])
+])# _LT_SET_OPTIONS
+
+
+## --------------------------------- ##
+## Macros to handle LT_INIT options. ##
+## --------------------------------- ##
+
+# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)
+# -----------------------------------------
+m4_define([_LT_MANGLE_DEFUN],
+[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])
+
+
+# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)
+# -----------------------------------------------
+m4_define([LT_OPTION_DEFINE],
+[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl
+])# LT_OPTION_DEFINE
+
+
+# dlopen
+# ------
+LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes
+])
+
+AU_DEFUN([AC_LIBTOOL_DLOPEN],
+[_LT_SET_OPTION([LT_INIT], [dlopen])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the `dlopen' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])
+
+
+# win32-dll
+# ---------
+# Declare package support for building win32 dll's.
+LT_OPTION_DEFINE([LT_INIT], [win32-dll],
+[enable_win32_dll=yes
+
+case $host in
+*-*-cygwin* | *-*-mingw* | *-*-pw32*)
+  AC_CHECK_TOOL(AS, as, false)
+  AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+  AC_CHECK_TOOL(OBJDUMP, objdump, false)
+  ;;
+esac
+
+test -z "$AS" && AS=as
+_LT_DECL([], [AS],      [0], [Assembler program])dnl
+
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+_LT_DECL([], [DLLTOOL], [0], [DLL creation program])dnl
+
+test -z "$OBJDUMP" && OBJDUMP=objdump
+_LT_DECL([], [OBJDUMP], [0], [Object dumper program])dnl
+])# win32-dll
+
+AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+_LT_SET_OPTION([LT_INIT], [win32-dll])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the `win32-dll' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])
+
+
+# _LT_ENABLE_SHARED([DEFAULT])
+# ----------------------------
+# implement the --enable-shared flag, and supports the `shared' and
+# `disable-shared' LT_INIT options.
+# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.
+m4_define([_LT_ENABLE_SHARED],
+[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([shared],
+    [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
+	[build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_shared=yes ;;
+    no) enable_shared=no ;;
+    *)
+      enable_shared=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_shared=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac],
+    [enable_shared=]_LT_ENABLE_SHARED_DEFAULT)
+
+    _LT_DECL([build_libtool_libs], [enable_shared], [0],
+	[Whether or not to build shared libraries])
+])# _LT_ENABLE_SHARED
+
+LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])
+
+# Old names:
+AC_DEFUN([AC_ENABLE_SHARED],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])
+])
+
+AC_DEFUN([AC_DISABLE_SHARED],
+[_LT_SET_OPTION([LT_INIT], [disable-shared])
+])
+
+AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
+AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_ENABLE_SHARED], [])
+dnl AC_DEFUN([AM_DISABLE_SHARED], [])
+
+
+
+# _LT_ENABLE_STATIC([DEFAULT])
+# ----------------------------
+# implement the --enable-static flag, and support the `static' and
+# `disable-static' LT_INIT options.
+# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.
+m4_define([_LT_ENABLE_STATIC],
+[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([static],
+    [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],
+	[build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_static=yes ;;
+    no) enable_static=no ;;
+    *)
+     enable_static=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_static=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac],
+    [enable_static=]_LT_ENABLE_STATIC_DEFAULT)
+
+    _LT_DECL([build_old_libs], [enable_static], [0],
+	[Whether or not to build static libraries])
+])# _LT_ENABLE_STATIC
+
+LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])
+
+# Old names:
+AC_DEFUN([AC_ENABLE_STATIC],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])
+])
+
+AC_DEFUN([AC_DISABLE_STATIC],
+[_LT_SET_OPTION([LT_INIT], [disable-static])
+])
+
+AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
+AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_ENABLE_STATIC], [])
+dnl AC_DEFUN([AM_DISABLE_STATIC], [])
+
+
+
+# _LT_ENABLE_FAST_INSTALL([DEFAULT])
+# ----------------------------------
+# implement the --enable-fast-install flag, and support the `fast-install'
+# and `disable-fast-install' LT_INIT options.
+# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.
+m4_define([_LT_ENABLE_FAST_INSTALL],
+[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([fast-install],
+    [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
+    [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_fast_install=yes ;;
+    no) enable_fast_install=no ;;
+    *)
+      enable_fast_install=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_fast_install=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac],
+    [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)
+
+_LT_DECL([fast_install], [enable_fast_install], [0],
+	 [Whether or not to optimize for fast installation])dnl
+])# _LT_ENABLE_FAST_INSTALL
+
+LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])
+
+# Old names:
+AU_DEFUN([AC_ENABLE_FAST_INSTALL],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you put
+the `fast-install' option into LT_INIT's first parameter.])
+])
+
+AU_DEFUN([AC_DISABLE_FAST_INSTALL],
+[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you put
+the `disable-fast-install' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
+dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])
+
+
+# _LT_WITH_PIC([MODE])
+# --------------------
+# implement the --with-pic flag, and support the `pic-only' and `no-pic'
+# LT_INIT options.
+# MODE is either `yes' or `no'.  If omitted, it defaults to `both'.
+m4_define([_LT_WITH_PIC],
+[AC_ARG_WITH([pic],
+    [AS_HELP_STRING([--with-pic],
+	[try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
+    [pic_mode="$withval"],
+    [pic_mode=default])
+
+test -z "$pic_mode" && pic_mode=m4_default([$1], [default])
+
+_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
+])# _LT_WITH_PIC
+
+LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])
+LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])
+
+# Old name:
+AU_DEFUN([AC_LIBTOOL_PICMODE],
+[_LT_SET_OPTION([LT_INIT], [pic-only])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the `pic-only' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])
+
+## ----------------- ##
+## LTDL_INIT Options ##
+## ----------------- ##
+
+m4_define([_LTDL_MODE], [])
+LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],
+		 [m4_define([_LTDL_MODE], [nonrecursive])])
+LT_OPTION_DEFINE([LTDL_INIT], [recursive],
+		 [m4_define([_LTDL_MODE], [recursive])])
+LT_OPTION_DEFINE([LTDL_INIT], [subproject],
+		 [m4_define([_LTDL_MODE], [subproject])])
+
+m4_define([_LTDL_TYPE], [])
+LT_OPTION_DEFINE([LTDL_INIT], [installable],
+		 [m4_define([_LTDL_TYPE], [installable])])
+LT_OPTION_DEFINE([LTDL_INIT], [convenience],
+		 [m4_define([_LTDL_TYPE], [convenience])])
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/config/ltsugar.m4 b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/config/ltsugar.m4
new file mode 100644
index 0000000..0d258e0
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/config/ltsugar.m4
@@ -0,0 +1,123 @@
+# ltsugar.m4 -- libtool m4 base layer.                         -*-Autoconf-*-
+#
+#   Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
+#   Written by Gary V. Vaughan, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 5 ltsugar.m4
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
+
+
+# lt_join(SEP, ARG1, [ARG2...])
+# -----------------------------
+# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
+# associated separator.
+# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
+# versions in m4sugar had bugs.
+m4_define([lt_join],
+[m4_if([$#], [1], [],
+       [$#], [2], [[$2]],
+       [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
+m4_define([_lt_join],
+[m4_if([$#$2], [2], [],
+       [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
+
+
+# lt_car(LIST)
+# lt_cdr(LIST)
+# ------------
+# Manipulate m4 lists.
+# These macros are necessary as long as will still need to support
+# Autoconf-2.59 which quotes differently.
+m4_define([lt_car], [[$1]])
+m4_define([lt_cdr],
+[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
+       [$#], 1, [],
+       [m4_dquote(m4_shift($@))])])
+m4_define([lt_unquote], $1)
+
+
+# lt_append(MACRO-NAME, STRING, [SEPARATOR])
+# ------------------------------------------
+# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'.
+# Note that neither SEPARATOR nor STRING are expanded; they are appended
+# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
+# No SEPARATOR is output if MACRO-NAME was previously undefined (different
+# than defined and empty).
+#
+# This macro is needed until we can rely on Autoconf 2.62, since earlier
+# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
+m4_define([lt_append],
+[m4_define([$1],
+	   m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
+
+
+
+# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
+# ----------------------------------------------------------
+# Produce a SEP delimited list of all paired combinations of elements of
+# PREFIX-LIST with SUFFIX1 through SUFFIXn.  Each element of the list
+# has the form PREFIXmINFIXSUFFIXn.
+m4_define([lt_combine],
+[m4_if([$2], [], [],
+  [m4_if([$4], [], [],
+    [lt_join(m4_quote(m4_default([$1], [[, ]])),
+      lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_prefix, [$2],
+		   [m4_foreach(_Lt_suffix, lt_car([m4_shiftn(3, $@)]),
+			       [_Lt_prefix[]$3[]_Lt_suffix ])])))))])])dnl
+])
+
+
+# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
+# -----------------------------------------------------------------------
+# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
+# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
+m4_define([lt_if_append_uniq],
+[m4_ifdef([$1],
+	  [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
+		 [lt_append([$1], [$2], [$3])$4],
+		 [$5])],
+	  [lt_append([$1], [$2], [$3])$4])])
+
+
+# lt_dict_add(DICT, KEY, VALUE)
+# -----------------------------
+m4_define([lt_dict_add],
+[m4_define([$1($2)], [$3])])
+
+
+# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
+# --------------------------------------------
+m4_define([lt_dict_add_subkey],
+[m4_define([$1($2:$3)], [$4])])
+
+
+# lt_dict_fetch(DICT, KEY, [SUBKEY])
+# ----------------------------------
+m4_define([lt_dict_fetch],
+[m4_ifval([$3],
+	m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
+    m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
+
+
+# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
+# -----------------------------------------------------------------
+m4_define([lt_if_dict_fetch],
+[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
+	[$5],
+    [$6])])
+
+
+# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
+# --------------------------------------------------------------
+m4_define([lt_dict_filter],
+[m4_if([$5], [], [],
+  [lt_join(m4_quote(m4_default([$4], [[, ]])),
+           lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
+		      [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
+])
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/config/ltversion.m4 b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/config/ltversion.m4
new file mode 100644
index 0000000..45cb155
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/config/ltversion.m4
@@ -0,0 +1,23 @@
+# ltversion.m4 -- version numbers			-*- Autoconf -*-
+#
+#   Copyright (C) 2004 Free Software Foundation, Inc.
+#   Written by Scott James Remnant, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# Generated from ltversion.in.
+
+# serial 2976 ltversion.m4
+# This file is part of GNU Libtool
+
+m4_define([LT_PACKAGE_VERSION], [2.2.4])
+m4_define([LT_PACKAGE_REVISION], [1.2976])
+
+AC_DEFUN([LTVERSION_VERSION],
+[macro_version='2.2.4'
+macro_revision='1.2976'
+_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
+_LT_DECL(, macro_revision, 0)
+])
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/config/lt~obsolete.m4 b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/config/lt~obsolete.m4
new file mode 100644
index 0000000..637bb20
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/config/lt~obsolete.m4
@@ -0,0 +1,92 @@
+# lt~obsolete.m4 -- aclocal satisfying obsolete definitions.    -*-Autoconf-*-
+#
+#   Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
+#   Written by Scott James Remnant, 2004.
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 4 lt~obsolete.m4
+
+# These exist entirely to fool aclocal when bootstrapping libtool.
+#
+# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN)
+# which have later been changed to m4_define as they aren't part of the
+# exported API, or moved to Autoconf or Automake where they belong.
+#
+# The trouble is, aclocal is a bit thick.  It'll see the old AC_DEFUN
+# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
+# using a macro with the same name in our local m4/libtool.m4 it'll
+# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
+# and doesn't know about Autoconf macros at all.)
+#
+# So we provide this file, which has a silly filename so it's always
+# included after everything else.  This provides aclocal with the
+# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
+# because those macros already exist, or will be overwritten later.
+# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. 
+#
+# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
+# Yes, that means every name once taken will need to remain here until
+# we give up compatibility with versions before 1.7, at which point
+# we need to keep only those names which we still refer to.
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
+
+m4_ifndef([AC_LIBTOOL_LINKER_OPTION],	[AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
+m4_ifndef([AC_PROG_EGREP],		[AC_DEFUN([AC_PROG_EGREP])])
+m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH],	[AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
+m4_ifndef([_LT_AC_SHELL_INIT],		[AC_DEFUN([_LT_AC_SHELL_INIT])])
+m4_ifndef([_LT_AC_SYS_LIBPATH_AIX],	[AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
+m4_ifndef([_LT_PROG_LTMAIN],		[AC_DEFUN([_LT_PROG_LTMAIN])])
+m4_ifndef([_LT_AC_TAGVAR],		[AC_DEFUN([_LT_AC_TAGVAR])])
+m4_ifndef([AC_LTDL_ENABLE_INSTALL],	[AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
+m4_ifndef([AC_LTDL_PREOPEN],		[AC_DEFUN([AC_LTDL_PREOPEN])])
+m4_ifndef([_LT_AC_SYS_COMPILER],	[AC_DEFUN([_LT_AC_SYS_COMPILER])])
+m4_ifndef([_LT_AC_LOCK],		[AC_DEFUN([_LT_AC_LOCK])])
+m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE],	[AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
+m4_ifndef([_LT_AC_TRY_DLOPEN_SELF],	[AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
+m4_ifndef([AC_LIBTOOL_PROG_CC_C_O],	[AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
+m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
+m4_ifndef([AC_LIBTOOL_OBJDIR],		[AC_DEFUN([AC_LIBTOOL_OBJDIR])])
+m4_ifndef([AC_LTDL_OBJDIR],		[AC_DEFUN([AC_LTDL_OBJDIR])])
+m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
+m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP],	[AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
+m4_ifndef([AC_PATH_MAGIC],		[AC_DEFUN([AC_PATH_MAGIC])])
+m4_ifndef([AC_PROG_LD_GNU],		[AC_DEFUN([AC_PROG_LD_GNU])])
+m4_ifndef([AC_PROG_LD_RELOAD_FLAG],	[AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
+m4_ifndef([AC_DEPLIBS_CHECK_METHOD],	[AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
+m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
+m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
+m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
+m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS],	[AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
+m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP],	[AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
+m4_ifndef([LT_AC_PROG_EGREP],		[AC_DEFUN([LT_AC_PROG_EGREP])])
+m4_ifndef([LT_AC_PROG_SED],		[AC_DEFUN([LT_AC_PROG_SED])])
+m4_ifndef([_LT_CC_BASENAME],		[AC_DEFUN([_LT_CC_BASENAME])])
+m4_ifndef([_LT_COMPILER_BOILERPLATE],	[AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
+m4_ifndef([_LT_LINKER_BOILERPLATE],	[AC_DEFUN([_LT_LINKER_BOILERPLATE])])
+m4_ifndef([_AC_PROG_LIBTOOL],		[AC_DEFUN([_AC_PROG_LIBTOOL])])
+m4_ifndef([AC_LIBTOOL_SETUP],		[AC_DEFUN([AC_LIBTOOL_SETUP])])
+m4_ifndef([_LT_AC_CHECK_DLFCN],		[AC_DEFUN([_LT_AC_CHECK_DLFCN])])
+m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER],	[AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
+m4_ifndef([_LT_AC_TAGCONFIG],		[AC_DEFUN([_LT_AC_TAGCONFIG])])
+m4_ifndef([AC_DISABLE_FAST_INSTALL],	[AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
+m4_ifndef([_LT_AC_LANG_CXX],		[AC_DEFUN([_LT_AC_LANG_CXX])])
+m4_ifndef([_LT_AC_LANG_F77],		[AC_DEFUN([_LT_AC_LANG_F77])])
+m4_ifndef([_LT_AC_LANG_GCJ],		[AC_DEFUN([_LT_AC_LANG_GCJ])])
+m4_ifndef([AC_LIBTOOL_RC],		[AC_DEFUN([AC_LIBTOOL_RC])])
+m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
+m4_ifndef([_LT_AC_LANG_C_CONFIG],	[AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
+m4_ifndef([_LT_AC_LANG_CXX_CONFIG],	[AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
+m4_ifndef([_LT_AC_LANG_F77_CONFIG],	[AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
+m4_ifndef([_LT_AC_LANG_GCJ_CONFIG],	[AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
+m4_ifndef([_LT_AC_LANG_RC_CONFIG],	[AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
+m4_ifndef([AC_LIBTOOL_CONFIG],		[AC_DEFUN([AC_LIBTOOL_CONFIG])])
+m4_ifndef([_LT_AC_FILE_LTDLL_C],	[AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/configure b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/configure
new file mode 100755
index 0000000..b984f5f
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/configure
@@ -0,0 +1,14361 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.64 for package-unused version-unused.
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software
+# Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test "x$CONFIG_SHELL" = x; then
+  as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+"
+  as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+  exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1"
+  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+  if (eval "$as_required") 2>/dev/null; then :
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  as_found=:
+  case $as_dir in #(
+	 /*)
+	   for as_base in sh bash ksh sh5; do
+	     # Try only shells that exist, to save several forks.
+	     as_shell=$as_dir/$as_base
+	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+		    { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  CONFIG_SHELL=$as_shell as_have_required=yes
+		   if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  break 2
+fi
+fi
+	   done;;
+       esac
+  as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+	      { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+  CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+      if test "x$CONFIG_SHELL" != x; then :
+  # We cannot yet assume a decent shell, so we have to provide a
+	# neutralization value for shells without unset; and this also
+	# works around shells that cannot unset nonexistent variables.
+	BASH_ENV=/dev/null
+	ENV=/dev/null
+	(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+	export CONFIG_SHELL
+	exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+    if test x$as_have_required = xno; then :
+  $as_echo "$0: This script requires a shell more modern than all"
+  $as_echo "$0: the shells that I found on your system."
+  if test x${ZSH_VERSION+set} = xset ; then
+    $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+    $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+  else
+    $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+  fi
+  exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+# as_fn_error ERROR [LINENO LOG_FD]
+# ---------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with status $?, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$?; test $as_status -eq 0 && as_status=1
+  if test "$3"; then
+    as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3
+  fi
+  $as_echo "$as_me: error: $1" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+  as_lineno_1=$LINENO as_lineno_1a=$LINENO
+  as_lineno_2=$LINENO as_lineno_2a=$LINENO
+  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -p'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -p'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -p'
+  fi
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+	test -d "$1/.";
+      else
+	case $1 in #(
+	-*)set "./$1";;
+	esac;
+	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+	???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+case X$lt_ECHO in
+X*--fallback-echo)
+  # Remove one level of quotation (which was required for Make).
+  ECHO=`echo "$lt_ECHO" | sed 's,\\\\\$\\$0,'$0','`
+  ;;
+esac
+
+ECHO=${lt_ECHO-echo}
+if test "X$1" = X--no-reexec; then
+  # Discard the --no-reexec flag, and continue.
+  shift
+elif test "X$1" = X--fallback-echo; then
+  # Avoid inline document here, it may be left over
+  :
+elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then
+  # Yippee, $ECHO works!
+  :
+else
+  # Restart under the correct shell.
+  exec $SHELL "$0" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+  # used as fallback echo
+  shift
+  cat <<_LT_EOF
+$*
+_LT_EOF
+  exit 0
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test -z "$lt_ECHO"; then
+  if test "X${echo_test_string+set}" != Xset; then
+    # find a string as large as possible, as long as the shell can cope with it
+    for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do
+      # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+      if { echo_test_string=`eval $cmd`; } 2>/dev/null &&
+	 { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null
+      then
+        break
+      fi
+    done
+  fi
+
+  if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' &&
+     echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` &&
+     test "X$echo_testing_string" = "X$echo_test_string"; then
+    :
+  else
+    # The Solaris, AIX, and Digital Unix default echo programs unquote
+    # backslashes.  This makes it impossible to quote backslashes using
+    #   echo "$something" | sed 's/\\/\\\\/g'
+    #
+    # So, first we look for a working echo in the user's PATH.
+
+    lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+    for dir in $PATH /usr/ucb; do
+      IFS="$lt_save_ifs"
+      if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+         test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+         echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
+         test "X$echo_testing_string" = "X$echo_test_string"; then
+        ECHO="$dir/echo"
+        break
+      fi
+    done
+    IFS="$lt_save_ifs"
+
+    if test "X$ECHO" = Xecho; then
+      # We didn't find a better echo, so look for alternatives.
+      if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' &&
+         echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` &&
+         test "X$echo_testing_string" = "X$echo_test_string"; then
+        # This shell has a builtin print -r that does the trick.
+        ECHO='print -r'
+      elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } &&
+	   test "X$CONFIG_SHELL" != X/bin/ksh; then
+        # If we have ksh, try running configure again with it.
+        ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+        export ORIGINAL_CONFIG_SHELL
+        CONFIG_SHELL=/bin/ksh
+        export CONFIG_SHELL
+        exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"}
+      else
+        # Try using printf.
+        ECHO='printf %s\n'
+        if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' &&
+	   echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` &&
+	   test "X$echo_testing_string" = "X$echo_test_string"; then
+	  # Cool, printf works
+	  :
+        elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
+	     test "X$echo_testing_string" = 'X\t' &&
+	     echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+	     test "X$echo_testing_string" = "X$echo_test_string"; then
+	  CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
+	  export CONFIG_SHELL
+	  SHELL="$CONFIG_SHELL"
+	  export SHELL
+	  ECHO="$CONFIG_SHELL $0 --fallback-echo"
+        elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
+	     test "X$echo_testing_string" = 'X\t' &&
+	     echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+	     test "X$echo_testing_string" = "X$echo_test_string"; then
+	  ECHO="$CONFIG_SHELL $0 --fallback-echo"
+        else
+	  # maybe with a smaller string...
+	  prev=:
+
+	  for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do
+	    if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null
+	    then
+	      break
+	    fi
+	    prev="$cmd"
+	  done
+
+	  if test "$prev" != 'sed 50q "$0"'; then
+	    echo_test_string=`eval $prev`
+	    export echo_test_string
+	    exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"}
+	  else
+	    # Oops.  We lost completely, so just stick with echo.
+	    ECHO=echo
+	  fi
+        fi
+      fi
+    fi
+  fi
+fi
+
+# Copy echo and quote the copy suitably for passing to libtool from
+# the Makefile, instead of quoting the original, which is used later.
+lt_ECHO=$ECHO
+if test "X$lt_ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then
+   lt_ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo"
+fi
+
+
+
+
+exec 7<&0 </dev/null 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='package-unused'
+PACKAGE_TARNAME='libbacktrace'
+PACKAGE_VERSION='version-unused'
+PACKAGE_STRING='package-unused version-unused'
+PACKAGE_BUGREPORT=''
+PACKAGE_URL=''
+
+ac_unique_file="backtrace.h"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='am__EXEEXT_FALSE
+am__EXEEXT_TRUE
+LTLIBOBJS
+LIBOBJS
+NATIVE_FALSE
+NATIVE_TRUE
+HAVE_OBJCOPY_DEBUGLINK_FALSE
+HAVE_OBJCOPY_DEBUGLINK_TRUE
+OBJCOPY
+HAVE_COMPRESSED_DEBUG_FALSE
+HAVE_COMPRESSED_DEBUG_TRUE
+HAVE_ZLIB_FALSE
+HAVE_ZLIB_TRUE
+HAVE_PTHREAD_FALSE
+HAVE_PTHREAD_TRUE
+PTHREAD_CFLAGS
+CLOCK_GETTIME_LINK
+BACKTRACE_USES_MALLOC
+ALLOC_FILE
+VIEW_FILE
+BACKTRACE_SUPPORTS_DATA
+BACKTRACE_SUPPORTED
+FORMAT_FILE
+BACKTRACE_SUPPORTS_THREADS
+PIC_FLAG
+WARN_FLAGS
+EXTRA_FLAGS
+BACKTRACE_FILE
+OTOOL64
+OTOOL
+LIPO
+NMEDIT
+DSYMUTIL
+lt_ECHO
+RANLIB
+AR
+LN_S
+NM
+ac_ct_DUMPBIN
+DUMPBIN
+LD
+FGREP
+SED
+LIBTOOL
+MAINT
+MAINTAINER_MODE_FALSE
+MAINTAINER_MODE_TRUE
+am__untar
+am__tar
+AMTAR
+am__leading_dot
+SET_MAKE
+AWK
+mkdir_p
+MKDIR_P
+INSTALL_STRIP_PROGRAM
+STRIP
+install_sh
+MAKEINFO
+AUTOHEADER
+AUTOMAKE
+AUTOCONF
+ACLOCAL
+VERSION
+PACKAGE
+CYGPATH_W
+am__isrc
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+libtool_VERSION
+EGREP
+GREP
+CPP
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+target_os
+target_vendor
+target_cpu
+target
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+multi_basedir
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_multilib
+enable_maintainer_mode
+with_target_subdir
+enable_shared
+enable_static
+with_pic
+enable_fast_install
+with_gnu_ld
+enable_libtool_lock
+enable_largefile
+with_system_libunwind
+enable_host_shared
+'
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP
+OBJCOPY'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=*)	ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *)	ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) as_fn_error "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information."
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    case $ac_envvar in #(
+      '' | [0-9]* | *[!_$as_cr_alnum]* )
+      as_fn_error "invalid variable name: \`$ac_envvar'" ;;
+    esac
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  as_fn_error "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+  case $enable_option_checking in
+    no) ;;
+    fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;;
+    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+  esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
+		datadir sysconfdir sharedstatedir localstatedir includedir \
+		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+		libdir localedir mandir
+do
+  eval ac_val=\$$ac_var
+  # Remove trailing slashes.
+  case $ac_val in
+    */ )
+      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+      eval $ac_var=\$ac_val;;
+  esac
+  # Be sure to have absolute directory names.
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  as_fn_error "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  as_fn_error "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  as_fn_error "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_myself" : 'X\(//\)[^/]' \| \
+	 X"$as_myself" : 'X\(//\)$' \| \
+	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  as_fn_error "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+	cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg"
+	pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures package-unused version-unused to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR            user executables [EPREFIX/bin]
+  --sbindir=DIR           system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR        program executables [EPREFIX/libexec]
+  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --libdir=DIR            object code libraries [EPREFIX/lib]
+  --includedir=DIR        C header files [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR           info documentation [DATAROOTDIR/info]
+  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR            man documentation [DATAROOTDIR/man]
+  --docdir=DIR            documentation root [DATAROOTDIR/doc/libbacktrace]
+  --htmldir=DIR           html documentation [DOCDIR]
+  --dvidir=DIR            dvi documentation [DOCDIR]
+  --pdfdir=DIR            pdf documentation [DOCDIR]
+  --psdir=DIR             ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+
+Program names:
+  --program-prefix=PREFIX            prepend PREFIX to installed program names
+  --program-suffix=SUFFIX            append SUFFIX to installed program names
+  --program-transform-name=PROGRAM   run sed PROGRAM on installed program names
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+  --target=TARGET   configure for building compilers for TARGET [HOST]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of package-unused version-unused:";;
+   esac
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-option-checking  ignore unrecognized --enable/--with options
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --enable-multilib       build many library versions (default)
+  --enable-maintainer-mode  enable make rules and dependencies not useful
+			  (and sometimes confusing) to the casual installer
+  --enable-shared[=PKGS]  build shared libraries [default=yes]
+  --enable-static[=PKGS]  build static libraries [default=yes]
+  --enable-fast-install[=PKGS]
+                          optimize for fast installation [default=yes]
+  --disable-libtool-lock  avoid locking (might break parallel builds)
+  --disable-largefile     omit support for large files
+  --enable-host-shared    build host code as shared libraries
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-target-subdir=SUBDIR      Configuring in a subdirectory for target
+  --with-pic              try to use only PIC/non-PIC objects [default=use
+                          both]
+  --with-gnu-ld           assume the C compiler uses GNU ld [default=no]
+  --with-system-libunwind use installed libunwind
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPPFLAGS    C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+  CPP         C preprocessor
+  OBJCOPY     location of objcopy
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" ||
+      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+      continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+package-unused configure version-unused
+generated by GNU Autoconf 2.64
+
+Copyright (C) 2009 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  return $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+    ac_retval=1
+fi
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  return $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_header_compiler=yes
+else
+  ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  ac_header_preproc=yes
+else
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+  yes:no: )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+    ;;
+esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_header_mongrel
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: program exited with status $ac_status" >&5
+       $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_retval=$ac_status
+fi
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  return $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest$ac_exeext
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  return $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $2 (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_func
+
+# ac_fn_c_check_decl LINENO SYMBOL VAR
+# ------------------------------------
+# Tests whether SYMBOL is declared, setting cache variable VAR accordingly.
+ac_fn_c_check_decl ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $2 is declared" >&5
+$as_echo_n "checking whether $2 is declared... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+#ifndef $2
+  (void) $2;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_decl
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by package-unused $as_me version-unused, which was
+generated by GNU Autoconf 2.64.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    $as_echo "PATH: $as_dir"
+  done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+    2)
+      as_fn_append ac_configure_args1 " '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      as_fn_append ac_configure_args " '$ac_arg'"
+      ;;
+    esac
+  done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+	"s/'\''/'\''\\\\'\'''\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      $as_echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=\$$ac_var
+	case $ac_val in
+	*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+	esac
+	$as_echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      $as_echo "$as_me: caught signal $ac_signal"
+    $as_echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+  ac_site_file1=$CONFIG_SITE
+elif test "x$prefix" != xNONE; then
+  ac_site_file1=$prefix/share/config.site
+  ac_site_file2=$prefix/etc/config.site
+else
+  ac_site_file1=$ac_default_prefix/share/config.site
+  ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+  test "x$ac_site_file" = xNONE && continue
+  if test -r "$ac_site_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	# differences in whitespace do not lead to failure.
+	ac_old_val_w=`echo x $ac_old_val`
+	ac_new_val_w=`echo x $ac_new_val`
+	if test "$ac_old_val_w" != "$ac_new_val_w"; then
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	  ac_cache_corrupted=:
+	else
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+	  eval $ac_var=\$ac_old_val
+	fi
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
+$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
+$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+
+
+# with_target_subdir is used when configured as part of a GCC tree.
+if test -n "${with_target_subdir}"; then
+  # Default to --enable-multilib
+# Check whether --enable-multilib was given.
+if test "${enable_multilib+set}" = set; then :
+  enableval=$enable_multilib; case "$enableval" in
+  yes) multilib=yes ;;
+  no)  multilib=no ;;
+  *)   as_fn_error "bad value $enableval for multilib option" "$LINENO" 5 ;;
+ esac
+else
+  multilib=yes
+fi
+
+
+# We may get other options which we leave undocumented:
+# --with-target-subdir, --with-multisrctop, --with-multisubdir
+# See config-ml.in if you want the gory details.
+
+if test "$srcdir" = "."; then
+  if test "$with_target_subdir" != "."; then
+    multi_basedir="$srcdir/$with_multisrctop../.."
+  else
+    multi_basedir="$srcdir/$with_multisrctop.."
+  fi
+else
+  multi_basedir="$srcdir/.."
+fi
+
+
+# Even if the default multilib is not a cross compilation,
+# it may be that some of the other multilibs are.
+if test $cross_compiling = no && test $multilib = yes \
+   && test "x${with_multisubdir}" != x ; then
+   cross_compiling=maybe
+fi
+
+ac_config_commands="$ac_config_commands default-1"
+
+fi
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+  for ac_t in install-sh install.sh shtool; do
+    if test -f "$ac_dir/$ac_t"; then
+      ac_aux_dir=$ac_dir
+      ac_install_sh="$ac_aux_dir/$ac_t -c"
+      break 2
+    fi
+  done
+done
+if test -z "$ac_aux_dir"; then
+  as_fn_error "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
+
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+  as_fn_error "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if test "${ac_cv_build+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+  ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+  as_fn_error "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+  as_fn_error "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if test "${ac_cv_host+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "x$host_alias" = x; then
+  ac_cv_host=$ac_cv_build
+else
+  ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+    as_fn_error "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5
+$as_echo_n "checking target system type... " >&6; }
+if test "${ac_cv_target+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "x$target_alias" = x; then
+  ac_cv_target=$ac_cv_host
+else
+  ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` ||
+    as_fn_error "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5
+$as_echo "$ac_cv_target" >&6; }
+case $ac_cv_target in
+*-*-*) ;;
+*) as_fn_error "invalid value of canonical target" "$LINENO" 5;;
+esac
+target=$ac_cv_target
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_target
+shift
+target_cpu=$1
+target_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+target_os=$*
+IFS=$ac_save_IFS
+case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+  test "$program_prefix$program_suffix$program_transform_name" = \
+    NONENONEs,x,x, &&
+  program_prefix=${target_alias}-
+
+target_alias=${target_alias-$host_alias}
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "no acceptable C compiler found in \$PATH
+See \`config.log' for more details." "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    rm -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out conftest.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+	;;
+    [ab].out )
+	# We found the default executable, but exeext='' is most
+	# certainly right.
+	break;;
+    *.* )
+	if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+	then :; else
+	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	fi
+	# We set ac_cv_exeext here because the later test for it is not
+	# safe: cross compilers may not add the suffix if given an `-o'
+	# argument, so we may need to know it at that point already.
+	# Even if this section looks crufty: it has the advantage of
+	# actually working.
+	break;;
+    * )
+	break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+if test -z "$ac_file"; then :
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ as_fn_set_status 77
+as_fn_error "C compiler cannot create executables
+See \`config.log' for more details." "$LINENO" 5; }; }
+fi
+ac_exeext=$ac_cv_exeext
+
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+  if { ac_try='./$ac_file'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." "$LINENO" 5; }
+    fi
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out conftest.out
+ac_clean_files=$ac_clean_files_save
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	  break;;
+    * ) break;;
+  esac
+done
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." "$LINENO" 5; }
+fi
+rm -f conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if test "${ac_cv_objext+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+else
+  CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  ac_c_werror_flag=$ac_save_c_werror_flag
+	 CFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$GREP"; then
+  ac_path_GREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in grep ggrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_GREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_GREP"; then
+    as_fn_error "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     if test -z "$EGREP"; then
+  ac_path_EGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in egrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_EGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_EGREP"; then
+    as_fn_error "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_header_stdc=yes
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then :
+  :
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+		   (('a' <= (c) && (c) <= 'i') \
+		     || ('j' <= (c) && (c) <= 'r') \
+		     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+	|| toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+		  inttypes.h stdint.h unistd.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+eval as_val=\$$as_ac_Header
+   if test "x$as_val" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+  ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default"
+if test "x$ac_cv_header_minix_config_h" = x""yes; then :
+  MINIX=yes
+else
+  MINIX=
+fi
+
+
+  if test "$MINIX" = yes; then
+
+$as_echo "#define _POSIX_SOURCE 1" >>confdefs.h
+
+
+$as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h
+
+
+$as_echo "#define _MINIX 1" >>confdefs.h
+
+  fi
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5
+$as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; }
+if test "${ac_cv_safe_to_define___extensions__+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#	  define __EXTENSIONS__ 1
+	  $ac_includes_default
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_safe_to_define___extensions__=yes
+else
+  ac_cv_safe_to_define___extensions__=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5
+$as_echo "$ac_cv_safe_to_define___extensions__" >&6; }
+  test $ac_cv_safe_to_define___extensions__ = yes &&
+    $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h
+
+  $as_echo "#define _ALL_SOURCE 1" >>confdefs.h
+
+  $as_echo "#define _GNU_SOURCE 1" >>confdefs.h
+
+  $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h
+
+  $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h
+
+
+
+libtool_VERSION=1:0:0
+
+
+# 1.11.1: Require that version of automake.
+# foreign: Don't require README, INSTALL, NEWS, etc.
+# no-define: Don't define PACKAGE and VERSION.
+# no-dependencies: Don't generate automatic dependencies.
+#    (because it breaks when using bootstrap-lean, since some of the
+#    headers are gone at "make install" time).
+# -Wall: Issue all automake warnings.
+# -Wno-portability: Don't warn about constructs supported by GNU make.
+#    (because GCC requires GNU make anyhow).
+am__api_version='1.11'
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+  ./ | .// | /[cC]/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+	if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+	  if test $ac_prog = install &&
+	    grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # AIX install.  It has an incompatible calling convention.
+	    :
+	  elif test $ac_prog = install &&
+	    grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # program-specific install script used by HP pwplus--don't use.
+	    :
+	  else
+	    rm -rf conftest.one conftest.two conftest.dir
+	    echo one > conftest.one
+	    echo two > conftest.two
+	    mkdir conftest.dir
+	    if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+	      test -s conftest.one && test -s conftest.two &&
+	      test -s conftest.dir/conftest.one &&
+	      test -s conftest.dir/conftest.two
+	    then
+	      ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+	      break 3
+	    fi
+	  fi
+	fi
+      done
+    done
+    ;;
+esac
+
+  done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    INSTALL=$ac_install_sh
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5
+$as_echo_n "checking whether build environment is sane... " >&6; }
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name.  Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+  *[\\\"\#\$\&\'\`$am_lf]*)
+    as_fn_error "unsafe absolute working directory name" "$LINENO" 5;;
+esac
+case $srcdir in
+  *[\\\"\#\$\&\'\`$am_lf\ \	]*)
+    as_fn_error "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;;
+esac
+
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+   if test "$*" = "X"; then
+      # -L didn't work.
+      set X `ls -t "$srcdir/configure" conftest.file`
+   fi
+   rm -f conftest.file
+   if test "$*" != "X $srcdir/configure conftest.file" \
+      && test "$*" != "X conftest.file $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      as_fn_error "ls -t appears to fail.  Make sure there is not a broken
+alias in your environment" "$LINENO" 5
+   fi
+
+   test "$2" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   as_fn_error "newly created file is older than distributed files!
+Check your system clock" "$LINENO" 5
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+test "$program_prefix" != NONE &&
+  program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+  program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $.
+# By default was `s,x,x', remove it if useless.
+ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
+program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
+
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+
+if test x"${MISSING+set}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+  *)
+    MISSING="\${SHELL} $am_aux_dir/missing" ;;
+  esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+  am_missing_run="$MISSING --run "
+else
+  am_missing_run=
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5
+$as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
+fi
+
+if test x"${install_sh}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+  *)
+    install_sh="\${SHELL} $am_aux_dir/install-sh"
+  esac
+fi
+
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'.  However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_STRIP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_STRIP" = x; then
+    STRIP=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    STRIP=$ac_ct_STRIP
+  fi
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5
+$as_echo_n "checking for a thread-safe mkdir -p... " >&6; }
+if test -z "$MKDIR_P"; then
+  if test "${ac_cv_path_mkdir+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in mkdir gmkdir; do
+	 for ac_exec_ext in '' $ac_executable_extensions; do
+	   { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue
+	   case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
+	     'mkdir (GNU coreutils) '* | \
+	     'mkdir (coreutils) '* | \
+	     'mkdir (fileutils) '4.1*)
+	       ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
+	       break 3;;
+	   esac
+	 done
+       done
+  done
+IFS=$as_save_IFS
+
+fi
+
+  if test "${ac_cv_path_mkdir+set}" = set; then
+    MKDIR_P="$ac_cv_path_mkdir -p"
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for MKDIR_P within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    test -d ./--version && rmdir ./--version
+    MKDIR_P="$ac_install_sh -d"
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
+$as_echo "$MKDIR_P" >&6; }
+
+mkdir_p="$MKDIR_P"
+case $mkdir_p in
+  [\\/$]* | ?:[\\/]*) ;;
+  */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+
+for ac_prog in gawk mawk nawk awk
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_AWK+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_AWK="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+$as_echo "$AWK" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$AWK" && break
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+	@echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+  *@@@%%%=?*=@@@%%%*)
+    eval ac_cv_prog_make_${ac_make}_set=yes;;
+  *)
+    eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+  SET_MAKE=
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  am__isrc=' -I$(srcdir)'
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    as_fn_error "source directory already configured; run \"make distclean\" there first" "$LINENO" 5
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE='libbacktrace'
+ VERSION='version-unused'
+
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+# Always define AMTAR for backward compatibility.  Yes, it's still used
+# in the wild :-(  We should find a proper way to deprecate it ...
+AMTAR='$${TAR-tar}'
+
+am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5
+$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; }
+    # Check whether --enable-maintainer-mode was given.
+if test "${enable_maintainer_mode+set}" = set; then :
+  enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval
+else
+  USE_MAINTAINER_MODE=no
+fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5
+$as_echo "$USE_MAINTAINER_MODE" >&6; }
+   if test $USE_MAINTAINER_MODE = yes; then
+  MAINTAINER_MODE_TRUE=
+  MAINTAINER_MODE_FALSE='#'
+else
+  MAINTAINER_MODE_TRUE='#'
+  MAINTAINER_MODE_FALSE=
+fi
+
+  MAINT=$MAINTAINER_MODE_TRUE
+
+
+
+
+# Check whether --with-target-subdir was given.
+if test "${with_target_subdir+set}" = set; then :
+  withval=$with_target_subdir;
+fi
+
+
+# We must force CC to /not/ be precious variables; otherwise
+# the wrong, non-multilib-adjusted value will be used in multilibs.
+# As a side effect, we have to subst CFLAGS ourselves.
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "no acceptable C compiler found in \$PATH
+See \`config.log' for more details." "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    rm -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+else
+  CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  ac_c_werror_flag=$ac_save_c_werror_flag
+	 CFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+for ac_prog in gawk mawk nawk awk
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_AWK+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_AWK="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+$as_echo "$AWK" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$AWK" && break
+done
+
+case "$AWK" in
+"") as_fn_error "can't build without awk" "$LINENO" 5 ;;
+esac
+
+case `pwd` in
+  *\ * | *\	*)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
+$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;;
+esac
+
+
+
+macro_version='2.2.4'
+macro_revision='1.2976'
+
+
+
+
+
+
+
+
+
+
+
+
+
+ltmain="$ac_aux_dir/ltmain.sh"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
+$as_echo_n "checking for a sed that does not truncate output... " >&6; }
+if test "${ac_cv_path_SED+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+            ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
+     for ac_i in 1 2 3 4 5 6 7; do
+       ac_script="$ac_script$as_nl$ac_script"
+     done
+     echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed
+     { ac_script=; unset ac_script;}
+     if test -z "$SED"; then
+  ac_path_SED_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in sed gsed; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_SED="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_SED" && $as_test_x "$ac_path_SED"; } || continue
+# Check for GNU ac_path_SED and select it if it is found.
+  # Check for GNU $ac_path_SED
+case `"$ac_path_SED" --version 2>&1` in
+*GNU*)
+  ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo '' >> "conftest.nl"
+    "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_SED_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_SED="$ac_path_SED"
+      ac_path_SED_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_SED_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_SED"; then
+    as_fn_error "no acceptable sed could be found in \$PATH" "$LINENO" 5
+  fi
+else
+  ac_cv_path_SED=$SED
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5
+$as_echo "$ac_cv_path_SED" >&6; }
+ SED="$ac_cv_path_SED"
+  rm -f conftest.sed
+
+test -z "$SED" && SED=sed
+Xsed="$SED -e 1s/^X//"
+
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5
+$as_echo_n "checking for fgrep... " >&6; }
+if test "${ac_cv_path_FGREP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1
+   then ac_cv_path_FGREP="$GREP -F"
+   else
+     if test -z "$FGREP"; then
+  ac_path_FGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in fgrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_FGREP" && $as_test_x "$ac_path_FGREP"; } || continue
+# Check for GNU ac_path_FGREP and select it if it is found.
+  # Check for GNU $ac_path_FGREP
+case `"$ac_path_FGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'FGREP' >> "conftest.nl"
+    "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_FGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_FGREP="$ac_path_FGREP"
+      ac_path_FGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_FGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_FGREP"; then
+    as_fn_error "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_FGREP=$FGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5
+$as_echo "$ac_cv_path_FGREP" >&6; }
+ FGREP="$ac_cv_path_FGREP"
+
+
+test -z "$GREP" && GREP=grep
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then :
+  withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes
+else
+  with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5
+$as_echo_n "checking for ld used by $CC... " >&6; }
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [\\/]* | ?:[\\/]*)
+      re_direlt='/[^/][^/]*/\.\./'
+      # Canonicalize the pathname of ld
+      ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+      while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+	ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
+$as_echo_n "checking for GNU ld... " >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
+$as_echo_n "checking for non-GNU ld... " >&6; }
+fi
+if test "${lt_cv_path_LD+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$LD"; then
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some variants of GNU ld only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+      *GNU* | *'with BFD'*)
+	test "$with_gnu_ld" != no && break
+	;;
+      *)
+	test "$with_gnu_ld" != yes && break
+	;;
+      esac
+    fi
+  done
+  IFS="$lt_save_ifs"
+else
+  lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
+$as_echo "$LD" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+test -z "$LD" && as_fn_error "no acceptable ld found in \$PATH" "$LINENO" 5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
+$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
+if test "${lt_cv_prog_gnu_ld+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  # I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+  lt_cv_prog_gnu_ld=yes
+  ;;
+*)
+  lt_cv_prog_gnu_ld=no
+  ;;
+esac
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5
+$as_echo "$lt_cv_prog_gnu_ld" >&6; }
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5
+$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; }
+if test "${lt_cv_path_NM+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$NM"; then
+  # Let the user override the test.
+  lt_cv_path_NM="$NM"
+else
+  lt_nm_to_check="${ac_tool_prefix}nm"
+  if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+    lt_nm_to_check="$lt_nm_to_check nm"
+  fi
+  for lt_tmp_nm in $lt_nm_to_check; do
+    lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+    for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+      IFS="$lt_save_ifs"
+      test -z "$ac_dir" && ac_dir=.
+      tmp_nm="$ac_dir/$lt_tmp_nm"
+      if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+	# Check to see if the nm accepts a BSD-compat flag.
+	# Adding the `sed 1q' prevents false positives on HP-UX, which says:
+	#   nm: unknown option "B" ignored
+	# Tru64's nm complains that /dev/null is an invalid object file
+	case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+	*/dev/null* | *'Invalid file or object type'*)
+	  lt_cv_path_NM="$tmp_nm -B"
+	  break
+	  ;;
+	*)
+	  case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+	  */dev/null*)
+	    lt_cv_path_NM="$tmp_nm -p"
+	    break
+	    ;;
+	  *)
+	    lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+	    continue # so that we can try to find one that supports BSD flags
+	    ;;
+	  esac
+	  ;;
+	esac
+      fi
+    done
+    IFS="$lt_save_ifs"
+  done
+  : ${lt_cv_path_NM=no}
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5
+$as_echo "$lt_cv_path_NM" >&6; }
+if test "$lt_cv_path_NM" != "no"; then
+  NM="$lt_cv_path_NM"
+else
+  # Didn't find any BSD compatible name lister, look for dumpbin.
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in "dumpbin -symbols" "link -dump -symbols"
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_DUMPBIN+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$DUMPBIN"; then
+  ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+DUMPBIN=$ac_cv_prog_DUMPBIN
+if test -n "$DUMPBIN"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5
+$as_echo "$DUMPBIN" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$DUMPBIN" && break
+  done
+fi
+if test -z "$DUMPBIN"; then
+  ac_ct_DUMPBIN=$DUMPBIN
+  for ac_prog in "dumpbin -symbols" "link -dump -symbols"
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_DUMPBIN+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_DUMPBIN"; then
+  ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_DUMPBIN="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN
+if test -n "$ac_ct_DUMPBIN"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5
+$as_echo "$ac_ct_DUMPBIN" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_DUMPBIN" && break
+done
+
+  if test "x$ac_ct_DUMPBIN" = x; then
+    DUMPBIN=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    DUMPBIN=$ac_ct_DUMPBIN
+  fi
+fi
+
+
+  if test "$DUMPBIN" != ":"; then
+    NM="$DUMPBIN"
+  fi
+fi
+test -z "$NM" && NM=nm
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5
+$as_echo_n "checking the name lister ($NM) interface... " >&6; }
+if test "${lt_cv_nm_interface+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_nm_interface="BSD nm"
+  echo "int some_variable = 0;" > conftest.$ac_ext
+  (eval echo "\"\$as_me:5363: $ac_compile\"" >&5)
+  (eval "$ac_compile" 2>conftest.err)
+  cat conftest.err >&5
+  (eval echo "\"\$as_me:5366: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+  (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
+  cat conftest.err >&5
+  (eval echo "\"\$as_me:5369: output\"" >&5)
+  cat conftest.out >&5
+  if $GREP 'External.*some_variable' conftest.out > /dev/null; then
+    lt_cv_nm_interface="MS dumpbin"
+  fi
+  rm -f conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5
+$as_echo "$lt_cv_nm_interface" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
+$as_echo_n "checking whether ln -s works... " >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
+$as_echo "no, using $LN_S" >&6; }
+fi
+
+# find the maximum length of command line arguments
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5
+$as_echo_n "checking the maximum length of command line arguments... " >&6; }
+if test "${lt_cv_sys_max_cmd_len+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+    i=0
+  teststring="ABCD"
+
+  case $build_os in
+  msdosdjgpp*)
+    # On DJGPP, this test can blow up pretty badly due to problems in libc
+    # (any single argument exceeding 2000 bytes causes a buffer overrun
+    # during glob expansion).  Even if it were fixed, the result of this
+    # check would be larger than it should be.
+    lt_cv_sys_max_cmd_len=12288;    # 12K is about right
+    ;;
+
+  gnu*)
+    # Under GNU Hurd, this test is not required because there is
+    # no limit to the length of command line arguments.
+    # Libtool will interpret -1 as no limit whatsoever
+    lt_cv_sys_max_cmd_len=-1;
+    ;;
+
+  cygwin* | mingw*)
+    # On Win9x/ME, this test blows up -- it succeeds, but takes
+    # about 5 minutes as the teststring grows exponentially.
+    # Worse, since 9x/ME are not pre-emptively multitasking,
+    # you end up with a "frozen" computer, even though with patience
+    # the test eventually succeeds (with a max line length of 256k).
+    # Instead, let's just punt: use the minimum linelength reported by
+    # all of the supported platforms: 8192 (on NT/2K/XP).
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  amigaos*)
+    # On AmigaOS with pdksh, this test takes hours, literally.
+    # So we just punt and use a minimum line length of 8192.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  netbsd* | freebsd* | openbsd* | darwin* | dragonfly* | bitrig*)
+    # This has been around since 386BSD, at least.  Likely further.
+    if test -x /sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+    elif test -x /usr/sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+    else
+      lt_cv_sys_max_cmd_len=65536	# usable default for all BSDs
+    fi
+    # And add a safety zone
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    ;;
+
+  interix*)
+    # We know the value 262144 and hardcode it with a safety zone (like BSD)
+    lt_cv_sys_max_cmd_len=196608
+    ;;
+
+  osf*)
+    # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+    # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+    # nice to cause kernel panics so lets avoid the loop below.
+    # First set a reasonable default.
+    lt_cv_sys_max_cmd_len=16384
+    #
+    if test -x /sbin/sysconfig; then
+      case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+        *1*) lt_cv_sys_max_cmd_len=-1 ;;
+      esac
+    fi
+    ;;
+  sco3.2v5*)
+    lt_cv_sys_max_cmd_len=102400
+    ;;
+  sysv5* | sco5v6* | sysv4.2uw2*)
+    kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+    if test -n "$kargmax"; then
+      lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[	 ]//'`
+    else
+      lt_cv_sys_max_cmd_len=32768
+    fi
+    ;;
+  *)
+    lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+    if test -n "$lt_cv_sys_max_cmd_len"; then
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    else
+      # Make teststring a little bigger before we do anything with it.
+      # a 1K string should be a reasonable start.
+      for i in 1 2 3 4 5 6 7 8 ; do
+        teststring=$teststring$teststring
+      done
+      SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+      # If test is not a shell built-in, we'll probably end up computing a
+      # maximum length that is only half of the actual maximum length, but
+      # we can't tell.
+      while { test "X"`$SHELL $0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \
+	         = "XX$teststring$teststring"; } >/dev/null 2>&1 &&
+	      test $i != 17 # 1/2 MB should be enough
+      do
+        i=`expr $i + 1`
+        teststring=$teststring$teststring
+      done
+      # Only check the string length outside the loop.
+      lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
+      teststring=
+      # Add a significant safety factor because C++ compilers can tack on
+      # massive amounts of additional arguments before passing them to the
+      # linker.  It appears as though 1/2 is a usable value.
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+    fi
+    ;;
+  esac
+
+fi
+
+if test -n $lt_cv_sys_max_cmd_len ; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5
+$as_echo "$lt_cv_sys_max_cmd_len" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5
+$as_echo "none" >&6; }
+fi
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+
+
+
+
+
+: ${CP="cp -f"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5
+$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; }
+# Try some XSI features
+xsi_shell=no
+( _lt_dummy="a/b/c"
+  test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \
+      = c,a/b,, \
+    && eval 'test $(( 1 + 1 )) -eq 2 \
+    && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \
+  && xsi_shell=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5
+$as_echo "$xsi_shell" >&6; }
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5
+$as_echo_n "checking whether the shell understands \"+=\"... " >&6; }
+lt_shell_append=no
+( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \
+    >/dev/null 2>&1 \
+  && lt_shell_append=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5
+$as_echo "$lt_shell_append" >&6; }
+
+
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  lt_unset=unset
+else
+  lt_unset=false
+fi
+
+
+
+
+
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+    # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+  lt_SP2NL='tr \040 \012'
+  lt_NL2SP='tr \015\012 \040\040'
+  ;;
+ *) # EBCDIC based system
+  lt_SP2NL='tr \100 \n'
+  lt_NL2SP='tr \r\n \100\100'
+  ;;
+esac
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5
+$as_echo_n "checking for $LD option to reload object files... " >&6; }
+if test "${lt_cv_ld_reload_flag+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_ld_reload_flag='-r'
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5
+$as_echo "$lt_cv_ld_reload_flag" >&6; }
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+  darwin*)
+    if test "$GCC" = yes; then
+      reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+    else
+      reload_cmds='$LD$reload_flag -o $output$reload_objs'
+    fi
+    ;;
+esac
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5
+$as_echo_n "checking how to recognize dependent libraries... " >&6; }
+if test "${lt_cv_deplibs_check_method+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix[4-9]*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+beos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+bsdi[45]*)
+  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
+  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  ;;
+
+cygwin*)
+  # func_win32_libid is a shell function defined in ltmain.sh
+  lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+  lt_cv_file_magic_cmd='func_win32_libid'
+  ;;
+
+mingw* | pw32*)
+  # Base MSYS/MinGW do not provide the 'file' command needed by
+  # func_win32_libid shell function, so use a weaker test based on 'objdump',
+  # unless we find 'file', for example because we are cross-compiling.
+  if ( file / ) >/dev/null 2>&1; then
+    lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+    lt_cv_file_magic_cmd='func_win32_libid'
+  else
+    lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+    lt_cv_file_magic_cmd='$OBJDUMP -f'
+  fi
+  ;;
+
+darwin* | rhapsody*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+freebsd* | dragonfly*)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    case $host_cpu in
+    i*86 )
+      # Not sure whether the presence of OpenBSD here was a mistake.
+      # Let's accept both of them until this is cleared up.
+      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library'
+      lt_cv_file_magic_cmd=/usr/bin/file
+      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+      ;;
+    esac
+  else
+    lt_cv_deplibs_check_method=pass_all
+  fi
+  ;;
+
+gnu*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+hpux10.20* | hpux11*)
+  lt_cv_file_magic_cmd=/usr/bin/file
+  case $host_cpu in
+  ia64*)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64'
+    lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+    ;;
+  hppa*64*)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'
+    lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+    ;;
+  *)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library'
+    lt_cv_file_magic_test_file=/usr/lib/libc.sl
+    ;;
+  esac
+  ;;
+
+interix[3-9]*)
+  # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+  lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$'
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $LD in
+  *-32|*"-32 ") libmagic=32-bit;;
+  *-n32|*"-n32 ") libmagic=N32;;
+  *-64|*"-64 ") libmagic=64-bit;;
+  *) libmagic=never-match;;
+  esac
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+netbsd*)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$'
+  fi
+  ;;
+
+newos6*)
+  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=/usr/lib/libnls.so
+  ;;
+
+*nto* | *qnx*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+openbsd*)
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+  fi
+  ;;
+
+osf3* | osf4* | osf5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+rdos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+solaris*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv4 | sysv4.3*)
+  case $host_vendor in
+  motorola)
+    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
+    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+    ;;
+  ncr)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  sequent)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
+    ;;
+  sni)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
+    lt_cv_file_magic_test_file=/lib/libc.so
+    ;;
+  siemens)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  pc)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  esac
+  ;;
+
+tpf*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+esac
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5
+$as_echo "$lt_cv_deplibs_check_method" >&6; }
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+
+
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_AR+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AR"; then
+  ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_AR="${ac_tool_prefix}ar"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+  ac_ct_AR=$AR
+  # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_AR+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_AR"; then
+  ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_AR="ar"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+$as_echo "$ac_ct_AR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_AR" = x; then
+    AR="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    AR=$ac_ct_AR
+  fi
+else
+  AR="$ac_cv_prog_AR"
+fi
+
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+
+
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_STRIP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_STRIP" = x; then
+    STRIP=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    STRIP=$ac_ct_STRIP
+  fi
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+test -z "$STRIP" && STRIP=:
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_RANLIB+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_RANLIB" = x; then
+    RANLIB=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    RANLIB=$ac_ct_RANLIB
+  fi
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+test -z "$RANLIB" && RANLIB=:
+
+
+
+
+
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+  case $host_os in
+  openbsd*)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
+    ;;
+  *)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
+    ;;
+  esac
+  old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5
+$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; }
+if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+  symcode='[BCDT]'
+  ;;
+cygwin* | mingw* | pw32*)
+  symcode='[ABCDGISTW]'
+  ;;
+hpux*)
+  if test "$host_cpu" = ia64; then
+    symcode='[ABCDEGRST]'
+  fi
+  ;;
+irix* | nonstopux*)
+  symcode='[BCDEGRST]'
+  ;;
+osf*)
+  symcode='[BCDEGQRST]'
+  ;;
+solaris*)
+  symcode='[BDRT]'
+  ;;
+sco3.2v5*)
+  symcode='[DT]'
+  ;;
+sysv4.2uw2*)
+  symcode='[DT]'
+  ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+  symcode='[ABDT]'
+  ;;
+sysv4)
+  symcode='[DFNSTU]'
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+  symcode='[ABCDGIRSTW]' ;;
+esac
+
+# Transform an extracted symbol line into a proper C declaration.
+# Some systems (esp. on ia64) link data and code symbols differently,
+# so use this general approach.
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/  {\"\2\", (void *) \&\2},/p'"
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\) $/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/  {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/  {\"lib\2\", (void *) \&\2},/p'"
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+  opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+  ;;
+esac
+
+# Try without a prefix underscore, then with it.
+for ac_symprfx in "" "_"; do
+
+  # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+  symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+  # Write the raw and C identifiers.
+  if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+    # Fake it for dumpbin and say T for any non-static function
+    # and D for any global variable.
+    # Also find C++ and __fastcall symbols from MSVC++,
+    # which start with @ or ?.
+    lt_cv_sys_global_symbol_pipe="$AWK '"\
+"     {last_section=section; section=\$ 3};"\
+"     /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+"     \$ 0!~/External *\|/{next};"\
+"     / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+"     {if(hide[section]) next};"\
+"     {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\
+"     {split(\$ 0, a, /\||\r/); split(a[2], s)};"\
+"     s[1]~/^[@?]/{print s[1], s[1]; next};"\
+"     s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\
+"     ' prfx=^$ac_symprfx"
+  else
+    lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[	 ]\($symcode$symcode*\)[	 ][	 ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+  fi
+
+  # Check to see that the pipe works correctly.
+  pipe_works=no
+
+  rm -f conftest*
+  cat > conftest.$ac_ext <<_LT_EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(void);
+void nm_test_func(void){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+_LT_EOF
+
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    # Now try to grab the symbols.
+    nlist=conftest.nm
+    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\""; } >&5
+  (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s "$nlist"; then
+      # Try sorting and uniquifying the output.
+      if sort "$nlist" | uniq > "$nlist"T; then
+	mv -f "$nlist"T "$nlist"
+      else
+	rm -f "$nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
+	if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+	  cat <<_LT_EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_LT_EOF
+	  # Now generate the symbol file.
+	  eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
+
+	  cat <<_LT_EOF >> conftest.$ac_ext
+
+/* The mapping between symbol names and symbols.  */
+const struct {
+  const char *name;
+  void       *address;
+}
+lt__PROGRAM__LTX_preloaded_symbols[] =
+{
+  { "@PROGRAM@", (void *) 0 },
+_LT_EOF
+	  $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/  {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
+	  cat <<\_LT_EOF >> conftest.$ac_ext
+  {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt__PROGRAM__LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+_LT_EOF
+	  # Now try linking the two files.
+	  mv conftest.$ac_objext conftstm.$ac_objext
+	  lt_save_LIBS="$LIBS"
+	  lt_save_CFLAGS="$CFLAGS"
+	  LIBS="conftstm.$ac_objext"
+	  CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag"
+	  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s conftest${ac_exeext}; then
+	    pipe_works=yes
+	  fi
+	  LIBS="$lt_save_LIBS"
+	  CFLAGS="$lt_save_CFLAGS"
+	else
+	  echo "cannot find nm_test_func in $nlist" >&5
+	fi
+      else
+	echo "cannot find nm_test_var in $nlist" >&5
+      fi
+    else
+      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5
+    fi
+  else
+    echo "$progname: failed program was:" >&5
+    cat conftest.$ac_ext >&5
+  fi
+  rm -rf conftest* conftst*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test "$pipe_works" = yes; then
+    break
+  else
+    lt_cv_sys_global_symbol_pipe=
+  fi
+done
+
+fi
+
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+  lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5
+$as_echo "failed" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
+$as_echo "ok" >&6; }
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Check whether --enable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then :
+  enableval=$enable_libtool_lock;
+fi
+
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    case `/usr/bin/file conftest.$ac_objext` in
+      *ELF-32*)
+	HPUX_IA64_MODE="32"
+	;;
+      *ELF-64*)
+	HPUX_IA64_MODE="64"
+	;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '#line 6467 "configure"' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    if test "$lt_cv_prog_gnu_ld" = yes; then
+      case `/usr/bin/file conftest.$ac_objext` in
+	*32-bit*)
+	  LD="${LD-ld} -melf32bsmip"
+	  ;;
+	*N32*)
+	  LD="${LD-ld} -melf32bmipn32"
+	  ;;
+	*64-bit*)
+	  LD="${LD-ld} -melf64bmip"
+	;;
+      esac
+    else
+      case `/usr/bin/file conftest.$ac_objext` in
+	*32-bit*)
+	  LD="${LD-ld} -32"
+	  ;;
+	*N32*)
+	  LD="${LD-ld} -n32"
+	  ;;
+	*64-bit*)
+	  LD="${LD-ld} -64"
+	  ;;
+      esac
+    fi
+  fi
+  rm -rf conftest*
+  ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    case `/usr/bin/file conftest.o` in
+      *32-bit*)
+	case $host in
+	  x86_64-*kfreebsd*-gnu)
+	    LD="${LD-ld} -m elf_i386_fbsd"
+	    ;;
+	  x86_64-*linux*)
+	    LD="${LD-ld} -m elf_i386"
+	    ;;
+	  ppc64-*linux*|powerpc64-*linux*)
+	    LD="${LD-ld} -m elf32ppclinux"
+	    ;;
+	  s390x-*linux*)
+	    LD="${LD-ld} -m elf_s390"
+	    ;;
+	  sparc64-*linux*)
+	    LD="${LD-ld} -m elf32_sparc"
+	    ;;
+	esac
+	;;
+      *64-bit*)
+	case $host in
+	  x86_64-*kfreebsd*-gnu)
+	    LD="${LD-ld} -m elf_x86_64_fbsd"
+	    ;;
+	  x86_64-*linux*)
+	    LD="${LD-ld} -m elf_x86_64"
+	    ;;
+	  ppc*-*linux*|powerpc*-*linux*)
+	    LD="${LD-ld} -m elf64ppc"
+	    ;;
+	  s390*-*linux*|s390*-*tpf*)
+	    LD="${LD-ld} -m elf64_s390"
+	    ;;
+	  sparc*-*linux*)
+	    LD="${LD-ld} -m elf64_sparc"
+	    ;;
+	esac
+	;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5
+$as_echo_n "checking whether the C compiler needs -belf... " >&6; }
+if test "${lt_cv_cc_needs_belf+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  lt_cv_cc_needs_belf=yes
+else
+  lt_cv_cc_needs_belf=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+     ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5
+$as_echo "$lt_cv_cc_needs_belf" >&6; }
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+sparc*-*solaris*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    case `/usr/bin/file conftest.o` in
+    *64-bit*)
+      case $lt_cv_prog_gnu_ld in
+      yes*) LD="${LD-ld} -m elf64_sparc" ;;
+      *)
+	if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
+	  LD="${LD-ld} -64"
+	fi
+	;;
+      esac
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+esac
+
+need_locks="$enable_libtool_lock"
+
+
+  case $host_os in
+    rhapsody* | darwin*)
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dsymutil; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_DSYMUTIL+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$DSYMUTIL"; then
+  ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+DSYMUTIL=$ac_cv_prog_DSYMUTIL
+if test -n "$DSYMUTIL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5
+$as_echo "$DSYMUTIL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_DSYMUTIL"; then
+  ac_ct_DSYMUTIL=$DSYMUTIL
+  # Extract the first word of "dsymutil", so it can be a program name with args.
+set dummy dsymutil; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_DSYMUTIL+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_DSYMUTIL"; then
+  ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_DSYMUTIL="dsymutil"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL
+if test -n "$ac_ct_DSYMUTIL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5
+$as_echo "$ac_ct_DSYMUTIL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_DSYMUTIL" = x; then
+    DSYMUTIL=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    DSYMUTIL=$ac_ct_DSYMUTIL
+  fi
+else
+  DSYMUTIL="$ac_cv_prog_DSYMUTIL"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args.
+set dummy ${ac_tool_prefix}nmedit; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_NMEDIT+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$NMEDIT"; then
+  ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+NMEDIT=$ac_cv_prog_NMEDIT
+if test -n "$NMEDIT"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5
+$as_echo "$NMEDIT" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_NMEDIT"; then
+  ac_ct_NMEDIT=$NMEDIT
+  # Extract the first word of "nmedit", so it can be a program name with args.
+set dummy nmedit; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_NMEDIT+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_NMEDIT"; then
+  ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_NMEDIT="nmedit"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT
+if test -n "$ac_ct_NMEDIT"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5
+$as_echo "$ac_ct_NMEDIT" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_NMEDIT" = x; then
+    NMEDIT=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    NMEDIT=$ac_ct_NMEDIT
+  fi
+else
+  NMEDIT="$ac_cv_prog_NMEDIT"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args.
+set dummy ${ac_tool_prefix}lipo; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_LIPO+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$LIPO"; then
+  ac_cv_prog_LIPO="$LIPO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_LIPO="${ac_tool_prefix}lipo"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+LIPO=$ac_cv_prog_LIPO
+if test -n "$LIPO"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5
+$as_echo "$LIPO" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_LIPO"; then
+  ac_ct_LIPO=$LIPO
+  # Extract the first word of "lipo", so it can be a program name with args.
+set dummy lipo; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_LIPO+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_LIPO"; then
+  ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_LIPO="lipo"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO
+if test -n "$ac_ct_LIPO"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5
+$as_echo "$ac_ct_LIPO" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_LIPO" = x; then
+    LIPO=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    LIPO=$ac_ct_LIPO
+  fi
+else
+  LIPO="$ac_cv_prog_LIPO"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}otool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_OTOOL+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$OTOOL"; then
+  ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_OTOOL="${ac_tool_prefix}otool"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+OTOOL=$ac_cv_prog_OTOOL
+if test -n "$OTOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5
+$as_echo "$OTOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OTOOL"; then
+  ac_ct_OTOOL=$OTOOL
+  # Extract the first word of "otool", so it can be a program name with args.
+set dummy otool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_OTOOL+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_OTOOL"; then
+  ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_OTOOL="otool"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL
+if test -n "$ac_ct_OTOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5
+$as_echo "$ac_ct_OTOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_OTOOL" = x; then
+    OTOOL=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OTOOL=$ac_ct_OTOOL
+  fi
+else
+  OTOOL="$ac_cv_prog_OTOOL"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args.
+set dummy ${ac_tool_prefix}otool64; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_OTOOL64+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$OTOOL64"; then
+  ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+OTOOL64=$ac_cv_prog_OTOOL64
+if test -n "$OTOOL64"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5
+$as_echo "$OTOOL64" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OTOOL64"; then
+  ac_ct_OTOOL64=$OTOOL64
+  # Extract the first word of "otool64", so it can be a program name with args.
+set dummy otool64; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_OTOOL64+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_OTOOL64"; then
+  ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_OTOOL64="otool64"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64
+if test -n "$ac_ct_OTOOL64"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5
+$as_echo "$ac_ct_OTOOL64" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_OTOOL64" = x; then
+    OTOOL64=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OTOOL64=$ac_ct_OTOOL64
+  fi
+else
+  OTOOL64="$ac_cv_prog_OTOOL64"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5
+$as_echo_n "checking for -single_module linker flag... " >&6; }
+if test "${lt_cv_apple_cc_single_mod+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_apple_cc_single_mod=no
+      if test -z "${LT_MULTI_MODULE}"; then
+	# By default we will add the -single_module flag. You can override
+	# by either setting the environment variable LT_MULTI_MODULE
+	# non-empty at configure time, or by adding -multi_module to the
+	# link flags.
+	rm -rf libconftest.dylib*
+	echo "int foo(void){return 1;}" > conftest.c
+	echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+-dynamiclib -Wl,-single_module conftest.c" >&5
+	$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+	  -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
+        _lt_result=$?
+	if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then
+	  lt_cv_apple_cc_single_mod=yes
+	else
+	  cat conftest.err >&5
+	fi
+	rm -rf libconftest.dylib*
+	rm -f conftest.*
+      fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5
+$as_echo "$lt_cv_apple_cc_single_mod" >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5
+$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; }
+if test "${lt_cv_ld_exported_symbols_list+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_ld_exported_symbols_list=no
+      save_LDFLAGS=$LDFLAGS
+      echo "_main" > conftest.sym
+      LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  lt_cv_ld_exported_symbols_list=yes
+else
+  lt_cv_ld_exported_symbols_list=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+	LDFLAGS="$save_LDFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5
+$as_echo "$lt_cv_ld_exported_symbols_list" >&6; }
+    case $host_os in
+    rhapsody* | darwin1.[012])
+      _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
+    darwin1.*)
+      _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+    darwin*) # darwin 5.x on
+      # if running on 10.5 or later, the deployment target defaults
+      # to the OS version, if on x86, and 10.4, the deployment
+      # target defaults to 10.4. Don't you love it?
+      case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
+	10.0,*86*-darwin8*|10.0,*-darwin[91]*)
+	  _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+	10.[012]*)
+	  _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+	10.*)
+	  _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+      esac
+    ;;
+  esac
+    if test "$lt_cv_apple_cc_single_mod" = "yes"; then
+      _lt_dar_single_mod='$single_module'
+    fi
+    if test "$lt_cv_ld_exported_symbols_list" = "yes"; then
+      _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym'
+    else
+      _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}'
+    fi
+    if test "$DSYMUTIL" != ":"; then
+      _lt_dsymutil='~$DSYMUTIL $lib || :'
+    else
+      _lt_dsymutil=
+    fi
+    ;;
+  esac
+
+for ac_header in dlfcn.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default
+"
+if test "x$ac_cv_header_dlfcn_h" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_DLFCN_H 1
+_ACEOF
+
+fi
+
+done
+
+
+
+# Set options
+
+
+
+        enable_dlopen=no
+
+
+  enable_win32_dll=no
+
+
+            # Check whether --enable-shared was given.
+if test "${enable_shared+set}" = set; then :
+  enableval=$enable_shared; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_shared=yes ;;
+    no) enable_shared=no ;;
+    *)
+      enable_shared=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_shared=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  enable_shared=yes
+fi
+
+
+
+
+
+
+
+
+
+  # Check whether --enable-static was given.
+if test "${enable_static+set}" = set; then :
+  enableval=$enable_static; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_static=yes ;;
+    no) enable_static=no ;;
+    *)
+     enable_static=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_static=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  enable_static=yes
+fi
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-pic was given.
+if test "${with_pic+set}" = set; then :
+  withval=$with_pic; pic_mode="$withval"
+else
+  pic_mode=default
+fi
+
+
+test -z "$pic_mode" && pic_mode=default
+
+
+
+
+
+
+
+  # Check whether --enable-fast-install was given.
+if test "${enable_fast_install+set}" = set; then :
+  enableval=$enable_fast_install; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_fast_install=yes ;;
+    no) enable_fast_install=no ;;
+    *)
+      enable_fast_install=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_fast_install=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  enable_fast_install=yes
+fi
+
+
+
+
+
+
+
+
+
+
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ltmain"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+test -z "$LN_S" && LN_S="ln -s"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+if test -n "${ZSH_VERSION+set}" ; then
+   setopt NO_GLOB_SUBST
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5
+$as_echo_n "checking for objdir... " >&6; }
+if test "${lt_cv_objdir+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+  lt_cv_objdir=.libs
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5
+$as_echo "$lt_cv_objdir" >&6; }
+objdir=$lt_cv_objdir
+
+
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define LT_OBJDIR "$lt_cv_objdir/"
+_ACEOF
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+case $host_os in
+aix3*)
+  # AIX sometimes has problems with the GCC collect2 program.  For some
+  # reason, if we set the COLLECT_NAMES environment variable, the problems
+  # vanish in a puff of smoke.
+  if test "X${COLLECT_NAMES+set}" != Xset; then
+    COLLECT_NAMES=
+    export COLLECT_NAMES
+  fi
+  ;;
+esac
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\(["`\\]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to delay expansion of an escaped single quote.
+delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+# Global variables:
+ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$LD" && LD=ld
+test -z "$ac_objext" && ac_objext=o
+
+for cc_temp in $compiler""; do
+  case $cc_temp in
+    compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+    distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+
+# Only perform the check for file, if the check method requires it
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+case $deplibs_check_method in
+file_magic*)
+  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5
+$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; }
+if test "${lt_cv_path_MAGIC_CMD+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MAGIC_CMD in
+[\\/*] |  ?:[\\/]*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD="$MAGIC_CMD"
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+  for ac_dir in $ac_dummy; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/${ac_tool_prefix}file; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file"
+      if test -n "$file_magic_test_file"; then
+	case $deplibs_check_method in
+	"file_magic "*)
+	  file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+	  MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+	    $EGREP "$file_magic_regex" > /dev/null; then
+	    :
+	  else
+	    cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+	  fi ;;
+	esac
+      fi
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+  MAGIC_CMD="$lt_save_MAGIC_CMD"
+  ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
+$as_echo "$MAGIC_CMD" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+
+
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+  if test -n "$ac_tool_prefix"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5
+$as_echo_n "checking for file... " >&6; }
+if test "${lt_cv_path_MAGIC_CMD+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MAGIC_CMD in
+[\\/*] |  ?:[\\/]*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD="$MAGIC_CMD"
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+  for ac_dir in $ac_dummy; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/file; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/file"
+      if test -n "$file_magic_test_file"; then
+	case $deplibs_check_method in
+	"file_magic "*)
+	  file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+	  MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+	    $EGREP "$file_magic_regex" > /dev/null; then
+	    :
+	  else
+	    cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+	  fi ;;
+	esac
+      fi
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+  MAGIC_CMD="$lt_save_MAGIC_CMD"
+  ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
+$as_echo "$MAGIC_CMD" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  else
+    MAGIC_CMD=:
+  fi
+fi
+
+  fi
+  ;;
+esac
+
+# Use C for the default configuration in the libtool script
+
+lt_save_CC="$CC"
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+objext=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+# Save the default compiler, since it gets overwritten when the other
+# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
+compiler_DEFAULT=$CC
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+
+lt_prog_compiler_no_builtin_flag=
+
+if test "$GCC" = yes; then
+  lt_prog_compiler_no_builtin_flag=' -fno-builtin'
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; }
+if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_rtti_exceptions=no
+   ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="-fno-rtti -fno-exceptions"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:7729: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:7733: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_rtti_exceptions=yes
+     fi
+   fi
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; }
+
+if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
+    lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions"
+else
+    :
+fi
+
+fi
+
+
+
+
+
+
+  lt_prog_compiler_wl=
+lt_prog_compiler_pic=
+lt_prog_compiler_static=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
+$as_echo_n "checking for $compiler option to produce PIC... " >&6; }
+
+  if test "$GCC" = yes; then
+    lt_prog_compiler_wl='-Wl,'
+    lt_prog_compiler_static='-static'
+
+    case $host_os in
+      aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+	# AIX 5 now supports IA64 processor
+	lt_prog_compiler_static='-Bstatic'
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            lt_prog_compiler_pic='-fPIC'
+        ;;
+      m68k)
+            # FIXME: we need at least 68020 code to build shared libraries, but
+            # adding the `-m68020' flag to GCC prevents building anything better,
+            # like `-m68040'.
+            lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
+        ;;
+      esac
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+
+    mingw* | cygwin* | pw32* | os2*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      lt_prog_compiler_pic='-DDLL_EXPORT'
+      ;;
+
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      lt_prog_compiler_pic='-fno-common'
+      ;;
+
+    hpux*)
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+	# +Z the default
+	;;
+      *)
+	lt_prog_compiler_pic='-fPIC'
+	;;
+      esac
+      ;;
+
+    interix[3-9]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+
+    msdosdjgpp*)
+      # Just because we use GCC doesn't mean we suddenly get shared libraries
+      # on systems that don't support them.
+      lt_prog_compiler_can_build_shared=no
+      enable_shared=no
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      lt_prog_compiler_pic='-fPIC -shared'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	lt_prog_compiler_pic=-Kconform_pic
+      fi
+      ;;
+
+    *)
+      lt_prog_compiler_pic='-fPIC'
+      ;;
+    esac
+  else
+    # PORTME Check for flag to pass linker flags through the system compiler.
+    case $host_os in
+    aix*)
+      lt_prog_compiler_wl='-Wl,'
+      if test "$host_cpu" = ia64; then
+	# AIX 5 now supports IA64 processor
+	lt_prog_compiler_static='-Bstatic'
+      else
+	lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+
+    mingw* | cygwin* | pw32* | os2*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      lt_prog_compiler_pic='-DDLL_EXPORT'
+      ;;
+
+    hpux9* | hpux10* | hpux11*)
+      lt_prog_compiler_wl='-Wl,'
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+	# +Z the default
+	;;
+      *)
+	lt_prog_compiler_pic='+Z'
+	;;
+      esac
+      # Is there a better lt_prog_compiler_static that works with the bundled CC?
+      lt_prog_compiler_static='${wl}-a ${wl}archive'
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      lt_prog_compiler_wl='-Wl,'
+      # PIC (with -KPIC) is the default.
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    linux* | k*bsd*-gnu)
+      case $cc_basename in
+      icc* | ecc* | ifort*)
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-KPIC'
+	lt_prog_compiler_static='-static'
+        ;;
+      pgcc* | pgf77* | pgf90* | pgf95*)
+        # Portland Group compilers (*not* the Pentium gcc compiler,
+	# which looks to be a dead project)
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-fpic'
+	lt_prog_compiler_static='-Bstatic'
+        ;;
+      ccc*)
+        lt_prog_compiler_wl='-Wl,'
+        # All Alpha code is PIC.
+        lt_prog_compiler_static='-non_shared'
+        ;;
+      xl*)
+	# IBM XL C 8.0/Fortran 10.1 on PPC
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-qpic'
+	lt_prog_compiler_static='-qstaticlink'
+	;;
+      *)
+	case `$CC -V 2>&1 | sed 5q` in
+	*Sun\ C*)
+	  # Sun C 5.9
+	  lt_prog_compiler_pic='-KPIC'
+	  lt_prog_compiler_static='-Bstatic'
+	  lt_prog_compiler_wl='-Wl,'
+	  ;;
+	*Sun\ F*)
+	  # Sun Fortran 8.3 passes all unrecognized flags to the linker
+	  lt_prog_compiler_pic='-KPIC'
+	  lt_prog_compiler_static='-Bstatic'
+	  lt_prog_compiler_wl=''
+	  ;;
+	esac
+	;;
+      esac
+      ;;
+
+    newsos6)
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      lt_prog_compiler_pic='-fPIC -shared'
+      ;;
+
+    osf3* | osf4* | osf5*)
+      lt_prog_compiler_wl='-Wl,'
+      # All OSF/1 code is PIC.
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    rdos*)
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    solaris*)
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      case $cc_basename in
+      f77* | f90* | f95*)
+	lt_prog_compiler_wl='-Qoption ld ';;
+      *)
+	lt_prog_compiler_wl='-Wl,';;
+      esac
+      ;;
+
+    sunos4*)
+      lt_prog_compiler_wl='-Qoption ld '
+      lt_prog_compiler_pic='-PIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    sysv4 | sysv4.2uw2* | sysv4.3*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec ;then
+	lt_prog_compiler_pic='-Kconform_pic'
+	lt_prog_compiler_static='-Bstatic'
+      fi
+      ;;
+
+    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    unicos*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_can_build_shared=no
+      ;;
+
+    uts4*)
+      lt_prog_compiler_pic='-pic'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    *)
+      lt_prog_compiler_can_build_shared=no
+      ;;
+    esac
+  fi
+
+case $host_os in
+  # For platforms which do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    lt_prog_compiler_pic=
+    ;;
+  *)
+    lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC"
+    ;;
+esac
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic" >&5
+$as_echo "$lt_prog_compiler_pic" >&6; }
+
+
+
+
+
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
+$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; }
+if test "${lt_cv_prog_compiler_pic_works+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_pic_works=no
+   ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$lt_prog_compiler_pic -DPIC"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:8053: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:8057: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_pic_works=yes
+     fi
+   fi
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5
+$as_echo "$lt_cv_prog_compiler_pic_works" >&6; }
+
+if test x"$lt_cv_prog_compiler_pic_works" = xyes; then
+    case $lt_prog_compiler_pic in
+     "" | " "*) ;;
+     *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;;
+     esac
+else
+    lt_prog_compiler_pic=
+     lt_prog_compiler_can_build_shared=no
+fi
+
+fi
+
+
+
+
+
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
+if test "${lt_cv_prog_compiler_static_works+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_static_works=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&5
+       $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         lt_cv_prog_compiler_static_works=yes
+       fi
+     else
+       lt_cv_prog_compiler_static_works=yes
+     fi
+   fi
+   $RM -r conftest*
+   LDFLAGS="$save_LDFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5
+$as_echo "$lt_cv_prog_compiler_static_works" >&6; }
+
+if test x"$lt_cv_prog_compiler_static_works" = xyes; then
+    :
+else
+    lt_prog_compiler_static=
+fi
+
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if test "${lt_cv_prog_compiler_c_o+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_c_o=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:8158: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:8162: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
+$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if test "${lt_cv_prog_compiler_c_o+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_c_o=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:8213: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:8217: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
+$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
+
+
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5
+$as_echo_n "checking if we can lock with hard links... " >&6; }
+  hard_links=yes
+  $RM conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5
+$as_echo "$hard_links" >&6; }
+  if test "$hard_links" = no; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
+
+  runpath_var=
+  allow_undefined_flag=
+  always_export_symbols=no
+  archive_cmds=
+  archive_expsym_cmds=
+  compiler_needs_object=no
+  enable_shared_with_static_runtimes=no
+  export_dynamic_flag_spec=
+  export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  hardcode_automatic=no
+  hardcode_direct=no
+  hardcode_direct_absolute=no
+  hardcode_libdir_flag_spec=
+  hardcode_libdir_flag_spec_ld=
+  hardcode_libdir_separator=
+  hardcode_minus_L=no
+  hardcode_shlibpath_var=unsupported
+  inherit_rpath=no
+  link_all_deplibs=unknown
+  module_cmds=
+  module_expsym_cmds=
+  old_archive_from_new_cmds=
+  old_archive_from_expsyms_cmds=
+  thread_safe_flag_spec=
+  whole_archive_flag_spec=
+  # include_expsyms should be a list of space-separated symbols to be *always*
+  # included in the symbol list
+  include_expsyms=
+  # exclude_expsyms can be an extended regexp of symbols to exclude
+  # it will be wrapped by ` (' and `)$', so one must not match beginning or
+  # end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+  # as well as any symbol that contains `d'.
+  exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
+  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+  # platforms (ab)use it in PIC code, but their linkers get confused if
+  # the symbol is explicitly referenced.  Since portable code cannot
+  # rely on this symbol name, it's probably fine to never include it in
+  # preloaded symbol tables.
+  # Exclude shared library initialization/finalization symbols.
+  extract_expsyms_cmds=
+
+  case $host_os in
+  cygwin* | mingw* | pw32*)
+    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    if test "$GCC" != yes; then
+      with_gnu_ld=no
+    fi
+    ;;
+  interix*)
+    # we just hope/assume this is gcc and not c89 (= MSVC++)
+    with_gnu_ld=yes
+    ;;
+  openbsd*)
+    with_gnu_ld=no
+    ;;
+  esac
+
+  ld_shlibs=yes
+  if test "$with_gnu_ld" = yes; then
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    wlarc='${wl}'
+
+    # Set some defaults for GNU ld with shared library support. These
+    # are reset later if shared libraries are not supported. Putting them
+    # here allows them to be overridden if necessary.
+    runpath_var=LD_RUN_PATH
+    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+    export_dynamic_flag_spec='${wl}--export-dynamic'
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
+      whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+    else
+      whole_archive_flag_spec=
+    fi
+    supports_anon_versioning=no
+    case `$LD -v 2>&1` in
+      *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+      *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+      *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+      *\ 2.11.*) ;; # other 2.11 versions
+      *) supports_anon_versioning=yes ;;
+    esac
+
+    # See if GNU ld supports shared libraries.
+    case $host_os in
+    aix[3-9]*)
+      # On AIX/PPC, the GNU linker is very broken
+      if test "$host_cpu" != ia64; then
+	ld_shlibs=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+_LT_EOF
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+            archive_expsym_cmds=''
+        ;;
+      m68k)
+            archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            hardcode_libdir_flag_spec='-L$libdir'
+            hardcode_minus_L=yes
+        ;;
+      esac
+      ;;
+
+    beos*)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	allow_undefined_flag=unsupported
+	# Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+	# support --undefined.  This deserves some investigation.  FIXME
+	archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    cygwin* | mingw* | pw32*)
+      # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless,
+      # as there is no search path for DLLs.
+      hardcode_libdir_flag_spec='-L$libdir'
+      allow_undefined_flag=unsupported
+      always_export_symbols=no
+      enable_shared_with_static_runtimes=yes
+      export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
+
+      if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+        archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+	# If the export-symbols file already is a .def file (1st line
+	# is EXPORTS), use it as is; otherwise, prepend...
+	archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+	  cp $export_symbols $output_objdir/$soname.def;
+	else
+	  echo EXPORTS > $output_objdir/$soname.def;
+	  cat $export_symbols >> $output_objdir/$soname.def;
+	fi~
+	$CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    interix[3-9]*)
+      hardcode_direct=no
+      hardcode_shlibpath_var=no
+      hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+      export_dynamic_flag_spec='${wl}-E'
+      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+      # Instead, shared libraries are loaded at an image base (0x10000000 by
+      # default) and relocated if they conflict, which is a slow very memory
+      # consuming and fragmenting process.  To avoid this, we pick a random,
+      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+      archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      ;;
+
+    gnu* | linux* | tpf* | k*bsd*-gnu)
+      tmp_diet=no
+      if test "$host_os" = linux-dietlibc; then
+	case $cc_basename in
+	  diet\ *) tmp_diet=yes;;	# linux-dietlibc with static linking (!diet-dyn)
+	esac
+      fi
+      if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+	 && test "$tmp_diet" = no
+      then
+	tmp_addflag=
+	tmp_sharedflag='-shared'
+	case $cc_basename,$host_cpu in
+        pgcc*)				# Portland Group C compiler
+	  whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+	  tmp_addflag=' $pic_flag'
+	  ;;
+	pgf77* | pgf90* | pgf95*)	# Portland Group f77 and f90 compilers
+	  whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+	  tmp_addflag=' $pic_flag -Mnomain' ;;
+	ecc*,ia64* | icc*,ia64*)	# Intel C compiler on ia64
+	  tmp_addflag=' -i_dynamic' ;;
+	efc*,ia64* | ifort*,ia64*)	# Intel Fortran compiler on ia64
+	  tmp_addflag=' -i_dynamic -nofor_main' ;;
+	ifc* | ifort*)			# Intel Fortran compiler
+	  tmp_addflag=' -nofor_main' ;;
+	xl[cC]*)			# IBM XL C 8.0 on PPC (deal with xlf below)
+	  tmp_sharedflag='-qmkshrobj'
+	  tmp_addflag= ;;
+	esac
+	case `$CC -V 2>&1 | sed 5q` in
+	*Sun\ C*)			# Sun C 5.9
+	  whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+	  compiler_needs_object=yes
+	  tmp_sharedflag='-G' ;;
+	*Sun\ F*)			# Sun Fortran 8.3
+	  tmp_sharedflag='-G' ;;
+	esac
+	archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+        if test "x$supports_anon_versioning" = xyes; then
+          archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+	    cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+	    echo "local: *; };" >> $output_objdir/$libname.ver~
+	    $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+        fi
+
+	case $cc_basename in
+	xlf*)
+	  # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
+	  whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive'
+	  hardcode_libdir_flag_spec=
+	  hardcode_libdir_flag_spec_ld='-rpath $libdir'
+	  archive_cmds='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib'
+	  if test "x$supports_anon_versioning" = xyes; then
+	    archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+	      cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+	      echo "local: *; };" >> $output_objdir/$libname.ver~
+	      $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+	  fi
+	  ;;
+	esac
+      else
+        ld_shlibs=no
+      fi
+      ;;
+
+    netbsd*)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+	wlarc=
+      else
+	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      fi
+      ;;
+
+    solaris*)
+      if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
+	ld_shlibs=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+      elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+      case `$LD -v 2>&1` in
+        *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+	ld_shlibs=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+	;;
+	*)
+	  # For security reasons, it is highly recommended that you always
+	  # use absolute paths for naming shared libraries, and exclude the
+	  # DT_RUNPATH tag from executables and libraries.  But doing so
+	  # requires that you compile everything twice, which is a pain.
+	  if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+	    archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	    archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+	  else
+	    ld_shlibs=no
+	  fi
+	;;
+      esac
+      ;;
+
+    sunos4*)
+      archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      wlarc=
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    *)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
+    esac
+
+    if test "$ld_shlibs" = no; then
+      runpath_var=
+      hardcode_libdir_flag_spec=
+      export_dynamic_flag_spec=
+      whole_archive_flag_spec=
+    fi
+  else
+    # PORTME fill in a description of your system's linker (not GNU ld)
+    case $host_os in
+    aix3*)
+      allow_undefined_flag=unsupported
+      always_export_symbols=yes
+      archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+      # Note: this linker hardcodes the directories in LIBPATH if there
+      # are no directories specified by -L.
+      hardcode_minus_L=yes
+      if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+	# Neither direct hardcoding nor static linking is supported with a
+	# broken collect2.
+	hardcode_direct=unsupported
+      fi
+      ;;
+
+    aix[4-9]*)
+      if test "$host_cpu" = ia64; then
+	# On IA64, the linker does run time linking by default, so we don't
+	# have to do anything special.
+	aix_use_runtimelinking=no
+	exp_sym_flag='-Bexport'
+	no_entry_flag=""
+      else
+	# If we're using GNU nm, then we don't want the "-C" option.
+	# -C means demangle to AIX nm, but means don't demangle with GNU nm
+	if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+	  export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+	else
+	  export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+	fi
+	aix_use_runtimelinking=no
+
+	# Test if we are trying to use run time linking or normal
+	# AIX style linking. If -brtl is somewhere in LDFLAGS, we
+	# need to do runtime linking.
+	case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
+	  for ld_flag in $LDFLAGS; do
+	  if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+	    aix_use_runtimelinking=yes
+	    break
+	  fi
+	  done
+	  ;;
+	esac
+
+	exp_sym_flag='-bexport'
+	no_entry_flag='-bnoentry'
+      fi
+
+      # When large executables or shared objects are built, AIX ld can
+      # have problems creating the table of contents.  If linking a library
+      # or program results in "error TOC overflow" add -mminimal-toc to
+      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+      archive_cmds=''
+      hardcode_direct=yes
+      hardcode_direct_absolute=yes
+      hardcode_libdir_separator=':'
+      link_all_deplibs=yes
+      file_list_spec='${wl}-f,'
+
+      if test "$GCC" = yes; then
+	case $host_os in aix4.[012]|aix4.[012].*)
+	# We only want to do this on AIX 4.2 and lower, the check
+	# below for broken collect2 doesn't work under 4.3+
+	  collect2name=`${CC} -print-prog-name=collect2`
+	  if test -f "$collect2name" &&
+	   strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+	  then
+	  # We have reworked collect2
+	  :
+	  else
+	  # We have old collect2
+	  hardcode_direct=unsupported
+	  # It fails to find uninstalled libraries when the uninstalled
+	  # path is not listed in the libpath.  Setting hardcode_minus_L
+	  # to unsupported forces relinking
+	  hardcode_minus_L=yes
+	  hardcode_libdir_flag_spec='-L$libdir'
+	  hardcode_libdir_separator=
+	  fi
+	  ;;
+	esac
+	shared_flag='-shared'
+	if test "$aix_use_runtimelinking" = yes; then
+	  shared_flag="$shared_flag "'${wl}-G'
+	fi
+      else
+	# not using gcc
+	if test "$host_cpu" = ia64; then
+	# VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+	# chokes on -Wl,-G. The following line is correct:
+	  shared_flag='-G'
+	else
+	  if test "$aix_use_runtimelinking" = yes; then
+	    shared_flag='${wl}-G'
+	  else
+	    shared_flag='${wl}-bM:SRE'
+	  fi
+	fi
+      fi
+
+      # It seems that -bexpall does not export symbols beginning with
+      # underscore (_), so it is better to generate a list of symbols to export.
+      always_export_symbols=yes
+      if test "$aix_use_runtimelinking" = yes; then
+	# Warning - without using the other runtime loading flags (-brtl),
+	# -berok will link without error, but may produce a broken library.
+	allow_undefined_flag='-berok'
+        # Determine the default libpath from the value encoded in an
+        # empty executable.
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+	/^0/ {
+	    s/^0  *\(.*\)$/\1/
+	    p
+	}
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+        hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+        archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+      else
+	if test "$host_cpu" = ia64; then
+	  hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+	  allow_undefined_flag="-z nodefs"
+	  archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+	else
+	 # Determine the default libpath from the value encoded in an
+	 # empty executable.
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+	/^0/ {
+	    s/^0  *\(.*\)$/\1/
+	    p
+	}
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+	 hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+	  # Warning - without using the other run time loading flags,
+	  # -berok will link without error, but may produce a broken library.
+	  no_undefined_flag=' ${wl}-bernotok'
+	  allow_undefined_flag=' ${wl}-berok'
+	  # Exported symbols can be pulled into shared objects from archives
+	  whole_archive_flag_spec='$convenience'
+	  archive_cmds_need_lc=yes
+	  # This is similar to how AIX traditionally builds its shared libraries.
+	  archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+	fi
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+            archive_expsym_cmds=''
+        ;;
+      m68k)
+            archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            hardcode_libdir_flag_spec='-L$libdir'
+            hardcode_minus_L=yes
+        ;;
+      esac
+      ;;
+
+    bsdi[45]*)
+      export_dynamic_flag_spec=-rdynamic
+      ;;
+
+    cygwin* | mingw* | pw32*)
+      # When not using gcc, we currently assume that we are using
+      # Microsoft Visual C++.
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      hardcode_libdir_flag_spec=' '
+      allow_undefined_flag=unsupported
+      # Tell ltmain to make .lib files, not .a files.
+      libext=lib
+      # Tell ltmain to make .dll files, not .so files.
+      shrext_cmds=".dll"
+      # FIXME: Setting linknames here is a bad hack.
+      archive_cmds='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames='
+      # The linker will automatically build a .lib file if we build a DLL.
+      old_archive_from_new_cmds='true'
+      # FIXME: Should let the user specify the lib program.
+      old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs'
+      fix_srcfile_path='`cygpath -w "$srcfile"`'
+      enable_shared_with_static_runtimes=yes
+      ;;
+
+    darwin* | rhapsody*)
+
+
+  archive_cmds_need_lc=no
+  hardcode_direct=no
+  hardcode_automatic=yes
+  hardcode_shlibpath_var=unsupported
+  whole_archive_flag_spec=''
+  link_all_deplibs=yes
+  allow_undefined_flag="$_lt_dar_allow_undefined"
+  if test "$GCC" = "yes"; then
+    output_verbose_link_cmd=echo
+    archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
+    module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
+    archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
+    module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
+
+  else
+  ld_shlibs=no
+  fi
+
+      ;;
+
+    dgux*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_shlibpath_var=no
+      ;;
+
+    freebsd1*)
+      ld_shlibs=no
+      ;;
+
+    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+    # support.  Future versions do this automatically, but an explicit c++rt0.o
+    # does not break anything, and helps significantly (at the cost of a little
+    # extra space).
+    freebsd2.2*)
+      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+    freebsd2*)
+      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct=yes
+      hardcode_minus_L=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+    freebsd* | dragonfly* | openbsd* | bitrig*)
+      archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    hpux9*)
+      if test "$GCC" = yes; then
+	archive_cmds='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      else
+	archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      fi
+      hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+      hardcode_libdir_separator=:
+      hardcode_direct=yes
+
+      # hardcode_minus_L: Not really in the search PATH,
+      # but as the default location of the library.
+      hardcode_minus_L=yes
+      export_dynamic_flag_spec='${wl}-E'
+      ;;
+
+    hpux10*)
+      if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+	archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      if test "$with_gnu_ld" = no; then
+	hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+	hardcode_libdir_flag_spec_ld='+b $libdir'
+	hardcode_libdir_separator=:
+	hardcode_direct=yes
+	hardcode_direct_absolute=yes
+	export_dynamic_flag_spec='${wl}-E'
+	# hardcode_minus_L: Not really in the search PATH,
+	# but as the default location of the library.
+	hardcode_minus_L=yes
+      fi
+      ;;
+
+    hpux11*)
+      if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+	case $host_cpu in
+	hppa*64*)
+	  archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	ia64*)
+	  archive_cmds='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+	  archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	esac
+      else
+	case $host_cpu in
+	hppa*64*)
+	  archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	ia64*)
+	  archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+	  archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	esac
+      fi
+      if test "$with_gnu_ld" = no; then
+	hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+	hardcode_libdir_separator=:
+
+	case $host_cpu in
+	hppa*64*|ia64*)
+	  hardcode_direct=no
+	  hardcode_shlibpath_var=no
+	  ;;
+	*)
+	  hardcode_direct=yes
+	  hardcode_direct_absolute=yes
+	  export_dynamic_flag_spec='${wl}-E'
+
+	  # hardcode_minus_L: Not really in the search PATH,
+	  # but as the default location of the library.
+	  hardcode_minus_L=yes
+	  ;;
+	esac
+      fi
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      if test "$GCC" = yes; then
+	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	# Try to use the -exported_symbol ld option, if it does not
+	# work, assume that -exports_file does not work either and
+	# implicitly export all symbols.
+        save_LDFLAGS="$LDFLAGS"
+        LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int foo(void) {}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+        LDFLAGS="$save_LDFLAGS"
+      else
+	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib'
+      fi
+      archive_cmds_need_lc='no'
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      inherit_rpath=yes
+      link_all_deplibs=yes
+      ;;
+
+    netbsd*)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+      else
+	archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+      fi
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    newsos6)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct=yes
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      hardcode_shlibpath_var=no
+      ;;
+
+    *nto* | *qnx*)
+      ;;
+
+    openbsd*)
+      if test -f /usr/libexec/ld.so; then
+	hardcode_direct=yes
+	hardcode_shlibpath_var=no
+	hardcode_direct_absolute=yes
+	if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+	  archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	  archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+	  hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+	  export_dynamic_flag_spec='${wl}-E'
+	else
+	  case $host_os in
+	   openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+	     archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+	     hardcode_libdir_flag_spec='-R$libdir'
+	     ;;
+	   *)
+	     archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	     hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+	     ;;
+	  esac
+	fi
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    os2*)
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_minus_L=yes
+      allow_undefined_flag=unsupported
+      archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+      old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+      ;;
+
+    osf3*)
+      if test "$GCC" = yes; then
+	allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+	allow_undefined_flag=' -expect_unresolved \*'
+	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+      fi
+      archive_cmds_need_lc='no'
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      ;;
+
+    osf4* | osf5*)	# as osf3* with the addition of -msym flag
+      if test "$GCC" = yes; then
+	allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      else
+	allow_undefined_flag=' -expect_unresolved \*'
+	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+	archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
+	$CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp'
+
+	# Both c and cxx compiler support -rpath directly
+	hardcode_libdir_flag_spec='-rpath $libdir'
+      fi
+      archive_cmds_need_lc='no'
+      hardcode_libdir_separator=:
+      ;;
+
+    solaris*)
+      no_undefined_flag=' -z defs'
+      if test "$GCC" = yes; then
+	wlarc='${wl}'
+	archive_cmds='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+      else
+	case `$CC -V 2>&1` in
+	*"Compilers 5.0"*)
+	  wlarc=''
+	  archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
+	  ;;
+	*)
+	  wlarc='${wl}'
+	  archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags'
+	  archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+	  ;;
+	esac
+      fi
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_shlibpath_var=no
+      case $host_os in
+      solaris2.[0-5] | solaris2.[0-5].*) ;;
+      *)
+	# The compiler driver will combine and reorder linker options,
+	# but understands `-z linker_flag'.  GCC discards it without `$wl',
+	# but is careful enough not to reorder.
+	# Supported since Solaris 2.6 (maybe 2.5.1?)
+	if test "$GCC" = yes; then
+	  whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+	else
+	  whole_archive_flag_spec='-z allextract$convenience -z defaultextract'
+	fi
+	;;
+      esac
+      link_all_deplibs=yes
+      ;;
+
+    sunos4*)
+      if test "x$host_vendor" = xsequent; then
+	# Use $CC to link under sequent, because it throws in some extra .o
+	# files that make .init and .fini sections work.
+	archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_direct=yes
+      hardcode_minus_L=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    sysv4)
+      case $host_vendor in
+	sni)
+	  archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  hardcode_direct=yes # is this really true???
+	;;
+	siemens)
+	  ## LD is ld it makes a PLAMLIB
+	  ## CC just makes a GrossModule.
+	  archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+	  reload_cmds='$CC -r -o $output$reload_objs'
+	  hardcode_direct=no
+        ;;
+	motorola)
+	  archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+	;;
+      esac
+      runpath_var='LD_RUN_PATH'
+      hardcode_shlibpath_var=no
+      ;;
+
+    sysv4.3*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_shlibpath_var=no
+      export_dynamic_flag_spec='-Bexport'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	hardcode_shlibpath_var=no
+	runpath_var=LD_RUN_PATH
+	hardcode_runpath_var=yes
+	ld_shlibs=yes
+      fi
+      ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+      no_undefined_flag='${wl}-z,text'
+      archive_cmds_need_lc=no
+      hardcode_shlibpath_var=no
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+	archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6*)
+      # Note: We can NOT use -z defs as we might desire, because we do not
+      # link with -lc, and that would cause any symbols used from libc to
+      # always be unresolved, which means just about no library would
+      # ever link correctly.  If we're not using GNU ld we use -z text
+      # though, which does catch some bad symbols but isn't as heavy-handed
+      # as -z defs.
+      no_undefined_flag='${wl}-z,text'
+      allow_undefined_flag='${wl}-z,nodefs'
+      archive_cmds_need_lc=no
+      hardcode_shlibpath_var=no
+      hardcode_libdir_flag_spec='${wl}-R,$libdir'
+      hardcode_libdir_separator=':'
+      link_all_deplibs=yes
+      export_dynamic_flag_spec='${wl}-Bexport'
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+	archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    uts4*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_shlibpath_var=no
+      ;;
+
+    *)
+      ld_shlibs=no
+      ;;
+    esac
+
+    if test x$host_vendor = xsni; then
+      case $host in
+      sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+	export_dynamic_flag_spec='${wl}-Blargedynsym'
+	;;
+      esac
+    fi
+  fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5
+$as_echo "$ld_shlibs" >&6; }
+test "$ld_shlibs" = no && can_build_shared=no
+
+with_gnu_ld=$with_gnu_ld
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc" in
+x|xyes)
+  # Assume -lc should be added
+  archive_cmds_need_lc=yes
+
+  if test "$enable_shared" = yes && test "$GCC" = yes; then
+    case $archive_cmds in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
+$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; }
+      $RM conftest*
+      echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+      if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } 2>conftest.err; then
+        soname=conftest
+        lib=conftest
+        libobjs=conftest.$ac_objext
+        deplibs=
+        wl=$lt_prog_compiler_wl
+	pic_flag=$lt_prog_compiler_pic
+        compiler_flags=-v
+        linker_flags=-v
+        verstring=
+        output_objdir=.
+        libname=conftest
+        lt_save_allow_undefined_flag=$allow_undefined_flag
+        allow_undefined_flag=
+        if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
+  (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+        then
+	  archive_cmds_need_lc=no
+        else
+	  archive_cmds_need_lc=yes
+        fi
+        allow_undefined_flag=$lt_save_allow_undefined_flag
+      else
+        cat conftest.err 1>&5
+      fi
+      $RM conftest*
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: $archive_cmds_need_lc" >&5
+$as_echo "$archive_cmds_need_lc" >&6; }
+      ;;
+    esac
+  fi
+  ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5
+$as_echo_n "checking dynamic linker characteristics... " >&6; }
+
+if test "$GCC" = yes; then
+  case $host_os in
+    darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
+    *) lt_awk_arg="/^libraries:/" ;;
+  esac
+  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+  if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then
+    # if the path contains ";" then we assume it to be the separator
+    # otherwise default to the standard path separator (i.e. ":") - it is
+    # assumed that no part of a normal pathname contains ";" but that should
+    # okay in the real world where ";" in dirpaths is itself problematic.
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'`
+  else
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
+  fi
+  # Ok, now we have the path, separated by spaces, we can step through it
+  # and add multilib dir if necessary.
+  lt_tmp_lt_search_path_spec=
+  lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+  for lt_sys_path in $lt_search_path_spec; do
+    if test -d "$lt_sys_path/$lt_multi_os_dir"; then
+      lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
+    else
+      test -d "$lt_sys_path" && \
+	lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+    fi
+  done
+  lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk '
+BEGIN {RS=" "; FS="/|\n";} {
+  lt_foo="";
+  lt_count=0;
+  for (lt_i = NF; lt_i > 0; lt_i--) {
+    if ($lt_i != "" && $lt_i != ".") {
+      if ($lt_i == "..") {
+        lt_count++;
+      } else {
+        if (lt_count == 0) {
+          lt_foo="/" $lt_i lt_foo;
+        } else {
+          lt_count--;
+        }
+      }
+    }
+  }
+  if (lt_foo != "") { lt_freq[lt_foo]++; }
+  if (lt_freq[lt_foo] == 1) { print lt_foo; }
+}'`
+  sys_lib_search_path_spec=`$ECHO $lt_search_path_spec`
+else
+  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX 3 has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}${shared_ext}$major'
+  ;;
+
+aix[4-9]*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  hardcode_into_libs=yes
+  if test "$host_cpu" = ia64; then
+    # AIX 5 supports IA64
+    library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line `#! .'.  This would cause the generated library to
+    # depend on `.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[01] | aix4.[01].*)
+      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+	   echo ' yes '
+	   echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then
+	:
+      else
+	can_build_shared=no
+      fi
+      ;;
+    esac
+    # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+    # soname into executable. Probably we can add versioning support to
+    # collect2, so additional links can be useful in future.
+    if test "$aix_use_runtimelinking" = yes; then
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    else
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='${libname}${release}.a $libname.a'
+      soname_spec='${libname}${release}${shared_ext}$major'
+    fi
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  case $host_cpu in
+  powerpc)
+    # Since July 2007 AmigaOS4 officially supports .so libraries.
+    # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    ;;
+  m68k)
+    library_names_spec='$libname.ixlibrary $libname.a'
+    # Create ${libname}_ixlibrary.a entries in /sys/libs.
+    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+    ;;
+  esac
+  ;;
+
+beos*)
+  library_names_spec='${libname}${shared_ext}'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi[45]*)
+  version_type=linux
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32*)
+  version_type=windows
+  shrext_cmds=".dll"
+  need_version=no
+  need_lib_prefix=no
+
+  case $GCC,$host_os in
+  yes,cygwin* | yes,mingw* | yes,pw32*)
+    library_names_spec='$libname.dll.a'
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname~
+      if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+        eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+      fi'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+
+    case $host_os in
+    cygwin*)
+      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+      soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+      ;;
+    mingw*)
+      # MinGW DLLs use traditional 'lib' prefix
+      soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+      if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then
+        # It is most probably a Windows format PATH printed by
+        # mingw gcc, but we are running on Cygwin. Gcc prints its search
+        # path with ; separators, and with drive letters. We can handle the
+        # drive letters (cygwin fileutils understands them), so leave them,
+        # especially as we might pass files found there to a mingw objdump,
+        # which wouldn't understand a cygwinified path. Ahh.
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+      else
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
+      fi
+      ;;
+    pw32*)
+      # pw32 DLLs use 'pw' prefix rather than 'lib'
+      library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    esac
+    ;;
+
+  *)
+    library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+    ;;
+  esac
+  dynamic_linker='Win32 ld.exe'
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+  soname_spec='${libname}${release}${major}$shared_ext'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+
+  sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"
+  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+  ;;
+
+dgux*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+freebsd1*)
+  dynamic_linker=no
+  ;;
+
+freebsd* | dragonfly*)
+  # DragonFly does not have aout.  When/if they implement a new
+  # versioning mechanism, adjust this.
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[123]*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  freebsd3.[01]* | freebsdelf3.[01]*)
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+  freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  *) # from 4.6 on, and DragonFly
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  case $host_cpu in
+  ia64*)
+    shrext_cmds='.so'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.so"
+    shlibpath_var=LD_LIBRARY_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    if test "X$HPUX_IA64_MODE" = X32; then
+      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+    else
+      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+    fi
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  hppa*64*)
+    shrext_cmds='.sl'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  *)
+    shrext_cmds='.sl'
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=SHLIB_PATH
+    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    ;;
+  esac
+  # HP-UX runs *really* slowly unless shared libraries are mode 555.
+  postinstall_cmds='chmod 555 $lib'
+  ;;
+
+interix[3-9]*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)
+	if test "$lt_cv_prog_gnu_ld" = yes; then
+		version_type=linux
+	else
+		version_type=irix
+	fi ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+      libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+      libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  hardcode_into_libs=yes
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+  dynamic_linker=no
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  # Some binutils ld are patched to set DT_RUNPATH
+  save_LDFLAGS=$LDFLAGS
+  save_libdir=$libdir
+  eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \
+       LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\""
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  if  ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then :
+  shlibpath_overrides_runpath=yes
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+  LDFLAGS=$save_LDFLAGS
+  libdir=$save_libdir
+
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # Append ld.so.conf contents to the search path
+  if test -f /etc/ld.so.conf; then
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+  fi
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+*nto* | *qnx*)
+  version_type=qnx
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='ldqnx.so'
+  ;;
+
+openbsd*)
+  version_type=sunos
+  sys_lib_dlsearch_path_spec="/usr/lib"
+  need_lib_prefix=no
+  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+  case $host_os in
+    openbsd3.3 | openbsd3.3.*)	need_version=yes ;;
+    *)				need_version=no  ;;
+  esac
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    case $host_os in
+      openbsd2.[89] | openbsd2.[89].*)
+	shlibpath_overrides_runpath=no
+	;;
+      *)
+	shlibpath_overrides_runpath=yes
+	;;
+      esac
+  else
+    shlibpath_overrides_runpath=yes
+  fi
+  ;;
+
+os2*)
+  libname_spec='$name'
+  shrext_cmds=".dll"
+  need_lib_prefix=no
+  library_names_spec='$libname${shared_ext} $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+rdos*)
+  dynamic_linker=no
+  ;;
+
+solaris*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux
+    library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+    soname_spec='$libname${shared_ext}.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  version_type=freebsd-elf
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  if test "$with_gnu_ld" = yes; then
+    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+  else
+    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+    case $host_os in
+      sco3.2v5*)
+        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+	;;
+    esac
+  fi
+  sys_lib_dlsearch_path_spec='/usr/lib'
+  ;;
+
+tpf*)
+  # TPF is a cross-target only.  Preferred cross-host = GNU/Linux.
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_name_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+uts4*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5
+$as_echo "$dynamic_linker" >&6; }
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
+  sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
+fi
+if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
+  sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
+$as_echo_n "checking how to hardcode library paths into programs... " >&6; }
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" ||
+   test -n "$runpath_var" ||
+   test "X$hardcode_automatic" = "Xyes" ; then
+
+  # We can hardcode non-existent directories.
+  if test "$hardcode_direct" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no &&
+     test "$hardcode_minus_L" != no; then
+    # Linking always hardcodes the temporary library directory.
+    hardcode_action=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    hardcode_action=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  hardcode_action=unsupported
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5
+$as_echo "$hardcode_action" >&6; }
+
+if test "$hardcode_action" = relink ||
+   test "$inherit_rpath" = yes; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+
+
+
+
+
+
+  if test "x$enable_dlopen" != xyes; then
+  enable_dlopen=unknown
+  enable_dlopen_self=unknown
+  enable_dlopen_self_static=unknown
+else
+  lt_cv_dlopen=no
+  lt_cv_dlopen_libs=
+
+  case $host_os in
+  beos*)
+    lt_cv_dlopen="load_add_on"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ;;
+
+  mingw* | pw32*)
+    lt_cv_dlopen="LoadLibrary"
+    lt_cv_dlopen_libs=
+    ;;
+
+  cygwin*)
+    lt_cv_dlopen="dlopen"
+    lt_cv_dlopen_libs=
+    ;;
+
+  darwin*)
+  # if libdl is installed we need to link against it
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+$as_echo_n "checking for dlopen in -ldl... " >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dl_dlopen=yes
+else
+  ac_cv_lib_dl_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = x""yes; then :
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+
+    lt_cv_dlopen="dyld"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+
+fi
+
+    ;;
+
+  *)
+    ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load"
+if test "x$ac_cv_func_shl_load" = x""yes; then :
+  lt_cv_dlopen="shl_load"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5
+$as_echo_n "checking for shl_load in -ldld... " >&6; }
+if test "${ac_cv_lib_dld_shl_load+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load ();
+int
+main ()
+{
+return shl_load ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dld_shl_load=yes
+else
+  ac_cv_lib_dld_shl_load=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5
+$as_echo "$ac_cv_lib_dld_shl_load" >&6; }
+if test "x$ac_cv_lib_dld_shl_load" = x""yes; then :
+  lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"
+else
+  ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen"
+if test "x$ac_cv_func_dlopen" = x""yes; then :
+  lt_cv_dlopen="dlopen"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+$as_echo_n "checking for dlopen in -ldl... " >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dl_dlopen=yes
+else
+  ac_cv_lib_dl_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = x""yes; then :
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5
+$as_echo_n "checking for dlopen in -lsvld... " >&6; }
+if test "${ac_cv_lib_svld_dlopen+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsvld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_svld_dlopen=yes
+else
+  ac_cv_lib_svld_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5
+$as_echo "$ac_cv_lib_svld_dlopen" >&6; }
+if test "x$ac_cv_lib_svld_dlopen" = x""yes; then :
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5
+$as_echo_n "checking for dld_link in -ldld... " >&6; }
+if test "${ac_cv_lib_dld_dld_link+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dld_link ();
+int
+main ()
+{
+return dld_link ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dld_dld_link=yes
+else
+  ac_cv_lib_dld_dld_link=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5
+$as_echo "$ac_cv_lib_dld_dld_link" >&6; }
+if test "x$ac_cv_lib_dld_dld_link" = x""yes; then :
+  lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+    ;;
+  esac
+
+  if test "x$lt_cv_dlopen" != xno; then
+    enable_dlopen=yes
+  else
+    enable_dlopen=no
+  fi
+
+  case $lt_cv_dlopen in
+  dlopen)
+    save_CPPFLAGS="$CPPFLAGS"
+    test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+    save_LDFLAGS="$LDFLAGS"
+    wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+    save_LIBS="$LIBS"
+    LIBS="$lt_cv_dlopen_libs $LIBS"
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5
+$as_echo_n "checking whether a program can dlopen itself... " >&6; }
+if test "${lt_cv_dlopen_self+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  	  if test "$cross_compiling" = yes; then :
+  lt_cv_dlopen_self=cross
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<_LT_EOF
+#line 10572 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL		RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL		DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL		0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW		RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW		DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW	RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW	DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW	0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+    exit (status);
+}
+_LT_EOF
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) >&5 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
+      x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;
+      x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;;
+    esac
+  else :
+    # compilation failed
+    lt_cv_dlopen_self=no
+  fi
+fi
+rm -fr conftest*
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5
+$as_echo "$lt_cv_dlopen_self" >&6; }
+
+    if test "x$lt_cv_dlopen_self" = xyes; then
+      wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5
+$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; }
+if test "${lt_cv_dlopen_self_static+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  	  if test "$cross_compiling" = yes; then :
+  lt_cv_dlopen_self_static=cross
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<_LT_EOF
+#line 10672 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL		RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL		DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL		0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW		RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW		DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW	RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW	DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW	0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+    exit (status);
+}
+_LT_EOF
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) >&5 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
+      x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;
+      x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;;
+    esac
+  else :
+    # compilation failed
+    lt_cv_dlopen_self_static=no
+  fi
+fi
+rm -fr conftest*
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5
+$as_echo "$lt_cv_dlopen_self_static" >&6; }
+    fi
+
+    CPPFLAGS="$save_CPPFLAGS"
+    LDFLAGS="$save_LDFLAGS"
+    LIBS="$save_LIBS"
+    ;;
+  esac
+
+  case $lt_cv_dlopen_self in
+  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+  *) enable_dlopen_self=unknown ;;
+  esac
+
+  case $lt_cv_dlopen_self_static in
+  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+  *) enable_dlopen_self_static=unknown ;;
+  esac
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+striplib=
+old_striplib=
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5
+$as_echo_n "checking whether stripping libraries is possible... " >&6; }
+if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+  case $host_os in
+  darwin*)
+    if test -n "$STRIP" ; then
+      striplib="$STRIP -x"
+      old_striplib="$STRIP -S"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+    else
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+    fi
+    ;;
+  *)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+    ;;
+  esac
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+  # Report which library types will actually be built
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5
+$as_echo_n "checking if libtool supports shared libraries... " >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5
+$as_echo "$can_build_shared" >&6; }
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5
+$as_echo_n "checking whether to build shared libraries... " >&6; }
+  test "$can_build_shared" = "no" && enable_shared=no
+
+  # On AIX, shared libraries and static libraries use the same namespace, and
+  # are all built from PIC.
+  case $host_os in
+  aix3*)
+    test "$enable_shared" = yes && enable_static=no
+    if test -n "$RANLIB"; then
+      archive_cmds="$archive_cmds~\$RANLIB \$lib"
+      postinstall_cmds='$RANLIB $lib'
+    fi
+    ;;
+
+  aix[4-9]*)
+    if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+      test "$enable_shared" = yes && enable_static=no
+    fi
+    ;;
+  esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5
+$as_echo "$enable_shared" >&6; }
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5
+$as_echo_n "checking whether to build static libraries... " >&6; }
+  # Make sure either enable_shared or enable_static is yes.
+  test "$enable_shared" = yes || enable_static=yes
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5
+$as_echo "$enable_static" >&6; }
+
+
+
+
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+
+
+
+
+
+
+
+
+
+
+
+
+        ac_config_commands="$ac_config_commands libtool"
+
+
+
+
+# Only expand once:
+
+
+
+
+# Check whether --enable-largefile was given.
+if test "${enable_largefile+set}" = set; then :
+  enableval=$enable_largefile;
+fi
+
+if test "$enable_largefile" != no; then
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5
+$as_echo_n "checking for special C compiler options needed for large files... " >&6; }
+if test "${ac_cv_sys_largefile_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_sys_largefile_CC=no
+     if test "$GCC" != yes; then
+       ac_save_CC=$CC
+       while :; do
+	 # IRIX 6.2 and later do not support large files by default,
+	 # so use the C compiler's -n32 option if that helps.
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+	 if ac_fn_c_try_compile "$LINENO"; then :
+  break
+fi
+rm -f core conftest.err conftest.$ac_objext
+	 CC="$CC -n32"
+	 if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_largefile_CC=' -n32'; break
+fi
+rm -f core conftest.err conftest.$ac_objext
+	 break
+       done
+       CC=$ac_save_CC
+       rm -f conftest.$ac_ext
+    fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5
+$as_echo "$ac_cv_sys_largefile_CC" >&6; }
+  if test "$ac_cv_sys_largefile_CC" != no; then
+    CC=$CC$ac_cv_sys_largefile_CC
+  fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5
+$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; }
+if test "${ac_cv_sys_file_offset_bits+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  while :; do
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_file_offset_bits=no; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#define _FILE_OFFSET_BITS 64
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_file_offset_bits=64; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  ac_cv_sys_file_offset_bits=unknown
+  break
+done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5
+$as_echo "$ac_cv_sys_file_offset_bits" >&6; }
+case $ac_cv_sys_file_offset_bits in #(
+  no | unknown) ;;
+  *)
+cat >>confdefs.h <<_ACEOF
+#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits
+_ACEOF
+;;
+esac
+rm -rf conftest*
+  if test $ac_cv_sys_file_offset_bits = unknown; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5
+$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; }
+if test "${ac_cv_sys_large_files+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  while :; do
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_large_files=no; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#define _LARGE_FILES 1
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_large_files=1; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  ac_cv_sys_large_files=unknown
+  break
+done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5
+$as_echo "$ac_cv_sys_large_files" >&6; }
+case $ac_cv_sys_large_files in #(
+  no | unknown) ;;
+  *)
+cat >>confdefs.h <<_ACEOF
+#define _LARGE_FILES $ac_cv_sys_large_files
+_ACEOF
+;;
+esac
+rm -rf conftest*
+  fi
+fi
+
+
+backtrace_supported=yes
+
+if test -n "${with_target_subdir}"; then
+  # We are compiling a GCC library.  We can assume that the unwind
+  # library exists.
+  BACKTRACE_FILE="backtrace.lo simple.lo"
+else
+  ac_fn_c_check_header_mongrel "$LINENO" "unwind.h" "ac_cv_header_unwind_h" "$ac_includes_default"
+if test "x$ac_cv_header_unwind_h" = x""yes; then :
+  ac_fn_c_check_func "$LINENO" "_Unwind_Backtrace" "ac_cv_func__Unwind_Backtrace"
+if test "x$ac_cv_func__Unwind_Backtrace" = x""yes; then :
+  BACKTRACE_FILE="backtrace.lo simple.lo"
+else
+  BACKTRACE_FILE="nounwind.lo"
+                    backtrace_supported=no
+fi
+
+else
+  BACKTRACE_FILE="nounwind.lo"
+     backtrace_supported=no
+fi
+
+
+fi
+
+
+EXTRA_FLAGS=
+if test -n "${with_target_subdir}"; then
+  EXTRA_FLAGS="-funwind-tables -frandom-seed=\$@"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -funwind-tables option" >&5
+$as_echo_n "checking for -funwind-tables option... " >&6; }
+if test "${libbacktrace_cv_c_unwind_tables+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  CFLAGS_hold="$CFLAGS"
+     CFLAGS="$CFLAGS -funwind-tables"
+     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+static int f() { return 0; }
+int
+main ()
+{
+return f();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libbacktrace_cv_c_unwind_tables=yes
+else
+  libbacktrace_cv_c_unwind_tables=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+     CFLAGS="$CFLAGS_hold"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libbacktrace_cv_c_unwind_tables" >&5
+$as_echo "$libbacktrace_cv_c_unwind_tables" >&6; }
+  if test "$libbacktrace_cv_c_unwind_tables" = "yes"; then
+    EXTRA_FLAGS=-funwind-tables
+  fi
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -frandom-seed=string option" >&5
+$as_echo_n "checking for -frandom-seed=string option... " >&6; }
+if test "${libbacktrace_cv_c_random_seed_string+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  CFLAGS_hold="$CFLAGS"
+     CFLAGS="$CFLAGS -frandom-seed=conftest.lo"
+     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libbacktrace_cv_c_random_seed_string=yes
+else
+  libbacktrace_cv_c_random_seed_string=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+     CFLAGS="$CFLAGS_hold"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libbacktrace_cv_c_random_seed_string" >&5
+$as_echo "$libbacktrace_cv_c_random_seed_string" >&6; }
+  if test "$libbacktrace_cv_c_random_seed_string" = "yes"; then
+    EXTRA_FLAGS="$EXTRA_FLAGS -frandom-seed=\$@"
+  fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+WARN_FLAGS=
+save_CFLAGS="$CFLAGS"
+for real_option in -W -Wall -Wwrite-strings -Wstrict-prototypes \
+			  -Wmissing-prototypes -Wold-style-definition \
+			  -Wmissing-format-attribute -Wcast-qual; do
+  # Do the check with the no- prefix removed since gcc silently
+  # accepts any -Wno-* option on purpose
+  case $real_option in
+    -Wno-*) option=-W`expr x$real_option : 'x-Wno-\(.*\)'` ;;
+    *) option=$real_option ;;
+  esac
+  as_acx_Woption=`$as_echo "acx_cv_prog_cc_warning_$option" | $as_tr_sh`
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports $option" >&5
+$as_echo_n "checking whether $CC supports $option... " >&6; }
+if { as_var=$as_acx_Woption; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+else
+  CFLAGS="$option"
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$as_acx_Woption=yes"
+else
+  eval "$as_acx_Woption=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+eval ac_res=\$$as_acx_Woption
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  if test `eval 'as_val=${'$as_acx_Woption'};$as_echo "$as_val"'` = yes; then :
+  WARN_FLAGS="$WARN_FLAGS${WARN_FLAGS:+ }$real_option"
+fi
+  done
+CFLAGS="$save_CFLAGS"
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+if test -n "${with_target_subdir}"; then
+  WARN_FLAGS="$WARN_FLAGS -Werror"
+fi
+
+
+
+if test -n "${with_target_subdir}"; then
+
+
+# Check whether --with-system-libunwind was given.
+if test "${with_system_libunwind+set}" = set; then :
+  withval=$with_system_libunwind;
+fi
+
+  # If system-libunwind was not specifically set, pick a default setting.
+  if test x$with_system_libunwind = x; then
+    case ${target} in
+      ia64-*-hpux*) with_system_libunwind=yes ;;
+      *) with_system_libunwind=no ;;
+    esac
+  fi
+  # Based on system-libunwind and target, do we have ipinfo?
+  if  test x$with_system_libunwind = xyes; then
+    case ${target} in
+      ia64-*-*) have_unwind_getipinfo=no ;;
+      *) have_unwind_getipinfo=yes ;;
+    esac
+  else
+    # Darwin before version 9 does not have _Unwind_GetIPInfo.
+
+    case ${target} in
+      *-*-darwin[3-8]|*-*-darwin[3-8].*) have_unwind_getipinfo=no ;;
+      *) have_unwind_getipinfo=yes ;;
+    esac
+
+  fi
+
+  if test x$have_unwind_getipinfo = xyes; then
+
+$as_echo "#define HAVE_GETIPINFO 1" >>confdefs.h
+
+  fi
+
+else
+  ac_save_CFFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -Werror-implicit-function-declaration"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _Unwind_GetIPInfo" >&5
+$as_echo_n "checking for _Unwind_GetIPInfo... " >&6; }
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include "unwind.h"
+	struct _Unwind_Context *context;
+	int ip_before_insn = 0;
+int
+main ()
+{
+return _Unwind_GetIPInfo (context, &ip_before_insn);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  have_unwind_getipinfo=yes
+else
+  have_unwind_getipinfo=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+  CFLAGS="$ac_save_CFLAGS"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_unwind_getipinfo" >&5
+$as_echo "$have_unwind_getipinfo" >&6; }
+  if test "$have_unwind_getipinfo" = "yes"; then
+
+$as_echo "#define HAVE_GETIPINFO 1" >>confdefs.h
+
+  fi
+fi
+
+# Enable --enable-host-shared.
+# Check whether --enable-host-shared was given.
+if test "${enable_host_shared+set}" = set; then :
+  enableval=$enable_host_shared; PIC_FLAG=-fPIC
+else
+  PIC_FLAG=
+fi
+
+
+
+# Test for __sync support.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking __sync extensions" >&5
+$as_echo_n "checking __sync extensions... " >&6; }
+if test "${libbacktrace_cv_sys_sync+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "${with_target_subdir}"; then
+   case "${host}" in
+   hppa*-*-hpux*) libbacktrace_cv_sys_sync=no ;;
+   *) libbacktrace_cv_sys_sync=yes ;;
+   esac
+ else
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int i;
+int
+main ()
+{
+__sync_bool_compare_and_swap (&i, i, i);
+                       __sync_lock_test_and_set (&i, 1);
+                       __sync_lock_release (&i);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  libbacktrace_cv_sys_sync=yes
+else
+  libbacktrace_cv_sys_sync=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libbacktrace_cv_sys_sync" >&5
+$as_echo "$libbacktrace_cv_sys_sync" >&6; }
+BACKTRACE_SUPPORTS_THREADS=0
+if test "$libbacktrace_cv_sys_sync" = "yes"; then
+  BACKTRACE_SUPPORTS_THREADS=1
+
+$as_echo "#define HAVE_SYNC_FUNCTIONS 1" >>confdefs.h
+
+fi
+
+
+# Test for __atomic support.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking __atomic extensions" >&5
+$as_echo_n "checking __atomic extensions... " >&6; }
+if test "${libbacktrace_cv_sys_atomic+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "${with_target_subdir}"; then
+   libbacktrace_cv_sys_atomic=yes
+ else
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int i;
+int
+main ()
+{
+__atomic_load_n (&i, __ATOMIC_ACQUIRE);
+		       __atomic_store_n (&i, 1, __ATOMIC_RELEASE);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  libbacktrace_cv_sys_atomic=yes
+else
+  libbacktrace_cv_sys_atomic=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libbacktrace_cv_sys_atomic" >&5
+$as_echo "$libbacktrace_cv_sys_atomic" >&6; }
+if test "$libbacktrace_cv_sys_atomic" = "yes"; then
+
+$as_echo "#define HAVE_ATOMIC_FUNCTIONS 1" >>confdefs.h
+
+fi
+
+# The library needs to be able to read the executable itself.  Compile
+# a file to determine the executable format.  The awk script
+# filetype.awk prints out the file type.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking output filetype" >&5
+$as_echo_n "checking output filetype... " >&6; }
+if test "${libbacktrace_cv_sys_filetype+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  filetype=
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int i;
+int
+main ()
+{
+int j;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  filetype=`${AWK} -f $srcdir/filetype.awk conftest.$ac_objext`
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "compiler failed
+See \`config.log' for more details." "$LINENO" 5; }
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+libbacktrace_cv_sys_filetype=$filetype
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libbacktrace_cv_sys_filetype" >&5
+$as_echo "$libbacktrace_cv_sys_filetype" >&6; }
+
+# Match the file type to decide what files to compile.
+FORMAT_FILE=
+backtrace_supports_data=yes
+case "$libbacktrace_cv_sys_filetype" in
+elf*) FORMAT_FILE="elf.lo" ;;
+pecoff) FORMAT_FILE="pecoff.lo"
+        backtrace_supports_data=no
+	;;
+xcoff*) FORMAT_FILE="xcoff.lo"
+        backtrace_supports_data=no
+        ;;
+macho*) FORMAT_FILE="macho.lo"
+        backtrace_supports_data=no
+        ;;
+*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not determine output file type" >&5
+$as_echo "$as_me: WARNING: could not determine output file type" >&2;}
+   FORMAT_FILE="unknown.lo"
+   backtrace_supported=no
+   ;;
+esac
+
+
+# ELF defines.
+elfsize=
+case "$libbacktrace_cv_sys_filetype" in
+elf32) elfsize=32 ;;
+elf64) elfsize=64 ;;
+*)     elfsize=unused
+esac
+
+cat >>confdefs.h <<_ACEOF
+#define BACKTRACE_ELF_SIZE $elfsize
+_ACEOF
+
+
+# XCOFF defines.
+xcoffsize=
+case "$libbacktrace_cv_sys_filetype" in
+xcoff32) xcoffsize=32 ;;
+xcoff64) xcoffsize=64 ;;
+*)       xcoffsize=unused
+esac
+
+cat >>confdefs.h <<_ACEOF
+#define BACKTRACE_XCOFF_SIZE $xcoffsize
+_ACEOF
+
+
+BACKTRACE_SUPPORTED=0
+if test "$backtrace_supported" = "yes"; then
+  BACKTRACE_SUPPORTED=1
+fi
+
+
+BACKTRACE_SUPPORTS_DATA=0
+if test "$backtrace_supports_data" = "yes"; then
+  BACKTRACE_SUPPORTS_DATA=1
+fi
+
+
+for ac_header in sys/mman.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "sys/mman.h" "ac_cv_header_sys_mman_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_mman_h" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_MMAN_H 1
+_ACEOF
+
+fi
+
+done
+
+if test "$ac_cv_header_sys_mman_h" = "no"; then
+  have_mmap=no
+else
+  if test -n "${with_target_subdir}"; then
+    # When built as a GCC target library, we can't do a link test.  We
+    # simply assume that if we have mman.h, we have mmap.
+    have_mmap=yes
+    case "${host}" in
+    spu-*-*|*-*-msdosdjgpp)
+        # The SPU does not have mmap, but it has a sys/mman.h header file
+        # containing "mmap_eaddr" and the mmap flags, confusing the test.
+        # DJGPP also has sys/man.h, but no mmap
+	have_mmap=no ;;
+    esac
+  else
+    ac_fn_c_check_func "$LINENO" "mmap" "ac_cv_func_mmap"
+if test "x$ac_cv_func_mmap" = x""yes; then :
+  have_mmap=yes
+else
+  have_mmap=no
+fi
+
+  fi
+fi
+
+case "${host_os}" in
+darwin*)
+  have_mmap=no ;;
+esac
+
+if test "$have_mmap" = "no"; then
+  VIEW_FILE=read.lo
+  ALLOC_FILE=alloc.lo
+else
+  VIEW_FILE=mmapio.lo
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/mman.h>
+#if !defined(MAP_ANONYMOUS) && !defined(MAP_ANON)
+  #error no MAP_ANONYMOUS
+#endif
+
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  ALLOC_FILE=alloc.lo
+else
+  ALLOC_FILE=alloc.lo
+fi
+rm -f conftest.err conftest.$ac_ext
+fi
+
+
+
+BACKTRACE_USES_MALLOC=0
+if test "$ALLOC_FILE" = "alloc.lo"; then
+  BACKTRACE_USES_MALLOC=1
+fi
+
+
+# Check for dl_iterate_phdr.
+for ac_header in link.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "link.h" "ac_cv_header_link_h" "$ac_includes_default"
+if test "x$ac_cv_header_link_h" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LINK_H 1
+_ACEOF
+
+fi
+
+done
+
+if test "$ac_cv_header_link_h" = "no"; then
+  have_dl_iterate_phdr=no
+else
+  if test -n "${with_target_subdir}"; then
+    # When built as a GCC target library, we can't do a link test.
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <link.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "dl_iterate_phdr" >/dev/null 2>&1; then :
+  have_dl_iterate_phdr=yes
+else
+  have_dl_iterate_phdr=no
+fi
+rm -f conftest*
+
+    case "${host}" in
+    *-*-solaris2.10*)
+        # Avoid dl_iterate_phdr on Solaris 10, where it is in the
+    	# header file but is only in -ldl.
+	have_dl_iterate_phdr=no ;;
+    esac
+  else
+    ac_fn_c_check_func "$LINENO" "dl_iterate_phdr" "ac_cv_func_dl_iterate_phdr"
+if test "x$ac_cv_func_dl_iterate_phdr" = x""yes; then :
+  have_dl_iterate_phdr=yes
+else
+  have_dl_iterate_phdr=no
+fi
+
+  fi
+fi
+if test "$have_dl_iterate_phdr" = "yes"; then
+
+$as_echo "#define HAVE_DL_ITERATE_PHDR 1" >>confdefs.h
+
+fi
+
+# Check for loadquery.
+for ac_header in sys/ldr.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "sys/ldr.h" "ac_cv_header_sys_ldr_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_ldr_h" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_LDR_H 1
+_ACEOF
+
+fi
+
+done
+
+if test "$ac_cv_header_sys_ldr_h" = "no"; then
+  have_loadquery=no
+else
+  if test -n "${with_target_subdir}"; then
+    # When built as a GCC target library, we can't do a link test.
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/ldr.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "loadquery" >/dev/null 2>&1; then :
+  have_loadquery=yes
+else
+  have_loadquery=no
+fi
+rm -f conftest*
+
+  else
+    ac_fn_c_check_func "$LINENO" "loadquery" "ac_cv_func_loadquery"
+if test "x$ac_cv_func_loadquery" = x""yes; then :
+  have_loadquery=yes
+else
+  have_loadquery=no
+fi
+
+  fi
+fi
+if test "$have_loadquery" = "yes"; then
+
+$as_echo "#define HAVE_LOADQUERY 1" >>confdefs.h
+
+fi
+
+# Check for the fcntl function.
+if test -n "${with_target_subdir}"; then
+   case "${host}" in
+   *-*-mingw*) have_fcntl=no ;;
+   spu-*-*) have_fcntl=no ;;
+   *) have_fcntl=yes ;;
+   esac
+else
+  ac_fn_c_check_func "$LINENO" "fcntl" "ac_cv_func_fcntl"
+if test "x$ac_cv_func_fcntl" = x""yes; then :
+  have_fcntl=yes
+else
+  have_fcntl=no
+fi
+
+fi
+if test "$have_fcntl" = "yes"; then
+
+$as_echo "#define HAVE_FCNTL 1" >>confdefs.h
+
+fi
+
+ac_fn_c_check_decl "$LINENO" "strnlen" "ac_cv_have_decl_strnlen" "$ac_includes_default"
+if test "x$ac_cv_have_decl_strnlen" = x""yes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_STRNLEN $ac_have_decl
+_ACEOF
+
+for ac_func in lstat readlink
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+eval as_val=\$$as_ac_var
+   if test "x$as_val" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+# Check for getexecname function.
+if test -n "${with_target_subdir}"; then
+   case "${host}" in
+   *-*-solaris2*) have_getexecname=yes ;;
+   *) have_getexecname=no ;;
+   esac
+else
+  ac_fn_c_check_func "$LINENO" "getexecname" "ac_cv_func_getexecname"
+if test "x$ac_cv_func_getexecname" = x""yes; then :
+  have_getexecname=yes
+else
+  have_getexecname=no
+fi
+
+fi
+if test "$have_getexecname" = "yes"; then
+
+$as_echo "#define HAVE_GETEXECNAME 1" >>confdefs.h
+
+fi
+
+# Check for the clock_gettime function.
+for ac_func in clock_gettime
+do :
+  ac_fn_c_check_func "$LINENO" "clock_gettime" "ac_cv_func_clock_gettime"
+if test "x$ac_cv_func_clock_gettime" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_CLOCK_GETTIME 1
+_ACEOF
+
+fi
+done
+
+clock_gettime_link=
+# At least for glibc, clock_gettime is in librt.  But don't
+# pull that in if it still doesn't give us the function we want.  This
+# test is copied from libgomp, and modified to not link in -lrt as
+# we're using this for test timing only.
+if test "$ac_cv_func_clock_gettime" = no; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
+$as_echo_n "checking for clock_gettime in -lrt... " >&6; }
+if test "${ac_cv_lib_rt_clock_gettime+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lrt  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char clock_gettime ();
+int
+main ()
+{
+return clock_gettime ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_rt_clock_gettime=yes
+else
+  ac_cv_lib_rt_clock_gettime=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
+$as_echo "$ac_cv_lib_rt_clock_gettime" >&6; }
+if test "x$ac_cv_lib_rt_clock_gettime" = x""yes; then :
+  CLOCK_GETTIME_LINK=-lrt
+
+$as_echo "#define HAVE_CLOCK_GETTIME 1" >>confdefs.h
+
+fi
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -pthread is supported" >&5
+$as_echo_n "checking whether -pthread is supported... " >&6; }
+if test "${libgo_cv_lib_pthread+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  CFLAGS_hold=$CFLAGS
+CFLAGS="$CFLAGS -pthread"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int i;
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libgo_cv_lib_pthread=yes
+else
+  libgo_cv_lib_pthread=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+CFLAGS=$CFLAGS_hold
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_lib_pthread" >&5
+$as_echo "$libgo_cv_lib_pthread" >&6; }
+PTHREAD_CFLAGS=
+if test "$libgo_cv_lib_pthread" = yes; then
+  PTHREAD_CFLAGS=-pthread
+fi
+
+
+ if test "$libgo_cv_lib_pthread" = yes; then
+  HAVE_PTHREAD_TRUE=
+  HAVE_PTHREAD_FALSE='#'
+else
+  HAVE_PTHREAD_TRUE='#'
+  HAVE_PTHREAD_FALSE=
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for compress in -lz" >&5
+$as_echo_n "checking for compress in -lz... " >&6; }
+if test "${ac_cv_lib_z_compress+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lz  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char compress ();
+int
+main ()
+{
+return compress ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_z_compress=yes
+else
+  ac_cv_lib_z_compress=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_compress" >&5
+$as_echo "$ac_cv_lib_z_compress" >&6; }
+if test "x$ac_cv_lib_z_compress" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBZ 1
+_ACEOF
+
+  LIBS="-lz $LIBS"
+
+fi
+
+if test $ac_cv_lib_z_compress = "yes"; then
+
+$as_echo "#define HAVE_ZLIB 1" >>confdefs.h
+
+fi
+ if test "$ac_cv_lib_z_compress" = yes; then
+  HAVE_ZLIB_TRUE=
+  HAVE_ZLIB_FALSE='#'
+else
+  HAVE_ZLIB_TRUE='#'
+  HAVE_ZLIB_FALSE=
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether --compress-debug-sections is supported" >&5
+$as_echo_n "checking whether --compress-debug-sections is supported... " >&6; }
+if test "${libgo_cv_ld_compress+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  LDFLAGS_hold=$LDFLAGS
+LDFLAGS="$LDFLAGS -Wl,--compress-debug-sections=zlib-gnu"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  libgo_cv_ld_compress=yes
+else
+  libgo_cv_ld_compress=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LDFLAGS=$LDFLAGS_hold
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_ld_compress" >&5
+$as_echo "$libgo_cv_ld_compress" >&6; }
+ if test "$libgo_cv_ld_compress" = yes; then
+  HAVE_COMPRESSED_DEBUG_TRUE=
+  HAVE_COMPRESSED_DEBUG_FALSE='#'
+else
+  HAVE_COMPRESSED_DEBUG_TRUE='#'
+  HAVE_COMPRESSED_DEBUG_FALSE=
+fi
+
+
+
+# Extract the first word of "objcopy", so it can be a program name with args.
+set dummy objcopy; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_OBJCOPY+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$OBJCOPY"; then
+  ac_cv_prog_OBJCOPY="$OBJCOPY" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_OBJCOPY="objcopy"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+OBJCOPY=$ac_cv_prog_OBJCOPY
+if test -n "$OBJCOPY"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJCOPY" >&5
+$as_echo "$OBJCOPY" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether objcopy supports debuglink" >&5
+$as_echo_n "checking whether objcopy supports debuglink... " >&6; }
+if test "${libbacktrace_cv_objcopy_debuglink+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "${with_target_subdir}"; then
+  libbacktrace_cv_objcopy_debuglink=no
+elif ${OBJCOPY} --add-gnu-debuglink=x /bin/ls /tmp/ls$$; then
+  rm -f /tmp/ls$$
+  libbacktrace_cv_objcopy_debuglink=yes
+else
+  libbacktrace_cv_objcopy_debuglink=no
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libbacktrace_cv_objcopy_debuglink" >&5
+$as_echo "$libbacktrace_cv_objcopy_debuglink" >&6; }
+ if test "$libbacktrace_cv_objcopy_debuglink" = yes; then
+  HAVE_OBJCOPY_DEBUGLINK_TRUE=
+  HAVE_OBJCOPY_DEBUGLINK_FALSE='#'
+else
+  HAVE_OBJCOPY_DEBUGLINK_TRUE='#'
+  HAVE_OBJCOPY_DEBUGLINK_FALSE=
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether tests can run" >&5
+$as_echo_n "checking whether tests can run... " >&6; }
+if test "${libbacktrace_cv_sys_native+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "$cross_compiling" = yes; then :
+  libbacktrace_cv_sys_native=no
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  libbacktrace_cv_sys_native=yes
+else
+  libbacktrace_cv_sys_native=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libbacktrace_cv_sys_native" >&5
+$as_echo "$libbacktrace_cv_sys_native" >&6; }
+ if test "$libbacktrace_cv_sys_native" = "yes"; then
+  NATIVE_TRUE=
+  NATIVE_FALSE='#'
+else
+  NATIVE_TRUE='#'
+  NATIVE_FALSE=
+fi
+
+
+if test "${multilib}" = "yes"; then
+  multilib_arg="--enable-multilib"
+else
+  multilib_arg=
+fi
+
+ac_config_files="$ac_config_files Makefile backtrace-supported.h"
+
+
+# We need multilib support, but only if configuring for the target.
+ac_config_commands="$ac_config_commands default"
+
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes: double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \.
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    test "x$cache_file" != "x/dev/null" &&
+      { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+    cat confcache >$cache_file
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+ if test -n "$EXEEXT"; then
+  am__EXEEXT_TRUE=
+  am__EXEEXT_FALSE='#'
+else
+  am__EXEEXT_TRUE='#'
+  am__EXEEXT_FALSE=
+fi
+
+if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
+  as_fn_error "conditional \"MAINTAINER_MODE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${HAVE_PTHREAD_TRUE}" && test -z "${HAVE_PTHREAD_FALSE}"; then
+  as_fn_error "conditional \"HAVE_PTHREAD\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${HAVE_ZLIB_TRUE}" && test -z "${HAVE_ZLIB_FALSE}"; then
+  as_fn_error "conditional \"HAVE_ZLIB\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${HAVE_COMPRESSED_DEBUG_TRUE}" && test -z "${HAVE_COMPRESSED_DEBUG_FALSE}"; then
+  as_fn_error "conditional \"HAVE_COMPRESSED_DEBUG\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${HAVE_OBJCOPY_DEBUGLINK_TRUE}" && test -z "${HAVE_OBJCOPY_DEBUGLINK_FALSE}"; then
+  as_fn_error "conditional \"HAVE_OBJCOPY_DEBUGLINK\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${NATIVE_TRUE}" && test -z "${NATIVE_FALSE}"; then
+  as_fn_error "conditional \"NATIVE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+
+: ${CONFIG_STATUS=./config.status}
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error ERROR [LINENO LOG_FD]
+# ---------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with status $?, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$?; test $as_status -eq 0 && as_status=1
+  if test "$3"; then
+    as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3
+  fi
+  $as_echo "$as_me: error: $1" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -p'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -p'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -p'
+  fi
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+	test -d "$1/.";
+      else
+	case $1 in #(
+	-*)set "./$1";;
+	esac;
+	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+	???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by package-unused $as_me version-unused, which was
+generated by GNU Autoconf 2.64.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration.  Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+      --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+      --header=FILE[:TEMPLATE]
+                   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_version="\\
+package-unused config.status version-unused
+configured by $0, generated by GNU Autoconf 2.64,
+  with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2009 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+MKDIR_P='$MKDIR_P'
+AWK='$AWK'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    $as_echo "$ac_cs_version"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    as_fn_append CONFIG_FILES " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h)
+    # Conflict between --help and --header
+    as_fn_error "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+  --help | --hel | -h )
+    $as_echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) as_fn_error "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+  *) as_fn_append ac_config_targets " $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+  set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  shift
+  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+  CONFIG_SHELL='$SHELL'
+  export CONFIG_SHELL
+  exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+#
+# INIT-COMMANDS
+#
+
+srcdir="$srcdir"
+host="$host"
+target="$target"
+with_multisubdir="$with_multisubdir"
+with_multisrctop="$with_multisrctop"
+with_target_subdir="$with_target_subdir"
+ac_configure_args="${multilib_arg} ${ac_configure_args}"
+multi_basedir="$multi_basedir"
+CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+CC="$CC"
+
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+sed_quote_subst='$sed_quote_subst'
+double_quote_subst='$double_quote_subst'
+delay_variable_subst='$delay_variable_subst'
+macro_version='`$ECHO "X$macro_version" | $Xsed -e "$delay_single_quote_subst"`'
+macro_revision='`$ECHO "X$macro_revision" | $Xsed -e "$delay_single_quote_subst"`'
+enable_shared='`$ECHO "X$enable_shared" | $Xsed -e "$delay_single_quote_subst"`'
+enable_static='`$ECHO "X$enable_static" | $Xsed -e "$delay_single_quote_subst"`'
+pic_mode='`$ECHO "X$pic_mode" | $Xsed -e "$delay_single_quote_subst"`'
+enable_fast_install='`$ECHO "X$enable_fast_install" | $Xsed -e "$delay_single_quote_subst"`'
+host_alias='`$ECHO "X$host_alias" | $Xsed -e "$delay_single_quote_subst"`'
+host='`$ECHO "X$host" | $Xsed -e "$delay_single_quote_subst"`'
+host_os='`$ECHO "X$host_os" | $Xsed -e "$delay_single_quote_subst"`'
+build_alias='`$ECHO "X$build_alias" | $Xsed -e "$delay_single_quote_subst"`'
+build='`$ECHO "X$build" | $Xsed -e "$delay_single_quote_subst"`'
+build_os='`$ECHO "X$build_os" | $Xsed -e "$delay_single_quote_subst"`'
+SED='`$ECHO "X$SED" | $Xsed -e "$delay_single_quote_subst"`'
+Xsed='`$ECHO "X$Xsed" | $Xsed -e "$delay_single_quote_subst"`'
+GREP='`$ECHO "X$GREP" | $Xsed -e "$delay_single_quote_subst"`'
+EGREP='`$ECHO "X$EGREP" | $Xsed -e "$delay_single_quote_subst"`'
+FGREP='`$ECHO "X$FGREP" | $Xsed -e "$delay_single_quote_subst"`'
+LD='`$ECHO "X$LD" | $Xsed -e "$delay_single_quote_subst"`'
+NM='`$ECHO "X$NM" | $Xsed -e "$delay_single_quote_subst"`'
+LN_S='`$ECHO "X$LN_S" | $Xsed -e "$delay_single_quote_subst"`'
+max_cmd_len='`$ECHO "X$max_cmd_len" | $Xsed -e "$delay_single_quote_subst"`'
+ac_objext='`$ECHO "X$ac_objext" | $Xsed -e "$delay_single_quote_subst"`'
+exeext='`$ECHO "X$exeext" | $Xsed -e "$delay_single_quote_subst"`'
+lt_unset='`$ECHO "X$lt_unset" | $Xsed -e "$delay_single_quote_subst"`'
+lt_SP2NL='`$ECHO "X$lt_SP2NL" | $Xsed -e "$delay_single_quote_subst"`'
+lt_NL2SP='`$ECHO "X$lt_NL2SP" | $Xsed -e "$delay_single_quote_subst"`'
+reload_flag='`$ECHO "X$reload_flag" | $Xsed -e "$delay_single_quote_subst"`'
+reload_cmds='`$ECHO "X$reload_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+deplibs_check_method='`$ECHO "X$deplibs_check_method" | $Xsed -e "$delay_single_quote_subst"`'
+file_magic_cmd='`$ECHO "X$file_magic_cmd" | $Xsed -e "$delay_single_quote_subst"`'
+AR='`$ECHO "X$AR" | $Xsed -e "$delay_single_quote_subst"`'
+AR_FLAGS='`$ECHO "X$AR_FLAGS" | $Xsed -e "$delay_single_quote_subst"`'
+STRIP='`$ECHO "X$STRIP" | $Xsed -e "$delay_single_quote_subst"`'
+RANLIB='`$ECHO "X$RANLIB" | $Xsed -e "$delay_single_quote_subst"`'
+old_postinstall_cmds='`$ECHO "X$old_postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+old_postuninstall_cmds='`$ECHO "X$old_postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+old_archive_cmds='`$ECHO "X$old_archive_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+CC='`$ECHO "X$CC" | $Xsed -e "$delay_single_quote_subst"`'
+CFLAGS='`$ECHO "X$CFLAGS" | $Xsed -e "$delay_single_quote_subst"`'
+compiler='`$ECHO "X$compiler" | $Xsed -e "$delay_single_quote_subst"`'
+GCC='`$ECHO "X$GCC" | $Xsed -e "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_pipe='`$ECHO "X$lt_cv_sys_global_symbol_pipe" | $Xsed -e "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_cdecl='`$ECHO "X$lt_cv_sys_global_symbol_to_cdecl" | $Xsed -e "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address" | $Xsed -e "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`'
+objdir='`$ECHO "X$objdir" | $Xsed -e "$delay_single_quote_subst"`'
+SHELL='`$ECHO "X$SHELL" | $Xsed -e "$delay_single_quote_subst"`'
+ECHO='`$ECHO "X$ECHO" | $Xsed -e "$delay_single_quote_subst"`'
+MAGIC_CMD='`$ECHO "X$MAGIC_CMD" | $Xsed -e "$delay_single_quote_subst"`'
+lt_prog_compiler_no_builtin_flag='`$ECHO "X$lt_prog_compiler_no_builtin_flag" | $Xsed -e "$delay_single_quote_subst"`'
+lt_prog_compiler_wl='`$ECHO "X$lt_prog_compiler_wl" | $Xsed -e "$delay_single_quote_subst"`'
+lt_prog_compiler_pic='`$ECHO "X$lt_prog_compiler_pic" | $Xsed -e "$delay_single_quote_subst"`'
+lt_prog_compiler_static='`$ECHO "X$lt_prog_compiler_static" | $Xsed -e "$delay_single_quote_subst"`'
+lt_cv_prog_compiler_c_o='`$ECHO "X$lt_cv_prog_compiler_c_o" | $Xsed -e "$delay_single_quote_subst"`'
+need_locks='`$ECHO "X$need_locks" | $Xsed -e "$delay_single_quote_subst"`'
+DSYMUTIL='`$ECHO "X$DSYMUTIL" | $Xsed -e "$delay_single_quote_subst"`'
+NMEDIT='`$ECHO "X$NMEDIT" | $Xsed -e "$delay_single_quote_subst"`'
+LIPO='`$ECHO "X$LIPO" | $Xsed -e "$delay_single_quote_subst"`'
+OTOOL='`$ECHO "X$OTOOL" | $Xsed -e "$delay_single_quote_subst"`'
+OTOOL64='`$ECHO "X$OTOOL64" | $Xsed -e "$delay_single_quote_subst"`'
+libext='`$ECHO "X$libext" | $Xsed -e "$delay_single_quote_subst"`'
+shrext_cmds='`$ECHO "X$shrext_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+extract_expsyms_cmds='`$ECHO "X$extract_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+archive_cmds_need_lc='`$ECHO "X$archive_cmds_need_lc" | $Xsed -e "$delay_single_quote_subst"`'
+enable_shared_with_static_runtimes='`$ECHO "X$enable_shared_with_static_runtimes" | $Xsed -e "$delay_single_quote_subst"`'
+export_dynamic_flag_spec='`$ECHO "X$export_dynamic_flag_spec" | $Xsed -e "$delay_single_quote_subst"`'
+whole_archive_flag_spec='`$ECHO "X$whole_archive_flag_spec" | $Xsed -e "$delay_single_quote_subst"`'
+compiler_needs_object='`$ECHO "X$compiler_needs_object" | $Xsed -e "$delay_single_quote_subst"`'
+old_archive_from_new_cmds='`$ECHO "X$old_archive_from_new_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+old_archive_from_expsyms_cmds='`$ECHO "X$old_archive_from_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+archive_cmds='`$ECHO "X$archive_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+archive_expsym_cmds='`$ECHO "X$archive_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+module_cmds='`$ECHO "X$module_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+module_expsym_cmds='`$ECHO "X$module_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+with_gnu_ld='`$ECHO "X$with_gnu_ld" | $Xsed -e "$delay_single_quote_subst"`'
+allow_undefined_flag='`$ECHO "X$allow_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`'
+no_undefined_flag='`$ECHO "X$no_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec='`$ECHO "X$hardcode_libdir_flag_spec" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec_ld='`$ECHO "X$hardcode_libdir_flag_spec_ld" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_libdir_separator='`$ECHO "X$hardcode_libdir_separator" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_direct='`$ECHO "X$hardcode_direct" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_direct_absolute='`$ECHO "X$hardcode_direct_absolute" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_minus_L='`$ECHO "X$hardcode_minus_L" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_shlibpath_var='`$ECHO "X$hardcode_shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_automatic='`$ECHO "X$hardcode_automatic" | $Xsed -e "$delay_single_quote_subst"`'
+inherit_rpath='`$ECHO "X$inherit_rpath" | $Xsed -e "$delay_single_quote_subst"`'
+link_all_deplibs='`$ECHO "X$link_all_deplibs" | $Xsed -e "$delay_single_quote_subst"`'
+fix_srcfile_path='`$ECHO "X$fix_srcfile_path" | $Xsed -e "$delay_single_quote_subst"`'
+always_export_symbols='`$ECHO "X$always_export_symbols" | $Xsed -e "$delay_single_quote_subst"`'
+export_symbols_cmds='`$ECHO "X$export_symbols_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+exclude_expsyms='`$ECHO "X$exclude_expsyms" | $Xsed -e "$delay_single_quote_subst"`'
+include_expsyms='`$ECHO "X$include_expsyms" | $Xsed -e "$delay_single_quote_subst"`'
+prelink_cmds='`$ECHO "X$prelink_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+file_list_spec='`$ECHO "X$file_list_spec" | $Xsed -e "$delay_single_quote_subst"`'
+variables_saved_for_relink='`$ECHO "X$variables_saved_for_relink" | $Xsed -e "$delay_single_quote_subst"`'
+need_lib_prefix='`$ECHO "X$need_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`'
+need_version='`$ECHO "X$need_version" | $Xsed -e "$delay_single_quote_subst"`'
+version_type='`$ECHO "X$version_type" | $Xsed -e "$delay_single_quote_subst"`'
+runpath_var='`$ECHO "X$runpath_var" | $Xsed -e "$delay_single_quote_subst"`'
+shlibpath_var='`$ECHO "X$shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`'
+shlibpath_overrides_runpath='`$ECHO "X$shlibpath_overrides_runpath" | $Xsed -e "$delay_single_quote_subst"`'
+libname_spec='`$ECHO "X$libname_spec" | $Xsed -e "$delay_single_quote_subst"`'
+library_names_spec='`$ECHO "X$library_names_spec" | $Xsed -e "$delay_single_quote_subst"`'
+soname_spec='`$ECHO "X$soname_spec" | $Xsed -e "$delay_single_quote_subst"`'
+postinstall_cmds='`$ECHO "X$postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+postuninstall_cmds='`$ECHO "X$postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+finish_cmds='`$ECHO "X$finish_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+finish_eval='`$ECHO "X$finish_eval" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_into_libs='`$ECHO "X$hardcode_into_libs" | $Xsed -e "$delay_single_quote_subst"`'
+sys_lib_search_path_spec='`$ECHO "X$sys_lib_search_path_spec" | $Xsed -e "$delay_single_quote_subst"`'
+sys_lib_dlsearch_path_spec='`$ECHO "X$sys_lib_dlsearch_path_spec" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_action='`$ECHO "X$hardcode_action" | $Xsed -e "$delay_single_quote_subst"`'
+enable_dlopen='`$ECHO "X$enable_dlopen" | $Xsed -e "$delay_single_quote_subst"`'
+enable_dlopen_self='`$ECHO "X$enable_dlopen_self" | $Xsed -e "$delay_single_quote_subst"`'
+enable_dlopen_self_static='`$ECHO "X$enable_dlopen_self_static" | $Xsed -e "$delay_single_quote_subst"`'
+old_striplib='`$ECHO "X$old_striplib" | $Xsed -e "$delay_single_quote_subst"`'
+striplib='`$ECHO "X$striplib" | $Xsed -e "$delay_single_quote_subst"`'
+
+LTCC='$LTCC'
+LTCFLAGS='$LTCFLAGS'
+compiler='$compiler_DEFAULT'
+
+# Quote evaled strings.
+for var in SED \
+GREP \
+EGREP \
+FGREP \
+LD \
+NM \
+LN_S \
+lt_SP2NL \
+lt_NL2SP \
+reload_flag \
+deplibs_check_method \
+file_magic_cmd \
+AR \
+AR_FLAGS \
+STRIP \
+RANLIB \
+CC \
+CFLAGS \
+compiler \
+lt_cv_sys_global_symbol_pipe \
+lt_cv_sys_global_symbol_to_cdecl \
+lt_cv_sys_global_symbol_to_c_name_address \
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \
+SHELL \
+ECHO \
+lt_prog_compiler_no_builtin_flag \
+lt_prog_compiler_wl \
+lt_prog_compiler_pic \
+lt_prog_compiler_static \
+lt_cv_prog_compiler_c_o \
+need_locks \
+DSYMUTIL \
+NMEDIT \
+LIPO \
+OTOOL \
+OTOOL64 \
+shrext_cmds \
+export_dynamic_flag_spec \
+whole_archive_flag_spec \
+compiler_needs_object \
+with_gnu_ld \
+allow_undefined_flag \
+no_undefined_flag \
+hardcode_libdir_flag_spec \
+hardcode_libdir_flag_spec_ld \
+hardcode_libdir_separator \
+fix_srcfile_path \
+exclude_expsyms \
+include_expsyms \
+file_list_spec \
+variables_saved_for_relink \
+libname_spec \
+library_names_spec \
+soname_spec \
+finish_eval \
+old_striplib \
+striplib; do
+    case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in
+    *[\\\\\\\`\\"\\\$]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+# Double-quote double-evaled strings.
+for var in reload_cmds \
+old_postinstall_cmds \
+old_postuninstall_cmds \
+old_archive_cmds \
+extract_expsyms_cmds \
+old_archive_from_new_cmds \
+old_archive_from_expsyms_cmds \
+archive_cmds \
+archive_expsym_cmds \
+module_cmds \
+module_expsym_cmds \
+export_symbols_cmds \
+prelink_cmds \
+postinstall_cmds \
+postuninstall_cmds \
+finish_cmds \
+sys_lib_search_path_spec \
+sys_lib_dlsearch_path_spec; do
+    case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in
+    *[\\\\\\\`\\"\\\$]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+# Fix-up fallback echo if it was mangled by the above quoting rules.
+case \$lt_ECHO in
+*'\\\$0 --fallback-echo"')  lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\$0 --fallback-echo"\$/\$0 --fallback-echo"/'\`
+  ;;
+esac
+
+ac_aux_dir='$ac_aux_dir'
+xsi_shell='$xsi_shell'
+lt_shell_append='$lt_shell_append'
+
+# See if we are running on zsh, and set the options which allow our
+# commands through without removal of \ escapes INIT.
+if test -n "\${ZSH_VERSION+set}" ; then
+   setopt NO_GLOB_SUBST
+fi
+
+
+    PACKAGE='$PACKAGE'
+    VERSION='$VERSION'
+    TIMESTAMP='$TIMESTAMP'
+    RM='$RM'
+    ofile='$ofile'
+
+
+
+
+# Variables needed in config.status (file generation) which aren't already
+# passed by autoconf.
+SUBDIRS="$SUBDIRS"
+
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+    "default-1") CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;;
+    "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
+    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+    "backtrace-supported.h") CONFIG_FILES="$CONFIG_FILES backtrace-supported.h" ;;
+    "default") CONFIG_COMMANDS="$CONFIG_COMMANDS default" ;;
+
+  *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp=
+  trap 'exit_status=$?
+  { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+  trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+  eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+  echo "cat >conf$$subs.awk <<_ACEOF" &&
+  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+  echo "_ACEOF"
+} >conf$$subs.sh ||
+  as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  . ./conf$$subs.sh ||
+    as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5
+
+  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+  if test $ac_delim_n = $ac_delim_num; then
+    break
+  elif $ac_last_try; then
+    as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\).*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\).*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+  N
+  s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = ""
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \
+  || as_fn_error "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[	 ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[	 ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+  ac_t=`sed -n "/$ac_delim/p" confdefs.h`
+  if test -z "$ac_t"; then
+    break
+  elif $ac_last_try; then
+    as_fn_error "could not make $CONFIG_HEADERS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any.  Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[	 ]*#[	 ]*define[	 ][	 ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  for (key in D) D_is_set[key] = 1
+  FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+  line = \$ 0
+  split(line, arg, " ")
+  if (arg[1] == "#") {
+    defundef = arg[2]
+    mac1 = arg[3]
+  } else {
+    defundef = substr(arg[1], 2)
+    mac1 = arg[2]
+  }
+  split(mac1, mac2, "(") #)
+  macro = mac2[1]
+  prefix = substr(line, 1, index(line, defundef) - 1)
+  if (D_is_set[macro]) {
+    # Preserve the white space surrounding the "#".
+    print prefix "define", macro P[macro] D[macro]
+    next
+  } else {
+    # Replace #undef with comments.  This is necessary, for example,
+    # in the case of _POSIX_SOURCE, which is predefined and required
+    # on some systems where configure will not decide to define it.
+    if (defundef == "undef") {
+      print "/*", prefix defundef, macro, "*/"
+      next
+    }
+  }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+  as_fn_error "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X "  :F $CONFIG_FILES  :H $CONFIG_HEADERS    :C $CONFIG_COMMANDS"
+shift
+for ac_tag
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
+	 # because $ac_f cannot contain `:'.
+	 test -f "$ac_f" ||
+	   case $ac_f in
+	   [\\/$]*) false;;
+	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+	   esac ||
+	   as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+      esac
+      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      as_fn_append ac_file_inputs " '$ac_f'"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input='Generated from '`
+	  $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+	`' by configure.'
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+    fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`$as_echo "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$tmp/stdin" \
+      || as_fn_error "could not create $ac_file" "$LINENO" 5 ;;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  as_dir="$ac_dir"; as_fn_mkdir_p
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+  esac
+  ac_MKDIR_P=$MKDIR_P
+  case $MKDIR_P in
+  [\\/$]* | ?:[\\/]* ) ;;
+  */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+  esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+  s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \
+  || as_fn_error "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&2;}
+
+  rm -f "$tmp/stdin"
+  case $ac_file in
+  -) cat "$tmp/out" && rm -f "$tmp/out";;
+  *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";;
+  esac \
+  || as_fn_error "could not create $ac_file" "$LINENO" 5
+ ;;
+  :H)
+  #
+  # CONFIG_HEADER
+  #
+  if test x"$ac_file" != x-; then
+    {
+      $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs"
+    } >"$tmp/config.h" \
+      || as_fn_error "could not create $ac_file" "$LINENO" 5
+    if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      rm -f "$ac_file"
+      mv "$tmp/config.h" "$ac_file" \
+	|| as_fn_error "could not create $ac_file" "$LINENO" 5
+    fi
+  else
+    $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \
+      || as_fn_error "could not create -" "$LINENO" 5
+  fi
+# Compute "$ac_file"'s index in $config_headers.
+_am_arg="$ac_file"
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $_am_arg | $_am_arg:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" ||
+$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$_am_arg" : 'X\(//\)[^/]' \| \
+	 X"$_am_arg" : 'X\(//\)$' \| \
+	 X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$_am_arg" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`/stamp-h$_am_stamp_count
+ ;;
+
+  :C)  { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
+$as_echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+  esac
+
+
+  case $ac_file$ac_mode in
+    "default-1":C)
+# Only add multilib support code if we just rebuilt the top-level
+# Makefile.
+case " $CONFIG_FILES " in
+ *" Makefile "*)
+   ac_file=Makefile . ${multi_basedir}/config-ml.in
+   ;;
+esac ;;
+    "libtool":C)
+
+    # See if we are running on zsh, and set the options which allow our
+    # commands through without removal of \ escapes.
+    if test -n "${ZSH_VERSION+set}" ; then
+      setopt NO_GLOB_SUBST
+    fi
+
+    cfgfile="${ofile}T"
+    trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+    $RM "$cfgfile"
+
+    cat <<_LT_EOF >> "$cfgfile"
+#! $SHELL
+
+# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+#   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+#                 2006, 2007, 2008 Free Software Foundation, Inc.
+#   Written by Gordon Matzigkeit, 1996
+#
+#   This file is part of GNU Libtool.
+#
+# GNU Libtool is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Libtool; see the file COPYING.  If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html, or
+# obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+# The names of the tagged configurations supported by this script.
+available_tags=""
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Which release of libtool.m4 was used?
+macro_version=$macro_version
+macro_revision=$macro_revision
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# What type of objects to build.
+pic_mode=$pic_mode
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="\$SED -e 1s/^X//"
+
+# A grep program that handles long lines.
+GREP=$lt_GREP
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# A literal string matcher.
+FGREP=$lt_FGREP
+
+# A BSD- or MS-compatible name lister.
+NM=$lt_NM
+
+# Whether we need soft or hard links.
+LN_S=$lt_LN_S
+
+# What is the maximum length of a command?
+max_cmd_len=$max_cmd_len
+
+# Object file suffix (normally "o").
+objext=$ac_objext
+
+# Executable file suffix (normally "").
+exeext=$exeext
+
+# whether the shell understands "unset".
+lt_unset=$lt_unset
+
+# turn spaces into newlines.
+SP2NL=$lt_lt_SP2NL
+
+# turn newlines into spaces.
+NL2SP=$lt_lt_NL2SP
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == "file_magic".
+file_magic_cmd=$lt_file_magic_cmd
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A symbol stripping program.
+STRIP=$lt_STRIP
+
+# Commands used to install an old-style archive.
+RANLIB=$lt_RANLIB
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# A C compiler.
+LTCC=$lt_CC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_CFLAGS
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration.
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair.
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# Transform the output of nm in a C name address pair when lib prefix is needed.
+global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# An echo program that does not interpret backslashes.
+ECHO=$lt_ECHO
+
+# Used to examine libraries when file_magic_cmd begins with "file".
+MAGIC_CMD=$MAGIC_CMD
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Tool to manipulate archived DWARF debug symbol files on Mac OS X.
+DSYMUTIL=$lt_DSYMUTIL
+
+# Tool to change global to local symbols on Mac OS X.
+NMEDIT=$lt_NMEDIT
+
+# Tool to manipulate fat objects and archives on Mac OS X.
+LIPO=$lt_LIPO
+
+# ldd/readelf like tool for Mach-O binaries on Mac OS X.
+OTOOL=$lt_OTOOL
+
+# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4.
+OTOOL64=$lt_OTOOL64
+
+# Old archive suffix (normally "a").
+libext=$libext
+
+# Shared library suffix (normally ".so").
+shrext_cmds=$lt_shrext_cmds
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at link time.
+variables_saved_for_relink=$lt_variables_saved_for_relink
+
+# Do we need the "lib" prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Library versioning type.
+version_type=$version_type
+
+# Shared library runtime path variable.
+runpath_var=$runpath_var
+
+# Shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names.  First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Command to use after installation of a shared archive.
+postinstall_cmds=$lt_postinstall_cmds
+
+# Command to use after uninstallation of a shared archive.
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# As "finish_cmds", except a single script fragment to be evaled but
+# not shown.
+finish_eval=$lt_finish_eval
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Compile-time system search path for libraries.
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries.
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+
+# The linker used to build libraries.
+LD=$lt_LD
+
+# Commands used to build an old-style archive.
+old_archive_cmds=$lt_old_archive_cmds
+
+# A language specific compiler.
+CC=$lt_compiler
+
+# Is the compiler the GNU compiler?
+with_gcc=$GCC
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc
+
+# Whether or not to disallow shared libs when runtime libs are static.
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec
+
+# Whether the compiler copes with passing no objects directly.
+compiler_needs_object=$lt_compiler_needs_object
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
+
+# Commands used to build a shared archive.
+archive_cmds=$lt_archive_cmds
+archive_expsym_cmds=$lt_archive_expsym_cmds
+
+# Commands used to build a loadable module if different from building
+# a shared archive.
+module_cmds=$lt_module_cmds
+module_expsym_cmds=$lt_module_expsym_cmds
+
+# Whether we are building with GNU ld or not.
+with_gnu_ld=$lt_with_gnu_ld
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag
+
+# Flag that enforces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
+
+# If ld is used when linking, flag to hardcode \$libdir into a binary
+# during linking.  This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld
+
+# Whether we need a single "-rpath" flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary and the resulting library dependency is
+# "absolute",i.e impossible to change by setting \${shlibpath_var} if the
+# library is relocated.
+hardcode_direct_absolute=$hardcode_direct_absolute
+
+# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+# into the resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+# into the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Set to "yes" if building a shared library automatically hardcodes DIR
+# into the library and all subsequent libraries and executables linked
+# against it.
+hardcode_automatic=$hardcode_automatic
+
+# Set to yes if linker adds runtime paths of dependent libraries
+# to runtime path list.
+inherit_rpath=$inherit_rpath
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path=$lt_fix_srcfile_path
+
+# Set to "yes" if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms
+
+# Commands necessary for linking programs (against libraries) with templates.
+prelink_cmds=$lt_prelink_cmds
+
+# Specify filename containing input files.
+file_list_spec=$lt_file_list_spec
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+  case $host_os in
+  aix3*)
+    cat <<\_LT_EOF >> "$cfgfile"
+# AIX sometimes has problems with the GCC collect2 program.  For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+  COLLECT_NAMES=
+  export COLLECT_NAMES
+fi
+_LT_EOF
+    ;;
+  esac
+
+
+ltmain="$ac_aux_dir/ltmain.sh"
+
+
+  # We use sed instead of cat because bash on DJGPP gets confused if
+  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
+  # text mode, it properly converts lines to CR/LF.  This bash problem
+  # is reportedly fixed, but why not run on old versions too?
+  sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \
+    || (rm -f "$cfgfile"; exit 1)
+
+  case $xsi_shell in
+  yes)
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE.  If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+  case ${1} in
+    */*) func_dirname_result="${1%/*}${2}" ;;
+    *  ) func_dirname_result="${3}" ;;
+  esac
+}
+
+# func_basename file
+func_basename ()
+{
+  func_basename_result="${1##*/}"
+}
+
+# func_dirname_and_basename file append nondir_replacement
+# perform func_basename and func_dirname in a single function
+# call:
+#   dirname:  Compute the dirname of FILE.  If nonempty,
+#             add APPEND to the result, otherwise set result
+#             to NONDIR_REPLACEMENT.
+#             value returned in "$func_dirname_result"
+#   basename: Compute filename of FILE.
+#             value retuned in "$func_basename_result"
+# Implementation must be kept synchronized with func_dirname
+# and func_basename. For efficiency, we do not delegate to
+# those functions but instead duplicate the functionality here.
+func_dirname_and_basename ()
+{
+  case ${1} in
+    */*) func_dirname_result="${1%/*}${2}" ;;
+    *  ) func_dirname_result="${3}" ;;
+  esac
+  func_basename_result="${1##*/}"
+}
+
+# func_stripname prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+func_stripname ()
+{
+  # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
+  # positional parameters, so assign one to ordinary parameter first.
+  func_stripname_result=${3}
+  func_stripname_result=${func_stripname_result#"${1}"}
+  func_stripname_result=${func_stripname_result%"${2}"}
+}
+
+# func_opt_split
+func_opt_split ()
+{
+  func_opt_split_opt=${1%%=*}
+  func_opt_split_arg=${1#*=}
+}
+
+# func_lo2o object
+func_lo2o ()
+{
+  case ${1} in
+    *.lo) func_lo2o_result=${1%.lo}.${objext} ;;
+    *)    func_lo2o_result=${1} ;;
+  esac
+}
+
+# func_xform libobj-or-source
+func_xform ()
+{
+  func_xform_result=${1%.*}.lo
+}
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+  func_arith_result=$(( $* ))
+}
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+  func_len_result=${#1}
+}
+
+_LT_EOF
+    ;;
+  *) # Bourne compatible functions.
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE.  If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+  # Extract subdirectory from the argument.
+  func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"`
+  if test "X$func_dirname_result" = "X${1}"; then
+    func_dirname_result="${3}"
+  else
+    func_dirname_result="$func_dirname_result${2}"
+  fi
+}
+
+# func_basename file
+func_basename ()
+{
+  func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"`
+}
+
+
+# func_stripname prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+# func_strip_suffix prefix name
+func_stripname ()
+{
+  case ${2} in
+    .*) func_stripname_result=`$ECHO "X${3}" \
+           | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;;
+    *)  func_stripname_result=`$ECHO "X${3}" \
+           | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;;
+  esac
+}
+
+# sed scripts:
+my_sed_long_opt='1s/^\(-[^=]*\)=.*/\1/;q'
+my_sed_long_arg='1s/^-[^=]*=//'
+
+# func_opt_split
+func_opt_split ()
+{
+  func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"`
+  func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"`
+}
+
+# func_lo2o object
+func_lo2o ()
+{
+  func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"`
+}
+
+# func_xform libobj-or-source
+func_xform ()
+{
+  func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[^.]*$/.lo/'`
+}
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+  func_arith_result=`expr "$@"`
+}
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+  func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len`
+}
+
+_LT_EOF
+esac
+
+case $lt_shell_append in
+  yes)
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+  eval "$1+=\$2"
+}
+_LT_EOF
+    ;;
+  *)
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+  eval "$1=\$$1\$2"
+}
+
+_LT_EOF
+    ;;
+  esac
+
+
+  sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \
+    || (rm -f "$cfgfile"; exit 1)
+
+  mv -f "$cfgfile" "$ofile" ||
+    (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+  chmod +x "$ofile"
+
+ ;;
+    "default":C) if test -n "$CONFIG_FILES"; then
+   if test -n "${with_target_subdir}"; then
+     # Multilibs need MULTISUBDIR defined correctly in certain makefiles so
+     # that multilib installs will end up installed in the correct place.
+     # The testsuite needs it for multilib-aware ABI baseline files.
+     # To work around this not being passed down from config-ml.in ->
+     # srcdir/Makefile.am -> srcdir/{src,libsupc++,...}/Makefile.am, manually
+     # append it here.  Only modify Makefiles that have just been created.
+     #
+     # Also, get rid of this simulated-VPATH thing that automake does.
+     cat > vpsed << \_EOF
+  s!`test -f '$<' || echo '$(srcdir)/'`!!
+_EOF
+     for i in $SUBDIRS; do
+      case $CONFIG_FILES in
+       *${i}/Makefile*)
+	 #echo "Adding MULTISUBDIR to $i/Makefile"
+	 sed -f vpsed $i/Makefile > tmp
+	 grep '^MULTISUBDIR =' Makefile >> tmp
+	 mv tmp $i/Makefile
+	 ;;
+      esac
+     done
+     rm vpsed
+   fi
+ fi
+ ;;
+
+  esac
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+  as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || as_fn_exit $?
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/configure.ac b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/configure.ac
new file mode 100644
index 0000000..b9056cc
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/configure.ac
@@ -0,0 +1,512 @@
+# configure.ac -- Backtrace configure script.
+# Copyright (C) 2012-2018 Free Software Foundation, Inc.
+
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+
+#     (1) Redistributions of source code must retain the above copyright
+#     notice, this list of conditions and the following disclaimer.
+
+#     (2) Redistributions in binary form must reproduce the above copyright
+#     notice, this list of conditions and the following disclaimer in
+#     the documentation and/or other materials provided with the
+#     distribution.
+
+#     (3) The name of the author may not be used to
+#     endorse or promote products derived from this software without
+#     specific prior written permission.
+
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+AC_PREREQ(2.64)
+AC_INIT(package-unused, version-unused,, libbacktrace)
+AC_CONFIG_SRCDIR(backtrace.h)
+AC_CONFIG_HEADER(config.h)
+AC_CONFIG_MACRO_DIR(config)
+
+# with_target_subdir is used when configured as part of a GCC tree.
+if test -n "${with_target_subdir}"; then
+  AM_ENABLE_MULTILIB(, ..)
+fi
+
+AC_CANONICAL_SYSTEM
+target_alias=${target_alias-$host_alias}
+
+AC_USE_SYSTEM_EXTENSIONS
+
+libtool_VERSION=1:0:0
+AC_SUBST(libtool_VERSION)
+
+# 1.11.1: Require that version of automake.
+# foreign: Don't require README, INSTALL, NEWS, etc.
+# no-define: Don't define PACKAGE and VERSION.
+# no-dependencies: Don't generate automatic dependencies.
+#    (because it breaks when using bootstrap-lean, since some of the
+#    headers are gone at "make install" time).
+# -Wall: Issue all automake warnings.
+# -Wno-portability: Don't warn about constructs supported by GNU make.
+#    (because GCC requires GNU make anyhow).
+AM_INIT_AUTOMAKE([1.11.1 foreign no-dist no-define no-dependencies -Wall -Wno-portability])
+
+AM_MAINTAINER_MODE
+
+AC_ARG_WITH(target-subdir,
+[  --with-target-subdir=SUBDIR      Configuring in a subdirectory for target])
+
+# We must force CC to /not/ be precious variables; otherwise
+# the wrong, non-multilib-adjusted value will be used in multilibs.
+# As a side effect, we have to subst CFLAGS ourselves.
+m4_rename([_AC_ARG_VAR_PRECIOUS],[backtrace_PRECIOUS])
+m4_define([_AC_ARG_VAR_PRECIOUS],[])
+AC_PROG_CC
+m4_rename_force([backtrace_PRECIOUS],[_AC_ARG_VAR_PRECIOUS])
+
+AC_SUBST(CFLAGS)
+
+AC_PROG_AWK
+case "$AWK" in
+"") AC_MSG_ERROR([can't build without awk]) ;;
+esac
+
+LT_INIT
+AM_PROG_LIBTOOL
+
+AC_SYS_LARGEFILE
+
+backtrace_supported=yes
+
+if test -n "${with_target_subdir}"; then
+  # We are compiling a GCC library.  We can assume that the unwind
+  # library exists.
+  BACKTRACE_FILE="backtrace.lo simple.lo"
+else
+  AC_CHECK_HEADER([unwind.h],
+    [AC_CHECK_FUNC([_Unwind_Backtrace],
+	           [BACKTRACE_FILE="backtrace.lo simple.lo"],
+		   [BACKTRACE_FILE="nounwind.lo"
+                    backtrace_supported=no])],
+    [BACKTRACE_FILE="nounwind.lo"
+     backtrace_supported=no])
+fi
+AC_SUBST(BACKTRACE_FILE)
+
+EXTRA_FLAGS=
+if test -n "${with_target_subdir}"; then
+  EXTRA_FLAGS="-funwind-tables -frandom-seed=\$@"
+else
+  AC_CACHE_CHECK([for -funwind-tables option],
+    [libbacktrace_cv_c_unwind_tables],
+    [CFLAGS_hold="$CFLAGS"
+     CFLAGS="$CFLAGS -funwind-tables"
+     AC_COMPILE_IFELSE(
+       [AC_LANG_PROGRAM([static int f() { return 0; }], [return f();])],
+       [libbacktrace_cv_c_unwind_tables=yes],
+       [libbacktrace_cv_c_unwind_tables=no])
+     CFLAGS="$CFLAGS_hold"])
+  if test "$libbacktrace_cv_c_unwind_tables" = "yes"; then
+    EXTRA_FLAGS=-funwind-tables
+  fi
+  AC_CACHE_CHECK([for -frandom-seed=string option],
+    [libbacktrace_cv_c_random_seed_string],
+    [CFLAGS_hold="$CFLAGS"
+     CFLAGS="$CFLAGS -frandom-seed=conftest.lo"
+     AC_COMPILE_IFELSE(
+       [AC_LANG_PROGRAM([], [return 0;])],
+       [libbacktrace_cv_c_random_seed_string=yes],
+       [libbacktrace_cv_c_random_seed_string=no])
+     CFLAGS="$CFLAGS_hold"])
+  if test "$libbacktrace_cv_c_random_seed_string" = "yes"; then
+    EXTRA_FLAGS="$EXTRA_FLAGS -frandom-seed=\$@"
+  fi
+fi
+AC_SUBST(EXTRA_FLAGS)
+
+ACX_PROG_CC_WARNING_OPTS([-W -Wall -Wwrite-strings -Wstrict-prototypes \
+			  -Wmissing-prototypes -Wold-style-definition \
+			  -Wmissing-format-attribute -Wcast-qual],
+			  [WARN_FLAGS])
+
+if test -n "${with_target_subdir}"; then
+  WARN_FLAGS="$WARN_FLAGS -Werror"
+fi
+
+AC_SUBST(WARN_FLAGS)
+
+if test -n "${with_target_subdir}"; then
+  GCC_CHECK_UNWIND_GETIPINFO
+else
+  ac_save_CFFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -Werror-implicit-function-declaration"
+  AC_MSG_CHECKING([for _Unwind_GetIPInfo])
+  AC_LINK_IFELSE(
+    [AC_LANG_PROGRAM(
+       [#include "unwind.h"
+	struct _Unwind_Context *context;
+	int ip_before_insn = 0;],
+	[return _Unwind_GetIPInfo (context, &ip_before_insn);])],
+	[have_unwind_getipinfo=yes], [have_unwind_getipinfo=no])
+  CFLAGS="$ac_save_CFLAGS"
+  AC_MSG_RESULT([$have_unwind_getipinfo])
+  if test "$have_unwind_getipinfo" = "yes"; then
+    AC_DEFINE(HAVE_GETIPINFO, 1, [Define if _Unwind_GetIPInfo is available.])
+  fi
+fi
+
+# Enable --enable-host-shared.
+AC_ARG_ENABLE(host-shared,
+[AS_HELP_STRING([--enable-host-shared],
+		[build host code as shared libraries])],
+[PIC_FLAG=-fPIC], [PIC_FLAG=])
+AC_SUBST(PIC_FLAG)
+
+# Test for __sync support.
+AC_CACHE_CHECK([__sync extensions],
+[libbacktrace_cv_sys_sync],
+[if test -n "${with_target_subdir}"; then
+   case "${host}" in
+   hppa*-*-hpux*) libbacktrace_cv_sys_sync=no ;;
+   *) libbacktrace_cv_sys_sync=yes ;;
+   esac
+ else
+   AC_LINK_IFELSE(
+     [AC_LANG_PROGRAM([int i;],
+                      [__sync_bool_compare_and_swap (&i, i, i);
+                       __sync_lock_test_and_set (&i, 1);
+                       __sync_lock_release (&i);])],
+     [libbacktrace_cv_sys_sync=yes],
+     [libbacktrace_cv_sys_sync=no])
+ fi])
+BACKTRACE_SUPPORTS_THREADS=0
+if test "$libbacktrace_cv_sys_sync" = "yes"; then
+  BACKTRACE_SUPPORTS_THREADS=1
+  AC_DEFINE([HAVE_SYNC_FUNCTIONS], 1,
+	    [Define to 1 if you have the __sync functions])
+fi
+AC_SUBST(BACKTRACE_SUPPORTS_THREADS)
+
+# Test for __atomic support.
+AC_CACHE_CHECK([__atomic extensions],
+[libbacktrace_cv_sys_atomic],
+[if test -n "${with_target_subdir}"; then
+   libbacktrace_cv_sys_atomic=yes
+ else
+   AC_LINK_IFELSE(
+     [AC_LANG_PROGRAM([int i;],
+     		      [__atomic_load_n (&i, __ATOMIC_ACQUIRE);
+		       __atomic_store_n (&i, 1, __ATOMIC_RELEASE);])],
+     [libbacktrace_cv_sys_atomic=yes],
+     [libbacktrace_cv_sys_atomic=no])
+ fi])
+if test "$libbacktrace_cv_sys_atomic" = "yes"; then
+  AC_DEFINE([HAVE_ATOMIC_FUNCTIONS], 1,
+	    [Define to 1 if you have the __atomic functions])
+fi
+
+# The library needs to be able to read the executable itself.  Compile
+# a file to determine the executable format.  The awk script
+# filetype.awk prints out the file type.
+AC_CACHE_CHECK([output filetype],
+[libbacktrace_cv_sys_filetype],
+[filetype=
+AC_COMPILE_IFELSE(
+  [AC_LANG_PROGRAM([int i;], [int j;])],
+  [filetype=`${AWK} -f $srcdir/filetype.awk conftest.$ac_objext`],
+  [AC_MSG_FAILURE([compiler failed])])
+libbacktrace_cv_sys_filetype=$filetype])
+
+# Match the file type to decide what files to compile.
+FORMAT_FILE=
+backtrace_supports_data=yes
+case "$libbacktrace_cv_sys_filetype" in
+elf*) FORMAT_FILE="elf.lo" ;;
+pecoff) FORMAT_FILE="pecoff.lo"
+        backtrace_supports_data=no
+	;;
+xcoff*) FORMAT_FILE="xcoff.lo"
+        backtrace_supports_data=no
+        ;;
+macho*) FORMAT_FILE="macho.lo"
+        backtrace_supports_data=no
+        ;;
+*) AC_MSG_WARN([could not determine output file type])
+   FORMAT_FILE="unknown.lo"
+   backtrace_supported=no
+   ;;
+esac
+AC_SUBST(FORMAT_FILE)
+
+# ELF defines.
+elfsize=
+case "$libbacktrace_cv_sys_filetype" in
+elf32) elfsize=32 ;;
+elf64) elfsize=64 ;;
+*)     elfsize=unused
+esac
+AC_DEFINE_UNQUOTED([BACKTRACE_ELF_SIZE], [$elfsize], [ELF size: 32 or 64])
+
+# XCOFF defines.
+xcoffsize=
+case "$libbacktrace_cv_sys_filetype" in
+xcoff32) xcoffsize=32 ;;
+xcoff64) xcoffsize=64 ;;
+*)       xcoffsize=unused
+esac
+AC_DEFINE_UNQUOTED([BACKTRACE_XCOFF_SIZE], [$xcoffsize], [XCOFF size: 32 or 64])
+
+BACKTRACE_SUPPORTED=0
+if test "$backtrace_supported" = "yes"; then
+  BACKTRACE_SUPPORTED=1
+fi
+AC_SUBST(BACKTRACE_SUPPORTED)
+
+BACKTRACE_SUPPORTS_DATA=0
+if test "$backtrace_supports_data" = "yes"; then
+  BACKTRACE_SUPPORTS_DATA=1
+fi
+AC_SUBST(BACKTRACE_SUPPORTS_DATA)
+
+AC_CHECK_HEADERS(sys/mman.h)
+if test "$ac_cv_header_sys_mman_h" = "no"; then
+  have_mmap=no
+else
+  if test -n "${with_target_subdir}"; then
+    # When built as a GCC target library, we can't do a link test.  We
+    # simply assume that if we have mman.h, we have mmap.
+    have_mmap=yes
+    case "${host}" in
+    spu-*-*|*-*-msdosdjgpp)
+        # The SPU does not have mmap, but it has a sys/mman.h header file
+        # containing "mmap_eaddr" and the mmap flags, confusing the test.
+        # DJGPP also has sys/man.h, but no mmap
+	have_mmap=no ;;
+    esac
+  else
+    AC_CHECK_FUNC(mmap, [have_mmap=yes], [have_mmap=no])
+  fi
+fi
+
+case "${host_os}" in
+darwin*)
+  have_mmap=no ;;
+esac
+
+if test "$have_mmap" = "no"; then
+  VIEW_FILE=read.lo
+  ALLOC_FILE=alloc.lo
+else
+  VIEW_FILE=mmapio.lo
+  AC_PREPROC_IFELSE([
+#include <sys/mman.h>
+#if !defined(MAP_ANONYMOUS) && !defined(MAP_ANON)
+  #error no MAP_ANONYMOUS
+#endif
+], [ALLOC_FILE=mmap.lo], [ALLOC_FILE=alloc.lo])
+fi
+AC_SUBST(VIEW_FILE)
+AC_SUBST(ALLOC_FILE)
+
+BACKTRACE_USES_MALLOC=0
+if test "$ALLOC_FILE" = "alloc.lo"; then
+  BACKTRACE_USES_MALLOC=1
+fi
+AC_SUBST(BACKTRACE_USES_MALLOC)
+
+# Check for dl_iterate_phdr.
+AC_CHECK_HEADERS(link.h)
+if test "$ac_cv_header_link_h" = "no"; then
+  have_dl_iterate_phdr=no
+else
+  if test -n "${with_target_subdir}"; then
+    # When built as a GCC target library, we can't do a link test.
+    AC_EGREP_HEADER([dl_iterate_phdr], [link.h], [have_dl_iterate_phdr=yes],
+		    [have_dl_iterate_phdr=no])
+    case "${host}" in
+    *-*-solaris2.10*)
+        # Avoid dl_iterate_phdr on Solaris 10, where it is in the
+    	# header file but is only in -ldl.
+	have_dl_iterate_phdr=no ;;
+    esac
+  else
+    AC_CHECK_FUNC([dl_iterate_phdr], [have_dl_iterate_phdr=yes],
+		  [have_dl_iterate_phdr=no])
+  fi
+fi
+if test "$have_dl_iterate_phdr" = "yes"; then
+  AC_DEFINE(HAVE_DL_ITERATE_PHDR, 1, [Define if dl_iterate_phdr is available.])
+fi
+
+# Check for loadquery.
+AC_CHECK_HEADERS(sys/ldr.h)
+if test "$ac_cv_header_sys_ldr_h" = "no"; then
+  have_loadquery=no
+else
+  if test -n "${with_target_subdir}"; then
+    # When built as a GCC target library, we can't do a link test.
+    AC_EGREP_HEADER([loadquery], [sys/ldr.h], [have_loadquery=yes],
+		    [have_loadquery=no])
+  else
+    AC_CHECK_FUNC([loadquery], [have_loadquery=yes],
+		  [have_loadquery=no])
+  fi
+fi
+if test "$have_loadquery" = "yes"; then
+  AC_DEFINE(HAVE_LOADQUERY, 1, [Define if AIX loadquery is available.])
+fi
+
+# Check for the fcntl function.
+if test -n "${with_target_subdir}"; then
+   case "${host}" in
+   *-*-mingw*) have_fcntl=no ;;
+   spu-*-*) have_fcntl=no ;;
+   *) have_fcntl=yes ;;
+   esac
+else
+  AC_CHECK_FUNC(fcntl, [have_fcntl=yes], [have_fcntl=no])
+fi
+if test "$have_fcntl" = "yes"; then
+  AC_DEFINE([HAVE_FCNTL], 1,
+	    [Define to 1 if you have the fcntl function])
+fi
+
+AC_CHECK_DECLS(strnlen)
+AC_CHECK_FUNCS(lstat readlink)
+
+# Check for getexecname function.
+if test -n "${with_target_subdir}"; then
+   case "${host}" in
+   *-*-solaris2*) have_getexecname=yes ;;
+   *) have_getexecname=no ;;
+   esac
+else
+  AC_CHECK_FUNC(getexecname, [have_getexecname=yes], [have_getexecname=no])
+fi
+if test "$have_getexecname" = "yes"; then
+  AC_DEFINE(HAVE_GETEXECNAME, 1, [Define if getexecname is available.])
+fi
+
+# Check for the clock_gettime function.
+AC_CHECK_FUNCS(clock_gettime)
+clock_gettime_link=
+# At least for glibc, clock_gettime is in librt.  But don't
+# pull that in if it still doesn't give us the function we want.  This
+# test is copied from libgomp, and modified to not link in -lrt as
+# we're using this for test timing only.
+if test "$ac_cv_func_clock_gettime" = no; then
+  AC_CHECK_LIB(rt, clock_gettime,
+    [CLOCK_GETTIME_LINK=-lrt
+     AC_DEFINE(HAVE_CLOCK_GETTIME, 1,
+	       [Define to 1 if you have the `clock_gettime' function.])])
+fi
+AC_SUBST(CLOCK_GETTIME_LINK)
+
+dnl Test whether the compiler supports the -pthread option.
+AC_CACHE_CHECK([whether -pthread is supported],
+[libgo_cv_lib_pthread],
+[CFLAGS_hold=$CFLAGS
+CFLAGS="$CFLAGS -pthread"
+AC_COMPILE_IFELSE([[int i;]],
+[libgo_cv_lib_pthread=yes],
+[libgo_cv_lib_pthread=no])
+CFLAGS=$CFLAGS_hold])
+PTHREAD_CFLAGS=
+if test "$libgo_cv_lib_pthread" = yes; then
+  PTHREAD_CFLAGS=-pthread
+fi
+AC_SUBST(PTHREAD_CFLAGS)
+
+AM_CONDITIONAL(HAVE_PTHREAD, test "$libgo_cv_lib_pthread" = yes)
+
+AC_CHECK_LIB([z], [compress], [])
+if test $ac_cv_lib_z_compress = "yes"; then
+  AC_DEFINE(HAVE_ZLIB, 1, [Define if -lz is available.])
+fi
+AM_CONDITIONAL(HAVE_ZLIB, test "$ac_cv_lib_z_compress" = yes)
+
+dnl Test whether the linker supports the --compress_debug_sections option.
+AC_CACHE_CHECK([whether --compress-debug-sections is supported],
+[libgo_cv_ld_compress],
+[LDFLAGS_hold=$LDFLAGS
+LDFLAGS="$LDFLAGS -Wl,--compress-debug-sections=zlib-gnu"
+AC_LINK_IFELSE([AC_LANG_PROGRAM(,)],
+[libgo_cv_ld_compress=yes],
+[libgo_cv_ld_compress=no])
+LDFLAGS=$LDFLAGS_hold])
+AM_CONDITIONAL(HAVE_COMPRESSED_DEBUG, test "$libgo_cv_ld_compress" = yes)
+
+AC_ARG_VAR(OBJCOPY, [location of objcopy])
+AC_CHECK_PROG(OBJCOPY, objcopy, objcopy,)
+AC_CACHE_CHECK([whether objcopy supports debuglink],
+[libbacktrace_cv_objcopy_debuglink],
+[if test -n "${with_target_subdir}"; then
+  libbacktrace_cv_objcopy_debuglink=no
+elif ${OBJCOPY} --add-gnu-debuglink=x /bin/ls /tmp/ls$$; then
+  rm -f /tmp/ls$$
+  libbacktrace_cv_objcopy_debuglink=yes
+else
+  libbacktrace_cv_objcopy_debuglink=no
+fi])
+AM_CONDITIONAL(HAVE_OBJCOPY_DEBUGLINK, test "$libbacktrace_cv_objcopy_debuglink" = yes)
+
+AC_CACHE_CHECK([whether tests can run],
+  [libbacktrace_cv_sys_native],
+  [AC_RUN_IFELSE([AC_LANG_PROGRAM([], [return 0;])],
+     [libbacktrace_cv_sys_native=yes],
+     [libbacktrace_cv_sys_native=no],
+     [libbacktrace_cv_sys_native=no])])
+AM_CONDITIONAL(NATIVE, test "$libbacktrace_cv_sys_native" = "yes")
+
+if test "${multilib}" = "yes"; then
+  multilib_arg="--enable-multilib"
+else
+  multilib_arg=
+fi
+
+AC_CONFIG_FILES(Makefile backtrace-supported.h)
+
+# We need multilib support, but only if configuring for the target.
+AC_CONFIG_COMMANDS([default],
+[if test -n "$CONFIG_FILES"; then
+   if test -n "${with_target_subdir}"; then
+     # Multilibs need MULTISUBDIR defined correctly in certain makefiles so
+     # that multilib installs will end up installed in the correct place.
+     # The testsuite needs it for multilib-aware ABI baseline files.
+     # To work around this not being passed down from config-ml.in ->
+     # srcdir/Makefile.am -> srcdir/{src,libsupc++,...}/Makefile.am, manually
+     # append it here.  Only modify Makefiles that have just been created.
+     #
+     # Also, get rid of this simulated-VPATH thing that automake does.
+     cat > vpsed << \_EOF
+  s!`test -f '$<' || echo '$(srcdir)/'`!!
+_EOF
+     for i in $SUBDIRS; do
+      case $CONFIG_FILES in
+       *${i}/Makefile*)
+	 #echo "Adding MULTISUBDIR to $i/Makefile"
+	 sed -f vpsed $i/Makefile > tmp
+	 grep '^MULTISUBDIR =' Makefile >> tmp
+	 mv tmp $i/Makefile
+	 ;;
+      esac
+     done
+     rm vpsed
+   fi
+ fi
+],
+[
+# Variables needed in config.status (file generation) which aren't already
+# passed by autoconf.
+SUBDIRS="$SUBDIRS"
+])
+
+AC_OUTPUT
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/dwarf.c b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/dwarf.c
new file mode 100644
index 0000000..1bd1488
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/dwarf.c
@@ -0,0 +1,3126 @@
+/* dwarf.c -- Get file/line information from DWARF for backtraces.
+   Copyright (C) 2012-2018 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "backtrace.h"
+#include "internal.h"
+
+/* DWARF constants.  */
+
+enum dwarf_tag {
+  DW_TAG_entry_point = 0x3,
+  DW_TAG_compile_unit = 0x11,
+  DW_TAG_inlined_subroutine = 0x1d,
+  DW_TAG_subprogram = 0x2e,
+};
+
+enum dwarf_form {
+  DW_FORM_addr = 0x1,
+  DW_FORM_block2 = 0x3,
+  DW_FORM_block4 = 0x4,
+  DW_FORM_data2 = 0x5,
+  DW_FORM_data4 = 0x6,
+  DW_FORM_data8 = 0x07,
+  DW_FORM_string = 0x08,
+  DW_FORM_block = 0x09,
+  DW_FORM_block1 = 0x0a,
+  DW_FORM_data1 = 0x0b,
+  DW_FORM_flag = 0x0c,
+  DW_FORM_sdata = 0x0d,
+  DW_FORM_strp = 0x0e,
+  DW_FORM_udata = 0x0f,
+  DW_FORM_ref_addr = 0x10,
+  DW_FORM_ref1 = 0x11,
+  DW_FORM_ref2 = 0x12,
+  DW_FORM_ref4 = 0x13,
+  DW_FORM_ref8 = 0x14,
+  DW_FORM_ref_udata = 0x15,
+  DW_FORM_indirect = 0x16,
+  DW_FORM_sec_offset = 0x17,
+  DW_FORM_exprloc = 0x18,
+  DW_FORM_flag_present = 0x19,
+  DW_FORM_ref_sig8 = 0x20,
+  DW_FORM_GNU_addr_index = 0x1f01,
+  DW_FORM_GNU_str_index = 0x1f02,
+  DW_FORM_GNU_ref_alt = 0x1f20,
+  DW_FORM_GNU_strp_alt = 0x1f21,
+};
+
+enum dwarf_attribute {
+  DW_AT_name = 0x3,
+  DW_AT_stmt_list = 0x10,
+  DW_AT_low_pc = 0x11,
+  DW_AT_high_pc = 0x12,
+  DW_AT_comp_dir = 0x1b,
+  DW_AT_abstract_origin = 0x31,
+  DW_AT_specification = 0x47,
+  DW_AT_ranges = 0x55,
+  DW_AT_call_file = 0x58,
+  DW_AT_call_line = 0x59,
+  DW_AT_linkage_name = 0x6e,
+  DW_AT_MIPS_linkage_name = 0x2007,
+};
+
+enum dwarf_line_number_op {
+  DW_LNS_extended_op = 0x0,
+  DW_LNS_copy = 0x1,
+  DW_LNS_advance_pc = 0x2,
+  DW_LNS_advance_line = 0x3,
+  DW_LNS_set_file = 0x4,
+  DW_LNS_set_column = 0x5,
+  DW_LNS_negate_stmt = 0x6,
+  DW_LNS_set_basic_block = 0x7,
+  DW_LNS_const_add_pc = 0x8,
+  DW_LNS_fixed_advance_pc = 0x9,
+  DW_LNS_set_prologue_end = 0xa,
+  DW_LNS_set_epilogue_begin = 0xb,
+  DW_LNS_set_isa = 0xc,
+};
+
+enum dwarf_extedned_line_number_op {
+  DW_LNE_end_sequence = 0x1,
+  DW_LNE_set_address = 0x2,
+  DW_LNE_define_file = 0x3,
+  DW_LNE_set_discriminator = 0x4,
+};
+
+#if defined(__MSDOS__) || defined(_WIN32) || defined(__OS2__) || defined (__CYGWIN__)
+# define IS_DIR_SEPARATOR(c) ((c) == '/' || (c) == '\\')
+#define HAS_DRIVE_SPEC(f) ((f)[0] && (f)[1] == ':')
+# define IS_ABSOLUTE_PATH(f) (IS_DIR_SEPARATOR(f[0]) || HAS_DRIVE_SPEC(f))
+#else
+# define IS_DIR_SEPARATOR(c) ((c) == '/')
+# define IS_ABSOLUTE_PATH(f) IS_DIR_SEPARATOR(f[0])
+#endif
+
+#if !defined(HAVE_DECL_STRNLEN) || !HAVE_DECL_STRNLEN
+
+/* If strnlen is not declared, provide our own version.  */
+
+static size_t
+xstrnlen (const char *s, size_t maxlen)
+{
+  size_t i;
+
+  for (i = 0; i < maxlen; ++i)
+    if (s[i] == '\0')
+      break;
+  return i;
+}
+
+#define strnlen xstrnlen
+
+#endif
+
+/* A buffer to read DWARF info.  */
+
+struct dwarf_buf
+{
+  /* Buffer name for error messages.  */
+  const char *name;
+  /* Start of the buffer.  */
+  const unsigned char *start;
+  /* Next byte to read.  */
+  const unsigned char *buf;
+  /* The number of bytes remaining.  */
+  size_t left;
+  /* Whether the data is big-endian.  */
+  int is_bigendian;
+  /* Error callback routine.  */
+  backtrace_error_callback error_callback;
+  /* Data for error_callback.  */
+  void *data;
+  /* Non-zero if we've reported an underflow error.  */
+  int reported_underflow;
+};
+
+/* A single attribute in a DWARF abbreviation.  */
+
+struct attr
+{
+  /* The attribute name.  */
+  enum dwarf_attribute name;
+  /* The attribute form.  */
+  enum dwarf_form form;
+};
+
+/* A single DWARF abbreviation.  */
+
+struct abbrev
+{
+  /* The abbrev code--the number used to refer to the abbrev.  */
+  uint64_t code;
+  /* The entry tag.  */
+  enum dwarf_tag tag;
+  /* Non-zero if this abbrev has child entries.  */
+  int has_children;
+  /* The number of attributes.  */
+  size_t num_attrs;
+  /* The attributes.  */
+  struct attr *attrs;
+};
+
+/* The DWARF abbreviations for a compilation unit.  This structure
+   only exists while reading the compilation unit.  Most DWARF readers
+   seem to a hash table to map abbrev ID's to abbrev entries.
+   However, we primarily care about GCC, and GCC simply issues ID's in
+   numerical order starting at 1.  So we simply keep a sorted vector,
+   and try to just look up the code.  */
+
+struct abbrevs
+{
+  /* The number of abbrevs in the vector.  */
+  size_t num_abbrevs;
+  /* The abbrevs, sorted by the code field.  */
+  struct abbrev *abbrevs;
+};
+
+/* The different kinds of attribute values.  */
+
+enum attr_val_encoding
+{
+  /* An address.  */
+  ATTR_VAL_ADDRESS,
+  /* A unsigned integer.  */
+  ATTR_VAL_UINT,
+  /* A sigd integer.  */
+  ATTR_VAL_SINT,
+  /* A string.  */
+  ATTR_VAL_STRING,
+  /* An offset to other data in the containing unit.  */
+  ATTR_VAL_REF_UNIT,
+  /* An offset to other data within the .dwarf_info section.  */
+  ATTR_VAL_REF_INFO,
+  /* An offset to data in some other section.  */
+  ATTR_VAL_REF_SECTION,
+  /* A type signature.  */
+  ATTR_VAL_REF_TYPE,
+  /* A block of data (not represented).  */
+  ATTR_VAL_BLOCK,
+  /* An expression (not represented).  */
+  ATTR_VAL_EXPR,
+};
+
+/* An attribute value.  */
+
+struct attr_val
+{
+  /* How the value is stored in the field u.  */
+  enum attr_val_encoding encoding;
+  union
+  {
+    /* ATTR_VAL_ADDRESS, ATTR_VAL_UINT, ATTR_VAL_REF*.  */
+    uint64_t uint;
+    /* ATTR_VAL_SINT.  */
+    int64_t sint;
+    /* ATTR_VAL_STRING.  */
+    const char *string;
+    /* ATTR_VAL_BLOCK not stored.  */
+  } u;
+};
+
+/* The line number program header.  */
+
+struct line_header
+{
+  /* The version of the line number information.  */
+  int version;
+  /* The minimum instruction length.  */
+  unsigned int min_insn_len;
+  /* The maximum number of ops per instruction.  */
+  unsigned int max_ops_per_insn;
+  /* The line base for special opcodes.  */
+  int line_base;
+  /* The line range for special opcodes.  */
+  unsigned int line_range;
+  /* The opcode base--the first special opcode.  */
+  unsigned int opcode_base;
+  /* Opcode lengths, indexed by opcode - 1.  */
+  const unsigned char *opcode_lengths;
+  /* The number of directory entries.  */
+  size_t dirs_count;
+  /* The directory entries.  */
+  const char **dirs;
+  /* The number of filenames.  */
+  size_t filenames_count;
+  /* The filenames.  */
+  const char **filenames;
+};
+
+/* Map a single PC value to a file/line.  We will keep a vector of
+   these sorted by PC value.  Each file/line will be correct from the
+   PC up to the PC of the next entry if there is one.  We allocate one
+   extra entry at the end so that we can use bsearch.  */
+
+struct line
+{
+  /* PC.  */
+  uintptr_t pc;
+  /* File name.  Many entries in the array are expected to point to
+     the same file name.  */
+  const char *filename;
+  /* Line number.  */
+  int lineno;
+  /* Index of the object in the original array read from the DWARF
+     section, before it has been sorted.  The index makes it possible
+     to use Quicksort and maintain stability.  */
+  int idx;
+};
+
+/* A growable vector of line number information.  This is used while
+   reading the line numbers.  */
+
+struct line_vector
+{
+  /* Memory.  This is an array of struct line.  */
+  struct backtrace_vector vec;
+  /* Number of valid mappings.  */
+  size_t count;
+};
+
+/* A function described in the debug info.  */
+
+struct function
+{
+  /* The name of the function.  */
+  const char *name;
+  /* If this is an inlined function, the filename of the call
+     site.  */
+  const char *caller_filename;
+  /* If this is an inlined function, the line number of the call
+     site.  */
+  int caller_lineno;
+  /* Map PC ranges to inlined functions.  */
+  struct function_addrs *function_addrs;
+  size_t function_addrs_count;
+};
+
+/* An address range for a function.  This maps a PC value to a
+   specific function.  */
+
+struct function_addrs
+{
+  /* Range is LOW <= PC < HIGH.  */
+  uint64_t low;
+  uint64_t high;
+  /* Function for this address range.  */
+  struct function *function;
+};
+
+/* A growable vector of function address ranges.  */
+
+struct function_vector
+{
+  /* Memory.  This is an array of struct function_addrs.  */
+  struct backtrace_vector vec;
+  /* Number of address ranges present.  */
+  size_t count;
+};
+
+/* A DWARF compilation unit.  This only holds the information we need
+   to map a PC to a file and line.  */
+
+struct unit
+{
+  /* The first entry for this compilation unit.  */
+  const unsigned char *unit_data;
+  /* The length of the data for this compilation unit.  */
+  size_t unit_data_len;
+  /* The offset of UNIT_DATA from the start of the information for
+     this compilation unit.  */
+  size_t unit_data_offset;
+  /* DWARF version.  */
+  int version;
+  /* Whether unit is DWARF64.  */
+  int is_dwarf64;
+  /* Address size.  */
+  int addrsize;
+  /* Offset into line number information.  */
+  off_t lineoff;
+  /* Primary source file.  */
+  const char *filename;
+  /* Compilation command working directory.  */
+  const char *comp_dir;
+  /* Absolute file name, only set if needed.  */
+  const char *abs_filename;
+  /* The abbreviations for this unit.  */
+  struct abbrevs abbrevs;
+
+  /* The fields above this point are read in during initialization and
+     may be accessed freely.  The fields below this point are read in
+     as needed, and therefore require care, as different threads may
+     try to initialize them simultaneously.  */
+
+  /* PC to line number mapping.  This is NULL if the values have not
+     been read.  This is (struct line *) -1 if there was an error
+     reading the values.  */
+  struct line *lines;
+  /* Number of entries in lines.  */
+  size_t lines_count;
+  /* PC ranges to function.  */
+  struct function_addrs *function_addrs;
+  size_t function_addrs_count;
+};
+
+/* An address range for a compilation unit.  This maps a PC value to a
+   specific compilation unit.  Note that we invert the representation
+   in DWARF: instead of listing the units and attaching a list of
+   ranges, we list the ranges and have each one point to the unit.
+   This lets us do a binary search to find the unit.  */
+
+struct unit_addrs
+{
+  /* Range is LOW <= PC < HIGH.  */
+  uint64_t low;
+  uint64_t high;
+  /* Compilation unit for this address range.  */
+  struct unit *u;
+};
+
+/* A growable vector of compilation unit address ranges.  */
+
+struct unit_addrs_vector
+{
+  /* Memory.  This is an array of struct unit_addrs.  */
+  struct backtrace_vector vec;
+  /* Number of address ranges present.  */
+  size_t count;
+};
+
+/* The information we need to map a PC to a file and line.  */
+
+struct dwarf_data
+{
+  /* The data for the next file we know about.  */
+  struct dwarf_data *next;
+  /* The base address for this file.  */
+  uintptr_t base_address;
+  /* A sorted list of address ranges.  */
+  struct unit_addrs *addrs;
+  /* Number of address ranges in list.  */
+  size_t addrs_count;
+  /* The unparsed .debug_info section.  */
+  const unsigned char *dwarf_info;
+  size_t dwarf_info_size;
+  /* The unparsed .debug_line section.  */
+  const unsigned char *dwarf_line;
+  size_t dwarf_line_size;
+  /* The unparsed .debug_ranges section.  */
+  const unsigned char *dwarf_ranges;
+  size_t dwarf_ranges_size;
+  /* The unparsed .debug_str section.  */
+  const unsigned char *dwarf_str;
+  size_t dwarf_str_size;
+  /* Whether the data is big-endian or not.  */
+  int is_bigendian;
+  /* A vector used for function addresses.  We keep this here so that
+     we can grow the vector as we read more functions.  */
+  struct function_vector fvec;
+};
+
+/* Report an error for a DWARF buffer.  */
+
+static void
+dwarf_buf_error (struct dwarf_buf *buf, const char *msg)
+{
+  char b[200];
+
+  snprintf (b, sizeof b, "%s in %s at %d",
+	    msg, buf->name, (int) (buf->buf - buf->start));
+  buf->error_callback (buf->data, b, 0);
+}
+
+/* Require at least COUNT bytes in BUF.  Return 1 if all is well, 0 on
+   error.  */
+
+static int
+require (struct dwarf_buf *buf, size_t count)
+{
+  if (buf->left >= count)
+    return 1;
+
+  if (!buf->reported_underflow)
+    {
+      dwarf_buf_error (buf, "DWARF underflow");
+      buf->reported_underflow = 1;
+    }
+
+  return 0;
+}
+
+/* Advance COUNT bytes in BUF.  Return 1 if all is well, 0 on
+   error.  */
+
+static int
+advance (struct dwarf_buf *buf, size_t count)
+{
+  if (!require (buf, count))
+    return 0;
+  buf->buf += count;
+  buf->left -= count;
+  return 1;
+}
+
+/* Read one byte from BUF and advance 1 byte.  */
+
+static unsigned char
+read_byte (struct dwarf_buf *buf)
+{
+  const unsigned char *p = buf->buf;
+
+  if (!advance (buf, 1))
+    return 0;
+  return p[0];
+}
+
+/* Read a signed char from BUF and advance 1 byte.  */
+
+static signed char
+read_sbyte (struct dwarf_buf *buf)
+{
+  const unsigned char *p = buf->buf;
+
+  if (!advance (buf, 1))
+    return 0;
+  return (*p ^ 0x80) - 0x80;
+}
+
+/* Read a uint16 from BUF and advance 2 bytes.  */
+
+static uint16_t
+read_uint16 (struct dwarf_buf *buf)
+{
+  const unsigned char *p = buf->buf;
+
+  if (!advance (buf, 2))
+    return 0;
+  if (buf->is_bigendian)
+    return ((uint16_t) p[0] << 8) | (uint16_t) p[1];
+  else
+    return ((uint16_t) p[1] << 8) | (uint16_t) p[0];
+}
+
+/* Read a uint32 from BUF and advance 4 bytes.  */
+
+static uint32_t
+read_uint32 (struct dwarf_buf *buf)
+{
+  const unsigned char *p = buf->buf;
+
+  if (!advance (buf, 4))
+    return 0;
+  if (buf->is_bigendian)
+    return (((uint32_t) p[0] << 24) | ((uint32_t) p[1] << 16)
+	    | ((uint32_t) p[2] << 8) | (uint32_t) p[3]);
+  else
+    return (((uint32_t) p[3] << 24) | ((uint32_t) p[2] << 16)
+	    | ((uint32_t) p[1] << 8) | (uint32_t) p[0]);
+}
+
+/* Read a uint64 from BUF and advance 8 bytes.  */
+
+static uint64_t
+read_uint64 (struct dwarf_buf *buf)
+{
+  const unsigned char *p = buf->buf;
+
+  if (!advance (buf, 8))
+    return 0;
+  if (buf->is_bigendian)
+    return (((uint64_t) p[0] << 56) | ((uint64_t) p[1] << 48)
+	    | ((uint64_t) p[2] << 40) | ((uint64_t) p[3] << 32)
+	    | ((uint64_t) p[4] << 24) | ((uint64_t) p[5] << 16)
+	    | ((uint64_t) p[6] << 8) | (uint64_t) p[7]);
+  else
+    return (((uint64_t) p[7] << 56) | ((uint64_t) p[6] << 48)
+	    | ((uint64_t) p[5] << 40) | ((uint64_t) p[4] << 32)
+	    | ((uint64_t) p[3] << 24) | ((uint64_t) p[2] << 16)
+	    | ((uint64_t) p[1] << 8) | (uint64_t) p[0]);
+}
+
+/* Read an offset from BUF and advance the appropriate number of
+   bytes.  */
+
+static uint64_t
+read_offset (struct dwarf_buf *buf, int is_dwarf64)
+{
+  if (is_dwarf64)
+    return read_uint64 (buf);
+  else
+    return read_uint32 (buf);
+}
+
+/* Read an address from BUF and advance the appropriate number of
+   bytes.  */
+
+static uint64_t
+read_address (struct dwarf_buf *buf, int addrsize)
+{
+  switch (addrsize)
+    {
+    case 1:
+      return read_byte (buf);
+    case 2:
+      return read_uint16 (buf);
+    case 4:
+      return read_uint32 (buf);
+    case 8:
+      return read_uint64 (buf);
+    default:
+      dwarf_buf_error (buf, "unrecognized address size");
+      return 0;
+    }
+}
+
+/* Return whether a value is the highest possible address, given the
+   address size.  */
+
+static int
+is_highest_address (uint64_t address, int addrsize)
+{
+  switch (addrsize)
+    {
+    case 1:
+      return address == (unsigned char) -1;
+    case 2:
+      return address == (uint16_t) -1;
+    case 4:
+      return address == (uint32_t) -1;
+    case 8:
+      return address == (uint64_t) -1;
+    default:
+      return 0;
+    }
+}
+
+/* Read an unsigned LEB128 number.  */
+
+static uint64_t
+read_uleb128 (struct dwarf_buf *buf)
+{
+  uint64_t ret;
+  unsigned int shift;
+  int overflow;
+  unsigned char b;
+
+  ret = 0;
+  shift = 0;
+  overflow = 0;
+  do
+    {
+      const unsigned char *p;
+
+      p = buf->buf;
+      if (!advance (buf, 1))
+	return 0;
+      b = *p;
+      if (shift < 64)
+	ret |= ((uint64_t) (b & 0x7f)) << shift;
+      else if (!overflow)
+	{
+	  dwarf_buf_error (buf, "LEB128 overflows uint64_t");
+	  overflow = 1;
+	}
+      shift += 7;
+    }
+  while ((b & 0x80) != 0);
+
+  return ret;
+}
+
+/* Read a signed LEB128 number.  */
+
+static int64_t
+read_sleb128 (struct dwarf_buf *buf)
+{
+  uint64_t val;
+  unsigned int shift;
+  int overflow;
+  unsigned char b;
+
+  val = 0;
+  shift = 0;
+  overflow = 0;
+  do
+    {
+      const unsigned char *p;
+
+      p = buf->buf;
+      if (!advance (buf, 1))
+	return 0;
+      b = *p;
+      if (shift < 64)
+	val |= ((uint64_t) (b & 0x7f)) << shift;
+      else if (!overflow)
+	{
+	  dwarf_buf_error (buf, "signed LEB128 overflows uint64_t");
+	  overflow = 1;
+	}
+      shift += 7;
+    }
+  while ((b & 0x80) != 0);
+
+  if ((b & 0x40) != 0 && shift < 64)
+    val |= ((uint64_t) -1) << shift;
+
+  return (int64_t) val;
+}
+
+/* Return the length of an LEB128 number.  */
+
+static size_t
+leb128_len (const unsigned char *p)
+{
+  size_t ret;
+
+  ret = 1;
+  while ((*p & 0x80) != 0)
+    {
+      ++p;
+      ++ret;
+    }
+  return ret;
+}
+
+/* Free an abbreviations structure.  */
+
+static void
+free_abbrevs (struct backtrace_state *state, struct abbrevs *abbrevs,
+	      backtrace_error_callback error_callback, void *data)
+{
+  size_t i;
+
+  for (i = 0; i < abbrevs->num_abbrevs; ++i)
+    backtrace_free (state, abbrevs->abbrevs[i].attrs,
+		    abbrevs->abbrevs[i].num_attrs * sizeof (struct attr),
+		    error_callback, data);
+  backtrace_free (state, abbrevs->abbrevs,
+		  abbrevs->num_abbrevs * sizeof (struct abbrev),
+		  error_callback, data);
+  abbrevs->num_abbrevs = 0;
+  abbrevs->abbrevs = NULL;
+}
+
+/* Read an attribute value.  Returns 1 on success, 0 on failure.  If
+   the value can be represented as a uint64_t, sets *VAL and sets
+   *IS_VALID to 1.  We don't try to store the value of other attribute
+   forms, because we don't care about them.  */
+
+static int
+read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
+		int is_dwarf64, int version, int addrsize,
+		const unsigned char *dwarf_str, size_t dwarf_str_size,
+		struct attr_val *val)
+{
+  /* Avoid warnings about val.u.FIELD may be used uninitialized if
+     this function is inlined.  The warnings aren't valid but can
+     occur because the different fields are set and used
+     conditionally.  */
+  memset (val, 0, sizeof *val);
+
+  switch (form)
+    {
+    case DW_FORM_addr:
+      val->encoding = ATTR_VAL_ADDRESS;
+      val->u.uint = read_address (buf, addrsize);
+      return 1;
+    case DW_FORM_block2:
+      val->encoding = ATTR_VAL_BLOCK;
+      return advance (buf, read_uint16 (buf));
+    case DW_FORM_block4:
+      val->encoding = ATTR_VAL_BLOCK;
+      return advance (buf, read_uint32 (buf));
+    case DW_FORM_data2:
+      val->encoding = ATTR_VAL_UINT;
+      val->u.uint = read_uint16 (buf);
+      return 1;
+    case DW_FORM_data4:
+      val->encoding = ATTR_VAL_UINT;
+      val->u.uint = read_uint32 (buf);
+      return 1;
+    case DW_FORM_data8:
+      val->encoding = ATTR_VAL_UINT;
+      val->u.uint = read_uint64 (buf);
+      return 1;
+    case DW_FORM_string:
+      val->encoding = ATTR_VAL_STRING;
+      val->u.string = (const char *) buf->buf;
+      return advance (buf, strnlen ((const char *) buf->buf, buf->left) + 1);
+    case DW_FORM_block:
+      val->encoding = ATTR_VAL_BLOCK;
+      return advance (buf, read_uleb128 (buf));
+    case DW_FORM_block1:
+      val->encoding = ATTR_VAL_BLOCK;
+      return advance (buf, read_byte (buf));
+    case DW_FORM_data1:
+      val->encoding = ATTR_VAL_UINT;
+      val->u.uint = read_byte (buf);
+      return 1;
+    case DW_FORM_flag:
+      val->encoding = ATTR_VAL_UINT;
+      val->u.uint = read_byte (buf);
+      return 1;
+    case DW_FORM_sdata:
+      val->encoding = ATTR_VAL_SINT;
+      val->u.sint = read_sleb128 (buf);
+      return 1;
+    case DW_FORM_strp:
+      {
+	uint64_t offset;
+
+	offset = read_offset (buf, is_dwarf64);
+	if (offset >= dwarf_str_size)
+	  {
+	    dwarf_buf_error (buf, "DW_FORM_strp out of range");
+	    return 0;
+	  }
+	val->encoding = ATTR_VAL_STRING;
+	val->u.string = (const char *) dwarf_str + offset;
+	return 1;
+      }
+    case DW_FORM_udata:
+      val->encoding = ATTR_VAL_UINT;
+      val->u.uint = read_uleb128 (buf);
+      return 1;
+    case DW_FORM_ref_addr:
+      val->encoding = ATTR_VAL_REF_INFO;
+      if (version == 2)
+	val->u.uint = read_address (buf, addrsize);
+      else
+	val->u.uint = read_offset (buf, is_dwarf64);
+      return 1;
+    case DW_FORM_ref1:
+      val->encoding = ATTR_VAL_REF_UNIT;
+      val->u.uint = read_byte (buf);
+      return 1;
+    case DW_FORM_ref2:
+      val->encoding = ATTR_VAL_REF_UNIT;
+      val->u.uint = read_uint16 (buf);
+      return 1;
+    case DW_FORM_ref4:
+      val->encoding = ATTR_VAL_REF_UNIT;
+      val->u.uint = read_uint32 (buf);
+      return 1;
+    case DW_FORM_ref8:
+      val->encoding = ATTR_VAL_REF_UNIT;
+      val->u.uint = read_uint64 (buf);
+      return 1;
+    case DW_FORM_ref_udata:
+      val->encoding = ATTR_VAL_REF_UNIT;
+      val->u.uint = read_uleb128 (buf);
+      return 1;
+    case DW_FORM_indirect:
+      {
+	uint64_t form;
+
+	form = read_uleb128 (buf);
+	return read_attribute ((enum dwarf_form) form, buf, is_dwarf64,
+			       version, addrsize, dwarf_str, dwarf_str_size,
+			       val);
+      }
+    case DW_FORM_sec_offset:
+      val->encoding = ATTR_VAL_REF_SECTION;
+      val->u.uint = read_offset (buf, is_dwarf64);
+      return 1;
+    case DW_FORM_exprloc:
+      val->encoding = ATTR_VAL_EXPR;
+      return advance (buf, read_uleb128 (buf));
+    case DW_FORM_flag_present:
+      val->encoding = ATTR_VAL_UINT;
+      val->u.uint = 1;
+      return 1;
+    case DW_FORM_ref_sig8:
+      val->encoding = ATTR_VAL_REF_TYPE;
+      val->u.uint = read_uint64 (buf);
+      return 1;
+    case DW_FORM_GNU_addr_index:
+      val->encoding = ATTR_VAL_REF_SECTION;
+      val->u.uint = read_uleb128 (buf);
+      return 1;
+    case DW_FORM_GNU_str_index:
+      val->encoding = ATTR_VAL_REF_SECTION;
+      val->u.uint = read_uleb128 (buf);
+      return 1;
+    case DW_FORM_GNU_ref_alt:
+      val->encoding = ATTR_VAL_REF_SECTION;
+      val->u.uint = read_offset (buf, is_dwarf64);
+      return 1;
+    case DW_FORM_GNU_strp_alt:
+      val->encoding = ATTR_VAL_REF_SECTION;
+      val->u.uint = read_offset (buf, is_dwarf64);
+      return 1;
+    default:
+      dwarf_buf_error (buf, "unrecognized DWARF form");
+      return 0;
+    }
+}
+
+/* Compare function_addrs for qsort.  When ranges are nested, make the
+   smallest one sort last.  */
+
+static int
+function_addrs_compare (const void *v1, const void *v2)
+{
+  const struct function_addrs *a1 = (const struct function_addrs *) v1;
+  const struct function_addrs *a2 = (const struct function_addrs *) v2;
+
+  if (a1->low < a2->low)
+    return -1;
+  if (a1->low > a2->low)
+    return 1;
+  if (a1->high < a2->high)
+    return 1;
+  if (a1->high > a2->high)
+    return -1;
+  return strcmp (a1->function->name, a2->function->name);
+}
+
+/* Compare a PC against a function_addrs for bsearch.  Note that if
+   there are multiple ranges containing PC, which one will be returned
+   is unpredictable.  We compensate for that in dwarf_fileline.  */
+
+static int
+function_addrs_search (const void *vkey, const void *ventry)
+{
+  const uintptr_t *key = (const uintptr_t *) vkey;
+  const struct function_addrs *entry = (const struct function_addrs *) ventry;
+  uintptr_t pc;
+
+  pc = *key;
+  if (pc < entry->low)
+    return -1;
+  else if (pc >= entry->high)
+    return 1;
+  else
+    return 0;
+}
+
+/* Add a new compilation unit address range to a vector.  Returns 1 on
+   success, 0 on failure.  */
+
+static int
+add_unit_addr (struct backtrace_state *state, uintptr_t base_address,
+	       struct unit_addrs addrs,
+	       backtrace_error_callback error_callback, void *data,
+	       struct unit_addrs_vector *vec)
+{
+  struct unit_addrs *p;
+
+  /* Add in the base address of the module here, so that we can look
+     up the PC directly.  */
+  addrs.low += base_address;
+  addrs.high += base_address;
+
+  /* Try to merge with the last entry.  */
+  if (vec->count > 0)
+    {
+      p = (struct unit_addrs *) vec->vec.base + (vec->count - 1);
+      if ((addrs.low == p->high || addrs.low == p->high + 1)
+	  && addrs.u == p->u)
+	{
+	  if (addrs.high > p->high)
+	    p->high = addrs.high;
+	  return 1;
+	}
+    }
+
+  p = ((struct unit_addrs *)
+       backtrace_vector_grow (state, sizeof (struct unit_addrs),
+			      error_callback, data, &vec->vec));
+  if (p == NULL)
+    return 0;
+
+  *p = addrs;
+  ++vec->count;
+  return 1;
+}
+
+/* Free a unit address vector.  */
+
+static void
+free_unit_addrs_vector (struct backtrace_state *state,
+			struct unit_addrs_vector *vec,
+			backtrace_error_callback error_callback, void *data)
+{
+  struct unit_addrs *addrs;
+  size_t i;
+
+  addrs = (struct unit_addrs *) vec->vec.base;
+  for (i = 0; i < vec->count; ++i)
+    free_abbrevs (state, &addrs[i].u->abbrevs, error_callback, data);
+}
+
+/* Compare unit_addrs for qsort.  When ranges are nested, make the
+   smallest one sort last.  */
+
+static int
+unit_addrs_compare (const void *v1, const void *v2)
+{
+  const struct unit_addrs *a1 = (const struct unit_addrs *) v1;
+  const struct unit_addrs *a2 = (const struct unit_addrs *) v2;
+
+  if (a1->low < a2->low)
+    return -1;
+  if (a1->low > a2->low)
+    return 1;
+  if (a1->high < a2->high)
+    return 1;
+  if (a1->high > a2->high)
+    return -1;
+  if (a1->u->lineoff < a2->u->lineoff)
+    return -1;
+  if (a1->u->lineoff > a2->u->lineoff)
+    return 1;
+  return 0;
+}
+
+/* Compare a PC against a unit_addrs for bsearch.  Note that if there
+   are multiple ranges containing PC, which one will be returned is
+   unpredictable.  We compensate for that in dwarf_fileline.  */
+
+static int
+unit_addrs_search (const void *vkey, const void *ventry)
+{
+  const uintptr_t *key = (const uintptr_t *) vkey;
+  const struct unit_addrs *entry = (const struct unit_addrs *) ventry;
+  uintptr_t pc;
+
+  pc = *key;
+  if (pc < entry->low)
+    return -1;
+  else if (pc >= entry->high)
+    return 1;
+  else
+    return 0;
+}
+
+/* Sort the line vector by PC.  We want a stable sort here to maintain
+   the order of lines for the same PC values.  Since the sequence is
+   being sorted in place, their addresses cannot be relied on to
+   maintain stability.  That is the purpose of the index member.  */
+
+static int
+line_compare (const void *v1, const void *v2)
+{
+  const struct line *ln1 = (const struct line *) v1;
+  const struct line *ln2 = (const struct line *) v2;
+
+  if (ln1->pc < ln2->pc)
+    return -1;
+  else if (ln1->pc > ln2->pc)
+    return 1;
+  else if (ln1->idx < ln2->idx)
+    return -1;
+  else if (ln1->idx > ln2->idx)
+    return 1;
+  else
+    return 0;
+}
+
+/* Find a PC in a line vector.  We always allocate an extra entry at
+   the end of the lines vector, so that this routine can safely look
+   at the next entry.  Note that when there are multiple mappings for
+   the same PC value, this will return the last one.  */
+
+static int
+line_search (const void *vkey, const void *ventry)
+{
+  const uintptr_t *key = (const uintptr_t *) vkey;
+  const struct line *entry = (const struct line *) ventry;
+  uintptr_t pc;
+
+  pc = *key;
+  if (pc < entry->pc)
+    return -1;
+  else if (pc >= (entry + 1)->pc)
+    return 1;
+  else
+    return 0;
+}
+
+/* Sort the abbrevs by the abbrev code.  This function is passed to
+   both qsort and bsearch.  */
+
+static int
+abbrev_compare (const void *v1, const void *v2)
+{
+  const struct abbrev *a1 = (const struct abbrev *) v1;
+  const struct abbrev *a2 = (const struct abbrev *) v2;
+
+  if (a1->code < a2->code)
+    return -1;
+  else if (a1->code > a2->code)
+    return 1;
+  else
+    {
+      /* This really shouldn't happen.  It means there are two
+	 different abbrevs with the same code, and that means we don't
+	 know which one lookup_abbrev should return.  */
+      return 0;
+    }
+}
+
+/* Read the abbreviation table for a compilation unit.  Returns 1 on
+   success, 0 on failure.  */
+
+static int
+read_abbrevs (struct backtrace_state *state, uint64_t abbrev_offset,
+	      const unsigned char *dwarf_abbrev, size_t dwarf_abbrev_size,
+	      int is_bigendian, backtrace_error_callback error_callback,
+	      void *data, struct abbrevs *abbrevs)
+{
+  struct dwarf_buf abbrev_buf;
+  struct dwarf_buf count_buf;
+  size_t num_abbrevs;
+
+  abbrevs->num_abbrevs = 0;
+  abbrevs->abbrevs = NULL;
+
+  if (abbrev_offset >= dwarf_abbrev_size)
+    {
+      error_callback (data, "abbrev offset out of range", 0);
+      return 0;
+    }
+
+  abbrev_buf.name = ".debug_abbrev";
+  abbrev_buf.start = dwarf_abbrev;
+  abbrev_buf.buf = dwarf_abbrev + abbrev_offset;
+  abbrev_buf.left = dwarf_abbrev_size - abbrev_offset;
+  abbrev_buf.is_bigendian = is_bigendian;
+  abbrev_buf.error_callback = error_callback;
+  abbrev_buf.data = data;
+  abbrev_buf.reported_underflow = 0;
+
+  /* Count the number of abbrevs in this list.  */
+
+  count_buf = abbrev_buf;
+  num_abbrevs = 0;
+  while (read_uleb128 (&count_buf) != 0)
+    {
+      if (count_buf.reported_underflow)
+	return 0;
+      ++num_abbrevs;
+      // Skip tag.
+      read_uleb128 (&count_buf);
+      // Skip has_children.
+      read_byte (&count_buf);
+      // Skip attributes.
+      while (read_uleb128 (&count_buf) != 0)
+	read_uleb128 (&count_buf);
+      // Skip form of last attribute.
+      read_uleb128 (&count_buf);
+    }
+
+  if (count_buf.reported_underflow)
+    return 0;
+
+  if (num_abbrevs == 0)
+    return 1;
+
+  abbrevs->num_abbrevs = num_abbrevs;
+  abbrevs->abbrevs = ((struct abbrev *)
+		      backtrace_alloc (state,
+				       num_abbrevs * sizeof (struct abbrev),
+				       error_callback, data));
+  if (abbrevs->abbrevs == NULL)
+    return 0;
+  memset (abbrevs->abbrevs, 0, num_abbrevs * sizeof (struct abbrev));
+
+  num_abbrevs = 0;
+  while (1)
+    {
+      uint64_t code;
+      struct abbrev a;
+      size_t num_attrs;
+      struct attr *attrs;
+
+      if (abbrev_buf.reported_underflow)
+	goto fail;
+
+      code = read_uleb128 (&abbrev_buf);
+      if (code == 0)
+	break;
+
+      a.code = code;
+      a.tag = (enum dwarf_tag) read_uleb128 (&abbrev_buf);
+      a.has_children = read_byte (&abbrev_buf);
+
+      count_buf = abbrev_buf;
+      num_attrs = 0;
+      while (read_uleb128 (&count_buf) != 0)
+	{
+	  ++num_attrs;
+	  read_uleb128 (&count_buf);
+	}
+
+      if (num_attrs == 0)
+	{
+	  attrs = NULL;
+	  read_uleb128 (&abbrev_buf);
+	  read_uleb128 (&abbrev_buf);
+	}
+      else
+	{
+	  attrs = ((struct attr *)
+		   backtrace_alloc (state, num_attrs * sizeof *attrs,
+				    error_callback, data));
+	  if (attrs == NULL)
+	    goto fail;
+	  num_attrs = 0;
+	  while (1)
+	    {
+	      uint64_t name;
+	      uint64_t form;
+
+	      name = read_uleb128 (&abbrev_buf);
+	      form = read_uleb128 (&abbrev_buf);
+	      if (name == 0)
+		break;
+	      attrs[num_attrs].name = (enum dwarf_attribute) name;
+	      attrs[num_attrs].form = (enum dwarf_form) form;
+	      ++num_attrs;
+	    }
+	}
+
+      a.num_attrs = num_attrs;
+      a.attrs = attrs;
+
+      abbrevs->abbrevs[num_abbrevs] = a;
+      ++num_abbrevs;
+    }
+
+  backtrace_qsort (abbrevs->abbrevs, abbrevs->num_abbrevs,
+		   sizeof (struct abbrev), abbrev_compare);
+
+  return 1;
+
+ fail:
+  free_abbrevs (state, abbrevs, error_callback, data);
+  return 0;
+}
+
+/* Return the abbrev information for an abbrev code.  */
+
+static const struct abbrev *
+lookup_abbrev (struct abbrevs *abbrevs, uint64_t code,
+	       backtrace_error_callback error_callback, void *data)
+{
+  struct abbrev key;
+  void *p;
+
+  /* With GCC, where abbrevs are simply numbered in order, we should
+     be able to just look up the entry.  */
+  if (code - 1 < abbrevs->num_abbrevs
+      && abbrevs->abbrevs[code - 1].code == code)
+    return &abbrevs->abbrevs[code - 1];
+
+  /* Otherwise we have to search.  */
+  memset (&key, 0, sizeof key);
+  key.code = code;
+  p = bsearch (&key, abbrevs->abbrevs, abbrevs->num_abbrevs,
+	       sizeof (struct abbrev), abbrev_compare);
+  if (p == NULL)
+    {
+      error_callback (data, "invalid abbreviation code", 0);
+      return NULL;
+    }
+  return (const struct abbrev *) p;
+}
+
+/* Add non-contiguous address ranges for a compilation unit.  Returns
+   1 on success, 0 on failure.  */
+
+static int
+add_unit_ranges (struct backtrace_state *state, uintptr_t base_address,
+		 struct unit *u, uint64_t ranges, uint64_t base,
+		 int is_bigendian, const unsigned char *dwarf_ranges,
+		 size_t dwarf_ranges_size,
+		 backtrace_error_callback error_callback, void *data,
+		 struct unit_addrs_vector *addrs)
+{
+  struct dwarf_buf ranges_buf;
+
+  if (ranges >= dwarf_ranges_size)
+    {
+      error_callback (data, "ranges offset out of range", 0);
+      return 0;
+    }
+
+  ranges_buf.name = ".debug_ranges";
+  ranges_buf.start = dwarf_ranges;
+  ranges_buf.buf = dwarf_ranges + ranges;
+  ranges_buf.left = dwarf_ranges_size - ranges;
+  ranges_buf.is_bigendian = is_bigendian;
+  ranges_buf.error_callback = error_callback;
+  ranges_buf.data = data;
+  ranges_buf.reported_underflow = 0;
+
+  while (1)
+    {
+      uint64_t low;
+      uint64_t high;
+
+      if (ranges_buf.reported_underflow)
+	return 0;
+
+      low = read_address (&ranges_buf, u->addrsize);
+      high = read_address (&ranges_buf, u->addrsize);
+
+      if (low == 0 && high == 0)
+	break;
+
+      if (is_highest_address (low, u->addrsize))
+	base = high;
+      else
+	{
+	  struct unit_addrs a;
+
+	  a.low = low + base;
+	  a.high = high + base;
+	  a.u = u;
+	  if (!add_unit_addr (state, base_address, a, error_callback, data,
+			      addrs))
+	    return 0;
+	}
+    }
+
+  if (ranges_buf.reported_underflow)
+    return 0;
+
+  return 1;
+}
+
+/* Find the address range covered by a compilation unit, reading from
+   UNIT_BUF and adding values to U.  Returns 1 if all data could be
+   read, 0 if there is some error.  */
+
+static int
+find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
+		     struct dwarf_buf *unit_buf,
+		     const unsigned char *dwarf_str, size_t dwarf_str_size,
+		     const unsigned char *dwarf_ranges,
+		     size_t dwarf_ranges_size,
+		     int is_bigendian, backtrace_error_callback error_callback,
+		     void *data, struct unit *u,
+		     struct unit_addrs_vector *addrs)
+{
+  while (unit_buf->left > 0)
+    {
+      uint64_t code;
+      const struct abbrev *abbrev;
+      uint64_t lowpc;
+      int have_lowpc;
+      uint64_t highpc;
+      int have_highpc;
+      int highpc_is_relative;
+      uint64_t ranges;
+      int have_ranges;
+      size_t i;
+
+      code = read_uleb128 (unit_buf);
+      if (code == 0)
+	return 1;
+
+      abbrev = lookup_abbrev (&u->abbrevs, code, error_callback, data);
+      if (abbrev == NULL)
+	return 0;
+
+      lowpc = 0;
+      have_lowpc = 0;
+      highpc = 0;
+      have_highpc = 0;
+      highpc_is_relative = 0;
+      ranges = 0;
+      have_ranges = 0;
+      for (i = 0; i < abbrev->num_attrs; ++i)
+	{
+	  struct attr_val val;
+
+	  if (!read_attribute (abbrev->attrs[i].form, unit_buf,
+			       u->is_dwarf64, u->version, u->addrsize,
+			       dwarf_str, dwarf_str_size, &val))
+	    return 0;
+
+	  switch (abbrev->attrs[i].name)
+	    {
+	    case DW_AT_low_pc:
+	      if (val.encoding == ATTR_VAL_ADDRESS)
+		{
+		  lowpc = val.u.uint;
+		  have_lowpc = 1;
+		}
+	      break;
+
+	    case DW_AT_high_pc:
+	      if (val.encoding == ATTR_VAL_ADDRESS)
+		{
+		  highpc = val.u.uint;
+		  have_highpc = 1;
+		}
+	      else if (val.encoding == ATTR_VAL_UINT)
+		{
+		  highpc = val.u.uint;
+		  have_highpc = 1;
+		  highpc_is_relative = 1;
+		}
+	      break;
+
+	    case DW_AT_ranges:
+	      if (val.encoding == ATTR_VAL_UINT
+		  || val.encoding == ATTR_VAL_REF_SECTION)
+		{
+		  ranges = val.u.uint;
+		  have_ranges = 1;
+		}
+	      break;
+
+	    case DW_AT_stmt_list:
+	      if (abbrev->tag == DW_TAG_compile_unit
+		  && (val.encoding == ATTR_VAL_UINT
+		      || val.encoding == ATTR_VAL_REF_SECTION))
+		u->lineoff = val.u.uint;
+	      break;
+
+	    case DW_AT_name:
+	      if (abbrev->tag == DW_TAG_compile_unit
+		  && val.encoding == ATTR_VAL_STRING)
+		u->filename = val.u.string;
+	      break;
+
+	    case DW_AT_comp_dir:
+	      if (abbrev->tag == DW_TAG_compile_unit
+		  && val.encoding == ATTR_VAL_STRING)
+		u->comp_dir = val.u.string;
+	      break;
+
+	    default:
+	      break;
+	    }
+	}
+
+      if (abbrev->tag == DW_TAG_compile_unit
+	  || abbrev->tag == DW_TAG_subprogram)
+	{
+	  if (have_ranges)
+	    {
+	      if (!add_unit_ranges (state, base_address, u, ranges, lowpc,
+				    is_bigendian, dwarf_ranges,
+				    dwarf_ranges_size, error_callback,
+				    data, addrs))
+		return 0;
+	    }
+	  else if (have_lowpc && have_highpc)
+	    {
+	      struct unit_addrs a;
+
+	      if (highpc_is_relative)
+		highpc += lowpc;
+	      a.low = lowpc;
+	      a.high = highpc;
+	      a.u = u;
+
+	      if (!add_unit_addr (state, base_address, a, error_callback, data,
+				  addrs))
+		return 0;
+	    }
+
+	  /* If we found the PC range in the DW_TAG_compile_unit, we
+	     can stop now.  */
+	  if (abbrev->tag == DW_TAG_compile_unit
+	      && (have_ranges || (have_lowpc && have_highpc)))
+	    return 1;
+	}
+
+      if (abbrev->has_children)
+	{
+	  if (!find_address_ranges (state, base_address, unit_buf,
+				    dwarf_str, dwarf_str_size,
+				    dwarf_ranges, dwarf_ranges_size,
+				    is_bigendian, error_callback, data,
+				    u, addrs))
+	    return 0;
+	}
+    }
+
+  return 1;
+}
+
+/* Build a mapping from address ranges to the compilation units where
+   the line number information for that range can be found.  Returns 1
+   on success, 0 on failure.  */
+
+static int
+build_address_map (struct backtrace_state *state, uintptr_t base_address,
+		   const unsigned char *dwarf_info, size_t dwarf_info_size,
+		   const unsigned char *dwarf_abbrev, size_t dwarf_abbrev_size,
+		   const unsigned char *dwarf_ranges, size_t dwarf_ranges_size,
+		   const unsigned char *dwarf_str, size_t dwarf_str_size,
+		   int is_bigendian, backtrace_error_callback error_callback,
+		   void *data, struct unit_addrs_vector *addrs)
+{
+  struct dwarf_buf info;
+  struct abbrevs abbrevs;
+
+  memset (&addrs->vec, 0, sizeof addrs->vec);
+  addrs->count = 0;
+
+  /* Read through the .debug_info section.  FIXME: Should we use the
+     .debug_aranges section?  gdb and addr2line don't use it, but I'm
+     not sure why.  */
+
+  info.name = ".debug_info";
+  info.start = dwarf_info;
+  info.buf = dwarf_info;
+  info.left = dwarf_info_size;
+  info.is_bigendian = is_bigendian;
+  info.error_callback = error_callback;
+  info.data = data;
+  info.reported_underflow = 0;
+
+  memset (&abbrevs, 0, sizeof abbrevs);
+  while (info.left > 0)
+    {
+      const unsigned char *unit_data_start;
+      uint64_t len;
+      int is_dwarf64;
+      struct dwarf_buf unit_buf;
+      int version;
+      uint64_t abbrev_offset;
+      int addrsize;
+      struct unit *u;
+
+      if (info.reported_underflow)
+	goto fail;
+
+      unit_data_start = info.buf;
+
+      is_dwarf64 = 0;
+      len = read_uint32 (&info);
+      if (len == 0xffffffff)
+	{
+	  len = read_uint64 (&info);
+	  is_dwarf64 = 1;
+	}
+
+      unit_buf = info;
+      unit_buf.left = len;
+
+      if (!advance (&info, len))
+	goto fail;
+
+      version = read_uint16 (&unit_buf);
+      if (version < 2 || version > 4)
+	{
+	  dwarf_buf_error (&unit_buf, "unrecognized DWARF version");
+	  goto fail;
+	}
+
+      abbrev_offset = read_offset (&unit_buf, is_dwarf64);
+      if (!read_abbrevs (state, abbrev_offset, dwarf_abbrev, dwarf_abbrev_size,
+			 is_bigendian, error_callback, data, &abbrevs))
+	goto fail;
+
+      addrsize = read_byte (&unit_buf);
+
+      u = ((struct unit *)
+	   backtrace_alloc (state, sizeof *u, error_callback, data));
+      if (u == NULL)
+	goto fail;
+      u->unit_data = unit_buf.buf;
+      u->unit_data_len = unit_buf.left;
+      u->unit_data_offset = unit_buf.buf - unit_data_start;
+      u->version = version;
+      u->is_dwarf64 = is_dwarf64;
+      u->addrsize = addrsize;
+      u->filename = NULL;
+      u->comp_dir = NULL;
+      u->abs_filename = NULL;
+      u->lineoff = 0;
+      u->abbrevs = abbrevs;
+      memset (&abbrevs, 0, sizeof abbrevs);
+
+      /* The actual line number mappings will be read as needed.  */
+      u->lines = NULL;
+      u->lines_count = 0;
+      u->function_addrs = NULL;
+      u->function_addrs_count = 0;
+
+      if (!find_address_ranges (state, base_address, &unit_buf,
+				dwarf_str, dwarf_str_size,
+				dwarf_ranges, dwarf_ranges_size,
+				is_bigendian, error_callback, data,
+				u, addrs))
+	{
+	  free_abbrevs (state, &u->abbrevs, error_callback, data);
+	  backtrace_free (state, u, sizeof *u, error_callback, data);
+	  goto fail;
+	}
+
+      if (unit_buf.reported_underflow)
+	{
+	  free_abbrevs (state, &u->abbrevs, error_callback, data);
+	  backtrace_free (state, u, sizeof *u, error_callback, data);
+	  goto fail;
+	}
+    }
+  if (info.reported_underflow)
+    goto fail;
+
+  return 1;
+
+ fail:
+  free_abbrevs (state, &abbrevs, error_callback, data);
+  free_unit_addrs_vector (state, addrs, error_callback, data);
+  return 0;
+}
+
+/* Add a new mapping to the vector of line mappings that we are
+   building.  Returns 1 on success, 0 on failure.  */
+
+static int
+add_line (struct backtrace_state *state, struct dwarf_data *ddata,
+	  uintptr_t pc, const char *filename, int lineno,
+	  backtrace_error_callback error_callback, void *data,
+	  struct line_vector *vec)
+{
+  struct line *ln;
+
+  /* If we are adding the same mapping, ignore it.  This can happen
+     when using discriminators.  */
+  if (vec->count > 0)
+    {
+      ln = (struct line *) vec->vec.base + (vec->count - 1);
+      if (pc == ln->pc && filename == ln->filename && lineno == ln->lineno)
+	return 1;
+    }
+
+  ln = ((struct line *)
+	backtrace_vector_grow (state, sizeof (struct line), error_callback,
+			       data, &vec->vec));
+  if (ln == NULL)
+    return 0;
+
+  /* Add in the base address here, so that we can look up the PC
+     directly.  */
+  ln->pc = pc + ddata->base_address;
+
+  ln->filename = filename;
+  ln->lineno = lineno;
+  ln->idx = vec->count;
+
+  ++vec->count;
+
+  return 1;
+}
+
+/* Free the line header information.  */
+
+static void
+free_line_header (struct backtrace_state *state, struct line_header *hdr,
+		  backtrace_error_callback error_callback, void *data)
+{
+  if (hdr->dirs_count != 0)
+    backtrace_free (state, hdr->dirs, hdr->dirs_count * sizeof (const char *),
+		    error_callback, data);
+  backtrace_free (state, hdr->filenames,
+		  hdr->filenames_count * sizeof (char *),
+		  error_callback, data);
+}
+
+/* Read the line header.  Return 1 on success, 0 on failure.  */
+
+static int
+read_line_header (struct backtrace_state *state, struct unit *u,
+		  int is_dwarf64, struct dwarf_buf *line_buf,
+		  struct line_header *hdr)
+{
+  uint64_t hdrlen;
+  struct dwarf_buf hdr_buf;
+  const unsigned char *p;
+  const unsigned char *pend;
+  size_t i;
+
+  hdr->version = read_uint16 (line_buf);
+  if (hdr->version < 2 || hdr->version > 4)
+    {
+      dwarf_buf_error (line_buf, "unsupported line number version");
+      return 0;
+    }
+
+  hdrlen = read_offset (line_buf, is_dwarf64);
+
+  hdr_buf = *line_buf;
+  hdr_buf.left = hdrlen;
+
+  if (!advance (line_buf, hdrlen))
+    return 0;
+
+  hdr->min_insn_len = read_byte (&hdr_buf);
+  if (hdr->version < 4)
+    hdr->max_ops_per_insn = 1;
+  else
+    hdr->max_ops_per_insn = read_byte (&hdr_buf);
+
+  /* We don't care about default_is_stmt.  */
+  read_byte (&hdr_buf);
+
+  hdr->line_base = read_sbyte (&hdr_buf);
+  hdr->line_range = read_byte (&hdr_buf);
+
+  hdr->opcode_base = read_byte (&hdr_buf);
+  hdr->opcode_lengths = hdr_buf.buf;
+  if (!advance (&hdr_buf, hdr->opcode_base - 1))
+    return 0;
+
+  /* Count the number of directory entries.  */
+  hdr->dirs_count = 0;
+  p = hdr_buf.buf;
+  pend = p + hdr_buf.left;
+  while (p < pend && *p != '\0')
+    {
+      p += strnlen((const char *) p, pend - p) + 1;
+      ++hdr->dirs_count;
+    }
+
+  hdr->dirs = NULL;
+  if (hdr->dirs_count != 0)
+    {
+      hdr->dirs = ((const char **)
+		   backtrace_alloc (state,
+				    hdr->dirs_count * sizeof (const char *),
+				    line_buf->error_callback, line_buf->data));
+      if (hdr->dirs == NULL)
+	return 0;
+    }
+
+  i = 0;
+  while (*hdr_buf.buf != '\0')
+    {
+      if (hdr_buf.reported_underflow)
+	return 0;
+
+      hdr->dirs[i] = (const char *) hdr_buf.buf;
+      ++i;
+      if (!advance (&hdr_buf,
+		    strnlen ((const char *) hdr_buf.buf, hdr_buf.left) + 1))
+	return 0;
+    }
+  if (!advance (&hdr_buf, 1))
+    return 0;
+
+  /* Count the number of file entries.  */
+  hdr->filenames_count = 0;
+  p = hdr_buf.buf;
+  pend = p + hdr_buf.left;
+  while (p < pend && *p != '\0')
+    {
+      p += strnlen ((const char *) p, pend - p) + 1;
+      p += leb128_len (p);
+      p += leb128_len (p);
+      p += leb128_len (p);
+      ++hdr->filenames_count;
+    }
+
+  hdr->filenames = ((const char **)
+		    backtrace_alloc (state,
+				     hdr->filenames_count * sizeof (char *),
+				     line_buf->error_callback,
+				     line_buf->data));
+  if (hdr->filenames == NULL)
+    return 0;
+  i = 0;
+  while (*hdr_buf.buf != '\0')
+    {
+      const char *filename;
+      uint64_t dir_index;
+
+      if (hdr_buf.reported_underflow)
+	return 0;
+
+      filename = (const char *) hdr_buf.buf;
+      if (!advance (&hdr_buf,
+		    strnlen ((const char *) hdr_buf.buf, hdr_buf.left) + 1))
+	return 0;
+      dir_index = read_uleb128 (&hdr_buf);
+      if (IS_ABSOLUTE_PATH (filename)
+	  || (dir_index == 0 && u->comp_dir == NULL))
+	hdr->filenames[i] = filename;
+      else
+	{
+	  const char *dir;
+	  size_t dir_len;
+	  size_t filename_len;
+	  char *s;
+
+	  if (dir_index == 0)
+	    dir = u->comp_dir;
+	  else if (dir_index - 1 < hdr->dirs_count)
+	    dir = hdr->dirs[dir_index - 1];
+	  else
+	    {
+	      dwarf_buf_error (line_buf,
+			       ("invalid directory index in "
+				"line number program header"));
+	      return 0;
+	    }
+	  dir_len = strlen (dir);
+	  filename_len = strlen (filename);
+	  s = ((char *)
+	       backtrace_alloc (state, dir_len + filename_len + 2,
+				line_buf->error_callback, line_buf->data));
+	  if (s == NULL)
+	    return 0;
+	  memcpy (s, dir, dir_len);
+	  /* FIXME: If we are on a DOS-based file system, and the
+	     directory or the file name use backslashes, then we
+	     should use a backslash here.  */
+	  s[dir_len] = '/';
+	  memcpy (s + dir_len + 1, filename, filename_len + 1);
+	  hdr->filenames[i] = s;
+	}
+
+      /* Ignore the modification time and size.  */
+      read_uleb128 (&hdr_buf);
+      read_uleb128 (&hdr_buf);
+
+      ++i;
+    }
+
+  if (hdr_buf.reported_underflow)
+    return 0;
+
+  return 1;
+}
+
+/* Read the line program, adding line mappings to VEC.  Return 1 on
+   success, 0 on failure.  */
+
+static int
+read_line_program (struct backtrace_state *state, struct dwarf_data *ddata,
+		   struct unit *u, const struct line_header *hdr,
+		   struct dwarf_buf *line_buf, struct line_vector *vec)
+{
+  uint64_t address;
+  unsigned int op_index;
+  const char *reset_filename;
+  const char *filename;
+  int lineno;
+
+  address = 0;
+  op_index = 0;
+  if (hdr->filenames_count > 0)
+    reset_filename = hdr->filenames[0];
+  else
+    reset_filename = "";
+  filename = reset_filename;
+  lineno = 1;
+  while (line_buf->left > 0)
+    {
+      unsigned int op;
+
+      op = read_byte (line_buf);
+      if (op >= hdr->opcode_base)
+	{
+	  unsigned int advance;
+
+	  /* Special opcode.  */
+	  op -= hdr->opcode_base;
+	  advance = op / hdr->line_range;
+	  address += (hdr->min_insn_len * (op_index + advance)
+		      / hdr->max_ops_per_insn);
+	  op_index = (op_index + advance) % hdr->max_ops_per_insn;
+	  lineno += hdr->line_base + (int) (op % hdr->line_range);
+	  add_line (state, ddata, address, filename, lineno,
+		    line_buf->error_callback, line_buf->data, vec);
+	}
+      else if (op == DW_LNS_extended_op)
+	{
+	  uint64_t len;
+
+	  len = read_uleb128 (line_buf);
+	  op = read_byte (line_buf);
+	  switch (op)
+	    {
+	    case DW_LNE_end_sequence:
+	      /* FIXME: Should we mark the high PC here?  It seems
+		 that we already have that information from the
+		 compilation unit.  */
+	      address = 0;
+	      op_index = 0;
+	      filename = reset_filename;
+	      lineno = 1;
+	      break;
+	    case DW_LNE_set_address:
+	      address = read_address (line_buf, u->addrsize);
+	      break;
+	    case DW_LNE_define_file:
+	      {
+		const char *f;
+		unsigned int dir_index;
+
+		f = (const char *) line_buf->buf;
+		if (!advance (line_buf, strnlen (f, line_buf->left) + 1))
+		  return 0;
+		dir_index = read_uleb128 (line_buf);
+		/* Ignore that time and length.  */
+		read_uleb128 (line_buf);
+		read_uleb128 (line_buf);
+		if (IS_ABSOLUTE_PATH (f))
+		  filename = f;
+		else
+		  {
+		    const char *dir;
+		    size_t dir_len;
+		    size_t f_len;
+		    char *p;
+
+		    if (dir_index == 0)
+		      dir = u->comp_dir;
+		    else if (dir_index - 1 < hdr->dirs_count)
+		      dir = hdr->dirs[dir_index - 1];
+		    else
+		      {
+			dwarf_buf_error (line_buf,
+					 ("invalid directory index "
+					  "in line number program"));
+			return 0;
+		      }
+		    dir_len = strlen (dir);
+		    f_len = strlen (f);
+		    p = ((char *)
+			 backtrace_alloc (state, dir_len + f_len + 2,
+					  line_buf->error_callback,
+					  line_buf->data));
+		    if (p == NULL)
+		      return 0;
+		    memcpy (p, dir, dir_len);
+		    /* FIXME: If we are on a DOS-based file system,
+		       and the directory or the file name use
+		       backslashes, then we should use a backslash
+		       here.  */
+		    p[dir_len] = '/';
+		    memcpy (p + dir_len + 1, f, f_len + 1);
+		    filename = p;
+		  }
+	      }
+	      break;
+	    case DW_LNE_set_discriminator:
+	      /* We don't care about discriminators.  */
+	      read_uleb128 (line_buf);
+	      break;
+	    default:
+	      if (!advance (line_buf, len - 1))
+		return 0;
+	      break;
+	    }
+	}
+      else
+	{
+	  switch (op)
+	    {
+	    case DW_LNS_copy:
+	      add_line (state, ddata, address, filename, lineno,
+			line_buf->error_callback, line_buf->data, vec);
+	      break;
+	    case DW_LNS_advance_pc:
+	      {
+		uint64_t advance;
+
+		advance = read_uleb128 (line_buf);
+		address += (hdr->min_insn_len * (op_index + advance)
+			    / hdr->max_ops_per_insn);
+		op_index = (op_index + advance) % hdr->max_ops_per_insn;
+	      }
+	      break;
+	    case DW_LNS_advance_line:
+	      lineno += (int) read_sleb128 (line_buf);
+	      break;
+	    case DW_LNS_set_file:
+	      {
+		uint64_t fileno;
+
+		fileno = read_uleb128 (line_buf);
+		if (fileno == 0)
+		  filename = "";
+		else
+		  {
+		    if (fileno - 1 >= hdr->filenames_count)
+		      {
+			dwarf_buf_error (line_buf,
+					 ("invalid file number in "
+					  "line number program"));
+			return 0;
+		      }
+		    filename = hdr->filenames[fileno - 1];
+		  }
+	      }
+	      break;
+	    case DW_LNS_set_column:
+	      read_uleb128 (line_buf);
+	      break;
+	    case DW_LNS_negate_stmt:
+	      break;
+	    case DW_LNS_set_basic_block:
+	      break;
+	    case DW_LNS_const_add_pc:
+	      {
+		unsigned int advance;
+
+		op = 255 - hdr->opcode_base;
+		advance = op / hdr->line_range;
+		address += (hdr->min_insn_len * (op_index + advance)
+			    / hdr->max_ops_per_insn);
+		op_index = (op_index + advance) % hdr->max_ops_per_insn;
+	      }
+	      break;
+	    case DW_LNS_fixed_advance_pc:
+	      address += read_uint16 (line_buf);
+	      op_index = 0;
+	      break;
+	    case DW_LNS_set_prologue_end:
+	      break;
+	    case DW_LNS_set_epilogue_begin:
+	      break;
+	    case DW_LNS_set_isa:
+	      read_uleb128 (line_buf);
+	      break;
+	    default:
+	      {
+		unsigned int i;
+
+		for (i = hdr->opcode_lengths[op - 1]; i > 0; --i)
+		  read_uleb128 (line_buf);
+	      }
+	      break;
+	    }
+	}
+    }
+
+  return 1;
+}
+
+/* Read the line number information for a compilation unit.  Returns 1
+   on success, 0 on failure.  */
+
+static int
+read_line_info (struct backtrace_state *state, struct dwarf_data *ddata,
+		backtrace_error_callback error_callback, void *data,
+		struct unit *u, struct line_header *hdr, struct line **lines,
+		size_t *lines_count)
+{
+  struct line_vector vec;
+  struct dwarf_buf line_buf;
+  uint64_t len;
+  int is_dwarf64;
+  struct line *ln;
+
+  memset (&vec.vec, 0, sizeof vec.vec);
+  vec.count = 0;
+
+  memset (hdr, 0, sizeof *hdr);
+
+  if (u->lineoff != (off_t) (size_t) u->lineoff
+      || (size_t) u->lineoff >= ddata->dwarf_line_size)
+    {
+      error_callback (data, "unit line offset out of range", 0);
+      goto fail;
+    }
+
+  line_buf.name = ".debug_line";
+  line_buf.start = ddata->dwarf_line;
+  line_buf.buf = ddata->dwarf_line + u->lineoff;
+  line_buf.left = ddata->dwarf_line_size - u->lineoff;
+  line_buf.is_bigendian = ddata->is_bigendian;
+  line_buf.error_callback = error_callback;
+  line_buf.data = data;
+  line_buf.reported_underflow = 0;
+
+  is_dwarf64 = 0;
+  len = read_uint32 (&line_buf);
+  if (len == 0xffffffff)
+    {
+      len = read_uint64 (&line_buf);
+      is_dwarf64 = 1;
+    }
+  line_buf.left = len;
+
+  if (!read_line_header (state, u, is_dwarf64, &line_buf, hdr))
+    goto fail;
+
+  if (!read_line_program (state, ddata, u, hdr, &line_buf, &vec))
+    goto fail;
+
+  if (line_buf.reported_underflow)
+    goto fail;
+
+  if (vec.count == 0)
+    {
+      /* This is not a failure in the sense of a generating an error,
+	 but it is a failure in that sense that we have no useful
+	 information.  */
+      goto fail;
+    }
+
+  /* Allocate one extra entry at the end.  */
+  ln = ((struct line *)
+	backtrace_vector_grow (state, sizeof (struct line), error_callback,
+			       data, &vec.vec));
+  if (ln == NULL)
+    goto fail;
+  ln->pc = (uintptr_t) -1;
+  ln->filename = NULL;
+  ln->lineno = 0;
+  ln->idx = 0;
+
+  if (!backtrace_vector_release (state, &vec.vec, error_callback, data))
+    goto fail;
+
+  ln = (struct line *) vec.vec.base;
+  backtrace_qsort (ln, vec.count, sizeof (struct line), line_compare);
+
+  *lines = ln;
+  *lines_count = vec.count;
+
+  return 1;
+
+ fail:
+  vec.vec.alc += vec.vec.size;
+  vec.vec.size = 0;
+  backtrace_vector_release (state, &vec.vec, error_callback, data);
+  free_line_header (state, hdr, error_callback, data);
+  *lines = (struct line *) (uintptr_t) -1;
+  *lines_count = 0;
+  return 0;
+}
+
+/* Read the name of a function from a DIE referenced by a
+   DW_AT_abstract_origin or DW_AT_specification tag.  OFFSET is within
+   the same compilation unit.  */
+
+static const char *
+read_referenced_name (struct dwarf_data *ddata, struct unit *u,
+		      uint64_t offset, backtrace_error_callback error_callback,
+		      void *data)
+{
+  struct dwarf_buf unit_buf;
+  uint64_t code;
+  const struct abbrev *abbrev;
+  const char *ret;
+  size_t i;
+
+  /* OFFSET is from the start of the data for this compilation unit.
+     U->unit_data is the data, but it starts U->unit_data_offset bytes
+     from the beginning.  */
+
+  if (offset < u->unit_data_offset
+      || offset - u->unit_data_offset >= u->unit_data_len)
+    {
+      error_callback (data,
+		      "abstract origin or specification out of range",
+		      0);
+      return NULL;
+    }
+
+  offset -= u->unit_data_offset;
+
+  unit_buf.name = ".debug_info";
+  unit_buf.start = ddata->dwarf_info;
+  unit_buf.buf = u->unit_data + offset;
+  unit_buf.left = u->unit_data_len - offset;
+  unit_buf.is_bigendian = ddata->is_bigendian;
+  unit_buf.error_callback = error_callback;
+  unit_buf.data = data;
+  unit_buf.reported_underflow = 0;
+
+  code = read_uleb128 (&unit_buf);
+  if (code == 0)
+    {
+      dwarf_buf_error (&unit_buf, "invalid abstract origin or specification");
+      return NULL;
+    }
+
+  abbrev = lookup_abbrev (&u->abbrevs, code, error_callback, data);
+  if (abbrev == NULL)
+    return NULL;
+
+  ret = NULL;
+  for (i = 0; i < abbrev->num_attrs; ++i)
+    {
+      struct attr_val val;
+
+      if (!read_attribute (abbrev->attrs[i].form, &unit_buf,
+			   u->is_dwarf64, u->version, u->addrsize,
+			   ddata->dwarf_str, ddata->dwarf_str_size,
+			   &val))
+	return NULL;
+
+      switch (abbrev->attrs[i].name)
+	{
+	case DW_AT_name:
+	  /* We prefer the linkage name if get one.  */
+	  if (val.encoding == ATTR_VAL_STRING)
+	    ret = val.u.string;
+	  break;
+
+	case DW_AT_linkage_name:
+	case DW_AT_MIPS_linkage_name:
+	  if (val.encoding == ATTR_VAL_STRING)
+	    return val.u.string;
+	  break;
+
+	case DW_AT_specification:
+	  if (abbrev->attrs[i].form == DW_FORM_ref_addr
+	      || abbrev->attrs[i].form == DW_FORM_ref_sig8)
+	    {
+	      /* This refers to a specification defined in some other
+		 compilation unit.  We can handle this case if we
+		 must, but it's harder.  */
+	      break;
+	    }
+	  if (val.encoding == ATTR_VAL_UINT
+	      || val.encoding == ATTR_VAL_REF_UNIT)
+	    {
+	      const char *name;
+
+	      name = read_referenced_name (ddata, u, val.u.uint,
+					   error_callback, data);
+	      if (name != NULL)
+		ret = name;
+	    }
+	  break;
+
+	default:
+	  break;
+	}
+    }
+
+  return ret;
+}
+
+/* Add a single range to U that maps to function.  Returns 1 on
+   success, 0 on error.  */
+
+static int
+add_function_range (struct backtrace_state *state, struct dwarf_data *ddata,
+		    struct function *function, uint64_t lowpc, uint64_t highpc,
+		    backtrace_error_callback error_callback,
+		    void *data, struct function_vector *vec)
+{
+  struct function_addrs *p;
+
+  /* Add in the base address here, so that we can look up the PC
+     directly.  */
+  lowpc += ddata->base_address;
+  highpc += ddata->base_address;
+
+  if (vec->count > 0)
+    {
+      p = (struct function_addrs *) vec->vec.base + vec->count - 1;
+      if ((lowpc == p->high || lowpc == p->high + 1)
+	  && function == p->function)
+	{
+	  if (highpc > p->high)
+	    p->high = highpc;
+	  return 1;
+	}
+    }
+
+  p = ((struct function_addrs *)
+       backtrace_vector_grow (state, sizeof (struct function_addrs),
+			      error_callback, data, &vec->vec));
+  if (p == NULL)
+    return 0;
+
+  p->low = lowpc;
+  p->high = highpc;
+  p->function = function;
+  ++vec->count;
+  return 1;
+}
+
+/* Add PC ranges to U that map to FUNCTION.  Returns 1 on success, 0
+   on error.  */
+
+static int
+add_function_ranges (struct backtrace_state *state, struct dwarf_data *ddata,
+		     struct unit *u, struct function *function,
+		     uint64_t ranges, uint64_t base,
+		     backtrace_error_callback error_callback, void *data,
+		     struct function_vector *vec)
+{
+  struct dwarf_buf ranges_buf;
+
+  if (ranges >= ddata->dwarf_ranges_size)
+    {
+      error_callback (data, "function ranges offset out of range", 0);
+      return 0;
+    }
+
+  ranges_buf.name = ".debug_ranges";
+  ranges_buf.start = ddata->dwarf_ranges;
+  ranges_buf.buf = ddata->dwarf_ranges + ranges;
+  ranges_buf.left = ddata->dwarf_ranges_size - ranges;
+  ranges_buf.is_bigendian = ddata->is_bigendian;
+  ranges_buf.error_callback = error_callback;
+  ranges_buf.data = data;
+  ranges_buf.reported_underflow = 0;
+
+  while (1)
+    {
+      uint64_t low;
+      uint64_t high;
+
+      if (ranges_buf.reported_underflow)
+	return 0;
+
+      low = read_address (&ranges_buf, u->addrsize);
+      high = read_address (&ranges_buf, u->addrsize);
+
+      if (low == 0 && high == 0)
+	break;
+
+      if (is_highest_address (low, u->addrsize))
+	base = high;
+      else
+	{
+	  if (!add_function_range (state, ddata, function, low + base,
+				   high + base, error_callback, data, vec))
+	    return 0;
+	}
+    }
+
+  if (ranges_buf.reported_underflow)
+    return 0;
+
+  return 1;
+}
+
+/* Read one entry plus all its children.  Add function addresses to
+   VEC.  Returns 1 on success, 0 on error.  */
+
+static int
+read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
+		     struct unit *u, uint64_t base, struct dwarf_buf *unit_buf,
+		     const struct line_header *lhdr,
+		     backtrace_error_callback error_callback, void *data,
+		     struct function_vector *vec_function,
+		     struct function_vector *vec_inlined)
+{
+  while (unit_buf->left > 0)
+    {
+      uint64_t code;
+      const struct abbrev *abbrev;
+      int is_function;
+      struct function *function;
+      struct function_vector *vec;
+      size_t i;
+      uint64_t lowpc;
+      int have_lowpc;
+      uint64_t highpc;
+      int have_highpc;
+      int highpc_is_relative;
+      uint64_t ranges;
+      int have_ranges;
+
+      code = read_uleb128 (unit_buf);
+      if (code == 0)
+	return 1;
+
+      abbrev = lookup_abbrev (&u->abbrevs, code, error_callback, data);
+      if (abbrev == NULL)
+	return 0;
+
+      is_function = (abbrev->tag == DW_TAG_subprogram
+		     || abbrev->tag == DW_TAG_entry_point
+		     || abbrev->tag == DW_TAG_inlined_subroutine);
+
+      if (abbrev->tag == DW_TAG_inlined_subroutine)
+	vec = vec_inlined;
+      else
+	vec = vec_function;
+
+      function = NULL;
+      if (is_function)
+	{
+	  function = ((struct function *)
+		      backtrace_alloc (state, sizeof *function,
+				       error_callback, data));
+	  if (function == NULL)
+	    return 0;
+	  memset (function, 0, sizeof *function);
+	}
+
+      lowpc = 0;
+      have_lowpc = 0;
+      highpc = 0;
+      have_highpc = 0;
+      highpc_is_relative = 0;
+      ranges = 0;
+      have_ranges = 0;
+      for (i = 0; i < abbrev->num_attrs; ++i)
+	{
+	  struct attr_val val;
+
+	  if (!read_attribute (abbrev->attrs[i].form, unit_buf,
+			       u->is_dwarf64, u->version, u->addrsize,
+			       ddata->dwarf_str, ddata->dwarf_str_size,
+			       &val))
+	    return 0;
+
+	  /* The compile unit sets the base address for any address
+	     ranges in the function entries.  */
+	  if (abbrev->tag == DW_TAG_compile_unit
+	      && abbrev->attrs[i].name == DW_AT_low_pc
+	      && val.encoding == ATTR_VAL_ADDRESS)
+	    base = val.u.uint;
+
+	  if (is_function)
+	    {
+	      switch (abbrev->attrs[i].name)
+		{
+		case DW_AT_call_file:
+		  if (val.encoding == ATTR_VAL_UINT)
+		    {
+		      if (val.u.uint == 0)
+			function->caller_filename = "";
+		      else
+			{
+			  if (val.u.uint - 1 >= lhdr->filenames_count)
+			    {
+			      dwarf_buf_error (unit_buf,
+					       ("invalid file number in "
+						"DW_AT_call_file attribute"));
+			      return 0;
+			    }
+			  function->caller_filename =
+			    lhdr->filenames[val.u.uint - 1];
+			}
+		    }
+		  break;
+
+		case DW_AT_call_line:
+		  if (val.encoding == ATTR_VAL_UINT)
+		    function->caller_lineno = val.u.uint;
+		  break;
+
+		case DW_AT_abstract_origin:
+		case DW_AT_specification:
+		  if (abbrev->attrs[i].form == DW_FORM_ref_addr
+		      || abbrev->attrs[i].form == DW_FORM_ref_sig8)
+		    {
+		      /* This refers to an abstract origin defined in
+			 some other compilation unit.  We can handle
+			 this case if we must, but it's harder.  */
+		      break;
+		    }
+		  if (val.encoding == ATTR_VAL_UINT
+		      || val.encoding == ATTR_VAL_REF_UNIT)
+		    {
+		      const char *name;
+
+		      name = read_referenced_name (ddata, u, val.u.uint,
+						   error_callback, data);
+		      if (name != NULL)
+			function->name = name;
+		    }
+		  break;
+
+		case DW_AT_name:
+		  if (val.encoding == ATTR_VAL_STRING)
+		    {
+		      /* Don't override a name we found in some other
+			 way, as it will normally be more
+			 useful--e.g., this name is normally not
+			 mangled.  */
+		      if (function->name == NULL)
+			function->name = val.u.string;
+		    }
+		  break;
+
+		case DW_AT_linkage_name:
+		case DW_AT_MIPS_linkage_name:
+		  if (val.encoding == ATTR_VAL_STRING)
+		    function->name = val.u.string;
+		  break;
+
+		case DW_AT_low_pc:
+		  if (val.encoding == ATTR_VAL_ADDRESS)
+		    {
+		      lowpc = val.u.uint;
+		      have_lowpc = 1;
+		    }
+		  break;
+
+		case DW_AT_high_pc:
+		  if (val.encoding == ATTR_VAL_ADDRESS)
+		    {
+		      highpc = val.u.uint;
+		      have_highpc = 1;
+		    }
+		  else if (val.encoding == ATTR_VAL_UINT)
+		    {
+		      highpc = val.u.uint;
+		      have_highpc = 1;
+		      highpc_is_relative = 1;
+		    }
+		  break;
+
+		case DW_AT_ranges:
+		  if (val.encoding == ATTR_VAL_UINT
+		      || val.encoding == ATTR_VAL_REF_SECTION)
+		    {
+		      ranges = val.u.uint;
+		      have_ranges = 1;
+		    }
+		  break;
+
+		default:
+		  break;
+		}
+	    }
+	}
+
+      /* If we couldn't find a name for the function, we have no use
+	 for it.  */
+      if (is_function && function->name == NULL)
+	{
+	  backtrace_free (state, function, sizeof *function,
+			  error_callback, data);
+	  is_function = 0;
+	}
+
+      if (is_function)
+	{
+	  if (have_ranges)
+	    {
+	      if (!add_function_ranges (state, ddata, u, function, ranges,
+					base, error_callback, data, vec))
+		return 0;
+	    }
+	  else if (have_lowpc && have_highpc)
+	    {
+	      if (highpc_is_relative)
+		highpc += lowpc;
+	      if (!add_function_range (state, ddata, function, lowpc, highpc,
+				       error_callback, data, vec))
+		return 0;
+	    }
+	  else
+	    {
+	      backtrace_free (state, function, sizeof *function,
+			      error_callback, data);
+	      is_function = 0;
+	    }
+	}
+
+      if (abbrev->has_children)
+	{
+	  if (!is_function)
+	    {
+	      if (!read_function_entry (state, ddata, u, base, unit_buf, lhdr,
+					error_callback, data, vec_function,
+					vec_inlined))
+		return 0;
+	    }
+	  else
+	    {
+	      struct function_vector fvec;
+
+	      /* Gather any information for inlined functions in
+		 FVEC.  */
+
+	      memset (&fvec, 0, sizeof fvec);
+
+	      if (!read_function_entry (state, ddata, u, base, unit_buf, lhdr,
+					error_callback, data, vec_function,
+					&fvec))
+		return 0;
+
+	      if (fvec.count > 0)
+		{
+		  struct function_addrs *faddrs;
+
+		  if (!backtrace_vector_release (state, &fvec.vec,
+						 error_callback, data))
+		    return 0;
+
+		  faddrs = (struct function_addrs *) fvec.vec.base;
+		  backtrace_qsort (faddrs, fvec.count,
+				   sizeof (struct function_addrs),
+				   function_addrs_compare);
+
+		  function->function_addrs = faddrs;
+		  function->function_addrs_count = fvec.count;
+		}
+	    }
+	}
+    }
+
+  return 1;
+}
+
+/* Read function name information for a compilation unit.  We look
+   through the whole unit looking for function tags.  */
+
+static void
+read_function_info (struct backtrace_state *state, struct dwarf_data *ddata,
+		    const struct line_header *lhdr,
+		    backtrace_error_callback error_callback, void *data,
+		    struct unit *u, struct function_vector *fvec,
+		    struct function_addrs **ret_addrs,
+		    size_t *ret_addrs_count)
+{
+  struct function_vector lvec;
+  struct function_vector *pfvec;
+  struct dwarf_buf unit_buf;
+  struct function_addrs *addrs;
+  size_t addrs_count;
+
+  /* Use FVEC if it is not NULL.  Otherwise use our own vector.  */
+  if (fvec != NULL)
+    pfvec = fvec;
+  else
+    {
+      memset (&lvec, 0, sizeof lvec);
+      pfvec = &lvec;
+    }
+
+  unit_buf.name = ".debug_info";
+  unit_buf.start = ddata->dwarf_info;
+  unit_buf.buf = u->unit_data;
+  unit_buf.left = u->unit_data_len;
+  unit_buf.is_bigendian = ddata->is_bigendian;
+  unit_buf.error_callback = error_callback;
+  unit_buf.data = data;
+  unit_buf.reported_underflow = 0;
+
+  while (unit_buf.left > 0)
+    {
+      if (!read_function_entry (state, ddata, u, 0, &unit_buf, lhdr,
+				error_callback, data, pfvec, pfvec))
+	return;
+    }
+
+  if (pfvec->count == 0)
+    return;
+
+  addrs_count = pfvec->count;
+
+  if (fvec == NULL)
+    {
+      if (!backtrace_vector_release (state, &lvec.vec, error_callback, data))
+	return;
+      addrs = (struct function_addrs *) pfvec->vec.base;
+    }
+  else
+    {
+      /* Finish this list of addresses, but leave the remaining space in
+	 the vector available for the next function unit.  */
+      addrs = ((struct function_addrs *)
+	       backtrace_vector_finish (state, &fvec->vec,
+					error_callback, data));
+      if (addrs == NULL)
+	return;
+      fvec->count = 0;
+    }
+
+  backtrace_qsort (addrs, addrs_count, sizeof (struct function_addrs),
+		   function_addrs_compare);
+
+  *ret_addrs = addrs;
+  *ret_addrs_count = addrs_count;
+}
+
+/* See if PC is inlined in FUNCTION.  If it is, print out the inlined
+   information, and update FILENAME and LINENO for the caller.
+   Returns whatever CALLBACK returns, or 0 to keep going.  */
+
+static int
+report_inlined_functions (uintptr_t pc, struct function *function,
+			  backtrace_full_callback callback, void *data,
+			  const char **filename, int *lineno)
+{
+  struct function_addrs *function_addrs;
+  struct function *inlined;
+  int ret;
+
+  if (function->function_addrs_count == 0)
+    return 0;
+
+  function_addrs = ((struct function_addrs *)
+		    bsearch (&pc, function->function_addrs,
+			     function->function_addrs_count,
+			     sizeof (struct function_addrs),
+			     function_addrs_search));
+  if (function_addrs == NULL)
+    return 0;
+
+  while (((size_t) (function_addrs - function->function_addrs) + 1
+	  < function->function_addrs_count)
+	 && pc >= (function_addrs + 1)->low
+	 && pc < (function_addrs + 1)->high)
+    ++function_addrs;
+
+  /* We found an inlined call.  */
+
+  inlined = function_addrs->function;
+
+  /* Report any calls inlined into this one.  */
+  ret = report_inlined_functions (pc, inlined, callback, data,
+				  filename, lineno);
+  if (ret != 0)
+    return ret;
+
+  /* Report this inlined call.  */
+  ret = callback (data, pc, *filename, *lineno, inlined->name);
+  if (ret != 0)
+    return ret;
+
+  /* Our caller will report the caller of the inlined function; tell
+     it the appropriate filename and line number.  */
+  *filename = inlined->caller_filename;
+  *lineno = inlined->caller_lineno;
+
+  return 0;
+}
+
+/* Look for a PC in the DWARF mapping for one module.  On success,
+   call CALLBACK and return whatever it returns.  On error, call
+   ERROR_CALLBACK and return 0.  Sets *FOUND to 1 if the PC is found,
+   0 if not.  */
+
+static int
+dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
+		 uintptr_t pc, backtrace_full_callback callback,
+		 backtrace_error_callback error_callback, void *data,
+		 int *found)
+{
+  struct unit_addrs *entry;
+  struct unit *u;
+  int new_data;
+  struct line *lines;
+  struct line *ln;
+  struct function_addrs *function_addrs;
+  struct function *function;
+  const char *filename;
+  int lineno;
+  int ret;
+
+  *found = 1;
+
+  /* Find an address range that includes PC.  */
+  entry = bsearch (&pc, ddata->addrs, ddata->addrs_count,
+		   sizeof (struct unit_addrs), unit_addrs_search);
+
+  if (entry == NULL)
+    {
+      *found = 0;
+      return 0;
+    }
+
+  /* If there are multiple ranges that contain PC, use the last one,
+     in order to produce predictable results.  If we assume that all
+     ranges are properly nested, then the last range will be the
+     smallest one.  */
+  while ((size_t) (entry - ddata->addrs) + 1 < ddata->addrs_count
+	 && pc >= (entry + 1)->low
+	 && pc < (entry + 1)->high)
+    ++entry;
+
+  /* We need the lines, lines_count, function_addrs,
+     function_addrs_count fields of u.  If they are not set, we need
+     to set them.  When running in threaded mode, we need to allow for
+     the possibility that some other thread is setting them
+     simultaneously.  */
+
+  u = entry->u;
+  lines = u->lines;
+
+  /* Skip units with no useful line number information by walking
+     backward.  Useless line number information is marked by setting
+     lines == -1.  */
+  while (entry > ddata->addrs
+	 && pc >= (entry - 1)->low
+	 && pc < (entry - 1)->high)
+    {
+      if (state->threaded)
+	lines = (struct line *) backtrace_atomic_load_pointer (&u->lines);
+
+      if (lines != (struct line *) (uintptr_t) -1)
+	break;
+
+      --entry;
+
+      u = entry->u;
+      lines = u->lines;
+    }
+
+  if (state->threaded)
+    lines = backtrace_atomic_load_pointer (&u->lines);
+
+  new_data = 0;
+  if (lines == NULL)
+    {
+      size_t function_addrs_count;
+      struct line_header lhdr;
+      size_t count;
+
+      /* We have never read the line information for this unit.  Read
+	 it now.  */
+
+      function_addrs = NULL;
+      function_addrs_count = 0;
+      if (read_line_info (state, ddata, error_callback, data, entry->u, &lhdr,
+			  &lines, &count))
+	{
+	  struct function_vector *pfvec;
+
+	  /* If not threaded, reuse DDATA->FVEC for better memory
+	     consumption.  */
+	  if (state->threaded)
+	    pfvec = NULL;
+	  else
+	    pfvec = &ddata->fvec;
+	  read_function_info (state, ddata, &lhdr, error_callback, data,
+			      entry->u, pfvec, &function_addrs,
+			      &function_addrs_count);
+	  free_line_header (state, &lhdr, error_callback, data);
+	  new_data = 1;
+	}
+
+      /* Atomically store the information we just read into the unit.
+	 If another thread is simultaneously writing, it presumably
+	 read the same information, and we don't care which one we
+	 wind up with; we just leak the other one.  We do have to
+	 write the lines field last, so that the acquire-loads above
+	 ensure that the other fields are set.  */
+
+      if (!state->threaded)
+	{
+	  u->lines_count = count;
+	  u->function_addrs = function_addrs;
+	  u->function_addrs_count = function_addrs_count;
+	  u->lines = lines;
+	}
+      else
+	{
+	  backtrace_atomic_store_size_t (&u->lines_count, count);
+	  backtrace_atomic_store_pointer (&u->function_addrs, function_addrs);
+	  backtrace_atomic_store_size_t (&u->function_addrs_count,
+					 function_addrs_count);
+	  backtrace_atomic_store_pointer (&u->lines, lines);
+	}
+    }
+
+  /* Now all fields of U have been initialized.  */
+
+  if (lines == (struct line *) (uintptr_t) -1)
+    {
+      /* If reading the line number information failed in some way,
+	 try again to see if there is a better compilation unit for
+	 this PC.  */
+      if (new_data)
+	return dwarf_lookup_pc (state, ddata, pc, callback, error_callback,
+				data, found);
+      return callback (data, pc, NULL, 0, NULL);
+    }
+
+  /* Search for PC within this unit.  */
+
+  ln = (struct line *) bsearch (&pc, lines, entry->u->lines_count,
+				sizeof (struct line), line_search);
+  if (ln == NULL)
+    {
+      /* The PC is between the low_pc and high_pc attributes of the
+	 compilation unit, but no entry in the line table covers it.
+	 This implies that the start of the compilation unit has no
+	 line number information.  */
+
+      if (entry->u->abs_filename == NULL)
+	{
+	  const char *filename;
+
+	  filename = entry->u->filename;
+	  if (filename != NULL
+	      && !IS_ABSOLUTE_PATH (filename)
+	      && entry->u->comp_dir != NULL)
+	    {
+	      size_t filename_len;
+	      const char *dir;
+	      size_t dir_len;
+	      char *s;
+
+	      filename_len = strlen (filename);
+	      dir = entry->u->comp_dir;
+	      dir_len = strlen (dir);
+	      s = (char *) backtrace_alloc (state, dir_len + filename_len + 2,
+					    error_callback, data);
+	      if (s == NULL)
+		{
+		  *found = 0;
+		  return 0;
+		}
+	      memcpy (s, dir, dir_len);
+	      /* FIXME: Should use backslash if DOS file system.  */
+	      s[dir_len] = '/';
+	      memcpy (s + dir_len + 1, filename, filename_len + 1);
+	      filename = s;
+	    }
+	  entry->u->abs_filename = filename;
+	}
+
+      return callback (data, pc, entry->u->abs_filename, 0, NULL);
+    }
+
+  /* Search for function name within this unit.  */
+
+  if (entry->u->function_addrs_count == 0)
+    return callback (data, pc, ln->filename, ln->lineno, NULL);
+
+  function_addrs = ((struct function_addrs *)
+		    bsearch (&pc, entry->u->function_addrs,
+			     entry->u->function_addrs_count,
+			     sizeof (struct function_addrs),
+			     function_addrs_search));
+  if (function_addrs == NULL)
+    return callback (data, pc, ln->filename, ln->lineno, NULL);
+
+  /* If there are multiple function ranges that contain PC, use the
+     last one, in order to produce predictable results.  */
+
+  while (((size_t) (function_addrs - entry->u->function_addrs + 1)
+	  < entry->u->function_addrs_count)
+	 && pc >= (function_addrs + 1)->low
+	 && pc < (function_addrs + 1)->high)
+    ++function_addrs;
+
+  function = function_addrs->function;
+
+  filename = ln->filename;
+  lineno = ln->lineno;
+
+  ret = report_inlined_functions (pc, function, callback, data,
+				  &filename, &lineno);
+  if (ret != 0)
+    return ret;
+
+  return callback (data, pc, filename, lineno, function->name);
+}
+
+
+/* Return the file/line information for a PC using the DWARF mapping
+   we built earlier.  */
+
+static int
+dwarf_fileline (struct backtrace_state *state, uintptr_t pc,
+		backtrace_full_callback callback,
+		backtrace_error_callback error_callback, void *data)
+{
+  struct dwarf_data *ddata;
+  int found;
+  int ret;
+
+  if (!state->threaded)
+    {
+      for (ddata = (struct dwarf_data *) state->fileline_data;
+	   ddata != NULL;
+	   ddata = ddata->next)
+	{
+	  ret = dwarf_lookup_pc (state, ddata, pc, callback, error_callback,
+				 data, &found);
+	  if (ret != 0 || found)
+	    return ret;
+	}
+    }
+  else
+    {
+      struct dwarf_data **pp;
+
+      pp = (struct dwarf_data **) (void *) &state->fileline_data;
+      while (1)
+	{
+	  ddata = backtrace_atomic_load_pointer (pp);
+	  if (ddata == NULL)
+	    break;
+
+	  ret = dwarf_lookup_pc (state, ddata, pc, callback, error_callback,
+				 data, &found);
+	  if (ret != 0 || found)
+	    return ret;
+
+	  pp = &ddata->next;
+	}
+    }
+
+  /* FIXME: See if any libraries have been dlopen'ed.  */
+
+  return callback (data, pc, NULL, 0, NULL);
+}
+
+/* Initialize our data structures from the DWARF debug info for a
+   file.  Return NULL on failure.  */
+
+static struct dwarf_data *
+build_dwarf_data (struct backtrace_state *state,
+		  uintptr_t base_address,
+		  const unsigned char *dwarf_info,
+		  size_t dwarf_info_size,
+		  const unsigned char *dwarf_line,
+		  size_t dwarf_line_size,
+		  const unsigned char *dwarf_abbrev,
+		  size_t dwarf_abbrev_size,
+		  const unsigned char *dwarf_ranges,
+		  size_t dwarf_ranges_size,
+		  const unsigned char *dwarf_str,
+		  size_t dwarf_str_size,
+		  int is_bigendian,
+		  backtrace_error_callback error_callback,
+		  void *data)
+{
+  struct unit_addrs_vector addrs_vec;
+  struct unit_addrs *addrs;
+  size_t addrs_count;
+  struct dwarf_data *fdata;
+
+  if (!build_address_map (state, base_address, dwarf_info, dwarf_info_size,
+			  dwarf_abbrev, dwarf_abbrev_size, dwarf_ranges,
+			  dwarf_ranges_size, dwarf_str, dwarf_str_size,
+			  is_bigendian, error_callback, data, &addrs_vec))
+    return NULL;
+
+  if (!backtrace_vector_release (state, &addrs_vec.vec, error_callback, data))
+    return NULL;
+  addrs = (struct unit_addrs *) addrs_vec.vec.base;
+  addrs_count = addrs_vec.count;
+  backtrace_qsort (addrs, addrs_count, sizeof (struct unit_addrs),
+		   unit_addrs_compare);
+
+  fdata = ((struct dwarf_data *)
+	   backtrace_alloc (state, sizeof (struct dwarf_data),
+			    error_callback, data));
+  if (fdata == NULL)
+    return NULL;
+
+  fdata->next = NULL;
+  fdata->base_address = base_address;
+  fdata->addrs = addrs;
+  fdata->addrs_count = addrs_count;
+  fdata->dwarf_info = dwarf_info;
+  fdata->dwarf_info_size = dwarf_info_size;
+  fdata->dwarf_line = dwarf_line;
+  fdata->dwarf_line_size = dwarf_line_size;
+  fdata->dwarf_ranges = dwarf_ranges;
+  fdata->dwarf_ranges_size = dwarf_ranges_size;
+  fdata->dwarf_str = dwarf_str;
+  fdata->dwarf_str_size = dwarf_str_size;
+  fdata->is_bigendian = is_bigendian;
+  memset (&fdata->fvec, 0, sizeof fdata->fvec);
+
+  return fdata;
+}
+
+/* Build our data structures from the DWARF sections for a module.
+   Set FILELINE_FN and STATE->FILELINE_DATA.  Return 1 on success, 0
+   on failure.  */
+
+int
+backtrace_dwarf_add (struct backtrace_state *state,
+		     uintptr_t base_address,
+		     const unsigned char *dwarf_info,
+		     size_t dwarf_info_size,
+		     const unsigned char *dwarf_line,
+		     size_t dwarf_line_size,
+		     const unsigned char *dwarf_abbrev,
+		     size_t dwarf_abbrev_size,
+		     const unsigned char *dwarf_ranges,
+		     size_t dwarf_ranges_size,
+		     const unsigned char *dwarf_str,
+		     size_t dwarf_str_size,
+		     int is_bigendian,
+		     backtrace_error_callback error_callback,
+		     void *data, fileline *fileline_fn)
+{
+  struct dwarf_data *fdata;
+
+  fdata = build_dwarf_data (state, base_address, dwarf_info, dwarf_info_size,
+			    dwarf_line, dwarf_line_size, dwarf_abbrev,
+			    dwarf_abbrev_size, dwarf_ranges, dwarf_ranges_size,
+			    dwarf_str, dwarf_str_size, is_bigendian,
+			    error_callback, data);
+  if (fdata == NULL)
+    return 0;
+
+  if (!state->threaded)
+    {
+      struct dwarf_data **pp;
+
+      for (pp = (struct dwarf_data **) (void *) &state->fileline_data;
+	   *pp != NULL;
+	   pp = &(*pp)->next)
+	;
+      *pp = fdata;
+    }
+  else
+    {
+      while (1)
+	{
+	  struct dwarf_data **pp;
+
+	  pp = (struct dwarf_data **) (void *) &state->fileline_data;
+
+	  while (1)
+	    {
+	      struct dwarf_data *p;
+
+	      p = backtrace_atomic_load_pointer (pp);
+
+	      if (p == NULL)
+		break;
+
+	      pp = &p->next;
+	    }
+
+	  if (__sync_bool_compare_and_swap (pp, NULL, fdata))
+	    break;
+	}
+    }
+
+  *fileline_fn = dwarf_fileline;
+
+  return 1;
+}
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/edtest.c b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/edtest.c
new file mode 100644
index 0000000..3a2cac41
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/edtest.c
@@ -0,0 +1,121 @@
+/* edtest.c -- Test for libbacktrace storage allocation stress handling
+   Copyright (C) 2017-2018 Free Software Foundation, Inc.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "backtrace.h"
+#include "backtrace-supported.h"
+#include "internal.h"
+
+#include "testlib.h"
+
+static int test1 (void) __attribute__ ((noinline, unused));
+static int test1 (void) __attribute__ ((noinline, unused));
+extern int f2 (int);
+extern int f3 (int, int);
+
+static int
+test1 (void)
+{
+  /* Returning a value here and elsewhere avoids a tailcall which
+     would mess up the backtrace.  */
+  return f2 (__LINE__) + 1;
+}
+
+int
+f3 (int f1line, int f2line)
+{
+  struct info all[20];
+  struct bdata data;
+  int f3line;
+  int i;
+
+  data.all = &all[0];
+  data.index = 0;
+  data.max = 20;
+  data.failed = 0;
+
+  f3line = __LINE__ + 1;
+  i = backtrace_full (state, 0, callback_one, error_callback_one, &data);
+
+  if (i != 0)
+    {
+      fprintf (stderr, "test1: unexpected return value %d\n", i);
+      data.failed = 1;
+    }
+
+  if (data.index < 3)
+    {
+      fprintf (stderr,
+               "test1: not enough frames; got %zu, expected at least 3\n",
+               data.index);
+      data.failed = 1;
+    }
+
+  check ("test1", 0, all, f3line, "f3", "edtest.c", &data.failed);
+  check ("test1", 1, all, f2line, "f2", "edtest2_build.c", &data.failed);
+  check ("test1", 2, all, f1line, "test1", "edtest.c", &data.failed);
+
+  printf ("%s: backtrace_full alloc stress\n", data.failed ? "FAIL" : "PASS");
+
+  if (data.failed)
+    ++failures;
+
+  return failures;
+}
+
+int
+main (int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
+{
+  state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,
+                                  error_callback_create, NULL);
+
+  // Grab the storage allocation lock prior to doing anything interesting.
+  // The intent here is to insure that the backtrace_alloc code is forced
+  // to always call mmap() for new memory as opposed to reusing previously
+  // allocated memory from the free list. Doing things this way helps
+  // simulate what you might see in a multithreaded program in which there
+  // are racing calls to the allocator.
+  struct backtrace_state *state_internal =
+      (struct backtrace_state *) state;
+  state_internal->lock_alloc = 1;
+
+  // Kick off the test
+  test1();
+
+  exit (failures > 0 ? EXIT_FAILURE : EXIT_SUCCESS);
+}
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/edtest2.c b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/edtest2.c
new file mode 100644
index 0000000..e0c0470
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/edtest2.c
@@ -0,0 +1,43 @@
+/* edtest2.c -- Test for libbacktrace storage allocation stress handling (p2)
+   Copyright (C) 2017-2018 Free Software Foundation, Inc.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+/* This file intentionally written without any #include's
+ */
+
+extern int f3(int, int);
+extern int f2(int);
+
+int f2(int x)
+{
+  /* Returning a value here and elsewhere avoids a tailcall which
+     would mess up the backtrace.  */
+  return f3(x, __LINE__) + 3;
+}
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/elf.c b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/elf.c
new file mode 100644
index 0000000..0fd5e6f
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/elf.c
@@ -0,0 +1,3340 @@
+/* elf.c -- Get debug data from an ELF file for backtraces.
+   Copyright (C) 2012-2018 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#ifdef HAVE_DL_ITERATE_PHDR
+#include <link.h>
+#endif
+
+#include "backtrace.h"
+#include "internal.h"
+
+#ifndef S_ISLNK
+ #ifndef S_IFLNK
+  #define S_IFLNK 0120000
+ #endif
+ #ifndef S_IFMT
+  #define S_IFMT 0170000
+ #endif
+ #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+#endif
+
+#ifndef __GNUC__
+#define __builtin_prefetch(p, r, l)
+#define unlikely(x) (x)
+#else
+#define unlikely(x) __builtin_expect(!!(x), 0)
+#endif
+
+#if !defined(HAVE_DECL_STRNLEN) || !HAVE_DECL_STRNLEN
+
+/* If strnlen is not declared, provide our own version.  */
+
+static size_t
+xstrnlen (const char *s, size_t maxlen)
+{
+  size_t i;
+
+  for (i = 0; i < maxlen; ++i)
+    if (s[i] == '\0')
+      break;
+  return i;
+}
+
+#define strnlen xstrnlen
+
+#endif
+
+#ifndef HAVE_LSTAT
+
+/* Dummy version of lstat for systems that don't have it.  */
+
+static int
+xlstat (const char *path ATTRIBUTE_UNUSED, struct stat *st ATTRIBUTE_UNUSED)
+{
+  return -1;
+}
+
+#define lstat xlstat
+
+#endif
+
+#ifndef HAVE_READLINK
+
+/* Dummy version of readlink for systems that don't have it.  */
+
+static ssize_t
+xreadlink (const char *path ATTRIBUTE_UNUSED, char *buf ATTRIBUTE_UNUSED,
+	   size_t bufsz ATTRIBUTE_UNUSED)
+{
+  return -1;
+}
+
+#define readlink xreadlink
+
+#endif
+
+#ifndef HAVE_DL_ITERATE_PHDR
+
+/* Dummy version of dl_iterate_phdr for systems that don't have it.  */
+
+#define dl_phdr_info x_dl_phdr_info
+#define dl_iterate_phdr x_dl_iterate_phdr
+
+struct dl_phdr_info
+{
+  uintptr_t dlpi_addr;
+  const char *dlpi_name;
+};
+
+static int
+dl_iterate_phdr (int (*callback) (struct dl_phdr_info *,
+				  size_t, void *) ATTRIBUTE_UNUSED,
+		 void *data ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
+
+#endif /* ! defined (HAVE_DL_ITERATE_PHDR) */
+
+/* The configure script must tell us whether we are 32-bit or 64-bit
+   ELF.  We could make this code test and support either possibility,
+   but there is no point.  This code only works for the currently
+   running executable, which means that we know the ELF mode at
+   configure time.  */
+
+#if BACKTRACE_ELF_SIZE != 32 && BACKTRACE_ELF_SIZE != 64
+#error "Unknown BACKTRACE_ELF_SIZE"
+#endif
+
+/* <link.h> might #include <elf.h> which might define our constants
+   with slightly different values.  Undefine them to be safe.  */
+
+#undef EI_NIDENT
+#undef EI_MAG0
+#undef EI_MAG1
+#undef EI_MAG2
+#undef EI_MAG3
+#undef EI_CLASS
+#undef EI_DATA
+#undef EI_VERSION
+#undef ELF_MAG0
+#undef ELF_MAG1
+#undef ELF_MAG2
+#undef ELF_MAG3
+#undef ELFCLASS32
+#undef ELFCLASS64
+#undef ELFDATA2LSB
+#undef ELFDATA2MSB
+#undef EV_CURRENT
+#undef ET_DYN
+#undef EM_PPC64
+#undef EF_PPC64_ABI
+#undef SHN_LORESERVE
+#undef SHN_XINDEX
+#undef SHN_UNDEF
+#undef SHT_PROGBITS
+#undef SHT_SYMTAB
+#undef SHT_STRTAB
+#undef SHT_DYNSYM
+#undef SHF_COMPRESSED
+#undef STT_OBJECT
+#undef STT_FUNC
+#undef NT_GNU_BUILD_ID
+#undef ELFCOMPRESS_ZLIB
+
+/* Basic types.  */
+
+typedef uint16_t b_elf_half;    /* Elf_Half.  */
+typedef uint32_t b_elf_word;    /* Elf_Word.  */
+typedef int32_t  b_elf_sword;   /* Elf_Sword.  */
+
+#if BACKTRACE_ELF_SIZE == 32
+
+typedef uint32_t b_elf_addr;    /* Elf_Addr.  */
+typedef uint32_t b_elf_off;     /* Elf_Off.  */
+
+typedef uint32_t b_elf_wxword;  /* 32-bit Elf_Word, 64-bit ELF_Xword.  */
+
+#else
+
+typedef uint64_t b_elf_addr;    /* Elf_Addr.  */
+typedef uint64_t b_elf_off;     /* Elf_Off.  */
+typedef uint64_t b_elf_xword;   /* Elf_Xword.  */
+typedef int64_t  b_elf_sxword;  /* Elf_Sxword.  */
+
+typedef uint64_t b_elf_wxword;  /* 32-bit Elf_Word, 64-bit ELF_Xword.  */
+
+#endif
+
+/* Data structures and associated constants.  */
+
+#define EI_NIDENT 16
+
+typedef struct {
+  unsigned char	e_ident[EI_NIDENT];	/* ELF "magic number" */
+  b_elf_half	e_type;			/* Identifies object file type */
+  b_elf_half	e_machine;		/* Specifies required architecture */
+  b_elf_word	e_version;		/* Identifies object file version */
+  b_elf_addr	e_entry;		/* Entry point virtual address */
+  b_elf_off	e_phoff;		/* Program header table file offset */
+  b_elf_off	e_shoff;		/* Section header table file offset */
+  b_elf_word	e_flags;		/* Processor-specific flags */
+  b_elf_half	e_ehsize;		/* ELF header size in bytes */
+  b_elf_half	e_phentsize;		/* Program header table entry size */
+  b_elf_half	e_phnum;		/* Program header table entry count */
+  b_elf_half	e_shentsize;		/* Section header table entry size */
+  b_elf_half	e_shnum;		/* Section header table entry count */
+  b_elf_half	e_shstrndx;		/* Section header string table index */
+} b_elf_ehdr;  /* Elf_Ehdr.  */
+
+#define EI_MAG0 0
+#define EI_MAG1 1
+#define EI_MAG2 2
+#define EI_MAG3 3
+#define EI_CLASS 4
+#define EI_DATA 5
+#define EI_VERSION 6
+
+#define ELFMAG0 0x7f
+#define ELFMAG1 'E'
+#define ELFMAG2 'L'
+#define ELFMAG3 'F'
+
+#define ELFCLASS32 1
+#define ELFCLASS64 2
+
+#define ELFDATA2LSB 1
+#define ELFDATA2MSB 2
+
+#define EV_CURRENT 1
+
+#define ET_DYN 3
+
+#define EM_PPC64 21
+#define EF_PPC64_ABI 3
+
+typedef struct {
+  b_elf_word	sh_name;		/* Section name, index in string tbl */
+  b_elf_word	sh_type;		/* Type of section */
+  b_elf_wxword	sh_flags;		/* Miscellaneous section attributes */
+  b_elf_addr	sh_addr;		/* Section virtual addr at execution */
+  b_elf_off	sh_offset;		/* Section file offset */
+  b_elf_wxword	sh_size;		/* Size of section in bytes */
+  b_elf_word	sh_link;		/* Index of another section */
+  b_elf_word	sh_info;		/* Additional section information */
+  b_elf_wxword	sh_addralign;		/* Section alignment */
+  b_elf_wxword	sh_entsize;		/* Entry size if section holds table */
+} b_elf_shdr;  /* Elf_Shdr.  */
+
+#define SHN_UNDEF	0x0000		/* Undefined section */
+#define SHN_LORESERVE	0xFF00		/* Begin range of reserved indices */
+#define SHN_XINDEX	0xFFFF		/* Section index is held elsewhere */
+
+#define SHT_PROGBITS 1
+#define SHT_SYMTAB 2
+#define SHT_STRTAB 3
+#define SHT_DYNSYM 11
+
+#define SHF_COMPRESSED 0x800
+
+#if BACKTRACE_ELF_SIZE == 32
+
+typedef struct
+{
+  b_elf_word	st_name;		/* Symbol name, index in string tbl */
+  b_elf_addr	st_value;		/* Symbol value */
+  b_elf_word	st_size;		/* Symbol size */
+  unsigned char	st_info;		/* Symbol binding and type */
+  unsigned char	st_other;		/* Visibility and other data */
+  b_elf_half	st_shndx;		/* Symbol section index */
+} b_elf_sym;  /* Elf_Sym.  */
+
+#else /* BACKTRACE_ELF_SIZE != 32 */
+
+typedef struct
+{
+  b_elf_word	st_name;		/* Symbol name, index in string tbl */
+  unsigned char	st_info;		/* Symbol binding and type */
+  unsigned char	st_other;		/* Visibility and other data */
+  b_elf_half	st_shndx;		/* Symbol section index */
+  b_elf_addr	st_value;		/* Symbol value */
+  b_elf_xword	st_size;		/* Symbol size */
+} b_elf_sym;  /* Elf_Sym.  */
+
+#endif /* BACKTRACE_ELF_SIZE != 32 */
+
+#define STT_OBJECT 1
+#define STT_FUNC 2
+
+typedef struct
+{
+  uint32_t namesz;
+  uint32_t descsz;
+  uint32_t type;
+  char name[1];
+} b_elf_note;
+
+#define NT_GNU_BUILD_ID 3
+
+#if BACKTRACE_ELF_SIZE == 32
+
+typedef struct
+{
+  b_elf_word	ch_type;		/* Compresstion algorithm */
+  b_elf_word	ch_size;		/* Uncompressed size */
+  b_elf_word	ch_addralign;		/* Alignment for uncompressed data */
+} b_elf_chdr;  /* Elf_Chdr */
+
+#else /* BACKTRACE_ELF_SIZE != 32 */
+
+typedef struct
+{
+  b_elf_word	ch_type;		/* Compression algorithm */
+  b_elf_word	ch_reserved;		/* Reserved */
+  b_elf_xword	ch_size;		/* Uncompressed size */
+  b_elf_xword	ch_addralign;		/* Alignment for uncompressed data */
+} b_elf_chdr;  /* Elf_Chdr */
+
+#endif /* BACKTRACE_ELF_SIZE != 32 */
+
+#define ELFCOMPRESS_ZLIB 1
+
+/* An index of ELF sections we care about.  */
+
+enum debug_section
+{
+  DEBUG_INFO,
+  DEBUG_LINE,
+  DEBUG_ABBREV,
+  DEBUG_RANGES,
+  DEBUG_STR,
+
+  /* The old style compressed sections.  This list must correspond to
+     the list of normal debug sections.  */
+  ZDEBUG_INFO,
+  ZDEBUG_LINE,
+  ZDEBUG_ABBREV,
+  ZDEBUG_RANGES,
+  ZDEBUG_STR,
+
+  DEBUG_MAX
+};
+
+/* Names of sections, indexed by enum elf_section.  */
+
+static const char * const debug_section_names[DEBUG_MAX] =
+{
+  ".debug_info",
+  ".debug_line",
+  ".debug_abbrev",
+  ".debug_ranges",
+  ".debug_str",
+  ".zdebug_info",
+  ".zdebug_line",
+  ".zdebug_abbrev",
+  ".zdebug_ranges",
+  ".zdebug_str"
+};
+
+/* Information we gather for the sections we care about.  */
+
+struct debug_section_info
+{
+  /* Section file offset.  */
+  off_t offset;
+  /* Section size.  */
+  size_t size;
+  /* Section contents, after read from file.  */
+  const unsigned char *data;
+  /* Whether the SHF_COMPRESSED flag is set for the section.  */
+  int compressed;
+};
+
+/* Information we keep for an ELF symbol.  */
+
+struct elf_symbol
+{
+  /* The name of the symbol.  */
+  const char *name;
+  /* The address of the symbol.  */
+  uintptr_t address;
+  /* The size of the symbol.  */
+  size_t size;
+};
+
+/* Information to pass to elf_syminfo.  */
+
+struct elf_syminfo_data
+{
+  /* Symbols for the next module.  */
+  struct elf_syminfo_data *next;
+  /* The ELF symbols, sorted by address.  */
+  struct elf_symbol *symbols;
+  /* The number of symbols.  */
+  size_t count;
+};
+
+/* Information about PowerPC64 ELFv1 .opd section.  */
+
+struct elf_ppc64_opd_data
+{
+  /* Address of the .opd section.  */
+  b_elf_addr addr;
+  /* Section data.  */
+  const char *data;
+  /* Size of the .opd section.  */
+  size_t size;
+  /* Corresponding section view.  */
+  struct backtrace_view view;
+};
+
+/* Compute the CRC-32 of BUF/LEN.  This uses the CRC used for
+   .gnu_debuglink files.  */
+
+static uint32_t
+elf_crc32 (uint32_t crc, const unsigned char *buf, size_t len)
+{
+  static const uint32_t crc32_table[256] =
+    {
+      0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
+      0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
+      0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
+      0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+      0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
+      0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+      0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
+      0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+      0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
+      0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
+      0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
+      0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+      0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
+      0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
+      0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
+      0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+      0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
+      0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+      0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
+      0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+      0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+      0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
+      0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
+      0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+      0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
+      0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
+      0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
+      0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+      0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
+      0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+      0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
+      0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+      0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
+      0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
+      0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+      0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+      0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
+      0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
+      0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
+      0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+      0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
+      0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+      0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
+      0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+      0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
+      0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
+      0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
+      0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+      0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
+      0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
+      0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
+      0x2d02ef8d
+    };
+  const unsigned char *end;
+
+  crc = ~crc;
+  for (end = buf + len; buf < end; ++ buf)
+    crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
+  return ~crc;
+}
+
+/* Return the CRC-32 of the entire file open at DESCRIPTOR.  */
+
+static uint32_t
+elf_crc32_file (struct backtrace_state *state, int descriptor,
+		backtrace_error_callback error_callback, void *data)
+{
+  struct stat st;
+  struct backtrace_view file_view;
+  uint32_t ret;
+
+  if (fstat (descriptor, &st) < 0)
+    {
+      error_callback (data, "fstat", errno);
+      return 0;
+    }
+
+  if (!backtrace_get_view (state, descriptor, 0, st.st_size, error_callback,
+			   data, &file_view))
+    return 0;
+
+  ret = elf_crc32 (0, (const unsigned char *) file_view.data, st.st_size);
+
+  backtrace_release_view (state, &file_view, error_callback, data);
+
+  return ret;
+}
+
+/* A dummy callback function used when we can't find any debug info.  */
+
+static int
+elf_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
+	     uintptr_t pc ATTRIBUTE_UNUSED,
+	     backtrace_full_callback callback ATTRIBUTE_UNUSED,
+	     backtrace_error_callback error_callback, void *data)
+{
+  error_callback (data, "no debug info in ELF executable", -1);
+  return 0;
+}
+
+/* A dummy callback function used when we can't find a symbol
+   table.  */
+
+static void
+elf_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,
+	    uintptr_t addr ATTRIBUTE_UNUSED,
+	    backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,
+	    backtrace_error_callback error_callback, void *data)
+{
+  error_callback (data, "no symbol table in ELF executable", -1);
+}
+
+/* Compare struct elf_symbol for qsort.  */
+
+static int
+elf_symbol_compare (const void *v1, const void *v2)
+{
+  const struct elf_symbol *e1 = (const struct elf_symbol *) v1;
+  const struct elf_symbol *e2 = (const struct elf_symbol *) v2;
+
+  if (e1->address < e2->address)
+    return -1;
+  else if (e1->address > e2->address)
+    return 1;
+  else
+    return 0;
+}
+
+/* Compare an ADDR against an elf_symbol for bsearch.  We allocate one
+   extra entry in the array so that this can look safely at the next
+   entry.  */
+
+static int
+elf_symbol_search (const void *vkey, const void *ventry)
+{
+  const uintptr_t *key = (const uintptr_t *) vkey;
+  const struct elf_symbol *entry = (const struct elf_symbol *) ventry;
+  uintptr_t addr;
+
+  addr = *key;
+  if (addr < entry->address)
+    return -1;
+  else if (addr >= entry->address + entry->size)
+    return 1;
+  else
+    return 0;
+}
+
+/* Initialize the symbol table info for elf_syminfo.  */
+
+static int
+elf_initialize_syminfo (struct backtrace_state *state,
+			uintptr_t base_address,
+			const unsigned char *symtab_data, size_t symtab_size,
+			const unsigned char *strtab, size_t strtab_size,
+			backtrace_error_callback error_callback,
+			void *data, struct elf_syminfo_data *sdata,
+			struct elf_ppc64_opd_data *opd)
+{
+  size_t sym_count;
+  const b_elf_sym *sym;
+  size_t elf_symbol_count;
+  size_t elf_symbol_size;
+  struct elf_symbol *elf_symbols;
+  size_t i;
+  unsigned int j;
+
+  sym_count = symtab_size / sizeof (b_elf_sym);
+
+  /* We only care about function symbols.  Count them.  */
+  sym = (const b_elf_sym *) symtab_data;
+  elf_symbol_count = 0;
+  for (i = 0; i < sym_count; ++i, ++sym)
+    {
+      int info;
+
+      info = sym->st_info & 0xf;
+      if ((info == STT_FUNC || info == STT_OBJECT)
+	  && sym->st_shndx != SHN_UNDEF)
+	++elf_symbol_count;
+    }
+
+  elf_symbol_size = elf_symbol_count * sizeof (struct elf_symbol);
+  elf_symbols = ((struct elf_symbol *)
+		 backtrace_alloc (state, elf_symbol_size, error_callback,
+				  data));
+  if (elf_symbols == NULL)
+    return 0;
+
+  sym = (const b_elf_sym *) symtab_data;
+  j = 0;
+  for (i = 0; i < sym_count; ++i, ++sym)
+    {
+      int info;
+
+      info = sym->st_info & 0xf;
+      if (info != STT_FUNC && info != STT_OBJECT)
+	continue;
+      if (sym->st_shndx == SHN_UNDEF)
+	continue;
+      if (sym->st_name >= strtab_size)
+	{
+	  error_callback (data, "symbol string index out of range", 0);
+	  backtrace_free (state, elf_symbols, elf_symbol_size, error_callback,
+			  data);
+	  return 0;
+	}
+      elf_symbols[j].name = (const char *) strtab + sym->st_name;
+      /* Special case PowerPC64 ELFv1 symbols in .opd section, if the symbol
+	 is a function descriptor, read the actual code address from the
+	 descriptor.  */
+      if (opd
+	  && sym->st_value >= opd->addr
+	  && sym->st_value < opd->addr + opd->size)
+	elf_symbols[j].address
+	  = *(const b_elf_addr *) (opd->data + (sym->st_value - opd->addr));
+      else
+	elf_symbols[j].address = sym->st_value;
+      elf_symbols[j].address += base_address;
+      elf_symbols[j].size = sym->st_size;
+      ++j;
+    }
+
+  backtrace_qsort (elf_symbols, elf_symbol_count, sizeof (struct elf_symbol),
+		   elf_symbol_compare);
+
+  sdata->next = NULL;
+  sdata->symbols = elf_symbols;
+  sdata->count = elf_symbol_count;
+
+  return 1;
+}
+
+/* Add EDATA to the list in STATE.  */
+
+static void
+elf_add_syminfo_data (struct backtrace_state *state,
+		      struct elf_syminfo_data *edata)
+{
+  if (!state->threaded)
+    {
+      struct elf_syminfo_data **pp;
+
+      for (pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data;
+	   *pp != NULL;
+	   pp = &(*pp)->next)
+	;
+      *pp = edata;
+    }
+  else
+    {
+      while (1)
+	{
+	  struct elf_syminfo_data **pp;
+
+	  pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data;
+
+	  while (1)
+	    {
+	      struct elf_syminfo_data *p;
+
+	      p = backtrace_atomic_load_pointer (pp);
+
+	      if (p == NULL)
+		break;
+
+	      pp = &p->next;
+	    }
+
+	  if (__sync_bool_compare_and_swap (pp, NULL, edata))
+	    break;
+	}
+    }
+}
+
+/* Return the symbol name and value for an ADDR.  */
+
+static void
+elf_syminfo (struct backtrace_state *state, uintptr_t addr,
+	     backtrace_syminfo_callback callback,
+	     backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
+	     void *data)
+{
+  struct elf_syminfo_data *edata;
+  struct elf_symbol *sym = NULL;
+
+  if (!state->threaded)
+    {
+      for (edata = (struct elf_syminfo_data *) state->syminfo_data;
+	   edata != NULL;
+	   edata = edata->next)
+	{
+	  sym = ((struct elf_symbol *)
+		 bsearch (&addr, edata->symbols, edata->count,
+			  sizeof (struct elf_symbol), elf_symbol_search));
+	  if (sym != NULL)
+	    break;
+	}
+    }
+  else
+    {
+      struct elf_syminfo_data **pp;
+
+      pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data;
+      while (1)
+	{
+	  edata = backtrace_atomic_load_pointer (pp);
+	  if (edata == NULL)
+	    break;
+
+	  sym = ((struct elf_symbol *)
+		 bsearch (&addr, edata->symbols, edata->count,
+			  sizeof (struct elf_symbol), elf_symbol_search));
+	  if (sym != NULL)
+	    break;
+
+	  pp = &edata->next;
+	}
+    }
+
+  if (sym == NULL)
+    callback (data, addr, NULL, 0, 0);
+  else
+    callback (data, addr, sym->name, sym->address, sym->size);
+}
+
+/* Return whether FILENAME is a symlink.  */
+
+static int
+elf_is_symlink (const char *filename)
+{
+  struct stat st;
+
+  if (lstat (filename, &st) < 0)
+    return 0;
+  return S_ISLNK (st.st_mode);
+}
+
+/* Return the results of reading the symlink FILENAME in a buffer
+   allocated by backtrace_alloc.  Return the length of the buffer in
+   *LEN.  */
+
+static char *
+elf_readlink (struct backtrace_state *state, const char *filename,
+	      backtrace_error_callback error_callback, void *data,
+	      size_t *plen)
+{
+  size_t len;
+  char *buf;
+
+  len = 128;
+  while (1)
+    {
+      ssize_t rl;
+
+      buf = backtrace_alloc (state, len, error_callback, data);
+      if (buf == NULL)
+	return NULL;
+      rl = readlink (filename, buf, len);
+      if (rl < 0)
+	{
+	  backtrace_free (state, buf, len, error_callback, data);
+	  return NULL;
+	}
+      if ((size_t) rl < len - 1)
+	{
+	  buf[rl] = '\0';
+	  *plen = len;
+	  return buf;
+	}
+      backtrace_free (state, buf, len, error_callback, data);
+      len *= 2;
+    }
+}
+
+/* Open a separate debug info file, using the build ID to find it.
+   Returns an open file descriptor, or -1.
+
+   The GDB manual says that the only place gdb looks for a debug file
+   when the build ID is known is in /usr/lib/debug/.build-id.  */
+
+static int
+elf_open_debugfile_by_buildid (struct backtrace_state *state,
+			       const char *buildid_data, size_t buildid_size,
+			       backtrace_error_callback error_callback,
+			       void *data)
+{
+  const char * const prefix = "/usr/lib/debug/.build-id/";
+  const size_t prefix_len = strlen (prefix);
+  const char * const suffix = ".debug";
+  const size_t suffix_len = strlen (suffix);
+  size_t len;
+  char *bd_filename;
+  char *t;
+  size_t i;
+  int ret;
+  int does_not_exist;
+
+  len = prefix_len + buildid_size * 2 + suffix_len + 2;
+  bd_filename = backtrace_alloc (state, len, error_callback, data);
+  if (bd_filename == NULL)
+    return -1;
+
+  t = bd_filename;
+  memcpy (t, prefix, prefix_len);
+  t += prefix_len;
+  for (i = 0; i < buildid_size; i++)
+    {
+      unsigned char b;
+      unsigned char nib;
+
+      b = (unsigned char) buildid_data[i];
+      nib = (b & 0xf0) >> 4;
+      *t++ = nib < 10 ? '0' + nib : 'a' + nib - 10;
+      nib = b & 0x0f;
+      *t++ = nib < 10 ? '0' + nib : 'a' + nib - 10;
+      if (i == 0)
+	*t++ = '/';
+    }
+  memcpy (t, suffix, suffix_len);
+  t[suffix_len] = '\0';
+
+  ret = backtrace_open (bd_filename, error_callback, data, &does_not_exist);
+
+  backtrace_free (state, bd_filename, len, error_callback, data);
+
+  /* gdb checks that the debuginfo file has the same build ID note.
+     That seems kind of pointless to me--why would it have the right
+     name but not the right build ID?--so skipping the check.  */
+
+  return ret;
+}
+
+/* Try to open a file whose name is PREFIX (length PREFIX_LEN)
+   concatenated with PREFIX2 (length PREFIX2_LEN) concatenated with
+   DEBUGLINK_NAME.  Returns an open file descriptor, or -1.  */
+
+static int
+elf_try_debugfile (struct backtrace_state *state, const char *prefix,
+		   size_t prefix_len, const char *prefix2, size_t prefix2_len,
+		   const char *debuglink_name,
+		   backtrace_error_callback error_callback, void *data)
+{
+  size_t debuglink_len;
+  size_t try_len;
+  char *try;
+  int does_not_exist;
+  int ret;
+
+  debuglink_len = strlen (debuglink_name);
+  try_len = prefix_len + prefix2_len + debuglink_len + 1;
+  try = backtrace_alloc (state, try_len, error_callback, data);
+  if (try == NULL)
+    return -1;
+
+  memcpy (try, prefix, prefix_len);
+  memcpy (try + prefix_len, prefix2, prefix2_len);
+  memcpy (try + prefix_len + prefix2_len, debuglink_name, debuglink_len);
+  try[prefix_len + prefix2_len + debuglink_len] = '\0';
+
+  ret = backtrace_open (try, error_callback, data, &does_not_exist);
+
+  backtrace_free (state, try, try_len, error_callback, data);
+
+  return ret;
+}
+
+/* Find a separate debug info file, using the debuglink section data
+   to find it.  Returns an open file descriptor, or -1.  */
+
+static int
+elf_find_debugfile_by_debuglink (struct backtrace_state *state,
+				 const char *filename,
+				 const char *debuglink_name,
+				 backtrace_error_callback error_callback,
+				 void *data)
+{
+  int ret;
+  char *alc;
+  size_t alc_len;
+  const char *slash;
+  int ddescriptor;
+  const char *prefix;
+  size_t prefix_len;
+
+  /* Resolve symlinks in FILENAME.  Since FILENAME is fairly likely to
+     be /proc/self/exe, symlinks are common.  We don't try to resolve
+     the whole path name, just the base name.  */
+  ret = -1;
+  alc = NULL;
+  alc_len = 0;
+  while (elf_is_symlink (filename))
+    {
+      char *new_buf;
+      size_t new_len;
+
+      new_buf = elf_readlink (state, filename, error_callback, data, &new_len);
+      if (new_buf == NULL)
+	break;
+
+      if (new_buf[0] == '/')
+	filename = new_buf;
+      else
+	{
+	  slash = strrchr (filename, '/');
+	  if (slash == NULL)
+	    filename = new_buf;
+	  else
+	    {
+	      size_t clen;
+	      char *c;
+
+	      slash++;
+	      clen = slash - filename + strlen (new_buf) + 1;
+	      c = backtrace_alloc (state, clen, error_callback, data);
+	      if (c == NULL)
+		goto done;
+
+	      memcpy (c, filename, slash - filename);
+	      memcpy (c + (slash - filename), new_buf, strlen (new_buf));
+	      c[slash - filename + strlen (new_buf)] = '\0';
+	      backtrace_free (state, new_buf, new_len, error_callback, data);
+	      filename = c;
+	      new_buf = c;
+	      new_len = clen;
+	    }
+	}
+
+      if (alc != NULL)
+	backtrace_free (state, alc, alc_len, error_callback, data);
+      alc = new_buf;
+      alc_len = new_len;
+    }
+
+  /* Look for DEBUGLINK_NAME in the same directory as FILENAME.  */
+
+  slash = strrchr (filename, '/');
+  if (slash == NULL)
+    {
+      prefix = "";
+      prefix_len = 0;
+    }
+  else
+    {
+      slash++;
+      prefix = filename;
+      prefix_len = slash - filename;
+    }
+
+  ddescriptor = elf_try_debugfile (state, prefix, prefix_len, "", 0,
+				   debuglink_name, error_callback, data);
+  if (ddescriptor >= 0)
+    {
+      ret = ddescriptor;
+      goto done;
+    }
+
+  /* Look for DEBUGLINK_NAME in a .debug subdirectory of FILENAME.  */
+
+  ddescriptor = elf_try_debugfile (state, prefix, prefix_len, ".debug/",
+				   strlen (".debug/"), debuglink_name,
+				   error_callback, data);
+  if (ddescriptor >= 0)
+    {
+      ret = ddescriptor;
+      goto done;
+    }
+
+  /* Look for DEBUGLINK_NAME in /usr/lib/debug.  */
+
+  ddescriptor = elf_try_debugfile (state, "/usr/lib/debug/",
+				   strlen ("/usr/lib/debug/"), prefix,
+				   prefix_len, debuglink_name,
+				   error_callback, data);
+  if (ddescriptor >= 0)
+    ret = ddescriptor;
+
+ done:
+  if (alc != NULL && alc_len > 0)
+    backtrace_free (state, alc, alc_len, error_callback, data);
+  return ret;
+}
+
+/* Open a separate debug info file, using the debuglink section data
+   to find it.  Returns an open file descriptor, or -1.  */
+
+static int
+elf_open_debugfile_by_debuglink (struct backtrace_state *state,
+				 const char *filename,
+				 const char *debuglink_name,
+				 uint32_t debuglink_crc,
+				 backtrace_error_callback error_callback,
+				 void *data)
+{
+  int ddescriptor;
+
+  ddescriptor = elf_find_debugfile_by_debuglink (state, filename,
+						 debuglink_name,
+						 error_callback, data);
+  if (ddescriptor < 0)
+    return -1;
+
+  if (debuglink_crc != 0)
+    {
+      uint32_t got_crc;
+
+      got_crc = elf_crc32_file (state, ddescriptor, error_callback, data);
+      if (got_crc != debuglink_crc)
+	{
+	  backtrace_close (ddescriptor, error_callback, data);
+	  return -1;
+	}
+    }
+
+  return ddescriptor;
+}
+
+/* A function useful for setting a breakpoint for an inflation failure
+   when this code is compiled with -g.  */
+
+static void
+elf_zlib_failed(void)
+{
+}
+
+/* *PVAL is the current value being read from the stream, and *PBITS
+   is the number of valid bits.  Ensure that *PVAL holds at least 15
+   bits by reading additional bits from *PPIN, up to PINEND, as
+   needed.  Updates *PPIN, *PVAL and *PBITS.  Returns 1 on success, 0
+   on error.  */
+
+static int
+elf_zlib_fetch (const unsigned char **ppin, const unsigned char *pinend,
+		uint64_t *pval, unsigned int *pbits)
+{
+  unsigned int bits;
+  const unsigned char *pin;
+  uint64_t val;
+  uint32_t next;
+
+  bits = *pbits;
+  if (bits >= 15)
+    return 1;
+  pin = *ppin;
+  val = *pval;
+
+  if (unlikely (pinend - pin < 4))
+    {
+      elf_zlib_failed ();
+      return 0;
+    }
+
+#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) \
+    && defined(__ORDER_BIG_ENDIAN__) \
+    && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ \
+        || __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+  /* We've ensured that PIN is aligned.  */
+  next = *(const uint32_t *)pin;
+
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+  next = __builtin_bswap32 (next);
+#endif
+#else
+  next = pin[0] | (pin[1] << 8) | (pin[2] << 16) | (pin[3] << 24);
+#endif
+
+  val |= (uint64_t)next << bits;
+  bits += 32;
+  pin += 4;
+
+  /* We will need the next four bytes soon.  */
+  __builtin_prefetch (pin, 0, 0);
+
+  *ppin = pin;
+  *pval = val;
+  *pbits = bits;
+  return 1;
+}
+
+/* Huffman code tables, like the rest of the zlib format, are defined
+   by RFC 1951.  We store a Huffman code table as a series of tables
+   stored sequentially in memory.  Each entry in a table is 16 bits.
+   The first, main, table has 256 entries.  It is followed by a set of
+   secondary tables of length 2 to 128 entries.  The maximum length of
+   a code sequence in the deflate format is 15 bits, so that is all we
+   need.  Each secondary table has an index, which is the offset of
+   the table in the overall memory storage.
+
+   The deflate format says that all codes of a given bit length are
+   lexicographically consecutive.  Perhaps we could have 130 values
+   that require a 15-bit code, perhaps requiring three secondary
+   tables of size 128.  I don't know if this is actually possible, but
+   it suggests that the maximum size required for secondary tables is
+   3 * 128 + 3 * 64 ... == 768.  The zlib enough program reports 660
+   as the maximum.  We permit 768, since in addition to the 256 for
+   the primary table, with two bytes per entry, and with the two
+   tables we need, that gives us a page.
+
+   A single table entry needs to store a value or (for the main table
+   only) the index and size of a secondary table.  Values range from 0
+   to 285, inclusive.  Secondary table indexes, per above, range from
+   0 to 510.  For a value we need to store the number of bits we need
+   to determine that value (one value may appear multiple times in the
+   table), which is 1 to 8.  For a secondary table we need to store
+   the number of bits used to index into the table, which is 1 to 7.
+   And of course we need 1 bit to decide whether we have a value or a
+   secondary table index.  So each entry needs 9 bits for value/table
+   index, 3 bits for size, 1 bit what it is.  For simplicity we use 16
+   bits per entry.  */
+
+/* Number of entries we allocate to for one code table.  We get a page
+   for the two code tables we need.  */
+
+#define HUFFMAN_TABLE_SIZE (1024)
+
+/* Bit masks and shifts for the values in the table.  */
+
+#define HUFFMAN_VALUE_MASK 0x01ff
+#define HUFFMAN_BITS_SHIFT 9
+#define HUFFMAN_BITS_MASK 0x7
+#define HUFFMAN_SECONDARY_SHIFT 12
+
+/* For working memory while inflating we need two code tables, we need
+   an array of code lengths (max value 15, so we use unsigned char),
+   and an array of unsigned shorts used while building a table.  The
+   latter two arrays must be large enough to hold the maximum number
+   of code lengths, which RFC 1951 defines as 286 + 30.  */
+
+#define ZDEBUG_TABLE_SIZE \
+  (2 * HUFFMAN_TABLE_SIZE * sizeof (uint16_t) \
+   + (286 + 30) * sizeof (uint16_t)	      \
+   + (286 + 30) * sizeof (unsigned char))
+
+#define ZDEBUG_TABLE_CODELEN_OFFSET \
+  (2 * HUFFMAN_TABLE_SIZE * sizeof (uint16_t) \
+   + (286 + 30) * sizeof (uint16_t))
+
+#define ZDEBUG_TABLE_WORK_OFFSET \
+  (2 * HUFFMAN_TABLE_SIZE * sizeof (uint16_t))
+
+#ifdef BACKTRACE_GENERATE_FIXED_HUFFMAN_TABLE
+
+/* Used by the main function that generates the fixed table to learn
+   the table size.  */
+static size_t final_next_secondary;
+
+#endif
+
+/* Build a Huffman code table from an array of lengths in CODES of
+   length CODES_LEN.  The table is stored into *TABLE.  ZDEBUG_TABLE
+   is the same as for elf_zlib_inflate, used to find some work space.
+   Returns 1 on success, 0 on error.  */
+
+static int
+elf_zlib_inflate_table (unsigned char *codes, size_t codes_len,
+			uint16_t *zdebug_table, uint16_t *table)
+{
+  uint16_t count[16];
+  uint16_t start[16];
+  uint16_t prev[16];
+  uint16_t firstcode[7];
+  uint16_t *next;
+  size_t i;
+  size_t j;
+  unsigned int code;
+  size_t next_secondary;
+
+  /* Count the number of code of each length.  Set NEXT[val] to be the
+     next value after VAL with the same bit length.  */
+
+  next = (uint16_t *) (((unsigned char *) zdebug_table)
+		       + ZDEBUG_TABLE_WORK_OFFSET);
+
+  memset (&count[0], 0, 16 * sizeof (uint16_t));
+  for (i = 0; i < codes_len; ++i)
+    {
+      if (unlikely (codes[i] >= 16))
+	{
+	  elf_zlib_failed ();
+	  return 0;
+	}
+
+      if (count[codes[i]] == 0)
+	{
+	  start[codes[i]] = i;
+	  prev[codes[i]] = i;
+	}
+      else
+	{
+	  next[prev[codes[i]]] = i;
+	  prev[codes[i]] = i;
+	}
+
+      ++count[codes[i]];
+    }
+
+  /* For each length, fill in the table for the codes of that
+     length.  */
+
+  memset (table, 0, HUFFMAN_TABLE_SIZE * sizeof (uint16_t));
+
+  /* Handle the values that do not require a secondary table.  */
+
+  code = 0;
+  for (j = 1; j <= 8; ++j)
+    {
+      unsigned int jcnt;
+      unsigned int val;
+
+      jcnt = count[j];
+      if (jcnt == 0)
+	continue;
+
+      if (unlikely (jcnt > (1U << j)))
+	{
+	  elf_zlib_failed ();
+	  return 0;
+	}
+
+      /* There are JCNT values that have this length, the values
+	 starting from START[j] continuing through NEXT[VAL].  Those
+	 values are assigned consecutive values starting at CODE.  */
+
+      val = start[j];
+      for (i = 0; i < jcnt; ++i)
+	{
+	  uint16_t tval;
+	  size_t ind;
+	  unsigned int incr;
+
+	  /* In the compressed bit stream, the value VAL is encoded as
+	     J bits with the value C.  */
+
+	  if (unlikely ((val & ~HUFFMAN_VALUE_MASK) != 0))
+	    {
+	      elf_zlib_failed ();
+	      return 0;
+	    }
+
+	  tval = val | ((j - 1) << HUFFMAN_BITS_SHIFT);
+
+	  /* The table lookup uses 8 bits.  If J is less than 8, we
+	     don't know what the other bits will be.  We need to fill
+	     in all possibilities in the table.  Since the Huffman
+	     code is unambiguous, those entries can't be used for any
+	     other code.  */
+
+	  for (ind = code; ind < 0x100; ind += 1 << j)
+	    {
+	      if (unlikely (table[ind] != 0))
+		{
+		  elf_zlib_failed ();
+		  return 0;
+		}
+	      table[ind] = tval;
+	    }
+
+	  /* Advance to the next value with this length.  */
+	  if (i + 1 < jcnt)
+	    val = next[val];
+
+	  /* The Huffman codes are stored in the bitstream with the
+	     most significant bit first, as is required to make them
+	     unambiguous.  The effect is that when we read them from
+	     the bitstream we see the bit sequence in reverse order:
+	     the most significant bit of the Huffman code is the least
+	     significant bit of the value we read from the bitstream.
+	     That means that to make our table lookups work, we need
+	     to reverse the bits of CODE.  Since reversing bits is
+	     tedious and in general requires using a table, we instead
+	     increment CODE in reverse order.  That is, if the number
+	     of bits we are currently using, here named J, is 3, we
+	     count as 000, 100, 010, 110, 001, 101, 011, 111, which is
+	     to say the numbers from 0 to 7 but with the bits
+	     reversed.  Going to more bits, aka incrementing J,
+	     effectively just adds more zero bits as the beginning,
+	     and as such does not change the numeric value of CODE.
+
+	     To increment CODE of length J in reverse order, find the
+	     most significant zero bit and set it to one while
+	     clearing all higher bits.  In other words, add 1 modulo
+	     2^J, only reversed.  */
+
+	  incr = 1U << (j - 1);
+	  while ((code & incr) != 0)
+	    incr >>= 1;
+	  if (incr == 0)
+	    code = 0;
+	  else
+	    {
+	      code &= incr - 1;
+	      code += incr;
+	    }
+	}
+    }
+
+  /* Handle the values that require a secondary table.  */
+
+  /* Set FIRSTCODE, the number at which the codes start, for each
+     length.  */
+
+  for (j = 9; j < 16; j++)
+    {
+      unsigned int jcnt;
+      unsigned int k;
+
+      jcnt = count[j];
+      if (jcnt == 0)
+	continue;
+
+      /* There are JCNT values that have this length, the values
+	 starting from START[j].  Those values are assigned
+	 consecutive values starting at CODE.  */
+
+      firstcode[j - 9] = code;
+
+      /* Reverse add JCNT to CODE modulo 2^J.  */
+      for (k = 0; k < j; ++k)
+	{
+	  if ((jcnt & (1U << k)) != 0)
+	    {
+	      unsigned int m;
+	      unsigned int bit;
+
+	      bit = 1U << (j - k - 1);
+	      for (m = 0; m < j - k; ++m, bit >>= 1)
+		{
+		  if ((code & bit) == 0)
+		    {
+		      code += bit;
+		      break;
+		    }
+		  code &= ~bit;
+		}
+	      jcnt &= ~(1U << k);
+	    }
+	}
+      if (unlikely (jcnt != 0))
+	{
+	  elf_zlib_failed ();
+	  return 0;
+	}
+    }
+
+  /* For J from 9 to 15, inclusive, we store COUNT[J] consecutive
+     values starting at START[J] with consecutive codes starting at
+     FIRSTCODE[J - 9].  In the primary table we need to point to the
+     secondary table, and the secondary table will be indexed by J - 9
+     bits.  We count down from 15 so that we install the larger
+     secondary tables first, as the smaller ones may be embedded in
+     the larger ones.  */
+
+  next_secondary = 0; /* Index of next secondary table (after primary).  */
+  for (j = 15; j >= 9; j--)
+    {
+      unsigned int jcnt;
+      unsigned int val;
+      size_t primary; /* Current primary index.  */
+      size_t secondary; /* Offset to current secondary table.  */
+      size_t secondary_bits; /* Bit size of current secondary table.  */
+
+      jcnt = count[j];
+      if (jcnt == 0)
+	continue;
+
+      val = start[j];
+      code = firstcode[j - 9];
+      primary = 0x100;
+      secondary = 0;
+      secondary_bits = 0;
+      for (i = 0; i < jcnt; ++i)
+	{
+	  uint16_t tval;
+	  size_t ind;
+	  unsigned int incr;
+
+	  if ((code & 0xff) != primary)
+	    {
+	      uint16_t tprimary;
+
+	      /* Fill in a new primary table entry.  */
+
+	      primary = code & 0xff;
+
+	      tprimary = table[primary];
+	      if (tprimary == 0)
+		{
+		  /* Start a new secondary table.  */
+
+		  if (unlikely ((next_secondary & HUFFMAN_VALUE_MASK)
+				!= next_secondary))
+		    {
+		      elf_zlib_failed ();
+		      return 0;
+		    }
+
+		  secondary = next_secondary;
+		  secondary_bits = j - 8;
+		  next_secondary += 1 << secondary_bits;
+		  table[primary] = (secondary
+				    + ((j - 8) << HUFFMAN_BITS_SHIFT)
+				    + (1U << HUFFMAN_SECONDARY_SHIFT));
+		}
+	      else
+		{
+		  /* There is an existing entry.  It had better be a
+		     secondary table with enough bits.  */
+		  if (unlikely ((tprimary & (1U << HUFFMAN_SECONDARY_SHIFT))
+				== 0))
+		    {
+		      elf_zlib_failed ();
+		      return 0;
+		    }
+		  secondary = tprimary & HUFFMAN_VALUE_MASK;
+		  secondary_bits = ((tprimary >> HUFFMAN_BITS_SHIFT)
+				    & HUFFMAN_BITS_MASK);
+		  if (unlikely (secondary_bits < j - 8))
+		    {
+		      elf_zlib_failed ();
+		      return 0;
+		    }
+		}
+	    }
+
+	  /* Fill in secondary table entries.  */
+
+	  tval = val | ((j - 8) << HUFFMAN_BITS_SHIFT);
+
+	  for (ind = code >> 8;
+	       ind < (1U << secondary_bits);
+	       ind += 1U << (j - 8))
+	    {
+	      if (unlikely (table[secondary + 0x100 + ind] != 0))
+		{
+		  elf_zlib_failed ();
+		  return 0;
+		}
+	      table[secondary + 0x100 + ind] = tval;
+	    }
+
+	  if (i + 1 < jcnt)
+	    val = next[val];
+
+	  incr = 1U << (j - 1);
+	  while ((code & incr) != 0)
+	    incr >>= 1;
+	  if (incr == 0)
+	    code = 0;
+	  else
+	    {
+	      code &= incr - 1;
+	      code += incr;
+	    }
+	}
+    }
+
+#ifdef BACKTRACE_GENERATE_FIXED_HUFFMAN_TABLE
+  final_next_secondary = next_secondary;
+#endif
+
+  return 1;
+}
+
+#ifdef BACKTRACE_GENERATE_FIXED_HUFFMAN_TABLE
+
+/* Used to generate the fixed Huffman table for block type 1.  */
+
+#include <stdio.h>
+
+static uint16_t table[ZDEBUG_TABLE_SIZE];
+static unsigned char codes[288];
+
+int
+main ()
+{
+  size_t i;
+
+  for (i = 0; i <= 143; ++i)
+    codes[i] = 8;
+  for (i = 144; i <= 255; ++i)
+    codes[i] = 9;
+  for (i = 256; i <= 279; ++i)
+    codes[i] = 7;
+  for (i = 280; i <= 287; ++i)
+    codes[i] = 8;
+  if (!elf_zlib_inflate_table (&codes[0], 288, &table[0], &table[0]))
+    {
+      fprintf (stderr, "elf_zlib_inflate_table failed\n");
+      exit (EXIT_FAILURE);
+    }
+
+  printf ("static const uint16_t elf_zlib_default_table[%#zx] =\n",
+	  final_next_secondary + 0x100);
+  printf ("{\n");
+  for (i = 0; i < final_next_secondary + 0x100; i += 8)
+    {
+      size_t j;
+
+      printf (" ");
+      for (j = i; j < final_next_secondary + 0x100 && j < i + 8; ++j)
+	printf (" %#x,", table[j]);
+      printf ("\n");
+    }
+  printf ("};\n");
+  printf ("\n");
+
+  for (i = 0; i < 32; ++i)
+    codes[i] = 5;
+  if (!elf_zlib_inflate_table (&codes[0], 32, &table[0], &table[0]))
+    {
+      fprintf (stderr, "elf_zlib_inflate_table failed\n");
+      exit (EXIT_FAILURE);
+    }
+
+  printf ("static const uint16_t elf_zlib_default_dist_table[%#zx] =\n",
+	  final_next_secondary + 0x100);
+  printf ("{\n");
+  for (i = 0; i < final_next_secondary + 0x100; i += 8)
+    {
+      size_t j;
+
+      printf (" ");
+      for (j = i; j < final_next_secondary + 0x100 && j < i + 8; ++j)
+	printf (" %#x,", table[j]);
+      printf ("\n");
+    }
+  printf ("};\n");
+
+  return 0;
+}
+
+#endif
+
+/* The fixed tables generated by the #ifdef'ed out main function
+   above.  */
+
+static const uint16_t elf_zlib_default_table[0x170] =
+{
+  0xd00, 0xe50, 0xe10, 0xf18, 0xd10, 0xe70, 0xe30, 0x1230,
+  0xd08, 0xe60, 0xe20, 0x1210, 0xe00, 0xe80, 0xe40, 0x1250,
+  0xd04, 0xe58, 0xe18, 0x1200, 0xd14, 0xe78, 0xe38, 0x1240,
+  0xd0c, 0xe68, 0xe28, 0x1220, 0xe08, 0xe88, 0xe48, 0x1260,
+  0xd02, 0xe54, 0xe14, 0xf1c, 0xd12, 0xe74, 0xe34, 0x1238,
+  0xd0a, 0xe64, 0xe24, 0x1218, 0xe04, 0xe84, 0xe44, 0x1258,
+  0xd06, 0xe5c, 0xe1c, 0x1208, 0xd16, 0xe7c, 0xe3c, 0x1248,
+  0xd0e, 0xe6c, 0xe2c, 0x1228, 0xe0c, 0xe8c, 0xe4c, 0x1268,
+  0xd01, 0xe52, 0xe12, 0xf1a, 0xd11, 0xe72, 0xe32, 0x1234,
+  0xd09, 0xe62, 0xe22, 0x1214, 0xe02, 0xe82, 0xe42, 0x1254,
+  0xd05, 0xe5a, 0xe1a, 0x1204, 0xd15, 0xe7a, 0xe3a, 0x1244,
+  0xd0d, 0xe6a, 0xe2a, 0x1224, 0xe0a, 0xe8a, 0xe4a, 0x1264,
+  0xd03, 0xe56, 0xe16, 0xf1e, 0xd13, 0xe76, 0xe36, 0x123c,
+  0xd0b, 0xe66, 0xe26, 0x121c, 0xe06, 0xe86, 0xe46, 0x125c,
+  0xd07, 0xe5e, 0xe1e, 0x120c, 0xd17, 0xe7e, 0xe3e, 0x124c,
+  0xd0f, 0xe6e, 0xe2e, 0x122c, 0xe0e, 0xe8e, 0xe4e, 0x126c,
+  0xd00, 0xe51, 0xe11, 0xf19, 0xd10, 0xe71, 0xe31, 0x1232,
+  0xd08, 0xe61, 0xe21, 0x1212, 0xe01, 0xe81, 0xe41, 0x1252,
+  0xd04, 0xe59, 0xe19, 0x1202, 0xd14, 0xe79, 0xe39, 0x1242,
+  0xd0c, 0xe69, 0xe29, 0x1222, 0xe09, 0xe89, 0xe49, 0x1262,
+  0xd02, 0xe55, 0xe15, 0xf1d, 0xd12, 0xe75, 0xe35, 0x123a,
+  0xd0a, 0xe65, 0xe25, 0x121a, 0xe05, 0xe85, 0xe45, 0x125a,
+  0xd06, 0xe5d, 0xe1d, 0x120a, 0xd16, 0xe7d, 0xe3d, 0x124a,
+  0xd0e, 0xe6d, 0xe2d, 0x122a, 0xe0d, 0xe8d, 0xe4d, 0x126a,
+  0xd01, 0xe53, 0xe13, 0xf1b, 0xd11, 0xe73, 0xe33, 0x1236,
+  0xd09, 0xe63, 0xe23, 0x1216, 0xe03, 0xe83, 0xe43, 0x1256,
+  0xd05, 0xe5b, 0xe1b, 0x1206, 0xd15, 0xe7b, 0xe3b, 0x1246,
+  0xd0d, 0xe6b, 0xe2b, 0x1226, 0xe0b, 0xe8b, 0xe4b, 0x1266,
+  0xd03, 0xe57, 0xe17, 0xf1f, 0xd13, 0xe77, 0xe37, 0x123e,
+  0xd0b, 0xe67, 0xe27, 0x121e, 0xe07, 0xe87, 0xe47, 0x125e,
+  0xd07, 0xe5f, 0xe1f, 0x120e, 0xd17, 0xe7f, 0xe3f, 0x124e,
+  0xd0f, 0xe6f, 0xe2f, 0x122e, 0xe0f, 0xe8f, 0xe4f, 0x126e,
+  0x290, 0x291, 0x292, 0x293, 0x294, 0x295, 0x296, 0x297,
+  0x298, 0x299, 0x29a, 0x29b, 0x29c, 0x29d, 0x29e, 0x29f,
+  0x2a0, 0x2a1, 0x2a2, 0x2a3, 0x2a4, 0x2a5, 0x2a6, 0x2a7,
+  0x2a8, 0x2a9, 0x2aa, 0x2ab, 0x2ac, 0x2ad, 0x2ae, 0x2af,
+  0x2b0, 0x2b1, 0x2b2, 0x2b3, 0x2b4, 0x2b5, 0x2b6, 0x2b7,
+  0x2b8, 0x2b9, 0x2ba, 0x2bb, 0x2bc, 0x2bd, 0x2be, 0x2bf,
+  0x2c0, 0x2c1, 0x2c2, 0x2c3, 0x2c4, 0x2c5, 0x2c6, 0x2c7,
+  0x2c8, 0x2c9, 0x2ca, 0x2cb, 0x2cc, 0x2cd, 0x2ce, 0x2cf,
+  0x2d0, 0x2d1, 0x2d2, 0x2d3, 0x2d4, 0x2d5, 0x2d6, 0x2d7,
+  0x2d8, 0x2d9, 0x2da, 0x2db, 0x2dc, 0x2dd, 0x2de, 0x2df,
+  0x2e0, 0x2e1, 0x2e2, 0x2e3, 0x2e4, 0x2e5, 0x2e6, 0x2e7,
+  0x2e8, 0x2e9, 0x2ea, 0x2eb, 0x2ec, 0x2ed, 0x2ee, 0x2ef,
+  0x2f0, 0x2f1, 0x2f2, 0x2f3, 0x2f4, 0x2f5, 0x2f6, 0x2f7,
+  0x2f8, 0x2f9, 0x2fa, 0x2fb, 0x2fc, 0x2fd, 0x2fe, 0x2ff,
+};
+
+static const uint16_t elf_zlib_default_dist_table[0x100] =
+{
+  0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c,
+  0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e,
+  0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d,
+  0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f,
+  0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c,
+  0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e,
+  0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d,
+  0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f,
+  0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c,
+  0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e,
+  0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d,
+  0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f,
+  0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c,
+  0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e,
+  0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d,
+  0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f,
+  0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c,
+  0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e,
+  0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d,
+  0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f,
+  0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c,
+  0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e,
+  0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d,
+  0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f,
+  0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c,
+  0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e,
+  0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d,
+  0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f,
+  0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c,
+  0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e,
+  0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d,
+  0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f,
+};
+
+/* Inflate a zlib stream from PIN/SIN to POUT/SOUT.  Return 1 on
+   success, 0 on some error parsing the stream.  */
+
+static int
+elf_zlib_inflate (const unsigned char *pin, size_t sin, uint16_t *zdebug_table,
+		  unsigned char *pout, size_t sout)
+{
+  unsigned char *porigout;
+  const unsigned char *pinend;
+  unsigned char *poutend;
+
+  /* We can apparently see multiple zlib streams concatenated
+     together, so keep going as long as there is something to read.
+     The last 4 bytes are the checksum.  */
+  porigout = pout;
+  pinend = pin + sin;
+  poutend = pout + sout;
+  while ((pinend - pin) > 4)
+    {
+      uint64_t val;
+      unsigned int bits;
+      int last;
+
+      /* Read the two byte zlib header.  */
+
+      if (unlikely ((pin[0] & 0xf) != 8)) /* 8 is zlib encoding.  */
+	{
+	  /* Unknown compression method.  */
+	  elf_zlib_failed ();
+	  return 0;
+	}
+      if (unlikely ((pin[0] >> 4) > 7))
+	{
+	  /* Window size too large.  Other than this check, we don't
+	     care about the window size.  */
+	  elf_zlib_failed ();
+	  return 0;
+	}
+      if (unlikely ((pin[1] & 0x20) != 0))
+	{
+	  /* Stream expects a predefined dictionary, but we have no
+	     dictionary.  */
+	  elf_zlib_failed ();
+	  return 0;
+	}
+      val = (pin[0] << 8) | pin[1];
+      if (unlikely (val % 31 != 0))
+	{
+	  /* Header check failure.  */
+	  elf_zlib_failed ();
+	  return 0;
+	}
+      pin += 2;
+
+      /* Align PIN to a 32-bit boundary.  */
+
+      val = 0;
+      bits = 0;
+      while ((((uintptr_t) pin) & 3) != 0)
+	{
+	  val |= (uint64_t)*pin << bits;
+	  bits += 8;
+	  ++pin;
+	}
+
+      /* Read blocks until one is marked last.  */
+
+      last = 0;
+
+      while (!last)
+	{
+	  unsigned int type;
+	  const uint16_t *tlit;
+	  const uint16_t *tdist;
+
+	  if (!elf_zlib_fetch (&pin, pinend, &val, &bits))
+	    return 0;
+
+	  last = val & 1;
+	  type = (val >> 1) & 3;
+	  val >>= 3;
+	  bits -= 3;
+
+	  if (unlikely (type == 3))
+	    {
+	      /* Invalid block type.  */
+	      elf_zlib_failed ();
+	      return 0;
+	    }
+
+	  if (type == 0)
+	    {
+	      uint16_t len;
+	      uint16_t lenc;
+
+	      /* An uncompressed block.  */
+
+	      /* If we've read ahead more than a byte, back up.  */
+	      while (bits > 8)
+		{
+		  --pin;
+		  bits -= 8;
+		}
+
+	      val = 0;
+	      bits = 0;
+	      if (unlikely ((pinend - pin) < 4))
+		{
+		  /* Missing length.  */
+		  elf_zlib_failed ();
+		  return 0;
+		}
+	      len = pin[0] | (pin[1] << 8);
+	      lenc = pin[2] | (pin[3] << 8);
+	      pin += 4;
+	      lenc = ~lenc;
+	      if (unlikely (len != lenc))
+		{
+		  /* Corrupt data.  */
+		  elf_zlib_failed ();
+		  return 0;
+		}
+	      if (unlikely (len > (unsigned int) (pinend - pin)
+			    || len > (unsigned int) (poutend - pout)))
+		{
+		  /* Not enough space in buffers.  */
+		  elf_zlib_failed ();
+		  return 0;
+		}
+	      memcpy (pout, pin, len);
+	      pout += len;
+	      pin += len;
+
+	      /* Align PIN.  */
+	      while ((((uintptr_t) pin) & 3) != 0)
+		{
+		  val |= (uint64_t)*pin << bits;
+		  bits += 8;
+		  ++pin;
+		}
+
+	      /* Go around to read the next block.  */
+	      continue;
+	    }
+
+	  if (type == 1)
+	    {
+	      tlit = elf_zlib_default_table;
+	      tdist = elf_zlib_default_dist_table;
+	    }
+	  else
+	    {
+	      unsigned int nlit;
+	      unsigned int ndist;
+	      unsigned int nclen;
+	      unsigned char codebits[19];
+	      unsigned char *plenbase;
+	      unsigned char *plen;
+	      unsigned char *plenend;
+
+	      /* Read a Huffman encoding table.  The various magic
+		 numbers here are from RFC 1951.  */
+
+	      if (!elf_zlib_fetch (&pin, pinend, &val, &bits))
+		return 0;
+
+	      nlit = (val & 0x1f) + 257;
+	      val >>= 5;
+	      ndist = (val & 0x1f) + 1;
+	      val >>= 5;
+	      nclen = (val & 0xf) + 4;
+	      val >>= 4;
+	      bits -= 14;
+	      if (unlikely (nlit > 286 || ndist > 30))
+		{
+		  /* Values out of range.  */
+		  elf_zlib_failed ();
+		  return 0;
+		}
+
+	      /* Read and build the table used to compress the
+		 literal, length, and distance codes.  */
+
+	      memset(&codebits[0], 0, 19);
+
+	      /* There are always at least 4 elements in the
+		 table.  */
+
+	      if (!elf_zlib_fetch (&pin, pinend, &val, &bits))
+		return 0;
+
+	      codebits[16] = val & 7;
+	      codebits[17] = (val >> 3) & 7;
+	      codebits[18] = (val >> 6) & 7;
+	      codebits[0] = (val >> 9) & 7;
+	      val >>= 12;
+	      bits -= 12;
+
+	      if (nclen == 4)
+		goto codebitsdone;
+
+	      codebits[8] = val & 7;
+	      val >>= 3;
+	      bits -= 3;
+
+	      if (nclen == 5)
+		goto codebitsdone;
+
+	      if (!elf_zlib_fetch (&pin, pinend, &val, &bits))
+		return 0;
+
+	      codebits[7] = val & 7;
+	      val >>= 3;
+	      bits -= 3;
+
+	      if (nclen == 6)
+		goto codebitsdone;
+
+	      codebits[9] = val & 7;
+	      val >>= 3;
+	      bits -= 3;
+
+	      if (nclen == 7)
+		goto codebitsdone;
+
+	      codebits[6] = val & 7;
+	      val >>= 3;
+	      bits -= 3;
+
+	      if (nclen == 8)
+		goto codebitsdone;
+
+	      codebits[10] = val & 7;
+	      val >>= 3;
+	      bits -= 3;
+
+	      if (nclen == 9)
+		goto codebitsdone;
+
+	      codebits[5] = val & 7;
+	      val >>= 3;
+	      bits -= 3;
+
+	      if (nclen == 10)
+		goto codebitsdone;
+
+	      if (!elf_zlib_fetch (&pin, pinend, &val, &bits))
+		return 0;
+
+	      codebits[11] = val & 7;
+	      val >>= 3;
+	      bits -= 3;
+
+	      if (nclen == 11)
+		goto codebitsdone;
+
+	      codebits[4] = val & 7;
+	      val >>= 3;
+	      bits -= 3;
+
+	      if (nclen == 12)
+		goto codebitsdone;
+
+	      codebits[12] = val & 7;
+	      val >>= 3;
+	      bits -= 3;
+
+	      if (nclen == 13)
+		goto codebitsdone;
+
+	      codebits[3] = val & 7;
+	      val >>= 3;
+	      bits -= 3;
+
+	      if (nclen == 14)
+		goto codebitsdone;
+
+	      codebits[13] = val & 7;
+	      val >>= 3;
+	      bits -= 3;
+
+	      if (nclen == 15)
+		goto codebitsdone;
+
+	      if (!elf_zlib_fetch (&pin, pinend, &val, &bits))
+		return 0;
+
+	      codebits[2] = val & 7;
+	      val >>= 3;
+	      bits -= 3;
+
+	      if (nclen == 16)
+		goto codebitsdone;
+
+	      codebits[14] = val & 7;
+	      val >>= 3;
+	      bits -= 3;
+
+	      if (nclen == 17)
+		goto codebitsdone;
+
+	      codebits[1] = val & 7;
+	      val >>= 3;
+	      bits -= 3;
+
+	      if (nclen == 18)
+		goto codebitsdone;
+
+	      codebits[15] = val & 7;
+	      val >>= 3;
+	      bits -= 3;
+
+	    codebitsdone:
+
+	      if (!elf_zlib_inflate_table (codebits, 19, zdebug_table,
+					   zdebug_table))
+		return 0;
+
+	      /* Read the compressed bit lengths of the literal,
+		 length, and distance codes.  We have allocated space
+		 at the end of zdebug_table to hold them.  */
+
+	      plenbase = (((unsigned char *) zdebug_table)
+			  + ZDEBUG_TABLE_CODELEN_OFFSET);
+	      plen = plenbase;
+	      plenend = plen + nlit + ndist;
+	      while (plen < plenend)
+		{
+		  uint16_t t;
+		  unsigned int b;
+		  uint16_t v;
+
+		  if (!elf_zlib_fetch (&pin, pinend, &val, &bits))
+		    return 0;
+
+		  t = zdebug_table[val & 0xff];
+
+		  /* The compression here uses bit lengths up to 7, so
+		     a secondary table is never necessary.  */
+		  if (unlikely ((t & (1U << HUFFMAN_SECONDARY_SHIFT)) != 0))
+		    {
+		      elf_zlib_failed ();
+		      return 0;
+		    }
+
+		  b = (t >> HUFFMAN_BITS_SHIFT) & HUFFMAN_BITS_MASK;
+		  val >>= b + 1;
+		  bits -= b + 1;
+
+		  v = t & HUFFMAN_VALUE_MASK;
+		  if (v < 16)
+		    *plen++ = v;
+		  else if (v == 16)
+		    {
+		      unsigned int c;
+		      unsigned int prev;
+
+		      /* Copy previous entry 3 to 6 times.  */
+
+		      if (unlikely (plen == plenbase))
+			{
+			  elf_zlib_failed ();
+			  return 0;
+			}
+
+		      /* We used up to 7 bits since the last
+			 elf_zlib_fetch, so we have at least 8 bits
+			 available here.  */
+
+		      c = 3 + (val & 0x3);
+		      val >>= 2;
+		      bits -= 2;
+		      if (unlikely ((unsigned int) (plenend - plen) < c))
+			{
+			  elf_zlib_failed ();
+			  return 0;
+			}
+
+		      prev = plen[-1];
+		      switch (c)
+			{
+			case 6:
+			  *plen++ = prev;
+			  /* fallthrough */
+			case 5:
+			  *plen++ = prev;
+			  /* fallthrough */
+			case 4:
+			  *plen++ = prev;
+			}
+		      *plen++ = prev;
+		      *plen++ = prev;
+		      *plen++ = prev;
+		    }
+		  else if (v == 17)
+		    {
+		      unsigned int c;
+
+		      /* Store zero 3 to 10 times.  */
+
+		      /* We used up to 7 bits since the last
+			 elf_zlib_fetch, so we have at least 8 bits
+			 available here.  */
+
+		      c = 3 + (val & 0x7);
+		      val >>= 3;
+		      bits -= 3;
+		      if (unlikely ((unsigned int) (plenend - plen) < c))
+			{
+			  elf_zlib_failed ();
+			  return 0;
+			}
+
+		      switch (c)
+			{
+			case 10:
+			  *plen++ = 0;
+			  /* fallthrough */
+			case 9:
+			  *plen++ = 0;
+			  /* fallthrough */
+			case 8:
+			  *plen++ = 0;
+			  /* fallthrough */
+			case 7:
+			  *plen++ = 0;
+			  /* fallthrough */
+			case 6:
+			  *plen++ = 0;
+			  /* fallthrough */
+			case 5:
+			  *plen++ = 0;
+			  /* fallthrough */
+			case 4:
+			  *plen++ = 0;
+			}
+		      *plen++ = 0;
+		      *plen++ = 0;
+		      *plen++ = 0;
+		    }
+		  else if (v == 18)
+		    {
+		      unsigned int c;
+
+		      /* Store zero 11 to 138 times.  */
+
+		      /* We used up to 7 bits since the last
+			 elf_zlib_fetch, so we have at least 8 bits
+			 available here.  */
+
+		      c = 11 + (val & 0x7f);
+		      val >>= 7;
+		      bits -= 7;
+		      if (unlikely ((unsigned int) (plenend - plen) < c))
+			{
+			  elf_zlib_failed ();
+			  return 0;
+			}
+
+		      memset (plen, 0, c);
+		      plen += c;
+		    }
+		  else
+		    {
+		      elf_zlib_failed ();
+		      return 0;
+		    }
+		}
+
+	      /* Make sure that the stop code can appear.  */
+
+	      plen = plenbase;
+	      if (unlikely (plen[256] == 0))
+		{
+		  elf_zlib_failed ();
+		  return 0;
+		}
+
+	      /* Build the decompression tables.  */
+
+	      if (!elf_zlib_inflate_table (plen, nlit, zdebug_table,
+					   zdebug_table))
+		return 0;
+	      if (!elf_zlib_inflate_table (plen + nlit, ndist, zdebug_table,
+					   zdebug_table + HUFFMAN_TABLE_SIZE))
+		return 0;
+	      tlit = zdebug_table;
+	      tdist = zdebug_table + HUFFMAN_TABLE_SIZE;
+	    }
+
+	  /* Inflate values until the end of the block.  This is the
+	     main loop of the inflation code.  */
+
+	  while (1)
+	    {
+	      uint16_t t;
+	      unsigned int b;
+	      uint16_t v;
+	      unsigned int lit;
+
+	      if (!elf_zlib_fetch (&pin, pinend, &val, &bits))
+		return 0;
+
+	      t = tlit[val & 0xff];
+	      b = (t >> HUFFMAN_BITS_SHIFT) & HUFFMAN_BITS_MASK;
+	      v = t & HUFFMAN_VALUE_MASK;
+
+	      if ((t & (1U << HUFFMAN_SECONDARY_SHIFT)) == 0)
+		{
+		  lit = v;
+		  val >>= b + 1;
+		  bits -= b + 1;
+		}
+	      else
+		{
+		  t = tlit[v + 0x100 + ((val >> 8) & ((1U << b) - 1))];
+		  b = (t >> HUFFMAN_BITS_SHIFT) & HUFFMAN_BITS_MASK;
+		  lit = t & HUFFMAN_VALUE_MASK;
+		  val >>= b + 8;
+		  bits -= b + 8;
+		}
+
+	      if (lit < 256)
+		{
+		  if (unlikely (pout == poutend))
+		    {
+		      elf_zlib_failed ();
+		      return 0;
+		    }
+
+		  *pout++ = lit;
+
+		  /* We will need to write the next byte soon.  We ask
+		     for high temporal locality because we will write
+		     to the whole cache line soon.  */
+		  __builtin_prefetch (pout, 1, 3);
+		}
+	      else if (lit == 256)
+		{
+		  /* The end of the block.  */
+		  break;
+		}
+	      else
+		{
+		  unsigned int dist;
+		  unsigned int len;
+
+		  /* Convert lit into a length.  */
+
+		  if (lit < 265)
+		    len = lit - 257 + 3;
+		  else if (lit == 285)
+		    len = 258;
+		  else if (unlikely (lit > 285))
+		    {
+		      elf_zlib_failed ();
+		      return 0;
+		    }
+		  else
+		    {
+		      unsigned int extra;
+
+		      if (!elf_zlib_fetch (&pin, pinend, &val, &bits))
+			return 0;
+
+		      /* This is an expression for the table of length
+			 codes in RFC 1951 3.2.5.  */
+		      lit -= 265;
+		      extra = (lit >> 2) + 1;
+		      len = (lit & 3) << extra;
+		      len += 11;
+		      len += ((1U << (extra - 1)) - 1) << 3;
+		      len += val & ((1U << extra) - 1);
+		      val >>= extra;
+		      bits -= extra;
+		    }
+
+		  if (!elf_zlib_fetch (&pin, pinend, &val, &bits))
+		    return 0;
+
+		  t = tdist[val & 0xff];
+		  b = (t >> HUFFMAN_BITS_SHIFT) & HUFFMAN_BITS_MASK;
+		  v = t & HUFFMAN_VALUE_MASK;
+
+		  if ((t & (1U << HUFFMAN_SECONDARY_SHIFT)) == 0)
+		    {
+		      dist = v;
+		      val >>= b + 1;
+		      bits -= b + 1;
+		    }
+		  else
+		    {
+		      t = tdist[v + 0x100 + ((val >> 8) & ((1U << b) - 1))];
+		      b = (t >> HUFFMAN_BITS_SHIFT) & HUFFMAN_BITS_MASK;
+		      dist = t & HUFFMAN_VALUE_MASK;
+		      val >>= b + 8;
+		      bits -= b + 8;
+		    }
+
+		  /* Convert dist to a distance.  */
+
+		  if (dist == 0)
+		    {
+		      /* A distance of 1.  A common case, meaning
+			 repeat the last character LEN times.  */
+
+		      if (unlikely (pout == porigout))
+			{
+			  elf_zlib_failed ();
+			  return 0;
+			}
+
+		      if (unlikely ((unsigned int) (poutend - pout) < len))
+			{
+			  elf_zlib_failed ();
+			  return 0;
+			}
+
+		      memset (pout, pout[-1], len);
+		      pout += len;
+		    }
+		  else if (unlikely (dist > 29))
+		    {
+		      elf_zlib_failed ();
+		      return 0;
+		    }
+		  else
+		    {
+		      if (dist < 4)
+			dist = dist + 1;
+		      else
+			{
+			  unsigned int extra;
+
+			  if (!elf_zlib_fetch (&pin, pinend, &val, &bits))
+			    return 0;
+
+			  /* This is an expression for the table of
+			     distance codes in RFC 1951 3.2.5.  */
+			  dist -= 4;
+			  extra = (dist >> 1) + 1;
+			  dist = (dist & 1) << extra;
+			  dist += 5;
+			  dist += ((1U << (extra - 1)) - 1) << 2;
+			  dist += val & ((1U << extra) - 1);
+			  val >>= extra;
+			  bits -= extra;
+			}
+
+		      /* Go back dist bytes, and copy len bytes from
+			 there.  */
+
+		      if (unlikely ((unsigned int) (pout - porigout) < dist))
+			{
+			  elf_zlib_failed ();
+			  return 0;
+			}
+
+		      if (unlikely ((unsigned int) (poutend - pout) < len))
+			{
+			  elf_zlib_failed ();
+			  return 0;
+			}
+
+		      if (dist >= len)
+			{
+			  memcpy (pout, pout - dist, len);
+			  pout += len;
+			}
+		      else
+			{
+			  while (len > 0)
+			    {
+			      unsigned int copy;
+
+			      copy = len < dist ? len : dist;
+			      memcpy (pout, pout - dist, copy);
+			      len -= copy;
+			      pout += copy;
+			    }
+			}
+		    }
+		}
+	    }
+	}
+    }
+
+  /* We should have filled the output buffer.  */
+  if (unlikely (pout != poutend))
+    {
+      elf_zlib_failed ();
+      return 0;
+    }
+
+  return 1;
+}
+
+/* Verify the zlib checksum.  The checksum is in the 4 bytes at
+   CHECKBYTES, and the uncompressed data is at UNCOMPRESSED /
+   UNCOMPRESSED_SIZE.  Returns 1 on success, 0 on failure.  */
+
+static int
+elf_zlib_verify_checksum (const unsigned char *checkbytes,
+			  const unsigned char *uncompressed,
+			  size_t uncompressed_size)
+{
+  unsigned int i;
+  unsigned int cksum;
+  const unsigned char *p;
+  uint32_t s1;
+  uint32_t s2;
+  size_t hsz;
+
+  cksum = 0;
+  for (i = 0; i < 4; i++)
+    cksum = (cksum << 8) | checkbytes[i];
+
+  s1 = 1;
+  s2 = 0;
+
+  /* Minimize modulo operations.  */
+
+  p = uncompressed;
+  hsz = uncompressed_size;
+  while (hsz >= 5552)
+    {
+      for (i = 0; i < 5552; i += 16)
+	{
+	  /* Manually unroll loop 16 times.  */
+	  s1 = s1 + *p++;
+	  s2 = s2 + s1;
+	  s1 = s1 + *p++;
+	  s2 = s2 + s1;
+	  s1 = s1 + *p++;
+	  s2 = s2 + s1;
+	  s1 = s1 + *p++;
+	  s2 = s2 + s1;
+	  s1 = s1 + *p++;
+	  s2 = s2 + s1;
+	  s1 = s1 + *p++;
+	  s2 = s2 + s1;
+	  s1 = s1 + *p++;
+	  s2 = s2 + s1;
+	  s1 = s1 + *p++;
+	  s2 = s2 + s1;
+	  s1 = s1 + *p++;
+	  s2 = s2 + s1;
+	  s1 = s1 + *p++;
+	  s2 = s2 + s1;
+	  s1 = s1 + *p++;
+	  s2 = s2 + s1;
+	  s1 = s1 + *p++;
+	  s2 = s2 + s1;
+	  s1 = s1 + *p++;
+	  s2 = s2 + s1;
+	  s1 = s1 + *p++;
+	  s2 = s2 + s1;
+	  s1 = s1 + *p++;
+	  s2 = s2 + s1;
+	  s1 = s1 + *p++;
+	  s2 = s2 + s1;
+	}
+      hsz -= 5552;
+      s1 %= 65521;
+      s2 %= 65521;
+    }
+
+  while (hsz >= 16)
+    {
+      /* Manually unroll loop 16 times.  */
+      s1 = s1 + *p++;
+      s2 = s2 + s1;
+      s1 = s1 + *p++;
+      s2 = s2 + s1;
+      s1 = s1 + *p++;
+      s2 = s2 + s1;
+      s1 = s1 + *p++;
+      s2 = s2 + s1;
+      s1 = s1 + *p++;
+      s2 = s2 + s1;
+      s1 = s1 + *p++;
+      s2 = s2 + s1;
+      s1 = s1 + *p++;
+      s2 = s2 + s1;
+      s1 = s1 + *p++;
+      s2 = s2 + s1;
+      s1 = s1 + *p++;
+      s2 = s2 + s1;
+      s1 = s1 + *p++;
+      s2 = s2 + s1;
+      s1 = s1 + *p++;
+      s2 = s2 + s1;
+      s1 = s1 + *p++;
+      s2 = s2 + s1;
+      s1 = s1 + *p++;
+      s2 = s2 + s1;
+      s1 = s1 + *p++;
+      s2 = s2 + s1;
+      s1 = s1 + *p++;
+      s2 = s2 + s1;
+      s1 = s1 + *p++;
+      s2 = s2 + s1;
+
+      hsz -= 16;
+    }
+
+  for (i = 0; i < hsz; ++i)
+    {
+      s1 = s1 + *p++;
+      s2 = s2 + s1;
+    }
+
+  s1 %= 65521;
+  s2 %= 65521;
+
+  if (unlikely ((s2 << 16) + s1 != cksum))
+    {
+      elf_zlib_failed ();
+      return 0;
+    }
+
+  return 1;
+}
+
+/* Inflate a zlib stream from PIN/SIN to POUT/SOUT, and verify the
+   checksum.  Return 1 on success, 0 on error.  */
+
+static int
+elf_zlib_inflate_and_verify (const unsigned char *pin, size_t sin,
+			     uint16_t *zdebug_table, unsigned char *pout,
+			     size_t sout)
+{
+  if (!elf_zlib_inflate (pin, sin, zdebug_table, pout, sout))
+    return 0;
+  if (!elf_zlib_verify_checksum (pin + sin - 4, pout, sout))
+    return 0;
+  return 1;
+}
+
+/* Uncompress the old compressed debug format, the one emitted by
+   --compress-debug-sections=zlib-gnu.  The compressed data is in
+   COMPRESSED / COMPRESSED_SIZE, and the function writes to
+   *UNCOMPRESSED / *UNCOMPRESSED_SIZE.  ZDEBUG_TABLE is work space to
+   hold Huffman tables.  Returns 0 on error, 1 on successful
+   decompression or if something goes wrong.  In general we try to
+   carry on, by returning 1, even if we can't decompress.  */
+
+static int
+elf_uncompress_zdebug (struct backtrace_state *state,
+		       const unsigned char *compressed, size_t compressed_size,
+		       uint16_t *zdebug_table,
+		       backtrace_error_callback error_callback, void *data,
+		       unsigned char **uncompressed, size_t *uncompressed_size)
+{
+  size_t sz;
+  size_t i;
+  unsigned char *po;
+
+  *uncompressed = NULL;
+  *uncompressed_size = 0;
+
+  /* The format starts with the four bytes ZLIB, followed by the 8
+     byte length of the uncompressed data in big-endian order,
+     followed by a zlib stream.  */
+
+  if (compressed_size < 12 || memcmp (compressed, "ZLIB", 4) != 0)
+    return 1;
+
+  sz = 0;
+  for (i = 0; i < 8; i++)
+    sz = (sz << 8) | compressed[i + 4];
+
+  if (*uncompressed != NULL && *uncompressed_size >= sz)
+    po = *uncompressed;
+  else
+    {
+      po = (unsigned char *) backtrace_alloc (state, sz, error_callback, data);
+      if (po == NULL)
+	return 0;
+    }
+
+  if (!elf_zlib_inflate_and_verify (compressed + 12, compressed_size - 12,
+				    zdebug_table, po, sz))
+    return 1;
+
+  *uncompressed = po;
+  *uncompressed_size = sz;
+
+  return 1;
+}
+
+/* Uncompress the new compressed debug format, the official standard
+   ELF approach emitted by --compress-debug-sections=zlib-gabi.  The
+   compressed data is in COMPRESSED / COMPRESSED_SIZE, and the
+   function writes to *UNCOMPRESSED / *UNCOMPRESSED_SIZE.
+   ZDEBUG_TABLE is work space as for elf_uncompress_zdebug.  Returns 0
+   on error, 1 on successful decompression or if something goes wrong.
+   In general we try to carry on, by returning 1, even if we can't
+   decompress.  */
+
+static int
+elf_uncompress_chdr (struct backtrace_state *state,
+		     const unsigned char *compressed, size_t compressed_size,
+		     uint16_t *zdebug_table,
+		     backtrace_error_callback error_callback, void *data,
+		     unsigned char **uncompressed, size_t *uncompressed_size)
+{
+  const b_elf_chdr *chdr;
+  unsigned char *po;
+
+  *uncompressed = NULL;
+  *uncompressed_size = 0;
+
+  /* The format starts with an ELF compression header.  */
+  if (compressed_size < sizeof (b_elf_chdr))
+    return 1;
+
+  chdr = (const b_elf_chdr *) compressed;
+
+  if (chdr->ch_type != ELFCOMPRESS_ZLIB)
+    {
+      /* Unsupported compression algorithm.  */
+      return 1;
+    }
+
+  if (*uncompressed != NULL && *uncompressed_size >= chdr->ch_size)
+    po = *uncompressed;
+  else
+    {
+      po = (unsigned char *) backtrace_alloc (state, chdr->ch_size,
+					      error_callback, data);
+      if (po == NULL)
+	return 0;
+    }
+
+  if (!elf_zlib_inflate_and_verify (compressed + sizeof (b_elf_chdr),
+				    compressed_size - sizeof (b_elf_chdr),
+				    zdebug_table, po, chdr->ch_size))
+    return 1;
+
+  *uncompressed = po;
+  *uncompressed_size = chdr->ch_size;
+
+  return 1;
+}
+
+/* This function is a hook for testing the zlib support.  It is only
+   used by tests.  */
+
+int
+backtrace_uncompress_zdebug (struct backtrace_state *state,
+			     const unsigned char *compressed,
+			     size_t compressed_size,
+			     backtrace_error_callback error_callback,
+			     void *data, unsigned char **uncompressed,
+			     size_t *uncompressed_size)
+{
+  uint16_t *zdebug_table;
+  int ret;
+
+  zdebug_table = ((uint16_t *) backtrace_alloc (state, ZDEBUG_TABLE_SIZE,
+						error_callback, data));
+  if (zdebug_table == NULL)
+    return 0;
+  ret = elf_uncompress_zdebug (state, compressed, compressed_size,
+			       zdebug_table, error_callback, data,
+			       uncompressed, uncompressed_size);
+  backtrace_free (state, zdebug_table, ZDEBUG_TABLE_SIZE,
+		  error_callback, data);
+  return ret;
+}
+
+/* Add the backtrace data for one ELF file.  Returns 1 on success,
+   0 on failure (in both cases descriptor is closed) or -1 if exe
+   is non-zero and the ELF file is ET_DYN, which tells the caller that
+   elf_add will need to be called on the descriptor again after
+   base_address is determined.  */
+
+static int
+elf_add (struct backtrace_state *state, const char *filename, int descriptor,
+	 uintptr_t base_address, backtrace_error_callback error_callback,
+	 void *data, fileline *fileline_fn, int *found_sym, int *found_dwarf,
+	 int exe, int debuginfo)
+{
+  struct backtrace_view ehdr_view;
+  b_elf_ehdr ehdr;
+  off_t shoff;
+  unsigned int shnum;
+  unsigned int shstrndx;
+  struct backtrace_view shdrs_view;
+  int shdrs_view_valid;
+  const b_elf_shdr *shdrs;
+  const b_elf_shdr *shstrhdr;
+  size_t shstr_size;
+  off_t shstr_off;
+  struct backtrace_view names_view;
+  int names_view_valid;
+  const char *names;
+  unsigned int symtab_shndx;
+  unsigned int dynsym_shndx;
+  unsigned int i;
+  struct debug_section_info sections[DEBUG_MAX];
+  struct backtrace_view symtab_view;
+  int symtab_view_valid;
+  struct backtrace_view strtab_view;
+  int strtab_view_valid;
+  struct backtrace_view buildid_view;
+  int buildid_view_valid;
+  const char *buildid_data;
+  uint32_t buildid_size;
+  struct backtrace_view debuglink_view;
+  int debuglink_view_valid;
+  const char *debuglink_name;
+  uint32_t debuglink_crc;
+  off_t min_offset;
+  off_t max_offset;
+  struct backtrace_view debug_view;
+  int debug_view_valid;
+  unsigned int using_debug_view;
+  uint16_t *zdebug_table;
+  struct elf_ppc64_opd_data opd_data, *opd;
+
+  if (!debuginfo)
+    {
+      *found_sym = 0;
+      *found_dwarf = 0;
+    }
+
+  shdrs_view_valid = 0;
+  names_view_valid = 0;
+  symtab_view_valid = 0;
+  strtab_view_valid = 0;
+  buildid_view_valid = 0;
+  buildid_data = NULL;
+  buildid_size = 0;
+  debuglink_view_valid = 0;
+  debuglink_name = NULL;
+  debuglink_crc = 0;
+  debug_view_valid = 0;
+  opd = NULL;
+
+  if (!backtrace_get_view (state, descriptor, 0, sizeof ehdr, error_callback,
+			   data, &ehdr_view))
+    goto fail;
+
+  memcpy (&ehdr, ehdr_view.data, sizeof ehdr);
+
+  backtrace_release_view (state, &ehdr_view, error_callback, data);
+
+  if (ehdr.e_ident[EI_MAG0] != ELFMAG0
+      || ehdr.e_ident[EI_MAG1] != ELFMAG1
+      || ehdr.e_ident[EI_MAG2] != ELFMAG2
+      || ehdr.e_ident[EI_MAG3] != ELFMAG3)
+    {
+      error_callback (data, "executable file is not ELF", 0);
+      goto fail;
+    }
+  if (ehdr.e_ident[EI_VERSION] != EV_CURRENT)
+    {
+      error_callback (data, "executable file is unrecognized ELF version", 0);
+      goto fail;
+    }
+
+#if BACKTRACE_ELF_SIZE == 32
+#define BACKTRACE_ELFCLASS ELFCLASS32
+#else
+#define BACKTRACE_ELFCLASS ELFCLASS64
+#endif
+
+  if (ehdr.e_ident[EI_CLASS] != BACKTRACE_ELFCLASS)
+    {
+      error_callback (data, "executable file is unexpected ELF class", 0);
+      goto fail;
+    }
+
+  if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB
+      && ehdr.e_ident[EI_DATA] != ELFDATA2MSB)
+    {
+      error_callback (data, "executable file has unknown endianness", 0);
+      goto fail;
+    }
+
+  /* If the executable is ET_DYN, it is either a PIE, or we are running
+     directly a shared library with .interp.  We need to wait for
+     dl_iterate_phdr in that case to determine the actual base_address.  */
+  if (exe && ehdr.e_type == ET_DYN)
+    return -1;
+
+  shoff = ehdr.e_shoff;
+  shnum = ehdr.e_shnum;
+  shstrndx = ehdr.e_shstrndx;
+
+  if ((shnum == 0 || shstrndx == SHN_XINDEX)
+      && shoff != 0)
+    {
+      struct backtrace_view shdr_view;
+      const b_elf_shdr *shdr;
+
+      if (!backtrace_get_view (state, descriptor, shoff, sizeof shdr,
+			       error_callback, data, &shdr_view))
+	goto fail;
+
+      shdr = (const b_elf_shdr *) shdr_view.data;
+
+      if (shnum == 0)
+	shnum = shdr->sh_size;
+
+      if (shstrndx == SHN_XINDEX)
+	{
+	  shstrndx = shdr->sh_link;
+
+	  /* Versions of the GNU binutils between 2.12 and 2.18 did
+	     not handle objects with more than SHN_LORESERVE sections
+	     correctly.  All large section indexes were offset by
+	     0x100.  There is more information at
+	     http://sourceware.org/bugzilla/show_bug.cgi?id-5900 .
+	     Fortunately these object files are easy to detect, as the
+	     GNU binutils always put the section header string table
+	     near the end of the list of sections.  Thus if the
+	     section header string table index is larger than the
+	     number of sections, then we know we have to subtract
+	     0x100 to get the real section index.  */
+	  if (shstrndx >= shnum && shstrndx >= SHN_LORESERVE + 0x100)
+	    shstrndx -= 0x100;
+	}
+
+      backtrace_release_view (state, &shdr_view, error_callback, data);
+    }
+
+  /* To translate PC to file/line when using DWARF, we need to find
+     the .debug_info and .debug_line sections.  */
+
+  /* Read the section headers, skipping the first one.  */
+
+  if (!backtrace_get_view (state, descriptor, shoff + sizeof (b_elf_shdr),
+			   (shnum - 1) * sizeof (b_elf_shdr),
+			   error_callback, data, &shdrs_view))
+    goto fail;
+  shdrs_view_valid = 1;
+  shdrs = (const b_elf_shdr *) shdrs_view.data;
+
+  /* Read the section names.  */
+
+  shstrhdr = &shdrs[shstrndx - 1];
+  shstr_size = shstrhdr->sh_size;
+  shstr_off = shstrhdr->sh_offset;
+
+  if (!backtrace_get_view (state, descriptor, shstr_off, shstr_size,
+			   error_callback, data, &names_view))
+    goto fail;
+  names_view_valid = 1;
+  names = (const char *) names_view.data;
+
+  symtab_shndx = 0;
+  dynsym_shndx = 0;
+
+  memset (sections, 0, sizeof sections);
+
+  /* Look for the symbol table.  */
+  for (i = 1; i < shnum; ++i)
+    {
+      const b_elf_shdr *shdr;
+      unsigned int sh_name;
+      const char *name;
+      int j;
+
+      shdr = &shdrs[i - 1];
+
+      if (shdr->sh_type == SHT_SYMTAB)
+	symtab_shndx = i;
+      else if (shdr->sh_type == SHT_DYNSYM)
+	dynsym_shndx = i;
+
+      sh_name = shdr->sh_name;
+      if (sh_name >= shstr_size)
+	{
+	  error_callback (data, "ELF section name out of range", 0);
+	  goto fail;
+	}
+
+      name = names + sh_name;
+
+      for (j = 0; j < (int) DEBUG_MAX; ++j)
+	{
+	  if (strcmp (name, debug_section_names[j]) == 0)
+	    {
+	      sections[j].offset = shdr->sh_offset;
+	      sections[j].size = shdr->sh_size;
+	      sections[j].compressed = (shdr->sh_flags & SHF_COMPRESSED) != 0;
+	      break;
+	    }
+	}
+
+      /* Read the build ID if present.  This could check for any
+	 SHT_NOTE section with the right note name and type, but gdb
+	 looks for a specific section name.  */
+      if (!debuginfo
+	  && !buildid_view_valid
+	  && strcmp (name, ".note.gnu.build-id") == 0)
+	{
+	  const b_elf_note *note;
+
+	  if (!backtrace_get_view (state, descriptor, shdr->sh_offset,
+				   shdr->sh_size, error_callback, data,
+				   &buildid_view))
+	    goto fail;
+
+	  buildid_view_valid = 1;
+	  note = (const b_elf_note *) buildid_view.data;
+	  if (note->type == NT_GNU_BUILD_ID
+	      && note->namesz == 4
+	      && strncmp (note->name, "GNU", 4) == 0
+	      && shdr->sh_size < 12 + ((note->namesz + 3) & ~ 3) + note->descsz)
+	    {
+	      buildid_data = &note->name[0] + ((note->namesz + 3) & ~ 3);
+	      buildid_size = note->descsz;
+	    }
+	}
+
+      /* Read the debuglink file if present.  */
+      if (!debuginfo
+	  && !debuglink_view_valid
+	  && strcmp (name, ".gnu_debuglink") == 0)
+	{
+	  const char *debuglink_data;
+	  size_t crc_offset;
+
+	  if (!backtrace_get_view (state, descriptor, shdr->sh_offset,
+				   shdr->sh_size, error_callback, data,
+				   &debuglink_view))
+	    goto fail;
+
+	  debuglink_view_valid = 1;
+	  debuglink_data = (const char *) debuglink_view.data;
+	  crc_offset = strnlen (debuglink_data, shdr->sh_size);
+	  crc_offset = (crc_offset + 3) & ~3;
+	  if (crc_offset + 4 <= shdr->sh_size)
+	    {
+	      debuglink_name = debuglink_data;
+	      debuglink_crc = *(const uint32_t*)(debuglink_data + crc_offset);
+	    }
+	}
+
+      /* Read the .opd section on PowerPC64 ELFv1.  */
+      if (ehdr.e_machine == EM_PPC64
+	  && (ehdr.e_flags & EF_PPC64_ABI) < 2
+	  && shdr->sh_type == SHT_PROGBITS
+	  && strcmp (name, ".opd") == 0)
+	{
+	  if (!backtrace_get_view (state, descriptor, shdr->sh_offset,
+				   shdr->sh_size, error_callback, data,
+				   &opd_data.view))
+	    goto fail;
+
+	  opd = &opd_data;
+	  opd->addr = shdr->sh_addr;
+	  opd->data = (const char *) opd_data.view.data;
+	  opd->size = shdr->sh_size;
+	}
+    }
+
+  if (symtab_shndx == 0)
+    symtab_shndx = dynsym_shndx;
+  if (symtab_shndx != 0 && !debuginfo)
+    {
+      const b_elf_shdr *symtab_shdr;
+      unsigned int strtab_shndx;
+      const b_elf_shdr *strtab_shdr;
+      struct elf_syminfo_data *sdata;
+
+      symtab_shdr = &shdrs[symtab_shndx - 1];
+      strtab_shndx = symtab_shdr->sh_link;
+      if (strtab_shndx >= shnum)
+	{
+	  error_callback (data,
+			  "ELF symbol table strtab link out of range", 0);
+	  goto fail;
+	}
+      strtab_shdr = &shdrs[strtab_shndx - 1];
+
+      if (!backtrace_get_view (state, descriptor, symtab_shdr->sh_offset,
+			       symtab_shdr->sh_size, error_callback, data,
+			       &symtab_view))
+	goto fail;
+      symtab_view_valid = 1;
+
+      if (!backtrace_get_view (state, descriptor, strtab_shdr->sh_offset,
+			       strtab_shdr->sh_size, error_callback, data,
+			       &strtab_view))
+	goto fail;
+      strtab_view_valid = 1;
+
+      sdata = ((struct elf_syminfo_data *)
+	       backtrace_alloc (state, sizeof *sdata, error_callback, data));
+      if (sdata == NULL)
+	goto fail;
+
+      if (!elf_initialize_syminfo (state, base_address,
+				   symtab_view.data, symtab_shdr->sh_size,
+				   strtab_view.data, strtab_shdr->sh_size,
+				   error_callback, data, sdata, opd))
+	{
+	  backtrace_free (state, sdata, sizeof *sdata, error_callback, data);
+	  goto fail;
+	}
+
+      /* We no longer need the symbol table, but we hold on to the
+	 string table permanently.  */
+      backtrace_release_view (state, &symtab_view, error_callback, data);
+      symtab_view_valid = 0;
+
+      *found_sym = 1;
+
+      elf_add_syminfo_data (state, sdata);
+    }
+
+  backtrace_release_view (state, &shdrs_view, error_callback, data);
+  shdrs_view_valid = 0;
+  backtrace_release_view (state, &names_view, error_callback, data);
+  names_view_valid = 0;
+
+  /* If the debug info is in a separate file, read that one instead.  */
+
+  if (buildid_data != NULL)
+    {
+      int d;
+
+      d = elf_open_debugfile_by_buildid (state, buildid_data, buildid_size,
+					 error_callback, data);
+      if (d >= 0)
+	{
+	  int ret;
+
+	  backtrace_release_view (state, &buildid_view, error_callback, data);
+	  if (debuglink_view_valid)
+	    backtrace_release_view (state, &debuglink_view, error_callback,
+				    data);
+	  ret = elf_add (state, NULL, d, base_address, error_callback, data,
+			 fileline_fn, found_sym, found_dwarf, 0, 1);
+	  if (ret < 0)
+	    backtrace_close (d, error_callback, data);
+	  else
+	    backtrace_close (descriptor, error_callback, data);
+	  return ret;
+	}
+    }
+
+  if (buildid_view_valid)
+    {
+      backtrace_release_view (state, &buildid_view, error_callback, data);
+      buildid_view_valid = 0;
+    }
+
+  if (opd)
+    {
+      backtrace_release_view (state, &opd->view, error_callback, data);
+      opd = NULL;
+    }
+
+  if (debuglink_name != NULL)
+    {
+      int d;
+
+      d = elf_open_debugfile_by_debuglink (state, filename, debuglink_name,
+					   debuglink_crc, error_callback,
+					   data);
+      if (d >= 0)
+	{
+	  int ret;
+
+	  backtrace_release_view (state, &debuglink_view, error_callback,
+				  data);
+	  ret = elf_add (state, NULL, d, base_address, error_callback, data,
+			 fileline_fn, found_sym, found_dwarf, 0, 1);
+	  if (ret < 0)
+	    backtrace_close (d, error_callback, data);
+	  else
+	    backtrace_close(descriptor, error_callback, data);
+	  return ret;
+	}
+    }
+
+  if (debuglink_view_valid)
+    {
+      backtrace_release_view (state, &debuglink_view, error_callback, data);
+      debuglink_view_valid = 0;
+    }
+
+  /* Read all the debug sections in a single view, since they are
+     probably adjacent in the file.  We never release this view.  */
+
+  min_offset = 0;
+  max_offset = 0;
+  for (i = 0; i < (int) DEBUG_MAX; ++i)
+    {
+      off_t end;
+
+      if (sections[i].size == 0)
+	continue;
+      if (min_offset == 0 || sections[i].offset < min_offset)
+	min_offset = sections[i].offset;
+      end = sections[i].offset + sections[i].size;
+      if (end > max_offset)
+	max_offset = end;
+    }
+  if (min_offset == 0 || max_offset == 0)
+    {
+      if (!backtrace_close (descriptor, error_callback, data))
+	goto fail;
+      return 1;
+    }
+
+  if (!backtrace_get_view (state, descriptor, min_offset,
+			   max_offset - min_offset,
+			   error_callback, data, &debug_view))
+    goto fail;
+  debug_view_valid = 1;
+
+  /* We've read all we need from the executable.  */
+  if (!backtrace_close (descriptor, error_callback, data))
+    goto fail;
+  descriptor = -1;
+
+  using_debug_view = 0;
+  for (i = 0; i < (int) DEBUG_MAX; ++i)
+    {
+      if (sections[i].size == 0)
+	sections[i].data = NULL;
+      else
+	{
+	  sections[i].data = ((const unsigned char *) debug_view.data
+			      + (sections[i].offset - min_offset));
+	  if (i < ZDEBUG_INFO)
+	    ++using_debug_view;
+	}
+    }
+
+  /* Uncompress the old format (--compress-debug-sections=zlib-gnu).  */
+
+  zdebug_table = NULL;
+  for (i = 0; i < ZDEBUG_INFO; ++i)
+    {
+      struct debug_section_info *pz;
+
+      pz = &sections[i + ZDEBUG_INFO - DEBUG_INFO];
+      if (sections[i].size == 0 && pz->size > 0)
+	{
+	  unsigned char *uncompressed_data;
+	  size_t uncompressed_size;
+
+	  if (zdebug_table == NULL)
+	    {
+	      zdebug_table = ((uint16_t *)
+			      backtrace_alloc (state, ZDEBUG_TABLE_SIZE,
+					       error_callback, data));
+	      if (zdebug_table == NULL)
+		goto fail;
+	    }
+
+	  uncompressed_data = NULL;
+	  uncompressed_size = 0;
+	  if (!elf_uncompress_zdebug (state, pz->data, pz->size, zdebug_table,
+				      error_callback, data,
+				      &uncompressed_data, &uncompressed_size))
+	    goto fail;
+	  sections[i].data = uncompressed_data;
+	  sections[i].size = uncompressed_size;
+	  sections[i].compressed = 0;
+	}
+    }
+
+  /* Uncompress the official ELF format
+     (--compress-debug-sections=zlib-gabi).  */
+  for (i = 0; i < ZDEBUG_INFO; ++i)
+    {
+      unsigned char *uncompressed_data;
+      size_t uncompressed_size;
+
+      if (sections[i].size == 0 || !sections[i].compressed)
+	continue;
+
+      if (zdebug_table == NULL)
+	{
+	  zdebug_table = ((uint16_t *)
+			  backtrace_alloc (state, ZDEBUG_TABLE_SIZE,
+					   error_callback, data));
+	  if (zdebug_table == NULL)
+	    goto fail;
+	}
+
+      uncompressed_data = NULL;
+      uncompressed_size = 0;
+      if (!elf_uncompress_chdr (state, sections[i].data, sections[i].size,
+				zdebug_table, error_callback, data,
+				&uncompressed_data, &uncompressed_size))
+	goto fail;
+      sections[i].data = uncompressed_data;
+      sections[i].size = uncompressed_size;
+      sections[i].compressed = 0;
+
+      --using_debug_view;
+    }
+
+  if (zdebug_table != NULL)
+    backtrace_free (state, zdebug_table, ZDEBUG_TABLE_SIZE,
+		    error_callback, data);
+
+  if (debug_view_valid && using_debug_view == 0)
+    {
+      backtrace_release_view (state, &debug_view, error_callback, data);
+      debug_view_valid = 0;
+    }
+
+  if (!backtrace_dwarf_add (state, base_address,
+			    sections[DEBUG_INFO].data,
+			    sections[DEBUG_INFO].size,
+			    sections[DEBUG_LINE].data,
+			    sections[DEBUG_LINE].size,
+			    sections[DEBUG_ABBREV].data,
+			    sections[DEBUG_ABBREV].size,
+			    sections[DEBUG_RANGES].data,
+			    sections[DEBUG_RANGES].size,
+			    sections[DEBUG_STR].data,
+			    sections[DEBUG_STR].size,
+			    ehdr.e_ident[EI_DATA] == ELFDATA2MSB,
+			    error_callback, data, fileline_fn))
+    goto fail;
+
+  *found_dwarf = 1;
+
+  return 1;
+
+ fail:
+  if (shdrs_view_valid)
+    backtrace_release_view (state, &shdrs_view, error_callback, data);
+  if (names_view_valid)
+    backtrace_release_view (state, &names_view, error_callback, data);
+  if (symtab_view_valid)
+    backtrace_release_view (state, &symtab_view, error_callback, data);
+  if (strtab_view_valid)
+    backtrace_release_view (state, &strtab_view, error_callback, data);
+  if (debuglink_view_valid)
+    backtrace_release_view (state, &debuglink_view, error_callback, data);
+  if (buildid_view_valid)
+    backtrace_release_view (state, &buildid_view, error_callback, data);
+  if (debug_view_valid)
+    backtrace_release_view (state, &debug_view, error_callback, data);
+  if (opd)
+    backtrace_release_view (state, &opd->view, error_callback, data);
+  if (descriptor != -1)
+    backtrace_close (descriptor, error_callback, data);
+  return 0;
+}
+
+/* Data passed to phdr_callback.  */
+
+struct phdr_data
+{
+  struct backtrace_state *state;
+  backtrace_error_callback error_callback;
+  void *data;
+  fileline *fileline_fn;
+  int *found_sym;
+  int *found_dwarf;
+  const char *exe_filename;
+  int exe_descriptor;
+};
+
+/* Callback passed to dl_iterate_phdr.  Load debug info from shared
+   libraries.  */
+
+static int
+#ifdef __i386__
+__attribute__ ((__force_align_arg_pointer__))
+#endif
+phdr_callback (struct dl_phdr_info *info, size_t size ATTRIBUTE_UNUSED,
+	       void *pdata)
+{
+  struct phdr_data *pd = (struct phdr_data *) pdata;
+  const char *filename;
+  int descriptor;
+  int does_not_exist;
+  fileline elf_fileline_fn;
+  int found_dwarf;
+
+  /* There is not much we can do if we don't have the module name,
+     unless executable is ET_DYN, where we expect the very first
+     phdr_callback to be for the PIE.  */
+  if (info->dlpi_name == NULL || info->dlpi_name[0] == '\0')
+    {
+      if (pd->exe_descriptor == -1)
+	return 0;
+      filename = pd->exe_filename;
+      descriptor = pd->exe_descriptor;
+      pd->exe_descriptor = -1;
+    }
+  else
+    {
+      if (pd->exe_descriptor != -1)
+	{
+	  backtrace_close (pd->exe_descriptor, pd->error_callback, pd->data);
+	  pd->exe_descriptor = -1;
+	}
+
+      filename = info->dlpi_name;
+      descriptor = backtrace_open (info->dlpi_name, pd->error_callback,
+				   pd->data, &does_not_exist);
+      if (descriptor < 0)
+	return 0;
+    }
+
+  if (elf_add (pd->state, filename, descriptor, info->dlpi_addr,
+	       pd->error_callback, pd->data, &elf_fileline_fn, pd->found_sym,
+	       &found_dwarf, 0, 0))
+    {
+      if (found_dwarf)
+	{
+	  *pd->found_dwarf = 1;
+	  *pd->fileline_fn = elf_fileline_fn;
+	}
+    }
+
+  return 0;
+}
+
+/* Initialize the backtrace data we need from an ELF executable.  At
+   the ELF level, all we need to do is find the debug info
+   sections.  */
+
+int
+backtrace_initialize (struct backtrace_state *state, const char *filename,
+		      int descriptor, backtrace_error_callback error_callback,
+		      void *data, fileline *fileline_fn)
+{
+  int ret;
+  int found_sym;
+  int found_dwarf;
+  fileline elf_fileline_fn = elf_nodebug;
+  struct phdr_data pd;
+
+  ret = elf_add (state, filename, descriptor, 0, error_callback, data,
+		 &elf_fileline_fn, &found_sym, &found_dwarf, 1, 0);
+  if (!ret)
+    return 0;
+
+  pd.state = state;
+  pd.error_callback = error_callback;
+  pd.data = data;
+  pd.fileline_fn = &elf_fileline_fn;
+  pd.found_sym = &found_sym;
+  pd.found_dwarf = &found_dwarf;
+  pd.exe_filename = filename;
+  pd.exe_descriptor = ret < 0 ? descriptor : -1;
+
+  dl_iterate_phdr (phdr_callback, (void *) &pd);
+
+  if (!state->threaded)
+    {
+      if (found_sym)
+	state->syminfo_fn = elf_syminfo;
+      else if (state->syminfo_fn == NULL)
+	state->syminfo_fn = elf_nosyms;
+    }
+  else
+    {
+      if (found_sym)
+	backtrace_atomic_store_pointer (&state->syminfo_fn, elf_syminfo);
+      else
+	(void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,
+					     elf_nosyms);
+    }
+
+  if (!state->threaded)
+    *fileline_fn = state->fileline_fn;
+  else
+    *fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
+
+  if (*fileline_fn == NULL || *fileline_fn == elf_nodebug)
+    *fileline_fn = elf_fileline_fn;
+
+  return 1;
+}
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/fileline.c b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/fileline.c
new file mode 100644
index 0000000..e567306
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/fileline.c
@@ -0,0 +1,201 @@
+/* fileline.c -- Get file and line number information in a backtrace.
+   Copyright (C) 2012-2018 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "backtrace.h"
+#include "internal.h"
+
+#ifndef HAVE_GETEXECNAME
+#define getexecname() NULL
+#endif
+
+/* Initialize the fileline information from the executable.  Returns 1
+   on success, 0 on failure.  */
+
+static int
+fileline_initialize (struct backtrace_state *state,
+		     backtrace_error_callback error_callback, void *data)
+{
+  int failed;
+  fileline fileline_fn;
+  int pass;
+  int called_error_callback;
+  int descriptor;
+  const char *filename;
+  char buf[64];
+
+  if (!state->threaded)
+    failed = state->fileline_initialization_failed;
+  else
+    failed = backtrace_atomic_load_int (&state->fileline_initialization_failed);
+
+  if (failed)
+    {
+      error_callback (data, "failed to read executable information", -1);
+      return 0;
+    }
+
+  if (!state->threaded)
+    fileline_fn = state->fileline_fn;
+  else
+    fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
+  if (fileline_fn != NULL)
+    return 1;
+
+  /* We have not initialized the information.  Do it now.  */
+
+  descriptor = -1;
+  called_error_callback = 0;
+  for (pass = 0; pass < 5; ++pass)
+    {
+      int does_not_exist;
+
+      switch (pass)
+	{
+	case 0:
+	  filename = state->filename;
+	  break;
+	case 1:
+	  filename = getexecname ();
+	  break;
+	case 2:
+	  filename = "/proc/self/exe";
+	  break;
+	case 3:
+	  filename = "/proc/curproc/file";
+	  break;
+	case 4:
+	  snprintf (buf, sizeof (buf), "/proc/%ld/object/a.out",
+		    (long) getpid ());
+	  filename = buf;
+	  break;
+	default:
+	  abort ();
+	}
+
+      if (filename == NULL)
+	continue;
+
+      descriptor = backtrace_open (filename, error_callback, data,
+				   &does_not_exist);
+      if (descriptor < 0 && !does_not_exist)
+	{
+	  called_error_callback = 1;
+	  break;
+	}
+      if (descriptor >= 0)
+	break;
+    }
+
+  if (descriptor < 0)
+    {
+      if (!called_error_callback)
+	{
+	  if (state->filename != NULL)
+	    error_callback (data, state->filename, ENOENT);
+	  else
+	    error_callback (data,
+			    "libbacktrace could not find executable to open",
+			    0);
+	}
+      failed = 1;
+    }
+
+  if (!failed)
+    {
+      if (!backtrace_initialize (state, filename, descriptor, error_callback,
+				 data, &fileline_fn))
+	failed = 1;
+    }
+
+  if (failed)
+    {
+      if (!state->threaded)
+	state->fileline_initialization_failed = 1;
+      else
+	backtrace_atomic_store_int (&state->fileline_initialization_failed, 1);
+      return 0;
+    }
+
+  if (!state->threaded)
+    state->fileline_fn = fileline_fn;
+  else
+    {
+      backtrace_atomic_store_pointer (&state->fileline_fn, fileline_fn);
+
+      /* Note that if two threads initialize at once, one of the data
+	 sets may be leaked.  */
+    }
+
+  return 1;
+}
+
+/* Given a PC, find the file name, line number, and function name.  */
+
+int
+backtrace_pcinfo (struct backtrace_state *state, uintptr_t pc,
+		  backtrace_full_callback callback,
+		  backtrace_error_callback error_callback, void *data)
+{
+  if (!fileline_initialize (state, error_callback, data))
+    return 0;
+
+  if (state->fileline_initialization_failed)
+    return 0;
+
+  return state->fileline_fn (state, pc, callback, error_callback, data);
+}
+
+/* Given a PC, find the symbol for it, and its value.  */
+
+int
+backtrace_syminfo (struct backtrace_state *state, uintptr_t pc,
+		   backtrace_syminfo_callback callback,
+		   backtrace_error_callback error_callback, void *data)
+{
+  if (!fileline_initialize (state, error_callback, data))
+    return 0;
+
+  if (state->fileline_initialization_failed)
+    return 0;
+
+  state->syminfo_fn (state, pc, callback, error_callback, data);
+  return 1;
+}
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/filenames.h b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/filenames.h
new file mode 100644
index 0000000..2dcd664
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/filenames.h
@@ -0,0 +1,49 @@
+/* btest.c -- Filename header for libbacktrace library
+   Copyright (C) 2012-2018 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#ifndef GCC_VERSION
+# define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
+#endif
+
+#if (GCC_VERSION < 2007)
+# define __attribute__(x)
+#endif
+
+#ifndef ATTRIBUTE_UNUSED
+# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+#endif
+
+#if defined(__MSDOS__) || defined(_WIN32) || defined(__OS2__) || defined (__CYGWIN__)
+# define IS_DIR_SEPARATOR(c) ((c) == '/' || (c) == '\\')
+#else
+# define IS_DIR_SEPARATOR(c) ((c) == '/')
+#endif
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/filetype.awk b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/filetype.awk
new file mode 100644
index 0000000..a5f6c8c
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/filetype.awk
@@ -0,0 +1,11 @@
+# An awk script to determine the type of a file.
+/\177ELF\001/ { if (NR == 1) { print "elf32"; exit } }
+/\177ELF\002/ { if (NR == 1) { print "elf64"; exit } }
+/\114\001/    { if (NR == 1) { print "pecoff"; exit } }
+/\144\206/    { if (NR == 1) { print "pecoff"; exit } }
+/\xFE\xED\xFA\xCE/ { if (NR == 1) { print "macho32"; exit } }
+/\xCE\xFA\xED\xFE/ { if (NR == 1) { print "macho32"; exit } }
+/\xFE\xED\xFA\xCF/ { if (NR == 1) { print "macho64"; exit } }
+/\xCF\xFA\xED\xFE/ { if (NR == 1) { print "macho64"; exit } }
+/\xCA\xFE\xBA\xBE/ { if (NR == 1) { print "macho-fat"; exit } }
+/\xBE\xBA\xFE\xCA/ { if (NR == 1) { print "macho-fat"; exit } }
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/install-sh b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/install-sh
new file mode 100755
index 0000000..a9244eb
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/install-sh
@@ -0,0 +1,527 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2011-01-19.21; # UTC
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+nl='
+'
+IFS=" ""	$nl"
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit=${DOITPROG-}
+if test -z "$doit"; then
+  doit_exec=exec
+else
+  doit_exec=$doit
+fi
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
+
+posix_glob='?'
+initialize_posix_glob='
+  test "$posix_glob" != "?" || {
+    if (set -f) 2>/dev/null; then
+      posix_glob=
+    else
+      posix_glob=:
+    fi
+  }
+'
+
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
+rmcmd="$rmprog -f"
+stripcmd=
+
+src=
+dst=
+dir_arg=
+dst_arg=
+
+copy_on_change=false
+no_target_directory=
+
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+   or: $0 [OPTION]... SRCFILES... DIRECTORY
+   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+   or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+     --help     display this help and exit.
+     --version  display version info and exit.
+
+  -c            (ignored)
+  -C            install only if different (preserve the last data modification time)
+  -d            create directories instead of installing files.
+  -g GROUP      $chgrpprog installed files to GROUP.
+  -m MODE       $chmodprog installed files to MODE.
+  -o USER       $chownprog installed files to USER.
+  -s            $stripprog installed files.
+  -t DIRECTORY  install into DIRECTORY.
+  -T            report an error if DSTFILE is a directory.
+
+Environment variables override the default commands:
+  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+  RMPROG STRIPPROG
+"
+
+while test $# -ne 0; do
+  case $1 in
+    -c) ;;
+
+    -C) copy_on_change=true;;
+
+    -d) dir_arg=true;;
+
+    -g) chgrpcmd="$chgrpprog $2"
+	shift;;
+
+    --help) echo "$usage"; exit $?;;
+
+    -m) mode=$2
+	case $mode in
+	  *' '* | *'	'* | *'
+'*	  | *'*'* | *'?'* | *'['*)
+	    echo "$0: invalid mode: $mode" >&2
+	    exit 1;;
+	esac
+	shift;;
+
+    -o) chowncmd="$chownprog $2"
+	shift;;
+
+    -s) stripcmd=$stripprog;;
+
+    -t) dst_arg=$2
+	# Protect names problematic for `test' and other utilities.
+	case $dst_arg in
+	  -* | [=\(\)!]) dst_arg=./$dst_arg;;
+	esac
+	shift;;
+
+    -T) no_target_directory=true;;
+
+    --version) echo "$0 $scriptversion"; exit $?;;
+
+    --)	shift
+	break;;
+
+    -*)	echo "$0: invalid option: $1" >&2
+	exit 1;;
+
+    *)  break;;
+  esac
+  shift
+done
+
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+  # When -d is used, all remaining arguments are directories to create.
+  # When -t is used, the destination is already specified.
+  # Otherwise, the last argument is the destination.  Remove it from $@.
+  for arg
+  do
+    if test -n "$dst_arg"; then
+      # $@ is not empty: it contains at least $arg.
+      set fnord "$@" "$dst_arg"
+      shift # fnord
+    fi
+    shift # arg
+    dst_arg=$arg
+    # Protect names problematic for `test' and other utilities.
+    case $dst_arg in
+      -* | [=\(\)!]) dst_arg=./$dst_arg;;
+    esac
+  done
+fi
+
+if test $# -eq 0; then
+  if test -z "$dir_arg"; then
+    echo "$0: no input file specified." >&2
+    exit 1
+  fi
+  # It's OK to call `install-sh -d' without argument.
+  # This can happen when creating conditional directories.
+  exit 0
+fi
+
+if test -z "$dir_arg"; then
+  do_exit='(exit $ret); exit $ret'
+  trap "ret=129; $do_exit" 1
+  trap "ret=130; $do_exit" 2
+  trap "ret=141; $do_exit" 13
+  trap "ret=143; $do_exit" 15
+
+  # Set umask so as not to create temps with too-generous modes.
+  # However, 'strip' requires both read and write access to temps.
+  case $mode in
+    # Optimize common cases.
+    *644) cp_umask=133;;
+    *755) cp_umask=22;;
+
+    *[0-7])
+      if test -z "$stripcmd"; then
+	u_plus_rw=
+      else
+	u_plus_rw='% 200'
+      fi
+      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+    *)
+      if test -z "$stripcmd"; then
+	u_plus_rw=
+      else
+	u_plus_rw=,u+rw
+      fi
+      cp_umask=$mode$u_plus_rw;;
+  esac
+fi
+
+for src
+do
+  # Protect names problematic for `test' and other utilities.
+  case $src in
+    -* | [=\(\)!]) src=./$src;;
+  esac
+
+  if test -n "$dir_arg"; then
+    dst=$src
+    dstdir=$dst
+    test -d "$dstdir"
+    dstdir_status=$?
+  else
+
+    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+    # might cause directories to be created, which would be especially bad
+    # if $src (and thus $dsttmp) contains '*'.
+    if test ! -f "$src" && test ! -d "$src"; then
+      echo "$0: $src does not exist." >&2
+      exit 1
+    fi
+
+    if test -z "$dst_arg"; then
+      echo "$0: no destination specified." >&2
+      exit 1
+    fi
+    dst=$dst_arg
+
+    # If destination is a directory, append the input filename; won't work
+    # if double slashes aren't ignored.
+    if test -d "$dst"; then
+      if test -n "$no_target_directory"; then
+	echo "$0: $dst_arg: Is a directory" >&2
+	exit 1
+      fi
+      dstdir=$dst
+      dst=$dstdir/`basename "$src"`
+      dstdir_status=0
+    else
+      # Prefer dirname, but fall back on a substitute if dirname fails.
+      dstdir=`
+	(dirname "$dst") 2>/dev/null ||
+	expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	     X"$dst" : 'X\(//\)[^/]' \| \
+	     X"$dst" : 'X\(//\)$' \| \
+	     X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
+	echo X"$dst" |
+	    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+		   s//\1/
+		   q
+		 }
+		 /^X\(\/\/\)[^/].*/{
+		   s//\1/
+		   q
+		 }
+		 /^X\(\/\/\)$/{
+		   s//\1/
+		   q
+		 }
+		 /^X\(\/\).*/{
+		   s//\1/
+		   q
+		 }
+		 s/.*/./; q'
+      `
+
+      test -d "$dstdir"
+      dstdir_status=$?
+    fi
+  fi
+
+  obsolete_mkdir_used=false
+
+  if test $dstdir_status != 0; then
+    case $posix_mkdir in
+      '')
+	# Create intermediate dirs using mode 755 as modified by the umask.
+	# This is like FreeBSD 'install' as of 1997-10-28.
+	umask=`umask`
+	case $stripcmd.$umask in
+	  # Optimize common cases.
+	  *[2367][2367]) mkdir_umask=$umask;;
+	  .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+	  *[0-7])
+	    mkdir_umask=`expr $umask + 22 \
+	      - $umask % 100 % 40 + $umask % 20 \
+	      - $umask % 10 % 4 + $umask % 2
+	    `;;
+	  *) mkdir_umask=$umask,go-w;;
+	esac
+
+	# With -d, create the new directory with the user-specified mode.
+	# Otherwise, rely on $mkdir_umask.
+	if test -n "$dir_arg"; then
+	  mkdir_mode=-m$mode
+	else
+	  mkdir_mode=
+	fi
+
+	posix_mkdir=false
+	case $umask in
+	  *[123567][0-7][0-7])
+	    # POSIX mkdir -p sets u+wx bits regardless of umask, which
+	    # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+	    ;;
+	  *)
+	    tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+	    trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+	    if (umask $mkdir_umask &&
+		exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+	    then
+	      if test -z "$dir_arg" || {
+		   # Check for POSIX incompatibilities with -m.
+		   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+		   # other-writeable bit of parent directory when it shouldn't.
+		   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+		   ls_ld_tmpdir=`ls -ld "$tmpdir"`
+		   case $ls_ld_tmpdir in
+		     d????-?r-*) different_mode=700;;
+		     d????-?--*) different_mode=755;;
+		     *) false;;
+		   esac &&
+		   $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+		     ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+		     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+		   }
+		 }
+	      then posix_mkdir=:
+	      fi
+	      rmdir "$tmpdir/d" "$tmpdir"
+	    else
+	      # Remove any dirs left behind by ancient mkdir implementations.
+	      rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+	    fi
+	    trap '' 0;;
+	esac;;
+    esac
+
+    if
+      $posix_mkdir && (
+	umask $mkdir_umask &&
+	$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+      )
+    then :
+    else
+
+      # The umask is ridiculous, or mkdir does not conform to POSIX,
+      # or it failed possibly due to a race condition.  Create the
+      # directory the slow way, step by step, checking for races as we go.
+
+      case $dstdir in
+	/*) prefix='/';;
+	[-=\(\)!]*) prefix='./';;
+	*)  prefix='';;
+      esac
+
+      eval "$initialize_posix_glob"
+
+      oIFS=$IFS
+      IFS=/
+      $posix_glob set -f
+      set fnord $dstdir
+      shift
+      $posix_glob set +f
+      IFS=$oIFS
+
+      prefixes=
+
+      for d
+      do
+	test X"$d" = X && continue
+
+	prefix=$prefix$d
+	if test -d "$prefix"; then
+	  prefixes=
+	else
+	  if $posix_mkdir; then
+	    (umask=$mkdir_umask &&
+	     $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+	    # Don't fail if two instances are running concurrently.
+	    test -d "$prefix" || exit 1
+	  else
+	    case $prefix in
+	      *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+	      *) qprefix=$prefix;;
+	    esac
+	    prefixes="$prefixes '$qprefix'"
+	  fi
+	fi
+	prefix=$prefix/
+      done
+
+      if test -n "$prefixes"; then
+	# Don't fail if two instances are running concurrently.
+	(umask $mkdir_umask &&
+	 eval "\$doit_exec \$mkdirprog $prefixes") ||
+	  test -d "$dstdir" || exit 1
+	obsolete_mkdir_used=true
+      fi
+    fi
+  fi
+
+  if test -n "$dir_arg"; then
+    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+  else
+
+    # Make a couple of temp file names in the proper directory.
+    dsttmp=$dstdir/_inst.$$_
+    rmtmp=$dstdir/_rm.$$_
+
+    # Trap to clean up those temp files at exit.
+    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+    # Copy the file name to the temp name.
+    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
+
+    # and set any options; do chmod last to preserve setuid bits.
+    #
+    # If any of these fail, we abort the whole thing.  If we want to
+    # ignore errors from any of these, just make sure not to ignore
+    # errors from the above "$doit $cpprog $src $dsttmp" command.
+    #
+    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+    # If -C, don't bother to copy if it wouldn't change the file.
+    if $copy_on_change &&
+       old=`LC_ALL=C ls -dlL "$dst"	2>/dev/null` &&
+       new=`LC_ALL=C ls -dlL "$dsttmp"	2>/dev/null` &&
+
+       eval "$initialize_posix_glob" &&
+       $posix_glob set -f &&
+       set X $old && old=:$2:$4:$5:$6 &&
+       set X $new && new=:$2:$4:$5:$6 &&
+       $posix_glob set +f &&
+
+       test "$old" = "$new" &&
+       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+    then
+      rm -f "$dsttmp"
+    else
+      # Rename the file to the real destination.
+      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+      # The rename failed, perhaps because mv can't rename something else
+      # to itself, or perhaps because mv is so ancient that it does not
+      # support -f.
+      {
+	# Now remove or move aside any old file at destination location.
+	# We try this two ways since rm can't unlink itself on some
+	# systems and the destination file might be busy for other
+	# reasons.  In this case, the final cleanup might fail but the new
+	# file should still install successfully.
+	{
+	  test ! -f "$dst" ||
+	  $doit $rmcmd -f "$dst" 2>/dev/null ||
+	  { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+	    { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
+	  } ||
+	  { echo "$0: cannot unlink or rename $dst" >&2
+	    (exit 1); exit 1
+	  }
+	} &&
+
+	# Now rename the file to the real destination.
+	$doit $mvcmd "$dsttmp" "$dst"
+      }
+    fi || exit 1
+
+    trap '' 0
+  fi
+done
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/internal.h b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/internal.h
new file mode 100644
index 0000000..bff8ed4
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/internal.h
@@ -0,0 +1,304 @@
+/* internal.h -- Internal header file for stack backtrace library.
+   Copyright (C) 2012-2018 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#ifndef BACKTRACE_INTERNAL_H
+#define BACKTRACE_INTERNAL_H
+
+/* We assume that <sys/types.h> and "backtrace.h" have already been
+   included.  */
+
+#ifndef GCC_VERSION
+# define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
+#endif
+
+#if (GCC_VERSION < 2007)
+# define __attribute__(x)
+#endif
+
+#ifndef ATTRIBUTE_UNUSED
+# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+#endif
+
+#ifndef ATTRIBUTE_MALLOC
+# if (GCC_VERSION >= 2096)
+#  define ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
+# else
+#  define ATTRIBUTE_MALLOC
+# endif
+#endif
+
+#ifndef HAVE_SYNC_FUNCTIONS
+
+/* Define out the sync functions.  These should never be called if
+   they are not available.  */
+
+#define __sync_bool_compare_and_swap(A, B, C) (abort(), 1)
+#define __sync_lock_test_and_set(A, B) (abort(), 0)
+#define __sync_lock_release(A) abort()
+
+#endif /* !defined (HAVE_SYNC_FUNCTIONS) */
+
+#ifdef HAVE_ATOMIC_FUNCTIONS
+
+/* We have the atomic builtin functions.  */
+
+#define backtrace_atomic_load_pointer(p) \
+    __atomic_load_n ((p), __ATOMIC_ACQUIRE)
+#define backtrace_atomic_load_int(p) \
+    __atomic_load_n ((p), __ATOMIC_ACQUIRE)
+#define backtrace_atomic_store_pointer(p, v) \
+    __atomic_store_n ((p), (v), __ATOMIC_RELEASE)
+#define backtrace_atomic_store_size_t(p, v) \
+    __atomic_store_n ((p), (v), __ATOMIC_RELEASE)
+#define backtrace_atomic_store_int(p, v) \
+    __atomic_store_n ((p), (v), __ATOMIC_RELEASE)
+
+#else /* !defined (HAVE_ATOMIC_FUNCTIONS) */
+#ifdef HAVE_SYNC_FUNCTIONS
+
+/* We have the sync functions but not the atomic functions.  Define
+   the atomic ones in terms of the sync ones.  */
+
+extern void *backtrace_atomic_load_pointer (void *);
+extern int backtrace_atomic_load_int (int *);
+extern void backtrace_atomic_store_pointer (void *, void *);
+extern void backtrace_atomic_store_size_t (size_t *, size_t);
+extern void backtrace_atomic_store_int (int *, int);
+
+#else /* !defined (HAVE_SYNC_FUNCTIONS) */
+
+/* We have neither the sync nor the atomic functions.  These will
+   never be called.  */
+
+#define backtrace_atomic_load_pointer(p) (abort(), (void *) NULL)
+#define backtrace_atomic_load_int(p) (abort(), 0)
+#define backtrace_atomic_store_pointer(p, v) abort()
+#define backtrace_atomic_store_size_t(p, v) abort()
+#define backtrace_atomic_store_int(p, v) abort()
+
+#endif /* !defined (HAVE_SYNC_FUNCTIONS) */
+#endif /* !defined (HAVE_ATOMIC_FUNCTIONS) */
+
+/* The type of the function that collects file/line information.  This
+   is like backtrace_pcinfo.  */
+
+typedef int (*fileline) (struct backtrace_state *state, uintptr_t pc,
+			 backtrace_full_callback callback,
+			 backtrace_error_callback error_callback, void *data);
+
+/* The type of the function that collects symbol information.  This is
+   like backtrace_syminfo.  */
+
+typedef void (*syminfo) (struct backtrace_state *state, uintptr_t pc,
+			 backtrace_syminfo_callback callback,
+			 backtrace_error_callback error_callback, void *data);
+
+/* What the backtrace state pointer points to.  */
+
+struct backtrace_state
+{
+  /* The name of the executable.  */
+  const char *filename;
+  /* Non-zero if threaded.  */
+  int threaded;
+  /* The master lock for fileline_fn, fileline_data, syminfo_fn,
+     syminfo_data, fileline_initialization_failed and everything the
+     data pointers point to.  */
+  void *lock;
+  /* The function that returns file/line information.  */
+  fileline fileline_fn;
+  /* The data to pass to FILELINE_FN.  */
+  void *fileline_data;
+  /* The function that returns symbol information.  */
+  syminfo syminfo_fn;
+  /* The data to pass to SYMINFO_FN.  */
+  void *syminfo_data;
+  /* Whether initializing the file/line information failed.  */
+  int fileline_initialization_failed;
+  /* The lock for the freelist.  */
+  int lock_alloc;
+  /* The freelist when using mmap.  */
+  struct backtrace_freelist_struct *freelist;
+};
+
+/* Open a file for reading.  Returns -1 on error.  If DOES_NOT_EXIST
+   is not NULL, *DOES_NOT_EXIST will be set to 0 normally and set to 1
+   if the file does not exist.  If the file does not exist and
+   DOES_NOT_EXIST is not NULL, the function will return -1 and will
+   not call ERROR_CALLBACK.  On other errors, or if DOES_NOT_EXIST is
+   NULL, the function will call ERROR_CALLBACK before returning.  */
+extern int backtrace_open (const char *filename,
+			   backtrace_error_callback error_callback,
+			   void *data,
+			   int *does_not_exist);
+
+/* A view of the contents of a file.  This supports mmap when
+   available.  A view will remain in memory even after backtrace_close
+   is called on the file descriptor from which the view was
+   obtained.  */
+
+struct backtrace_view
+{
+  /* The data that the caller requested.  */
+  const void *data;
+  /* The base of the view.  */
+  void *base;
+  /* The total length of the view.  */
+  size_t len;
+};
+
+/* Create a view of SIZE bytes from DESCRIPTOR at OFFSET.  Store the
+   result in *VIEW.  Returns 1 on success, 0 on error.  */
+extern int backtrace_get_view (struct backtrace_state *state, int descriptor,
+			       off_t offset, size_t size,
+			       backtrace_error_callback error_callback,
+			       void *data, struct backtrace_view *view);
+
+/* Release a view created by backtrace_get_view.  */
+extern void backtrace_release_view (struct backtrace_state *state,
+				    struct backtrace_view *view,
+				    backtrace_error_callback error_callback,
+				    void *data);
+
+/* Close a file opened by backtrace_open.  Returns 1 on success, 0 on
+   error.  */
+
+extern int backtrace_close (int descriptor,
+			    backtrace_error_callback error_callback,
+			    void *data);
+
+/* Sort without using memory.  */
+
+extern void backtrace_qsort (void *base, size_t count, size_t size,
+			     int (*compar) (const void *, const void *));
+
+/* Allocate memory.  This is like malloc.  If ERROR_CALLBACK is NULL,
+   this does not report an error, it just returns NULL.  */
+
+extern void *backtrace_alloc (struct backtrace_state *state, size_t size,
+			      backtrace_error_callback error_callback,
+			      void *data) ATTRIBUTE_MALLOC;
+
+/* Free memory allocated by backtrace_alloc.  If ERROR_CALLBACK is
+   NULL, this does not report an error.  */
+
+extern void backtrace_free (struct backtrace_state *state, void *mem,
+			    size_t size,
+			    backtrace_error_callback error_callback,
+			    void *data);
+
+/* A growable vector of some struct.  This is used for more efficient
+   allocation when we don't know the final size of some group of data
+   that we want to represent as an array.  */
+
+struct backtrace_vector
+{
+  /* The base of the vector.  */
+  void *base;
+  /* The number of bytes in the vector.  */
+  size_t size;
+  /* The number of bytes available at the current allocation.  */
+  size_t alc;
+};
+
+/* Grow VEC by SIZE bytes.  Return a pointer to the newly allocated
+   bytes.  Note that this may move the entire vector to a new memory
+   location.  Returns NULL on failure.  */
+
+extern void *backtrace_vector_grow (struct backtrace_state *state, size_t size,
+				    backtrace_error_callback error_callback,
+				    void *data,
+				    struct backtrace_vector *vec);
+
+/* Finish the current allocation on VEC.  Prepare to start a new
+   allocation.  The finished allocation will never be freed.  Returns
+   a pointer to the base of the finished entries, or NULL on
+   failure.  */
+
+extern void* backtrace_vector_finish (struct backtrace_state *state,
+				      struct backtrace_vector *vec,
+				      backtrace_error_callback error_callback,
+				      void *data);
+
+/* Release any extra space allocated for VEC.  This may change
+   VEC->base.  Returns 1 on success, 0 on failure.  */
+
+extern int backtrace_vector_release (struct backtrace_state *state,
+				     struct backtrace_vector *vec,
+				     backtrace_error_callback error_callback,
+				     void *data);
+
+/* Read initial debug data from a descriptor, and set the
+   fileline_data, syminfo_fn, and syminfo_data fields of STATE.
+   Return the fileln_fn field in *FILELN_FN--this is done this way so
+   that the synchronization code is only implemented once.  This is
+   called after the descriptor has first been opened.  It will close
+   the descriptor if it is no longer needed.  Returns 1 on success, 0
+   on error.  There will be multiple implementations of this function,
+   for different file formats.  Each system will compile the
+   appropriate one.  */
+
+extern int backtrace_initialize (struct backtrace_state *state,
+				 const char *filename,
+				 int descriptor,
+				 backtrace_error_callback error_callback,
+				 void *data,
+				 fileline *fileline_fn);
+
+/* Add file/line information for a DWARF module.  */
+
+extern int backtrace_dwarf_add (struct backtrace_state *state,
+				uintptr_t base_address,
+				const unsigned char* dwarf_info,
+				size_t dwarf_info_size,
+				const unsigned char *dwarf_line,
+				size_t dwarf_line_size,
+				const unsigned char *dwarf_abbrev,
+				size_t dwarf_abbrev_size,
+				const unsigned char *dwarf_ranges,
+				size_t dwarf_range_size,
+				const unsigned char *dwarf_str,
+				size_t dwarf_str_size,
+				int is_bigendian,
+				backtrace_error_callback error_callback,
+				void *data, fileline *fileline_fn);
+
+/* A test-only hook for elf_uncompress_zdebug.  */
+
+extern int backtrace_uncompress_zdebug (struct backtrace_state *,
+					const unsigned char *compressed,
+					size_t compressed_size,
+					backtrace_error_callback, void *data,
+					unsigned char **uncompressed,
+					size_t *uncompressed_size);
+
+#endif
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/ltmain.sh b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/ltmain.sh
new file mode 100755
index 0000000..93793bf
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/ltmain.sh
@@ -0,0 +1,7874 @@
+# Generated from ltmain.m4sh.
+
+# ltmain.sh (GNU libtool) 2.2.4
+# Written by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007 2008 Free Software Foundation, Inc.
+# This is free software; see the source for copying conditions.  There is NO
+# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+# GNU Libtool is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Libtool; see the file COPYING.  If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html,
+# or obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+# Usage: $progname [OPTION]... [MODE-ARG]...
+#
+# Provide generalized library-building support services.
+#
+#     --config             show all configuration variables
+#     --debug              enable verbose shell tracing
+# -n, --dry-run            display commands without modifying any files
+#     --features           display basic configuration information and exit
+#     --mode=MODE          use operation mode MODE
+#     --preserve-dup-deps  don't remove duplicate dependency libraries
+#     --quiet, --silent    don't print informational messages
+#     --tag=TAG            use configuration variables from tag TAG
+# -v, --verbose            print informational messages (default)
+#     --version            print version information
+# -h, --help               print short or long help message
+#
+# MODE must be one of the following:
+#
+#       clean              remove files from the build directory
+#       compile            compile a source file into a libtool object
+#       execute            automatically set library path, then run a program
+#       finish             complete the installation of libtool libraries
+#       install            install libraries or executables
+#       link               create a library or an executable
+#       uninstall          remove libraries from an installed directory
+#
+# MODE-ARGS vary depending on the MODE.
+# Try `$progname --help --mode=MODE' for a more detailed description of MODE.
+#
+# When reporting a bug, please describe a test case to reproduce it and
+# include the following information:
+#
+#       host-triplet:	$host
+#       shell:		$SHELL
+#       compiler:		$LTCC
+#       compiler flags:		$LTCFLAGS
+#       linker:		$LD (gnu? $with_gnu_ld)
+#       $progname:		(GNU libtool) 2.2.4
+#       automake:		$automake_version
+#       autoconf:		$autoconf_version
+#
+# Report bugs to <bug-libtool@gnu.org>.
+
+PROGRAM=ltmain.sh
+PACKAGE=libtool
+VERSION=2.2.4
+TIMESTAMP=""
+package_revision=1.2976
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# NLS nuisances: We save the old values to restore during execute mode.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+lt_user_locale=
+lt_safe_locale=
+for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+do
+  eval "if test \"\${$lt_var+set}\" = set; then
+          save_$lt_var=\$$lt_var
+          $lt_var=C
+	  export $lt_var
+	  lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\"
+	  lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\"
+	fi"
+done
+
+$lt_unset CDPATH
+
+
+
+
+
+: ${CP="cp -f"}
+: ${ECHO="echo"}
+: ${EGREP="/usr/bin/grep -E"}
+: ${FGREP="/usr/bin/grep -F"}
+: ${GREP="/usr/bin/grep"}
+: ${LN_S="ln -s"}
+: ${MAKE="make"}
+: ${MKDIR="mkdir"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+: ${SED="/opt/local/bin/gsed"}
+: ${SHELL="${CONFIG_SHELL-/bin/sh}"}
+: ${Xsed="$SED -e 1s/^X//"}
+
+# Global variables:
+EXIT_SUCCESS=0
+EXIT_FAILURE=1
+EXIT_MISMATCH=63  # $? = 63 is used to indicate version mismatch to missing.
+EXIT_SKIP=77	  # $? = 77 is used to indicate a skipped test to automake.
+
+exit_status=$EXIT_SUCCESS
+
+# Make sure IFS has a sensible default
+lt_nl='
+'
+IFS=" 	$lt_nl"
+
+dirname="s,/[^/]*$,,"
+basename="s,^.*/,,"
+
+# func_dirname_and_basename file append nondir_replacement
+# perform func_basename and func_dirname in a single function
+# call:
+#   dirname:  Compute the dirname of FILE.  If nonempty,
+#             add APPEND to the result, otherwise set result
+#             to NONDIR_REPLACEMENT.
+#             value returned in "$func_dirname_result"
+#   basename: Compute filename of FILE.
+#             value retuned in "$func_basename_result"
+# Implementation must be kept synchronized with func_dirname
+# and func_basename. For efficiency, we do not delegate to
+# those functions but instead duplicate the functionality here.
+func_dirname_and_basename ()
+{
+  # Extract subdirectory from the argument.
+  func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"`
+  if test "X$func_dirname_result" = "X${1}"; then
+    func_dirname_result="${3}"
+  else
+    func_dirname_result="$func_dirname_result${2}"
+  fi
+  func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"`
+}
+
+# Generated shell functions inserted here.
+
+# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
+# is ksh but when the shell is invoked as "sh" and the current value of
+# the _XPG environment variable is not equal to 1 (one), the special
+# positional parameter $0, within a function call, is the name of the
+# function.
+progpath="$0"
+
+# The name of this program:
+# In the unlikely event $progname began with a '-', it would play havoc with
+# func_echo (imagine progname=-n), so we prepend ./ in that case:
+func_dirname_and_basename "$progpath"
+progname=$func_basename_result
+case $progname in
+  -*) progname=./$progname ;;
+esac
+
+# Make sure we have an absolute path for reexecution:
+case $progpath in
+  [\\/]*|[A-Za-z]:\\*) ;;
+  *[\\/]*)
+     progdir=$func_dirname_result
+     progdir=`cd "$progdir" && pwd`
+     progpath="$progdir/$progname"
+     ;;
+  *)
+     save_IFS="$IFS"
+     IFS=:
+     for progdir in $PATH; do
+       IFS="$save_IFS"
+       test -x "$progdir/$progname" && break
+     done
+     IFS="$save_IFS"
+     test -n "$progdir" || progdir=`pwd`
+     progpath="$progdir/$progname"
+     ;;
+esac
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed="${SED}"' -e 1s/^X//'
+sed_quote_subst='s/\([`"$\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\(["`\\]\)/\\\1/g'
+
+# Re-`\' parameter expansions in output of double_quote_subst that were
+# `\'-ed in input to the same.  If an odd number of `\' preceded a '$'
+# in input to double_quote_subst, that '$' was protected from expansion.
+# Since each input `\' is now two `\'s, look for any number of runs of
+# four `\'s followed by two `\'s and then a '$'.  `\' that '$'.
+bs='\\'
+bs2='\\\\'
+bs4='\\\\\\\\'
+dollar='\$'
+sed_double_backslash="\
+  s/$bs4/&\\
+/g
+  s/^$bs2$dollar/$bs&/
+  s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g
+  s/\n//g"
+
+# Standard options:
+opt_dry_run=false
+opt_help=false
+opt_quiet=false
+opt_verbose=false
+opt_warning=:
+
+# func_echo arg...
+# Echo program name prefixed message, along with the current mode
+# name if it has been set yet.
+func_echo ()
+{
+    $ECHO "$progname${mode+: }$mode: $*"
+}
+
+# func_verbose arg...
+# Echo program name prefixed message in verbose mode only.
+func_verbose ()
+{
+    $opt_verbose && func_echo ${1+"$@"}
+
+    # A bug in bash halts the script if the last line of a function
+    # fails when set -e is in force, so we need another command to
+    # work around that:
+    :
+}
+
+# func_error arg...
+# Echo program name prefixed message to standard error.
+func_error ()
+{
+    $ECHO "$progname${mode+: }$mode: "${1+"$@"} 1>&2
+}
+
+# func_warning arg...
+# Echo program name prefixed warning message to standard error.
+func_warning ()
+{
+    $opt_warning && $ECHO "$progname${mode+: }$mode: warning: "${1+"$@"} 1>&2
+
+    # bash bug again:
+    :
+}
+
+# func_fatal_error arg...
+# Echo program name prefixed message to standard error, and exit.
+func_fatal_error ()
+{
+    func_error ${1+"$@"}
+    exit $EXIT_FAILURE
+}
+
+# func_fatal_help arg...
+# Echo program name prefixed message to standard error, followed by
+# a help hint, and exit.
+func_fatal_help ()
+{
+    func_error ${1+"$@"}
+    func_fatal_error "$help"
+}
+help="Try \`$progname --help' for more information."  ## default
+
+
+# func_grep expression filename
+# Check whether EXPRESSION matches any line of FILENAME, without output.
+func_grep ()
+{
+    $GREP "$1" "$2" >/dev/null 2>&1
+}
+
+
+# func_mkdir_p directory-path
+# Make sure the entire path to DIRECTORY-PATH is available.
+func_mkdir_p ()
+{
+    my_directory_path="$1"
+    my_dir_list=
+
+    if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then
+
+      # Protect directory names starting with `-'
+      case $my_directory_path in
+        -*) my_directory_path="./$my_directory_path" ;;
+      esac
+
+      # While some portion of DIR does not yet exist...
+      while test ! -d "$my_directory_path"; do
+        # ...make a list in topmost first order.  Use a colon delimited
+	# list incase some portion of path contains whitespace.
+        my_dir_list="$my_directory_path:$my_dir_list"
+
+        # If the last portion added has no slash in it, the list is done
+        case $my_directory_path in */*) ;; *) break ;; esac
+
+        # ...otherwise throw away the child directory and loop
+        my_directory_path=`$ECHO "X$my_directory_path" | $Xsed -e "$dirname"`
+      done
+      my_dir_list=`$ECHO "X$my_dir_list" | $Xsed -e 's,:*$,,'`
+
+      save_mkdir_p_IFS="$IFS"; IFS=':'
+      for my_dir in $my_dir_list; do
+	IFS="$save_mkdir_p_IFS"
+        # mkdir can fail with a `File exist' error if two processes
+        # try to create one of the directories concurrently.  Don't
+        # stop in that case!
+        $MKDIR "$my_dir" 2>/dev/null || :
+      done
+      IFS="$save_mkdir_p_IFS"
+
+      # Bail out if we (or some other process) failed to create a directory.
+      test -d "$my_directory_path" || \
+        func_fatal_error "Failed to create \`$1'"
+    fi
+}
+
+
+# func_mktempdir [string]
+# Make a temporary directory that won't clash with other running
+# libtool processes, and avoids race conditions if possible.  If
+# given, STRING is the basename for that directory.
+func_mktempdir ()
+{
+    my_template="${TMPDIR-/tmp}/${1-$progname}"
+
+    if test "$opt_dry_run" = ":"; then
+      # Return a directory name, but don't create it in dry-run mode
+      my_tmpdir="${my_template}-$$"
+    else
+
+      # If mktemp works, use that first and foremost
+      my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null`
+
+      if test ! -d "$my_tmpdir"; then
+        # Failing that, at least try and use $RANDOM to avoid a race
+        my_tmpdir="${my_template}-${RANDOM-0}$$"
+
+        save_mktempdir_umask=`umask`
+        umask 0077
+        $MKDIR "$my_tmpdir"
+        umask $save_mktempdir_umask
+      fi
+
+      # If we're not in dry-run mode, bomb out on failure
+      test -d "$my_tmpdir" || \
+        func_fatal_error "cannot create temporary directory \`$my_tmpdir'"
+    fi
+
+    $ECHO "X$my_tmpdir" | $Xsed
+}
+
+
+# func_quote_for_eval arg
+# Aesthetically quote ARG to be evaled later.
+# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT
+# is double-quoted, suitable for a subsequent eval, whereas
+# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters
+# which are still active within double quotes backslashified.
+func_quote_for_eval ()
+{
+    case $1 in
+      *[\\\`\"\$]*)
+	func_quote_for_eval_unquoted_result=`$ECHO "X$1" | $Xsed -e "$sed_quote_subst"` ;;
+      *)
+        func_quote_for_eval_unquoted_result="$1" ;;
+    esac
+
+    case $func_quote_for_eval_unquoted_result in
+      # Double-quote args containing shell metacharacters to delay
+      # word splitting, command substitution and and variable
+      # expansion for a subsequent eval.
+      # Many Bourne shells cannot handle close brackets correctly
+      # in scan sets, so we specify it separately.
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+        func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\""
+        ;;
+      *)
+        func_quote_for_eval_result="$func_quote_for_eval_unquoted_result"
+    esac
+}
+
+
+# func_quote_for_expand arg
+# Aesthetically quote ARG to be evaled later; same as above,
+# but do not quote variable references.
+func_quote_for_expand ()
+{
+    case $1 in
+      *[\\\`\"]*)
+	my_arg=`$ECHO "X$1" | $Xsed \
+	    -e "$double_quote_subst" -e "$sed_double_backslash"` ;;
+      *)
+        my_arg="$1" ;;
+    esac
+
+    case $my_arg in
+      # Double-quote args containing shell metacharacters to delay
+      # word splitting and command substitution for a subsequent eval.
+      # Many Bourne shells cannot handle close brackets correctly
+      # in scan sets, so we specify it separately.
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+        my_arg="\"$my_arg\""
+        ;;
+    esac
+
+    func_quote_for_expand_result="$my_arg"
+}
+
+
+# func_show_eval cmd [fail_exp]
+# Unless opt_silent is true, then output CMD.  Then, if opt_dryrun is
+# not true, evaluate CMD.  If the evaluation of CMD fails, and FAIL_EXP
+# is given, then evaluate it.
+func_show_eval ()
+{
+    my_cmd="$1"
+    my_fail_exp="${2-:}"
+
+    ${opt_silent-false} || {
+      func_quote_for_expand "$my_cmd"
+      eval "func_echo $func_quote_for_expand_result"
+    }
+
+    if ${opt_dry_run-false}; then :; else
+      eval "$my_cmd"
+      my_status=$?
+      if test "$my_status" -eq 0; then :; else
+	eval "(exit $my_status); $my_fail_exp"
+      fi
+    fi
+}
+
+
+# func_show_eval_locale cmd [fail_exp]
+# Unless opt_silent is true, then output CMD.  Then, if opt_dryrun is
+# not true, evaluate CMD.  If the evaluation of CMD fails, and FAIL_EXP
+# is given, then evaluate it.  Use the saved locale for evaluation.
+func_show_eval_locale ()
+{
+    my_cmd="$1"
+    my_fail_exp="${2-:}"
+
+    ${opt_silent-false} || {
+      func_quote_for_expand "$my_cmd"
+      eval "func_echo $func_quote_for_expand_result"
+    }
+
+    if ${opt_dry_run-false}; then :; else
+      eval "$lt_user_locale
+	    $my_cmd"
+      my_status=$?
+      eval "$lt_safe_locale"
+      if test "$my_status" -eq 0; then :; else
+	eval "(exit $my_status); $my_fail_exp"
+      fi
+    fi
+}
+
+
+
+
+
+# func_version
+# Echo version message to standard output and exit.
+func_version ()
+{
+    $SED -n '/^# '$PROGRAM' (GNU /,/# warranty; / {
+        s/^# //
+	s/^# *$//
+        s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/
+        p
+     }' < "$progpath"
+     exit $?
+}
+
+# func_usage
+# Echo short help message to standard output and exit.
+func_usage ()
+{
+    $SED -n '/^# Usage:/,/# -h/ {
+        s/^# //
+	s/^# *$//
+	s/\$progname/'$progname'/
+	p
+    }' < "$progpath"
+    $ECHO
+    $ECHO "run \`$progname --help | more' for full usage"
+    exit $?
+}
+
+# func_help
+# Echo long help message to standard output and exit.
+func_help ()
+{
+    $SED -n '/^# Usage:/,/# Report bugs to/ {
+        s/^# //
+	s/^# *$//
+	s*\$progname*'$progname'*
+	s*\$host*'"$host"'*
+	s*\$SHELL*'"$SHELL"'*
+	s*\$LTCC*'"$LTCC"'*
+	s*\$LTCFLAGS*'"$LTCFLAGS"'*
+	s*\$LD*'"$LD"'*
+	s/\$with_gnu_ld/'"$with_gnu_ld"'/
+	s/\$automake_version/'"`(automake --version) 2>/dev/null |$SED 1q`"'/
+	s/\$autoconf_version/'"`(autoconf --version) 2>/dev/null |$SED 1q`"'/
+	p
+     }' < "$progpath"
+    exit $?
+}
+
+# func_missing_arg argname
+# Echo program name prefixed message to standard error and set global
+# exit_cmd.
+func_missing_arg ()
+{
+    func_error "missing argument for $1"
+    exit_cmd=exit
+}
+
+exit_cmd=:
+
+
+
+
+
+# Check that we have a working $ECHO.
+if test "X$1" = X--no-reexec; then
+  # Discard the --no-reexec flag, and continue.
+  shift
+elif test "X$1" = X--fallback-echo; then
+  # Avoid inline document here, it may be left over
+  :
+elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t'; then
+  # Yippee, $ECHO works!
+  :
+else
+  # Restart under the correct shell, and then maybe $ECHO will work.
+  exec $SHELL "$progpath" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+  # used as fallback echo
+  shift
+  cat <<EOF
+$*
+EOF
+  exit $EXIT_SUCCESS
+fi
+
+magic="%%%MAGIC variable%%%"
+magic_exe="%%%MAGIC EXE variable%%%"
+
+# Global variables.
+# $mode is unset
+nonopt=
+execute_dlfiles=
+preserve_args=
+lo2o="s/\\.lo\$/.${objext}/"
+o2lo="s/\\.${objext}\$/.lo/"
+extracted_archives=
+extracted_serial=0
+
+opt_dry_run=false
+opt_duplicate_deps=false
+opt_silent=false
+opt_debug=:
+
+# If this variable is set in any of the actions, the command in it
+# will be execed at the end.  This prevents here-documents from being
+# left over by shells.
+exec_cmd=
+
+# func_fatal_configuration arg...
+# Echo program name prefixed message to standard error, followed by
+# a configuration failure hint, and exit.
+func_fatal_configuration ()
+{
+    func_error ${1+"$@"}
+    func_error "See the $PACKAGE documentation for more information."
+    func_fatal_error "Fatal configuration error."
+}
+
+
+# func_config
+# Display the configuration for all the tags in this script.
+func_config ()
+{
+    re_begincf='^# ### BEGIN LIBTOOL'
+    re_endcf='^# ### END LIBTOOL'
+
+    # Default configuration.
+    $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath"
+
+    # Now print the configurations for the tags.
+    for tagname in $taglist; do
+      $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath"
+    done
+
+    exit $?
+}
+
+# func_features
+# Display the features supported by this script.
+func_features ()
+{
+    $ECHO "host: $host"
+    if test "$build_libtool_libs" = yes; then
+      $ECHO "enable shared libraries"
+    else
+      $ECHO "disable shared libraries"
+    fi
+    if test "$build_old_libs" = yes; then
+      $ECHO "enable static libraries"
+    else
+      $ECHO "disable static libraries"
+    fi
+
+    exit $?
+}
+
+# func_enable_tag tagname
+# Verify that TAGNAME is valid, and either flag an error and exit, or
+# enable the TAGNAME tag.  We also add TAGNAME to the global $taglist
+# variable here.
+func_enable_tag ()
+{
+  # Global variable:
+  tagname="$1"
+
+  re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$"
+  re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$"
+  sed_extractcf="/$re_begincf/,/$re_endcf/p"
+
+  # Validate tagname.
+  case $tagname in
+    *[!-_A-Za-z0-9,/]*)
+      func_fatal_error "invalid tag name: $tagname"
+      ;;
+  esac
+
+  # Don't test for the "default" C tag, as we know it's
+  # there but not specially marked.
+  case $tagname in
+    CC) ;;
+    *)
+      if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then
+	taglist="$taglist $tagname"
+
+	# Evaluate the configuration.  Be careful to quote the path
+	# and the sed script, to avoid splitting on whitespace, but
+	# also don't use non-portable quotes within backquotes within
+	# quotes we have to do it in 2 steps:
+	extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"`
+	eval "$extractedcf"
+      else
+	func_error "ignoring unknown tag $tagname"
+      fi
+      ;;
+  esac
+}
+
+# Parse options once, thoroughly.  This comes as soon as possible in
+# the script to make things like `libtool --version' happen quickly.
+{
+
+  # Shorthand for --mode=foo, only valid as the first argument
+  case $1 in
+  clean|clea|cle|cl)
+    shift; set dummy --mode clean ${1+"$@"}; shift
+    ;;
+  compile|compil|compi|comp|com|co|c)
+    shift; set dummy --mode compile ${1+"$@"}; shift
+    ;;
+  execute|execut|execu|exec|exe|ex|e)
+    shift; set dummy --mode execute ${1+"$@"}; shift
+    ;;
+  finish|finis|fini|fin|fi|f)
+    shift; set dummy --mode finish ${1+"$@"}; shift
+    ;;
+  install|instal|insta|inst|ins|in|i)
+    shift; set dummy --mode install ${1+"$@"}; shift
+    ;;
+  link|lin|li|l)
+    shift; set dummy --mode link ${1+"$@"}; shift
+    ;;
+  uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u)
+    shift; set dummy --mode uninstall ${1+"$@"}; shift
+    ;;
+  esac
+
+  # Parse non-mode specific arguments:
+  while test "$#" -gt 0; do
+    opt="$1"
+    shift
+
+    case $opt in
+      --config)		func_config					;;
+
+      --debug)		preserve_args="$preserve_args $opt"
+			func_echo "enabling shell trace mode"
+			opt_debug='set -x'
+			$opt_debug
+			;;
+
+      -dlopen)		test "$#" -eq 0 && func_missing_arg "$opt" && break
+			execute_dlfiles="$execute_dlfiles $1"
+			shift
+			;;
+
+      --dry-run | -n)	opt_dry_run=:					;;
+      --features)       func_features					;;
+      --finish)		mode="finish"					;;
+
+      --mode)		test "$#" -eq 0 && func_missing_arg "$opt" && break
+			case $1 in
+			  # Valid mode arguments:
+			  clean)	;;
+			  compile)	;;
+			  execute)	;;
+			  finish)	;;
+			  install)	;;
+			  link)		;;
+			  relink)	;;
+			  uninstall)	;;
+
+			  # Catch anything else as an error
+			  *) func_error "invalid argument for $opt"
+			     exit_cmd=exit
+			     break
+			     ;;
+		        esac
+
+			mode="$1"
+			shift
+			;;
+
+      --preserve-dup-deps)
+			opt_duplicate_deps=:				;;
+
+      --quiet|--silent)	preserve_args="$preserve_args $opt"
+			opt_silent=:
+			;;
+
+      --verbose| -v)	preserve_args="$preserve_args $opt"
+			opt_silent=false
+			;;
+
+      --tag)		test "$#" -eq 0 && func_missing_arg "$opt" && break
+			preserve_args="$preserve_args $opt $1"
+			func_enable_tag "$1"	# tagname is set here
+			shift
+			;;
+
+      # Separate optargs to long options:
+      -dlopen=*|--mode=*|--tag=*)
+			func_opt_split "$opt"
+			set dummy "$func_opt_split_opt" "$func_opt_split_arg" ${1+"$@"}
+			shift
+			;;
+
+      -\?|-h)		func_usage					;;
+      --help)		opt_help=:					;;
+      --version)	func_version					;;
+
+      -*)		func_fatal_help "unrecognized option \`$opt'"	;;
+
+      *)		nonopt="$opt"
+			break
+			;;
+    esac
+  done
+
+
+  case $host in
+    *cygwin* | *mingw* | *pw32*)
+      # don't eliminate duplications in $postdeps and $predeps
+      opt_duplicate_compiler_generated_deps=:
+      ;;
+    *)
+      opt_duplicate_compiler_generated_deps=$opt_duplicate_deps
+      ;;
+  esac
+
+  # Having warned about all mis-specified options, bail out if
+  # anything was wrong.
+  $exit_cmd $EXIT_FAILURE
+}
+
+# func_check_version_match
+# Ensure that we are using m4 macros, and libtool script from the same
+# release of libtool.
+func_check_version_match ()
+{
+  if test "$package_revision" != "$macro_revision"; then
+    if test "$VERSION" != "$macro_version"; then
+      if test -z "$macro_version"; then
+        cat >&2 <<_LT_EOF
+$progname: Version mismatch error.  This is $PACKAGE $VERSION, but the
+$progname: definition of this LT_INIT comes from an older release.
+$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
+$progname: and run autoconf again.
+_LT_EOF
+      else
+        cat >&2 <<_LT_EOF
+$progname: Version mismatch error.  This is $PACKAGE $VERSION, but the
+$progname: definition of this LT_INIT comes from $PACKAGE $macro_version.
+$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
+$progname: and run autoconf again.
+_LT_EOF
+      fi
+    else
+      cat >&2 <<_LT_EOF
+$progname: Version mismatch error.  This is $PACKAGE $VERSION, revision $package_revision,
+$progname: but the definition of this LT_INIT comes from revision $macro_revision.
+$progname: You should recreate aclocal.m4 with macros from revision $package_revision
+$progname: of $PACKAGE $VERSION and run autoconf again.
+_LT_EOF
+    fi
+
+    exit $EXIT_MISMATCH
+  fi
+}
+
+
+## ----------- ##
+##    Main.    ##
+## ----------- ##
+
+$opt_help || {
+  # Sanity checks first:
+  func_check_version_match
+
+  if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
+    func_fatal_configuration "not configured to build any kind of library"
+  fi
+
+  test -z "$mode" && func_fatal_error "error: you must specify a MODE."
+
+
+  # Darwin sucks
+  eval std_shrext=\"$shrext_cmds\"
+
+
+  # Only execute mode is allowed to have -dlopen flags.
+  if test -n "$execute_dlfiles" && test "$mode" != execute; then
+    func_error "unrecognized option \`-dlopen'"
+    $ECHO "$help" 1>&2
+    exit $EXIT_FAILURE
+  fi
+
+  # Change the help message to a mode-specific one.
+  generic_help="$help"
+  help="Try \`$progname --help --mode=$mode' for more information."
+}
+
+
+# func_lalib_p file
+# True iff FILE is a libtool `.la' library or `.lo' object file.
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_lalib_p ()
+{
+    $SED -e 4q "$1" 2>/dev/null \
+      | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1
+}
+
+# func_lalib_unsafe_p file
+# True iff FILE is a libtool `.la' library or `.lo' object file.
+# This function implements the same check as func_lalib_p without
+# resorting to external programs.  To this end, it redirects stdin and
+# closes it afterwards, without saving the original file descriptor.
+# As a safety measure, use it only where a negative result would be
+# fatal anyway.  Works if `file' does not exist.
+func_lalib_unsafe_p ()
+{
+    lalib_p=no
+    if test -r "$1" && exec 5<&0 <"$1"; then
+	for lalib_p_l in 1 2 3 4
+	do
+	    read lalib_p_line
+	    case "$lalib_p_line" in
+		\#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;;
+	    esac
+	done
+	exec 0<&5 5<&-
+    fi
+    test "$lalib_p" = yes
+}
+
+# func_ltwrapper_script_p file
+# True iff FILE is a libtool wrapper script
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_script_p ()
+{
+    func_lalib_p "$1"
+}
+
+# func_ltwrapper_executable_p file
+# True iff FILE is a libtool wrapper executable
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_executable_p ()
+{
+    func_ltwrapper_exec_suffix=
+    case $1 in
+    *.exe) ;;
+    *) func_ltwrapper_exec_suffix=.exe ;;
+    esac
+    $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1
+}
+
+# func_ltwrapper_scriptname file
+# Assumes file is an ltwrapper_executable
+# uses $file to determine the appropriate filename for a
+# temporary ltwrapper_script.
+func_ltwrapper_scriptname ()
+{
+    func_ltwrapper_scriptname_result=""
+    if func_ltwrapper_executable_p "$1"; then
+	func_dirname_and_basename "$1" "" "."
+	func_stripname '' '.exe' "$func_basename_result"
+	func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper"
+    fi
+}
+
+# func_ltwrapper_p file
+# True iff FILE is a libtool wrapper script or wrapper executable
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_p ()
+{
+    func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1"
+}
+
+
+# func_execute_cmds commands fail_cmd
+# Execute tilde-delimited COMMANDS.
+# If FAIL_CMD is given, eval that upon failure.
+# FAIL_CMD may read-access the current command in variable CMD!
+func_execute_cmds ()
+{
+    $opt_debug
+    save_ifs=$IFS; IFS='~'
+    for cmd in $1; do
+      IFS=$save_ifs
+      eval cmd=\"$cmd\"
+      func_show_eval "$cmd" "${2-:}"
+    done
+    IFS=$save_ifs
+}
+
+
+# func_source file
+# Source FILE, adding directory component if necessary.
+# Note that it is not necessary on cygwin/mingw to append a dot to
+# FILE even if both FILE and FILE.exe exist: automatic-append-.exe
+# behavior happens only for exec(3), not for open(2)!  Also, sourcing
+# `FILE.' does not work on cygwin managed mounts.
+func_source ()
+{
+    $opt_debug
+    case $1 in
+    */* | *\\*)	. "$1" ;;
+    *)		. "./$1" ;;
+    esac
+}
+
+
+# func_infer_tag arg
+# Infer tagged configuration to use if any are available and
+# if one wasn't chosen via the "--tag" command line option.
+# Only attempt this if the compiler in the base compile
+# command doesn't match the default compiler.
+# arg is usually of the form 'gcc ...'
+func_infer_tag ()
+{
+    $opt_debug
+    if test -n "$available_tags" && test -z "$tagname"; then
+      CC_quoted=
+      for arg in $CC; do
+        func_quote_for_eval "$arg"
+	CC_quoted="$CC_quoted $func_quote_for_eval_result"
+      done
+      case $@ in
+      # Blanks in the command may have been stripped by the calling shell,
+      # but not from the CC environment variable when configure was run.
+      " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*) ;;
+      # Blanks at the start of $base_compile will cause this to fail
+      # if we don't check for them as well.
+      *)
+	for z in $available_tags; do
+	  if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then
+	    # Evaluate the configuration.
+	    eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`"
+	    CC_quoted=
+	    for arg in $CC; do
+	      # Double-quote args containing other shell metacharacters.
+	      func_quote_for_eval "$arg"
+	      CC_quoted="$CC_quoted $func_quote_for_eval_result"
+	    done
+	    case "$@ " in
+	      " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*)
+	      # The compiler in the base compile command matches
+	      # the one in the tagged configuration.
+	      # Assume this is the tagged configuration we want.
+	      tagname=$z
+	      break
+	      ;;
+	    esac
+	  fi
+	done
+	# If $tagname still isn't set, then no tagged configuration
+	# was found and let the user know that the "--tag" command
+	# line option must be used.
+	if test -z "$tagname"; then
+	  func_echo "unable to infer tagged configuration"
+	  func_fatal_error "specify a tag with \`--tag'"
+#	else
+#	  func_verbose "using $tagname tagged configuration"
+	fi
+	;;
+      esac
+    fi
+}
+
+
+
+# func_write_libtool_object output_name pic_name nonpic_name
+# Create a libtool object file (analogous to a ".la" file),
+# but don't create it if we're doing a dry run.
+func_write_libtool_object ()
+{
+    write_libobj=${1}
+    if test "$build_libtool_libs" = yes; then
+      write_lobj=\'${2}\'
+    else
+      write_lobj=none
+    fi
+
+    if test "$build_old_libs" = yes; then
+      write_oldobj=\'${3}\'
+    else
+      write_oldobj=none
+    fi
+
+    $opt_dry_run || {
+      cat >${write_libobj}T <<EOF
+# $write_libobj - a libtool object file
+# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+pic_object=$write_lobj
+
+# Name of the non-PIC object
+non_pic_object=$write_oldobj
+
+EOF
+      $MV "${write_libobj}T" "${write_libobj}"
+    }
+}
+
+# func_mode_compile arg...
+func_mode_compile ()
+{
+    $opt_debug
+    # Get the compilation command and the source file.
+    base_compile=
+    srcfile="$nonopt"  #  always keep a non-empty value in "srcfile"
+    suppress_opt=yes
+    suppress_output=
+    arg_mode=normal
+    libobj=
+    later=
+    pie_flag=
+
+    for arg
+    do
+      case $arg_mode in
+      arg  )
+	# do not "continue".  Instead, add this to base_compile
+	lastarg="$arg"
+	arg_mode=normal
+	;;
+
+      target )
+	libobj="$arg"
+	arg_mode=normal
+	continue
+	;;
+
+      normal )
+	# Accept any command-line options.
+	case $arg in
+	-o)
+	  test -n "$libobj" && \
+	    func_fatal_error "you cannot specify \`-o' more than once"
+	  arg_mode=target
+	  continue
+	  ;;
+
+	-pie | -fpie | -fPIE)
+          pie_flag="$pie_flag $arg"
+	  continue
+	  ;;
+
+	-shared | -static | -prefer-pic | -prefer-non-pic)
+	  later="$later $arg"
+	  continue
+	  ;;
+
+	-no-suppress)
+	  suppress_opt=no
+	  continue
+	  ;;
+
+	-Xcompiler)
+	  arg_mode=arg  #  the next one goes into the "base_compile" arg list
+	  continue      #  The current "srcfile" will either be retained or
+	  ;;            #  replaced later.  I would guess that would be a bug.
+
+	-Wc,*)
+	  func_stripname '-Wc,' '' "$arg"
+	  args=$func_stripname_result
+	  lastarg=
+	  save_ifs="$IFS"; IFS=','
+	  for arg in $args; do
+	    IFS="$save_ifs"
+	    func_quote_for_eval "$arg"
+	    lastarg="$lastarg $func_quote_for_eval_result"
+	  done
+	  IFS="$save_ifs"
+	  func_stripname ' ' '' "$lastarg"
+	  lastarg=$func_stripname_result
+
+	  # Add the arguments to base_compile.
+	  base_compile="$base_compile $lastarg"
+	  continue
+	  ;;
+
+	*)
+	  # Accept the current argument as the source file.
+	  # The previous "srcfile" becomes the current argument.
+	  #
+	  lastarg="$srcfile"
+	  srcfile="$arg"
+	  ;;
+	esac  #  case $arg
+	;;
+      esac    #  case $arg_mode
+
+      # Aesthetically quote the previous argument.
+      func_quote_for_eval "$lastarg"
+      base_compile="$base_compile $func_quote_for_eval_result"
+    done # for arg
+
+    case $arg_mode in
+    arg)
+      func_fatal_error "you must specify an argument for -Xcompile"
+      ;;
+    target)
+      func_fatal_error "you must specify a target with \`-o'"
+      ;;
+    *)
+      # Get the name of the library object.
+      test -z "$libobj" && {
+	func_basename "$srcfile"
+	libobj="$func_basename_result"
+      }
+      ;;
+    esac
+
+    # Recognize several different file suffixes.
+    # If the user specifies -o file.o, it is replaced with file.lo
+    case $libobj in
+    *.[cCFSifmso] | \
+    *.ada | *.adb | *.ads | *.asm | \
+    *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \
+    *.[fF][09]? | *.for | *.java | *.obj | *.sx)
+      func_xform "$libobj"
+      libobj=$func_xform_result
+      ;;
+    esac
+
+    case $libobj in
+    *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;;
+    *)
+      func_fatal_error "cannot determine name of library object from \`$libobj'"
+      ;;
+    esac
+
+    func_infer_tag $base_compile
+
+    for arg in $later; do
+      case $arg in
+      -shared)
+	test "$build_libtool_libs" != yes && \
+	  func_fatal_configuration "can not build a shared library"
+	build_old_libs=no
+	continue
+	;;
+
+      -static)
+	build_libtool_libs=no
+	build_old_libs=yes
+	continue
+	;;
+
+      -prefer-pic)
+	pic_mode=yes
+	continue
+	;;
+
+      -prefer-non-pic)
+	pic_mode=no
+	continue
+	;;
+      esac
+    done
+
+    func_quote_for_eval "$libobj"
+    test "X$libobj" != "X$func_quote_for_eval_result" \
+      && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"'	 &()|`$[]' \
+      && func_warning "libobj name \`$libobj' may not contain shell special characters."
+    func_dirname_and_basename "$obj" "/" ""
+    objname="$func_basename_result"
+    xdir="$func_dirname_result"
+    lobj=${xdir}$objdir/$objname
+
+    test -z "$base_compile" && \
+      func_fatal_help "you must specify a compilation command"
+
+    # Delete any leftover library objects.
+    if test "$build_old_libs" = yes; then
+      removelist="$obj $lobj $libobj ${libobj}T"
+    else
+      removelist="$lobj $libobj ${libobj}T"
+    fi
+
+    # On Cygwin there's no "real" PIC flag so we must build both object types
+    case $host_os in
+    cygwin* | mingw* | pw32* | os2*)
+      pic_mode=default
+      ;;
+    esac
+    if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then
+      # non-PIC code in shared libraries is not supported
+      pic_mode=default
+    fi
+
+    # Calculate the filename of the output object if compiler does
+    # not support -o with -c
+    if test "$compiler_c_o" = no; then
+      output_obj=`$ECHO "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext}
+      lockfile="$output_obj.lock"
+    else
+      output_obj=
+      need_locks=no
+      lockfile=
+    fi
+
+    # Lock this critical section if it is needed
+    # We use this script file to make the link, it avoids creating a new file
+    if test "$need_locks" = yes; then
+      until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do
+	func_echo "Waiting for $lockfile to be removed"
+	sleep 2
+      done
+    elif test "$need_locks" = warn; then
+      if test -f "$lockfile"; then
+	$ECHO "\
+*** ERROR, $lockfile exists and contains:
+`cat $lockfile 2>/dev/null`
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+	$opt_dry_run || $RM $removelist
+	exit $EXIT_FAILURE
+      fi
+      removelist="$removelist $output_obj"
+      $ECHO "$srcfile" > "$lockfile"
+    fi
+
+    $opt_dry_run || $RM $removelist
+    removelist="$removelist $lockfile"
+    trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15
+
+    if test -n "$fix_srcfile_path"; then
+      eval srcfile=\"$fix_srcfile_path\"
+    fi
+    func_quote_for_eval "$srcfile"
+    qsrcfile=$func_quote_for_eval_result
+
+    # Only build a PIC object if we are building libtool libraries.
+    if test "$build_libtool_libs" = yes; then
+      # Without this assignment, base_compile gets emptied.
+      fbsd_hideous_sh_bug=$base_compile
+
+      if test "$pic_mode" != no; then
+	command="$base_compile $qsrcfile $pic_flag"
+      else
+	# Don't build PIC code
+	command="$base_compile $qsrcfile"
+      fi
+
+      func_mkdir_p "$xdir$objdir"
+
+      if test -z "$output_obj"; then
+	# Place PIC objects in $objdir
+	command="$command -o $lobj"
+      fi
+
+      func_show_eval_locale "$command"	\
+          'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE'
+
+      if test "$need_locks" = warn &&
+	 test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+	$ECHO "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+	$opt_dry_run || $RM $removelist
+	exit $EXIT_FAILURE
+      fi
+
+      # Just move the object if needed, then go on to compile the next one
+      if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
+	func_show_eval '$MV "$output_obj" "$lobj"' \
+	  'error=$?; $opt_dry_run || $RM $removelist; exit $error'
+      fi
+
+      # Allow error messages only from the first compilation.
+      if test "$suppress_opt" = yes; then
+	suppress_output=' >/dev/null 2>&1'
+      fi
+    fi
+
+    # Only build a position-dependent object if we build old libraries.
+    if test "$build_old_libs" = yes; then
+      if test "$pic_mode" != yes; then
+	# Don't build PIC code
+	command="$base_compile $qsrcfile$pie_flag"
+      else
+	command="$base_compile $qsrcfile $pic_flag"
+      fi
+      if test "$compiler_c_o" = yes; then
+	command="$command -o $obj"
+      fi
+
+      # Suppress compiler output if we already did a PIC compilation.
+      command="$command$suppress_output"
+      func_show_eval_locale "$command" \
+        '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE'
+
+      if test "$need_locks" = warn &&
+	 test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+	$ECHO "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+	$opt_dry_run || $RM $removelist
+	exit $EXIT_FAILURE
+      fi
+
+      # Just move the object if needed
+      if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
+	func_show_eval '$MV "$output_obj" "$obj"' \
+	  'error=$?; $opt_dry_run || $RM $removelist; exit $error'
+      fi
+    fi
+
+    $opt_dry_run || {
+      func_write_libtool_object "$libobj" "$objdir/$objname" "$objname"
+
+      # Unlock the critical section if it was locked
+      if test "$need_locks" != no; then
+	removelist=$lockfile
+        $RM "$lockfile"
+      fi
+    }
+
+    exit $EXIT_SUCCESS
+}
+
+$opt_help || {
+test "$mode" = compile && func_mode_compile ${1+"$@"}
+}
+
+func_mode_help ()
+{
+    # We need to display help for each of the modes.
+    case $mode in
+      "")
+        # Generic help is extracted from the usage comments
+        # at the start of this file.
+        func_help
+        ;;
+
+      clean)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
+
+Remove files from the build directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm').  RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, object or program, all the files associated
+with it are deleted. Otherwise, only FILE itself is deleted using RM."
+        ;;
+
+      compile)
+      $ECHO \
+"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
+
+Compile a source file into a libtool library object.
+
+This mode accepts the following additional options:
+
+  -o OUTPUT-FILE    set the output file name to OUTPUT-FILE
+  -no-suppress      do not suppress compiler output for multiple passes
+  -prefer-pic       try to building PIC objects only
+  -prefer-non-pic   try to building non-PIC objects only
+  -shared           do not build a \`.o' file suitable for static linking
+  -static           only build a \`.o' file suitable for static linking
+
+COMPILE-COMMAND is a command to be used in creating a \`standard' object file
+from the given SOURCEFILE.
+
+The output file name is determined by removing the directory component from
+SOURCEFILE, then substituting the C source code suffix \`.c' with the
+library object suffix, \`.lo'."
+        ;;
+
+      execute)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]...
+
+Automatically set library path, then run a program.
+
+This mode accepts the following additional options:
+
+  -dlopen FILE      add the directory containing FILE to the library path
+
+This mode sets the library path environment variable according to \`-dlopen'
+flags.
+
+If any of the ARGS are libtool executable wrappers, then they are translated
+into their corresponding uninstalled binary, and any of their required library
+directories are added to the library path.
+
+Then, COMMAND is executed, with ARGS as arguments."
+        ;;
+
+      finish)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=finish [LIBDIR]...
+
+Complete the installation of libtool libraries.
+
+Each LIBDIR is a directory that contains libtool libraries.
+
+The commands that this mode executes may require superuser privileges.  Use
+the \`--dry-run' option if you just want to see what would be executed."
+        ;;
+
+      install)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND...
+
+Install executables or libraries.
+
+INSTALL-COMMAND is the installation command.  The first component should be
+either the \`install' or \`cp' program.
+
+The following components of INSTALL-COMMAND are treated specially:
+
+  -inst-prefix PREFIX-DIR  Use PREFIX-DIR as a staging area for installation
+
+The rest of the components are interpreted as arguments to that command (only
+BSD-compatible install options are recognized)."
+        ;;
+
+      link)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=link LINK-COMMAND...
+
+Link object files or libraries together to form another library, or to
+create an executable program.
+
+LINK-COMMAND is a command using the C compiler that you would use to create
+a program from several object files.
+
+The following components of LINK-COMMAND are treated specially:
+
+  -all-static       do not do any dynamic linking at all
+  -avoid-version    do not add a version suffix if possible
+  -dlopen FILE      \`-dlpreopen' FILE if it cannot be dlopened at runtime
+  -dlpreopen FILE   link in FILE and add its symbols to lt_preloaded_symbols
+  -export-dynamic   allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
+  -export-symbols SYMFILE
+                    try to export only the symbols listed in SYMFILE
+  -export-symbols-regex REGEX
+                    try to export only the symbols matching REGEX
+  -LLIBDIR          search LIBDIR for required installed libraries
+  -lNAME            OUTPUT-FILE requires the installed library libNAME
+  -module           build a library that can dlopened
+  -no-fast-install  disable the fast-install mode
+  -no-install       link a not-installable executable
+  -no-undefined     declare that a library does not refer to external symbols
+  -o OUTPUT-FILE    create OUTPUT-FILE from the specified objects
+  -objectlist FILE  Use a list of object files found in FILE to specify objects
+  -precious-files-regex REGEX
+                    don't remove output files matching REGEX
+  -release RELEASE  specify package release information
+  -rpath LIBDIR     the created library will eventually be installed in LIBDIR
+  -R[ ]LIBDIR       add LIBDIR to the runtime path of programs and libraries
+  -shared           only do dynamic linking of libtool libraries
+  -shrext SUFFIX    override the standard shared library file extension
+  -static           do not do any dynamic linking of uninstalled libtool libraries
+  -static-libtool-libs
+                    do not do any dynamic linking of libtool libraries
+  -version-info CURRENT[:REVISION[:AGE]]
+                    specify library version info [each variable defaults to 0]
+  -weak LIBNAME     declare that the target provides the LIBNAME interface
+
+All other options (arguments beginning with \`-') are ignored.
+
+Every other argument is treated as a filename.  Files ending in \`.la' are
+treated as uninstalled libtool libraries, other files are standard or library
+object files.
+
+If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
+only library objects (\`.lo' files) may be specified, and \`-rpath' is
+required, except when creating a convenience library.
+
+If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
+using \`ar' and \`ranlib', or on Windows using \`lib'.
+
+If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
+is created, otherwise an executable program is created."
+        ;;
+
+      uninstall)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
+
+Remove libraries from an installation directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm').  RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, all the files associated with it are deleted.
+Otherwise, only FILE itself is deleted using RM."
+        ;;
+
+      *)
+        func_fatal_help "invalid operation mode \`$mode'"
+        ;;
+    esac
+
+    $ECHO
+    $ECHO "Try \`$progname --help' for more information about other modes."
+
+    exit $?
+}
+
+  # Now that we've collected a possible --mode arg, show help if necessary
+  $opt_help && func_mode_help
+
+
+# func_mode_execute arg...
+func_mode_execute ()
+{
+    $opt_debug
+    # The first argument is the command name.
+    cmd="$nonopt"
+    test -z "$cmd" && \
+      func_fatal_help "you must specify a COMMAND"
+
+    # Handle -dlopen flags immediately.
+    for file in $execute_dlfiles; do
+      test -f "$file" \
+	|| func_fatal_help "\`$file' is not a file"
+
+      dir=
+      case $file in
+      *.la)
+	# Check to see that this really is a libtool archive.
+	func_lalib_unsafe_p "$file" \
+	  || func_fatal_help "\`$lib' is not a valid libtool archive"
+
+	# Read the libtool library.
+	dlname=
+	library_names=
+	func_source "$file"
+
+	# Skip this library if it cannot be dlopened.
+	if test -z "$dlname"; then
+	  # Warn if it was a shared library.
+	  test -n "$library_names" && \
+	    func_warning "\`$file' was not linked with \`-export-dynamic'"
+	  continue
+	fi
+
+	func_dirname "$file" "" "."
+	dir="$func_dirname_result"
+
+	if test -f "$dir/$objdir/$dlname"; then
+	  dir="$dir/$objdir"
+	else
+	  if test ! -f "$dir/$dlname"; then
+	    func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'"
+	  fi
+	fi
+	;;
+
+      *.lo)
+	# Just add the directory containing the .lo file.
+	func_dirname "$file" "" "."
+	dir="$func_dirname_result"
+	;;
+
+      *)
+	func_warning "\`-dlopen' is ignored for non-libtool libraries and objects"
+	continue
+	;;
+      esac
+
+      # Get the absolute pathname.
+      absdir=`cd "$dir" && pwd`
+      test -n "$absdir" && dir="$absdir"
+
+      # Now add the directory to shlibpath_var.
+      if eval "test -z \"\$$shlibpath_var\""; then
+	eval "$shlibpath_var=\"\$dir\""
+      else
+	eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
+      fi
+    done
+
+    # This variable tells wrapper scripts just to set shlibpath_var
+    # rather than running their programs.
+    libtool_execute_magic="$magic"
+
+    # Check if any of the arguments is a wrapper script.
+    args=
+    for file
+    do
+      case $file in
+      -*) ;;
+      *)
+	# Do a test to see if this is really a libtool program.
+	if func_ltwrapper_script_p "$file"; then
+	  func_source "$file"
+	  # Transform arg to wrapped name.
+	  file="$progdir/$program"
+	elif func_ltwrapper_executable_p "$file"; then
+	  func_ltwrapper_scriptname "$file"
+	  func_source "$func_ltwrapper_scriptname_result"
+	  # Transform arg to wrapped name.
+	  file="$progdir/$program"
+	fi
+	;;
+      esac
+      # Quote arguments (to preserve shell metacharacters).
+      func_quote_for_eval "$file"
+      args="$args $func_quote_for_eval_result"
+    done
+
+    if test "X$opt_dry_run" = Xfalse; then
+      if test -n "$shlibpath_var"; then
+	# Export the shlibpath_var.
+	eval "export $shlibpath_var"
+      fi
+
+      # Restore saved environment variables
+      for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+      do
+	eval "if test \"\${save_$lt_var+set}\" = set; then
+                $lt_var=\$save_$lt_var; export $lt_var
+	      else
+		$lt_unset $lt_var
+	      fi"
+      done
+
+      # Now prepare to actually exec the command.
+      exec_cmd="\$cmd$args"
+    else
+      # Display what would be done.
+      if test -n "$shlibpath_var"; then
+	eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\""
+	$ECHO "export $shlibpath_var"
+      fi
+      $ECHO "$cmd$args"
+      exit $EXIT_SUCCESS
+    fi
+}
+
+test "$mode" = execute && func_mode_execute ${1+"$@"}
+
+
+# func_mode_finish arg...
+func_mode_finish ()
+{
+    $opt_debug
+    libdirs="$nonopt"
+    admincmds=
+
+    if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+      for dir
+      do
+	libdirs="$libdirs $dir"
+      done
+
+      for libdir in $libdirs; do
+	if test -n "$finish_cmds"; then
+	  # Do each command in the finish commands.
+	  func_execute_cmds "$finish_cmds" 'admincmds="$admincmds
+'"$cmd"'"'
+	fi
+	if test -n "$finish_eval"; then
+	  # Do the single finish_eval.
+	  eval cmds=\"$finish_eval\"
+	  $opt_dry_run || eval "$cmds" || admincmds="$admincmds
+       $cmds"
+	fi
+      done
+    fi
+
+    # Exit here if they wanted silent mode.
+    $opt_silent && exit $EXIT_SUCCESS
+
+    $ECHO "X----------------------------------------------------------------------" | $Xsed
+    $ECHO "Libraries have been installed in:"
+    for libdir in $libdirs; do
+      $ECHO "   $libdir"
+    done
+    $ECHO
+    $ECHO "If you ever happen to want to link against installed libraries"
+    $ECHO "in a given directory, LIBDIR, you must either use libtool, and"
+    $ECHO "specify the full pathname of the library, or use the \`-LLIBDIR'"
+    $ECHO "flag during linking and do at least one of the following:"
+    if test -n "$shlibpath_var"; then
+      $ECHO "   - add LIBDIR to the \`$shlibpath_var' environment variable"
+      $ECHO "     during execution"
+    fi
+    if test -n "$runpath_var"; then
+      $ECHO "   - add LIBDIR to the \`$runpath_var' environment variable"
+      $ECHO "     during linking"
+    fi
+    if test -n "$hardcode_libdir_flag_spec"; then
+      libdir=LIBDIR
+      eval flag=\"$hardcode_libdir_flag_spec\"
+
+      $ECHO "   - use the \`$flag' linker flag"
+    fi
+    if test -n "$admincmds"; then
+      $ECHO "   - have your system administrator run these commands:$admincmds"
+    fi
+    if test -f /etc/ld.so.conf; then
+      $ECHO "   - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
+    fi
+    $ECHO
+
+    $ECHO "See any operating system documentation about shared libraries for"
+    case $host in
+      solaris2.[6789]|solaris2.1[0-9])
+        $ECHO "more information, such as the ld(1), crle(1) and ld.so(8) manual"
+	$ECHO "pages."
+	;;
+      *)
+        $ECHO "more information, such as the ld(1) and ld.so(8) manual pages."
+        ;;
+    esac
+    $ECHO "X----------------------------------------------------------------------" | $Xsed
+    exit $EXIT_SUCCESS
+}
+
+test "$mode" = finish && func_mode_finish ${1+"$@"}
+
+
+# func_mode_install arg...
+func_mode_install ()
+{
+    $opt_debug
+    # There may be an optional sh(1) argument at the beginning of
+    # install_prog (especially on Windows NT).
+    if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
+       # Allow the use of GNU shtool's install command.
+       $ECHO "X$nonopt" | $GREP shtool >/dev/null; then
+      # Aesthetically quote it.
+      func_quote_for_eval "$nonopt"
+      install_prog="$func_quote_for_eval_result "
+      arg=$1
+      shift
+    else
+      install_prog=
+      arg=$nonopt
+    fi
+
+    # The real first argument should be the name of the installation program.
+    # Aesthetically quote it.
+    func_quote_for_eval "$arg"
+    install_prog="$install_prog$func_quote_for_eval_result"
+
+    # We need to accept at least all the BSD install flags.
+    dest=
+    files=
+    opts=
+    prev=
+    install_type=
+    isdir=no
+    stripme=
+    for arg
+    do
+      if test -n "$dest"; then
+	files="$files $dest"
+	dest=$arg
+	continue
+      fi
+
+      case $arg in
+      -d) isdir=yes ;;
+      -f)
+	case " $install_prog " in
+	*[\\\ /]cp\ *) ;;
+	*) prev=$arg ;;
+	esac
+	;;
+      -g | -m | -o)
+	prev=$arg
+	;;
+      -s)
+	stripme=" -s"
+	continue
+	;;
+      -*)
+	;;
+      *)
+	# If the previous option needed an argument, then skip it.
+	if test -n "$prev"; then
+	  prev=
+	else
+	  dest=$arg
+	  continue
+	fi
+	;;
+      esac
+
+      # Aesthetically quote the argument.
+      func_quote_for_eval "$arg"
+      install_prog="$install_prog $func_quote_for_eval_result"
+    done
+
+    test -z "$install_prog" && \
+      func_fatal_help "you must specify an install program"
+
+    test -n "$prev" && \
+      func_fatal_help "the \`$prev' option requires an argument"
+
+    if test -z "$files"; then
+      if test -z "$dest"; then
+	func_fatal_help "no file or destination specified"
+      else
+	func_fatal_help "you must specify a destination"
+      fi
+    fi
+
+    # Strip any trailing slash from the destination.
+    func_stripname '' '/' "$dest"
+    dest=$func_stripname_result
+
+    # Check to see that the destination is a directory.
+    test -d "$dest" && isdir=yes
+    if test "$isdir" = yes; then
+      destdir="$dest"
+      destname=
+    else
+      func_dirname_and_basename "$dest" "" "."
+      destdir="$func_dirname_result"
+      destname="$func_basename_result"
+
+      # Not a directory, so check to see that there is only one file specified.
+      set dummy $files; shift
+      test "$#" -gt 1 && \
+	func_fatal_help "\`$dest' is not a directory"
+    fi
+    case $destdir in
+    [\\/]* | [A-Za-z]:[\\/]*) ;;
+    *)
+      for file in $files; do
+	case $file in
+	*.lo) ;;
+	*)
+	  func_fatal_help "\`$destdir' must be an absolute directory name"
+	  ;;
+	esac
+      done
+      ;;
+    esac
+
+    # This variable tells wrapper scripts just to set variables rather
+    # than running their programs.
+    libtool_install_magic="$magic"
+
+    staticlibs=
+    future_libdirs=
+    current_libdirs=
+    for file in $files; do
+
+      # Do each installation.
+      case $file in
+      *.$libext)
+	# Do the static libraries later.
+	staticlibs="$staticlibs $file"
+	;;
+
+      *.la)
+	# Check to see that this really is a libtool archive.
+	func_lalib_unsafe_p "$file" \
+	  || func_fatal_help "\`$file' is not a valid libtool archive"
+
+	library_names=
+	old_library=
+	relink_command=
+	func_source "$file"
+
+	# Add the libdir to current_libdirs if it is the destination.
+	if test "X$destdir" = "X$libdir"; then
+	  case "$current_libdirs " in
+	  *" $libdir "*) ;;
+	  *) current_libdirs="$current_libdirs $libdir" ;;
+	  esac
+	else
+	  # Note the libdir as a future libdir.
+	  case "$future_libdirs " in
+	  *" $libdir "*) ;;
+	  *) future_libdirs="$future_libdirs $libdir" ;;
+	  esac
+	fi
+
+	func_dirname "$file" "/" ""
+	dir="$func_dirname_result"
+	dir="$dir$objdir"
+
+	if test -n "$relink_command"; then
+	  # Determine the prefix the user has applied to our future dir.
+	  inst_prefix_dir=`$ECHO "X$destdir" | $Xsed -e "s%$libdir\$%%"`
+
+	  # Don't allow the user to place us outside of our expected
+	  # location b/c this prevents finding dependent libraries that
+	  # are installed to the same prefix.
+	  # At present, this check doesn't affect windows .dll's that
+	  # are installed into $libdir/../bin (currently, that works fine)
+	  # but it's something to keep an eye on.
+	  test "$inst_prefix_dir" = "$destdir" && \
+	    func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir"
+
+	  if test -n "$inst_prefix_dir"; then
+	    # Stick the inst_prefix_dir data into the link command.
+	    relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
+	  else
+	    relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%%"`
+	  fi
+
+	  func_warning "relinking \`$file'"
+	  func_show_eval "$relink_command" \
+	    'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"'
+	fi
+
+	# See the names of the shared library.
+	set dummy $library_names; shift
+	if test -n "$1"; then
+	  realname="$1"
+	  shift
+
+	  srcname="$realname"
+	  test -n "$relink_command" && srcname="$realname"T
+
+	  # Install the shared library and build the symlinks.
+	  func_show_eval "$install_prog $dir/$srcname $destdir/$realname" \
+	      'exit $?'
+	  tstripme="$stripme"
+	  case $host_os in
+	  cygwin* | mingw* | pw32*)
+	    case $realname in
+	    *.dll.a)
+	      tstripme=""
+	      ;;
+	    esac
+	    ;;
+	  esac
+	  if test -n "$tstripme" && test -n "$striplib"; then
+	    func_show_eval "$striplib $destdir/$realname" 'exit $?'
+	  fi
+
+	  if test "$#" -gt 0; then
+	    # Delete the old symlinks, and create new ones.
+	    # Try `ln -sf' first, because the `ln' binary might depend on
+	    # the symlink we replace!  Solaris /bin/ln does not understand -f,
+	    # so we also need to try rm && ln -s.
+	    for linkname
+	    do
+	      test "$linkname" != "$realname" \
+		&& func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })"
+	    done
+	  fi
+
+	  # Do each command in the postinstall commands.
+	  lib="$destdir/$realname"
+	  func_execute_cmds "$postinstall_cmds" 'exit $?'
+	fi
+
+	# Install the pseudo-library for information purposes.
+	func_basename "$file"
+	name="$func_basename_result"
+	instname="$dir/$name"i
+	func_show_eval "$install_prog $instname $destdir/$name" 'exit $?'
+
+	# Maybe install the static library, too.
+	test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
+	;;
+
+      *.lo)
+	# Install (i.e. copy) a libtool object.
+
+	# Figure out destination file name, if it wasn't already specified.
+	if test -n "$destname"; then
+	  destfile="$destdir/$destname"
+	else
+	  func_basename "$file"
+	  destfile="$func_basename_result"
+	  destfile="$destdir/$destfile"
+	fi
+
+	# Deduce the name of the destination old-style object file.
+	case $destfile in
+	*.lo)
+	  func_lo2o "$destfile"
+	  staticdest=$func_lo2o_result
+	  ;;
+	*.$objext)
+	  staticdest="$destfile"
+	  destfile=
+	  ;;
+	*)
+	  func_fatal_help "cannot copy a libtool object to \`$destfile'"
+	  ;;
+	esac
+
+	# Install the libtool object if requested.
+	test -n "$destfile" && \
+	  func_show_eval "$install_prog $file $destfile" 'exit $?'
+
+	# Install the old object if enabled.
+	if test "$build_old_libs" = yes; then
+	  # Deduce the name of the old-style object file.
+	  func_lo2o "$file"
+	  staticobj=$func_lo2o_result
+	  func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?'
+	fi
+	exit $EXIT_SUCCESS
+	;;
+
+      *)
+	# Figure out destination file name, if it wasn't already specified.
+	if test -n "$destname"; then
+	  destfile="$destdir/$destname"
+	else
+	  func_basename "$file"
+	  destfile="$func_basename_result"
+	  destfile="$destdir/$destfile"
+	fi
+
+	# If the file is missing, and there is a .exe on the end, strip it
+	# because it is most likely a libtool script we actually want to
+	# install
+	stripped_ext=""
+	case $file in
+	  *.exe)
+	    if test ! -f "$file"; then
+	      func_stripname '' '.exe' "$file"
+	      file=$func_stripname_result
+	      stripped_ext=".exe"
+	    fi
+	    ;;
+	esac
+
+	# Do a test to see if this is really a libtool program.
+	case $host in
+	*cygwin*|*mingw*)
+	    if func_ltwrapper_executable_p "$file"; then
+	      func_ltwrapper_scriptname "$file"
+	      wrapper=$func_ltwrapper_scriptname_result
+	    else
+	      func_stripname '' '.exe' "$file"
+	      wrapper=$func_stripname_result
+	    fi
+	    ;;
+	*)
+	    wrapper=$file
+	    ;;
+	esac
+	if func_ltwrapper_script_p "$wrapper"; then
+	  notinst_deplibs=
+	  relink_command=
+
+	  func_source "$wrapper"
+
+	  # Check the variables that should have been set.
+	  test -z "$generated_by_libtool_version" && \
+	    func_fatal_error "invalid libtool wrapper script \`$wrapper'"
+
+	  finalize=yes
+	  for lib in $notinst_deplibs; do
+	    # Check to see that each library is installed.
+	    libdir=
+	    if test -f "$lib"; then
+	      func_source "$lib"
+	    fi
+	    libfile="$libdir/"`$ECHO "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test
+	    if test -n "$libdir" && test ! -f "$libfile"; then
+	      func_warning "\`$lib' has not been installed in \`$libdir'"
+	      finalize=no
+	    fi
+	  done
+
+	  relink_command=
+	  func_source "$wrapper"
+
+	  outputname=
+	  if test "$fast_install" = no && test -n "$relink_command"; then
+	    $opt_dry_run || {
+	      if test "$finalize" = yes; then
+	        tmpdir=`func_mktempdir`
+		func_basename "$file$stripped_ext"
+		file="$func_basename_result"
+	        outputname="$tmpdir/$file"
+	        # Replace the output file specification.
+	        relink_command=`$ECHO "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'`
+
+	        $opt_silent || {
+	          func_quote_for_expand "$relink_command"
+		  eval "func_echo $func_quote_for_expand_result"
+	        }
+	        if eval "$relink_command"; then :
+	          else
+		  func_error "error: relink \`$file' with the above command before installing it"
+		  $opt_dry_run || ${RM}r "$tmpdir"
+		  continue
+	        fi
+	        file="$outputname"
+	      else
+	        func_warning "cannot relink \`$file'"
+	      fi
+	    }
+	  else
+	    # Install the binary that we compiled earlier.
+	    file=`$ECHO "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
+	  fi
+	fi
+
+	# remove .exe since cygwin /usr/bin/install will append another
+	# one anyway
+	case $install_prog,$host in
+	*/usr/bin/install*,*cygwin*)
+	  case $file:$destfile in
+	  *.exe:*.exe)
+	    # this is ok
+	    ;;
+	  *.exe:*)
+	    destfile=$destfile.exe
+	    ;;
+	  *:*.exe)
+	    func_stripname '' '.exe' "$destfile"
+	    destfile=$func_stripname_result
+	    ;;
+	  esac
+	  ;;
+	esac
+	func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?'
+	$opt_dry_run || if test -n "$outputname"; then
+	  ${RM}r "$tmpdir"
+	fi
+	;;
+      esac
+    done
+
+    for file in $staticlibs; do
+      func_basename "$file"
+      name="$func_basename_result"
+
+      # Set up the ranlib parameters.
+      oldlib="$destdir/$name"
+
+      func_show_eval "$install_prog \$file \$oldlib" 'exit $?'
+
+      if test -n "$stripme" && test -n "$old_striplib"; then
+	func_show_eval "$old_striplib $oldlib" 'exit $?'
+      fi
+
+      # Do each command in the postinstall commands.
+      func_execute_cmds "$old_postinstall_cmds" 'exit $?'
+    done
+
+    test -n "$future_libdirs" && \
+      func_warning "remember to run \`$progname --finish$future_libdirs'"
+
+    if test -n "$current_libdirs"; then
+      # Maybe just do a dry run.
+      $opt_dry_run && current_libdirs=" -n$current_libdirs"
+      exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs'
+    else
+      exit $EXIT_SUCCESS
+    fi
+}
+
+test "$mode" = install && func_mode_install ${1+"$@"}
+
+
+# func_generate_dlsyms outputname originator pic_p
+# Extract symbols from dlprefiles and create ${outputname}S.o with
+# a dlpreopen symbol table.
+func_generate_dlsyms ()
+{
+    $opt_debug
+    my_outputname="$1"
+    my_originator="$2"
+    my_pic_p="${3-no}"
+    my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'`
+    my_dlsyms=
+
+    if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+      if test -n "$NM" && test -n "$global_symbol_pipe"; then
+	my_dlsyms="${my_outputname}S.c"
+      else
+	func_error "not configured to extract global symbols from dlpreopened files"
+      fi
+    fi
+
+    if test -n "$my_dlsyms"; then
+      case $my_dlsyms in
+      "") ;;
+      *.c)
+	# Discover the nlist of each of the dlfiles.
+	nlist="$output_objdir/${my_outputname}.nm"
+
+	func_show_eval "$RM $nlist ${nlist}S ${nlist}T"
+
+	# Parse the name list into a source file.
+	func_verbose "creating $output_objdir/$my_dlsyms"
+
+	$opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\
+/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */
+/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+/* External symbol declarations for the compiler. */\
+"
+
+	if test "$dlself" = yes; then
+	  func_verbose "generating symbol list for \`$output'"
+
+	  $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist"
+
+	  # Add our own program objects to the symbol list.
+	  progfiles=`$ECHO "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+	  for progfile in $progfiles; do
+	    func_verbose "extracting global C symbols from \`$progfile'"
+	    $opt_dry_run || eval "$NM $progfile | $global_symbol_pipe >> '$nlist'"
+	  done
+
+	  if test -n "$exclude_expsyms"; then
+	    $opt_dry_run || {
+	      eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
+	      eval '$MV "$nlist"T "$nlist"'
+	    }
+	  fi
+
+	  if test -n "$export_symbols_regex"; then
+	    $opt_dry_run || {
+	      eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T'
+	      eval '$MV "$nlist"T "$nlist"'
+	    }
+	  fi
+
+	  # Prepare the list of exported symbols
+	  if test -z "$export_symbols"; then
+	    export_symbols="$output_objdir/$outputname.exp"
+	    $opt_dry_run || {
+	      $RM $export_symbols
+	      eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+	      case $host in
+	      *cygwin* | *mingw* )
+                eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+                eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"'
+	        ;;
+	      esac
+	    }
+	  else
+	    $opt_dry_run || {
+	      eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"'
+	      eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T'
+	      eval '$MV "$nlist"T "$nlist"'
+	      case $host in
+	        *cygwin | *mingw* )
+	          eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+	          eval 'cat "$nlist" >> "$output_objdir/$outputname.def"'
+	          ;;
+	      esac
+	    }
+	  fi
+	fi
+
+	for dlprefile in $dlprefiles; do
+	  func_verbose "extracting global C symbols from \`$dlprefile'"
+	  func_basename "$dlprefile"
+	  name="$func_basename_result"
+	  $opt_dry_run || {
+	    eval '$ECHO ": $name " >> "$nlist"'
+	    eval "$NM $dlprefile 2>/dev/null | $global_symbol_pipe >> '$nlist'"
+	  }
+	done
+
+	$opt_dry_run || {
+	  # Make sure we have at least an empty file.
+	  test -f "$nlist" || : > "$nlist"
+
+	  if test -n "$exclude_expsyms"; then
+	    $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+	    $MV "$nlist"T "$nlist"
+	  fi
+
+	  # Try sorting and uniquifying the output.
+	  if $GREP -v "^: " < "$nlist" |
+	      if sort -k 3 </dev/null >/dev/null 2>&1; then
+		sort -k 3
+	      else
+		sort +2
+	      fi |
+	      uniq > "$nlist"S; then
+	    :
+	  else
+	    $GREP -v "^: " < "$nlist" > "$nlist"S
+	  fi
+
+	  if test -f "$nlist"S; then
+	    eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"'
+	  else
+	    $ECHO '/* NONE */' >> "$output_objdir/$my_dlsyms"
+	  fi
+
+	  $ECHO >> "$output_objdir/$my_dlsyms" "\
+
+/* The mapping between symbol names and symbols.  */
+typedef struct {
+  const char *name;
+  void *address;
+} lt_dlsymlist;
+"
+	  case $host in
+	  *cygwin* | *mingw* )
+	    $ECHO >> "$output_objdir/$my_dlsyms" "\
+/* DATA imports from DLLs on WIN32 con't be const, because
+   runtime relocations are performed -- see ld's documentation
+   on pseudo-relocs.  */"
+	    lt_dlsym_const= ;;
+	  *osf5*)
+	    echo >> "$output_objdir/$my_dlsyms" "\
+/* This system does not cope well with relocations in const data */"
+	    lt_dlsym_const= ;;
+	  *)
+	    lt_dlsym_const=const ;;
+	  esac
+
+	  $ECHO >> "$output_objdir/$my_dlsyms" "\
+extern $lt_dlsym_const lt_dlsymlist
+lt_${my_prefix}_LTX_preloaded_symbols[];
+$lt_dlsym_const lt_dlsymlist
+lt_${my_prefix}_LTX_preloaded_symbols[] =
+{\
+  { \"$my_originator\", (void *) 0 },"
+
+	  case $need_lib_prefix in
+	  no)
+	    eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms"
+	    ;;
+	  *)
+	    eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms"
+	    ;;
+	  esac
+	  $ECHO >> "$output_objdir/$my_dlsyms" "\
+  {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt_${my_prefix}_LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif\
+"
+	} # !$opt_dry_run
+
+	pic_flag_for_symtable=
+	case "$compile_command " in
+	*" -static "*) ;;
+	*)
+	  case $host in
+	  # compiling the symbol table file with pic_flag works around
+	  # a FreeBSD bug that causes programs to crash when -lm is
+	  # linked before any other PIC object.  But we must not use
+	  # pic_flag when linking with -static.  The problem exists in
+	  # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
+	  *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
+	    pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;;
+	  *-*-hpux*)
+	    pic_flag_for_symtable=" $pic_flag"  ;;
+	  *)
+	    if test "X$my_pic_p" != Xno; then
+	      pic_flag_for_symtable=" $pic_flag"
+	    fi
+	    ;;
+	  esac
+	  ;;
+	esac
+	symtab_cflags=
+	for arg in $LTCFLAGS; do
+	  case $arg in
+	  -pie | -fpie | -fPIE) ;;
+	  *) symtab_cflags="$symtab_cflags $arg" ;;
+	  esac
+	done
+
+	# Now compile the dynamic symbol file.
+	func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?'
+
+	# Clean up the generated files.
+	func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"'
+
+	# Transform the symbol file into the correct name.
+	symfileobj="$output_objdir/${my_outputname}S.$objext"
+	case $host in
+	*cygwin* | *mingw* )
+	  if test -f "$output_objdir/$my_outputname.def"; then
+	    compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
+	    finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
+	  else
+	    compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"`
+	    finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"`
+	  fi
+	  ;;
+	*)
+	  compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"`
+	  finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"`
+	  ;;
+	esac
+	;;
+      *)
+	func_fatal_error "unknown suffix for \`$my_dlsyms'"
+	;;
+      esac
+    else
+      # We keep going just in case the user didn't refer to
+      # lt_preloaded_symbols.  The linker will fail if global_symbol_pipe
+      # really was required.
+
+      # Nullify the symbol file.
+      compile_command=`$ECHO "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"`
+      finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"`
+    fi
+}
+
+# func_win32_libid arg
+# return the library type of file 'arg'
+#
+# Need a lot of goo to handle *both* DLLs and import libs
+# Has to be a shell function in order to 'eat' the argument
+# that is supplied when $file_magic_command is called.
+func_win32_libid ()
+{
+  $opt_debug
+  win32_libid_type="unknown"
+  win32_fileres=`file -L $1 2>/dev/null`
+  case $win32_fileres in
+  *ar\ archive\ import\ library*) # definitely import
+    win32_libid_type="x86 archive import"
+    ;;
+  *ar\ archive*) # could be an import, or static
+    if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null |
+       $EGREP 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then
+      win32_nmres=`eval $NM -f posix -A $1 |
+	$SED -n -e '
+	    1,100{
+		/ I /{
+		    s,.*,import,
+		    p
+		    q
+		}
+	    }'`
+      case $win32_nmres in
+      import*)  win32_libid_type="x86 archive import";;
+      *)        win32_libid_type="x86 archive static";;
+      esac
+    fi
+    ;;
+  *DLL*)
+    win32_libid_type="x86 DLL"
+    ;;
+  *executable*) # but shell scripts are "executable" too...
+    case $win32_fileres in
+    *MS\ Windows\ PE\ Intel*)
+      win32_libid_type="x86 DLL"
+      ;;
+    esac
+    ;;
+  esac
+  $ECHO "$win32_libid_type"
+}
+
+
+
+# func_extract_an_archive dir oldlib
+func_extract_an_archive ()
+{
+    $opt_debug
+    f_ex_an_ar_dir="$1"; shift
+    f_ex_an_ar_oldlib="$1"
+    func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" 'exit $?'
+    if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
+     :
+    else
+      func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib"
+    fi
+}
+
+
+# func_extract_archives gentop oldlib ...
+func_extract_archives ()
+{
+    $opt_debug
+    my_gentop="$1"; shift
+    my_oldlibs=${1+"$@"}
+    my_oldobjs=""
+    my_xlib=""
+    my_xabs=""
+    my_xdir=""
+
+    for my_xlib in $my_oldlibs; do
+      # Extract the objects.
+      case $my_xlib in
+	[\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;;
+	*) my_xabs=`pwd`"/$my_xlib" ;;
+      esac
+      func_basename "$my_xlib"
+      my_xlib="$func_basename_result"
+      my_xlib_u=$my_xlib
+      while :; do
+        case " $extracted_archives " in
+	*" $my_xlib_u "*)
+	  func_arith $extracted_serial + 1
+	  extracted_serial=$func_arith_result
+	  my_xlib_u=lt$extracted_serial-$my_xlib ;;
+	*) break ;;
+	esac
+      done
+      extracted_archives="$extracted_archives $my_xlib_u"
+      my_xdir="$my_gentop/$my_xlib_u"
+
+      func_mkdir_p "$my_xdir"
+
+      case $host in
+      *-darwin*)
+	func_verbose "Extracting $my_xabs"
+	# Do not bother doing anything if just a dry run
+	$opt_dry_run || {
+	  darwin_orig_dir=`pwd`
+	  cd $my_xdir || exit $?
+	  darwin_archive=$my_xabs
+	  darwin_curdir=`pwd`
+	  darwin_base_archive=`basename "$darwin_archive"`
+	  darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true`
+	  if test -n "$darwin_arches"; then
+	    darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'`
+	    darwin_arch=
+	    func_verbose "$darwin_base_archive has multiple architectures $darwin_arches"
+	    for darwin_arch in  $darwin_arches ; do
+	      func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+	      $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}"
+	      cd "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+	      func_extract_an_archive "`pwd`" "${darwin_base_archive}"
+	      cd "$darwin_curdir"
+	      $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}"
+	    done # $darwin_arches
+            ## Okay now we've a bunch of thin objects, gotta fatten them up :)
+	    darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u`
+	    darwin_file=
+	    darwin_files=
+	    for darwin_file in $darwin_filelist; do
+	      darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP`
+	      $LIPO -create -output "$darwin_file" $darwin_files
+	    done # $darwin_filelist
+	    $RM -rf unfat-$$
+	    cd "$darwin_orig_dir"
+	  else
+	    cd $darwin_orig_dir
+	    func_extract_an_archive "$my_xdir" "$my_xabs"
+	  fi # $darwin_arches
+	} # !$opt_dry_run
+	;;
+      *)
+        func_extract_an_archive "$my_xdir" "$my_xabs"
+	;;
+      esac
+      my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
+    done
+
+    func_extract_archives_result="$my_oldobjs"
+}
+
+
+
+# func_emit_wrapper arg
+#
+# emit a libtool wrapper script on stdout
+# don't directly open a file because we may want to
+# incorporate the script contents within a cygwin/mingw
+# wrapper executable.  Must ONLY be called from within
+# func_mode_link because it depends on a number of variable
+# set therein.
+#
+# arg is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR
+# variable will take.  If 'yes', then the emitted script
+# will assume that the directory in which it is stored is
+# the '.lib' directory.  This is a cygwin/mingw-specific
+# behavior.
+func_emit_wrapper ()
+{
+	func_emit_wrapper_arg1=no
+	if test -n "$1" ; then
+	  func_emit_wrapper_arg1=$1
+	fi
+
+	$ECHO "\
+#! $SHELL
+
+# $output - temporary wrapper script for $objdir/$outputname
+# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+#
+# The $output program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='${SED} -e 1s/^X//'
+sed_quote_subst='$sed_quote_subst'
+
+# Be Bourne compatible
+if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command=\"$relink_command\"
+
+# This environment variable determines our operation mode.
+if test \"\$libtool_install_magic\" = \"$magic\"; then
+  # install mode needs the following variables:
+  generated_by_libtool_version='$macro_version'
+  notinst_deplibs='$notinst_deplibs'
+else
+  # When we are sourced in execute mode, \$file and \$ECHO are already set.
+  if test \"\$libtool_execute_magic\" != \"$magic\"; then
+    ECHO=\"$qecho\"
+    file=\"\$0\"
+    # Make sure echo works.
+    if test \"X\$1\" = X--no-reexec; then
+      # Discard the --no-reexec flag, and continue.
+      shift
+    elif test \"X\`{ \$ECHO '\t'; } 2>/dev/null\`\" = 'X\t'; then
+      # Yippee, \$ECHO works!
+      :
+    else
+      # Restart under the correct shell, and then maybe \$ECHO will work.
+      exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"}
+    fi
+  fi\
+"
+	$ECHO "\
+
+  # Find the directory that this script lives in.
+  thisdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\`
+  test \"x\$thisdir\" = \"x\$file\" && thisdir=.
+
+  # Follow symbolic links until we get to the real thisdir.
+  file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\`
+  while test -n \"\$file\"; do
+    destdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\`
+
+    # If there was a directory component, then change thisdir.
+    if test \"x\$destdir\" != \"x\$file\"; then
+      case \"\$destdir\" in
+      [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
+      *) thisdir=\"\$thisdir/\$destdir\" ;;
+      esac
+    fi
+
+    file=\`\$ECHO \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
+    file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\`
+  done
+
+  # Usually 'no', except on cygwin/mingw when embedded into
+  # the cwrapper.
+  WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1
+  if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then
+    # special case for '.'
+    if test \"\$thisdir\" = \".\"; then
+      thisdir=\`pwd\`
+    fi
+    # remove .libs from thisdir
+    case \"\$thisdir\" in
+    *[\\\\/]$objdir ) thisdir=\`\$ECHO \"X\$thisdir\" | \$Xsed -e 's%[\\\\/][^\\\\/]*$%%'\` ;;
+    $objdir )   thisdir=. ;;
+    esac
+  fi
+
+  # Try to get the absolute directory name.
+  absdir=\`cd \"\$thisdir\" && pwd\`
+  test -n \"\$absdir\" && thisdir=\"\$absdir\"
+"
+
+	if test "$fast_install" = yes; then
+	  $ECHO "\
+  program=lt-'$outputname'$exeext
+  progdir=\"\$thisdir/$objdir\"
+
+  if test ! -f \"\$progdir/\$program\" ||
+     { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\
+       test \"X\$file\" != \"X\$progdir/\$program\"; }; then
+
+    file=\"\$\$-\$program\"
+
+    if test ! -d \"\$progdir\"; then
+      $MKDIR \"\$progdir\"
+    else
+      $RM \"\$progdir/\$file\"
+    fi"
+
+	  $ECHO "\
+
+    # relink executable if necessary
+    if test -n \"\$relink_command\"; then
+      if relink_command_output=\`eval \$relink_command 2>&1\`; then :
+      else
+	$ECHO \"\$relink_command_output\" >&2
+	$RM \"\$progdir/\$file\"
+	exit 1
+      fi
+    fi
+
+    $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
+    { $RM \"\$progdir/\$program\";
+      $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; }
+    $RM \"\$progdir/\$file\"
+  fi"
+	else
+	  $ECHO "\
+  program='$outputname'
+  progdir=\"\$thisdir/$objdir\"
+"
+	fi
+
+	$ECHO "\
+
+  if test -f \"\$progdir/\$program\"; then"
+
+	# Export our shlibpath_var if we have one.
+	if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+	  $ECHO "\
+    # Add our own library path to $shlibpath_var
+    $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
+
+    # Some systems cannot cope with colon-terminated $shlibpath_var
+    # The second colon is a workaround for a bug in BeOS R4 sed
+    $shlibpath_var=\`\$ECHO \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
+
+    export $shlibpath_var
+"
+	fi
+
+	# fixup the dll searchpath if we need to.
+	if test -n "$dllsearchpath"; then
+	  $ECHO "\
+    # Add the dll search path components to the executable PATH
+    PATH=$dllsearchpath:\$PATH
+"
+	fi
+
+	$ECHO "\
+    if test \"\$libtool_execute_magic\" != \"$magic\"; then
+      # Run the actual program with our arguments.
+"
+	case $host in
+	# Backslashes separate directories on plain windows
+	*-*-mingw | *-*-os2*)
+	  $ECHO "\
+      exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
+"
+	  ;;
+
+	*)
+	  $ECHO "\
+      exec \"\$progdir/\$program\" \${1+\"\$@\"}
+"
+	  ;;
+	esac
+	$ECHO "\
+      \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2
+      exit 1
+    fi
+  else
+    # The program doesn't exist.
+    \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2
+    \$ECHO \"This script is just a wrapper for \$program.\" 1>&2
+    $ECHO \"See the $PACKAGE documentation for more information.\" 1>&2
+    exit 1
+  fi
+fi\
+"
+}
+# end: func_emit_wrapper
+
+# func_emit_cwrapperexe_src
+# emit the source code for a wrapper executable on stdout
+# Must ONLY be called from within func_mode_link because
+# it depends on a number of variable set therein.
+func_emit_cwrapperexe_src ()
+{
+	cat <<EOF
+
+/* $cwrappersource - temporary wrapper executable for $objdir/$outputname
+   Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+
+   The $output program cannot be directly executed until all the libtool
+   libraries that it depends on are installed.
+
+   This wrapper executable should never be moved out of the build directory.
+   If it is, it will not operate correctly.
+
+   Currently, it simply execs the wrapper *script* "$SHELL $output",
+   but could eventually absorb all of the scripts functionality and
+   exec $objdir/$outputname directly.
+*/
+EOF
+	    cat <<"EOF"
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef _MSC_VER
+# include <direct.h>
+# include <process.h>
+# include <io.h>
+# define setmode _setmode
+#else
+# include <unistd.h>
+# include <stdint.h>
+# ifdef __CYGWIN__
+#  include <io.h>
+# endif
+#endif
+#include <malloc.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#if defined(PATH_MAX)
+# define LT_PATHMAX PATH_MAX
+#elif defined(MAXPATHLEN)
+# define LT_PATHMAX MAXPATHLEN
+#else
+# define LT_PATHMAX 1024
+#endif
+
+#ifndef S_IXOTH
+# define S_IXOTH 0
+#endif
+#ifndef S_IXGRP
+# define S_IXGRP 0
+#endif
+
+#ifdef _MSC_VER
+# define S_IXUSR _S_IEXEC
+# define stat _stat
+# ifndef _INTPTR_T_DEFINED
+#  define intptr_t int
+# endif
+#endif
+
+#ifndef DIR_SEPARATOR
+# define DIR_SEPARATOR '/'
+# define PATH_SEPARATOR ':'
+#endif
+
+#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \
+  defined (__OS2__)
+# define HAVE_DOS_BASED_FILE_SYSTEM
+# define FOPEN_WB "wb"
+# ifndef DIR_SEPARATOR_2
+#  define DIR_SEPARATOR_2 '\\'
+# endif
+# ifndef PATH_SEPARATOR_2
+#  define PATH_SEPARATOR_2 ';'
+# endif
+#endif
+
+#ifndef DIR_SEPARATOR_2
+# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
+#else /* DIR_SEPARATOR_2 */
+# define IS_DIR_SEPARATOR(ch) \
+	(((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
+#endif /* DIR_SEPARATOR_2 */
+
+#ifndef PATH_SEPARATOR_2
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR)
+#else /* PATH_SEPARATOR_2 */
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)
+#endif /* PATH_SEPARATOR_2 */
+
+#ifdef __CYGWIN__
+# define FOPEN_WB "wb"
+#endif
+
+#ifndef FOPEN_WB
+# define FOPEN_WB "w"
+#endif
+#ifndef _O_BINARY
+# define _O_BINARY 0
+#endif
+
+#define XMALLOC(type, num)      ((type *) xmalloc ((num) * sizeof(type)))
+#define XFREE(stale) do { \
+  if (stale) { free ((void *) stale); stale = 0; } \
+} while (0)
+
+#undef LTWRAPPER_DEBUGPRINTF
+#if defined DEBUGWRAPPER
+# define LTWRAPPER_DEBUGPRINTF(args) ltwrapper_debugprintf args
+static void
+ltwrapper_debugprintf (const char *fmt, ...)
+{
+    va_list args;
+    va_start (args, fmt);
+    (void) vfprintf (stderr, fmt, args);
+    va_end (args);
+}
+#else
+# define LTWRAPPER_DEBUGPRINTF(args)
+#endif
+
+const char *program_name = NULL;
+
+void *xmalloc (size_t num);
+char *xstrdup (const char *string);
+const char *base_name (const char *name);
+char *find_executable (const char *wrapper);
+char *chase_symlinks (const char *pathspec);
+int make_executable (const char *path);
+int check_executable (const char *path);
+char *strendzap (char *str, const char *pat);
+void lt_fatal (const char *message, ...);
+
+static const char *script_text =
+EOF
+
+	    func_emit_wrapper yes |
+	        $SED -e 's/\([\\"]\)/\\\1/g' \
+	             -e 's/^/  "/' -e 's/$/\\n"/'
+	    echo ";"
+
+	    cat <<EOF
+const char * MAGIC_EXE = "$magic_exe";
+
+int
+main (int argc, char *argv[])
+{
+  char **newargz;
+  char *tmp_pathspec;
+  char *actual_cwrapper_path;
+  char *shwrapper_name;
+  intptr_t rval = 127;
+  FILE *shwrapper;
+
+  const char *dumpscript_opt = "--lt-dump-script";
+  int i;
+
+  program_name = (char *) xstrdup (base_name (argv[0]));
+  LTWRAPPER_DEBUGPRINTF (("(main) argv[0]      : %s\n", argv[0]));
+  LTWRAPPER_DEBUGPRINTF (("(main) program_name : %s\n", program_name));
+
+  /* very simple arg parsing; don't want to rely on getopt */
+  for (i = 1; i < argc; i++)
+    {
+      if (strcmp (argv[i], dumpscript_opt) == 0)
+	{
+EOF
+	    case "$host" in
+	      *mingw* | *cygwin* )
+		# make stdout use "unix" line endings
+		echo "          setmode(1,_O_BINARY);"
+		;;
+	      esac
+
+	    cat <<EOF
+	  printf ("%s", script_text);
+	  return 0;
+	}
+    }
+
+  newargz = XMALLOC (char *, argc + 2);
+EOF
+
+	    if test -n "$TARGETSHELL" ; then
+	      # no path translation at all
+	      lt_newargv0=$TARGETSHELL
+	    else
+	      case "$host" in
+		*mingw* )
+		  # awkward: cmd appends spaces to result
+		  lt_sed_strip_trailing_spaces="s/[ ]*\$//"
+		  lt_newargv0=`( cmd //c echo $SHELL | $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo $SHELL`
+		  case $lt_newargv0 in
+		    *.exe | *.EXE) ;;
+		    *) lt_newargv0=$lt_newargv0.exe ;;
+		  esac
+		  ;;
+		* ) lt_newargv0=$SHELL ;;
+	      esac
+	    fi
+
+		cat <<EOF
+  newargz[0] = (char *) xstrdup ("$lt_newargv0");
+EOF
+
+	    cat <<"EOF"
+  tmp_pathspec = find_executable (argv[0]);
+  if (tmp_pathspec == NULL)
+    lt_fatal ("Couldn't find %s", argv[0]);
+  LTWRAPPER_DEBUGPRINTF (("(main) found exe (before symlink chase) at : %s\n",
+			  tmp_pathspec));
+
+  actual_cwrapper_path = chase_symlinks (tmp_pathspec);
+  LTWRAPPER_DEBUGPRINTF (("(main) found exe (after symlink chase) at : %s\n",
+			  actual_cwrapper_path));
+  XFREE (tmp_pathspec);
+
+  shwrapper_name = (char *) xstrdup (base_name (actual_cwrapper_path));
+  strendzap (actual_cwrapper_path, shwrapper_name);
+
+  /* shwrapper_name transforms */
+  strendzap (shwrapper_name, ".exe");
+  tmp_pathspec = XMALLOC (char, (strlen (shwrapper_name) +
+				 strlen ("_ltshwrapperTMP") + 1));
+  strcpy (tmp_pathspec, shwrapper_name);
+  strcat (tmp_pathspec, "_ltshwrapperTMP");
+  XFREE (shwrapper_name);
+  shwrapper_name = tmp_pathspec;
+  tmp_pathspec = 0;
+  LTWRAPPER_DEBUGPRINTF (("(main) libtool shell wrapper name: %s\n",
+			  shwrapper_name));
+EOF
+
+	    cat <<EOF
+  newargz[1] =
+    XMALLOC (char, (strlen (actual_cwrapper_path) +
+		    strlen ("$objdir") + 1 + strlen (shwrapper_name) + 1));
+  strcpy (newargz[1], actual_cwrapper_path);
+  strcat (newargz[1], "$objdir");
+  strcat (newargz[1], "/");
+  strcat (newargz[1], shwrapper_name);
+EOF
+
+
+	    case $host_os in
+	      mingw*)
+	    cat <<"EOF"
+  {
+    char* p;
+    while ((p = strchr (newargz[1], '\\')) != NULL)
+      {
+	*p = '/';
+      }
+  }
+EOF
+	    ;;
+	    esac
+
+	    cat <<"EOF"
+  XFREE (shwrapper_name);
+  XFREE (actual_cwrapper_path);
+
+  /* always write in binary mode */
+  if ((shwrapper = fopen (newargz[1], FOPEN_WB)) == 0)
+    {
+      lt_fatal ("Could not open %s for writing", newargz[1]);
+    }
+  fprintf (shwrapper, "%s", script_text);
+  fclose (shwrapper);
+
+  make_executable (newargz[1]);
+
+  for (i = 1; i < argc; i++)
+    newargz[i + 1] = xstrdup (argv[i]);
+  newargz[argc + 1] = NULL;
+
+  for (i = 0; i < argc + 1; i++)
+    {
+      LTWRAPPER_DEBUGPRINTF (("(main) newargz[%d]   : %s\n", i, newargz[i]));
+    }
+
+EOF
+
+	    case $host_os in
+	      mingw*)
+		cat <<EOF
+  /* execv doesn't actually work on mingw as expected on unix */
+  rval = _spawnv (_P_WAIT, "$lt_newargv0", (const char * const *) newargz);
+  if (rval == -1)
+    {
+      /* failed to start process */
+      LTWRAPPER_DEBUGPRINTF (("(main) failed to launch target \"$lt_newargv0\": errno = %d\n", errno));
+      return 127;
+    }
+  return rval;
+}
+EOF
+		;;
+	      *)
+		cat <<EOF
+  execv ("$lt_newargv0", newargz);
+  return rval; /* =127, but avoids unused variable warning */
+}
+EOF
+		;;
+	    esac
+
+	    cat <<"EOF"
+
+void *
+xmalloc (size_t num)
+{
+  void *p = (void *) malloc (num);
+  if (!p)
+    lt_fatal ("Memory exhausted");
+
+  return p;
+}
+
+char *
+xstrdup (const char *string)
+{
+  return string ? strcpy ((char *) xmalloc (strlen (string) + 1),
+			  string) : NULL;
+}
+
+const char *
+base_name (const char *name)
+{
+  const char *base;
+
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  /* Skip over the disk name in MSDOS pathnames. */
+  if (isalpha ((unsigned char) name[0]) && name[1] == ':')
+    name += 2;
+#endif
+
+  for (base = name; *name; name++)
+    if (IS_DIR_SEPARATOR (*name))
+      base = name + 1;
+  return base;
+}
+
+int
+check_executable (const char *path)
+{
+  struct stat st;
+
+  LTWRAPPER_DEBUGPRINTF (("(check_executable)  : %s\n",
+			  path ? (*path ? path : "EMPTY!") : "NULL!"));
+  if ((!path) || (!*path))
+    return 0;
+
+  if ((stat (path, &st) >= 0)
+      && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
+    return 1;
+  else
+    return 0;
+}
+
+int
+make_executable (const char *path)
+{
+  int rval = 0;
+  struct stat st;
+
+  LTWRAPPER_DEBUGPRINTF (("(make_executable)   : %s\n",
+			  path ? (*path ? path : "EMPTY!") : "NULL!"));
+  if ((!path) || (!*path))
+    return 0;
+
+  if (stat (path, &st) >= 0)
+    {
+      rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR);
+    }
+  return rval;
+}
+
+/* Searches for the full path of the wrapper.  Returns
+   newly allocated full path name if found, NULL otherwise
+   Does not chase symlinks, even on platforms that support them.
+*/
+char *
+find_executable (const char *wrapper)
+{
+  int has_slash = 0;
+  const char *p;
+  const char *p_next;
+  /* static buffer for getcwd */
+  char tmp[LT_PATHMAX + 1];
+  int tmp_len;
+  char *concat_name;
+
+  LTWRAPPER_DEBUGPRINTF (("(find_executable)   : %s\n",
+			  wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!"));
+
+  if ((wrapper == NULL) || (*wrapper == '\0'))
+    return NULL;
+
+  /* Absolute path? */
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':')
+    {
+      concat_name = xstrdup (wrapper);
+      if (check_executable (concat_name))
+	return concat_name;
+      XFREE (concat_name);
+    }
+  else
+    {
+#endif
+      if (IS_DIR_SEPARATOR (wrapper[0]))
+	{
+	  concat_name = xstrdup (wrapper);
+	  if (check_executable (concat_name))
+	    return concat_name;
+	  XFREE (concat_name);
+	}
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+    }
+#endif
+
+  for (p = wrapper; *p; p++)
+    if (*p == '/')
+      {
+	has_slash = 1;
+	break;
+      }
+  if (!has_slash)
+    {
+      /* no slashes; search PATH */
+      const char *path = getenv ("PATH");
+      if (path != NULL)
+	{
+	  for (p = path; *p; p = p_next)
+	    {
+	      const char *q;
+	      size_t p_len;
+	      for (q = p; *q; q++)
+		if (IS_PATH_SEPARATOR (*q))
+		  break;
+	      p_len = q - p;
+	      p_next = (*q == '\0' ? q : q + 1);
+	      if (p_len == 0)
+		{
+		  /* empty path: current directory */
+		  if (getcwd (tmp, LT_PATHMAX) == NULL)
+		    lt_fatal ("getcwd failed");
+		  tmp_len = strlen (tmp);
+		  concat_name =
+		    XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
+		  memcpy (concat_name, tmp, tmp_len);
+		  concat_name[tmp_len] = '/';
+		  strcpy (concat_name + tmp_len + 1, wrapper);
+		}
+	      else
+		{
+		  concat_name =
+		    XMALLOC (char, p_len + 1 + strlen (wrapper) + 1);
+		  memcpy (concat_name, p, p_len);
+		  concat_name[p_len] = '/';
+		  strcpy (concat_name + p_len + 1, wrapper);
+		}
+	      if (check_executable (concat_name))
+		return concat_name;
+	      XFREE (concat_name);
+	    }
+	}
+      /* not found in PATH; assume curdir */
+    }
+  /* Relative path | not found in path: prepend cwd */
+  if (getcwd (tmp, LT_PATHMAX) == NULL)
+    lt_fatal ("getcwd failed");
+  tmp_len = strlen (tmp);
+  concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
+  memcpy (concat_name, tmp, tmp_len);
+  concat_name[tmp_len] = '/';
+  strcpy (concat_name + tmp_len + 1, wrapper);
+
+  if (check_executable (concat_name))
+    return concat_name;
+  XFREE (concat_name);
+  return NULL;
+}
+
+char *
+chase_symlinks (const char *pathspec)
+{
+#ifndef S_ISLNK
+  return xstrdup (pathspec);
+#else
+  char buf[LT_PATHMAX];
+  struct stat s;
+  char *tmp_pathspec = xstrdup (pathspec);
+  char *p;
+  int has_symlinks = 0;
+  while (strlen (tmp_pathspec) && !has_symlinks)
+    {
+      LTWRAPPER_DEBUGPRINTF (("checking path component for symlinks: %s\n",
+			      tmp_pathspec));
+      if (lstat (tmp_pathspec, &s) == 0)
+	{
+	  if (S_ISLNK (s.st_mode) != 0)
+	    {
+	      has_symlinks = 1;
+	      break;
+	    }
+
+	  /* search backwards for last DIR_SEPARATOR */
+	  p = tmp_pathspec + strlen (tmp_pathspec) - 1;
+	  while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
+	    p--;
+	  if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
+	    {
+	      /* no more DIR_SEPARATORS left */
+	      break;
+	    }
+	  *p = '\0';
+	}
+      else
+	{
+	  char *errstr = strerror (errno);
+	  lt_fatal ("Error accessing file %s (%s)", tmp_pathspec, errstr);
+	}
+    }
+  XFREE (tmp_pathspec);
+
+  if (!has_symlinks)
+    {
+      return xstrdup (pathspec);
+    }
+
+  tmp_pathspec = realpath (pathspec, buf);
+  if (tmp_pathspec == 0)
+    {
+      lt_fatal ("Could not follow symlinks for %s", pathspec);
+    }
+  return xstrdup (tmp_pathspec);
+#endif
+}
+
+char *
+strendzap (char *str, const char *pat)
+{
+  size_t len, patlen;
+
+  assert (str != NULL);
+  assert (pat != NULL);
+
+  len = strlen (str);
+  patlen = strlen (pat);
+
+  if (patlen <= len)
+    {
+      str += len - patlen;
+      if (strcmp (str, pat) == 0)
+	*str = '\0';
+    }
+  return str;
+}
+
+static void
+lt_error_core (int exit_status, const char *mode,
+	       const char *message, va_list ap)
+{
+  fprintf (stderr, "%s: %s: ", program_name, mode);
+  vfprintf (stderr, message, ap);
+  fprintf (stderr, ".\n");
+
+  if (exit_status >= 0)
+    exit (exit_status);
+}
+
+void
+lt_fatal (const char *message, ...)
+{
+  va_list ap;
+  va_start (ap, message);
+  lt_error_core (EXIT_FAILURE, "FATAL", message, ap);
+  va_end (ap);
+}
+EOF
+}
+# end: func_emit_cwrapperexe_src
+
+# func_mode_link arg...
+func_mode_link ()
+{
+    $opt_debug
+    case $host in
+    *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+      # It is impossible to link a dll without this setting, and
+      # we shouldn't force the makefile maintainer to figure out
+      # which system we are compiling for in order to pass an extra
+      # flag for every libtool invocation.
+      # allow_undefined=no
+
+      # FIXME: Unfortunately, there are problems with the above when trying
+      # to make a dll which has undefined symbols, in which case not
+      # even a static library is built.  For now, we need to specify
+      # -no-undefined on the libtool link line when we can be certain
+      # that all symbols are satisfied, otherwise we get a static library.
+      allow_undefined=yes
+      ;;
+    *)
+      allow_undefined=yes
+      ;;
+    esac
+    libtool_args=$nonopt
+    base_compile="$nonopt $@"
+    compile_command=$nonopt
+    finalize_command=$nonopt
+
+    compile_rpath=
+    finalize_rpath=
+    compile_shlibpath=
+    finalize_shlibpath=
+    convenience=
+    old_convenience=
+    deplibs=
+    old_deplibs=
+    compiler_flags=
+    linker_flags=
+    dllsearchpath=
+    lib_search_path=`pwd`
+    inst_prefix_dir=
+    new_inherited_linker_flags=
+
+    avoid_version=no
+    dlfiles=
+    dlprefiles=
+    dlself=no
+    export_dynamic=no
+    export_symbols=
+    export_symbols_regex=
+    generated=
+    libobjs=
+    ltlibs=
+    module=no
+    no_install=no
+    objs=
+    non_pic_objects=
+    precious_files_regex=
+    prefer_static_libs=no
+    preload=no
+    prev=
+    prevarg=
+    release=
+    rpath=
+    xrpath=
+    perm_rpath=
+    temp_rpath=
+    thread_safe=no
+    vinfo=
+    vinfo_number=no
+    weak_libs=
+    single_module="${wl}-single_module"
+    func_infer_tag $base_compile
+
+    # We need to know -static, to get the right output filenames.
+    for arg
+    do
+      case $arg in
+      -shared)
+	test "$build_libtool_libs" != yes && \
+	  func_fatal_configuration "can not build a shared library"
+	build_old_libs=no
+	break
+	;;
+      -all-static | -static | -static-libtool-libs)
+	case $arg in
+	-all-static)
+	  if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
+	    func_warning "complete static linking is impossible in this configuration"
+	  fi
+	  if test -n "$link_static_flag"; then
+	    dlopen_self=$dlopen_self_static
+	  fi
+	  prefer_static_libs=yes
+	  ;;
+	-static)
+	  if test -z "$pic_flag" && test -n "$link_static_flag"; then
+	    dlopen_self=$dlopen_self_static
+	  fi
+	  prefer_static_libs=built
+	  ;;
+	-static-libtool-libs)
+	  if test -z "$pic_flag" && test -n "$link_static_flag"; then
+	    dlopen_self=$dlopen_self_static
+	  fi
+	  prefer_static_libs=yes
+	  ;;
+	esac
+	build_libtool_libs=no
+	build_old_libs=yes
+	break
+	;;
+      esac
+    done
+
+    # See if our shared archives depend on static archives.
+    test -n "$old_archive_from_new_cmds" && build_old_libs=yes
+
+    # Go through the arguments, transforming them on the way.
+    while test "$#" -gt 0; do
+      arg="$1"
+      shift
+      func_quote_for_eval "$arg"
+      qarg=$func_quote_for_eval_unquoted_result
+      func_append libtool_args " $func_quote_for_eval_result"
+
+      # If the previous option needs an argument, assign it.
+      if test -n "$prev"; then
+	case $prev in
+	output)
+	  func_append compile_command " @OUTPUT@"
+	  func_append finalize_command " @OUTPUT@"
+	  ;;
+	esac
+
+	case $prev in
+	dlfiles|dlprefiles)
+	  if test "$preload" = no; then
+	    # Add the symbol object into the linking commands.
+	    func_append compile_command " @SYMFILE@"
+	    func_append finalize_command " @SYMFILE@"
+	    preload=yes
+	  fi
+	  case $arg in
+	  *.la | *.lo) ;;  # We handle these cases below.
+	  force)
+	    if test "$dlself" = no; then
+	      dlself=needless
+	      export_dynamic=yes
+	    fi
+	    prev=
+	    continue
+	    ;;
+	  self)
+	    if test "$prev" = dlprefiles; then
+	      dlself=yes
+	    elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
+	      dlself=yes
+	    else
+	      dlself=needless
+	      export_dynamic=yes
+	    fi
+	    prev=
+	    continue
+	    ;;
+	  *)
+	    if test "$prev" = dlfiles; then
+	      dlfiles="$dlfiles $arg"
+	    else
+	      dlprefiles="$dlprefiles $arg"
+	    fi
+	    prev=
+	    continue
+	    ;;
+	  esac
+	  ;;
+	expsyms)
+	  export_symbols="$arg"
+	  test -f "$arg" \
+	    || func_fatal_error "symbol file \`$arg' does not exist"
+	  prev=
+	  continue
+	  ;;
+	expsyms_regex)
+	  export_symbols_regex="$arg"
+	  prev=
+	  continue
+	  ;;
+	framework)
+	  case $host in
+	    *-*-darwin*)
+	      case "$deplibs " in
+		*" $qarg.ltframework "*) ;;
+		*) deplibs="$deplibs $qarg.ltframework" # this is fixed later
+		   ;;
+	      esac
+	      ;;
+	  esac
+	  prev=
+	  continue
+	  ;;
+	inst_prefix)
+	  inst_prefix_dir="$arg"
+	  prev=
+	  continue
+	  ;;
+	objectlist)
+	  if test -f "$arg"; then
+	    save_arg=$arg
+	    moreargs=
+	    for fil in `cat "$save_arg"`
+	    do
+#	      moreargs="$moreargs $fil"
+	      arg=$fil
+	      # A libtool-controlled object.
+
+	      # Check to see that this really is a libtool object.
+	      if func_lalib_unsafe_p "$arg"; then
+		pic_object=
+		non_pic_object=
+
+		# Read the .lo file
+		func_source "$arg"
+
+		if test -z "$pic_object" ||
+		   test -z "$non_pic_object" ||
+		   test "$pic_object" = none &&
+		   test "$non_pic_object" = none; then
+		  func_fatal_error "cannot find name of object for \`$arg'"
+		fi
+
+		# Extract subdirectory from the argument.
+		func_dirname "$arg" "/" ""
+		xdir="$func_dirname_result"
+
+		if test "$pic_object" != none; then
+		  # Prepend the subdirectory the object is found in.
+		  pic_object="$xdir$pic_object"
+
+		  if test "$prev" = dlfiles; then
+		    if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+		      dlfiles="$dlfiles $pic_object"
+		      prev=
+		      continue
+		    else
+		      # If libtool objects are unsupported, then we need to preload.
+		      prev=dlprefiles
+		    fi
+		  fi
+
+		  # CHECK ME:  I think I busted this.  -Ossama
+		  if test "$prev" = dlprefiles; then
+		    # Preload the old-style object.
+		    dlprefiles="$dlprefiles $pic_object"
+		    prev=
+		  fi
+
+		  # A PIC object.
+		  func_append libobjs " $pic_object"
+		  arg="$pic_object"
+		fi
+
+		# Non-PIC object.
+		if test "$non_pic_object" != none; then
+		  # Prepend the subdirectory the object is found in.
+		  non_pic_object="$xdir$non_pic_object"
+
+		  # A standard non-PIC object
+		  func_append non_pic_objects " $non_pic_object"
+		  if test -z "$pic_object" || test "$pic_object" = none ; then
+		    arg="$non_pic_object"
+		  fi
+		else
+		  # If the PIC object exists, use it instead.
+		  # $xdir was prepended to $pic_object above.
+		  non_pic_object="$pic_object"
+		  func_append non_pic_objects " $non_pic_object"
+		fi
+	      else
+		# Only an error if not doing a dry-run.
+		if $opt_dry_run; then
+		  # Extract subdirectory from the argument.
+		  func_dirname "$arg" "/" ""
+		  xdir="$func_dirname_result"
+
+		  func_lo2o "$arg"
+		  pic_object=$xdir$objdir/$func_lo2o_result
+		  non_pic_object=$xdir$func_lo2o_result
+		  func_append libobjs " $pic_object"
+		  func_append non_pic_objects " $non_pic_object"
+	        else
+		  func_fatal_error "\`$arg' is not a valid libtool object"
+		fi
+	      fi
+	    done
+	  else
+	    func_fatal_error "link input file \`$arg' does not exist"
+	  fi
+	  arg=$save_arg
+	  prev=
+	  continue
+	  ;;
+	precious_regex)
+	  precious_files_regex="$arg"
+	  prev=
+	  continue
+	  ;;
+	release)
+	  release="-$arg"
+	  prev=
+	  continue
+	  ;;
+	rpath | xrpath)
+	  # We need an absolute path.
+	  case $arg in
+	  [\\/]* | [A-Za-z]:[\\/]*) ;;
+	  *)
+	    func_fatal_error "only absolute run-paths are allowed"
+	    ;;
+	  esac
+	  if test "$prev" = rpath; then
+	    case "$rpath " in
+	    *" $arg "*) ;;
+	    *) rpath="$rpath $arg" ;;
+	    esac
+	  else
+	    case "$xrpath " in
+	    *" $arg "*) ;;
+	    *) xrpath="$xrpath $arg" ;;
+	    esac
+	  fi
+	  prev=
+	  continue
+	  ;;
+	shrext)
+	  shrext_cmds="$arg"
+	  prev=
+	  continue
+	  ;;
+	weak)
+	  weak_libs="$weak_libs $arg"
+	  prev=
+	  continue
+	  ;;
+	xcclinker)
+	  linker_flags="$linker_flags $qarg"
+	  compiler_flags="$compiler_flags $qarg"
+	  prev=
+	  func_append compile_command " $qarg"
+	  func_append finalize_command " $qarg"
+	  continue
+	  ;;
+	xcompiler)
+	  compiler_flags="$compiler_flags $qarg"
+	  prev=
+	  func_append compile_command " $qarg"
+	  func_append finalize_command " $qarg"
+	  continue
+	  ;;
+	xlinker)
+	  linker_flags="$linker_flags $qarg"
+	  compiler_flags="$compiler_flags $wl$qarg"
+	  prev=
+	  func_append compile_command " $wl$qarg"
+	  func_append finalize_command " $wl$qarg"
+	  continue
+	  ;;
+	*)
+	  eval "$prev=\"\$arg\""
+	  prev=
+	  continue
+	  ;;
+	esac
+      fi # test -n "$prev"
+
+      prevarg="$arg"
+
+      case $arg in
+      -all-static)
+	if test -n "$link_static_flag"; then
+	  # See comment for -static flag below, for more details.
+	  func_append compile_command " $link_static_flag"
+	  func_append finalize_command " $link_static_flag"
+	fi
+	continue
+	;;
+
+      -allow-undefined)
+	# FIXME: remove this flag sometime in the future.
+	func_fatal_error "\`-allow-undefined' must not be used because it is the default"
+	;;
+
+      -avoid-version)
+	avoid_version=yes
+	continue
+	;;
+
+      -dlopen)
+	prev=dlfiles
+	continue
+	;;
+
+      -dlpreopen)
+	prev=dlprefiles
+	continue
+	;;
+
+      -export-dynamic)
+	export_dynamic=yes
+	continue
+	;;
+
+      -export-symbols | -export-symbols-regex)
+	if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+	  func_fatal_error "more than one -exported-symbols argument is not allowed"
+	fi
+	if test "X$arg" = "X-export-symbols"; then
+	  prev=expsyms
+	else
+	  prev=expsyms_regex
+	fi
+	continue
+	;;
+
+      -framework)
+	prev=framework
+	continue
+	;;
+
+      -inst-prefix-dir)
+	prev=inst_prefix
+	continue
+	;;
+
+      # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
+      # so, if we see these flags be careful not to treat them like -L
+      -L[A-Z][A-Z]*:*)
+	case $with_gcc/$host in
+	no/*-*-irix* | /*-*-irix*)
+	  func_append compile_command " $arg"
+	  func_append finalize_command " $arg"
+	  ;;
+	esac
+	continue
+	;;
+
+      -L*)
+	func_stripname '-L' '' "$arg"
+	dir=$func_stripname_result
+	# We need an absolute path.
+	case $dir in
+	[\\/]* | [A-Za-z]:[\\/]*) ;;
+	*)
+	  absdir=`cd "$dir" && pwd`
+	  test -z "$absdir" && \
+	    func_fatal_error "cannot determine absolute directory name of \`$dir'"
+	  dir="$absdir"
+	  ;;
+	esac
+	case "$deplibs " in
+	*" -L$dir "*) ;;
+	*)
+	  deplibs="$deplibs -L$dir"
+	  lib_search_path="$lib_search_path $dir"
+	  ;;
+	esac
+	case $host in
+	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+	  testbindir=`$ECHO "X$dir" | $Xsed -e 's*/lib$*/bin*'`
+	  case :$dllsearchpath: in
+	  *":$dir:"*) ;;
+	  *) dllsearchpath="$dllsearchpath:$dir";;
+	  esac
+	  case :$dllsearchpath: in
+	  *":$testbindir:"*) ;;
+	  *) dllsearchpath="$dllsearchpath:$testbindir";;
+	  esac
+	  ;;
+	esac
+	continue
+	;;
+
+      -l*)
+	if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
+	  case $host in
+	  *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos*)
+	    # These systems don't actually have a C or math library (as such)
+	    continue
+	    ;;
+	  *-*-os2*)
+	    # These systems don't actually have a C library (as such)
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+	  *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*)
+	    # Do not include libc due to us having libc/libc_r.
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+	  *-*-rhapsody* | *-*-darwin1.[012])
+	    # Rhapsody C and math libraries are in the System framework
+	    deplibs="$deplibs System.ltframework"
+	    continue
+	    ;;
+	  *-*-sco3.2v5* | *-*-sco5v6*)
+	    # Causes problems with __ctype
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+	  *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+	    # Compiler inserts libc in the correct place for threads to work
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+	  esac
+	elif test "X$arg" = "X-lc_r"; then
+	 case $host in
+	 *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+	   # Do not include libc_r directly, use -pthread flag.
+	   continue
+	   ;;
+	 esac
+	fi
+	deplibs="$deplibs $arg"
+	continue
+	;;
+
+      -module)
+	module=yes
+	continue
+	;;
+
+      # Tru64 UNIX uses -model [arg] to determine the layout of C++
+      # classes, name mangling, and exception handling.
+      # Darwin uses the -arch flag to determine output architecture.
+      -model|-arch|-isysroot)
+	compiler_flags="$compiler_flags $arg"
+	func_append compile_command " $arg"
+	func_append finalize_command " $arg"
+	prev=xcompiler
+	continue
+	;;
+
+      -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads)
+	compiler_flags="$compiler_flags $arg"
+	func_append compile_command " $arg"
+	func_append finalize_command " $arg"
+	case "$new_inherited_linker_flags " in
+	    *" $arg "*) ;;
+	    * ) new_inherited_linker_flags="$new_inherited_linker_flags $arg" ;;
+	esac
+	continue
+	;;
+
+      -multi_module)
+	single_module="${wl}-multi_module"
+	continue
+	;;
+
+      -no-fast-install)
+	fast_install=no
+	continue
+	;;
+
+      -no-install)
+	case $host in
+	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin*)
+	  # The PATH hackery in wrapper scripts is required on Windows
+	  # and Darwin in order for the loader to find any dlls it needs.
+	  func_warning "\`-no-install' is ignored for $host"
+	  func_warning "assuming \`-no-fast-install' instead"
+	  fast_install=no
+	  ;;
+	*) no_install=yes ;;
+	esac
+	continue
+	;;
+
+      -no-undefined)
+	allow_undefined=no
+	continue
+	;;
+
+      -objectlist)
+	prev=objectlist
+	continue
+	;;
+
+      -o) prev=output ;;
+
+      -precious-files-regex)
+	prev=precious_regex
+	continue
+	;;
+
+      -release)
+	prev=release
+	continue
+	;;
+
+      -rpath)
+	prev=rpath
+	continue
+	;;
+
+      -R)
+	prev=xrpath
+	continue
+	;;
+
+      -R*)
+	func_stripname '-R' '' "$arg"
+	dir=$func_stripname_result
+	# We need an absolute path.
+	case $dir in
+	[\\/]* | [A-Za-z]:[\\/]*) ;;
+	*)
+	  func_fatal_error "only absolute run-paths are allowed"
+	  ;;
+	esac
+	case "$xrpath " in
+	*" $dir "*) ;;
+	*) xrpath="$xrpath $dir" ;;
+	esac
+	continue
+	;;
+
+      -shared)
+	# The effects of -shared are defined in a previous loop.
+	continue
+	;;
+
+      -shrext)
+	prev=shrext
+	continue
+	;;
+
+      -static | -static-libtool-libs)
+	# The effects of -static are defined in a previous loop.
+	# We used to do the same as -all-static on platforms that
+	# didn't have a PIC flag, but the assumption that the effects
+	# would be equivalent was wrong.  It would break on at least
+	# Digital Unix and AIX.
+	continue
+	;;
+
+      -thread-safe)
+	thread_safe=yes
+	continue
+	;;
+
+      -version-info)
+	prev=vinfo
+	continue
+	;;
+
+      -version-number)
+	prev=vinfo
+	vinfo_number=yes
+	continue
+	;;
+
+      -weak)
+        prev=weak
+	continue
+	;;
+
+      -Wc,*)
+	func_stripname '-Wc,' '' "$arg"
+	args=$func_stripname_result
+	arg=
+	save_ifs="$IFS"; IFS=','
+	for flag in $args; do
+	  IFS="$save_ifs"
+          func_quote_for_eval "$flag"
+	  arg="$arg $wl$func_quote_for_eval_result"
+	  compiler_flags="$compiler_flags $func_quote_for_eval_result"
+	done
+	IFS="$save_ifs"
+	func_stripname ' ' '' "$arg"
+	arg=$func_stripname_result
+	;;
+
+      -Wl,*)
+	func_stripname '-Wl,' '' "$arg"
+	args=$func_stripname_result
+	arg=
+	save_ifs="$IFS"; IFS=','
+	for flag in $args; do
+	  IFS="$save_ifs"
+          func_quote_for_eval "$flag"
+	  arg="$arg $wl$func_quote_for_eval_result"
+	  compiler_flags="$compiler_flags $wl$func_quote_for_eval_result"
+	  linker_flags="$linker_flags $func_quote_for_eval_result"
+	done
+	IFS="$save_ifs"
+	func_stripname ' ' '' "$arg"
+	arg=$func_stripname_result
+	;;
+
+      -Xcompiler)
+	prev=xcompiler
+	continue
+	;;
+
+      -Xlinker)
+	prev=xlinker
+	continue
+	;;
+
+      -XCClinker)
+	prev=xcclinker
+	continue
+	;;
+
+      # -msg_* for osf cc
+      -msg_*)
+	func_quote_for_eval "$arg"
+	arg="$func_quote_for_eval_result"
+	;;
+
+      # -64, -mips[0-9] enable 64-bit mode on the SGI compiler
+      # -r[0-9][0-9]* specifies the processor on the SGI compiler
+      # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler
+      # +DA*, +DD* enable 64-bit mode on the HP compiler
+      # -q* pass through compiler args for the IBM compiler
+      # -m*, -t[45]*, -txscale* pass through architecture-specific
+      # compiler args for GCC
+      # -F/path gives path to uninstalled frameworks, gcc on darwin
+      # -p, -pg, --coverage, -fprofile-* pass through profiling flag for GCC
+      # @file GCC response files
+      -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \
+      -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*)
+        func_quote_for_eval "$arg"
+	arg="$func_quote_for_eval_result"
+        func_append compile_command " $arg"
+        func_append finalize_command " $arg"
+        compiler_flags="$compiler_flags $arg"
+        continue
+        ;;
+
+      # Some other compiler flag.
+      -* | +*)
+        func_quote_for_eval "$arg"
+	arg="$func_quote_for_eval_result"
+	;;
+
+      *.$objext)
+	# A standard object.
+	objs="$objs $arg"
+	;;
+
+      *.lo)
+	# A libtool-controlled object.
+
+	# Check to see that this really is a libtool object.
+	if func_lalib_unsafe_p "$arg"; then
+	  pic_object=
+	  non_pic_object=
+
+	  # Read the .lo file
+	  func_source "$arg"
+
+	  if test -z "$pic_object" ||
+	     test -z "$non_pic_object" ||
+	     test "$pic_object" = none &&
+	     test "$non_pic_object" = none; then
+	    func_fatal_error "cannot find name of object for \`$arg'"
+	  fi
+
+	  # Extract subdirectory from the argument.
+	  func_dirname "$arg" "/" ""
+	  xdir="$func_dirname_result"
+
+	  if test "$pic_object" != none; then
+	    # Prepend the subdirectory the object is found in.
+	    pic_object="$xdir$pic_object"
+
+	    if test "$prev" = dlfiles; then
+	      if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+		dlfiles="$dlfiles $pic_object"
+		prev=
+		continue
+	      else
+		# If libtool objects are unsupported, then we need to preload.
+		prev=dlprefiles
+	      fi
+	    fi
+
+	    # CHECK ME:  I think I busted this.  -Ossama
+	    if test "$prev" = dlprefiles; then
+	      # Preload the old-style object.
+	      dlprefiles="$dlprefiles $pic_object"
+	      prev=
+	    fi
+
+	    # A PIC object.
+	    func_append libobjs " $pic_object"
+	    arg="$pic_object"
+	  fi
+
+	  # Non-PIC object.
+	  if test "$non_pic_object" != none; then
+	    # Prepend the subdirectory the object is found in.
+	    non_pic_object="$xdir$non_pic_object"
+
+	    # A standard non-PIC object
+	    func_append non_pic_objects " $non_pic_object"
+	    if test -z "$pic_object" || test "$pic_object" = none ; then
+	      arg="$non_pic_object"
+	    fi
+	  else
+	    # If the PIC object exists, use it instead.
+	    # $xdir was prepended to $pic_object above.
+	    non_pic_object="$pic_object"
+	    func_append non_pic_objects " $non_pic_object"
+	  fi
+	else
+	  # Only an error if not doing a dry-run.
+	  if $opt_dry_run; then
+	    # Extract subdirectory from the argument.
+	    func_dirname "$arg" "/" ""
+	    xdir="$func_dirname_result"
+
+	    func_lo2o "$arg"
+	    pic_object=$xdir$objdir/$func_lo2o_result
+	    non_pic_object=$xdir$func_lo2o_result
+	    func_append libobjs " $pic_object"
+	    func_append non_pic_objects " $non_pic_object"
+	  else
+	    func_fatal_error "\`$arg' is not a valid libtool object"
+	  fi
+	fi
+	;;
+
+      *.$libext)
+	# An archive.
+	deplibs="$deplibs $arg"
+	old_deplibs="$old_deplibs $arg"
+	continue
+	;;
+
+      *.la)
+	# A libtool-controlled library.
+
+	if test "$prev" = dlfiles; then
+	  # This library was specified with -dlopen.
+	  dlfiles="$dlfiles $arg"
+	  prev=
+	elif test "$prev" = dlprefiles; then
+	  # The library was specified with -dlpreopen.
+	  dlprefiles="$dlprefiles $arg"
+	  prev=
+	else
+	  deplibs="$deplibs $arg"
+	fi
+	continue
+	;;
+
+      # Some other compiler argument.
+      *)
+	# Unknown arguments in both finalize_command and compile_command need
+	# to be aesthetically quoted because they are evaled later.
+	func_quote_for_eval "$arg"
+	arg="$func_quote_for_eval_result"
+	;;
+      esac # arg
+
+      # Now actually substitute the argument into the commands.
+      if test -n "$arg"; then
+	func_append compile_command " $arg"
+	func_append finalize_command " $arg"
+      fi
+    done # argument parsing loop
+
+    test -n "$prev" && \
+      func_fatal_help "the \`$prevarg' option requires an argument"
+
+    if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
+      eval arg=\"$export_dynamic_flag_spec\"
+      func_append compile_command " $arg"
+      func_append finalize_command " $arg"
+    fi
+
+    oldlibs=
+    # calculate the name of the file, without its directory
+    func_basename "$output"
+    outputname="$func_basename_result"
+    libobjs_save="$libobjs"
+
+    if test -n "$shlibpath_var"; then
+      # get the directories listed in $shlibpath_var
+      eval shlib_search_path=\`\$ECHO \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\`
+    else
+      shlib_search_path=
+    fi
+    eval sys_lib_search_path=\"$sys_lib_search_path_spec\"
+    eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
+
+    func_dirname "$output" "/" ""
+    output_objdir="$func_dirname_result$objdir"
+    # Create the object directory.
+    func_mkdir_p "$output_objdir"
+
+    # Determine the type of output
+    case $output in
+    "")
+      func_fatal_help "you must specify an output file"
+      ;;
+    *.$libext) linkmode=oldlib ;;
+    *.lo | *.$objext) linkmode=obj ;;
+    *.la) linkmode=lib ;;
+    *) linkmode=prog ;; # Anything else should be a program.
+    esac
+
+    specialdeplibs=
+
+    libs=
+    # Find all interdependent deplibs by searching for libraries
+    # that are linked more than once (e.g. -la -lb -la)
+    for deplib in $deplibs; do
+      if $opt_duplicate_deps ; then
+	case "$libs " in
+	*" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+	esac
+      fi
+      libs="$libs $deplib"
+    done
+
+    if test "$linkmode" = lib; then
+      libs="$predeps $libs $compiler_lib_search_path $postdeps"
+
+      # Compute libraries that are listed more than once in $predeps
+      # $postdeps and mark them as special (i.e., whose duplicates are
+      # not to be eliminated).
+      pre_post_deps=
+      if $opt_duplicate_compiler_generated_deps; then
+	for pre_post_dep in $predeps $postdeps; do
+	  case "$pre_post_deps " in
+	  *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;;
+	  esac
+	  pre_post_deps="$pre_post_deps $pre_post_dep"
+	done
+      fi
+      pre_post_deps=
+    fi
+
+    deplibs=
+    newdependency_libs=
+    newlib_search_path=
+    need_relink=no # whether we're linking any uninstalled libtool libraries
+    notinst_deplibs= # not-installed libtool libraries
+    notinst_path= # paths that contain not-installed libtool libraries
+
+    case $linkmode in
+    lib)
+	passes="conv dlpreopen link"
+	for file in $dlfiles $dlprefiles; do
+	  case $file in
+	  *.la) ;;
+	  *)
+	    func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file"
+	    ;;
+	  esac
+	done
+	;;
+    prog)
+	compile_deplibs=
+	finalize_deplibs=
+	alldeplibs=no
+	newdlfiles=
+	newdlprefiles=
+	passes="conv scan dlopen dlpreopen link"
+	;;
+    *)  passes="conv"
+	;;
+    esac
+
+    for pass in $passes; do
+      # The preopen pass in lib mode reverses $deplibs; put it back here
+      # so that -L comes before libs that need it for instance...
+      if test "$linkmode,$pass" = "lib,link"; then
+	## FIXME: Find the place where the list is rebuilt in the wrong
+	##        order, and fix it there properly
+        tmp_deplibs=
+	for deplib in $deplibs; do
+	  tmp_deplibs="$deplib $tmp_deplibs"
+	done
+	deplibs="$tmp_deplibs"
+      fi
+
+      if test "$linkmode,$pass" = "lib,link" ||
+	 test "$linkmode,$pass" = "prog,scan"; then
+	libs="$deplibs"
+	deplibs=
+      fi
+      if test "$linkmode" = prog; then
+	case $pass in
+	dlopen) libs="$dlfiles" ;;
+	dlpreopen) libs="$dlprefiles" ;;
+	link) libs="$deplibs %DEPLIBS% $dependency_libs" ;;
+	esac
+      fi
+      if test "$linkmode,$pass" = "lib,dlpreopen"; then
+	# Collect and forward deplibs of preopened libtool libs
+	for lib in $dlprefiles; do
+	  # Ignore non-libtool-libs
+	  dependency_libs=
+	  case $lib in
+	  *.la)	func_source "$lib" ;;
+	  esac
+
+	  # Collect preopened libtool deplibs, except any this library
+	  # has declared as weak libs
+	  for deplib in $dependency_libs; do
+            deplib_base=`$ECHO "X$deplib" | $Xsed -e "$basename"`
+	    case " $weak_libs " in
+	    *" $deplib_base "*) ;;
+	    *) deplibs="$deplibs $deplib" ;;
+	    esac
+	  done
+	done
+	libs="$dlprefiles"
+      fi
+      if test "$pass" = dlopen; then
+	# Collect dlpreopened libraries
+	save_deplibs="$deplibs"
+	deplibs=
+      fi
+
+      for deplib in $libs; do
+	lib=
+	found=no
+	case $deplib in
+	-mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads)
+	  if test "$linkmode,$pass" = "prog,link"; then
+	    compile_deplibs="$deplib $compile_deplibs"
+	    finalize_deplibs="$deplib $finalize_deplibs"
+	  else
+	    compiler_flags="$compiler_flags $deplib"
+	    if test "$linkmode" = lib ; then
+		case "$new_inherited_linker_flags " in
+		    *" $deplib "*) ;;
+		    * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;;
+		esac
+	    fi
+	  fi
+	  continue
+	  ;;
+	-l*)
+	  if test "$linkmode" != lib && test "$linkmode" != prog; then
+	    func_warning "\`-l' is ignored for archives/objects"
+	    continue
+	  fi
+	  func_stripname '-l' '' "$deplib"
+	  name=$func_stripname_result
+	  if test "$linkmode" = lib; then
+	    searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path"
+	  else
+	    searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path"
+	  fi
+	  for searchdir in $searchdirs; do
+	    for search_ext in .la $std_shrext .so .a; do
+	      # Search the libtool library
+	      lib="$searchdir/lib${name}${search_ext}"
+	      if test -f "$lib"; then
+		if test "$search_ext" = ".la"; then
+		  found=yes
+		else
+		  found=no
+		fi
+		break 2
+	      fi
+	    done
+	  done
+	  if test "$found" != yes; then
+	    # deplib doesn't seem to be a libtool library
+	    if test "$linkmode,$pass" = "prog,link"; then
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    else
+	      deplibs="$deplib $deplibs"
+	      test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+	    fi
+	    continue
+	  else # deplib is a libtool library
+	    # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
+	    # We need to do some special things here, and not later.
+	    if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+	      case " $predeps $postdeps " in
+	      *" $deplib "*)
+		if func_lalib_p "$lib"; then
+		  library_names=
+		  old_library=
+		  func_source "$lib"
+		  for l in $old_library $library_names; do
+		    ll="$l"
+		  done
+		  if test "X$ll" = "X$old_library" ; then # only static version available
+		    found=no
+		    func_dirname "$lib" "" "."
+		    ladir="$func_dirname_result"
+		    lib=$ladir/$old_library
+		    if test "$linkmode,$pass" = "prog,link"; then
+		      compile_deplibs="$deplib $compile_deplibs"
+		      finalize_deplibs="$deplib $finalize_deplibs"
+		    else
+		      deplibs="$deplib $deplibs"
+		      test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+		    fi
+		    continue
+		  fi
+		fi
+		;;
+	      *) ;;
+	      esac
+	    fi
+	  fi
+	  ;; # -l
+	*.ltframework)
+	  if test "$linkmode,$pass" = "prog,link"; then
+	    compile_deplibs="$deplib $compile_deplibs"
+	    finalize_deplibs="$deplib $finalize_deplibs"
+	  else
+	    deplibs="$deplib $deplibs"
+	    if test "$linkmode" = lib ; then
+		case "$new_inherited_linker_flags " in
+		    *" $deplib "*) ;;
+		    * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;;
+		esac
+	    fi
+	  fi
+	  continue
+	  ;;
+	-L*)
+	  case $linkmode in
+	  lib)
+	    deplibs="$deplib $deplibs"
+	    test "$pass" = conv && continue
+	    newdependency_libs="$deplib $newdependency_libs"
+	    func_stripname '-L' '' "$deplib"
+	    newlib_search_path="$newlib_search_path $func_stripname_result"
+	    ;;
+	  prog)
+	    if test "$pass" = conv; then
+	      deplibs="$deplib $deplibs"
+	      continue
+	    fi
+	    if test "$pass" = scan; then
+	      deplibs="$deplib $deplibs"
+	    else
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    fi
+	    func_stripname '-L' '' "$deplib"
+	    newlib_search_path="$newlib_search_path $func_stripname_result"
+	    ;;
+	  *)
+	    func_warning "\`-L' is ignored for archives/objects"
+	    ;;
+	  esac # linkmode
+	  continue
+	  ;; # -L
+	-R*)
+	  if test "$pass" = link; then
+	    func_stripname '-R' '' "$deplib"
+	    dir=$func_stripname_result
+	    # Make sure the xrpath contains only unique directories.
+	    case "$xrpath " in
+	    *" $dir "*) ;;
+	    *) xrpath="$xrpath $dir" ;;
+	    esac
+	  fi
+	  deplibs="$deplib $deplibs"
+	  continue
+	  ;;
+	*.la) lib="$deplib" ;;
+	*.$libext)
+	  if test "$pass" = conv; then
+	    deplibs="$deplib $deplibs"
+	    continue
+	  fi
+	  case $linkmode in
+	  lib)
+	    # Linking convenience modules into shared libraries is allowed,
+	    # but linking other static libraries is non-portable.
+	    case " $dlpreconveniencelibs " in
+	    *" $deplib "*) ;;
+	    *)
+	      valid_a_lib=no
+	      case $deplibs_check_method in
+		match_pattern*)
+		  set dummy $deplibs_check_method; shift
+		  match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+		  if eval "\$ECHO \"X$deplib\"" 2>/dev/null | $Xsed -e 10q \
+		    | $EGREP "$match_pattern_regex" > /dev/null; then
+		    valid_a_lib=yes
+		  fi
+		;;
+		pass_all)
+		  valid_a_lib=yes
+		;;
+	      esac
+	      if test "$valid_a_lib" != yes; then
+		$ECHO
+		$ECHO "*** Warning: Trying to link with static lib archive $deplib."
+		$ECHO "*** I have the capability to make that library automatically link in when"
+		$ECHO "*** you link to this library.  But I can only do this if you have a"
+		$ECHO "*** shared version of the library, which you do not appear to have"
+		$ECHO "*** because the file extensions .$libext of this argument makes me believe"
+		$ECHO "*** that it is just a static archive that I should not use here."
+	      else
+		$ECHO
+		$ECHO "*** Warning: Linking the shared library $output against the"
+		$ECHO "*** static library $deplib is not portable!"
+		deplibs="$deplib $deplibs"
+	      fi
+	      ;;
+	    esac
+	    continue
+	    ;;
+	  prog)
+	    if test "$pass" != link; then
+	      deplibs="$deplib $deplibs"
+	    else
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    fi
+	    continue
+	    ;;
+	  esac # linkmode
+	  ;; # *.$libext
+	*.lo | *.$objext)
+	  if test "$pass" = conv; then
+	    deplibs="$deplib $deplibs"
+	  elif test "$linkmode" = prog; then
+	    if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
+	      # If there is no dlopen support or we're linking statically,
+	      # we need to preload.
+	      newdlprefiles="$newdlprefiles $deplib"
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    else
+	      newdlfiles="$newdlfiles $deplib"
+	    fi
+	  fi
+	  continue
+	  ;;
+	%DEPLIBS%)
+	  alldeplibs=yes
+	  continue
+	  ;;
+	esac # case $deplib
+
+	if test "$found" = yes || test -f "$lib"; then :
+	else
+	  func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'"
+	fi
+
+	# Check to see that this really is a libtool archive.
+	func_lalib_unsafe_p "$lib" \
+	  || func_fatal_error "\`$lib' is not a valid libtool archive"
+
+	func_dirname "$lib" "" "."
+	ladir="$func_dirname_result"
+
+	dlname=
+	dlopen=
+	dlpreopen=
+	libdir=
+	library_names=
+	old_library=
+	inherited_linker_flags=
+	# If the library was installed with an old release of libtool,
+	# it will not redefine variables installed, or shouldnotlink
+	installed=yes
+	shouldnotlink=no
+	avoidtemprpath=
+
+
+	# Read the .la file
+	func_source "$lib"
+
+	# Convert "-framework foo" to "foo.ltframework"
+	if test -n "$inherited_linker_flags"; then
+	  tmp_inherited_linker_flags=`$ECHO "X$inherited_linker_flags" | $Xsed -e 's/-framework \([^ $]*\)/\1.ltframework/g'`
+	  for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do
+	    case " $new_inherited_linker_flags " in
+	      *" $tmp_inherited_linker_flag "*) ;;
+	      *) new_inherited_linker_flags="$new_inherited_linker_flags $tmp_inherited_linker_flag";;
+	    esac
+	  done
+	fi
+	dependency_libs=`$ECHO "X $dependency_libs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+	if test "$linkmode,$pass" = "lib,link" ||
+	   test "$linkmode,$pass" = "prog,scan" ||
+	   { test "$linkmode" != prog && test "$linkmode" != lib; }; then
+	  test -n "$dlopen" && dlfiles="$dlfiles $dlopen"
+	  test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen"
+	fi
+
+	if test "$pass" = conv; then
+	  # Only check for convenience libraries
+	  deplibs="$lib $deplibs"
+	  if test -z "$libdir"; then
+	    if test -z "$old_library"; then
+	      func_fatal_error "cannot find name of link library for \`$lib'"
+	    fi
+	    # It is a libtool convenience library, so add in its objects.
+	    convenience="$convenience $ladir/$objdir/$old_library"
+	    old_convenience="$old_convenience $ladir/$objdir/$old_library"
+	  elif test "$linkmode" != prog && test "$linkmode" != lib; then
+	    func_fatal_error "\`$lib' is not a convenience library"
+	  fi
+	  tmp_libs=
+	  for deplib in $dependency_libs; do
+	    deplibs="$deplib $deplibs"
+	    if $opt_duplicate_deps ; then
+	      case "$tmp_libs " in
+	      *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+	      esac
+	    fi
+	    tmp_libs="$tmp_libs $deplib"
+	  done
+	  continue
+	fi # $pass = conv
+
+
+	# Get the name of the library we link against.
+	linklib=
+	for l in $old_library $library_names; do
+	  linklib="$l"
+	done
+	if test -z "$linklib"; then
+	  func_fatal_error "cannot find name of link library for \`$lib'"
+	fi
+
+	# This library was specified with -dlopen.
+	if test "$pass" = dlopen; then
+	  if test -z "$libdir"; then
+	    func_fatal_error "cannot -dlopen a convenience library: \`$lib'"
+	  fi
+	  if test -z "$dlname" ||
+	     test "$dlopen_support" != yes ||
+	     test "$build_libtool_libs" = no; then
+	    # If there is no dlname, no dlopen support or we're linking
+	    # statically, we need to preload.  We also need to preload any
+	    # dependent libraries so libltdl's deplib preloader doesn't
+	    # bomb out in the load deplibs phase.
+	    dlprefiles="$dlprefiles $lib $dependency_libs"
+	  else
+	    newdlfiles="$newdlfiles $lib"
+	  fi
+	  continue
+	fi # $pass = dlopen
+
+	# We need an absolute path.
+	case $ladir in
+	[\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;;
+	*)
+	  abs_ladir=`cd "$ladir" && pwd`
+	  if test -z "$abs_ladir"; then
+	    func_warning "cannot determine absolute directory name of \`$ladir'"
+	    func_warning "passing it literally to the linker, although it might fail"
+	    abs_ladir="$ladir"
+	  fi
+	  ;;
+	esac
+	func_basename "$lib"
+	laname="$func_basename_result"
+
+	# Find the relevant object directory and library name.
+	if test "X$installed" = Xyes; then
+	  if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+	    func_warning "library \`$lib' was moved."
+	    dir="$ladir"
+	    absdir="$abs_ladir"
+	    libdir="$abs_ladir"
+	  else
+	    dir="$libdir"
+	    absdir="$libdir"
+	  fi
+	  test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes
+	else
+	  if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+	    dir="$ladir"
+	    absdir="$abs_ladir"
+	    # Remove this search path later
+	    notinst_path="$notinst_path $abs_ladir"
+	  else
+	    dir="$ladir/$objdir"
+	    absdir="$abs_ladir/$objdir"
+	    # Remove this search path later
+	    notinst_path="$notinst_path $abs_ladir"
+	  fi
+	fi # $installed = yes
+	func_stripname 'lib' '.la' "$laname"
+	name=$func_stripname_result
+
+	# This library was specified with -dlpreopen.
+	if test "$pass" = dlpreopen; then
+	  if test -z "$libdir" && test "$linkmode" = prog; then
+	    func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'"
+	  fi
+	  # Prefer using a static library (so that no silly _DYNAMIC symbols
+	  # are required to link).
+	  if test -n "$old_library"; then
+	    newdlprefiles="$newdlprefiles $dir/$old_library"
+	    # Keep a list of preopened convenience libraries to check
+	    # that they are being used correctly in the link pass.
+	    test -z "$libdir" && \
+		dlpreconveniencelibs="$dlpreconveniencelibs $dir/$old_library"
+	  # Otherwise, use the dlname, so that lt_dlopen finds it.
+	  elif test -n "$dlname"; then
+	    newdlprefiles="$newdlprefiles $dir/$dlname"
+	  else
+	    newdlprefiles="$newdlprefiles $dir/$linklib"
+	  fi
+	fi # $pass = dlpreopen
+
+	if test -z "$libdir"; then
+	  # Link the convenience library
+	  if test "$linkmode" = lib; then
+	    deplibs="$dir/$old_library $deplibs"
+	  elif test "$linkmode,$pass" = "prog,link"; then
+	    compile_deplibs="$dir/$old_library $compile_deplibs"
+	    finalize_deplibs="$dir/$old_library $finalize_deplibs"
+	  else
+	    deplibs="$lib $deplibs" # used for prog,scan pass
+	  fi
+	  continue
+	fi
+
+
+	if test "$linkmode" = prog && test "$pass" != link; then
+	  newlib_search_path="$newlib_search_path $ladir"
+	  deplibs="$lib $deplibs"
+
+	  linkalldeplibs=no
+	  if test "$link_all_deplibs" != no || test -z "$library_names" ||
+	     test "$build_libtool_libs" = no; then
+	    linkalldeplibs=yes
+	  fi
+
+	  tmp_libs=
+	  for deplib in $dependency_libs; do
+	    case $deplib in
+	    -L*) func_stripname '-L' '' "$deplib"
+	         newlib_search_path="$newlib_search_path $func_stripname_result"
+		 ;;
+	    esac
+	    # Need to link against all dependency_libs?
+	    if test "$linkalldeplibs" = yes; then
+	      deplibs="$deplib $deplibs"
+	    else
+	      # Need to hardcode shared library paths
+	      # or/and link against static libraries
+	      newdependency_libs="$deplib $newdependency_libs"
+	    fi
+	    if $opt_duplicate_deps ; then
+	      case "$tmp_libs " in
+	      *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+	      esac
+	    fi
+	    tmp_libs="$tmp_libs $deplib"
+	  done # for deplib
+	  continue
+	fi # $linkmode = prog...
+
+	if test "$linkmode,$pass" = "prog,link"; then
+	  if test -n "$library_names" &&
+	     { { test "$prefer_static_libs" = no ||
+	         test "$prefer_static_libs,$installed" = "built,yes"; } ||
+	       test -z "$old_library"; }; then
+	    # We need to hardcode the library path
+	    if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then
+	      # Make sure the rpath contains only unique directories.
+	      case "$temp_rpath:" in
+	      *"$absdir:"*) ;;
+	      *) temp_rpath="$temp_rpath$absdir:" ;;
+	      esac
+	    fi
+
+	    # Hardcode the library path.
+	    # Skip directories that are in the system default run-time
+	    # search path.
+	    case " $sys_lib_dlsearch_path " in
+	    *" $absdir "*) ;;
+	    *)
+	      case "$compile_rpath " in
+	      *" $absdir "*) ;;
+	      *) compile_rpath="$compile_rpath $absdir"
+	      esac
+	      ;;
+	    esac
+	    case " $sys_lib_dlsearch_path " in
+	    *" $libdir "*) ;;
+	    *)
+	      case "$finalize_rpath " in
+	      *" $libdir "*) ;;
+	      *) finalize_rpath="$finalize_rpath $libdir"
+	      esac
+	      ;;
+	    esac
+	  fi # $linkmode,$pass = prog,link...
+
+	  if test "$alldeplibs" = yes &&
+	     { test "$deplibs_check_method" = pass_all ||
+	       { test "$build_libtool_libs" = yes &&
+		 test -n "$library_names"; }; }; then
+	    # We only need to search for static libraries
+	    continue
+	  fi
+	fi
+
+	link_static=no # Whether the deplib will be linked statically
+	use_static_libs=$prefer_static_libs
+	if test "$use_static_libs" = built && test "$installed" = yes; then
+	  use_static_libs=no
+	fi
+	if test -n "$library_names" &&
+	   { test "$use_static_libs" = no || test -z "$old_library"; }; then
+	  case $host in
+	  *cygwin* | *mingw*)
+	      # No point in relinking DLLs because paths are not encoded
+	      notinst_deplibs="$notinst_deplibs $lib"
+	      need_relink=no
+	    ;;
+	  *)
+	    if test "$installed" = no; then
+	      notinst_deplibs="$notinst_deplibs $lib"
+	      need_relink=yes
+	    fi
+	    ;;
+	  esac
+	  # This is a shared library
+
+	  # Warn about portability, can't link against -module's on some
+	  # systems (darwin).  Don't bleat about dlopened modules though!
+	  dlopenmodule=""
+	  for dlpremoduletest in $dlprefiles; do
+	    if test "X$dlpremoduletest" = "X$lib"; then
+	      dlopenmodule="$dlpremoduletest"
+	      break
+	    fi
+	  done
+	  if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then
+	    $ECHO
+	    if test "$linkmode" = prog; then
+	      $ECHO "*** Warning: Linking the executable $output against the loadable module"
+	    else
+	      $ECHO "*** Warning: Linking the shared library $output against the loadable module"
+	    fi
+	    $ECHO "*** $linklib is not portable!"
+	  fi
+	  if test "$linkmode" = lib &&
+	     test "$hardcode_into_libs" = yes; then
+	    # Hardcode the library path.
+	    # Skip directories that are in the system default run-time
+	    # search path.
+	    case " $sys_lib_dlsearch_path " in
+	    *" $absdir "*) ;;
+	    *)
+	      case "$compile_rpath " in
+	      *" $absdir "*) ;;
+	      *) compile_rpath="$compile_rpath $absdir"
+	      esac
+	      ;;
+	    esac
+	    case " $sys_lib_dlsearch_path " in
+	    *" $libdir "*) ;;
+	    *)
+	      case "$finalize_rpath " in
+	      *" $libdir "*) ;;
+	      *) finalize_rpath="$finalize_rpath $libdir"
+	      esac
+	      ;;
+	    esac
+	  fi
+
+	  if test -n "$old_archive_from_expsyms_cmds"; then
+	    # figure out the soname
+	    set dummy $library_names
+	    shift
+	    realname="$1"
+	    shift
+	    libname=`eval "\\$ECHO \"$libname_spec\""`
+	    # use dlname if we got it. it's perfectly good, no?
+	    if test -n "$dlname"; then
+	      soname="$dlname"
+	    elif test -n "$soname_spec"; then
+	      # bleh windows
+	      case $host in
+	      *cygwin* | mingw*)
+	        func_arith $current - $age
+		major=$func_arith_result
+		versuffix="-$major"
+		;;
+	      esac
+	      eval soname=\"$soname_spec\"
+	    else
+	      soname="$realname"
+	    fi
+
+	    # Make a new name for the extract_expsyms_cmds to use
+	    soroot="$soname"
+	    func_basename "$soroot"
+	    soname="$func_basename_result"
+	    func_stripname 'lib' '.dll' "$soname"
+	    newlib=libimp-$func_stripname_result.a
+
+	    # If the library has no export list, then create one now
+	    if test -f "$output_objdir/$soname-def"; then :
+	    else
+	      func_verbose "extracting exported symbol list from \`$soname'"
+	      func_execute_cmds "$extract_expsyms_cmds" 'exit $?'
+	    fi
+
+	    # Create $newlib
+	    if test -f "$output_objdir/$newlib"; then :; else
+	      func_verbose "generating import library for \`$soname'"
+	      func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?'
+	    fi
+	    # make sure the library variables are pointing to the new library
+	    dir=$output_objdir
+	    linklib=$newlib
+	  fi # test -n "$old_archive_from_expsyms_cmds"
+
+	  if test "$linkmode" = prog || test "$mode" != relink; then
+	    add_shlibpath=
+	    add_dir=
+	    add=
+	    lib_linked=yes
+	    case $hardcode_action in
+	    immediate | unsupported)
+	      if test "$hardcode_direct" = no; then
+		add="$dir/$linklib"
+		case $host in
+		  *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;;
+		  *-*-sysv4*uw2*) add_dir="-L$dir" ;;
+		  *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \
+		    *-*-unixware7*) add_dir="-L$dir" ;;
+		  *-*-darwin* )
+		    # if the lib is a (non-dlopened) module then we can not
+		    # link against it, someone is ignoring the earlier warnings
+		    if /usr/bin/file -L $add 2> /dev/null |
+			 $GREP ": [^:]* bundle" >/dev/null ; then
+		      if test "X$dlopenmodule" != "X$lib"; then
+			$ECHO "*** Warning: lib $linklib is a module, not a shared library"
+			if test -z "$old_library" ; then
+			  $ECHO
+			  $ECHO "*** And there doesn't seem to be a static archive available"
+			  $ECHO "*** The link will probably fail, sorry"
+			else
+			  add="$dir/$old_library"
+			fi
+		      elif test -n "$old_library"; then
+			add="$dir/$old_library"
+		      fi
+		    fi
+		esac
+	      elif test "$hardcode_minus_L" = no; then
+		case $host in
+		*-*-sunos*) add_shlibpath="$dir" ;;
+		esac
+		add_dir="-L$dir"
+		add="-l$name"
+	      elif test "$hardcode_shlibpath_var" = no; then
+		add_shlibpath="$dir"
+		add="-l$name"
+	      else
+		lib_linked=no
+	      fi
+	      ;;
+	    relink)
+	      if test "$hardcode_direct" = yes &&
+	         test "$hardcode_direct_absolute" = no; then
+		add="$dir/$linklib"
+	      elif test "$hardcode_minus_L" = yes; then
+		add_dir="-L$dir"
+		# Try looking first in the location we're being installed to.
+		if test -n "$inst_prefix_dir"; then
+		  case $libdir in
+		    [\\/]*)
+		      add_dir="$add_dir -L$inst_prefix_dir$libdir"
+		      ;;
+		  esac
+		fi
+		add="-l$name"
+	      elif test "$hardcode_shlibpath_var" = yes; then
+		add_shlibpath="$dir"
+		add="-l$name"
+	      else
+		lib_linked=no
+	      fi
+	      ;;
+	    *) lib_linked=no ;;
+	    esac
+
+	    if test "$lib_linked" != yes; then
+	      func_fatal_configuration "unsupported hardcode properties"
+	    fi
+
+	    if test -n "$add_shlibpath"; then
+	      case :$compile_shlibpath: in
+	      *":$add_shlibpath:"*) ;;
+	      *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;;
+	      esac
+	    fi
+	    if test "$linkmode" = prog; then
+	      test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
+	      test -n "$add" && compile_deplibs="$add $compile_deplibs"
+	    else
+	      test -n "$add_dir" && deplibs="$add_dir $deplibs"
+	      test -n "$add" && deplibs="$add $deplibs"
+	      if test "$hardcode_direct" != yes &&
+		 test "$hardcode_minus_L" != yes &&
+		 test "$hardcode_shlibpath_var" = yes; then
+		case :$finalize_shlibpath: in
+		*":$libdir:"*) ;;
+		*) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+		esac
+	      fi
+	    fi
+	  fi
+
+	  if test "$linkmode" = prog || test "$mode" = relink; then
+	    add_shlibpath=
+	    add_dir=
+	    add=
+	    # Finalize command for both is simple: just hardcode it.
+	    if test "$hardcode_direct" = yes &&
+	       test "$hardcode_direct_absolute" = no; then
+	      add="$libdir/$linklib"
+	    elif test "$hardcode_minus_L" = yes; then
+	      add_dir="-L$libdir"
+	      add="-l$name"
+	    elif test "$hardcode_shlibpath_var" = yes; then
+	      case :$finalize_shlibpath: in
+	      *":$libdir:"*) ;;
+	      *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+	      esac
+	      add="-l$name"
+	    elif test "$hardcode_automatic" = yes; then
+	      if test -n "$inst_prefix_dir" &&
+		 test -f "$inst_prefix_dir$libdir/$linklib" ; then
+		add="$inst_prefix_dir$libdir/$linklib"
+	      else
+		add="$libdir/$linklib"
+	      fi
+	    else
+	      # We cannot seem to hardcode it, guess we'll fake it.
+	      add_dir="-L$libdir"
+	      # Try looking first in the location we're being installed to.
+	      if test -n "$inst_prefix_dir"; then
+		case $libdir in
+		  [\\/]*)
+		    add_dir="$add_dir -L$inst_prefix_dir$libdir"
+		    ;;
+		esac
+	      fi
+	      add="-l$name"
+	    fi
+
+	    if test "$linkmode" = prog; then
+	      test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
+	      test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
+	    else
+	      test -n "$add_dir" && deplibs="$add_dir $deplibs"
+	      test -n "$add" && deplibs="$add $deplibs"
+	    fi
+	  fi
+	elif test "$linkmode" = prog; then
+	  # Here we assume that one of hardcode_direct or hardcode_minus_L
+	  # is not unsupported.  This is valid on all known static and
+	  # shared platforms.
+	  if test "$hardcode_direct" != unsupported; then
+	    test -n "$old_library" && linklib="$old_library"
+	    compile_deplibs="$dir/$linklib $compile_deplibs"
+	    finalize_deplibs="$dir/$linklib $finalize_deplibs"
+	  else
+	    compile_deplibs="-l$name -L$dir $compile_deplibs"
+	    finalize_deplibs="-l$name -L$dir $finalize_deplibs"
+	  fi
+	elif test "$build_libtool_libs" = yes; then
+	  # Not a shared library
+	  if test "$deplibs_check_method" != pass_all; then
+	    # We're trying link a shared library against a static one
+	    # but the system doesn't support it.
+
+	    # Just print a warning and add the library to dependency_libs so
+	    # that the program can be linked against the static library.
+	    $ECHO
+	    $ECHO "*** Warning: This system can not link to static lib archive $lib."
+	    $ECHO "*** I have the capability to make that library automatically link in when"
+	    $ECHO "*** you link to this library.  But I can only do this if you have a"
+	    $ECHO "*** shared version of the library, which you do not appear to have."
+	    if test "$module" = yes; then
+	      $ECHO "*** But as you try to build a module library, libtool will still create "
+	      $ECHO "*** a static module, that should work as long as the dlopening application"
+	      $ECHO "*** is linked with the -dlopen flag to resolve symbols at runtime."
+	      if test -z "$global_symbol_pipe"; then
+		$ECHO
+		$ECHO "*** However, this would only work if libtool was able to extract symbol"
+		$ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could"
+		$ECHO "*** not find such a program.  So, this module is probably useless."
+		$ECHO "*** \`nm' from GNU binutils and a full rebuild may help."
+	      fi
+	      if test "$build_old_libs" = no; then
+		build_libtool_libs=module
+		build_old_libs=yes
+	      else
+		build_libtool_libs=no
+	      fi
+	    fi
+	  else
+	    deplibs="$dir/$old_library $deplibs"
+	    link_static=yes
+	  fi
+	fi # link shared/static library?
+
+	if test "$linkmode" = lib; then
+	  if test -n "$dependency_libs" &&
+	     { test "$hardcode_into_libs" != yes ||
+	       test "$build_old_libs" = yes ||
+	       test "$link_static" = yes; }; then
+	    # Extract -R from dependency_libs
+	    temp_deplibs=
+	    for libdir in $dependency_libs; do
+	      case $libdir in
+	      -R*) func_stripname '-R' '' "$libdir"
+	           temp_xrpath=$func_stripname_result
+		   case " $xrpath " in
+		   *" $temp_xrpath "*) ;;
+		   *) xrpath="$xrpath $temp_xrpath";;
+		   esac;;
+	      *) temp_deplibs="$temp_deplibs $libdir";;
+	      esac
+	    done
+	    dependency_libs="$temp_deplibs"
+	  fi
+
+	  newlib_search_path="$newlib_search_path $absdir"
+	  # Link against this library
+	  test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
+	  # ... and its dependency_libs
+	  tmp_libs=
+	  for deplib in $dependency_libs; do
+	    newdependency_libs="$deplib $newdependency_libs"
+	    if $opt_duplicate_deps ; then
+	      case "$tmp_libs " in
+	      *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+	      esac
+	    fi
+	    tmp_libs="$tmp_libs $deplib"
+	  done
+
+	  if test "$link_all_deplibs" != no; then
+	    # Add the search paths of all dependency libraries
+	    for deplib in $dependency_libs; do
+	      case $deplib in
+	      -L*) path="$deplib" ;;
+	      *.la)
+	        func_dirname "$deplib" "" "."
+		dir="$func_dirname_result"
+		# We need an absolute path.
+		case $dir in
+		[\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;;
+		*)
+		  absdir=`cd "$dir" && pwd`
+		  if test -z "$absdir"; then
+		    func_warning "cannot determine absolute directory name of \`$dir'"
+		    absdir="$dir"
+		  fi
+		  ;;
+		esac
+		if $GREP "^installed=no" $deplib > /dev/null; then
+		case $host in
+		*-*-darwin*)
+		  depdepl=
+		  eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
+		  if test -n "$deplibrary_names" ; then
+		    for tmp in $deplibrary_names ; do
+		      depdepl=$tmp
+		    done
+		    if test -f "$absdir/$objdir/$depdepl" ; then
+		      depdepl="$absdir/$objdir/$depdepl"
+		      darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'`
+                      if test -z "$darwin_install_name"; then
+                          darwin_install_name=`${OTOOL64} -L $depdepl  | awk '{if (NR == 2) {print $1;exit}}'`
+                      fi
+		      compiler_flags="$compiler_flags ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}"
+		      linker_flags="$linker_flags -dylib_file ${darwin_install_name}:${depdepl}"
+		      path=
+		    fi
+		  fi
+		  ;;
+		*)
+		  path="-L$absdir/$objdir"
+		  ;;
+		esac
+		else
+		  eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+		  test -z "$libdir" && \
+		    func_fatal_error "\`$deplib' is not a valid libtool archive"
+		  test "$absdir" != "$libdir" && \
+		    func_warning "\`$deplib' seems to be moved"
+
+		  path="-L$absdir"
+		fi
+		;;
+	      esac
+	      case " $deplibs " in
+	      *" $path "*) ;;
+	      *) deplibs="$path $deplibs" ;;
+	      esac
+	    done
+	  fi # link_all_deplibs != no
+	fi # linkmode = lib
+      done # for deplib in $libs
+      if test "$pass" = link; then
+	if test "$linkmode" = "prog"; then
+	  compile_deplibs="$new_inherited_linker_flags $compile_deplibs"
+	  finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs"
+	else
+	  compiler_flags="$compiler_flags "`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+	fi
+      fi
+      dependency_libs="$newdependency_libs"
+      if test "$pass" = dlpreopen; then
+	# Link the dlpreopened libraries before other libraries
+	for deplib in $save_deplibs; do
+	  deplibs="$deplib $deplibs"
+	done
+      fi
+      if test "$pass" != dlopen; then
+	if test "$pass" != conv; then
+	  # Make sure lib_search_path contains only unique directories.
+	  lib_search_path=
+	  for dir in $newlib_search_path; do
+	    case "$lib_search_path " in
+	    *" $dir "*) ;;
+	    *) lib_search_path="$lib_search_path $dir" ;;
+	    esac
+	  done
+	  newlib_search_path=
+	fi
+
+	if test "$linkmode,$pass" != "prog,link"; then
+	  vars="deplibs"
+	else
+	  vars="compile_deplibs finalize_deplibs"
+	fi
+	for var in $vars dependency_libs; do
+	  # Add libraries to $var in reverse order
+	  eval tmp_libs=\"\$$var\"
+	  new_libs=
+	  for deplib in $tmp_libs; do
+	    # FIXME: Pedantically, this is the right thing to do, so
+	    #        that some nasty dependency loop isn't accidentally
+	    #        broken:
+	    #new_libs="$deplib $new_libs"
+	    # Pragmatically, this seems to cause very few problems in
+	    # practice:
+	    case $deplib in
+	    -L*) new_libs="$deplib $new_libs" ;;
+	    -R*) ;;
+	    *)
+	      # And here is the reason: when a library appears more
+	      # than once as an explicit dependence of a library, or
+	      # is implicitly linked in more than once by the
+	      # compiler, it is considered special, and multiple
+	      # occurrences thereof are not removed.  Compare this
+	      # with having the same library being listed as a
+	      # dependency of multiple other libraries: in this case,
+	      # we know (pedantically, we assume) the library does not
+	      # need to be listed more than once, so we keep only the
+	      # last copy.  This is not always right, but it is rare
+	      # enough that we require users that really mean to play
+	      # such unportable linking tricks to link the library
+	      # using -Wl,-lname, so that libtool does not consider it
+	      # for duplicate removal.
+	      case " $specialdeplibs " in
+	      *" $deplib "*) new_libs="$deplib $new_libs" ;;
+	      *)
+		case " $new_libs " in
+		*" $deplib "*) ;;
+		*) new_libs="$deplib $new_libs" ;;
+		esac
+		;;
+	      esac
+	      ;;
+	    esac
+	  done
+	  tmp_libs=
+	  for deplib in $new_libs; do
+	    case $deplib in
+	    -L*)
+	      case " $tmp_libs " in
+	      *" $deplib "*) ;;
+	      *) tmp_libs="$tmp_libs $deplib" ;;
+	      esac
+	      ;;
+	    *) tmp_libs="$tmp_libs $deplib" ;;
+	    esac
+	  done
+	  eval $var=\"$tmp_libs\"
+	done # for var
+      fi
+      # Last step: remove runtime libs from dependency_libs
+      # (they stay in deplibs)
+      tmp_libs=
+      for i in $dependency_libs ; do
+	case " $predeps $postdeps $compiler_lib_search_path " in
+	*" $i "*)
+	  i=""
+	  ;;
+	esac
+	if test -n "$i" ; then
+	  tmp_libs="$tmp_libs $i"
+	fi
+      done
+      dependency_libs=$tmp_libs
+    done # for pass
+    if test "$linkmode" = prog; then
+      dlfiles="$newdlfiles"
+    fi
+    if test "$linkmode" = prog || test "$linkmode" = lib; then
+      dlprefiles="$newdlprefiles"
+    fi
+
+    case $linkmode in
+    oldlib)
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+	func_warning "\`-dlopen' is ignored for archives"
+      fi
+
+      case " $deplibs" in
+      *\ -l* | *\ -L*)
+	func_warning "\`-l' and \`-L' are ignored for archives" ;;
+      esac
+
+      test -n "$rpath" && \
+	func_warning "\`-rpath' is ignored for archives"
+
+      test -n "$xrpath" && \
+	func_warning "\`-R' is ignored for archives"
+
+      test -n "$vinfo" && \
+	func_warning "\`-version-info/-version-number' is ignored for archives"
+
+      test -n "$release" && \
+	func_warning "\`-release' is ignored for archives"
+
+      test -n "$export_symbols$export_symbols_regex" && \
+	func_warning "\`-export-symbols' is ignored for archives"
+
+      # Now set the variables for building old libraries.
+      build_libtool_libs=no
+      oldlibs="$output"
+      objs="$objs$old_deplibs"
+      ;;
+
+    lib)
+      # Make sure we only generate libraries of the form `libNAME.la'.
+      case $outputname in
+      lib*)
+	func_stripname 'lib' '.la' "$outputname"
+	name=$func_stripname_result
+	eval shared_ext=\"$shrext_cmds\"
+	eval libname=\"$libname_spec\"
+	;;
+      *)
+	test "$module" = no && \
+	  func_fatal_help "libtool library \`$output' must begin with \`lib'"
+
+	if test "$need_lib_prefix" != no; then
+	  # Add the "lib" prefix for modules if required
+	  func_stripname '' '.la' "$outputname"
+	  name=$func_stripname_result
+	  eval shared_ext=\"$shrext_cmds\"
+	  eval libname=\"$libname_spec\"
+	else
+	  func_stripname '' '.la' "$outputname"
+	  libname=$func_stripname_result
+	fi
+	;;
+      esac
+
+      if test -n "$objs"; then
+	if test "$deplibs_check_method" != pass_all; then
+	  func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs"
+	else
+	  $ECHO
+	  $ECHO "*** Warning: Linking the shared library $output against the non-libtool"
+	  $ECHO "*** objects $objs is not portable!"
+	  libobjs="$libobjs $objs"
+	fi
+      fi
+
+      test "$dlself" != no && \
+	func_warning "\`-dlopen self' is ignored for libtool libraries"
+
+      set dummy $rpath
+      shift
+      test "$#" -gt 1 && \
+	func_warning "ignoring multiple \`-rpath's for a libtool library"
+
+      install_libdir="$1"
+
+      oldlibs=
+      if test -z "$rpath"; then
+	if test "$build_libtool_libs" = yes; then
+	  # Building a libtool convenience library.
+	  # Some compilers have problems with a `.al' extension so
+	  # convenience libraries should have the same extension an
+	  # archive normally would.
+	  oldlibs="$output_objdir/$libname.$libext $oldlibs"
+	  build_libtool_libs=convenience
+	  build_old_libs=yes
+	fi
+
+	test -n "$vinfo" && \
+	  func_warning "\`-version-info/-version-number' is ignored for convenience libraries"
+
+	test -n "$release" && \
+	  func_warning "\`-release' is ignored for convenience libraries"
+      else
+
+	# Parse the version information argument.
+	save_ifs="$IFS"; IFS=':'
+	set dummy $vinfo 0 0 0
+	shift
+	IFS="$save_ifs"
+
+	test -n "$7" && \
+	  func_fatal_help "too many parameters to \`-version-info'"
+
+	# convert absolute version numbers to libtool ages
+	# this retains compatibility with .la files and attempts
+	# to make the code below a bit more comprehensible
+
+	case $vinfo_number in
+	yes)
+	  number_major="$1"
+	  number_minor="$2"
+	  number_revision="$3"
+	  #
+	  # There are really only two kinds -- those that
+	  # use the current revision as the major version
+	  # and those that subtract age and use age as
+	  # a minor version.  But, then there is irix
+	  # which has an extra 1 added just for fun
+	  #
+	  case $version_type in
+	  darwin|linux|osf|windows|none)
+	    func_arith $number_major + $number_minor
+	    current=$func_arith_result
+	    age="$number_minor"
+	    revision="$number_revision"
+	    ;;
+	  freebsd-aout|freebsd-elf|sunos)
+	    current="$number_major"
+	    revision="$number_minor"
+	    age="0"
+	    ;;
+	  irix|nonstopux)
+	    func_arith $number_major + $number_minor
+	    current=$func_arith_result
+	    age="$number_minor"
+	    revision="$number_minor"
+	    lt_irix_increment=no
+	    ;;
+	  esac
+	  ;;
+	no)
+	  current="$1"
+	  revision="$2"
+	  age="$3"
+	  ;;
+	esac
+
+	# Check that each of the things are valid numbers.
+	case $current in
+	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+	*)
+	  func_error "CURRENT \`$current' must be a nonnegative integer"
+	  func_fatal_error "\`$vinfo' is not valid version information"
+	  ;;
+	esac
+
+	case $revision in
+	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+	*)
+	  func_error "REVISION \`$revision' must be a nonnegative integer"
+	  func_fatal_error "\`$vinfo' is not valid version information"
+	  ;;
+	esac
+
+	case $age in
+	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+	*)
+	  func_error "AGE \`$age' must be a nonnegative integer"
+	  func_fatal_error "\`$vinfo' is not valid version information"
+	  ;;
+	esac
+
+	if test "$age" -gt "$current"; then
+	  func_error "AGE \`$age' is greater than the current interface number \`$current'"
+	  func_fatal_error "\`$vinfo' is not valid version information"
+	fi
+
+	# Calculate the version variables.
+	major=
+	versuffix=
+	verstring=
+	case $version_type in
+	none) ;;
+
+	darwin)
+	  # Like Linux, but with the current version available in
+	  # verstring for coding it into the library header
+	  func_arith $current - $age
+	  major=.$func_arith_result
+	  versuffix="$major.$age.$revision"
+	  # Darwin ld doesn't like 0 for these options...
+	  func_arith $current + 1
+	  minor_current=$func_arith_result
+	  xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision"
+	  verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
+	  ;;
+
+	freebsd-aout)
+	  major=".$current"
+	  versuffix=".$current.$revision";
+	  ;;
+
+	freebsd-elf)
+	  major=".$current"
+	  versuffix=".$current"
+	  ;;
+
+	irix | nonstopux)
+	  if test "X$lt_irix_increment" = "Xno"; then
+	    func_arith $current - $age
+	  else
+	    func_arith $current - $age + 1
+	  fi
+	  major=$func_arith_result
+
+	  case $version_type in
+	    nonstopux) verstring_prefix=nonstopux ;;
+	    *)         verstring_prefix=sgi ;;
+	  esac
+	  verstring="$verstring_prefix$major.$revision"
+
+	  # Add in all the interfaces that we are compatible with.
+	  loop=$revision
+	  while test "$loop" -ne 0; do
+	    func_arith $revision - $loop
+	    iface=$func_arith_result
+	    func_arith $loop - 1
+	    loop=$func_arith_result
+	    verstring="$verstring_prefix$major.$iface:$verstring"
+	  done
+
+	  # Before this point, $major must not contain `.'.
+	  major=.$major
+	  versuffix="$major.$revision"
+	  ;;
+
+	linux)
+	  func_arith $current - $age
+	  major=.$func_arith_result
+	  versuffix="$major.$age.$revision"
+	  ;;
+
+	osf)
+	  func_arith $current - $age
+	  major=.$func_arith_result
+	  versuffix=".$current.$age.$revision"
+	  verstring="$current.$age.$revision"
+
+	  # Add in all the interfaces that we are compatible with.
+	  loop=$age
+	  while test "$loop" -ne 0; do
+	    func_arith $current - $loop
+	    iface=$func_arith_result
+	    func_arith $loop - 1
+	    loop=$func_arith_result
+	    verstring="$verstring:${iface}.0"
+	  done
+
+	  # Make executables depend on our current version.
+	  verstring="$verstring:${current}.0"
+	  ;;
+
+	qnx)
+	  major=".$current"
+	  versuffix=".$current"
+	  ;;
+
+	sunos)
+	  major=".$current"
+	  versuffix=".$current.$revision"
+	  ;;
+
+	windows)
+	  # Use '-' rather than '.', since we only want one
+	  # extension on DOS 8.3 filesystems.
+	  func_arith $current - $age
+	  major=$func_arith_result
+	  versuffix="-$major"
+	  ;;
+
+	*)
+	  func_fatal_configuration "unknown library version type \`$version_type'"
+	  ;;
+	esac
+
+	# Clear the version info if we defaulted, and they specified a release.
+	if test -z "$vinfo" && test -n "$release"; then
+	  major=
+	  case $version_type in
+	  darwin)
+	    # we can't check for "0.0" in archive_cmds due to quoting
+	    # problems, so we reset it completely
+	    verstring=
+	    ;;
+	  *)
+	    verstring="0.0"
+	    ;;
+	  esac
+	  if test "$need_version" = no; then
+	    versuffix=
+	  else
+	    versuffix=".0.0"
+	  fi
+	fi
+
+	# Remove version info from name if versioning should be avoided
+	if test "$avoid_version" = yes && test "$need_version" = no; then
+	  major=
+	  versuffix=
+	  verstring=""
+	fi
+
+	# Check to see if the archive will have undefined symbols.
+	if test "$allow_undefined" = yes; then
+	  if test "$allow_undefined_flag" = unsupported; then
+	    func_warning "undefined symbols not allowed in $host shared libraries"
+	    build_libtool_libs=no
+	    build_old_libs=yes
+	  fi
+	else
+	  # Don't allow undefined symbols.
+	  allow_undefined_flag="$no_undefined_flag"
+	fi
+
+      fi
+
+      func_generate_dlsyms "$libname" "$libname" "yes"
+      libobjs="$libobjs $symfileobj"
+      test "X$libobjs" = "X " && libobjs=
+
+      if test "$mode" != relink; then
+	# Remove our outputs, but don't remove object files since they
+	# may have been created when compiling PIC objects.
+	removelist=
+	tempremovelist=`$ECHO "$output_objdir/*"`
+	for p in $tempremovelist; do
+	  case $p in
+	    *.$objext)
+	       ;;
+	    $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*)
+	       if test "X$precious_files_regex" != "X"; then
+		 if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
+		 then
+		   continue
+		 fi
+	       fi
+	       removelist="$removelist $p"
+	       ;;
+	    *) ;;
+	  esac
+	done
+	test -n "$removelist" && \
+	  func_show_eval "${RM}r \$removelist"
+      fi
+
+      # Now set the variables for building old libraries.
+      if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
+	oldlibs="$oldlibs $output_objdir/$libname.$libext"
+
+	# Transform .lo files to .o files.
+	oldobjs="$objs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP`
+      fi
+
+      # Eliminate all temporary directories.
+      #for path in $notinst_path; do
+      #	lib_search_path=`$ECHO "X$lib_search_path " | $Xsed -e "s% $path % %g"`
+      #	deplibs=`$ECHO "X$deplibs " | $Xsed -e "s% -L$path % %g"`
+      #	dependency_libs=`$ECHO "X$dependency_libs " | $Xsed -e "s% -L$path % %g"`
+      #done
+
+      if test -n "$xrpath"; then
+	# If the user specified any rpath flags, then add them.
+	temp_xrpath=
+	for libdir in $xrpath; do
+	  temp_xrpath="$temp_xrpath -R$libdir"
+	  case "$finalize_rpath " in
+	  *" $libdir "*) ;;
+	  *) finalize_rpath="$finalize_rpath $libdir" ;;
+	  esac
+	done
+	if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then
+	  dependency_libs="$temp_xrpath $dependency_libs"
+	fi
+      fi
+
+      # Make sure dlfiles contains only unique files that won't be dlpreopened
+      old_dlfiles="$dlfiles"
+      dlfiles=
+      for lib in $old_dlfiles; do
+	case " $dlprefiles $dlfiles " in
+	*" $lib "*) ;;
+	*) dlfiles="$dlfiles $lib" ;;
+	esac
+      done
+
+      # Make sure dlprefiles contains only unique files
+      old_dlprefiles="$dlprefiles"
+      dlprefiles=
+      for lib in $old_dlprefiles; do
+	case "$dlprefiles " in
+	*" $lib "*) ;;
+	*) dlprefiles="$dlprefiles $lib" ;;
+	esac
+      done
+
+      if test "$build_libtool_libs" = yes; then
+	if test -n "$rpath"; then
+	  case $host in
+	  *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*)
+	    # these systems don't actually have a c library (as such)!
+	    ;;
+	  *-*-rhapsody* | *-*-darwin1.[012])
+	    # Rhapsody C library is in the System framework
+	    deplibs="$deplibs System.ltframework"
+	    ;;
+	  *-*-netbsd*)
+	    # Don't link with libc until the a.out ld.so is fixed.
+	    ;;
+	  *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+	    # Do not include libc due to us having libc/libc_r.
+	    ;;
+	  *-*-sco3.2v5* | *-*-sco5v6*)
+	    # Causes problems with __ctype
+	    ;;
+	  *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+	    # Compiler inserts libc in the correct place for threads to work
+	    ;;
+	  *)
+	    # Add libc to deplibs on all other systems if necessary.
+	    if test "$build_libtool_need_lc" = "yes"; then
+	      deplibs="$deplibs -lc"
+	    fi
+	    ;;
+	  esac
+	fi
+
+	# Transform deplibs into only deplibs that can be linked in shared.
+	name_save=$name
+	libname_save=$libname
+	release_save=$release
+	versuffix_save=$versuffix
+	major_save=$major
+	# I'm not sure if I'm treating the release correctly.  I think
+	# release should show up in the -l (ie -lgmp5) so we don't want to
+	# add it in twice.  Is that correct?
+	release=""
+	versuffix=""
+	major=""
+	newdeplibs=
+	droppeddeps=no
+	case $deplibs_check_method in
+	pass_all)
+	  # Don't check for shared/static.  Everything works.
+	  # This might be a little naive.  We might want to check
+	  # whether the library exists or not.  But this is on
+	  # osf3 & osf4 and I'm not really sure... Just
+	  # implementing what was already the behavior.
+	  newdeplibs=$deplibs
+	  ;;
+	test_compile)
+	  # This code stresses the "libraries are programs" paradigm to its
+	  # limits. Maybe even breaks it.  We compile a program, linking it
+	  # against the deplibs as a proxy for the library.  Then we can check
+	  # whether they linked in statically or dynamically with ldd.
+	  $opt_dry_run || $RM conftest.c
+	  cat > conftest.c <<EOF
+	  int main() { return 0; }
+EOF
+	  $opt_dry_run || $RM conftest
+	  if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then
+	    ldd_output=`ldd conftest`
+	    for i in $deplibs; do
+	      case $i in
+	      -l*)
+		func_stripname -l '' "$i"
+		name=$func_stripname_result
+		if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		  case " $predeps $postdeps " in
+		  *" $i "*)
+		    newdeplibs="$newdeplibs $i"
+		    i=""
+		    ;;
+		  esac
+		fi
+		if test -n "$i" ; then
+		  libname=`eval "\\$ECHO \"$libname_spec\""`
+		  deplib_matches=`eval "\\$ECHO \"$library_names_spec\""`
+		  set dummy $deplib_matches; shift
+		  deplib_match=$1
+		  if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+		    newdeplibs="$newdeplibs $i"
+		  else
+		    droppeddeps=yes
+		    $ECHO
+		    $ECHO "*** Warning: dynamic linker does not accept needed library $i."
+		    $ECHO "*** I have the capability to make that library automatically link in when"
+		    $ECHO "*** you link to this library.  But I can only do this if you have a"
+		    $ECHO "*** shared version of the library, which I believe you do not have"
+		    $ECHO "*** because a test_compile did reveal that the linker did not use it for"
+		    $ECHO "*** its dynamic dependency list that programs get resolved with at runtime."
+		  fi
+		fi
+		;;
+	      *)
+		newdeplibs="$newdeplibs $i"
+		;;
+	      esac
+	    done
+	  else
+	    # Error occurred in the first compile.  Let's try to salvage
+	    # the situation: Compile a separate program for each library.
+	    for i in $deplibs; do
+	      case $i in
+	      -l*)
+		func_stripname -l '' "$i"
+		name=$func_stripname_result
+		$opt_dry_run || $RM conftest
+		if $LTCC $LTCFLAGS -o conftest conftest.c $i; then
+		  ldd_output=`ldd conftest`
+		  if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		    case " $predeps $postdeps " in
+		    *" $i "*)
+		      newdeplibs="$newdeplibs $i"
+		      i=""
+		      ;;
+		    esac
+		  fi
+		  if test -n "$i" ; then
+		    libname=`eval "\\$ECHO \"$libname_spec\""`
+		    deplib_matches=`eval "\\$ECHO \"$library_names_spec\""`
+		    set dummy $deplib_matches; shift
+		    deplib_match=$1
+		    if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+		      newdeplibs="$newdeplibs $i"
+		    else
+		      droppeddeps=yes
+		      $ECHO
+		      $ECHO "*** Warning: dynamic linker does not accept needed library $i."
+		      $ECHO "*** I have the capability to make that library automatically link in when"
+		      $ECHO "*** you link to this library.  But I can only do this if you have a"
+		      $ECHO "*** shared version of the library, which you do not appear to have"
+		      $ECHO "*** because a test_compile did reveal that the linker did not use this one"
+		      $ECHO "*** as a dynamic dependency that programs can get resolved with at runtime."
+		    fi
+		  fi
+		else
+		  droppeddeps=yes
+		  $ECHO
+		  $ECHO "*** Warning!  Library $i is needed by this library but I was not able to"
+		  $ECHO "*** make it link in!  You will probably need to install it or some"
+		  $ECHO "*** library that it depends on before this library will be fully"
+		  $ECHO "*** functional.  Installing it before continuing would be even better."
+		fi
+		;;
+	      *)
+		newdeplibs="$newdeplibs $i"
+		;;
+	      esac
+	    done
+	  fi
+	  ;;
+	file_magic*)
+	  set dummy $deplibs_check_method; shift
+	  file_magic_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+	  for a_deplib in $deplibs; do
+	    case $a_deplib in
+	    -l*)
+	      func_stripname -l '' "$a_deplib"
+	      name=$func_stripname_result
+	      if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		case " $predeps $postdeps " in
+		*" $a_deplib "*)
+		  newdeplibs="$newdeplibs $a_deplib"
+		  a_deplib=""
+		  ;;
+		esac
+	      fi
+	      if test -n "$a_deplib" ; then
+		libname=`eval "\\$ECHO \"$libname_spec\""`
+		for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+		  potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+		  for potent_lib in $potential_libs; do
+		      # Follow soft links.
+		      if ls -lLd "$potent_lib" 2>/dev/null |
+			 $GREP " -> " >/dev/null; then
+			continue
+		      fi
+		      # The statement above tries to avoid entering an
+		      # endless loop below, in case of cyclic links.
+		      # We might still enter an endless loop, since a link
+		      # loop can be closed while we follow links,
+		      # but so what?
+		      potlib="$potent_lib"
+		      while test -h "$potlib" 2>/dev/null; do
+			potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'`
+			case $potliblink in
+			[\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
+			*) potlib=`$ECHO "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
+			esac
+		      done
+		      if eval $file_magic_cmd \"\$potlib\" 2>/dev/null |
+			 $SED -e 10q |
+			 $EGREP "$file_magic_regex" > /dev/null; then
+			newdeplibs="$newdeplibs $a_deplib"
+			a_deplib=""
+			break 2
+		      fi
+		  done
+		done
+	      fi
+	      if test -n "$a_deplib" ; then
+		droppeddeps=yes
+		$ECHO
+		$ECHO "*** Warning: linker path does not have real file for library $a_deplib."
+		$ECHO "*** I have the capability to make that library automatically link in when"
+		$ECHO "*** you link to this library.  But I can only do this if you have a"
+		$ECHO "*** shared version of the library, which you do not appear to have"
+		$ECHO "*** because I did check the linker path looking for a file starting"
+		if test -z "$potlib" ; then
+		  $ECHO "*** with $libname but no candidates were found. (...for file magic test)"
+		else
+		  $ECHO "*** with $libname and none of the candidates passed a file format test"
+		  $ECHO "*** using a file magic. Last file checked: $potlib"
+		fi
+	      fi
+	      ;;
+	    *)
+	      # Add a -L argument.
+	      newdeplibs="$newdeplibs $a_deplib"
+	      ;;
+	    esac
+	  done # Gone through all deplibs.
+	  ;;
+	match_pattern*)
+	  set dummy $deplibs_check_method; shift
+	  match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+	  for a_deplib in $deplibs; do
+	    case $a_deplib in
+	    -l*)
+	      func_stripname -l '' "$a_deplib"
+	      name=$func_stripname_result
+	      if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		case " $predeps $postdeps " in
+		*" $a_deplib "*)
+		  newdeplibs="$newdeplibs $a_deplib"
+		  a_deplib=""
+		  ;;
+		esac
+	      fi
+	      if test -n "$a_deplib" ; then
+		libname=`eval "\\$ECHO \"$libname_spec\""`
+		for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+		  potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+		  for potent_lib in $potential_libs; do
+		    potlib="$potent_lib" # see symlink-check above in file_magic test
+		    if eval "\$ECHO \"X$potent_lib\"" 2>/dev/null | $Xsed -e 10q | \
+		       $EGREP "$match_pattern_regex" > /dev/null; then
+		      newdeplibs="$newdeplibs $a_deplib"
+		      a_deplib=""
+		      break 2
+		    fi
+		  done
+		done
+	      fi
+	      if test -n "$a_deplib" ; then
+		droppeddeps=yes
+		$ECHO
+		$ECHO "*** Warning: linker path does not have real file for library $a_deplib."
+		$ECHO "*** I have the capability to make that library automatically link in when"
+		$ECHO "*** you link to this library.  But I can only do this if you have a"
+		$ECHO "*** shared version of the library, which you do not appear to have"
+		$ECHO "*** because I did check the linker path looking for a file starting"
+		if test -z "$potlib" ; then
+		  $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)"
+		else
+		  $ECHO "*** with $libname and none of the candidates passed a file format test"
+		  $ECHO "*** using a regex pattern. Last file checked: $potlib"
+		fi
+	      fi
+	      ;;
+	    *)
+	      # Add a -L argument.
+	      newdeplibs="$newdeplibs $a_deplib"
+	      ;;
+	    esac
+	  done # Gone through all deplibs.
+	  ;;
+	none | unknown | *)
+	  newdeplibs=""
+	  tmp_deplibs=`$ECHO "X $deplibs" | $Xsed \
+	      -e 's/ -lc$//' -e 's/ -[LR][^ ]*//g'`
+	  if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+	    for i in $predeps $postdeps ; do
+	      # can't use Xsed below, because $i might contain '/'
+	      tmp_deplibs=`$ECHO "X $tmp_deplibs" | $Xsed -e "s,$i,,"`
+	    done
+	  fi
+	  if $ECHO "X $tmp_deplibs" | $Xsed -e 's/[	 ]//g' |
+	     $GREP . >/dev/null; then
+	    $ECHO
+	    if test "X$deplibs_check_method" = "Xnone"; then
+	      $ECHO "*** Warning: inter-library dependencies are not supported in this platform."
+	    else
+	      $ECHO "*** Warning: inter-library dependencies are not known to be supported."
+	    fi
+	    $ECHO "*** All declared inter-library dependencies are being dropped."
+	    droppeddeps=yes
+	  fi
+	  ;;
+	esac
+	versuffix=$versuffix_save
+	major=$major_save
+	release=$release_save
+	libname=$libname_save
+	name=$name_save
+
+	case $host in
+	*-*-rhapsody* | *-*-darwin1.[012])
+	  # On Rhapsody replace the C library with the System framework
+	  newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's/ -lc / System.ltframework /'`
+	  ;;
+	esac
+
+	if test "$droppeddeps" = yes; then
+	  if test "$module" = yes; then
+	    $ECHO
+	    $ECHO "*** Warning: libtool could not satisfy all declared inter-library"
+	    $ECHO "*** dependencies of module $libname.  Therefore, libtool will create"
+	    $ECHO "*** a static module, that should work as long as the dlopening"
+	    $ECHO "*** application is linked with the -dlopen flag."
+	    if test -z "$global_symbol_pipe"; then
+	      $ECHO
+	      $ECHO "*** However, this would only work if libtool was able to extract symbol"
+	      $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could"
+	      $ECHO "*** not find such a program.  So, this module is probably useless."
+	      $ECHO "*** \`nm' from GNU binutils and a full rebuild may help."
+	    fi
+	    if test "$build_old_libs" = no; then
+	      oldlibs="$output_objdir/$libname.$libext"
+	      build_libtool_libs=module
+	      build_old_libs=yes
+	    else
+	      build_libtool_libs=no
+	    fi
+	  else
+	    $ECHO "*** The inter-library dependencies that have been dropped here will be"
+	    $ECHO "*** automatically added whenever a program is linked with this library"
+	    $ECHO "*** or is declared to -dlopen it."
+
+	    if test "$allow_undefined" = no; then
+	      $ECHO
+	      $ECHO "*** Since this library must not contain undefined symbols,"
+	      $ECHO "*** because either the platform does not support them or"
+	      $ECHO "*** it was explicitly requested with -no-undefined,"
+	      $ECHO "*** libtool will only create a static version of it."
+	      if test "$build_old_libs" = no; then
+		oldlibs="$output_objdir/$libname.$libext"
+		build_libtool_libs=module
+		build_old_libs=yes
+	      else
+		build_libtool_libs=no
+	      fi
+	    fi
+	  fi
+	fi
+	# Done checking deplibs!
+	deplibs=$newdeplibs
+      fi
+      # Time to change all our "foo.ltframework" stuff back to "-framework foo"
+      case $host in
+	*-*-darwin*)
+	  newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+	  new_inherited_linker_flags=`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+	  deplibs=`$ECHO "X $deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+	  ;;
+      esac
+
+      # move library search paths that coincide with paths to not yet
+      # installed libraries to the beginning of the library search list
+      new_libs=
+      for path in $notinst_path; do
+	case " $new_libs " in
+	*" -L$path/$objdir "*) ;;
+	*)
+	  case " $deplibs " in
+	  *" -L$path/$objdir "*)
+	    new_libs="$new_libs -L$path/$objdir" ;;
+	  esac
+	  ;;
+	esac
+      done
+      for deplib in $deplibs; do
+	case $deplib in
+	-L*)
+	  case " $new_libs " in
+	  *" $deplib "*) ;;
+	  *) new_libs="$new_libs $deplib" ;;
+	  esac
+	  ;;
+	*) new_libs="$new_libs $deplib" ;;
+	esac
+      done
+      deplibs="$new_libs"
+
+      # All the library-specific variables (install_libdir is set above).
+      library_names=
+      old_library=
+      dlname=
+
+      # Test again, we may have decided not to build it any more
+      if test "$build_libtool_libs" = yes; then
+	if test "$hardcode_into_libs" = yes; then
+	  # Hardcode the library paths
+	  hardcode_libdirs=
+	  dep_rpath=
+	  rpath="$finalize_rpath"
+	  test "$mode" != relink && rpath="$compile_rpath$rpath"
+	  for libdir in $rpath; do
+	    if test -n "$hardcode_libdir_flag_spec"; then
+	      if test -n "$hardcode_libdir_separator"; then
+		if test -z "$hardcode_libdirs"; then
+		  hardcode_libdirs="$libdir"
+		else
+		  # Just accumulate the unique libdirs.
+		  case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+		  *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+		    ;;
+		  *)
+		    hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+		    ;;
+		  esac
+		fi
+	      else
+		eval flag=\"$hardcode_libdir_flag_spec\"
+		dep_rpath="$dep_rpath $flag"
+	      fi
+	    elif test -n "$runpath_var"; then
+	      case "$perm_rpath " in
+	      *" $libdir "*) ;;
+	      *) perm_rpath="$perm_rpath $libdir" ;;
+	      esac
+	    fi
+	  done
+	  # Substitute the hardcoded libdirs into the rpath.
+	  if test -n "$hardcode_libdir_separator" &&
+	     test -n "$hardcode_libdirs"; then
+	    libdir="$hardcode_libdirs"
+	    if test -n "$hardcode_libdir_flag_spec_ld"; then
+	      eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\"
+	    else
+	      eval dep_rpath=\"$hardcode_libdir_flag_spec\"
+	    fi
+	  fi
+	  if test -n "$runpath_var" && test -n "$perm_rpath"; then
+	    # We should set the runpath_var.
+	    rpath=
+	    for dir in $perm_rpath; do
+	      rpath="$rpath$dir:"
+	    done
+	    eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
+	  fi
+	  test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
+	fi
+
+	shlibpath="$finalize_shlibpath"
+	test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath"
+	if test -n "$shlibpath"; then
+	  eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
+	fi
+
+	# Get the real and link names of the library.
+	eval shared_ext=\"$shrext_cmds\"
+	eval library_names=\"$library_names_spec\"
+	set dummy $library_names
+	shift
+	realname="$1"
+	shift
+
+	if test -n "$soname_spec"; then
+	  eval soname=\"$soname_spec\"
+	else
+	  soname="$realname"
+	fi
+	if test -z "$dlname"; then
+	  dlname=$soname
+	fi
+
+	lib="$output_objdir/$realname"
+	linknames=
+	for link
+	do
+	  linknames="$linknames $link"
+	done
+
+	# Use standard objects if they are pic
+	test -z "$pic_flag" && libobjs=`$ECHO "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+	test "X$libobjs" = "X " && libobjs=
+
+	delfiles=
+	if test -n "$export_symbols" && test -n "$include_expsyms"; then
+	  $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp"
+	  export_symbols="$output_objdir/$libname.uexp"
+	  delfiles="$delfiles $export_symbols"
+	fi
+
+	orig_export_symbols=
+	case $host_os in
+	cygwin* | mingw*)
+	  if test -n "$export_symbols" && test -z "$export_symbols_regex"; then
+	    # exporting using user supplied symfile
+	    if test "x`$SED 1q $export_symbols`" != xEXPORTS; then
+	      # and it's NOT already a .def file. Must figure out
+	      # which of the given symbols are data symbols and tag
+	      # them as such. So, trigger use of export_symbols_cmds.
+	      # export_symbols gets reassigned inside the "prepare
+	      # the list of exported symbols" if statement, so the
+	      # include_expsyms logic still works.
+	      orig_export_symbols="$export_symbols"
+	      export_symbols=
+	      always_export_symbols=yes
+	    fi
+	  fi
+	  ;;
+	esac
+
+	# Prepare the list of exported symbols
+	if test -z "$export_symbols"; then
+	  if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
+	    func_verbose "generating symbol list for \`$libname.la'"
+	    export_symbols="$output_objdir/$libname.exp"
+	    $opt_dry_run || $RM $export_symbols
+	    cmds=$export_symbols_cmds
+	    save_ifs="$IFS"; IFS='~'
+	    for cmd in $cmds; do
+	      IFS="$save_ifs"
+	      eval cmd=\"$cmd\"
+	      func_len " $cmd"
+	      len=$func_len_result
+	      if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+		func_show_eval "$cmd" 'exit $?'
+		skipped_export=false
+	      else
+		# The command line is too long to execute in one step.
+		func_verbose "using reloadable object file for export list..."
+		skipped_export=:
+		# Break out early, otherwise skipped_export may be
+		# set to false by a later but shorter cmd.
+		break
+	      fi
+	    done
+	    IFS="$save_ifs"
+	    if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then
+	      func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+	      func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
+	    fi
+	  fi
+	fi
+
+	if test -n "$export_symbols" && test -n "$include_expsyms"; then
+	  tmp_export_symbols="$export_symbols"
+	  test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols"
+	  $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"'
+	fi
+
+	if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then
+	  # The given exports_symbols file has to be filtered, so filter it.
+	  func_verbose "filter symbol list for \`$libname.la' to tag DATA exports"
+	  # FIXME: $output_objdir/$libname.filter potentially contains lots of
+	  # 's' commands which not all seds can handle. GNU sed should be fine
+	  # though. Also, the filter scales superlinearly with the number of
+	  # global variables. join(1) would be nice here, but unfortunately
+	  # isn't a blessed tool.
+	  $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
+	  delfiles="$delfiles $export_symbols $output_objdir/$libname.filter"
+	  export_symbols=$output_objdir/$libname.def
+	  $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
+	fi
+
+	tmp_deplibs=
+	for test_deplib in $deplibs; do
+	  case " $convenience " in
+	  *" $test_deplib "*) ;;
+	  *)
+	    tmp_deplibs="$tmp_deplibs $test_deplib"
+	    ;;
+	  esac
+	done
+	deplibs="$tmp_deplibs"
+
+	if test -n "$convenience"; then
+	  if test -n "$whole_archive_flag_spec" &&
+	    test "$compiler_needs_object" = yes &&
+	    test -z "$libobjs"; then
+	    # extract the archives, so we have objects to list.
+	    # TODO: could optimize this to just extract one archive.
+	    whole_archive_flag_spec=
+	  fi
+	  if test -n "$whole_archive_flag_spec"; then
+	    save_libobjs=$libobjs
+	    eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+	    test "X$libobjs" = "X " && libobjs=
+	  else
+	    gentop="$output_objdir/${outputname}x"
+	    generated="$generated $gentop"
+
+	    func_extract_archives $gentop $convenience
+	    libobjs="$libobjs $func_extract_archives_result"
+	    test "X$libobjs" = "X " && libobjs=
+	  fi
+	fi
+
+	if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
+	  eval flag=\"$thread_safe_flag_spec\"
+	  linker_flags="$linker_flags $flag"
+	fi
+
+	# Make a backup of the uninstalled library when relinking
+	if test "$mode" = relink; then
+	  $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $?
+	fi
+
+	# Do each of the archive commands.
+	if test "$module" = yes && test -n "$module_cmds" ; then
+	  if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+	    eval test_cmds=\"$module_expsym_cmds\"
+	    cmds=$module_expsym_cmds
+	  else
+	    eval test_cmds=\"$module_cmds\"
+	    cmds=$module_cmds
+	  fi
+	else
+	  if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+	    eval test_cmds=\"$archive_expsym_cmds\"
+	    cmds=$archive_expsym_cmds
+	  else
+	    eval test_cmds=\"$archive_cmds\"
+	    cmds=$archive_cmds
+	  fi
+	fi
+
+	if test "X$skipped_export" != "X:" &&
+	   func_len " $test_cmds" &&
+	   len=$func_len_result &&
+	   test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+	  :
+	else
+	  # The command line is too long to link in one step, link piecewise
+	  # or, if using GNU ld and skipped_export is not :, use a linker
+	  # script.
+
+	  # Save the value of $output and $libobjs because we want to
+	  # use them later.  If we have whole_archive_flag_spec, we
+	  # want to use save_libobjs as it was before
+	  # whole_archive_flag_spec was expanded, because we can't
+	  # assume the linker understands whole_archive_flag_spec.
+	  # This may have to be revisited, in case too many
+	  # convenience libraries get linked in and end up exceeding
+	  # the spec.
+	  if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
+	    save_libobjs=$libobjs
+	  fi
+	  save_output=$output
+	  output_la=`$ECHO "X$output" | $Xsed -e "$basename"`
+
+	  # Clear the reloadable object creation command queue and
+	  # initialize k to one.
+	  test_cmds=
+	  concat_cmds=
+	  objlist=
+	  last_robj=
+	  k=1
+
+	  if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then
+	    output=${output_objdir}/${output_la}.lnkscript
+	    func_verbose "creating GNU ld script: $output"
+	    $ECHO 'INPUT (' > $output
+	    for obj in $save_libobjs
+	    do
+	      $ECHO "$obj" >> $output
+	    done
+	    $ECHO ')' >> $output
+	    delfiles="$delfiles $output"
+	  elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then
+	    output=${output_objdir}/${output_la}.lnk
+	    func_verbose "creating linker input file list: $output"
+	    : > $output
+	    set x $save_libobjs
+	    shift
+	    firstobj=
+	    if test "$compiler_needs_object" = yes; then
+	      firstobj="$1 "
+	      shift
+	    fi
+	    for obj
+	    do
+	      $ECHO "$obj" >> $output
+	    done
+	    delfiles="$delfiles $output"
+	    output=$firstobj\"$file_list_spec$output\"
+	  else
+	    if test -n "$save_libobjs"; then
+	      func_verbose "creating reloadable object files..."
+	      output=$output_objdir/$output_la-${k}.$objext
+	      eval test_cmds=\"$reload_cmds\"
+	      func_len " $test_cmds"
+	      len0=$func_len_result
+	      len=$len0
+
+	      # Loop over the list of objects to be linked.
+	      for obj in $save_libobjs
+	      do
+		func_len " $obj"
+		func_arith $len + $func_len_result
+		len=$func_arith_result
+		if test "X$objlist" = X ||
+		   test "$len" -lt "$max_cmd_len"; then
+		  func_append objlist " $obj"
+		else
+		  # The command $test_cmds is almost too long, add a
+		  # command to the queue.
+		  if test "$k" -eq 1 ; then
+		    # The first file doesn't have a previous command to add.
+		    eval concat_cmds=\"$reload_cmds $objlist $last_robj\"
+		  else
+		    # All subsequent reloadable object files will link in
+		    # the last one created.
+		    eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj~\$RM $last_robj\"
+		  fi
+		  last_robj=$output_objdir/$output_la-${k}.$objext
+		  func_arith $k + 1
+		  k=$func_arith_result
+		  output=$output_objdir/$output_la-${k}.$objext
+		  objlist=$obj
+		  func_len " $last_robj"
+		  func_arith $len0 + $func_len_result
+		  len=$func_arith_result
+		fi
+	      done
+	      # Handle the remaining objects by creating one last
+	      # reloadable object file.  All subsequent reloadable object
+	      # files will link in the last one created.
+	      test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+	      eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\"
+	      if test -n "$last_robj"; then
+	        eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\"
+	      fi
+	      delfiles="$delfiles $output"
+
+	    else
+	      output=
+	    fi
+
+	    if ${skipped_export-false}; then
+	      func_verbose "generating symbol list for \`$libname.la'"
+	      export_symbols="$output_objdir/$libname.exp"
+	      $opt_dry_run || $RM $export_symbols
+	      libobjs=$output
+	      # Append the command to create the export file.
+	      test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+	      eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\"
+	      if test -n "$last_robj"; then
+		eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\"
+	      fi
+	    fi
+
+	    test -n "$save_libobjs" &&
+	      func_verbose "creating a temporary reloadable object file: $output"
+
+	    # Loop through the commands generated above and execute them.
+	    save_ifs="$IFS"; IFS='~'
+	    for cmd in $concat_cmds; do
+	      IFS="$save_ifs"
+	      $opt_silent || {
+		  func_quote_for_expand "$cmd"
+		  eval "func_echo $func_quote_for_expand_result"
+	      }
+	      $opt_dry_run || eval "$cmd" || {
+		lt_exit=$?
+
+		# Restore the uninstalled library and exit
+		if test "$mode" = relink; then
+		  ( cd "$output_objdir" && \
+		    $RM "${realname}T" && \
+		    $MV "${realname}U" "$realname" )
+		fi
+
+		exit $lt_exit
+	      }
+	    done
+	    IFS="$save_ifs"
+
+	    if test -n "$export_symbols_regex" && ${skipped_export-false}; then
+	      func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+	      func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
+	    fi
+	  fi
+
+          if ${skipped_export-false}; then
+	    if test -n "$export_symbols" && test -n "$include_expsyms"; then
+	      tmp_export_symbols="$export_symbols"
+	      test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols"
+	      $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"'
+	    fi
+
+	    if test -n "$orig_export_symbols"; then
+	      # The given exports_symbols file has to be filtered, so filter it.
+	      func_verbose "filter symbol list for \`$libname.la' to tag DATA exports"
+	      # FIXME: $output_objdir/$libname.filter potentially contains lots of
+	      # 's' commands which not all seds can handle. GNU sed should be fine
+	      # though. Also, the filter scales superlinearly with the number of
+	      # global variables. join(1) would be nice here, but unfortunately
+	      # isn't a blessed tool.
+	      $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
+	      delfiles="$delfiles $export_symbols $output_objdir/$libname.filter"
+	      export_symbols=$output_objdir/$libname.def
+	      $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
+	    fi
+	  fi
+
+	  libobjs=$output
+	  # Restore the value of output.
+	  output=$save_output
+
+	  if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
+	    eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+	    test "X$libobjs" = "X " && libobjs=
+	  fi
+	  # Expand the library linking commands again to reset the
+	  # value of $libobjs for piecewise linking.
+
+	  # Do each of the archive commands.
+	  if test "$module" = yes && test -n "$module_cmds" ; then
+	    if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+	      cmds=$module_expsym_cmds
+	    else
+	      cmds=$module_cmds
+	    fi
+	  else
+	    if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+	      cmds=$archive_expsym_cmds
+	    else
+	      cmds=$archive_cmds
+	    fi
+	  fi
+	fi
+
+	if test -n "$delfiles"; then
+	  # Append the command to remove temporary files to $cmds.
+	  eval cmds=\"\$cmds~\$RM $delfiles\"
+	fi
+
+	# Add any objects from preloaded convenience libraries
+	if test -n "$dlprefiles"; then
+	  gentop="$output_objdir/${outputname}x"
+	  generated="$generated $gentop"
+
+	  func_extract_archives $gentop $dlprefiles
+	  libobjs="$libobjs $func_extract_archives_result"
+	  test "X$libobjs" = "X " && libobjs=
+	fi
+
+	save_ifs="$IFS"; IFS='~'
+	for cmd in $cmds; do
+	  IFS="$save_ifs"
+	  eval cmd=\"$cmd\"
+	  $opt_silent || {
+	    func_quote_for_expand "$cmd"
+	    eval "func_echo $func_quote_for_expand_result"
+	  }
+	  $opt_dry_run || eval "$cmd" || {
+	    lt_exit=$?
+
+	    # Restore the uninstalled library and exit
+	    if test "$mode" = relink; then
+	      ( cd "$output_objdir" && \
+	        $RM "${realname}T" && \
+		$MV "${realname}U" "$realname" )
+	    fi
+
+	    exit $lt_exit
+	  }
+	done
+	IFS="$save_ifs"
+
+	# Restore the uninstalled library and exit
+	if test "$mode" = relink; then
+	  $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $?
+
+	  if test -n "$convenience"; then
+	    if test -z "$whole_archive_flag_spec"; then
+	      func_show_eval '${RM}r "$gentop"'
+	    fi
+	  fi
+
+	  exit $EXIT_SUCCESS
+	fi
+
+	# Create links to the real library.
+	for linkname in $linknames; do
+	  if test "$realname" != "$linkname"; then
+	    func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?'
+	  fi
+	done
+
+	# If -module or -export-dynamic was specified, set the dlname.
+	if test "$module" = yes || test "$export_dynamic" = yes; then
+	  # On all known operating systems, these are identical.
+	  dlname="$soname"
+	fi
+      fi
+      ;;
+
+    obj)
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+	func_warning "\`-dlopen' is ignored for objects"
+      fi
+
+      case " $deplibs" in
+      *\ -l* | *\ -L*)
+	func_warning "\`-l' and \`-L' are ignored for objects" ;;
+      esac
+
+      test -n "$rpath" && \
+	func_warning "\`-rpath' is ignored for objects"
+
+      test -n "$xrpath" && \
+	func_warning "\`-R' is ignored for objects"
+
+      test -n "$vinfo" && \
+	func_warning "\`-version-info' is ignored for objects"
+
+      test -n "$release" && \
+	func_warning "\`-release' is ignored for objects"
+
+      case $output in
+      *.lo)
+	test -n "$objs$old_deplibs" && \
+	  func_fatal_error "cannot build library object \`$output' from non-libtool objects"
+
+	libobj=$output
+	func_lo2o "$libobj"
+	obj=$func_lo2o_result
+	;;
+      *)
+	libobj=
+	obj="$output"
+	;;
+      esac
+
+      # Delete the old objects.
+      $opt_dry_run || $RM $obj $libobj
+
+      # Objects from convenience libraries.  This assumes
+      # single-version convenience libraries.  Whenever we create
+      # different ones for PIC/non-PIC, this we'll have to duplicate
+      # the extraction.
+      reload_conv_objs=
+      gentop=
+      # reload_cmds runs $LD directly, so let us get rid of
+      # -Wl from whole_archive_flag_spec and hope we can get by with
+      # turning comma into space..
+      wl=
+
+      if test -n "$convenience"; then
+	if test -n "$whole_archive_flag_spec"; then
+	  eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\"
+	  reload_conv_objs=$reload_objs\ `$ECHO "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'`
+	else
+	  gentop="$output_objdir/${obj}x"
+	  generated="$generated $gentop"
+
+	  func_extract_archives $gentop $convenience
+	  reload_conv_objs="$reload_objs $func_extract_archives_result"
+	fi
+      fi
+
+      # Create the old-style object.
+      reload_objs="$objs$old_deplibs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
+
+      output="$obj"
+      func_execute_cmds "$reload_cmds" 'exit $?'
+
+      # Exit if we aren't doing a library object file.
+      if test -z "$libobj"; then
+	if test -n "$gentop"; then
+	  func_show_eval '${RM}r "$gentop"'
+	fi
+
+	exit $EXIT_SUCCESS
+      fi
+
+      if test "$build_libtool_libs" != yes; then
+	if test -n "$gentop"; then
+	  func_show_eval '${RM}r "$gentop"'
+	fi
+
+	# Create an invalid libtool object if no PIC, so that we don't
+	# accidentally link it into a program.
+	# $show "echo timestamp > $libobj"
+	# $opt_dry_run || eval "echo timestamp > $libobj" || exit $?
+	exit $EXIT_SUCCESS
+      fi
+
+      if test -n "$pic_flag" || test "$pic_mode" != default; then
+	# Only do commands if we really have different PIC objects.
+	reload_objs="$libobjs $reload_conv_objs"
+	output="$libobj"
+	func_execute_cmds "$reload_cmds" 'exit $?'
+      fi
+
+      if test -n "$gentop"; then
+	func_show_eval '${RM}r "$gentop"'
+      fi
+
+      exit $EXIT_SUCCESS
+      ;;
+
+    prog)
+      case $host in
+	*cygwin*) func_stripname '' '.exe' "$output"
+	          output=$func_stripname_result.exe;;
+      esac
+      test -n "$vinfo" && \
+	func_warning "\`-version-info' is ignored for programs"
+
+      test -n "$release" && \
+	func_warning "\`-release' is ignored for programs"
+
+      test "$preload" = yes \
+        && test "$dlopen_support" = unknown \
+	&& test "$dlopen_self" = unknown \
+	&& test "$dlopen_self_static" = unknown && \
+	  func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support."
+
+      case $host in
+      *-*-rhapsody* | *-*-darwin1.[012])
+	# On Rhapsody replace the C library is the System framework
+	compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'`
+	finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'`
+	;;
+      esac
+
+      case $host in
+      *-*-darwin*)
+	# Don't allow lazy linking, it breaks C++ global constructors
+	# But is supposedly fixed on 10.4 or later (yay!).
+	if test "$tagname" = CXX ; then
+	  case ${MACOSX_DEPLOYMENT_TARGET-10.0} in
+	    10.[0123])
+	      compile_command="$compile_command ${wl}-bind_at_load"
+	      finalize_command="$finalize_command ${wl}-bind_at_load"
+	    ;;
+	  esac
+	fi
+	# Time to change all our "foo.ltframework" stuff back to "-framework foo"
+	compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+	finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+	;;
+      esac
+
+
+      # move library search paths that coincide with paths to not yet
+      # installed libraries to the beginning of the library search list
+      new_libs=
+      for path in $notinst_path; do
+	case " $new_libs " in
+	*" -L$path/$objdir "*) ;;
+	*)
+	  case " $compile_deplibs " in
+	  *" -L$path/$objdir "*)
+	    new_libs="$new_libs -L$path/$objdir" ;;
+	  esac
+	  ;;
+	esac
+      done
+      for deplib in $compile_deplibs; do
+	case $deplib in
+	-L*)
+	  case " $new_libs " in
+	  *" $deplib "*) ;;
+	  *) new_libs="$new_libs $deplib" ;;
+	  esac
+	  ;;
+	*) new_libs="$new_libs $deplib" ;;
+	esac
+      done
+      compile_deplibs="$new_libs"
+
+
+      compile_command="$compile_command $compile_deplibs"
+      finalize_command="$finalize_command $finalize_deplibs"
+
+      if test -n "$rpath$xrpath"; then
+	# If the user specified any rpath flags, then add them.
+	for libdir in $rpath $xrpath; do
+	  # This is the magic to use -rpath.
+	  case "$finalize_rpath " in
+	  *" $libdir "*) ;;
+	  *) finalize_rpath="$finalize_rpath $libdir" ;;
+	  esac
+	done
+      fi
+
+      # Now hardcode the library paths
+      rpath=
+      hardcode_libdirs=
+      for libdir in $compile_rpath $finalize_rpath; do
+	if test -n "$hardcode_libdir_flag_spec"; then
+	  if test -n "$hardcode_libdir_separator"; then
+	    if test -z "$hardcode_libdirs"; then
+	      hardcode_libdirs="$libdir"
+	    else
+	      # Just accumulate the unique libdirs.
+	      case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+	      *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+		;;
+	      *)
+		hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+		;;
+	      esac
+	    fi
+	  else
+	    eval flag=\"$hardcode_libdir_flag_spec\"
+	    rpath="$rpath $flag"
+	  fi
+	elif test -n "$runpath_var"; then
+	  case "$perm_rpath " in
+	  *" $libdir "*) ;;
+	  *) perm_rpath="$perm_rpath $libdir" ;;
+	  esac
+	fi
+	case $host in
+	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+	  testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'`
+	  case :$dllsearchpath: in
+	  *":$libdir:"*) ;;
+	  *) dllsearchpath="$dllsearchpath:$libdir";;
+	  esac
+	  case :$dllsearchpath: in
+	  *":$testbindir:"*) ;;
+	  *) dllsearchpath="$dllsearchpath:$testbindir";;
+	  esac
+	  ;;
+	esac
+      done
+      # Substitute the hardcoded libdirs into the rpath.
+      if test -n "$hardcode_libdir_separator" &&
+	 test -n "$hardcode_libdirs"; then
+	libdir="$hardcode_libdirs"
+	eval rpath=\" $hardcode_libdir_flag_spec\"
+      fi
+      compile_rpath="$rpath"
+
+      rpath=
+      hardcode_libdirs=
+      for libdir in $finalize_rpath; do
+	if test -n "$hardcode_libdir_flag_spec"; then
+	  if test -n "$hardcode_libdir_separator"; then
+	    if test -z "$hardcode_libdirs"; then
+	      hardcode_libdirs="$libdir"
+	    else
+	      # Just accumulate the unique libdirs.
+	      case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+	      *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+		;;
+	      *)
+		hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+		;;
+	      esac
+	    fi
+	  else
+	    eval flag=\"$hardcode_libdir_flag_spec\"
+	    rpath="$rpath $flag"
+	  fi
+	elif test -n "$runpath_var"; then
+	  case "$finalize_perm_rpath " in
+	  *" $libdir "*) ;;
+	  *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;;
+	  esac
+	fi
+      done
+      # Substitute the hardcoded libdirs into the rpath.
+      if test -n "$hardcode_libdir_separator" &&
+	 test -n "$hardcode_libdirs"; then
+	libdir="$hardcode_libdirs"
+	eval rpath=\" $hardcode_libdir_flag_spec\"
+      fi
+      finalize_rpath="$rpath"
+
+      if test -n "$libobjs" && test "$build_old_libs" = yes; then
+	# Transform all the library objects into standard objects.
+	compile_command=`$ECHO "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+	finalize_command=`$ECHO "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+      fi
+
+      func_generate_dlsyms "$outputname" "@PROGRAM@" "no"
+
+      # template prelinking step
+      if test -n "$prelink_cmds"; then
+	func_execute_cmds "$prelink_cmds" 'exit $?'
+      fi
+
+      wrappers_required=yes
+      case $host in
+      *cygwin* | *mingw* )
+        if test "$build_libtool_libs" != yes; then
+          wrappers_required=no
+        fi
+        ;;
+      *)
+        if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
+          wrappers_required=no
+        fi
+        ;;
+      esac
+      if test "$wrappers_required" = no; then
+	# Replace the output file specification.
+	compile_command=`$ECHO "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+	link_command="$compile_command$compile_rpath"
+
+	# We have no uninstalled library dependencies, so finalize right now.
+	exit_status=0
+	func_show_eval "$link_command" 'exit_status=$?'
+
+	# Delete the generated files.
+	if test -f "$output_objdir/${outputname}S.${objext}"; then
+	  func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"'
+	fi
+
+	exit $exit_status
+      fi
+
+      if test -n "$compile_shlibpath$finalize_shlibpath"; then
+	compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
+      fi
+      if test -n "$finalize_shlibpath"; then
+	finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
+      fi
+
+      compile_var=
+      finalize_var=
+      if test -n "$runpath_var"; then
+	if test -n "$perm_rpath"; then
+	  # We should set the runpath_var.
+	  rpath=
+	  for dir in $perm_rpath; do
+	    rpath="$rpath$dir:"
+	  done
+	  compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
+	fi
+	if test -n "$finalize_perm_rpath"; then
+	  # We should set the runpath_var.
+	  rpath=
+	  for dir in $finalize_perm_rpath; do
+	    rpath="$rpath$dir:"
+	  done
+	  finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
+	fi
+      fi
+
+      if test "$no_install" = yes; then
+	# We don't need to create a wrapper script.
+	link_command="$compile_var$compile_command$compile_rpath"
+	# Replace the output file specification.
+	link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+	# Delete the old output file.
+	$opt_dry_run || $RM $output
+	# Link the executable and exit
+	func_show_eval "$link_command" 'exit $?'
+	exit $EXIT_SUCCESS
+      fi
+
+      if test "$hardcode_action" = relink; then
+	# Fast installation is not supported
+	link_command="$compile_var$compile_command$compile_rpath"
+	relink_command="$finalize_var$finalize_command$finalize_rpath"
+
+	func_warning "this platform does not like uninstalled shared libraries"
+	func_warning "\`$output' will be relinked during installation"
+      else
+	if test "$fast_install" != no; then
+	  link_command="$finalize_var$compile_command$finalize_rpath"
+	  if test "$fast_install" = yes; then
+	    relink_command=`$ECHO "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'`
+	  else
+	    # fast_install is set to needless
+	    relink_command=
+	  fi
+	else
+	  link_command="$compile_var$compile_command$compile_rpath"
+	  relink_command="$finalize_var$finalize_command$finalize_rpath"
+	fi
+      fi
+
+      # Replace the output file specification.
+      link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
+
+      # Delete the old output files.
+      $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname
+
+      func_show_eval "$link_command" 'exit $?'
+
+      # Now create the wrapper script.
+      func_verbose "creating $output"
+
+      # Quote the relink command for shipping.
+      if test -n "$relink_command"; then
+	# Preserve any variables that may affect compiler behavior
+	for var in $variables_saved_for_relink; do
+	  if eval test -z \"\${$var+set}\"; then
+	    relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
+	  elif eval var_value=\$$var; test -z "$var_value"; then
+	    relink_command="$var=; export $var; $relink_command"
+	  else
+	    func_quote_for_eval "$var_value"
+	    relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
+	  fi
+	done
+	relink_command="(cd `pwd`; $relink_command)"
+	relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+      fi
+
+      # Quote $ECHO for shipping.
+      if test "X$ECHO" = "X$SHELL $progpath --fallback-echo"; then
+	case $progpath in
+	[\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";;
+	*) qecho="$SHELL `pwd`/$progpath --fallback-echo";;
+	esac
+	qecho=`$ECHO "X$qecho" | $Xsed -e "$sed_quote_subst"`
+      else
+	qecho=`$ECHO "X$ECHO" | $Xsed -e "$sed_quote_subst"`
+      fi
+
+      # Only actually do things if not in dry run mode.
+      $opt_dry_run || {
+	# win32 will think the script is a binary if it has
+	# a .exe suffix, so we strip it off here.
+	case $output in
+	  *.exe) func_stripname '' '.exe' "$output"
+	         output=$func_stripname_result ;;
+	esac
+	# test for cygwin because mv fails w/o .exe extensions
+	case $host in
+	  *cygwin*)
+	    exeext=.exe
+	    func_stripname '' '.exe' "$outputname"
+	    outputname=$func_stripname_result ;;
+	  *) exeext= ;;
+	esac
+	case $host in
+	  *cygwin* | *mingw* )
+	    func_dirname_and_basename "$output" "" "."
+	    output_name=$func_basename_result
+	    output_path=$func_dirname_result
+	    cwrappersource="$output_path/$objdir/lt-$output_name.c"
+	    cwrapper="$output_path/$output_name.exe"
+	    $RM $cwrappersource $cwrapper
+	    trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
+
+	    func_emit_cwrapperexe_src > $cwrappersource
+
+	    # we should really use a build-platform specific compiler
+	    # here, but OTOH, the wrappers (shell script and this C one)
+	    # are only useful if you want to execute the "real" binary.
+	    # Since the "real" binary is built for $host, then this
+	    # wrapper might as well be built for $host, too.
+	    $opt_dry_run || {
+	      $LTCC $LTCFLAGS -o $cwrapper $cwrappersource
+	      $STRIP $cwrapper
+	    }
+
+	    # Now, create the wrapper script for func_source use:
+	    func_ltwrapper_scriptname $cwrapper
+	    $RM $func_ltwrapper_scriptname_result
+	    trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15
+	    $opt_dry_run || {
+	      # note: this script will not be executed, so do not chmod.
+	      if test "x$build" = "x$host" ; then
+		$cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result
+	      else
+		func_emit_wrapper no > $func_ltwrapper_scriptname_result
+	      fi
+	    }
+	  ;;
+	  * )
+	    $RM $output
+	    trap "$RM $output; exit $EXIT_FAILURE" 1 2 15
+
+	    func_emit_wrapper no > $output
+	    chmod +x $output
+	  ;;
+	esac
+      }
+      exit $EXIT_SUCCESS
+      ;;
+    esac
+
+    # See if we need to build an old-fashioned archive.
+    for oldlib in $oldlibs; do
+
+      if test "$build_libtool_libs" = convenience; then
+	oldobjs="$libobjs_save $symfileobj"
+	addlibs="$convenience"
+	build_libtool_libs=no
+      else
+	if test "$build_libtool_libs" = module; then
+	  oldobjs="$libobjs_save"
+	  build_libtool_libs=no
+	else
+	  oldobjs="$old_deplibs $non_pic_objects"
+	  if test "$preload" = yes && test -f "$symfileobj"; then
+	    oldobjs="$oldobjs $symfileobj"
+	  fi
+	fi
+	addlibs="$old_convenience"
+      fi
+
+      if test -n "$addlibs"; then
+	gentop="$output_objdir/${outputname}x"
+	generated="$generated $gentop"
+
+	func_extract_archives $gentop $addlibs
+	oldobjs="$oldobjs $func_extract_archives_result"
+      fi
+
+      # Do each command in the archive commands.
+      if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
+	cmds=$old_archive_from_new_cmds
+      else
+
+	# Add any objects from preloaded convenience libraries
+	if test -n "$dlprefiles"; then
+	  gentop="$output_objdir/${outputname}x"
+	  generated="$generated $gentop"
+
+	  func_extract_archives $gentop $dlprefiles
+	  oldobjs="$oldobjs $func_extract_archives_result"
+	fi
+
+	# POSIX demands no paths to be encoded in archives.  We have
+	# to avoid creating archives with duplicate basenames if we
+	# might have to extract them afterwards, e.g., when creating a
+	# static archive out of a convenience library, or when linking
+	# the entirety of a libtool archive into another (currently
+	# not supported by libtool).
+	if (for obj in $oldobjs
+	    do
+	      func_basename "$obj"
+	      $ECHO "$func_basename_result"
+	    done | sort | sort -uc >/dev/null 2>&1); then
+	  :
+	else
+	  $ECHO "copying selected object files to avoid basename conflicts..."
+	  gentop="$output_objdir/${outputname}x"
+	  generated="$generated $gentop"
+	  func_mkdir_p "$gentop"
+	  save_oldobjs=$oldobjs
+	  oldobjs=
+	  counter=1
+	  for obj in $save_oldobjs
+	  do
+	    func_basename "$obj"
+	    objbase="$func_basename_result"
+	    case " $oldobjs " in
+	    " ") oldobjs=$obj ;;
+	    *[\ /]"$objbase "*)
+	      while :; do
+		# Make sure we don't pick an alternate name that also
+		# overlaps.
+		newobj=lt$counter-$objbase
+		func_arith $counter + 1
+		counter=$func_arith_result
+		case " $oldobjs " in
+		*[\ /]"$newobj "*) ;;
+		*) if test ! -f "$gentop/$newobj"; then break; fi ;;
+		esac
+	      done
+	      func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
+	      oldobjs="$oldobjs $gentop/$newobj"
+	      ;;
+	    *) oldobjs="$oldobjs $obj" ;;
+	    esac
+	  done
+	fi
+	eval cmds=\"$old_archive_cmds\"
+
+	func_len " $cmds"
+	len=$func_len_result
+	if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+	  cmds=$old_archive_cmds
+	else
+	  # the command line is too long to link in one step, link in parts
+	  func_verbose "using piecewise archive linking..."
+	  save_RANLIB=$RANLIB
+	  RANLIB=:
+	  objlist=
+	  concat_cmds=
+	  save_oldobjs=$oldobjs
+	  oldobjs=
+	  # Is there a better way of finding the last object in the list?
+	  for obj in $save_oldobjs
+	  do
+	    last_oldobj=$obj
+	  done
+	  eval test_cmds=\"$old_archive_cmds\"
+	  func_len " $test_cmds"
+	  len0=$func_len_result
+	  len=$len0
+	  for obj in $save_oldobjs
+	  do
+	    func_len " $obj"
+	    func_arith $len + $func_len_result
+	    len=$func_arith_result
+	    func_append objlist " $obj"
+	    if test "$len" -lt "$max_cmd_len"; then
+	      :
+	    else
+	      # the above command should be used before it gets too long
+	      oldobjs=$objlist
+	      if test "$obj" = "$last_oldobj" ; then
+		RANLIB=$save_RANLIB
+	      fi
+	      test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+	      eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\"
+	      objlist=
+	      len=$len0
+	    fi
+	  done
+	  RANLIB=$save_RANLIB
+	  oldobjs=$objlist
+	  if test "X$oldobjs" = "X" ; then
+	    eval cmds=\"\$concat_cmds\"
+	  else
+	    eval cmds=\"\$concat_cmds~\$old_archive_cmds\"
+	  fi
+	fi
+      fi
+      func_execute_cmds "$cmds" 'exit $?'
+    done
+
+    test -n "$generated" && \
+      func_show_eval "${RM}r$generated"
+
+    # Now create the libtool archive.
+    case $output in
+    *.la)
+      old_library=
+      test "$build_old_libs" = yes && old_library="$libname.$libext"
+      func_verbose "creating $output"
+
+      # Preserve any variables that may affect compiler behavior
+      for var in $variables_saved_for_relink; do
+	if eval test -z \"\${$var+set}\"; then
+	  relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
+	elif eval var_value=\$$var; test -z "$var_value"; then
+	  relink_command="$var=; export $var; $relink_command"
+	else
+	  func_quote_for_eval "$var_value"
+	  relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
+	fi
+      done
+      # Quote the link command for shipping.
+      relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
+      relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+      if test "$hardcode_automatic" = yes ; then
+	relink_command=
+      fi
+
+      # Only create the output if not a dry run.
+      $opt_dry_run || {
+	for installed in no yes; do
+	  if test "$installed" = yes; then
+	    if test -z "$install_libdir"; then
+	      break
+	    fi
+	    output="$output_objdir/$outputname"i
+	    # Replace all uninstalled libtool libraries with the installed ones
+	    newdependency_libs=
+	    for deplib in $dependency_libs; do
+	      case $deplib in
+	      *.la)
+		func_basename "$deplib"
+		name="$func_basename_result"
+		eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+		test -z "$libdir" && \
+		  func_fatal_error "\`$deplib' is not a valid libtool archive"
+		newdependency_libs="$newdependency_libs $libdir/$name"
+		;;
+	      *) newdependency_libs="$newdependency_libs $deplib" ;;
+	      esac
+	    done
+	    dependency_libs="$newdependency_libs"
+	    newdlfiles=
+
+	    for lib in $dlfiles; do
+	      case $lib in
+	      *.la)
+	        func_basename "$lib"
+		name="$func_basename_result"
+		eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+		test -z "$libdir" && \
+		  func_fatal_error "\`$lib' is not a valid libtool archive"
+		newdlfiles="$newdlfiles $libdir/$name"
+		;;
+	      *) newdlfiles="$newdlfiles $lib" ;;
+	      esac
+	    done
+	    dlfiles="$newdlfiles"
+	    newdlprefiles=
+	    for lib in $dlprefiles; do
+	      case $lib in
+	      *.la)
+		# Only pass preopened files to the pseudo-archive (for
+		# eventual linking with the app. that links it) if we
+		# didn't already link the preopened objects directly into
+		# the library:
+		func_basename "$lib"
+		name="$func_basename_result"
+		eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+		test -z "$libdir" && \
+		  func_fatal_error "\`$lib' is not a valid libtool archive"
+		newdlprefiles="$newdlprefiles $libdir/$name"
+		;;
+	      esac
+	    done
+	    dlprefiles="$newdlprefiles"
+	  else
+	    newdlfiles=
+	    for lib in $dlfiles; do
+	      case $lib in
+		[\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+		*) abs=`pwd`"/$lib" ;;
+	      esac
+	      newdlfiles="$newdlfiles $abs"
+	    done
+	    dlfiles="$newdlfiles"
+	    newdlprefiles=
+	    for lib in $dlprefiles; do
+	      case $lib in
+		[\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+		*) abs=`pwd`"/$lib" ;;
+	      esac
+	      newdlprefiles="$newdlprefiles $abs"
+	    done
+	    dlprefiles="$newdlprefiles"
+	  fi
+	  $RM $output
+	  # place dlname in correct position for cygwin
+	  tdlname=$dlname
+	  case $host,$output,$installed,$module,$dlname in
+	    *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;;
+	  esac
+	  $ECHO > $output "\
+# $outputname - a libtool library file
+# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='$tdlname'
+
+# Names of this library.
+library_names='$library_names'
+
+# The name of the static archive.
+old_library='$old_library'
+
+# Linker flags that can not go in dependency_libs.
+inherited_linker_flags='$new_inherited_linker_flags'
+
+# Libraries that this one depends upon.
+dependency_libs='$dependency_libs'
+
+# Names of additional weak libraries provided by this library
+weak_library_names='$weak_libs'
+
+# Version information for $libname.
+current=$current
+age=$age
+revision=$revision
+
+# Is this an already installed library?
+installed=$installed
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=$module
+
+# Files to dlopen/dlpreopen
+dlopen='$dlfiles'
+dlpreopen='$dlprefiles'
+
+# Directory that this library needs to be installed in:
+libdir='$install_libdir'"
+	  if test "$installed" = no && test "$need_relink" = yes; then
+	    $ECHO >> $output "\
+relink_command=\"$relink_command\""
+	  fi
+	done
+      }
+
+      # Do a symbolic link so that the libtool archive can be found in
+      # LD_LIBRARY_PATH before the program is installed.
+      func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?'
+      ;;
+    esac
+    exit $EXIT_SUCCESS
+}
+
+{ test "$mode" = link || test "$mode" = relink; } &&
+    func_mode_link ${1+"$@"}
+
+
+# func_mode_uninstall arg...
+func_mode_uninstall ()
+{
+    $opt_debug
+    RM="$nonopt"
+    files=
+    rmforce=
+    exit_status=0
+
+    # This variable tells wrapper scripts just to set variables rather
+    # than running their programs.
+    libtool_install_magic="$magic"
+
+    for arg
+    do
+      case $arg in
+      -f) RM="$RM $arg"; rmforce=yes ;;
+      -*) RM="$RM $arg" ;;
+      *) files="$files $arg" ;;
+      esac
+    done
+
+    test -z "$RM" && \
+      func_fatal_help "you must specify an RM program"
+
+    rmdirs=
+
+    origobjdir="$objdir"
+    for file in $files; do
+      func_dirname "$file" "" "."
+      dir="$func_dirname_result"
+      if test "X$dir" = X.; then
+	objdir="$origobjdir"
+      else
+	objdir="$dir/$origobjdir"
+      fi
+      func_basename "$file"
+      name="$func_basename_result"
+      test "$mode" = uninstall && objdir="$dir"
+
+      # Remember objdir for removal later, being careful to avoid duplicates
+      if test "$mode" = clean; then
+	case " $rmdirs " in
+	  *" $objdir "*) ;;
+	  *) rmdirs="$rmdirs $objdir" ;;
+	esac
+      fi
+
+      # Don't error if the file doesn't exist and rm -f was used.
+      if { test -L "$file"; } >/dev/null 2>&1 ||
+	 { test -h "$file"; } >/dev/null 2>&1 ||
+	 test -f "$file"; then
+	:
+      elif test -d "$file"; then
+	exit_status=1
+	continue
+      elif test "$rmforce" = yes; then
+	continue
+      fi
+
+      rmfiles="$file"
+
+      case $name in
+      *.la)
+	# Possibly a libtool archive, so verify it.
+	if func_lalib_p "$file"; then
+	  func_source $dir/$name
+
+	  # Delete the libtool libraries and symlinks.
+	  for n in $library_names; do
+	    rmfiles="$rmfiles $objdir/$n"
+	  done
+	  test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library"
+
+	  case "$mode" in
+	  clean)
+	    case "  $library_names " in
+	    # "  " in the beginning catches empty $dlname
+	    *" $dlname "*) ;;
+	    *) rmfiles="$rmfiles $objdir/$dlname" ;;
+	    esac
+	    test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
+	    ;;
+	  uninstall)
+	    if test -n "$library_names"; then
+	      # Do each command in the postuninstall commands.
+	      func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1'
+	    fi
+
+	    if test -n "$old_library"; then
+	      # Do each command in the old_postuninstall commands.
+	      func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1'
+	    fi
+	    # FIXME: should reinstall the best remaining shared library.
+	    ;;
+	  esac
+	fi
+	;;
+
+      *.lo)
+	# Possibly a libtool object, so verify it.
+	if func_lalib_p "$file"; then
+
+	  # Read the .lo file
+	  func_source $dir/$name
+
+	  # Add PIC object to the list of files to remove.
+	  if test -n "$pic_object" &&
+	     test "$pic_object" != none; then
+	    rmfiles="$rmfiles $dir/$pic_object"
+	  fi
+
+	  # Add non-PIC object to the list of files to remove.
+	  if test -n "$non_pic_object" &&
+	     test "$non_pic_object" != none; then
+	    rmfiles="$rmfiles $dir/$non_pic_object"
+	  fi
+	fi
+	;;
+
+      *)
+	if test "$mode" = clean ; then
+	  noexename=$name
+	  case $file in
+	  *.exe)
+	    func_stripname '' '.exe' "$file"
+	    file=$func_stripname_result
+	    func_stripname '' '.exe' "$name"
+	    noexename=$func_stripname_result
+	    # $file with .exe has already been added to rmfiles,
+	    # add $file without .exe
+	    rmfiles="$rmfiles $file"
+	    ;;
+	  esac
+	  # Do a test to see if this is a libtool program.
+	  if func_ltwrapper_p "$file"; then
+	    if func_ltwrapper_executable_p "$file"; then
+	      func_ltwrapper_scriptname "$file"
+	      relink_command=
+	      func_source $func_ltwrapper_scriptname_result
+	      rmfiles="$rmfiles $func_ltwrapper_scriptname_result"
+	    else
+	      relink_command=
+	      func_source $dir/$noexename
+	    fi
+
+	    # note $name still contains .exe if it was in $file originally
+	    # as does the version of $file that was added into $rmfiles
+	    rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}"
+	    if test "$fast_install" = yes && test -n "$relink_command"; then
+	      rmfiles="$rmfiles $objdir/lt-$name"
+	    fi
+	    if test "X$noexename" != "X$name" ; then
+	      rmfiles="$rmfiles $objdir/lt-${noexename}.c"
+	    fi
+	  fi
+	fi
+	;;
+      esac
+      func_show_eval "$RM $rmfiles" 'exit_status=1'
+    done
+    objdir="$origobjdir"
+
+    # Try to remove the ${objdir}s in the directories where we deleted files
+    for dir in $rmdirs; do
+      if test -d "$dir"; then
+	func_show_eval "rmdir $dir >/dev/null 2>&1"
+      fi
+    done
+
+    exit $exit_status
+}
+
+{ test "$mode" = uninstall || test "$mode" = clean; } &&
+    func_mode_uninstall ${1+"$@"}
+
+test -z "$mode" && {
+  help="$generic_help"
+  func_fatal_help "you must specify a MODE"
+}
+
+test -z "$exec_cmd" && \
+  func_fatal_help "invalid operation mode \`$mode'"
+
+if test -n "$exec_cmd"; then
+  eval exec "$exec_cmd"
+  exit $EXIT_FAILURE
+fi
+
+exit $exit_status
+
+
+# The TAGs below are defined such that we never get into a situation
+# in which we disable both kinds of libraries.  Given conflicting
+# choices, we go for a static library, that is the most portable,
+# since we can't tell whether shared libraries were disabled because
+# the user asked for that or because the platform doesn't support
+# them.  This is particularly important on AIX, because we don't
+# support having both static and shared libraries enabled at the same
+# time on that platform, so we default to a shared-only configuration.
+# If a disable-shared tag is given, we'll fallback to a static-only
+# configuration.  But we'll never go from static-only to shared-only.
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
+build_libtool_libs=no
+build_old_libs=yes
+# ### END LIBTOOL TAG CONFIG: disable-shared
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-static
+build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac`
+# ### END LIBTOOL TAG CONFIG: disable-static
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
+# vi:sw=2
+
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/macho.c b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/macho.c
new file mode 100644
index 0000000..b43ea22
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/macho.c
@@ -0,0 +1,1418 @@
+/* macho.c -- Get debug data from an Mach-O file for backtraces.
+   Copyright (C) 2012-2016 Free Software Foundation, Inc.
+   Written by John Colanduoni.
+
+   Pending upstream pull request:
+   https://github.com/ianlancetaylor/libbacktrace/pull/2
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+/* We can't use autotools to detect the pointer width of our program because
+   we may be building a fat Mach-O file containing both 32-bit and 64-bit
+   variants. However Mach-O runs a limited set of platforms so detection
+   via preprocessor is not difficult.  */
+
+#if defined(__MACH__)
+#if defined(__LP64__)
+#define BACKTRACE_BITS 64
+#else
+#define BACKTRACE_BITS 32
+#endif
+#else
+#error Attempting to build Mach-O support on incorrect platform
+#endif
+
+#if defined(__x86_64__)
+#define NATIVE_CPU_TYPE CPU_TYPE_X86_64
+#elif defined(__i386__)
+#define NATIVE_CPU_TYPE CPU_TYPE_X86
+#elif defined(__aarch64__)
+#define NATIVE_CPU_TYPE CPU_TYPE_ARM64
+#elif defined(__arm__)
+#define NATIVE_CPU_TYPE CPU_TYPE_ARM
+#else
+#error Could not detect native Mach-O cpu_type_t
+#endif
+
+#include <sys/types.h>
+#include <sys/syslimits.h>
+#include <string.h>
+#include <mach-o/loader.h>
+#include <mach-o/nlist.h>
+#include <mach-o/fat.h>
+#include <mach-o/dyld.h>
+#include <uuid/uuid.h>
+#include <dirent.h>
+#include <stdlib.h>
+
+#include "backtrace.h"
+#include "internal.h"
+
+struct macho_commands_view
+{
+    struct backtrace_view view;
+    uint32_t commands_count;
+    uint32_t commands_total_size;
+    int bytes_swapped;
+    size_t base_offset;
+};
+
+enum debug_section
+{
+    DEBUG_INFO,
+    DEBUG_LINE,
+    DEBUG_ABBREV,
+    DEBUG_RANGES,
+    DEBUG_STR,
+    DEBUG_MAX
+};
+
+static const char *const debug_section_names[DEBUG_MAX] =
+    {
+        "__debug_info",
+        "__debug_line",
+        "__debug_abbrev",
+        "__debug_ranges",
+        "__debug_str"
+    };
+
+struct found_dwarf_section
+{
+    uint32_t file_offset;
+    uintptr_t file_size;
+    const unsigned char *data;
+};
+
+/* Mach-O symbols don't have a length. As a result we have to infer it
+   by sorting the symbol addresses for each image and recording the
+   memory range attributed to each image.  */
+struct macho_symbol
+{
+    uintptr_t addr;
+    size_t size;
+    const char *name;
+};
+
+struct macho_syminfo_data
+{
+    struct macho_syminfo_data *next;
+    struct macho_symbol *symbols;
+    size_t symbol_count;
+    uintptr_t min_addr;
+    uintptr_t max_addr;
+};
+
+uint16_t
+macho_file_to_host_u16 (int file_bytes_swapped, uint16_t input)
+{
+  if (file_bytes_swapped)
+    return (input >> 8) | (input << 8);
+  else
+    return input;
+}
+
+uint32_t
+macho_file_to_host_u32 (int file_bytes_swapped, uint32_t input)
+{
+  if (file_bytes_swapped)
+    {
+      return ((input >> 24) & 0x000000FF)
+             | ((input >> 8) & 0x0000FF00)
+             | ((input << 8) & 0x00FF0000)
+             | ((input << 24) & 0xFF000000);
+    }
+  else
+    {
+      return input;
+    }
+}
+
+uint64_t
+macho_file_to_host_u64 (int file_bytes_swapped, uint64_t input)
+{
+  if (file_bytes_swapped)
+    {
+      return macho_file_to_host_u32 (file_bytes_swapped,
+                                     (uint32_t) (input >> 32))
+             | (((uint64_t) macho_file_to_host_u32 (file_bytes_swapped,
+                                                    (uint32_t) input)) << 32);
+    }
+  else
+    {
+      return input;
+    }
+}
+
+#if BACKTRACE_BITS == 64
+#define macho_file_to_host_usize macho_file_to_host_u64
+typedef struct mach_header_64 mach_header_native_t;
+#define LC_SEGMENT_NATIVE LC_SEGMENT_64
+typedef struct segment_command_64 segment_command_native_t;
+typedef struct nlist_64 nlist_native_t;
+typedef struct section_64 section_native_t;
+#else /* BACKTRACE_BITS == 32 */
+#define macho_file_to_host_usize macho_file_to_host_u32
+typedef struct mach_header mach_header_native_t;
+#define LC_SEGMENT_NATIVE LC_SEGMENT
+typedef struct segment_command segment_command_native_t;
+typedef struct nlist nlist_native_t;
+typedef struct section section_native_t;
+#endif
+
+// Gets a view into a Mach-O image, taking any slice offset into account
+int
+macho_get_view (struct backtrace_state *state, int descriptor,
+                off_t offset, size_t size,
+                backtrace_error_callback error_callback,
+                void *data, struct macho_commands_view *commands_view,
+                struct backtrace_view *view)
+{
+  return backtrace_get_view (state, descriptor,
+                             commands_view->base_offset + offset, size,
+                             error_callback, data, view);
+}
+
+int
+macho_get_commands (struct backtrace_state *state, int descriptor,
+                    backtrace_error_callback error_callback,
+                    void *data, struct macho_commands_view *commands_view,
+                    int *incompatible)
+{
+  int ret = 0;
+  int is_fat = 0;
+  struct backtrace_view file_header_view;
+  int file_header_view_valid = 0;
+  struct backtrace_view fat_archs_view;
+  int fat_archs_view_valid = 0;
+  const mach_header_native_t *file_header;
+  uint64_t commands_offset;
+
+  *incompatible = 0;
+
+  if (!backtrace_get_view (state, descriptor, 0, sizeof (mach_header_native_t),
+                           error_callback, data, &file_header_view))
+    goto end;
+  file_header_view_valid = 1;
+
+  switch (*(uint32_t *) file_header_view.data)
+    {
+      case MH_MAGIC:
+        if (BACKTRACE_BITS == 32)
+          commands_view->bytes_swapped = 0;
+        else
+          {
+            *incompatible = 1;
+            goto end;
+          }
+      break;
+      case MH_CIGAM:
+        if (BACKTRACE_BITS == 32)
+          commands_view->bytes_swapped = 1;
+        else
+          {
+            *incompatible = 1;
+            goto end;
+          }
+      break;
+      case MH_MAGIC_64:
+        if (BACKTRACE_BITS == 64)
+          commands_view->bytes_swapped = 0;
+        else
+          {
+            *incompatible = 1;
+            goto end;
+          }
+      break;
+      case MH_CIGAM_64:
+        if (BACKTRACE_BITS == 64)
+          commands_view->bytes_swapped = 1;
+        else
+          {
+            *incompatible = 1;
+            goto end;
+          }
+      break;
+      case FAT_MAGIC:
+        is_fat = 1;
+        commands_view->bytes_swapped = 0;
+      break;
+      case FAT_CIGAM:
+        is_fat = 1;
+        commands_view->bytes_swapped = 1;
+      break;
+      default:
+        goto end;
+    }
+
+  if (is_fat)
+    {
+      uint32_t native_slice_offset;
+      size_t archs_total_size;
+      uint32_t arch_count;
+      const struct fat_header *fat_header;
+      const struct fat_arch *archs;
+      uint32_t i;
+
+      fat_header = file_header_view.data;
+      arch_count =
+          macho_file_to_host_u32 (commands_view->bytes_swapped,
+                                  fat_header->nfat_arch);
+
+      archs_total_size = arch_count * sizeof (struct fat_arch);
+
+      if (!backtrace_get_view (state, descriptor, sizeof (struct fat_header),
+                               archs_total_size, error_callback,
+                               data, &fat_archs_view))
+        goto end;
+      fat_archs_view_valid = 1;
+
+      native_slice_offset = 0;
+      archs = fat_archs_view.data;
+      for (i = 0; i < arch_count; i++)
+        {
+          const struct fat_arch *raw_arch = archs + i;
+          int cpu_type =
+              (int) macho_file_to_host_u32 (commands_view->bytes_swapped,
+                                            (uint32_t) raw_arch->cputype);
+
+          if (cpu_type == NATIVE_CPU_TYPE)
+            {
+              native_slice_offset =
+                  macho_file_to_host_u32 (commands_view->bytes_swapped,
+                                          raw_arch->offset);
+
+              break;
+            }
+        }
+
+      if (native_slice_offset == 0)
+        {
+          *incompatible = 1;
+          goto end;
+        }
+
+      backtrace_release_view (state, &file_header_view, error_callback, data);
+      file_header_view_valid = 0;
+      if (!backtrace_get_view (state, descriptor, native_slice_offset,
+                               sizeof (mach_header_native_t), error_callback,
+                               data, &file_header_view))
+        goto end;
+      file_header_view_valid = 1;
+
+      // The endianess of the slice may be different than the fat image
+      switch (*(uint32_t *) file_header_view.data)
+        {
+          case MH_MAGIC:
+            if (BACKTRACE_BITS == 32)
+              commands_view->bytes_swapped = 0;
+            else
+              goto end;
+          break;
+          case MH_CIGAM:
+            if (BACKTRACE_BITS == 32)
+              commands_view->bytes_swapped = 1;
+            else
+              goto end;
+          break;
+          case MH_MAGIC_64:
+            if (BACKTRACE_BITS == 64)
+              commands_view->bytes_swapped = 0;
+            else
+              goto end;
+          break;
+          case MH_CIGAM_64:
+            if (BACKTRACE_BITS == 64)
+              commands_view->bytes_swapped = 1;
+            else
+              goto end;
+          break;
+          default:
+            goto end;
+        }
+
+      commands_view->base_offset = native_slice_offset;
+    }
+  else
+    commands_view->base_offset = 0;
+
+  file_header = file_header_view.data;
+  commands_view->commands_count =
+      macho_file_to_host_u32 (commands_view->bytes_swapped,
+                              file_header->ncmds);
+  commands_view->commands_total_size =
+      macho_file_to_host_u32 (commands_view->bytes_swapped,
+                              file_header->sizeofcmds);
+  commands_offset =
+      commands_view->base_offset + sizeof (mach_header_native_t);
+
+  if (!backtrace_get_view (state, descriptor, commands_offset,
+                           commands_view->commands_total_size, error_callback,
+                           data, &commands_view->view))
+    goto end;
+
+  ret = 1;
+
+end:
+  if (file_header_view_valid)
+    backtrace_release_view (state, &file_header_view, error_callback, data);
+  if (fat_archs_view_valid)
+    backtrace_release_view (state, &fat_archs_view, error_callback, data);
+  return ret;
+}
+
+int
+macho_get_uuid (struct backtrace_state *state ATTRIBUTE_UNUSED,
+                int descriptor ATTRIBUTE_UNUSED,
+                backtrace_error_callback error_callback,
+                void *data, struct macho_commands_view *commands_view,
+                uuid_t *uuid)
+{
+  size_t offset = 0;
+  uint32_t i = 0;
+
+  for (i = 0; i < commands_view->commands_count; i++)
+    {
+      const struct load_command *raw_command;
+      struct load_command command;
+
+      if (offset + sizeof (struct load_command)
+          > commands_view->commands_total_size)
+        {
+          error_callback (data,
+                          "executable file contains out of range command offset",
+                          0);
+          return 0;
+        }
+
+      raw_command =
+          commands_view->view.data + offset;
+      command.cmd = macho_file_to_host_u32 (commands_view->bytes_swapped,
+                                            raw_command->cmd);
+      command.cmdsize = macho_file_to_host_u32 (commands_view->bytes_swapped,
+                                                raw_command->cmdsize);
+
+      if (command.cmd == LC_UUID)
+        {
+          const struct uuid_command *uuid_command;
+
+          if (offset + sizeof (struct uuid_command)
+              > commands_view->commands_total_size)
+            {
+              error_callback (data,
+                              "executable file contains out of range command offset",
+                              0);
+              return 0;
+            }
+
+          uuid_command =
+              (struct uuid_command *) raw_command;
+          memcpy (uuid, uuid_command->uuid, sizeof (uuid_t));
+          return 1;
+        }
+
+      offset += command.cmdsize;
+    }
+
+  error_callback (data, "executable file is missing an identifying UUID", 0);
+  return 0;
+}
+
+/* Returns the base address of a Mach-O image, as encoded in the file header.
+ * WARNING: This does not take ASLR into account, which is ubiquitous on recent
+ * Darwin platforms.
+ */
+int
+macho_get_addr_range (struct backtrace_state *state ATTRIBUTE_UNUSED,
+                      int descriptor ATTRIBUTE_UNUSED,
+                      backtrace_error_callback error_callback,
+                      void *data, struct macho_commands_view *commands_view,
+                      uintptr_t *base_address, uintptr_t *max_address)
+{
+  size_t offset = 0;
+  int found_text = 0;
+  uint32_t i = 0;
+
+  *max_address = 0;
+
+  for (i = 0; i < commands_view->commands_count; i++)
+    {
+      const struct load_command *raw_command;
+      struct load_command command;
+
+      if (offset + sizeof (struct load_command)
+          > commands_view->commands_total_size)
+        {
+          error_callback (data,
+                          "executable file contains out of range command offset",
+                          0);
+          return 0;
+        }
+
+      raw_command = commands_view->view.data + offset;
+      command.cmd = macho_file_to_host_u32 (commands_view->bytes_swapped,
+                                            raw_command->cmd);
+      command.cmdsize = macho_file_to_host_u32 (commands_view->bytes_swapped,
+                                                raw_command->cmdsize);
+
+      if (command.cmd == LC_SEGMENT_NATIVE)
+        {
+          const segment_command_native_t *raw_segment;
+          uintptr_t segment_vmaddr;
+          uintptr_t segment_vmsize;
+          uintptr_t segment_maxaddr;
+          uintptr_t text_fileoff;
+
+          if (offset + sizeof (segment_command_native_t)
+              > commands_view->commands_total_size)
+            {
+              error_callback (data,
+                              "executable file contains out of range command offset",
+                              0);
+              return 0;
+            }
+
+          raw_segment = (segment_command_native_t *) raw_command;
+
+          segment_vmaddr = macho_file_to_host_usize (
+              commands_view->bytes_swapped, raw_segment->vmaddr);
+          segment_vmsize = macho_file_to_host_usize (
+              commands_view->bytes_swapped, raw_segment->vmsize);
+          segment_maxaddr = segment_vmaddr + segment_vmsize;
+
+          if (strncmp (raw_segment->segname, "__TEXT",
+                       sizeof (raw_segment->segname)) == 0)
+            {
+              text_fileoff = macho_file_to_host_usize (
+                  commands_view->bytes_swapped, raw_segment->fileoff);
+              *base_address = segment_vmaddr - text_fileoff;
+
+              found_text = 1;
+            }
+
+          if (segment_maxaddr > *max_address)
+            *max_address = segment_maxaddr;
+        }
+
+      offset += command.cmdsize;
+    }
+
+  if (found_text)
+    return 1;
+  else
+    {
+      error_callback (data, "executable is missing __TEXT segment", 0);
+      return 0;
+    }
+}
+
+static int
+macho_symbol_compare_addr (const void *left_raw, const void *right_raw)
+{
+  const struct macho_symbol *left = left_raw;
+  const struct macho_symbol *right = right_raw;
+
+  if (left->addr > right->addr)
+    return 1;
+  else if (left->addr < right->addr)
+    return -1;
+  else
+    return 0;
+}
+
+int
+macho_symbol_type_relevant (uint8_t type)
+{
+  uint8_t type_field = (uint8_t) (type & N_TYPE);
+
+  return !(type & N_EXT) &&
+         (type_field == N_ABS || type_field == N_SECT);
+}
+
+int
+macho_add_symtab (struct backtrace_state *state,
+                  backtrace_error_callback error_callback,
+                  void *data, int descriptor,
+                  struct macho_commands_view *commands_view,
+                  uintptr_t base_address, uintptr_t max_image_address,
+                  intptr_t vmslide, int *found_sym)
+{
+  struct macho_syminfo_data *syminfo_data;
+
+  int ret = 0;
+  size_t offset = 0;
+  struct backtrace_view symtab_view;
+  int symtab_view_valid = 0;
+  struct backtrace_view strtab_view;
+  int strtab_view_valid = 0;
+  size_t syminfo_index = 0;
+  size_t function_count = 0;
+  uint32_t i = 0;
+  uint32_t j = 0;
+  uint32_t symtab_index = 0;
+
+  *found_sym = 0;
+
+  for (i = 0; i < commands_view->commands_count; i++)
+    {
+      const struct load_command *raw_command;
+      struct load_command command;
+
+      if (offset + sizeof (struct load_command)
+          > commands_view->commands_total_size)
+        {
+          error_callback (data,
+                          "executable file contains out of range command offset",
+                          0);
+          return 0;
+        }
+
+      raw_command = commands_view->view.data + offset;
+      command.cmd = macho_file_to_host_u32 (commands_view->bytes_swapped,
+                                            raw_command->cmd);
+      command.cmdsize = macho_file_to_host_u32 (commands_view->bytes_swapped,
+                                                raw_command->cmdsize);
+
+      if (command.cmd == LC_SYMTAB)
+        {
+          const struct symtab_command *symtab_command;
+          uint32_t symbol_table_offset;
+          uint32_t symbol_count;
+          uint32_t string_table_offset;
+          uint32_t string_table_size;
+
+          if (offset + sizeof (struct symtab_command)
+              > commands_view->commands_total_size)
+            {
+              error_callback (data,
+                              "executable file contains out of range command offset",
+                              0);
+              return 0;
+            }
+
+          symtab_command = (struct symtab_command *) raw_command;
+
+          symbol_table_offset = macho_file_to_host_u32 (
+              commands_view->bytes_swapped, symtab_command->symoff);
+          symbol_count = macho_file_to_host_u32 (
+              commands_view->bytes_swapped, symtab_command->nsyms);
+          string_table_offset = macho_file_to_host_u32 (
+              commands_view->bytes_swapped, symtab_command->stroff);
+          string_table_size = macho_file_to_host_u32 (
+              commands_view->bytes_swapped, symtab_command->strsize);
+
+
+          if (!macho_get_view (state, descriptor, symbol_table_offset,
+                               symbol_count * sizeof (nlist_native_t),
+                               error_callback, data, commands_view,
+                               &symtab_view))
+            goto end;
+          symtab_view_valid = 1;
+
+          if (!macho_get_view (state, descriptor, string_table_offset,
+                               string_table_size, error_callback, data,
+                               commands_view, &strtab_view))
+            goto end;
+          strtab_view_valid = 1;
+
+          // Count functions first
+          for (j = 0; j < symbol_count; j++)
+            {
+              const nlist_native_t *raw_sym =
+                  ((const nlist_native_t *) symtab_view.data) + j;
+
+              if (macho_symbol_type_relevant (raw_sym->n_type))
+                {
+                  function_count += 1;
+                }
+            }
+
+          // Allocate space for the:
+          //  (a) macho_syminfo_data for this image
+          //  (b) macho_symbol entries
+          syminfo_data =
+              backtrace_alloc (state,
+                               sizeof (struct macho_syminfo_data),
+                               error_callback, data);
+          if (syminfo_data == NULL)
+            goto end;
+
+          syminfo_data->symbols = backtrace_alloc (
+              state, function_count * sizeof (struct macho_symbol),
+              error_callback, data);
+          if (syminfo_data->symbols == NULL)
+            goto end;
+
+          syminfo_data->symbol_count = function_count;
+          syminfo_data->next = NULL;
+          syminfo_data->min_addr = base_address;
+          syminfo_data->max_addr = max_image_address;
+
+          for (symtab_index = 0;
+               symtab_index < symbol_count; symtab_index++)
+            {
+              const nlist_native_t *raw_sym =
+                  ((const nlist_native_t *) symtab_view.data) +
+                  symtab_index;
+
+              if (macho_symbol_type_relevant (raw_sym->n_type))
+                {
+                  size_t strtab_index;
+                  const char *name;
+                  size_t max_len_plus_one;
+
+                  syminfo_data->symbols[syminfo_index].addr =
+                      macho_file_to_host_usize (commands_view->bytes_swapped,
+                                                raw_sym->n_value) + vmslide;
+
+                  strtab_index = macho_file_to_host_u32 (
+                      commands_view->bytes_swapped,
+                      raw_sym->n_un.n_strx);
+
+                  // Check the range of the supposed "string" we've been
+                  // given
+                  if (strtab_index >= string_table_size)
+                    {
+                      error_callback (
+                          data,
+                          "dSYM file contains out of range string table index",
+                          0);
+                      goto end;
+                    }
+
+                  name = strtab_view.data + strtab_index;
+                  max_len_plus_one = string_table_size - strtab_index;
+
+                  if (strnlen (name, max_len_plus_one) >= max_len_plus_one)
+                    {
+                      error_callback (
+                          data,
+                          "dSYM file contains unterminated string",
+                          0);
+                      goto end;
+                    }
+
+                  // Remove underscore prefixes
+                  if (name[0] == '_')
+                    {
+                      name = name + 1;
+                    }
+
+                  syminfo_data->symbols[syminfo_index].name = name;
+
+                  syminfo_index += 1;
+                }
+            }
+
+          backtrace_qsort (syminfo_data->symbols,
+                           syminfo_data->symbol_count,
+                           sizeof (struct macho_symbol),
+                           macho_symbol_compare_addr);
+
+          // Calculate symbol sizes
+          for (syminfo_index = 0;
+               syminfo_index < syminfo_data->symbol_count; syminfo_index++)
+            {
+              if (syminfo_index + 1 < syminfo_data->symbol_count)
+                {
+                  syminfo_data->symbols[syminfo_index].size =
+                      syminfo_data->symbols[syminfo_index + 1].addr -
+                      syminfo_data->symbols[syminfo_index].addr;
+                }
+              else
+                {
+                  syminfo_data->symbols[syminfo_index].size =
+                      max_image_address -
+                      syminfo_data->symbols[syminfo_index].addr;
+                }
+            }
+
+          if (!state->threaded)
+            {
+              struct macho_syminfo_data **pp;
+
+              for (pp = (struct macho_syminfo_data **) (void *) &state->syminfo_data;
+                   *pp != NULL;
+                   pp = &(*pp)->next);
+              *pp = syminfo_data;
+            }
+          else
+            {
+              while (1)
+                {
+                  struct macho_syminfo_data **pp;
+
+                  pp = (struct macho_syminfo_data **) (void *) &state->syminfo_data;
+
+                  while (1)
+                    {
+                      struct macho_syminfo_data *p;
+
+                      p = backtrace_atomic_load_pointer (pp);
+
+                      if (p == NULL)
+                        break;
+
+                      pp = &p->next;
+                    }
+
+                  if (__sync_bool_compare_and_swap (pp, NULL, syminfo_data))
+                    break;
+                }
+            }
+
+          strtab_view_valid = 0; // We need to keep string table around
+          *found_sym = 1;
+          ret = 1;
+          goto end;
+        }
+
+      offset += command.cmdsize;
+    }
+
+  // No symbol table here
+  ret = 1;
+  goto end;
+
+end:
+  if (symtab_view_valid)
+    backtrace_release_view (state, &symtab_view, error_callback, data);
+  if (strtab_view_valid)
+    backtrace_release_view (state, &strtab_view, error_callback, data);
+  return ret;
+}
+
+int
+macho_try_dwarf (struct backtrace_state *state,
+                 backtrace_error_callback error_callback,
+                 void *data, fileline *fileline_fn, uuid_t *executable_uuid,
+                 uintptr_t base_address, uintptr_t max_image_address,
+                 intptr_t vmslide, char *dwarf_filename, int *matched,
+                 int *found_sym, int *found_dwarf)
+{
+  uuid_t dwarf_uuid;
+
+  int ret = 0;
+  int dwarf_descriptor;
+  int dwarf_descriptor_valid = 0;
+  struct macho_commands_view commands_view;
+  int commands_view_valid = 0;
+  struct backtrace_view dwarf_view;
+  int dwarf_view_valid = 0;
+  size_t offset = 0;
+  struct found_dwarf_section dwarf_sections[DEBUG_MAX];
+  uintptr_t min_dwarf_offset = 0;
+  uintptr_t max_dwarf_offset = 0;
+  uint32_t i = 0;
+  uint32_t j = 0;
+  int k = 0;
+
+  *matched = 0;
+  *found_sym = 0;
+  *found_dwarf = 0;
+
+  if ((dwarf_descriptor = backtrace_open (dwarf_filename, error_callback,
+                                          data, NULL)) == 0)
+    goto end;
+  dwarf_descriptor_valid = 1;
+
+  int incompatible;
+  if (!macho_get_commands (state, dwarf_descriptor, error_callback, data,
+                           &commands_view, &incompatible))
+    {
+      // Failing to read the header here is fine, because this dSYM may be
+      // for a different architecture
+      if (incompatible)
+        {
+          ret = 1;
+        }
+      goto end;
+    }
+  commands_view_valid = 1;
+
+  // Get dSYM UUID and compare
+  if (!macho_get_uuid (state, dwarf_descriptor, error_callback, data,
+                       &commands_view, &dwarf_uuid))
+    {
+      error_callback (data, "dSYM file is missing an identifying uuid", 0);
+      goto end;
+    }
+  if (memcmp (executable_uuid, &dwarf_uuid, sizeof (uuid_t)) != 0)
+    {
+      // DWARF doesn't belong to desired executable
+      ret = 1;
+      goto end;
+    }
+
+  *matched = 1;
+
+  // Read symbol table
+  if (!macho_add_symtab (state, error_callback, data, dwarf_descriptor,
+                         &commands_view, base_address, max_image_address,
+                         vmslide, found_sym))
+    goto end;
+
+  // Get DWARF sections
+
+  memset (dwarf_sections, 0, sizeof (dwarf_sections));
+  offset = 0;
+  for (i = 0; i < commands_view.commands_count; i++)
+    {
+      const struct load_command *raw_command;
+      struct load_command command;
+
+      if (offset + sizeof (struct load_command)
+          > commands_view.commands_total_size)
+        {
+          error_callback (data,
+                          "dSYM file contains out of range command offset", 0);
+          goto end;
+        }
+
+      raw_command = commands_view.view.data + offset;
+      command.cmd = macho_file_to_host_u32 (commands_view.bytes_swapped,
+                                            raw_command->cmd);
+      command.cmdsize = macho_file_to_host_u32 (commands_view.bytes_swapped,
+                                                raw_command->cmdsize);
+
+      if (command.cmd == LC_SEGMENT_NATIVE)
+        {
+          uint32_t section_count;
+          size_t section_offset;
+          const segment_command_native_t *raw_segment;
+
+          if (offset + sizeof (segment_command_native_t)
+              > commands_view.commands_total_size)
+            {
+              error_callback (data,
+                              "dSYM file contains out of range command offset",
+                              0);
+              goto end;
+            }
+
+          raw_segment = (const segment_command_native_t *) raw_command;
+
+          if (strncmp (raw_segment->segname, "__DWARF",
+                       sizeof (raw_segment->segname)) == 0)
+            {
+              section_count = macho_file_to_host_u32 (
+                  commands_view.bytes_swapped,
+                  raw_segment->nsects);
+
+              section_offset = offset + sizeof (segment_command_native_t);
+
+              // Search sections for relevant DWARF section names
+              for (j = 0; j < section_count; j++)
+                {
+                  const section_native_t *raw_section;
+
+                  if (section_offset + sizeof (section_native_t) >
+                      commands_view.commands_total_size)
+                    {
+                      error_callback (data,
+                                      "dSYM file contains out of range command offset",
+                                      0);
+                      goto end;
+                    }
+
+                  raw_section = commands_view.view.data + section_offset;
+
+                  for (k = 0; k < DEBUG_MAX; k++)
+                    {
+                      uintptr_t dwarf_section_end;
+
+                      if (strncmp (raw_section->sectname,
+                                   debug_section_names[k],
+                                   sizeof (raw_section->sectname)) == 0)
+                        {
+                          *found_dwarf = 1;
+
+                          dwarf_sections[k].file_offset =
+                              macho_file_to_host_u32 (
+                                  commands_view.bytes_swapped,
+                                  raw_section->offset);
+                          dwarf_sections[k].file_size =
+                              macho_file_to_host_usize (
+                                  commands_view.bytes_swapped,
+                                  raw_section->size);
+
+                          if (min_dwarf_offset == 0 ||
+                              dwarf_sections[k].file_offset <
+                              min_dwarf_offset)
+                            min_dwarf_offset = dwarf_sections[k].file_offset;
+
+                          dwarf_section_end =
+                              dwarf_sections[k].file_offset +
+                              dwarf_sections[k].file_size;
+                          if (dwarf_section_end > max_dwarf_offset)
+                            max_dwarf_offset = dwarf_section_end;
+
+                          break;
+                        }
+                    }
+
+                  section_offset += sizeof (section_native_t);
+                }
+
+              break;
+            }
+        }
+
+      offset += command.cmdsize;
+    }
+
+  if (!*found_dwarf)
+    {
+      // No DWARF in this file
+      ret = 1;
+      goto end;
+    }
+
+  if (!macho_get_view (state, dwarf_descriptor, (off_t) min_dwarf_offset,
+                       max_dwarf_offset - min_dwarf_offset, error_callback,
+                       data, &commands_view, &dwarf_view))
+    goto end;
+  dwarf_view_valid = 1;
+
+  for (i = 0; i < DEBUG_MAX; i++)
+    {
+      if (dwarf_sections[i].file_offset == 0)
+        dwarf_sections[i].data = NULL;
+      else
+        dwarf_sections[i].data =
+            dwarf_view.data + dwarf_sections[i].file_offset - min_dwarf_offset;
+    }
+
+  if (!backtrace_dwarf_add (state, vmslide,
+                            dwarf_sections[DEBUG_INFO].data,
+                            dwarf_sections[DEBUG_INFO].file_size,
+                            dwarf_sections[DEBUG_LINE].data,
+                            dwarf_sections[DEBUG_LINE].file_size,
+                            dwarf_sections[DEBUG_ABBREV].data,
+                            dwarf_sections[DEBUG_ABBREV].file_size,
+                            dwarf_sections[DEBUG_RANGES].data,
+                            dwarf_sections[DEBUG_RANGES].file_size,
+                            dwarf_sections[DEBUG_STR].data,
+                            dwarf_sections[DEBUG_STR].file_size,
+                            ((__DARWIN_BYTE_ORDER == __DARWIN_BIG_ENDIAN)
+                            ^ commands_view.bytes_swapped),
+                            error_callback, data, fileline_fn))
+    goto end;
+
+  // Don't release the DWARF view because it is still in use
+  dwarf_descriptor_valid = 0;
+  dwarf_view_valid = 0;
+  ret = 1;
+
+end:
+  if (dwarf_descriptor_valid)
+    backtrace_close (dwarf_descriptor, error_callback, data);
+  if (commands_view_valid)
+    backtrace_release_view (state, &commands_view.view, error_callback, data);
+  if (dwarf_view_valid)
+    backtrace_release_view (state, &dwarf_view, error_callback, data);
+  return ret;
+}
+
+int
+macho_try_dsym (struct backtrace_state *state,
+                backtrace_error_callback error_callback,
+                void *data, fileline *fileline_fn, uuid_t *executable_uuid,
+                uintptr_t base_address, uintptr_t max_image_address,
+                intptr_t vmslide, char *dsym_filename, int *matched,
+                int *found_sym, int *found_dwarf)
+{
+  int ret = 0;
+  char dwarf_image_dir_path[PATH_MAX];
+  DIR *dwarf_image_dir;
+  int dwarf_image_dir_valid = 0;
+  struct dirent *directory_entry;
+  char dwarf_filename[PATH_MAX];
+  int dwarf_matched;
+  int dwarf_had_sym;
+  int dwarf_had_dwarf;
+
+  *matched = 0;
+  *found_sym = 0;
+  *found_dwarf = 0;
+
+  strncpy (dwarf_image_dir_path, dsym_filename, PATH_MAX);
+  strncat (dwarf_image_dir_path, "/Contents/Resources/DWARF", PATH_MAX);
+
+  if (!(dwarf_image_dir = opendir (dwarf_image_dir_path)))
+    {
+      error_callback (data, "could not open DWARF directory in dSYM",
+                      0);
+      goto end;
+    }
+  dwarf_image_dir_valid = 1;
+
+  while ((directory_entry = readdir (dwarf_image_dir)))
+    {
+      if (directory_entry->d_type != DT_REG)
+        continue;
+
+      strncpy (dwarf_filename, dwarf_image_dir_path, PATH_MAX);
+      strncat (dwarf_filename, "/", PATH_MAX);
+      strncat (dwarf_filename, directory_entry->d_name, PATH_MAX);
+
+      if (!macho_try_dwarf (state, error_callback, data, fileline_fn,
+                            executable_uuid, base_address, max_image_address,
+                            vmslide, dwarf_filename,
+                            &dwarf_matched, &dwarf_had_sym, &dwarf_had_dwarf))
+        goto end;
+
+      if (dwarf_matched)
+        {
+          *matched = 1;
+          *found_sym = dwarf_had_sym;
+          *found_dwarf = dwarf_had_dwarf;
+          ret = 1;
+          goto end;
+        }
+    }
+
+  // No matching DWARF in this dSYM
+  ret = 1;
+  goto end;
+
+end:
+  if (dwarf_image_dir_valid)
+    closedir (dwarf_image_dir);
+  return ret;
+}
+
+int
+macho_add (struct backtrace_state *state,
+           backtrace_error_callback error_callback, void *data, int descriptor,
+           const char *filename, fileline *fileline_fn, intptr_t vmslide,
+           int *found_sym, int *found_dwarf)
+{
+  uuid_t image_uuid;
+  uintptr_t image_file_base_address;
+  uintptr_t image_file_max_address;
+  uintptr_t image_actual_base_address = 0;
+  uintptr_t image_actual_max_address = 0;
+
+  int ret = 0;
+  struct macho_commands_view commands_view;
+  int commands_view_valid = 0;
+  char executable_dirname[PATH_MAX];
+  size_t filename_len;
+  DIR *executable_dir = NULL;
+  int executable_dir_valid = 0;
+  struct dirent *directory_entry;
+  char dsym_full_path[PATH_MAX];
+  static const char *extension;
+  size_t extension_len;
+  ssize_t i;
+
+  *found_sym = 0;
+  *found_dwarf = 0;
+
+  // Find Mach-O commands list
+  int incompatible;
+  if (!macho_get_commands (state, descriptor, error_callback, data,
+                           &commands_view, &incompatible))
+    goto end;
+  commands_view_valid = 1;
+
+  // First we need to get the uuid of our file so we can hunt down the correct
+  // dSYM
+  if (!macho_get_uuid (state, descriptor, error_callback, data, &commands_view,
+                       &image_uuid))
+    goto end;
+
+  // Now we need to find the in memory base address. Step one is to find out
+  // what the executable thinks the base address is
+  if (!macho_get_addr_range (state, descriptor, error_callback, data,
+                             &commands_view,
+                             &image_file_base_address,
+                             &image_file_max_address))
+    goto end;
+
+  image_actual_base_address =
+      image_file_base_address + vmslide;
+  image_actual_max_address =
+      image_file_max_address + vmslide;
+
+  if (image_actual_base_address == 0)
+    {
+      error_callback (data, "executable file is not loaded", 0);
+      goto end;
+    }
+
+  // Look for dSYM in our executable's directory
+  strncpy (executable_dirname, filename, PATH_MAX);
+  filename_len = strlen (executable_dirname);
+  for (i = filename_len - 1; i >= 0; i--)
+    {
+      if (executable_dirname[i] == '/')
+        {
+          executable_dirname[i] = '\0';
+          break;
+        }
+      else if (i == 0)
+        {
+          executable_dirname[0] = '.';
+          executable_dirname[1] = '\0';
+          break;
+        }
+    }
+
+  if (!(executable_dir = opendir (executable_dirname)))
+    {
+      error_callback (data, "could not open directory containing executable",
+                      0);
+      goto end;
+    }
+  executable_dir_valid = 1;
+
+  extension = ".dSYM";
+  extension_len = strlen (extension);
+  while ((directory_entry = readdir (executable_dir)))
+    {
+      if (directory_entry->d_namlen < extension_len)
+        continue;
+      if (strncasecmp (directory_entry->d_name + directory_entry->d_namlen
+                       - extension_len, extension, extension_len) == 0)
+        {
+          int matched;
+          int dsym_had_sym;
+          int dsym_had_dwarf;
+
+          // Found a dSYM
+          strncpy (dsym_full_path, executable_dirname, PATH_MAX);
+          strncat (dsym_full_path, "/", PATH_MAX);
+          strncat (dsym_full_path, directory_entry->d_name, PATH_MAX);
+
+          if (!macho_try_dsym (state, error_callback, data,
+                               fileline_fn, &image_uuid,
+                               image_actual_base_address,
+                               image_actual_max_address, vmslide,
+                               dsym_full_path,
+                               &matched, &dsym_had_sym, &dsym_had_dwarf))
+            goto end;
+
+          if (matched)
+            {
+              *found_sym = dsym_had_sym;
+              *found_dwarf = dsym_had_dwarf;
+              ret = 1;
+              goto end;
+            }
+        }
+    }
+
+  // No matching dSYM
+  ret = 1;
+  goto end;
+
+end:
+  if (commands_view_valid)
+    backtrace_release_view (state, &commands_view.view, error_callback,
+                            data);
+  if (executable_dir_valid)
+    closedir (executable_dir);
+  return ret;
+}
+
+static int
+macho_symbol_search (const void *vkey, const void *ventry)
+{
+  const uintptr_t *key = (const uintptr_t *) vkey;
+  const struct macho_symbol *entry = (const struct macho_symbol *) ventry;
+  uintptr_t addr;
+
+  addr = *key;
+  if (addr < entry->addr)
+    return -1;
+  else if (addr >= entry->addr + entry->size)
+    return 1;
+  else
+    return 0;
+}
+
+static void
+macho_syminfo (struct backtrace_state *state,
+               uintptr_t addr,
+               backtrace_syminfo_callback callback,
+               backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
+               void *data)
+{
+  struct macho_syminfo_data *edata;
+  struct macho_symbol *sym = NULL;
+
+  if (!state->threaded)
+    {
+      for (edata = (struct macho_syminfo_data *) state->syminfo_data;
+           edata != NULL;
+           edata = edata->next)
+        {
+          if (addr >= edata->min_addr && addr <= edata->max_addr)
+            {
+              sym = ((struct macho_symbol *)
+                  bsearch (&addr, edata->symbols, edata->symbol_count,
+                           sizeof (struct macho_symbol), macho_symbol_search));
+              if (sym != NULL)
+                break;
+            }
+        }
+    }
+  else
+    {
+      struct macho_syminfo_data **pp;
+
+      pp = (struct macho_syminfo_data **) (void *) &state->syminfo_data;
+      while (1)
+        {
+          edata = backtrace_atomic_load_pointer (pp);
+          if (edata == NULL)
+            break;
+
+          if (addr >= edata->min_addr && addr <= edata->max_addr)
+            {
+              sym = ((struct macho_symbol *)
+                  bsearch (&addr, edata->symbols, edata->symbol_count,
+                           sizeof (struct macho_symbol), macho_symbol_search));
+              if (sym != NULL)
+                break;
+            }
+
+          pp = &edata->next;
+        }
+    }
+
+  if (sym == NULL)
+    callback (data, addr, NULL, 0, 0);
+  else
+    callback (data, addr, sym->name, sym->addr, sym->size);
+}
+
+
+static int
+macho_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
+               uintptr_t pc ATTRIBUTE_UNUSED,
+               backtrace_full_callback callback ATTRIBUTE_UNUSED,
+               backtrace_error_callback error_callback, void *data)
+{
+  error_callback (data, "no debug info in Mach-O executable", -1);
+  return 0;
+}
+
+static void
+macho_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,
+              uintptr_t addr ATTRIBUTE_UNUSED,
+              backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,
+              backtrace_error_callback error_callback, void *data)
+{
+  error_callback (data, "no symbol table in Mach-O executable", -1);
+}
+
+int
+backtrace_initialize (struct backtrace_state *state,
+                      const char *filename,
+                      int descriptor,
+                      backtrace_error_callback error_callback,
+                      void *data, fileline *fileline_fn)
+{
+  int ret;
+  fileline macho_fileline_fn = macho_nodebug;
+  int found_sym = 0;
+  int found_dwarf = 0;
+  uint32_t i = 0;
+  uint32_t loaded_image_count;
+
+  // Add all loaded images
+  loaded_image_count = _dyld_image_count ();
+  for (i = 0; i < loaded_image_count; i++)
+    {
+      int current_found_sym;
+      int current_found_dwarf;
+      int current_descriptor;
+      intptr_t current_vmslide;
+      const char *current_name;
+
+      current_vmslide = _dyld_get_image_vmaddr_slide (i);
+      current_name = _dyld_get_image_name (i);
+
+      if (current_name == NULL || (i != 0 && current_vmslide == 0))
+        continue;
+
+      if (!(current_descriptor =
+                backtrace_open (current_name, error_callback, data, NULL)))
+        {
+          continue;
+        }
+
+      if (macho_add (state, error_callback, data, current_descriptor,
+                      current_name, &macho_fileline_fn, current_vmslide,
+                      &current_found_sym, &current_found_dwarf))
+        {
+          found_sym = found_sym || current_found_sym;
+          found_dwarf = found_dwarf || current_found_dwarf;
+        }
+
+      backtrace_close (current_descriptor, error_callback, data);
+    }
+
+  if (!state->threaded)
+    {
+      if (found_sym)
+        state->syminfo_fn = macho_syminfo;
+      else if (state->syminfo_fn == NULL)
+        state->syminfo_fn = macho_nosyms;
+    }
+  else
+    {
+      if (found_sym)
+        backtrace_atomic_store_pointer (&state->syminfo_fn, macho_syminfo);
+      else
+        (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,
+                                             macho_nosyms);
+    }
+
+  if (!state->threaded)
+    {
+      if (state->fileline_fn == NULL || state->fileline_fn == macho_nodebug)
+        *fileline_fn = macho_fileline_fn;
+    }
+  else
+    {
+      fileline current_fn;
+
+      current_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
+      if (current_fn == NULL || current_fn == macho_nodebug)
+        *fileline_fn = macho_fileline_fn;
+    }
+
+  return 1;
+}
+
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/missing b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/missing
new file mode 100755
index 0000000..86a8fc3
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/missing
@@ -0,0 +1,331 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+
+scriptversion=2012-01-06.13; # UTC
+
+# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006,
+# 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
+# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program 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 General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+if test $# -eq 0; then
+  echo 1>&2 "Try \`$0 --help' for more information"
+  exit 1
+fi
+
+run=:
+sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
+sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
+
+# In the cases where this matters, `missing' is being run in the
+# srcdir already.
+if test -f configure.ac; then
+  configure_ac=configure.ac
+else
+  configure_ac=configure.in
+fi
+
+msg="missing on your system"
+
+case $1 in
+--run)
+  # Try to run requested program, and just exit if it succeeds.
+  run=
+  shift
+  "$@" && exit 0
+  # Exit code 63 means version mismatch.  This often happens
+  # when the user try to use an ancient version of a tool on
+  # a file that requires a minimum version.  In this case we
+  # we should proceed has if the program had been absent, or
+  # if --run hadn't been passed.
+  if test $? = 63; then
+    run=:
+    msg="probably too old"
+  fi
+  ;;
+
+  -h|--h|--he|--hel|--help)
+    echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+  -h, --help      display this help and exit
+  -v, --version   output version information and exit
+  --run           try to run the given command, and emulate it if it fails
+
+Supported PROGRAM values:
+  aclocal      touch file \`aclocal.m4'
+  autoconf     touch file \`configure'
+  autoheader   touch file \`config.h.in'
+  autom4te     touch the output file, or create a stub one
+  automake     touch all \`Makefile.in' files
+  bison        create \`y.tab.[ch]', if possible, from existing .[ch]
+  flex         create \`lex.yy.c', if possible, from existing .c
+  help2man     touch the output file
+  lex          create \`lex.yy.c', if possible, from existing .c
+  makeinfo     touch the output file
+  yacc         create \`y.tab.[ch]', if possible, from existing .[ch]
+
+Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and
+\`g' are ignored when checking the name.
+
+Send bug reports to <bug-automake@gnu.org>."
+    exit $?
+    ;;
+
+  -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+    echo "missing $scriptversion (GNU Automake)"
+    exit $?
+    ;;
+
+  -*)
+    echo 1>&2 "$0: Unknown \`$1' option"
+    echo 1>&2 "Try \`$0 --help' for more information"
+    exit 1
+    ;;
+
+esac
+
+# normalize program name to check for.
+program=`echo "$1" | sed '
+  s/^gnu-//; t
+  s/^gnu//; t
+  s/^g//; t'`
+
+# Now exit if we have it, but it failed.  Also exit now if we
+# don't have it and --version was passed (most likely to detect
+# the program).  This is about non-GNU programs, so use $1 not
+# $program.
+case $1 in
+  lex*|yacc*)
+    # Not GNU programs, they don't have --version.
+    ;;
+
+  *)
+    if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+       # We have it, but it failed.
+       exit 1
+    elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+       # Could not run --version or --help.  This is probably someone
+       # running `$TOOL --version' or `$TOOL --help' to check whether
+       # $TOOL exists and not knowing $TOOL uses missing.
+       exit 1
+    fi
+    ;;
+esac
+
+# If it does not exist, or fails to run (possibly an outdated version),
+# try to emulate it.
+case $program in
+  aclocal*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified \`acinclude.m4' or \`${configure_ac}'.  You might want
+         to install the \`Automake' and \`Perl' packages.  Grab them from
+         any GNU archive site."
+    touch aclocal.m4
+    ;;
+
+  autoconf*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified \`${configure_ac}'.  You might want to install the
+         \`Autoconf' and \`GNU m4' packages.  Grab them from any GNU
+         archive site."
+    touch configure
+    ;;
+
+  autoheader*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified \`acconfig.h' or \`${configure_ac}'.  You might want
+         to install the \`Autoconf' and \`GNU m4' packages.  Grab them
+         from any GNU archive site."
+    files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
+    test -z "$files" && files="config.h"
+    touch_files=
+    for f in $files; do
+      case $f in
+      *:*) touch_files="$touch_files "`echo "$f" |
+				       sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+      *) touch_files="$touch_files $f.in";;
+      esac
+    done
+    touch $touch_files
+    ;;
+
+  automake*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
+         You might want to install the \`Automake' and \`Perl' packages.
+         Grab them from any GNU archive site."
+    find . -type f -name Makefile.am -print |
+	   sed 's/\.am$/.in/' |
+	   while read f; do touch "$f"; done
+    ;;
+
+  autom4te*)
+    echo 1>&2 "\
+WARNING: \`$1' is needed, but is $msg.
+         You might have modified some files without having the
+         proper tools for further handling them.
+         You can get \`$1' as part of \`Autoconf' from any GNU
+         archive site."
+
+    file=`echo "$*" | sed -n "$sed_output"`
+    test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+    if test -f "$file"; then
+	touch $file
+    else
+	test -z "$file" || exec >$file
+	echo "#! /bin/sh"
+	echo "# Created by GNU Automake missing as a replacement of"
+	echo "#  $ $@"
+	echo "exit 0"
+	chmod +x $file
+	exit 1
+    fi
+    ;;
+
+  bison*|yacc*)
+    echo 1>&2 "\
+WARNING: \`$1' $msg.  You should only need it if
+         you modified a \`.y' file.  You may need the \`Bison' package
+         in order for those modifications to take effect.  You can get
+         \`Bison' from any GNU archive site."
+    rm -f y.tab.c y.tab.h
+    if test $# -ne 1; then
+        eval LASTARG=\${$#}
+	case $LASTARG in
+	*.y)
+	    SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+	    if test -f "$SRCFILE"; then
+	         cp "$SRCFILE" y.tab.c
+	    fi
+	    SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+	    if test -f "$SRCFILE"; then
+	         cp "$SRCFILE" y.tab.h
+	    fi
+	  ;;
+	esac
+    fi
+    if test ! -f y.tab.h; then
+	echo >y.tab.h
+    fi
+    if test ! -f y.tab.c; then
+	echo 'main() { return 0; }' >y.tab.c
+    fi
+    ;;
+
+  lex*|flex*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified a \`.l' file.  You may need the \`Flex' package
+         in order for those modifications to take effect.  You can get
+         \`Flex' from any GNU archive site."
+    rm -f lex.yy.c
+    if test $# -ne 1; then
+        eval LASTARG=\${$#}
+	case $LASTARG in
+	*.l)
+	    SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+	    if test -f "$SRCFILE"; then
+	         cp "$SRCFILE" lex.yy.c
+	    fi
+	  ;;
+	esac
+    fi
+    if test ! -f lex.yy.c; then
+	echo 'main() { return 0; }' >lex.yy.c
+    fi
+    ;;
+
+  help2man*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+	 you modified a dependency of a manual page.  You may need the
+	 \`Help2man' package in order for those modifications to take
+	 effect.  You can get \`Help2man' from any GNU archive site."
+
+    file=`echo "$*" | sed -n "$sed_output"`
+    test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+    if test -f "$file"; then
+	touch $file
+    else
+	test -z "$file" || exec >$file
+	echo ".ab help2man is required to generate this page"
+	exit $?
+    fi
+    ;;
+
+  makeinfo*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified a \`.texi' or \`.texinfo' file, or any other file
+         indirectly affecting the aspect of the manual.  The spurious
+         call might also be the consequence of using a buggy \`make' (AIX,
+         DU, IRIX).  You might want to install the \`Texinfo' package or
+         the \`GNU make' package.  Grab either from any GNU archive site."
+    # The file to touch is that specified with -o ...
+    file=`echo "$*" | sed -n "$sed_output"`
+    test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+    if test -z "$file"; then
+      # ... or it is the one specified with @setfilename ...
+      infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+      file=`sed -n '
+	/^@setfilename/{
+	  s/.* \([^ ]*\) *$/\1/
+	  p
+	  q
+	}' $infile`
+      # ... or it is derived from the source name (dir/f.texi becomes f.info)
+      test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
+    fi
+    # If the file does not exist, the user really needs makeinfo;
+    # let's fail without touching anything.
+    test -f $file || exit 1
+    touch $file
+    ;;
+
+  *)
+    echo 1>&2 "\
+WARNING: \`$1' is needed, and is $msg.
+         You might have modified some files without having the
+         proper tools for further handling them.  Check the \`README' file,
+         it often tells you about the needed prerequisites for installing
+         this package.  You may also peek at any GNU archive site, in case
+         some other package would contain this missing \`$1' program."
+    exit 1
+    ;;
+esac
+
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/mmap.c b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/mmap.c
new file mode 100644
index 0000000..32fcba6
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/mmap.c
@@ -0,0 +1,325 @@
+/* mmap.c -- Memory allocation with mmap.
+   Copyright (C) 2012-2018 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+
+#include "backtrace.h"
+#include "internal.h"
+
+/* Memory allocation on systems that provide anonymous mmap.  This
+   permits the backtrace functions to be invoked from a signal
+   handler, assuming that mmap is async-signal safe.  */
+
+#ifndef MAP_ANONYMOUS
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *)-1)
+#endif
+
+/* A list of free memory blocks.  */
+
+struct backtrace_freelist_struct
+{
+  /* Next on list.  */
+  struct backtrace_freelist_struct *next;
+  /* Size of this block, including this structure.  */
+  size_t size;
+};
+
+/* Free memory allocated by backtrace_alloc.  */
+
+static void
+backtrace_free_locked (struct backtrace_state *state, void *addr, size_t size)
+{
+  /* Just leak small blocks.  We don't have to be perfect.  Don't put
+     more than 16 entries on the free list, to avoid wasting time
+     searching when allocating a block.  If we have more than 16
+     entries, leak the smallest entry.  */
+
+  if (size >= sizeof (struct backtrace_freelist_struct))
+    {
+      size_t c;
+      struct backtrace_freelist_struct **ppsmall;
+      struct backtrace_freelist_struct **pp;
+      struct backtrace_freelist_struct *p;
+
+      c = 0;
+      ppsmall = NULL;
+      for (pp = &state->freelist; *pp != NULL; pp = &(*pp)->next)
+	{
+	  if (ppsmall == NULL || (*pp)->size < (*ppsmall)->size)
+	    ppsmall = pp;
+	  ++c;
+	}
+      if (c >= 16)
+	{
+	  if (size <= (*ppsmall)->size)
+	    return;
+	  *ppsmall = (*ppsmall)->next;
+	}
+
+      p = (struct backtrace_freelist_struct *) addr;
+      p->next = state->freelist;
+      p->size = size;
+      state->freelist = p;
+    }
+}
+
+/* Allocate memory like malloc.  If ERROR_CALLBACK is NULL, don't
+   report an error.  */
+
+void *
+backtrace_alloc (struct backtrace_state *state,
+		 size_t size, backtrace_error_callback error_callback,
+		 void *data)
+{
+  void *ret;
+  int locked;
+  struct backtrace_freelist_struct **pp;
+  size_t pagesize;
+  size_t asksize;
+  void *page;
+
+  ret = NULL;
+
+  /* If we can acquire the lock, then see if there is space on the
+     free list.  If we can't acquire the lock, drop straight into
+     using mmap.  __sync_lock_test_and_set returns the old state of
+     the lock, so we have acquired it if it returns 0.  */
+
+  if (!state->threaded)
+    locked = 1;
+  else
+    locked = __sync_lock_test_and_set (&state->lock_alloc, 1) == 0;
+
+  if (locked)
+    {
+      for (pp = &state->freelist; *pp != NULL; pp = &(*pp)->next)
+	{
+	  if ((*pp)->size >= size)
+	    {
+	      struct backtrace_freelist_struct *p;
+
+	      p = *pp;
+	      *pp = p->next;
+
+	      /* Round for alignment; we assume that no type we care about
+		 is more than 8 bytes.  */
+	      size = (size + 7) & ~ (size_t) 7;
+	      if (size < p->size)
+		backtrace_free_locked (state, (char *) p + size,
+				       p->size - size);
+
+	      ret = (void *) p;
+
+	      break;
+	    }
+	}
+
+      if (state->threaded)
+	__sync_lock_release (&state->lock_alloc);
+    }
+
+  if (ret == NULL)
+    {
+      /* Allocate a new page.  */
+
+      pagesize = getpagesize ();
+      asksize = (size + pagesize - 1) & ~ (pagesize - 1);
+      page = mmap (NULL, asksize, PROT_READ | PROT_WRITE,
+		   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+      if (page == MAP_FAILED)
+	{
+	  if (error_callback)
+	    error_callback (data, "mmap", errno);
+	}
+      else
+	{
+	  size = (size + 7) & ~ (size_t) 7;
+	  if (size < asksize)
+	    backtrace_free (state, (char *) page + size, asksize - size,
+			    error_callback, data);
+
+	  ret = page;
+	}
+    }
+
+  return ret;
+}
+
+/* Free memory allocated by backtrace_alloc.  */
+
+void
+backtrace_free (struct backtrace_state *state, void *addr, size_t size,
+		backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
+		void *data ATTRIBUTE_UNUSED)
+{
+  int locked;
+
+  /* If we are freeing a large aligned block, just release it back to
+     the system.  This case arises when growing a vector for a large
+     binary with lots of debug info.  Calling munmap here may cause us
+     to call mmap again if there is also a large shared library; we
+     just live with that.  */
+  if (size >= 16 * 4096)
+    {
+      size_t pagesize;
+
+      pagesize = getpagesize ();
+      if (((uintptr_t) addr & (pagesize - 1)) == 0
+	  && (size & (pagesize - 1)) == 0)
+	{
+	  /* If munmap fails for some reason, just add the block to
+	     the freelist.  */
+	  if (munmap (addr, size) == 0)
+	    return;
+	}
+    }
+
+  /* If we can acquire the lock, add the new space to the free list.
+     If we can't acquire the lock, just leak the memory.
+     __sync_lock_test_and_set returns the old state of the lock, so we
+     have acquired it if it returns 0.  */
+
+  if (!state->threaded)
+    locked = 1;
+  else
+    locked = __sync_lock_test_and_set (&state->lock_alloc, 1) == 0;
+
+  if (locked)
+    {
+      backtrace_free_locked (state, addr, size);
+
+      if (state->threaded)
+	__sync_lock_release (&state->lock_alloc);
+    }
+}
+
+/* Grow VEC by SIZE bytes.  */
+
+void *
+backtrace_vector_grow (struct backtrace_state *state,size_t size,
+		       backtrace_error_callback error_callback,
+		       void *data, struct backtrace_vector *vec)
+{
+  void *ret;
+
+  if (size > vec->alc)
+    {
+      size_t pagesize;
+      size_t alc;
+      void *base;
+
+      pagesize = getpagesize ();
+      alc = vec->size + size;
+      if (vec->size == 0)
+	alc = 16 * size;
+      else if (alc < pagesize)
+	{
+	  alc *= 2;
+	  if (alc > pagesize)
+	    alc = pagesize;
+	}
+      else
+	{
+	  alc *= 2;
+	  alc = (alc + pagesize - 1) & ~ (pagesize - 1);
+	}
+      base = backtrace_alloc (state, alc, error_callback, data);
+      if (base == NULL)
+	return NULL;
+      if (vec->base != NULL)
+	{
+	  memcpy (base, vec->base, vec->size);
+	  backtrace_free (state, vec->base, vec->size + vec->alc,
+			  error_callback, data);
+	}
+      vec->base = base;
+      vec->alc = alc - vec->size;
+    }
+
+  ret = (char *) vec->base + vec->size;
+  vec->size += size;
+  vec->alc -= size;
+  return ret;
+}
+
+/* Finish the current allocation on VEC.  */
+
+void *
+backtrace_vector_finish (
+  struct backtrace_state *state ATTRIBUTE_UNUSED,
+  struct backtrace_vector *vec,
+  backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
+  void *data ATTRIBUTE_UNUSED)
+{
+  void *ret;
+
+  ret = vec->base;
+  vec->base = (char *) vec->base + vec->size;
+  vec->size = 0;
+  return ret;
+}
+
+/* Release any extra space allocated for VEC.  */
+
+int
+backtrace_vector_release (struct backtrace_state *state,
+			  struct backtrace_vector *vec,
+			  backtrace_error_callback error_callback,
+			  void *data)
+{
+  size_t size;
+  size_t alc;
+  size_t aligned;
+
+  /* Make sure that the block that we free is aligned on an 8-byte
+     boundary.  */
+  size = vec->size;
+  alc = vec->alc;
+  aligned = (size + 7) & ~ (size_t) 7;
+  alc -= aligned - size;
+
+  backtrace_free (state, (char *) vec->base + aligned, alc,
+		  error_callback, data);
+  vec->alc = 0;
+  return 1;
+}
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/mmapio.c b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/mmapio.c
new file mode 100644
index 0000000..94e8c93
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/mmapio.c
@@ -0,0 +1,100 @@
+/* mmapio.c -- File views using mmap.
+   Copyright (C) 2012-2018 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#include "backtrace.h"
+#include "internal.h"
+
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *)-1)
+#endif
+
+/* This file implements file views and memory allocation when mmap is
+   available.  */
+
+/* Create a view of SIZE bytes from DESCRIPTOR at OFFSET.  */
+
+int
+backtrace_get_view (struct backtrace_state *state ATTRIBUTE_UNUSED,
+		    int descriptor, off_t offset, size_t size,
+		    backtrace_error_callback error_callback,
+		    void *data, struct backtrace_view *view)
+{
+  size_t pagesize;
+  unsigned int inpage;
+  off_t pageoff;
+  void *map;
+
+  pagesize = getpagesize ();
+  inpage = offset % pagesize;
+  pageoff = offset - inpage;
+
+  size += inpage;
+  size = (size + (pagesize - 1)) & ~ (pagesize - 1);
+
+  map = mmap (NULL, size, PROT_READ, MAP_PRIVATE, descriptor, pageoff);
+  if (map == MAP_FAILED)
+    {
+      error_callback (data, "mmap", errno);
+      return 0;
+    }
+
+  view->data = (char *) map + inpage;
+  view->base = map;
+  view->len = size;
+
+  return 1;
+}
+
+/* Release a view read by backtrace_get_view.  */
+
+void
+backtrace_release_view (struct backtrace_state *state ATTRIBUTE_UNUSED,
+			struct backtrace_view *view,
+			backtrace_error_callback error_callback,
+			void *data)
+{
+  union {
+    const void *cv;
+    void *v;
+  } const_cast;
+
+  const_cast.cv = view->base;
+  if (munmap (const_cast.v, view->len) < 0)
+    error_callback (data, "munmap", errno);
+}
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/move-if-change b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/move-if-change
new file mode 100644
index 0000000..88d9574
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/move-if-change
@@ -0,0 +1,83 @@
+#!/bin/sh
+# Like mv $1 $2, but if the files are the same, just delete $1.
+# Status is zero if successful, nonzero otherwise.
+
+VERSION='2012-01-06 07:23'; # UTC
+# The definition above must lie within the first 8 lines in order
+# for the Emacs time-stamp write hook (at end) to update it.
+# If you change this file with Emacs, please let the write hook
+# do its job.  Otherwise, update this string manually.
+
+# Copyright (C) 2002-2014 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program 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 General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+usage="usage: $0 SOURCE DEST"
+
+help="$usage
+  or:  $0 OPTION
+If SOURCE is different than DEST, then move it to DEST; else remove SOURCE.
+
+  --help     display this help and exit
+  --version  output version information and exit
+
+The variable CMPPROG can be used to specify an alternative to 'cmp'.
+
+Report bugs to <bug-gnulib@gnu.org>."
+
+version=`expr "$VERSION" : '\([^ ]*\)'`
+version="move-if-change (gnulib) $version
+Copyright (C) 2011 Free Software Foundation, Inc.
+License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
+This is free software: you are free to change and redistribute it.
+There is NO WARRANTY, to the extent permitted by law."
+
+cmpprog=${CMPPROG-cmp}
+
+for arg
+do
+  case $arg in
+    --help | --hel | --he | --h)
+      exec echo "$help" ;;
+    --version | --versio | --versi | --vers | --ver | --ve | --v)
+      exec echo "$version" ;;
+    --)
+      shift
+      break ;;
+    -*)
+      echo "$0: invalid option: $arg" >&2
+      exit 1 ;;
+    *)
+      break ;;
+  esac
+done
+
+test $# -eq 2 || { echo "$0: $usage" >&2; exit 1; }
+
+if test -r "$2" && $cmpprog -- "$1" "$2" >/dev/null; then
+  rm -f -- "$1"
+else
+  if mv -f -- "$1" "$2"; then :; else
+    # Ignore failure due to a concurrent move-if-change.
+    test -r "$2" && $cmpprog -- "$1" "$2" >/dev/null && rm -f -- "$1"
+  fi
+fi
+
+## Local Variables:
+## eval: (add-hook 'write-file-hooks 'time-stamp)
+## time-stamp-start: "VERSION='"
+## time-stamp-format: "%:y-%02m-%02d %02H:%02M"
+## time-stamp-time-zone: "UTC"
+## time-stamp-end: "'; # UTC"
+## End:
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/nounwind.c b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/nounwind.c
new file mode 100644
index 0000000..0a046cc
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/nounwind.c
@@ -0,0 +1,66 @@
+/* backtrace.c -- Entry point for stack backtrace library.
+   Copyright (C) 2012-2018 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <sys/types.h>
+
+#include "backtrace.h"
+
+#include "internal.h"
+
+/* This source file is compiled if the unwind library is not
+   available.  */
+
+int
+backtrace_full (struct backtrace_state *state ATTRIBUTE_UNUSED,
+		int skip ATTRIBUTE_UNUSED,
+		backtrace_full_callback callback ATTRIBUTE_UNUSED,
+		backtrace_error_callback error_callback, void *data)
+{
+  error_callback (data,
+		  "no stack trace because unwind library not available",
+		  0);
+  return 0;
+}
+
+int
+backtrace_simple (struct backtrace_state *state ATTRIBUTE_UNUSED,
+		  int skip ATTRIBUTE_UNUSED,
+		  backtrace_simple_callback callback ATTRIBUTE_UNUSED,
+		  backtrace_error_callback error_callback, void *data)
+{
+  error_callback (data,
+		  "no stack trace because unwind library not available",
+		  0);
+  return 0;
+}
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/pecoff.c b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/pecoff.c
new file mode 100644
index 0000000..049d7e3
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/pecoff.c
@@ -0,0 +1,943 @@
+/* pecoff.c -- Get debug data from a PE/COFFF file for backtraces.
+   Copyright (C) 2015-2018 Free Software Foundation, Inc.
+   Adapted from elf.c by Tristan Gingold, AdaCore.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "backtrace.h"
+#include "internal.h"
+
+/* Coff file header.  */
+
+typedef struct {
+  uint16_t machine;
+  uint16_t number_of_sections;
+  uint32_t time_date_stamp;
+  uint32_t pointer_to_symbol_table;
+  uint32_t number_of_symbols;
+  uint16_t size_of_optional_header;
+  uint16_t characteristics;
+} b_coff_file_header;
+
+/* Coff optional header.  */
+
+typedef struct {
+  uint16_t magic;
+  uint8_t  major_linker_version;
+  uint8_t  minor_linker_version;
+  uint32_t size_of_code;
+  uint32_t size_of_initialized_data;
+  uint32_t size_of_uninitialized_data;
+  uint32_t address_of_entry_point;
+  uint32_t base_of_code;
+  union {
+    struct {
+      uint32_t base_of_data;
+      uint32_t image_base;
+    } pe;
+    struct {
+      uint64_t image_base;
+    } pep;
+  } u;
+} b_coff_optional_header;
+
+/* Values of magic in optional header.  */
+
+#define PE_MAGIC 0x10b		/* PE32 executable.  */
+#define PEP_MAGIC 0x20b		/* PE32+ executable (for 64bit targets).  */
+
+/* Coff section header.  */
+
+typedef struct {
+  char name[8];
+  uint32_t virtual_size;
+  uint32_t virtual_address;
+  uint32_t size_of_raw_data;
+  uint32_t pointer_to_raw_data;
+  uint32_t pointer_to_relocations;
+  uint32_t pointer_to_line_numbers;
+  uint16_t number_of_relocations;
+  uint16_t number_of_line_numbers;
+  uint32_t characteristics;
+} b_coff_section_header;
+
+/* Coff symbol name.  */
+
+typedef union {
+  char short_name[8];
+  struct {
+    unsigned char zeroes[4];
+    unsigned char off[4];
+  } long_name;
+} b_coff_name;
+
+/* Coff symbol (external representation which is unaligned).  */
+
+typedef struct {
+  b_coff_name name;
+  unsigned char value[4];
+  unsigned char section_number[2];
+  unsigned char type[2];
+  unsigned char storage_class;
+  unsigned char number_of_aux_symbols;
+} b_coff_external_symbol;
+
+/* Symbol types.  */
+
+#define N_TBSHFT 4			/* Shift for the derived type.  */
+#define IMAGE_SYM_DTYPE_FUNCTION 2	/* Function derived type.  */
+
+/* Size of a coff symbol.  */
+
+#define SYM_SZ 18
+
+/* Coff symbol, internal representation (aligned).  */
+
+typedef struct {
+  const char *name;
+  uint32_t value;
+  int16_t sec;
+  uint16_t type;
+  uint16_t sc;
+} b_coff_internal_symbol;
+
+/* An index of sections we care about.  */
+
+enum debug_section
+{
+  DEBUG_INFO,
+  DEBUG_LINE,
+  DEBUG_ABBREV,
+  DEBUG_RANGES,
+  DEBUG_STR,
+  DEBUG_MAX
+};
+
+/* Names of sections, indexed by enum debug_section.  */
+
+static const char * const debug_section_names[DEBUG_MAX] =
+{
+  ".debug_info",
+  ".debug_line",
+  ".debug_abbrev",
+  ".debug_ranges",
+  ".debug_str"
+};
+
+/* Information we gather for the sections we care about.  */
+
+struct debug_section_info
+{
+  /* Section file offset.  */
+  off_t offset;
+  /* Section size.  */
+  size_t size;
+  /* Section contents, after read from file.  */
+  const unsigned char *data;
+};
+
+/* Information we keep for an coff symbol.  */
+
+struct coff_symbol
+{
+  /* The name of the symbol.  */
+  const char *name;
+  /* The address of the symbol.  */
+  uintptr_t address;
+};
+
+/* Information to pass to coff_syminfo.  */
+
+struct coff_syminfo_data
+{
+  /* Symbols for the next module.  */
+  struct coff_syminfo_data *next;
+  /* The COFF symbols, sorted by address.  */
+  struct coff_symbol *symbols;
+  /* The number of symbols.  */
+  size_t count;
+};
+
+/* A dummy callback function used when we can't find any debug info.  */
+
+static int
+coff_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
+	      uintptr_t pc ATTRIBUTE_UNUSED,
+	      backtrace_full_callback callback ATTRIBUTE_UNUSED,
+	      backtrace_error_callback error_callback, void *data)
+{
+  error_callback (data, "no debug info in PE/COFF executable", -1);
+  return 0;
+}
+
+/* A dummy callback function used when we can't find a symbol
+   table.  */
+
+static void
+coff_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,
+	     uintptr_t addr ATTRIBUTE_UNUSED,
+	     backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,
+	     backtrace_error_callback error_callback, void *data)
+{
+  error_callback (data, "no symbol table in PE/COFF executable", -1);
+}
+
+/* Read a potentially unaligned 4 byte word at P, using native endianness.  */
+
+static uint32_t
+coff_read4 (const unsigned char *p)
+{
+  uint32_t res;
+
+  memcpy (&res, p, 4);
+  return res;
+}
+
+/* Read a potentially unaligned 2 byte word at P, using native endianness.
+   All 2 byte word in symbols are always aligned, but for coherency all
+   fields are declared as char arrays.  */
+
+static uint16_t
+coff_read2 (const unsigned char *p)
+{
+  uint16_t res;
+
+  memcpy (&res, p, sizeof (res));
+  return res;
+}
+
+/* Return the length (without the trailing 0) of a COFF short name.  */
+
+static size_t
+coff_short_name_len (const char *name)
+{
+  int i;
+
+  for (i = 0; i < 8; i++)
+    if (name[i] == 0)
+      return i;
+  return 8;
+}
+
+/* Return true iff COFF short name CNAME is the same as NAME (a NUL-terminated
+   string).  */
+
+static int
+coff_short_name_eq (const char *name, const char *cname)
+{
+  int i;
+
+  for (i = 0; i < 8; i++)
+    {
+      if (name[i] != cname[i])
+	return 0;
+      if (name[i] == 0)
+	return 1;
+    }
+  return name[8] == 0;
+}
+
+/* Return true iff NAME is the same as string at offset OFF.  */
+
+static int
+coff_long_name_eq (const char *name, unsigned int off,
+		   struct backtrace_view *str_view)
+{
+  if (off >= str_view->len)
+    return 0;
+  return strcmp (name, (const char *)str_view->data + off) == 0;
+}
+
+/* Compare struct coff_symbol for qsort.  */
+
+static int
+coff_symbol_compare (const void *v1, const void *v2)
+{
+  const struct coff_symbol *e1 = (const struct coff_symbol *) v1;
+  const struct coff_symbol *e2 = (const struct coff_symbol *) v2;
+
+  if (e1->address < e2->address)
+    return -1;
+  else if (e1->address > e2->address)
+    return 1;
+  else
+    return 0;
+}
+
+/* Convert SYM to internal (and aligned) format ISYM, using string table
+   from STRTAB and STRTAB_SIZE, and number of sections SECTS_NUM.
+   Return -1 in case of error (invalid section number or string index).  */
+
+static int
+coff_expand_symbol (b_coff_internal_symbol *isym,
+		    const b_coff_external_symbol *sym,
+		    uint16_t sects_num,
+		    const unsigned char *strtab, size_t strtab_size)
+{
+  isym->type = coff_read2 (sym->type);
+  isym->sec = coff_read2 (sym->section_number);
+  isym->sc = sym->storage_class;
+
+  if (isym->sec > 0 && (uint16_t) isym->sec > sects_num)
+    return -1;
+  if (sym->name.short_name[0] != 0)
+    isym->name = sym->name.short_name;
+  else
+    {
+      uint32_t off = coff_read4 (sym->name.long_name.off);
+
+      if (off >= strtab_size)
+	return -1;
+      isym->name = (const char *) strtab + off;
+    }
+  return 0;
+}
+
+/* Return true iff SYM is a defined symbol for a function.  Data symbols
+   aren't considered because they aren't easily identified (same type as
+   section names, presence of symbols defined by the linker script).  */
+
+static int
+coff_is_function_symbol (const b_coff_internal_symbol *isym)
+{
+  return (isym->type >> N_TBSHFT) == IMAGE_SYM_DTYPE_FUNCTION
+    && isym->sec > 0;
+}
+
+/* Initialize the symbol table info for coff_syminfo.  */
+
+static int
+coff_initialize_syminfo (struct backtrace_state *state,
+			 uintptr_t base_address,
+			 const b_coff_section_header *sects, size_t sects_num,
+			 const b_coff_external_symbol *syms, size_t syms_size,
+			 const unsigned char *strtab, size_t strtab_size,
+			 backtrace_error_callback error_callback,
+			 void *data, struct coff_syminfo_data *sdata)
+{
+  size_t syms_count;
+  char *coff_symstr;
+  size_t coff_symstr_len;
+  size_t coff_symbol_count;
+  size_t coff_symbol_size;
+  struct coff_symbol *coff_symbols;
+  struct coff_symbol *coff_sym;
+  char *coff_str;
+  size_t i;
+
+  syms_count = syms_size / SYM_SZ;
+
+  /* We only care about function symbols.  Count them.  Also count size of
+     strings for in-symbol names.  */
+  coff_symbol_count = 0;
+  coff_symstr_len = 0;
+  for (i = 0; i < syms_count; ++i)
+    {
+      const b_coff_external_symbol *asym = &syms[i];
+      b_coff_internal_symbol isym;
+
+      if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size) < 0)
+	{
+	  error_callback (data, "invalid section or offset in coff symbol", 0);
+	  return 0;
+	}
+      if (coff_is_function_symbol (&isym))
+	{
+	  ++coff_symbol_count;
+	  if (asym->name.short_name[0] != 0)
+	    coff_symstr_len += coff_short_name_len (asym->name.short_name) + 1;
+	}
+
+      i += asym->number_of_aux_symbols;
+    }
+
+  coff_symbol_size = (coff_symbol_count + 1) * sizeof (struct coff_symbol);
+  coff_symbols = ((struct coff_symbol *)
+		  backtrace_alloc (state, coff_symbol_size, error_callback,
+				   data));
+  if (coff_symbols == NULL)
+    return 0;
+
+  /* Allocate memory for symbols strings.  */
+  if (coff_symstr_len > 0)
+    {
+      coff_symstr = ((char *)
+		     backtrace_alloc (state, coff_symstr_len, error_callback,
+				      data));
+      if (coff_symstr == NULL)
+	{
+	  backtrace_free (state, coff_symbols, coff_symbol_size,
+			  error_callback, data);
+	  return 0;
+	}
+    }
+  else
+    coff_symstr = NULL;
+
+  /* Copy symbols.  */
+  coff_sym = coff_symbols;
+  coff_str = coff_symstr;
+  for (i = 0; i < syms_count; ++i)
+    {
+      const b_coff_external_symbol *asym = &syms[i];
+      b_coff_internal_symbol isym;
+
+      if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size))
+	{
+	  /* Should not fail, as it was already tested in the previous
+	     loop.  */
+	  abort ();
+	}
+      if (coff_is_function_symbol (&isym))
+	{
+	  const char *name;
+	  int16_t secnum;
+
+	  if (asym->name.short_name[0] != 0)
+	    {
+	      size_t len = coff_short_name_len (isym.name);
+	      name = coff_str;
+	      memcpy (coff_str, isym.name, len);
+	      coff_str[len] = 0;
+	      coff_str += len + 1;
+	    }
+	  else
+	    name = isym.name;
+
+	  /* Strip leading '_'.  */
+	  if (name[0] == '_')
+	    name++;
+
+	  /* Symbol value is section relative, so we need to read the address
+	     of its section.  */
+	  secnum = coff_read2 (asym->section_number);
+
+	  coff_sym->name = name;
+	  coff_sym->address = (coff_read4 (asym->value)
+			       + sects[secnum - 1].virtual_address
+			       + base_address);
+	  coff_sym++;
+	}
+
+      i += asym->number_of_aux_symbols;
+    }
+
+  /* End of symbols marker.  */
+  coff_sym->name = NULL;
+  coff_sym->address = -1;
+
+  backtrace_qsort (coff_symbols, coff_symbol_count,
+		   sizeof (struct coff_symbol), coff_symbol_compare);
+
+  sdata->next = NULL;
+  sdata->symbols = coff_symbols;
+  sdata->count = coff_symbol_count;
+
+  return 1;
+}
+
+/* Add EDATA to the list in STATE.  */
+
+static void
+coff_add_syminfo_data (struct backtrace_state *state,
+		       struct coff_syminfo_data *sdata)
+{
+  if (!state->threaded)
+    {
+      struct coff_syminfo_data **pp;
+
+      for (pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
+	   *pp != NULL;
+	   pp = &(*pp)->next)
+	;
+      *pp = sdata;
+    }
+  else
+    {
+      while (1)
+	{
+	  struct coff_syminfo_data **pp;
+
+	  pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
+
+	  while (1)
+	    {
+	      struct coff_syminfo_data *p;
+
+	      p = backtrace_atomic_load_pointer (pp);
+
+	      if (p == NULL)
+		break;
+
+	      pp = &p->next;
+	    }
+
+	  if (__sync_bool_compare_and_swap (pp, NULL, sdata))
+	    break;
+	}
+    }
+}
+
+/* Compare an ADDR against an elf_symbol for bsearch.  We allocate one
+   extra entry in the array so that this can look safely at the next
+   entry.  */
+
+static int
+coff_symbol_search (const void *vkey, const void *ventry)
+{
+  const uintptr_t *key = (const uintptr_t *) vkey;
+  const struct coff_symbol *entry = (const struct coff_symbol *) ventry;
+  uintptr_t addr;
+
+  addr = *key;
+  if (addr < entry->address)
+    return -1;
+  else if (addr >= entry[1].address)
+    return 1;
+  else
+    return 0;
+}
+
+/* Return the symbol name and value for an ADDR.  */
+
+static void
+coff_syminfo (struct backtrace_state *state, uintptr_t addr,
+	      backtrace_syminfo_callback callback,
+	      backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
+	      void *data)
+{
+  struct coff_syminfo_data *sdata;
+  struct coff_symbol *sym = NULL;
+
+  if (!state->threaded)
+    {
+      for (sdata = (struct coff_syminfo_data *) state->syminfo_data;
+	   sdata != NULL;
+	   sdata = sdata->next)
+	{
+	  sym = ((struct coff_symbol *)
+		 bsearch (&addr, sdata->symbols, sdata->count,
+			  sizeof (struct coff_symbol), coff_symbol_search));
+	  if (sym != NULL)
+	    break;
+	}
+    }
+  else
+    {
+      struct coff_syminfo_data **pp;
+
+      pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
+      while (1)
+	{
+	  sdata = backtrace_atomic_load_pointer (pp);
+	  if (sdata == NULL)
+	    break;
+
+	  sym = ((struct coff_symbol *)
+		 bsearch (&addr, sdata->symbols, sdata->count,
+			  sizeof (struct coff_symbol), coff_symbol_search));
+	  if (sym != NULL)
+	    break;
+
+	  pp = &sdata->next;
+	}
+    }
+
+  if (sym == NULL)
+    callback (data, addr, NULL, 0, 0);
+  else
+    callback (data, addr, sym->name, sym->address, 0);
+}
+
+/* Add the backtrace data for one PE/COFF file.  Returns 1 on success,
+   0 on failure (in both cases descriptor is closed).  */
+
+static int
+coff_add (struct backtrace_state *state, int descriptor,
+	  backtrace_error_callback error_callback, void *data,
+	  fileline *fileline_fn, int *found_sym, int *found_dwarf)
+{
+  struct backtrace_view fhdr_view;
+  off_t fhdr_off;
+  int magic_ok;
+  b_coff_file_header fhdr;
+  off_t opt_sects_off;
+  size_t opt_sects_size;
+  unsigned int sects_num;
+  struct backtrace_view sects_view;
+  int sects_view_valid;
+  const b_coff_optional_header *opt_hdr;
+  const b_coff_section_header *sects;
+  struct backtrace_view str_view;
+  int str_view_valid;
+  uint32_t str_size;
+  off_t str_off;
+  // NOTE: upstream doesn't have `{0}`, this is a fix for Rust issue #39468.
+  //       If syms_view is not initialized, then `free(syms_view.base)` may segfault later.
+  struct backtrace_view syms_view = {0};
+  off_t syms_off;
+  size_t syms_size;
+  int syms_view_valid;
+  unsigned int syms_num;
+  unsigned int i;
+  struct debug_section_info sections[DEBUG_MAX];
+  off_t min_offset;
+  off_t max_offset;
+  struct backtrace_view debug_view;
+  int debug_view_valid;
+  uintptr_t image_base;
+
+  *found_sym = 0;
+  *found_dwarf = 0;
+
+  sects_view_valid = 0;
+  syms_view_valid = 0;
+  str_view_valid = 0;
+  debug_view_valid = 0;
+
+  /* Map the MS-DOS stub (if any) and extract file header offset.  */
+  if (!backtrace_get_view (state, descriptor, 0, 0x40, error_callback,
+			   data, &fhdr_view))
+    goto fail;
+
+  {
+    const unsigned char *vptr = fhdr_view.data;
+
+    if (vptr[0] == 'M' && vptr[1] == 'Z')
+      fhdr_off = coff_read4 (vptr + 0x3c);
+    else
+      fhdr_off = 0;
+  }
+
+  backtrace_release_view (state, &fhdr_view, error_callback, data);
+
+  /* Map the coff file header.  */
+  if (!backtrace_get_view (state, descriptor, fhdr_off,
+			   sizeof (b_coff_file_header) + 4,
+			   error_callback, data, &fhdr_view))
+    goto fail;
+
+  if (fhdr_off != 0)
+    {
+      const char *magic = (const char *) fhdr_view.data;
+      magic_ok = memcmp (magic, "PE\0", 4) == 0;
+      fhdr_off += 4;
+
+      memcpy (&fhdr, fhdr_view.data + 4, sizeof fhdr);
+    }
+  else
+    {
+      memcpy (&fhdr, fhdr_view.data, sizeof fhdr);
+      /* TODO: test fhdr.machine for coff but non-PE platforms.  */
+      magic_ok = 0;
+    }
+  backtrace_release_view (state, &fhdr_view, error_callback, data);
+
+  if (!magic_ok)
+    {
+      error_callback (data, "executable file is not COFF", 0);
+      goto fail;
+    }
+
+  sects_num = fhdr.number_of_sections;
+  syms_num = fhdr.number_of_symbols;
+
+  opt_sects_off = fhdr_off + sizeof (fhdr);
+  opt_sects_size = (fhdr.size_of_optional_header
+		    + sects_num * sizeof (b_coff_section_header));
+
+  /* To translate PC to file/line when using DWARF, we need to find
+     the .debug_info and .debug_line sections.  */
+
+  /* Read the optional header and the section headers.  */
+
+  if (!backtrace_get_view (state, descriptor, opt_sects_off, opt_sects_size,
+			   error_callback, data, &sects_view))
+    goto fail;
+  sects_view_valid = 1;
+  opt_hdr = (const b_coff_optional_header *) sects_view.data;
+  sects = (const b_coff_section_header *)
+    (sects_view.data + fhdr.size_of_optional_header);
+
+  if (fhdr.size_of_optional_header > sizeof (*opt_hdr))
+    {
+      if (opt_hdr->magic == PE_MAGIC)
+	image_base = opt_hdr->u.pe.image_base;
+      else if (opt_hdr->magic == PEP_MAGIC)
+	image_base = opt_hdr->u.pep.image_base;
+      else
+	{
+	  error_callback (data, "bad magic in PE optional header", 0);
+	  goto fail;
+	}
+    }
+  else
+    image_base = 0;
+
+  /* Read the symbol table and the string table.  */
+
+  if (fhdr.pointer_to_symbol_table == 0)
+    {
+      /* No symbol table, no string table.  */
+      str_off = 0;
+      str_size = 0;
+      syms_num = 0;
+      syms_size = 0;
+    }
+  else
+    {
+      /* Symbol table is followed by the string table.  The string table
+	 starts with its length (on 4 bytes).
+	 Map the symbol table and the length of the string table.  */
+      syms_off = fhdr.pointer_to_symbol_table;
+      syms_size = syms_num * SYM_SZ;
+
+      if (!backtrace_get_view (state, descriptor, syms_off, syms_size + 4,
+			       error_callback, data, &syms_view))
+	goto fail;
+      syms_view_valid = 1;
+
+      str_size = coff_read4 (syms_view.data + syms_size);
+
+      str_off = syms_off + syms_size;
+
+      if (str_size > 4)
+	{
+	  /* Map string table (including the length word).  */
+
+	  if (!backtrace_get_view (state, descriptor, str_off, str_size,
+				   error_callback, data, &str_view))
+	    goto fail;
+	  str_view_valid = 1;
+	}
+    }
+
+  memset (sections, 0, sizeof sections);
+
+  /* Look for the symbol table.  */
+  for (i = 0; i < sects_num; ++i)
+    {
+      const b_coff_section_header *s = sects + i;
+      unsigned int str_off;
+      int j;
+
+      if (s->name[0] == '/')
+	{
+	  /* Extended section name.  */
+	  str_off = atoi (s->name + 1);
+	}
+      else
+	str_off = 0;
+
+      for (j = 0; j < (int) DEBUG_MAX; ++j)
+	{
+	  const char *dbg_name = debug_section_names[j];
+	  int match;
+
+	  if (str_off != 0)
+	    match = coff_long_name_eq (dbg_name, str_off, &str_view);
+	  else
+	    match = coff_short_name_eq (dbg_name, s->name);
+	  if (match)
+	    {
+	      sections[j].offset = s->pointer_to_raw_data;
+	      sections[j].size = s->virtual_size <= s->size_of_raw_data ?
+		s->virtual_size : s->size_of_raw_data;
+	      break;
+	    }
+	}
+    }
+
+  if (syms_num != 0)
+    {
+      struct coff_syminfo_data *sdata;
+
+      sdata = ((struct coff_syminfo_data *)
+	       backtrace_alloc (state, sizeof *sdata, error_callback, data));
+      if (sdata == NULL)
+	goto fail;
+
+      if (!coff_initialize_syminfo (state, image_base,
+				    sects, sects_num,
+				    syms_view.data, syms_size,
+				    str_view.data, str_size,
+				    error_callback, data, sdata))
+	{
+	  backtrace_free (state, sdata, sizeof *sdata, error_callback, data);
+	  goto fail;
+	}
+
+      *found_sym = 1;
+
+      coff_add_syminfo_data (state, sdata);
+    }
+
+  backtrace_release_view (state, &sects_view, error_callback, data);
+  sects_view_valid = 0;
+  if (syms_view_valid)
+    {
+      backtrace_release_view (state, &syms_view, error_callback, data);
+      syms_view_valid = 0;
+    }
+
+  /* Read all the debug sections in a single view, since they are
+     probably adjacent in the file.  We never release this view.  */
+
+  min_offset = 0;
+  max_offset = 0;
+  for (i = 0; i < (int) DEBUG_MAX; ++i)
+    {
+      off_t end;
+
+      if (sections[i].size == 0)
+	continue;
+      if (min_offset == 0 || sections[i].offset < min_offset)
+	min_offset = sections[i].offset;
+      end = sections[i].offset + sections[i].size;
+      if (end > max_offset)
+	max_offset = end;
+    }
+  if (min_offset == 0 || max_offset == 0)
+    {
+      if (!backtrace_close (descriptor, error_callback, data))
+	goto fail;
+      *fileline_fn = coff_nodebug;
+      return 1;
+    }
+
+  if (!backtrace_get_view (state, descriptor, min_offset,
+			   max_offset - min_offset,
+			   error_callback, data, &debug_view))
+    goto fail;
+  debug_view_valid = 1;
+
+  /* We've read all we need from the executable.  */
+  if (!backtrace_close (descriptor, error_callback, data))
+    goto fail;
+  descriptor = -1;
+
+  for (i = 0; i < (int) DEBUG_MAX; ++i)
+    {
+      if (sections[i].size == 0)
+	sections[i].data = NULL;
+      else
+	sections[i].data = ((const unsigned char *) debug_view.data
+			    + (sections[i].offset - min_offset));
+    }
+
+  if (!backtrace_dwarf_add (state, /* base_address */ 0,
+			    sections[DEBUG_INFO].data,
+			    sections[DEBUG_INFO].size,
+			    sections[DEBUG_LINE].data,
+			    sections[DEBUG_LINE].size,
+			    sections[DEBUG_ABBREV].data,
+			    sections[DEBUG_ABBREV].size,
+			    sections[DEBUG_RANGES].data,
+			    sections[DEBUG_RANGES].size,
+			    sections[DEBUG_STR].data,
+			    sections[DEBUG_STR].size,
+			    0, /* FIXME */
+			    error_callback, data, fileline_fn))
+    goto fail;
+
+  *found_dwarf = 1;
+
+  return 1;
+
+ fail:
+  if (sects_view_valid)
+    backtrace_release_view (state, &sects_view, error_callback, data);
+  if (str_view_valid)
+    backtrace_release_view (state, &str_view, error_callback, data);
+  if (syms_view_valid)
+    backtrace_release_view (state, &syms_view, error_callback, data);
+  if (debug_view_valid)
+    backtrace_release_view (state, &debug_view, error_callback, data);
+  if (descriptor != -1)
+    backtrace_close (descriptor, error_callback, data);
+  return 0;
+}
+
+/* Initialize the backtrace data we need from an ELF executable.  At
+   the ELF level, all we need to do is find the debug info
+   sections.  */
+
+int
+backtrace_initialize (struct backtrace_state *state,
+		      const char *filename ATTRIBUTE_UNUSED, int descriptor,
+		      backtrace_error_callback error_callback,
+		      void *data, fileline *fileline_fn)
+{
+  int ret;
+  int found_sym;
+  int found_dwarf;
+  fileline coff_fileline_fn;
+
+  ret = coff_add (state, descriptor, error_callback, data,
+		  &coff_fileline_fn, &found_sym, &found_dwarf);
+  if (!ret)
+    return 0;
+
+  if (!state->threaded)
+    {
+      if (found_sym)
+	state->syminfo_fn = coff_syminfo;
+      else if (state->syminfo_fn == NULL)
+	state->syminfo_fn = coff_nosyms;
+    }
+  else
+    {
+      if (found_sym)
+	backtrace_atomic_store_pointer (&state->syminfo_fn, coff_syminfo);
+      else
+	__sync_bool_compare_and_swap (&state->syminfo_fn, NULL, coff_nosyms);
+    }
+
+  if (!state->threaded)
+    {
+      if (state->fileline_fn == NULL || state->fileline_fn == coff_nodebug)
+	*fileline_fn = coff_fileline_fn;
+    }
+  else
+    {
+      fileline current_fn;
+
+      current_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
+      if (current_fn == NULL || current_fn == coff_nodebug)
+	*fileline_fn = coff_fileline_fn;
+    }
+
+  return 1;
+}
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/posix.c b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/posix.c
new file mode 100644
index 0000000..ce441d9
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/posix.c
@@ -0,0 +1,100 @@
+/* posix.c -- POSIX file I/O routines for the backtrace library.
+   Copyright (C) 2012-2018 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "backtrace.h"
+#include "internal.h"
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
+
+#ifndef FD_CLOEXEC
+#define FD_CLOEXEC 1
+#endif
+
+/* Open a file for reading.  */
+
+int
+backtrace_open (const char *filename, backtrace_error_callback error_callback,
+		void *data, int *does_not_exist)
+{
+  int descriptor;
+
+  if (does_not_exist != NULL)
+    *does_not_exist = 0;
+
+  descriptor = open (filename, (int) (O_RDONLY | O_BINARY | O_CLOEXEC));
+  if (descriptor < 0)
+    {
+      if (does_not_exist != NULL && errno == ENOENT)
+	*does_not_exist = 1;
+      else
+	error_callback (data, filename, errno);
+      return -1;
+    }
+
+#ifdef HAVE_FCNTL
+  /* Set FD_CLOEXEC just in case the kernel does not support
+     O_CLOEXEC. It doesn't matter if this fails for some reason.
+     FIXME: At some point it should be safe to only do this if
+     O_CLOEXEC == 0.  */
+  fcntl (descriptor, F_SETFD, FD_CLOEXEC);
+#endif
+
+  return descriptor;
+}
+
+/* Close DESCRIPTOR.  */
+
+int
+backtrace_close (int descriptor, backtrace_error_callback error_callback,
+		 void *data)
+{
+  if (close (descriptor) < 0)
+    {
+      error_callback (data, "close", errno);
+      return 0;
+    }
+  return 1;
+}
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/print.c b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/print.c
new file mode 100644
index 0000000..3c6bad2
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/print.c
@@ -0,0 +1,92 @@
+/* print.c -- Print the current backtrace.
+   Copyright (C) 2012-2018 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "backtrace.h"
+#include "internal.h"
+
+/* Passed to callbacks.  */
+
+struct print_data
+{
+  struct backtrace_state *state;
+  FILE *f;
+};
+
+/* Print one level of a backtrace.  */
+
+static int
+print_callback (void *data, uintptr_t pc, const char *filename, int lineno,
+		const char *function)
+{
+  struct print_data *pdata = (struct print_data *) data;
+
+  fprintf (pdata->f, "0x%lx %s\n\t%s:%d\n",
+	   (unsigned long) pc,
+	   function == NULL ? "???" : function,
+	   filename == NULL ? "???" : filename,
+	   lineno);
+  return 0;
+}
+
+/* Print errors to stderr.  */
+
+static void
+error_callback (void *data, const char *msg, int errnum)
+{
+  struct print_data *pdata = (struct print_data *) data;
+
+  if (pdata->state->filename != NULL)
+    fprintf (stderr, "%s: ", pdata->state->filename);
+  fprintf (stderr, "libbacktrace: %s", msg);
+  if (errnum > 0)
+    fprintf (stderr, ": %s", strerror (errnum));
+  fputc ('\n', stderr);
+}
+
+/* Print a backtrace.  */
+
+void
+backtrace_print (struct backtrace_state *state, int skip, FILE *f)
+{
+  struct print_data data;
+
+  data.state = state;
+  data.f = f;
+  backtrace_full (state, skip + 1, print_callback, error_callback,
+		  (void *) &data);
+}
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/read.c b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/read.c
new file mode 100644
index 0000000..211d645
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/read.c
@@ -0,0 +1,96 @@
+/* read.c -- File views without mmap.
+   Copyright (C) 2012-2018 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "backtrace.h"
+#include "internal.h"
+
+/* This file implements file views when mmap is not available.  */
+
+/* Create a view of SIZE bytes from DESCRIPTOR at OFFSET.  */
+
+int
+backtrace_get_view (struct backtrace_state *state, int descriptor,
+		    off_t offset, size_t size,
+		    backtrace_error_callback error_callback,
+		    void *data, struct backtrace_view *view)
+{
+  ssize_t got;
+
+  if (lseek (descriptor, offset, SEEK_SET) < 0)
+    {
+      error_callback (data, "lseek", errno);
+      return 0;
+    }
+
+  view->base = backtrace_alloc (state, size, error_callback, data);
+  if (view->base == NULL)
+    return 0;
+  view->data = view->base;
+  view->len = size;
+
+  got = read (descriptor, view->base, size);
+  if (got < 0)
+    {
+      error_callback (data, "read", errno);
+      free (view->base);
+      return 0;
+    }
+
+  if ((size_t) got < size)
+    {
+      error_callback (data, "file too short", 0);
+      free (view->base);
+      return 0;
+    }
+
+  return 1;
+}
+
+/* Release a view read by backtrace_get_view.  */
+
+void
+backtrace_release_view (struct backtrace_state *state,
+			struct backtrace_view *view,
+			backtrace_error_callback error_callback,
+			void *data)
+{
+  backtrace_free (state, view->base, view->len, error_callback, data);
+  view->data = NULL;
+  view->base = NULL;
+}
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/simple.c b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/simple.c
new file mode 100644
index 0000000..510877c
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/simple.c
@@ -0,0 +1,108 @@
+/* simple.c -- The backtrace_simple function.
+   Copyright (C) 2012-2018 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include "unwind.h"
+#include "backtrace.h"
+
+/* The simple_backtrace routine.  */
+
+/* Data passed through _Unwind_Backtrace.  */
+
+struct backtrace_simple_data
+{
+  /* Number of frames to skip.  */
+  int skip;
+  /* Library state.  */
+  struct backtrace_state *state;
+  /* Callback routine.  */
+  backtrace_simple_callback callback;
+  /* Error callback routine.  */
+  backtrace_error_callback error_callback;
+  /* Data to pass to callback routine.  */
+  void *data;
+  /* Value to return from backtrace.  */
+  int ret;
+};
+
+/* Unwind library callback routine.  This is passd to
+   _Unwind_Backtrace.  */
+
+static _Unwind_Reason_Code
+simple_unwind (struct _Unwind_Context *context, void *vdata)
+{
+  struct backtrace_simple_data *bdata = (struct backtrace_simple_data *) vdata;
+  uintptr_t pc;
+  int ip_before_insn = 0;
+
+#ifdef HAVE_GETIPINFO
+  pc = _Unwind_GetIPInfo (context, &ip_before_insn);
+#else
+  pc = _Unwind_GetIP (context);
+#endif
+
+  if (bdata->skip > 0)
+    {
+      --bdata->skip;
+      return _URC_NO_REASON;
+    }
+
+  if (!ip_before_insn)
+    --pc;
+
+  bdata->ret = bdata->callback (bdata->data, pc);
+
+  if (bdata->ret != 0)
+    return _URC_END_OF_STACK;
+
+  return _URC_NO_REASON;
+}
+
+/* Get a simple stack backtrace.  */
+
+int
+backtrace_simple (struct backtrace_state *state, int skip,
+		  backtrace_simple_callback callback,
+		  backtrace_error_callback error_callback, void *data)
+{
+  struct backtrace_simple_data bdata;
+
+  bdata.skip = skip + 1;
+  bdata.state = state;
+  bdata.callback = callback;
+  bdata.error_callback = error_callback;
+  bdata.data = data;
+  bdata.ret = 0;
+  _Unwind_Backtrace (simple_unwind, &bdata);
+  return bdata.ret;
+}
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/sort.c b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/sort.c
new file mode 100644
index 0000000..9121bcb
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/sort.c
@@ -0,0 +1,108 @@
+/* sort.c -- Sort without allocating memory
+   Copyright (C) 2012-2018 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <stddef.h>
+#include <sys/types.h>
+
+#include "backtrace.h"
+#include "internal.h"
+
+/* The GNU glibc version of qsort allocates memory, which we must not
+   do if we are invoked by a signal handler.  So provide our own
+   sort.  */
+
+static void
+swap (char *a, char *b, size_t size)
+{
+  size_t i;
+
+  for (i = 0; i < size; i++, a++, b++)
+    {
+      char t;
+
+      t = *a;
+      *a = *b;
+      *b = t;
+    }
+}
+
+void
+backtrace_qsort (void *basearg, size_t count, size_t size,
+		 int (*compar) (const void *, const void *))
+{
+  char *base = (char *) basearg;
+  size_t i;
+  size_t mid;
+
+ tail_recurse:
+  if (count < 2)
+    return;
+
+  /* The symbol table and DWARF tables, which is all we use this
+     routine for, tend to be roughly sorted.  Pick the middle element
+     in the array as our pivot point, so that we are more likely to
+     cut the array in half for each recursion step.  */
+  swap (base, base + (count / 2) * size, size);
+
+  mid = 0;
+  for (i = 1; i < count; i++)
+    {
+      if ((*compar) (base, base + i * size) > 0)
+	{
+	  ++mid;
+	  if (i != mid)
+	    swap (base + mid * size, base + i * size, size);
+	}
+    }
+
+  if (mid > 0)
+    swap (base, base + mid * size, size);
+
+  /* Recurse with the smaller array, loop with the larger one.  That
+     ensures that our maximum stack depth is log count.  */
+  if (2 * mid < count)
+    {
+      backtrace_qsort (base, mid, size, compar);
+      base += (mid + 1) * size;
+      count -= mid + 1;
+      goto tail_recurse;
+    }
+  else
+    {
+      backtrace_qsort (base + (mid + 1) * size, count - (mid + 1),
+		       size, compar);
+      count = mid;
+      goto tail_recurse;
+    }
+}
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/state.c b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/state.c
new file mode 100644
index 0000000..ad360a6
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/state.c
@@ -0,0 +1,72 @@
+/* state.c -- Create the backtrace state.
+   Copyright (C) 2012-2018 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <string.h>
+#include <sys/types.h>
+
+#include "backtrace.h"
+#include "backtrace-supported.h"
+#include "internal.h"
+
+/* Create the backtrace state.  This will then be passed to all the
+   other routines.  */
+
+struct backtrace_state *
+backtrace_create_state (const char *filename, int threaded,
+			backtrace_error_callback error_callback,
+			void *data)
+{
+  struct backtrace_state init_state;
+  struct backtrace_state *state;
+
+#ifndef HAVE_SYNC_FUNCTIONS
+  if (threaded)
+    {
+      error_callback (data, "backtrace library does not support threads", 0);
+      return NULL;
+    }
+#endif
+
+  memset (&init_state, 0, sizeof init_state);
+  init_state.filename = filename;
+  init_state.threaded = threaded;
+
+  state = ((struct backtrace_state *)
+	   backtrace_alloc (&init_state, sizeof *state, error_callback, data));
+  if (state == NULL)
+    return NULL;
+  *state = init_state;
+
+  return state;
+}
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/stest.c b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/stest.c
new file mode 100644
index 0000000..2eb9880
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/stest.c
@@ -0,0 +1,137 @@
+/* stest.c -- Test for libbacktrace internal sort function
+   Copyright (C) 2012-2018 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "backtrace.h"
+#include "internal.h"
+
+/* Test the local qsort implementation.  */
+
+#define MAX 10
+
+struct test
+{
+  size_t count;
+  int input[MAX];
+  int output[MAX];
+};
+
+static struct test tests[] =
+  {
+    {
+      10,
+      { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
+      { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }
+    },
+    {
+      9,
+      { 1, 2, 3, 4, 5, 6, 7, 8, 9 },
+      { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
+    },
+    {
+      10,
+      { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 },
+      { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
+    },
+    {
+      9,
+      { 9, 8, 7, 6, 5, 4, 3, 2, 1 },
+      { 1, 2, 3, 4, 5, 6, 7, 8, 9 },
+    },
+    {
+      10,
+      { 2, 4, 6, 8, 10, 1, 3, 5, 7, 9 },
+      { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
+    },
+    {
+      5,
+      { 4, 5, 3, 1, 2 },
+      { 1, 2, 3, 4, 5 },
+    },
+    {
+      5,
+      { 1, 1, 1, 1, 1 },
+      { 1, 1, 1, 1, 1 },
+    },
+    {
+      5,
+      { 1, 1, 2, 1, 1 },
+      { 1, 1, 1, 1, 2 },
+    },
+    {
+      5,
+      { 2, 1, 1, 1, 1 },
+      { 1, 1, 1, 1, 2 },
+    },
+  };
+
+static int
+compare (const void *a, const void *b)
+{
+  const int *ai = (const int *) a;
+  const int *bi = (const int *) b;
+
+  return *ai - *bi;
+}
+
+int
+main (int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
+{
+  int failures;
+  size_t i;
+  int a[MAX];
+
+  failures = 0;
+  for (i = 0; i < sizeof tests / sizeof tests[0]; i++)
+    {
+      memcpy (a, tests[i].input, tests[i].count * sizeof (int));
+      backtrace_qsort (a, tests[i].count, sizeof (int), compare);
+      if (memcmp (a, tests[i].output, tests[i].count * sizeof (int)) != 0)
+	{
+	  size_t j;
+
+	  fprintf (stderr, "test %d failed:", (int) i);
+	  for (j = 0; j < tests[i].count; j++)
+	    fprintf (stderr, " %d", a[j]);
+	  fprintf (stderr, "\n");
+	  ++failures;
+	}
+    }
+
+  exit (failures > 0 ? EXIT_FAILURE : EXIT_SUCCESS);
+}
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/testlib.c b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/testlib.c
new file mode 100644
index 0000000..6dbef7c
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/testlib.c
@@ -0,0 +1,234 @@
+/* testlib.c -- test functions for libbacktrace library
+   Copyright (C) 2012-2018 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "filenames.h"
+
+#include "backtrace.h"
+
+#include "testlib.h"
+
+/* The backtrace state.  */
+
+void *state;
+
+/* The number of failures.  */
+
+int failures;
+
+/* Return the base name in a path.  */
+
+const char *
+base (const char *p)
+{
+  const char *last;
+  const char *s;
+
+  last = NULL;
+  for (s = p; *s != '\0'; ++s)
+    {
+      if (IS_DIR_SEPARATOR (*s))
+	last = s + 1;
+    }
+  return last != NULL ? last : p;
+}
+
+/* Check an entry in a struct info array.  */
+
+void
+check (const char *name, int index, const struct info *all, int want_lineno,
+       const char *want_function, const char *want_file, int *failed)
+{
+  if (*failed)
+    return;
+  if (all[index].filename == NULL || all[index].function == NULL)
+    {
+      fprintf (stderr, "%s: [%d]: missing file name or function name\n",
+	       name, index);
+      *failed = 1;
+      return;
+    }
+  if (strcmp (base (all[index].filename), want_file) != 0)
+    {
+      fprintf (stderr, "%s: [%d]: got %s expected %s\n", name, index,
+	       all[index].filename, want_file);
+      *failed = 1;
+    }
+  if (all[index].lineno != want_lineno)
+    {
+      fprintf (stderr, "%s: [%d]: got %d expected %d\n", name, index,
+	       all[index].lineno, want_lineno);
+      *failed = 1;
+    }
+  if (strcmp (all[index].function, want_function) != 0)
+    {
+      fprintf (stderr, "%s: [%d]: got %s expected %s\n", name, index,
+	       all[index].function, want_function);
+      *failed = 1;
+    }
+}
+
+/* The backtrace callback function.  */
+
+int
+callback_one (void *vdata, uintptr_t pc ATTRIBUTE_UNUSED,
+	      const char *filename, int lineno, const char *function)
+{
+  struct bdata *data = (struct bdata *) vdata;
+  struct info *p;
+
+  if (data->index >= data->max)
+    {
+      fprintf (stderr, "callback_one: callback called too many times\n");
+      data->failed = 1;
+      return 1;
+    }
+
+  p = &data->all[data->index];
+  if (filename == NULL)
+    p->filename = NULL;
+  else
+    {
+      p->filename = strdup (filename);
+      assert (p->filename != NULL);
+    }
+  p->lineno = lineno;
+  if (function == NULL)
+    p->function = NULL;
+  else
+    {
+      p->function = strdup (function);
+      assert (p->function != NULL);
+    }
+  ++data->index;
+
+  return 0;
+}
+
+/* An error callback passed to backtrace.  */
+
+void
+error_callback_one (void *vdata, const char *msg, int errnum)
+{
+  struct bdata *data = (struct bdata *) vdata;
+
+  fprintf (stderr, "%s", msg);
+  if (errnum > 0)
+    fprintf (stderr, ": %s", strerror (errnum));
+  fprintf (stderr, "\n");
+  data->failed = 1;
+}
+
+/* The backtrace_simple callback function.  */
+
+int
+callback_two (void *vdata, uintptr_t pc)
+{
+  struct sdata *data = (struct sdata *) vdata;
+
+  if (data->index >= data->max)
+    {
+      fprintf (stderr, "callback_two: callback called too many times\n");
+      data->failed = 1;
+      return 1;
+    }
+
+  data->addrs[data->index] = pc;
+  ++data->index;
+
+  return 0;
+}
+
+/* An error callback passed to backtrace_simple.  */
+
+void
+error_callback_two (void *vdata, const char *msg, int errnum)
+{
+  struct sdata *data = (struct sdata *) vdata;
+
+  fprintf (stderr, "%s", msg);
+  if (errnum > 0)
+    fprintf (stderr, ": %s", strerror (errnum));
+  fprintf (stderr, "\n");
+  data->failed = 1;
+}
+
+/* The backtrace_syminfo callback function.  */
+
+void
+callback_three (void *vdata, uintptr_t pc ATTRIBUTE_UNUSED,
+		const char *symname, uintptr_t symval,
+		uintptr_t symsize)
+{
+  struct symdata *data = (struct symdata *) vdata;
+
+  if (symname == NULL)
+    data->name = NULL;
+  else
+    {
+      data->name = strdup (symname);
+      assert (data->name != NULL);
+    }
+  data->val = symval;
+  data->size = symsize;
+}
+
+/* The backtrace_syminfo error callback function.  */
+
+void
+error_callback_three (void *vdata, const char *msg, int errnum)
+{
+  struct symdata *data = (struct symdata *) vdata;
+
+  fprintf (stderr, "%s", msg);
+  if (errnum > 0)
+    fprintf (stderr, ": %s", strerror (errnum));
+  fprintf (stderr, "\n");
+  data->failed = 1;
+}
+
+/* The backtrace_create_state error callback function.  */
+
+void
+error_callback_create (void *data ATTRIBUTE_UNUSED, const char *msg,
+                       int errnum)
+{
+  fprintf (stderr, "%s", msg);
+  if (errnum > 0)
+    fprintf (stderr, ": %s", strerror (errnum));
+  fprintf (stderr, "\n");
+  exit (EXIT_FAILURE);
+}
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/testlib.h b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/testlib.h
new file mode 100644
index 0000000..5094656
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/testlib.h
@@ -0,0 +1,110 @@
+/* testlib.h -- Header for test functions for libbacktrace library
+   Copyright (C) 2012-2018 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#ifndef LIBBACKTRACE_TESTLIB_H
+#define LIBBACKTRACE_TESTLIB_H
+
+/* Portable attribute syntax.  Actually some of these tests probably
+   won't work if the attributes are not recognized.  */
+
+#ifndef GCC_VERSION
+# define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
+#endif
+
+#if (GCC_VERSION < 2007)
+# define __attribute__(x)
+#endif
+
+#ifndef ATTRIBUTE_UNUSED
+# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+#endif
+
+/* Used to collect backtrace info.  */
+
+struct info
+{
+  char *filename;
+  int lineno;
+  char *function;
+};
+
+/* Passed to backtrace callback function.  */
+
+struct bdata
+{
+  struct info *all;
+  size_t index;
+  size_t max;
+  int failed;
+};
+
+/* Passed to backtrace_simple callback function.  */
+
+struct sdata
+{
+  uintptr_t *addrs;
+  size_t index;
+  size_t max;
+  int failed;
+};
+
+/* Passed to backtrace_syminfo callback function.  */
+
+struct symdata
+{
+  const char *name;
+  uintptr_t val, size;
+  int failed;
+};
+
+/* The backtrace state.  */
+
+extern void *state;
+
+/* The number of failures.  */
+
+extern int failures;
+
+extern const char *base (const char *p);
+extern void check (const char *name, int index, const struct info *all,
+		   int want_lineno, const char *want_function,
+		   const char *want_file, int *failed);
+extern int callback_one (void *, uintptr_t, const char *, int, const char *);
+extern void error_callback_one (void *, const char *, int);
+extern int callback_two (void *, uintptr_t);
+extern void error_callback_two (void *, const char *, int);
+extern void callback_three (void *, uintptr_t, const char *, uintptr_t,
+			    uintptr_t);
+extern void error_callback_three (void *, const char *, int);
+extern void error_callback_create (void *, const char *, int);
+
+#endif /* !defined(LIBBACKTRACE_TESTLIB_H) */
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/ttest.c b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/ttest.c
new file mode 100644
index 0000000..ca55e9b
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/ttest.c
@@ -0,0 +1,161 @@
+/* ttest.c -- Test for libbacktrace library
+   Copyright (C) 2017-2018 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+/* Test using the libbacktrace library from multiple threads.  */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <pthread.h>
+
+#include "filenames.h"
+
+#include "backtrace.h"
+#include "backtrace-supported.h"
+
+#include "testlib.h"
+
+static int f2 (int) __attribute__ ((noinline));
+static int f3 (int, int) __attribute__ ((noinline));
+
+/* Test that a simple backtrace works.  This is called via
+   pthread_create.  It returns the number of failures, as void *.  */
+
+static void *
+test1_thread (void *arg ATTRIBUTE_UNUSED)
+{
+  /* Returning a value here and elsewhere avoids a tailcall which
+     would mess up the backtrace.  */
+  return (void *) (uintptr_t) (f2 (__LINE__) - 2);
+}
+
+static int
+f2 (int f1line)
+{
+  return f3 (f1line, __LINE__) + 2;
+}
+
+static int
+f3 (int f1line, int f2line)
+{
+  struct info all[20];
+  struct bdata data;
+  int f3line;
+  int i;
+
+  data.all = &all[0];
+  data.index = 0;
+  data.max = 20;
+  data.failed = 0;
+
+  f3line = __LINE__ + 1;
+  i = backtrace_full (state, 0, callback_one, error_callback_one, &data);
+
+  if (i != 0)
+    {
+      fprintf (stderr, "test1: unexpected return value %d\n", i);
+      data.failed = 1;
+    }
+
+  if (data.index < 3)
+    {
+      fprintf (stderr,
+	       "test1: not enough frames; got %zu, expected at least 3\n",
+	       data.index);
+      data.failed = 1;
+    }
+
+  check ("test1", 0, all, f3line, "f3", "ttest.c", &data.failed);
+  check ("test1", 1, all, f2line, "f2", "ttest.c", &data.failed);
+  check ("test1", 2, all, f1line, "test1_thread", "ttest.c", &data.failed);
+
+  return data.failed;
+}
+
+/* Run the test with 10 threads simultaneously.  */
+
+#define THREAD_COUNT 10
+
+static void test1 (void) __attribute__ ((unused));
+
+static void
+test1 (void)
+{
+  pthread_t atid[THREAD_COUNT];
+  int i;
+  int errnum;
+  int this_fail;
+  void *ret;
+
+  for (i = 0; i < THREAD_COUNT; i++)
+    {
+      errnum = pthread_create (&atid[i], NULL, test1_thread, NULL);
+      if (errnum != 0)
+	{
+	  fprintf (stderr, "pthread_create %d: %s\n", i, strerror (errnum));
+	  exit (EXIT_FAILURE);
+	}
+    }
+
+  this_fail = 0;
+  for (i = 0; i < THREAD_COUNT; i++)
+    {
+      errnum = pthread_join (atid[i], &ret);
+      if (errnum != 0)
+	{
+	  fprintf (stderr, "pthread_join %d: %s\n", i, strerror (errnum));
+	  exit (EXIT_FAILURE);
+	}
+      this_fail += (int) (uintptr_t) ret;
+    }
+
+  printf ("%s: threaded backtrace_full noinline\n", this_fail > 0 ? "FAIL" : "PASS");
+
+  failures += this_fail;
+}
+
+int
+main (int argc ATTRIBUTE_UNUSED, char **argv)
+{
+  state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,
+				  error_callback_create, NULL);
+
+#if BACKTRACE_SUPPORTED
+#if BACKTRACE_SUPPORTS_THREADS
+  test1 ();
+#endif
+#endif
+
+  exit (failures ? EXIT_FAILURE : EXIT_SUCCESS);
+}
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/unknown.c b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/unknown.c
new file mode 100644
index 0000000..be521a8
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/unknown.c
@@ -0,0 +1,65 @@
+/* unknown.c -- used when backtrace configury does not know file format.
+   Copyright (C) 2012-2018 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <sys/types.h>
+
+#include "backtrace.h"
+#include "internal.h"
+
+/* A trivial routine that always fails to find fileline data.  */
+
+static int
+unknown_fileline (struct backtrace_state *state ATTRIBUTE_UNUSED,
+		  uintptr_t pc, backtrace_full_callback callback,
+		  backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
+		  void *data)
+
+{
+  return callback (data, pc, NULL, 0, NULL);
+}
+
+/* Initialize the backtrace data when we don't know how to read the
+   debug info.  */
+
+int
+backtrace_initialize (struct backtrace_state *state ATTRIBUTE_UNUSED,
+		      const char *filename ATTRIBUTE_UNUSED,
+		      int descriptor ATTRIBUTE_UNUSED,
+		      backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
+		      void *data ATTRIBUTE_UNUSED, fileline *fileline_fn)
+{
+  state->fileline_data = NULL;
+  *fileline_fn = unknown_fileline;
+  return 1;
+}
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/xcoff.c b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/xcoff.c
new file mode 100644
index 0000000..1ae001d
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/xcoff.c
@@ -0,0 +1,1642 @@
+/* xcoff.c -- Get debug data from an XCOFF file for backtraces.
+   Copyright (C) 2012-2018 Free Software Foundation, Inc.
+   Adapted from elf.c.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#ifdef HAVE_LOADQUERY
+#include <sys/ldr.h>
+#endif
+
+#include "backtrace.h"
+#include "internal.h"
+
+/* The configure script must tell us whether we are 32-bit or 64-bit
+   XCOFF.  We could make this code test and support either possibility,
+   but there is no point.  This code only works for the currently
+   running executable, which means that we know the XCOFF mode at
+   configure time.  */
+
+#if BACKTRACE_XCOFF_SIZE != 32 && BACKTRACE_XCOFF_SIZE != 64
+#error "Unknown BACKTRACE_XCOFF_SIZE"
+#endif
+
+/* XCOFF file header.  */
+
+#if BACKTRACE_XCOFF_SIZE == 32
+
+typedef struct {
+  uint16_t f_magic;
+  uint16_t f_nscns;
+  uint32_t f_timdat;
+  uint32_t f_symptr;
+  uint32_t f_nsyms;
+  uint16_t f_opthdr;
+  uint16_t f_flags;
+} b_xcoff_filhdr;
+
+#define XCOFF_MAGIC	0737
+
+#else /* BACKTRACE_XCOFF_SIZE != 32 */
+
+typedef struct {
+  uint16_t f_magic;
+  uint16_t f_nscns;
+  uint32_t f_timdat;
+  uint64_t f_symptr;
+  uint16_t f_opthdr;
+  uint16_t f_flags;
+  uint32_t f_nsyms;
+} b_xcoff_filhdr;
+
+#define XCOFF_MAGIC	0767
+
+#endif /* BACKTRACE_XCOFF_SIZE != 32 */
+
+#define F_SHROBJ	0x2000	/* File is a shared object.  */
+
+/* XCOFF section header.  */
+
+#if BACKTRACE_XCOFF_SIZE == 32
+
+typedef struct {
+  char s_name[8];
+  uint32_t s_paddr;
+  uint32_t s_vaddr;
+  uint32_t s_size;
+  uint32_t s_scnptr;
+  uint32_t s_relptr;
+  uint32_t s_lnnoptr;
+  uint16_t s_nreloc;
+  uint16_t s_nlnno;
+  uint32_t s_flags;
+} b_xcoff_scnhdr;
+
+#define _OVERFLOW_MARKER	65535
+
+#else /* BACKTRACE_XCOFF_SIZE != 32 */
+
+typedef struct {
+  char name[8];
+  uint64_t s_paddr;
+  uint64_t s_vaddr;
+  uint64_t s_size;
+  uint64_t s_scnptr;
+  uint64_t s_relptr;
+  uint64_t s_lnnoptr;
+  uint32_t s_nreloc;
+  uint32_t s_nlnno;
+  uint32_t s_flags;
+} b_xcoff_scnhdr;
+
+#endif /* BACKTRACE_XCOFF_SIZE != 32 */
+
+#define STYP_DWARF	0x10	/* DWARF debugging section.  */
+#define STYP_TEXT	0x20	/* Executable text (code) section.  */
+#define STYP_OVRFLO	0x8000	/* Line-number field overflow section.  */
+
+#define SSUBTYP_DWINFO	0x10000	/* DWARF info section.  */
+#define SSUBTYP_DWLINE	0x20000	/* DWARF line-number section.  */
+#define SSUBTYP_DWARNGE	0x50000	/* DWARF aranges section.  */
+#define SSUBTYP_DWABREV	0x60000	/* DWARF abbreviation section.  */
+#define SSUBTYP_DWSTR	0x70000	/* DWARF strings section.  */
+
+/* XCOFF symbol.  */
+
+#define SYMNMLEN	8
+
+#if BACKTRACE_XCOFF_SIZE == 32
+
+typedef struct {
+  union {
+    char _name[SYMNMLEN];
+    struct {
+      uint32_t _zeroes;
+      uint32_t _offset;
+    } _s;
+  } _u;
+#define n_name		_u._name
+#define n_zeroes	_u._s._zeroes
+#define n_offset_	_u._s._offset
+
+  uint32_t n_value;
+  int16_t  n_scnum;
+  uint16_t n_type;
+  uint8_t  n_sclass;
+  uint8_t  n_numaux;
+} __attribute__ ((packed)) b_xcoff_syment;
+
+#else /* BACKTRACE_XCOFF_SIZE != 32 */
+
+typedef struct {
+  uint64_t n_value;
+  uint32_t n_offset_;
+  int16_t  n_scnum;
+  uint16_t n_type;
+  uint8_t  n_sclass;
+  uint8_t  n_numaux;
+} __attribute__ ((packed)) b_xcoff_syment;
+
+#endif /* BACKTRACE_XCOFF_SIZE != 32 */
+
+#define SYMESZ	18
+
+#define C_EXT		2	/* External symbol.  */
+#define C_FCN		101	/* Beginning or end of function.  */
+#define C_FILE		103	/* Source file name.  */
+#define C_HIDEXT	107	/* Unnamed external symbol.  */
+#define C_BINCL		108	/* Beginning of include file.  */
+#define C_EINCL		109	/* End of include file.  */
+#define C_WEAKEXT	111	/* Weak external symbol.  */
+
+#define ISFCN(x)	((x) & 0x0020)
+
+/* XCOFF AUX entry.  */
+
+#define AUXESZ		18
+#define FILNMLEN	14
+
+typedef union {
+#if BACKTRACE_XCOFF_SIZE == 32
+  struct {
+    uint16_t pad;
+    uint16_t x_lnnohi;
+    uint16_t x_lnno;
+  } x_block;
+#else
+  struct {
+    uint32_t x_lnno;
+  } x_block;
+#endif
+  union {
+    char x_fname[FILNMLEN];
+    struct {
+      uint32_t x_zeroes;
+      uint32_t x_offset;
+      char     pad[FILNMLEN-8];
+      uint8_t  x_ftype;
+    } _x;
+  } x_file;
+#if BACKTRACE_XCOFF_SIZE == 32
+  struct {
+    uint32_t x_exptr;
+    uint32_t x_fsize;
+    uint32_t x_lnnoptr;
+    uint32_t x_endndx;
+  } x_fcn;
+#else
+  struct {
+    uint64_t x_lnnoptr;
+    uint32_t x_fsize;
+    uint32_t x_endndx;
+  } x_fcn;
+#endif
+  struct {
+    uint8_t pad[AUXESZ-1];
+    uint8_t x_auxtype;
+  } x_auxtype;
+} __attribute__ ((packed)) b_xcoff_auxent;
+
+/* XCOFF line number entry.  */
+
+#if BACKTRACE_XCOFF_SIZE == 32
+
+typedef struct {
+  union {
+    uint32_t l_symndx;
+    uint32_t l_paddr;
+  } l_addr;
+  uint16_t l_lnno;
+} b_xcoff_lineno;
+
+#define LINESZ	6
+
+#else /* BACKTRACE_XCOFF_SIZE != 32 */
+
+typedef struct {
+  union {
+    uint32_t l_symndx;
+    uint64_t l_paddr;
+  } l_addr;
+  uint32_t l_lnno;
+} b_xcoff_lineno;
+
+#define LINESZ	12
+
+#endif /* BACKTRACE_XCOFF_SIZE != 32 */
+
+#if BACKTRACE_XCOFF_SIZE == 32
+#define XCOFF_AIX_TEXTBASE	0x10000000u
+#else
+#define XCOFF_AIX_TEXTBASE	0x100000000ul
+#endif
+
+/* AIX big archive fixed-length header.  */
+
+#define AIAMAGBIG	"<bigaf>\n"
+
+typedef struct {
+  char fl_magic[8];	/* Archive magic string.  */
+  char fl_memoff[20];	/* Offset to member table.  */
+  char fl_gstoff[20];	/* Offset to global symbol table.  */
+  char fl_gst64off[20];	/* Offset to global symbol table for 64-bit objects.  */
+  char fl_fstmoff[20];	/* Offset to first archive member.  */
+  char fl_freeoff[20];	/* Offset to first member on free list.  */
+} b_ar_fl_hdr;
+
+/* AIX big archive file member header.  */
+
+typedef struct {
+  char ar_size[20];	/* File member size - decimal.  */
+  char ar_nxtmem[20];	/* Next member offset - decimal.  */
+  char ar_prvmem[20];	/* Previous member offset - decimal.  */
+  char ar_date[12];	/* File member date - decimal.  */
+  char ar_uid[12];	/* File member userid - decimal.  */
+  char ar_gid[12];	/* File member group id - decimal.  */
+  char ar_mode[12];	/* File member mode - octal.  */
+  char ar_namlen[4];	/* File member name length - decimal.  */
+  char ar_name[2];	/* Start of member name.  */
+} b_ar_hdr;
+
+
+/* Information we keep for an XCOFF symbol.  */
+
+struct xcoff_symbol
+{
+  /* The name of the symbol.  */
+  const char *name;
+  /* The address of the symbol.  */
+  uintptr_t address;
+  /* The size of the symbol.  */
+  size_t size;
+};
+
+/* Information to pass to xcoff_syminfo.  */
+
+struct xcoff_syminfo_data
+{
+  /* Symbols for the next module.  */
+  struct xcoff_syminfo_data *next;
+  /* The XCOFF symbols, sorted by address.  */
+  struct xcoff_symbol *symbols;
+  /* The number of symbols.  */
+  size_t count;
+};
+
+/* Information about an include file.  */
+
+struct xcoff_incl
+{
+  /* File name.  */
+  const char *filename;
+  /* Offset to first line number from the include file.  */
+  uintptr_t begin;
+  /* Offset to last line number from the include file.  */
+  uintptr_t end;
+};
+
+/* A growable vector of include files information.  */
+
+struct xcoff_incl_vector
+{
+  /* Memory.  This is an array of struct xcoff_incl.  */
+  struct backtrace_vector vec;
+  /* Number of include files.  */
+  size_t count;
+};
+
+/* Map a single PC value to a file/function/line.  */
+
+struct xcoff_line
+{
+  /* PC.  */
+  uintptr_t pc;
+  /* File name.  Many entries in the array are expected to point to
+     the same file name.  */
+  const char *filename;
+  /* Function name.  */
+  const char *function;
+  /* Line number.  */
+  int lineno;
+};
+
+/* A growable vector of line number information.  This is used while
+   reading the line numbers.  */
+
+struct xcoff_line_vector
+{
+  /* Memory.  This is an array of struct xcoff_line.  */
+  struct backtrace_vector vec;
+  /* Number of valid mappings.  */
+  size_t count;
+};
+
+/* The information we need to map a PC to a file and line.  */
+
+struct xcoff_fileline_data
+{
+  /* The data for the next file we know about.  */
+  struct xcoff_fileline_data *next;
+  /* Line number information.  */
+  struct xcoff_line_vector vec;
+};
+
+/* An index of DWARF sections we care about.  */
+
+enum dwarf_section
+{
+  DWSECT_INFO,
+  DWSECT_LINE,
+  DWSECT_ABBREV,
+  DWSECT_RANGES,
+  DWSECT_STR,
+  DWSECT_MAX
+};
+
+/* Information we gather for the DWARF sections we care about.  */
+
+struct dwsect_info
+{
+  /* Section file offset.  */
+  off_t offset;
+  /* Section size.  */
+  size_t size;
+  /* Section contents, after read from file.  */
+  const unsigned char *data;
+};
+
+/* A dummy callback function used when we can't find any debug info.  */
+
+static int
+xcoff_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
+	       uintptr_t pc ATTRIBUTE_UNUSED,
+	       backtrace_full_callback callback ATTRIBUTE_UNUSED,
+	       backtrace_error_callback error_callback, void *data)
+{
+  error_callback (data, "no debug info in XCOFF executable", -1);
+  return 0;
+}
+
+/* A dummy callback function used when we can't find a symbol
+   table.  */
+
+static void
+xcoff_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,
+	      uintptr_t addr ATTRIBUTE_UNUSED,
+	      backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,
+	      backtrace_error_callback error_callback, void *data)
+{
+  error_callback (data, "no symbol table in XCOFF executable", -1);
+}
+
+/* Compare struct xcoff_symbol for qsort.  */
+
+static int
+xcoff_symbol_compare (const void *v1, const void *v2)
+{
+  const struct xcoff_symbol *e1 = (const struct xcoff_symbol *) v1;
+  const struct xcoff_symbol *e2 = (const struct xcoff_symbol *) v2;
+
+  if (e1->address < e2->address)
+    return -1;
+  else if (e1->address > e2->address)
+    return 1;
+  else
+    return 0;
+}
+
+/* Compare an ADDR against an xcoff_symbol for bsearch.  */
+
+static int
+xcoff_symbol_search (const void *vkey, const void *ventry)
+{
+  const uintptr_t *key = (const uintptr_t *) vkey;
+  const struct xcoff_symbol *entry = (const struct xcoff_symbol *) ventry;
+  uintptr_t addr;
+
+  addr = *key;
+  if (addr < entry->address)
+    return -1;
+  else if ((entry->size == 0 && addr > entry->address)
+	   || (entry->size > 0 && addr >= entry->address + entry->size))
+    return 1;
+  else
+    return 0;
+}
+
+/* Add XDATA to the list in STATE.  */
+
+static void
+xcoff_add_syminfo_data (struct backtrace_state *state,
+			struct xcoff_syminfo_data *xdata)
+{
+  if (!state->threaded)
+    {
+      struct xcoff_syminfo_data **pp;
+
+      for (pp = (struct xcoff_syminfo_data **) (void *) &state->syminfo_data;
+	   *pp != NULL;
+	   pp = &(*pp)->next)
+	;
+      *pp = xdata;
+    }
+  else
+    {
+      while (1)
+	{
+	  struct xcoff_syminfo_data **pp;
+
+	  pp = (struct xcoff_syminfo_data **) (void *) &state->syminfo_data;
+
+	  while (1)
+	    {
+	      struct xcoff_syminfo_data *p;
+
+	      p = backtrace_atomic_load_pointer (pp);
+
+	      if (p == NULL)
+		break;
+
+	      pp = &p->next;
+	    }
+
+	  if (__sync_bool_compare_and_swap (pp, NULL, xdata))
+	    break;
+	}
+    }
+}
+
+/* Return the symbol name and value for an ADDR.  */
+
+static void
+xcoff_syminfo (struct backtrace_state *state ATTRIBUTE_UNUSED, uintptr_t addr,
+	       backtrace_syminfo_callback callback,
+	       backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
+	       void *data)
+{
+  struct xcoff_syminfo_data *edata;
+  struct xcoff_symbol *sym = NULL;
+
+  if (!state->threaded)
+    {
+      for (edata = (struct xcoff_syminfo_data *) state->syminfo_data;
+	   edata != NULL;
+	   edata = edata->next)
+	{
+	  sym = ((struct xcoff_symbol *)
+		 bsearch (&addr, edata->symbols, edata->count,
+			  sizeof (struct xcoff_symbol), xcoff_symbol_search));
+	  if (sym != NULL)
+	    break;
+	}
+    }
+  else
+    {
+      struct xcoff_syminfo_data **pp;
+
+      pp = (struct xcoff_syminfo_data **) (void *) &state->syminfo_data;
+      while (1)
+	{
+	  edata = backtrace_atomic_load_pointer (pp);
+	  if (edata == NULL)
+	    break;
+
+	  sym = ((struct xcoff_symbol *)
+		 bsearch (&addr, edata->symbols, edata->count,
+			  sizeof (struct xcoff_symbol), xcoff_symbol_search));
+	  if (sym != NULL)
+	    break;
+
+	  pp = &edata->next;
+	}
+    }
+
+  if (sym == NULL)
+    callback (data, addr, NULL, 0, 0);
+  else
+    callback (data, addr, sym->name, sym->address, sym->size);
+}
+
+/* Return the name of an XCOFF symbol.  */
+
+static const char *
+xcoff_symname (const b_xcoff_syment *asym,
+	       const unsigned char *strtab, size_t strtab_size)
+{
+#if BACKTRACE_XCOFF_SIZE == 32
+  if (asym->n_zeroes != 0)
+    {
+      /* Make a copy as we will release the symtab view.  */
+      char name[SYMNMLEN+1];
+      strncpy (name, asym->n_name, SYMNMLEN);
+      name[SYMNMLEN] = '\0';
+      return strdup (name);
+    }
+#endif
+  if (asym->n_sclass & 0x80)
+    return NULL; /* .debug */
+  if (asym->n_offset_ >= strtab_size)
+    return NULL;
+  return (const char *) strtab + asym->n_offset_;
+}
+
+/* Initialize the symbol table info for xcoff_syminfo.  */
+
+static int
+xcoff_initialize_syminfo (struct backtrace_state *state,
+			  uintptr_t base_address,
+			  const b_xcoff_scnhdr *sects,
+			  const b_xcoff_syment *syms, size_t nsyms,
+			  const unsigned char *strtab, size_t strtab_size,
+			  backtrace_error_callback error_callback, void *data,
+			  struct xcoff_syminfo_data *sdata)
+{
+  size_t xcoff_symbol_count;
+  size_t xcoff_symbol_size;
+  struct xcoff_symbol *xcoff_symbols;
+  size_t i;
+  unsigned int j;
+
+  /* We only care about function symbols.  Count them.  */
+  xcoff_symbol_count = 0;
+  for (i = 0; i < nsyms; ++i)
+    {
+      const b_xcoff_syment *asym = &syms[i];
+      if ((asym->n_sclass == C_EXT || asym->n_sclass == C_HIDEXT
+	    || asym->n_sclass == C_WEAKEXT)
+	  && ISFCN (asym->n_type) && asym->n_numaux > 0 && asym->n_scnum > 0)
+	++xcoff_symbol_count;
+
+      i += asym->n_numaux;
+    }
+
+  xcoff_symbol_size = xcoff_symbol_count * sizeof (struct xcoff_symbol);
+  xcoff_symbols = ((struct xcoff_symbol *)
+		   backtrace_alloc (state, xcoff_symbol_size, error_callback,
+				    data));
+  if (xcoff_symbols == NULL)
+    return 0;
+
+  j = 0;
+  for (i = 0; i < nsyms; ++i)
+    {
+      const b_xcoff_syment *asym = &syms[i];
+      if ((asym->n_sclass == C_EXT || asym->n_sclass == C_HIDEXT
+	    || asym->n_sclass == C_WEAKEXT)
+	  && ISFCN (asym->n_type) && asym->n_numaux > 0 && asym->n_scnum > 0)
+	{
+	  const b_xcoff_auxent *aux = (const b_xcoff_auxent *) (asym + 1);
+	  xcoff_symbols[j].name = xcoff_symname (asym, strtab, strtab_size);
+	  xcoff_symbols[j].address = base_address + asym->n_value
+				   - sects[asym->n_scnum - 1].s_paddr;
+	  /* x_fsize will be 0 if there is no debug information.  */
+	  xcoff_symbols[j].size = aux->x_fcn.x_fsize;
+	  ++j;
+	}
+
+      i += asym->n_numaux;
+    }
+
+  backtrace_qsort (xcoff_symbols, xcoff_symbol_count,
+		   sizeof (struct xcoff_symbol), xcoff_symbol_compare);
+
+  sdata->next = NULL;
+  sdata->symbols = xcoff_symbols;
+  sdata->count = xcoff_symbol_count;
+
+  return 1;
+}
+
+/* Compare struct xcoff_line for qsort.  */
+
+static int
+xcoff_line_compare (const void *v1, const void *v2)
+{
+  const struct xcoff_line *ln1 = (const struct xcoff_line *) v1;
+  const struct xcoff_line *ln2 = (const struct xcoff_line *) v2;
+
+  if (ln1->pc < ln2->pc)
+    return -1;
+  else if (ln1->pc > ln2->pc)
+    return 1;
+  else
+    return 0;
+}
+
+/* Find a PC in a line vector.  We always allocate an extra entry at
+   the end of the lines vector, so that this routine can safely look
+   at the next entry.  */
+
+static int
+xcoff_line_search (const void *vkey, const void *ventry)
+{
+  const uintptr_t *key = (const uintptr_t *) vkey;
+  const struct xcoff_line *entry = (const struct xcoff_line *) ventry;
+  uintptr_t pc;
+
+  pc = *key;
+  if (pc < entry->pc)
+    return -1;
+  else if ((entry + 1)->pc == (uintptr_t) -1 || pc >= (entry + 1)->pc)
+    return 1;
+  else
+    return 0;
+}
+
+/* Look for a PC in the line vector for one module.  On success,
+   call CALLBACK and return whatever it returns.  On error, call
+   ERROR_CALLBACK and return 0.  Sets *FOUND to 1 if the PC is found,
+   0 if not.  */
+
+static int
+xcoff_lookup_pc (struct backtrace_state *state ATTRIBUTE_UNUSED,
+		 struct xcoff_fileline_data *fdata, uintptr_t pc,
+		 backtrace_full_callback callback,
+		 backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
+		 void *data, int *found)
+{
+  const struct xcoff_line *ln;
+  const char *function;
+
+  *found = 1;
+
+  ln = (struct xcoff_line *) bsearch (&pc, fdata->vec.vec.base,
+				      fdata->vec.count,
+				      sizeof (struct xcoff_line),
+				      xcoff_line_search);
+  if (ln == NULL)
+    {
+      *found = 0;
+      return 0;
+    }
+
+  function = ln->function;
+  /* AIX prepends a '.' to function entry points, remove it.  */
+  if (*function == '.')
+    ++function;
+  return callback (data, pc, ln->filename, ln->lineno, function);
+}
+
+/* Return the file/line information for a PC using the XCOFF lineno
+   mapping we built earlier.  */
+
+static int
+xcoff_fileline (struct backtrace_state *state, uintptr_t pc,
+		backtrace_full_callback callback,
+		backtrace_error_callback error_callback, void *data)
+
+{
+  struct xcoff_fileline_data *fdata;
+  int found;
+  int ret;
+
+  if (!state->threaded)
+    {
+      for (fdata = (struct xcoff_fileline_data *) state->fileline_data;
+	   fdata != NULL;
+	   fdata = fdata->next)
+	{
+	  ret = xcoff_lookup_pc (state, fdata, pc, callback, error_callback,
+				 data, &found);
+	  if (ret != 0 || found)
+	    return ret;
+	}
+    }
+  else
+    {
+      struct xcoff_fileline_data **pp;
+
+      pp = (struct xcoff_fileline_data **) (void *) &state->fileline_data;
+      while (1)
+	{
+	  fdata = backtrace_atomic_load_pointer (pp);
+	  if (fdata == NULL)
+	    break;
+
+	  ret = xcoff_lookup_pc (state, fdata, pc, callback, error_callback,
+				 data, &found);
+	  if (ret != 0 || found)
+	    return ret;
+
+	  pp = &fdata->next;
+	}
+    }
+
+  /* FIXME: See if any libraries have been dlopen'ed.  */
+
+  return callback (data, pc, NULL, 0, NULL);
+}
+
+/* Compare struct xcoff_incl for qsort.  */
+
+static int
+xcoff_incl_compare (const void *v1, const void *v2)
+{
+  const struct xcoff_incl *in1 = (const struct xcoff_incl *) v1;
+  const struct xcoff_incl *in2 = (const struct xcoff_incl *) v2;
+
+  if (in1->begin < in2->begin)
+    return -1;
+  else if (in1->begin > in2->begin)
+    return 1;
+  else
+    return 0;
+}
+
+/* Find a lnnoptr in an include file.  */
+
+static int
+xcoff_incl_search (const void *vkey, const void *ventry)
+{
+  const uintptr_t *key = (const uintptr_t *) vkey;
+  const struct xcoff_incl *entry = (const struct xcoff_incl *) ventry;
+  uintptr_t lnno;
+
+  lnno = *key;
+  if (lnno < entry->begin)
+    return -1;
+  else if (lnno > entry->end)
+    return 1;
+  else
+    return 0;
+}
+
+/* Add a new mapping to the vector of line mappings that we are
+   building.  Returns 1 on success, 0 on failure.  */
+
+static int
+xcoff_add_line (struct backtrace_state *state, uintptr_t pc,
+		const char *filename, const char *function, uint32_t lnno,
+		backtrace_error_callback error_callback, void *data,
+		struct xcoff_line_vector *vec)
+{
+  struct xcoff_line *ln;
+
+  ln = ((struct xcoff_line *)
+	backtrace_vector_grow (state, sizeof (struct xcoff_line),
+			       error_callback, data, &vec->vec));
+  if (ln == NULL)
+    return 0;
+
+  ln->pc = pc;
+  ln->filename = filename;
+  ln->function = function;
+  ln->lineno = lnno;
+
+  ++vec->count;
+
+  return 1;
+}
+
+/* Add the line number entries for a function to the line vector.  */
+
+static int
+xcoff_process_linenos (struct backtrace_state *state, uintptr_t base_address,
+		       const b_xcoff_syment *fsym, const char *filename,
+		       const b_xcoff_scnhdr *sects,
+		       const unsigned char *strtab, size_t strtab_size,
+		       uint32_t fcn_lnno, struct xcoff_incl_vector *vec,
+		       struct xcoff_line_vector *lvec,
+		       const unsigned char *linenos, size_t linenos_size,
+		       uintptr_t lnnoptr0,
+		       backtrace_error_callback error_callback, void *data)
+{
+  const b_xcoff_auxent *aux;
+  const b_xcoff_lineno *lineno;
+  const unsigned char *lineptr;
+  const char *function;
+  struct xcoff_incl *incl = NULL;
+  uintptr_t lnnoptr;
+  uintptr_t pc;
+  uint32_t lnno;
+  int begincl;
+
+  aux = (const b_xcoff_auxent *) (fsym + 1);
+  lnnoptr = aux->x_fcn.x_lnnoptr;
+
+  if (lnnoptr < lnnoptr0 || lnnoptr + LINESZ > lnnoptr0 + linenos_size)
+    return 0;
+
+  function = xcoff_symname (fsym, strtab, strtab_size);
+  if (function == NULL)
+    return 0;
+
+  /* Skip first entry that points to symtab.  */
+
+  lnnoptr += LINESZ;
+
+  lineptr = linenos + (lnnoptr - lnnoptr0);
+
+  begincl = -1;
+  while (lineptr + LINESZ <= linenos + linenos_size)
+    {
+      lineno = (const b_xcoff_lineno *) lineptr;
+
+      lnno = lineno->l_lnno;
+      if (lnno == 0)
+	  break;
+
+      /* If part of a function other than the beginning comes from an
+	 include file, the line numbers are absolute, rather than
+	 relative to the beginning of the function.  */
+      incl = (struct xcoff_incl *) bsearch (&lnnoptr, vec->vec.base,
+					    vec->count,
+					    sizeof (struct xcoff_incl),
+					    xcoff_incl_search);
+      if (begincl == -1)
+	begincl = incl != NULL;
+      if (incl != NULL)
+	{
+	  filename = incl->filename;
+	  if (begincl == 1)
+	    lnno += fcn_lnno - 1;
+	}
+      else
+	lnno += fcn_lnno - 1;
+
+      pc = base_address + lineno->l_addr.l_paddr
+	 - sects[fsym->n_scnum - 1].s_paddr;
+      xcoff_add_line (state, pc, filename, function, lnno, error_callback,
+		      data, lvec);
+
+      lnnoptr += LINESZ;
+      lineptr += LINESZ;
+    }
+
+  return 1;
+}
+
+/* Initialize the line vector info for xcoff_fileline.  */
+
+static int
+xcoff_initialize_fileline (struct backtrace_state *state,
+			   uintptr_t base_address,
+			   const b_xcoff_scnhdr *sects,
+			   const b_xcoff_syment *syms, size_t nsyms,
+			   const unsigned char *strtab, size_t strtab_size,
+			   const unsigned char *linenos, size_t linenos_size,
+			   uint64_t lnnoptr0,
+			   backtrace_error_callback error_callback, void *data)
+{
+  struct xcoff_fileline_data *fdata;
+  struct xcoff_incl_vector vec;
+  struct xcoff_line *ln;
+  const b_xcoff_syment *fsym;
+  const b_xcoff_auxent *aux;
+  const char *filename;
+  const char *name;
+  struct xcoff_incl *incl;
+  uintptr_t begin, end;
+  uintptr_t lnno;
+  size_t i;
+
+  fdata = ((struct xcoff_fileline_data *)
+	   backtrace_alloc (state, sizeof (struct xcoff_fileline_data),
+			    error_callback, data));
+  if (fdata == NULL)
+    return 0;
+
+  memset (fdata, 0, sizeof *fdata);
+  memset (&vec, 0, sizeof vec);
+
+  /* Process include files first.  */
+
+  begin = 0;
+  for (i = 0; i < nsyms; ++i)
+    {
+      const b_xcoff_syment *asym = &syms[i];
+
+      switch (asym->n_sclass)
+	{
+	  case C_BINCL:
+	    begin = asym->n_value;
+	    break;
+
+	  case C_EINCL:
+	    if (begin == 0)
+	      break;
+	    end = asym->n_value;
+	    incl = ((struct xcoff_incl *)
+		    backtrace_vector_grow (state, sizeof (struct xcoff_incl),
+					   error_callback, data, &vec.vec));
+	    if (incl != NULL)
+	      {
+		incl->filename = xcoff_symname (asym, strtab, strtab_size);
+		incl->begin = begin;
+		incl->end = end;
+		++vec.count;
+	      }
+	    begin = 0;
+	    break;
+	}
+
+      i += asym->n_numaux;
+    }
+
+  backtrace_qsort (vec.vec.base, vec.count,
+		   sizeof (struct xcoff_incl), xcoff_incl_compare);
+
+  filename = NULL;
+  fsym = NULL;
+  for (i = 0; i < nsyms; ++i)
+    {
+      const b_xcoff_syment *asym = &syms[i];
+
+      switch (asym->n_sclass)
+	{
+	  case C_FILE:
+	    filename = xcoff_symname (asym, strtab, strtab_size);
+	    if (filename == NULL)
+	      break;
+
+	    /* If the file auxiliary entry is not used, the symbol name is
+	       the name of the source file. If the file auxiliary entry is
+	       used, then the symbol name should be .file, and the first
+	       file auxiliary entry (by convention) contains the source
+	       file name.  */
+
+	    if (asym->n_numaux > 0 && !strcmp (filename, ".file"))
+	      {
+		aux = (const b_xcoff_auxent *) (asym + 1);
+		if (aux->x_file._x.x_zeroes != 0)
+		  {
+		    /* Make a copy as we will release the symtab view.  */
+		    char name[FILNMLEN+1];
+		    strncpy (name, aux->x_file.x_fname, FILNMLEN);
+		    name[FILNMLEN] = '\0';
+		    filename = strdup (name);
+		  }
+		else if (aux->x_file._x.x_offset < strtab_size)
+		  filename = (const char *) strtab + aux->x_file._x.x_offset;
+		else
+		  filename = NULL;
+	      }
+	    break;
+
+	  case C_EXT:
+	  case C_HIDEXT:
+	  case C_WEAKEXT:
+	    fsym = NULL;
+	    if (!ISFCN (asym->n_type) || asym->n_numaux == 0)
+	      break;
+	    if (filename == NULL)
+	      break;
+	    fsym = asym;
+	    break;
+
+	  case C_FCN:
+	    if (asym->n_numaux == 0)
+	      break;
+	    if (fsym == NULL)
+	      break;
+	    name = xcoff_symname (asym, strtab, strtab_size);
+	    if (name == NULL)
+	      break;
+	    aux = (const b_xcoff_auxent *) (asym + 1);
+#if BACKTRACE_XCOFF_SIZE == 32
+	    lnno = (uint32_t) aux->x_block.x_lnnohi << 16
+		 | aux->x_block.x_lnno;
+#else
+	    lnno = aux->x_block.x_lnno;
+#endif
+	    if (!strcmp (name, ".bf"))
+	      {
+		xcoff_process_linenos (state, base_address, fsym, filename,
+				       sects, strtab, strtab_size, lnno, &vec,
+				       &fdata->vec, linenos, linenos_size,
+				       lnnoptr0, error_callback, data);
+	      }
+	    else if (!strcmp (name, ".ef"))
+	      {
+		fsym = NULL;
+	      }
+	    break;
+	}
+
+      i += asym->n_numaux;
+    }
+
+  /* Allocate one extra entry at the end.  */
+  ln = ((struct xcoff_line *)
+	backtrace_vector_grow (state, sizeof (struct xcoff_line),
+			       error_callback, data, &fdata->vec.vec));
+  if (ln == NULL)
+    goto fail;
+  ln->pc = (uintptr_t) -1;
+  ln->filename = NULL;
+  ln->function = NULL;
+  ln->lineno = 0;
+
+  if (!backtrace_vector_release (state, &fdata->vec.vec, error_callback, data))
+    goto fail;
+
+  backtrace_qsort (fdata->vec.vec.base, fdata->vec.count,
+		   sizeof (struct xcoff_line), xcoff_line_compare);
+
+  if (!state->threaded)
+    {
+      struct xcoff_fileline_data **pp;
+
+      for (pp = (struct xcoff_fileline_data **) (void *) &state->fileline_data;
+	   *pp != NULL;
+	   pp = &(*pp)->next)
+	;
+      *pp = fdata;
+    }
+  else
+    {
+      while (1)
+	{
+	  struct xcoff_fileline_data **pp;
+
+	  pp = (struct xcoff_fileline_data **) (void *) &state->fileline_data;
+
+	  while (1)
+	    {
+	      struct xcoff_fileline_data *p;
+
+	      p = backtrace_atomic_load_pointer (pp);
+
+	      if (p == NULL)
+		break;
+
+	      pp = &p->next;
+	    }
+
+	  if (__sync_bool_compare_and_swap (pp, NULL, fdata))
+	    break;
+	}
+    }
+
+  return 1;
+
+fail:
+  return 0;
+}
+
+/* Add the backtrace data for one XCOFF file.  Returns 1 on success,
+   0 on failure (in both cases descriptor is closed).  */
+
+static int
+xcoff_add (struct backtrace_state *state, int descriptor, off_t offset,
+	   uintptr_t base_address, backtrace_error_callback error_callback,
+	   void *data, fileline *fileline_fn, int *found_sym, int exe)
+{
+  struct backtrace_view fhdr_view;
+  struct backtrace_view sects_view;
+  struct backtrace_view linenos_view;
+  struct backtrace_view syms_view;
+  struct backtrace_view str_view;
+  struct backtrace_view dwarf_view;
+  b_xcoff_filhdr fhdr;
+  const b_xcoff_scnhdr *sects;
+  const b_xcoff_scnhdr *stext;
+  uint64_t lnnoptr;
+  uint32_t nlnno;
+  off_t str_off;
+  off_t min_offset;
+  off_t max_offset;
+  struct dwsect_info dwsect[DWSECT_MAX];
+  size_t sects_size;
+  size_t syms_size;
+  int32_t str_size;
+  int sects_view_valid;
+  int linenos_view_valid;
+  int syms_view_valid;
+  int str_view_valid;
+  int dwarf_view_valid;
+  int magic_ok;
+  int i;
+
+  *found_sym = 0;
+
+  sects_view_valid = 0;
+  linenos_view_valid = 0;
+  syms_view_valid = 0;
+  str_view_valid = 0;
+  dwarf_view_valid = 0;
+
+  str_size = 0;
+
+  /* Map the XCOFF file header.  */
+  if (!backtrace_get_view (state, descriptor, offset, sizeof (b_xcoff_filhdr),
+			   error_callback, data, &fhdr_view))
+    goto fail;
+
+  memcpy (&fhdr, fhdr_view.data, sizeof fhdr);
+  magic_ok = (fhdr.f_magic == XCOFF_MAGIC);
+
+  backtrace_release_view (state, &fhdr_view, error_callback, data);
+
+  if (!magic_ok)
+    {
+      if (exe)
+	error_callback (data, "executable file is not XCOFF", 0);
+      goto fail;
+    }
+
+  /* Verify object is of expected type.  */
+  if ((exe && (fhdr.f_flags & F_SHROBJ))
+      || (!exe && !(fhdr.f_flags & F_SHROBJ)))
+    goto fail;
+
+  /* Read the section headers.  */
+
+  sects_size = fhdr.f_nscns * sizeof (b_xcoff_scnhdr);
+
+  if (!backtrace_get_view (state, descriptor,
+			   offset + sizeof (fhdr) + fhdr.f_opthdr,
+			   sects_size, error_callback, data, &sects_view))
+    goto fail;
+  sects_view_valid = 1;
+  sects = (const b_xcoff_scnhdr *) sects_view.data;
+
+  /* FIXME: assumes only one .text section.  */
+  for (i = 0; i < fhdr.f_nscns; ++i)
+    if ((sects[i].s_flags & 0xffff) == STYP_TEXT)
+      break;
+  if (i == fhdr.f_nscns)
+    goto fail;
+
+  stext = &sects[i];
+
+  /* AIX ldinfo_textorg includes the XCOFF headers.  */
+  base_address = (exe ? XCOFF_AIX_TEXTBASE : base_address) + stext->s_scnptr;
+
+  lnnoptr = stext->s_lnnoptr;
+  nlnno = stext->s_nlnno;
+
+#if BACKTRACE_XCOFF_SIZE == 32
+  if (nlnno == _OVERFLOW_MARKER)
+    {
+      int sntext = i + 1;
+      /* Find the matching .ovrflo section.  */
+      for (i = 0; i < fhdr.f_nscns; ++i)
+	{
+	  if (((sects[i].s_flags & 0xffff) == STYP_OVRFLO)
+	      && sects[i].s_nlnno == sntext)
+	    {
+	      nlnno = sects[i].s_vaddr;
+	      break;
+	    }
+	}
+    }
+#endif
+
+  /* Read the symbol table and the string table.  */
+
+  if (fhdr.f_symptr != 0)
+    {
+      struct xcoff_syminfo_data *sdata;
+
+      /* Symbol table is followed by the string table.  The string table
+	 starts with its length (on 4 bytes).
+	 Map the symbol table and the length of the string table.  */
+      syms_size = fhdr.f_nsyms * sizeof (b_xcoff_syment);
+
+      if (!backtrace_get_view (state, descriptor, offset + fhdr.f_symptr,
+			       syms_size + 4, error_callback, data,
+			       &syms_view))
+	goto fail;
+      syms_view_valid = 1;
+
+      memcpy (&str_size, syms_view.data + syms_size, 4);
+
+      str_off = fhdr.f_symptr + syms_size;
+
+      if (str_size > 4)
+	{
+	  /* Map string table (including the length word).  */
+
+	  if (!backtrace_get_view (state, descriptor, offset + str_off,
+				   str_size, error_callback, data, &str_view))
+	    goto fail;
+	  str_view_valid = 1;
+	}
+
+      sdata = ((struct xcoff_syminfo_data *)
+	       backtrace_alloc (state, sizeof *sdata, error_callback, data));
+      if (sdata == NULL)
+	goto fail;
+
+      if (!xcoff_initialize_syminfo (state, base_address, sects,
+				     syms_view.data, fhdr.f_nsyms,
+				     str_view.data, str_size,
+				     error_callback, data, sdata))
+	{
+	  backtrace_free (state, sdata, sizeof *sdata, error_callback, data);
+	  goto fail;
+	}
+
+      *found_sym = 1;
+
+      xcoff_add_syminfo_data (state, sdata);
+    }
+
+  /* Read all the DWARF sections in a single view, since they are
+     probably adjacent in the file.  We never release this view.  */
+
+  min_offset = 0;
+  max_offset = 0;
+  memset (dwsect, 0, sizeof dwsect);
+  for (i = 0; i < fhdr.f_nscns; ++i)
+    {
+      off_t end;
+      int idx;
+
+      if ((sects[i].s_flags & 0xffff) != STYP_DWARF
+	  || sects[i].s_size == 0)
+	continue;
+      /* Map DWARF section to array index.  */
+      switch (sects[i].s_flags & 0xffff0000)
+	{
+	  case SSUBTYP_DWINFO:
+	    idx = DWSECT_INFO;
+	    break;
+	  case SSUBTYP_DWLINE:
+	    idx = DWSECT_LINE;
+	    break;
+	  case SSUBTYP_DWABREV:
+	    idx = DWSECT_ABBREV;
+	    break;
+	  case SSUBTYP_DWARNGE:
+	    idx = DWSECT_RANGES;
+	    break;
+	  case SSUBTYP_DWSTR:
+	    idx = DWSECT_STR;
+	    break;
+	  default:
+	    continue;
+	}
+      if (min_offset == 0 || (off_t) sects[i].s_scnptr < min_offset)
+	min_offset = sects[i].s_scnptr;
+      end = sects[i].s_scnptr + sects[i].s_size;
+      if (end > max_offset)
+	max_offset = end;
+      dwsect[idx].offset = sects[i].s_scnptr;
+      dwsect[idx].size = sects[i].s_size;
+    }
+  if (min_offset != 0 && max_offset != 0)
+    {
+      if (!backtrace_get_view (state, descriptor, offset + min_offset,
+			       max_offset - min_offset,
+			       error_callback, data, &dwarf_view))
+	goto fail;
+      dwarf_view_valid = 1;
+
+      for (i = 0; i < (int) DWSECT_MAX; ++i)
+	{
+	  if (dwsect[i].offset == 0)
+	    dwsect[i].data = NULL;
+	  else
+	    dwsect[i].data = ((const unsigned char *) dwarf_view.data
+			      + (dwsect[i].offset - min_offset));
+	}
+
+      if (!backtrace_dwarf_add (state, 0,
+				dwsect[DWSECT_INFO].data,
+				dwsect[DWSECT_INFO].size,
+#if BACKTRACE_XCOFF_SIZE == 32
+				/* XXX workaround for broken lineoff */
+				dwsect[DWSECT_LINE].data - 4,
+#else
+				/* XXX workaround for broken lineoff */
+				dwsect[DWSECT_LINE].data - 12,
+#endif
+				dwsect[DWSECT_LINE].size,
+				dwsect[DWSECT_ABBREV].data,
+				dwsect[DWSECT_ABBREV].size,
+				dwsect[DWSECT_RANGES].data,
+				dwsect[DWSECT_RANGES].size,
+				dwsect[DWSECT_STR].data,
+				dwsect[DWSECT_STR].size,
+				1, /* big endian */
+				error_callback, data, fileline_fn))
+	goto fail;
+    }
+
+  /* Read the XCOFF line number entries if DWARF sections not found.  */
+
+  if (!dwarf_view_valid && fhdr.f_symptr != 0 && lnnoptr != 0)
+    {
+      size_t linenos_size = (size_t) nlnno * LINESZ;
+
+      if (!backtrace_get_view (state, descriptor, offset + lnnoptr,
+			       linenos_size,
+			       error_callback, data, &linenos_view))
+	goto fail;
+      linenos_view_valid = 1;
+
+      if (xcoff_initialize_fileline (state, base_address, sects,
+				     syms_view.data, fhdr.f_nsyms,
+				     str_view.data, str_size,
+				     linenos_view.data, linenos_size,
+				     lnnoptr, error_callback, data))
+	*fileline_fn = xcoff_fileline;
+
+      backtrace_release_view (state, &linenos_view, error_callback, data);
+      linenos_view_valid = 0;
+    }
+
+  backtrace_release_view (state, &sects_view, error_callback, data);
+  sects_view_valid = 0;
+  if (syms_view_valid)
+    backtrace_release_view (state, &syms_view, error_callback, data);
+  syms_view_valid = 0;
+
+  /* We've read all we need from the executable.  */
+  if (!backtrace_close (descriptor, error_callback, data))
+    goto fail;
+  descriptor = -1;
+
+  return 1;
+
+ fail:
+  if (sects_view_valid)
+    backtrace_release_view (state, &sects_view, error_callback, data);
+  if (str_view_valid)
+    backtrace_release_view (state, &str_view, error_callback, data);
+  if (syms_view_valid)
+    backtrace_release_view (state, &syms_view, error_callback, data);
+  if (linenos_view_valid)
+    backtrace_release_view (state, &linenos_view, error_callback, data);
+  if (dwarf_view_valid)
+    backtrace_release_view (state, &dwarf_view, error_callback, data);
+  if (descriptor != -1 && offset == 0)
+    backtrace_close (descriptor, error_callback, data);
+  return 0;
+}
+
+#ifdef HAVE_LOADQUERY
+
+/* Read an integer value in human-readable format from an AIX
+   big archive fixed-length or member header.  */
+
+static int
+xcoff_parse_decimal (const char *buf, size_t size, off_t *off)
+{
+  char str[32];
+  char *end;
+
+  if (size >= sizeof str)
+    return 0;
+  memcpy (str, buf, size);
+  str[size] = '\0';
+  *off = strtol (str, &end, 10);
+  if (*end != '\0' && *end != ' ')
+    return 0;
+
+  return 1;
+}
+
+/* Add the backtrace data for a member of an AIX big archive.
+   Returns 1 on success, 0 on failure.  */
+
+static int
+xcoff_armem_add (struct backtrace_state *state, int descriptor,
+		 uintptr_t base_address, const char *member,
+		 backtrace_error_callback error_callback, void *data,
+		 fileline *fileline_fn, int *found_sym)
+{
+  struct backtrace_view view;
+  b_ar_fl_hdr fl_hdr;
+  const b_ar_hdr *ar_hdr;
+  off_t off;
+  off_t len;
+  int memlen;
+
+  *found_sym = 0;
+
+  /* Map archive fixed-length header.  */
+
+  if (!backtrace_get_view (state, descriptor, 0, sizeof (b_ar_fl_hdr),
+			   error_callback, data, &view))
+    goto fail;
+
+  memcpy (&fl_hdr, view.data, sizeof (b_ar_fl_hdr));
+
+  backtrace_release_view (state, &view, error_callback, data);
+
+  if (memcmp (fl_hdr.fl_magic, AIAMAGBIG, 8) != 0)
+    goto fail;
+
+  memlen = strlen (member);
+
+  /* Read offset of first archive member.  */
+  if (!xcoff_parse_decimal (fl_hdr.fl_fstmoff, sizeof fl_hdr.fl_fstmoff, &off))
+    goto fail;
+  while (off != 0)
+    {
+      /* Map archive member header and member name.  */
+
+      if (!backtrace_get_view (state, descriptor, off,
+			       sizeof (b_ar_hdr) + memlen,
+			       error_callback, data, &view))
+	break;
+
+      ar_hdr = (const b_ar_hdr *) view.data;
+
+      /* Read archive member name length.  */
+      if (!xcoff_parse_decimal (ar_hdr->ar_namlen, sizeof ar_hdr->ar_namlen,
+				&len))
+	{
+	  backtrace_release_view (state, &view, error_callback, data);
+	  break;
+	}
+      if (len == memlen && !memcmp (ar_hdr->ar_name, member, memlen))
+	{
+	  off = (off + sizeof (b_ar_hdr) + memlen + 1) & ~1;
+
+	  /* The archive can contain several members with the same name
+	     (e.g. 32-bit and 64-bit), so continue if not ok.  */
+
+	  if (xcoff_add (state, descriptor, off, base_address, error_callback,
+			 data, fileline_fn, found_sym, 0))
+	    {
+	      backtrace_release_view (state, &view, error_callback, data);
+	      return 1;
+	    }
+	}
+
+      /* Read offset of next archive member.  */
+      if (!xcoff_parse_decimal (ar_hdr->ar_nxtmem, sizeof ar_hdr->ar_nxtmem,
+				&off))
+	{
+	  backtrace_release_view (state, &view, error_callback, data);
+	  break;
+	}
+      backtrace_release_view (state, &view, error_callback, data);
+    }
+
+ fail:
+  /* No matching member found.  */
+  backtrace_close (descriptor, error_callback, data);
+  return 0;
+}
+
+/* Add the backtrace data for dynamically loaded libraries.  */
+
+static void
+xcoff_add_shared_libs (struct backtrace_state *state,
+		       backtrace_error_callback error_callback,
+		       void *data, fileline *fileline_fn, int *found_sym)
+{
+  const struct ld_info *ldinfo;
+  void *buf;
+  unsigned int buflen;
+  const char *member;
+  int descriptor;
+  int does_not_exist;
+  int lib_found_sym;
+  int ret;
+
+  /* Retrieve the list of loaded libraries.  */
+
+  buf = NULL;
+  buflen = 512;
+  do
+    {
+      buf = realloc (buf, buflen);
+      if (buf == NULL)
+	{
+	  ret = -1;
+	  break;
+	}
+      ret = loadquery (L_GETINFO, buf, buflen);
+      if (ret == 0)
+	break;
+      buflen *= 2;
+    }
+  while (ret == -1 && errno == ENOMEM);
+  if (ret != 0)
+    {
+      free (buf);
+      return;
+    }
+
+  ldinfo = (const struct ld_info *) buf;
+  while ((const char *) ldinfo < (const char *) buf + buflen)
+    {
+      if (*ldinfo->ldinfo_filename != '/')
+	goto next;
+
+      descriptor = backtrace_open (ldinfo->ldinfo_filename, error_callback,
+				   data, &does_not_exist);
+      if (descriptor < 0)
+	goto next;
+
+      /* Check if it is an archive (member name not empty).  */
+
+      member = ldinfo->ldinfo_filename + strlen (ldinfo->ldinfo_filename) + 1;
+      if (*member)
+	{
+	  xcoff_armem_add (state, descriptor,
+			   (uintptr_t) ldinfo->ldinfo_textorg, member,
+			   error_callback, data, fileline_fn, &lib_found_sym);
+	}
+      else
+	{
+	  xcoff_add (state, descriptor, 0, (uintptr_t) ldinfo->ldinfo_textorg,
+		     error_callback, data, fileline_fn, &lib_found_sym, 0);
+	}
+      if (lib_found_sym)
+	*found_sym = 1;
+
+ next:
+      if (ldinfo->ldinfo_next == 0)
+	break;
+      ldinfo = (const struct ld_info *) ((const char *) ldinfo
+					 + ldinfo->ldinfo_next);
+    }
+
+    free (buf);
+}
+#endif /* HAVE_LOADQUERY */
+
+/* Initialize the backtrace data we need from an XCOFF executable.
+   Returns 1 on success, 0 on failure.  */
+
+int
+backtrace_initialize (struct backtrace_state *state,
+		      const char *filename ATTRIBUTE_UNUSED, int descriptor,
+		      backtrace_error_callback error_callback,
+		      void *data, fileline *fileline_fn)
+{
+  int ret;
+  int found_sym;
+  fileline xcoff_fileline_fn = xcoff_nodebug;
+
+  ret = xcoff_add (state, descriptor, 0, 0, error_callback, data,
+		   &xcoff_fileline_fn, &found_sym, 1);
+  if (!ret)
+    return 0;
+
+#ifdef HAVE_LOADQUERY
+  xcoff_add_shared_libs (state, error_callback, data, &xcoff_fileline_fn,
+			 &found_sym);
+#endif
+
+  if (!state->threaded)
+    {
+      if (found_sym)
+	state->syminfo_fn = xcoff_syminfo;
+      else if (state->syminfo_fn == NULL)
+	state->syminfo_fn = xcoff_nosyms;
+    }
+  else
+    {
+      if (found_sym)
+	backtrace_atomic_store_pointer (&state->syminfo_fn, xcoff_syminfo);
+      else
+	__sync_bool_compare_and_swap (&state->syminfo_fn, NULL, xcoff_nosyms);
+    }
+
+  if (!state->threaded)
+    {
+      if (state->fileline_fn == NULL || state->fileline_fn == xcoff_nodebug)
+	*fileline_fn = xcoff_fileline_fn;
+    }
+  else
+    {
+      fileline current_fn;
+
+      current_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
+      if (current_fn == NULL || current_fn == xcoff_nodebug)
+	*fileline_fn = xcoff_fileline_fn;
+    }
+
+  return 1;
+}
diff --git a/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/ztest.c b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/ztest.c
new file mode 100644
index 0000000..9cd712a
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace-sys/src/libbacktrace/ztest.c
@@ -0,0 +1,537 @@
+/* ztest.c -- Test for libbacktrace inflate code.
+   Copyright (C) 2017-2018 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    (1) Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    (2) Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    (3) The name of the author may not be used to
+    endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.  */
+
+#include "config.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef HAVE_ZLIB
+#include <zlib.h>
+#endif
+
+#include "backtrace.h"
+#include "backtrace-supported.h"
+
+#include "internal.h"
+#include "testlib.h"
+
+#ifndef HAVE_CLOCK_GETTIME
+
+typedef int xclockid_t;
+
+static int
+xclock_gettime (xclockid_t id ATTRIBUTE_UNUSED,
+		struct timespec *ts ATTRIBUTE_UNUSED)
+{
+  errno = EINVAL;
+  return -1;
+}
+
+#define clockid_t xclockid_t
+#define clock_gettime xclock_gettime
+#undef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+
+#endif /* !defined(HAVE_CLOCK_GETTIME) */
+
+#ifdef CLOCK_PROCESS_CPUTIME_ID
+#define ZLIB_CLOCK_GETTIME_ARG CLOCK_PROCESS_CPUTIME_ID
+#else
+#define ZLIB_CLOCK_GETTIME_ARG CLOCK_REALTIME
+#endif
+
+/* Some tests for the local zlib inflation code.  */
+
+struct zlib_test
+{
+  const char *name;
+  const char *uncompressed;
+  size_t uncompressed_len;
+  const char *compressed;
+  size_t compressed_len;
+};
+
+/* Error callback.  */
+
+static void
+error_callback_compress (void *vdata, const char *msg, int errnum)
+{
+  fprintf (stderr, "%s", msg);
+  if (errnum > 0)
+    fprintf (stderr, ": %s", strerror (errnum));
+  fprintf (stderr, "\n");
+  exit (EXIT_FAILURE);
+}
+
+static const struct zlib_test tests[] =
+{
+  {
+    "empty",
+    "",
+    0,
+    "\x78\x9c\x03\x00\x00\x00\x00\x01",
+    8,
+  },
+  {
+    "hello",
+    "hello, world\n",
+    0,
+    ("\x78\x9c\xca\x48\xcd\xc9\xc9\xd7\x51\x28\xcf"
+     "\x2f\xca\x49\xe1\x02\x04\x00\x00\xff\xff\x21\xe7\x04\x93"),
+    25,
+  },
+  {
+    "goodbye",
+    "goodbye, world",
+    0,
+    ("\x78\x9c\x4b\xcf\xcf\x4f\x49\xaa"
+     "\x4c\xd5\x51\x28\xcf\x2f\xca\x49"
+     "\x01\x00\x28\xa5\x05\x5e"),
+    22,
+  },
+  {
+    "ranges",
+    ("\xcc\x11\x00\x00\x00\x00\x00\x00\xd5\x13\x00\x00\x00\x00\x00\x00"
+     "\x1c\x14\x00\x00\x00\x00\x00\x00\x72\x14\x00\x00\x00\x00\x00\x00"
+     "\x9d\x14\x00\x00\x00\x00\x00\x00\xd5\x14\x00\x00\x00\x00\x00\x00"
+     "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+     "\xfb\x12\x00\x00\x00\x00\x00\x00\x09\x13\x00\x00\x00\x00\x00\x00"
+     "\x0c\x13\x00\x00\x00\x00\x00\x00\xcb\x13\x00\x00\x00\x00\x00\x00"
+     "\x29\x14\x00\x00\x00\x00\x00\x00\x4e\x14\x00\x00\x00\x00\x00\x00"
+     "\x9d\x14\x00\x00\x00\x00\x00\x00\xd5\x14\x00\x00\x00\x00\x00\x00"
+     "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+     "\xfb\x12\x00\x00\x00\x00\x00\x00\x09\x13\x00\x00\x00\x00\x00\x00"
+     "\x67\x13\x00\x00\x00\x00\x00\x00\xcb\x13\x00\x00\x00\x00\x00\x00"
+     "\x9d\x14\x00\x00\x00\x00\x00\x00\xd5\x14\x00\x00\x00\x00\x00\x00"
+     "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+     "\x5f\x0b\x00\x00\x00\x00\x00\x00\x6c\x0b\x00\x00\x00\x00\x00\x00"
+     "\x7d\x0b\x00\x00\x00\x00\x00\x00\x7e\x0c\x00\x00\x00\x00\x00\x00"
+     "\x38\x0f\x00\x00\x00\x00\x00\x00\x5c\x0f\x00\x00\x00\x00\x00\x00"
+     "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+     "\x83\x0c\x00\x00\x00\x00\x00\x00\xfa\x0c\x00\x00\x00\x00\x00\x00"
+     "\xfd\x0d\x00\x00\x00\x00\x00\x00\xef\x0e\x00\x00\x00\x00\x00\x00"
+     "\x14\x0f\x00\x00\x00\x00\x00\x00\x38\x0f\x00\x00\x00\x00\x00\x00"
+     "\x9f\x0f\x00\x00\x00\x00\x00\x00\xac\x0f\x00\x00\x00\x00\x00\x00"
+     "\xdb\x0f\x00\x00\x00\x00\x00\x00\xff\x0f\x00\x00\x00\x00\x00\x00"
+     "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+     "\xfd\x0d\x00\x00\x00\x00\x00\x00\xd8\x0e\x00\x00\x00\x00\x00\x00"
+     "\x9f\x0f\x00\x00\x00\x00\x00\x00\xac\x0f\x00\x00\x00\x00\x00\x00"
+     "\xdb\x0f\x00\x00\x00\x00\x00\x00\xff\x0f\x00\x00\x00\x00\x00\x00"
+     "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+     "\xfa\x0c\x00\x00\x00\x00\x00\x00\xea\x0d\x00\x00\x00\x00\x00\x00"
+     "\xef\x0e\x00\x00\x00\x00\x00\x00\x14\x0f\x00\x00\x00\x00\x00\x00"
+     "\x5c\x0f\x00\x00\x00\x00\x00\x00\x9f\x0f\x00\x00\x00\x00\x00\x00"
+     "\xac\x0f\x00\x00\x00\x00\x00\x00\xdb\x0f\x00\x00\x00\x00\x00\x00"
+     "\xff\x0f\x00\x00\x00\x00\x00\x00\x2c\x10\x00\x00\x00\x00\x00\x00"
+     "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+     "\x60\x11\x00\x00\x00\x00\x00\x00\xd1\x16\x00\x00\x00\x00\x00\x00"
+     "\x40\x0b\x00\x00\x00\x00\x00\x00\x2c\x10\x00\x00\x00\x00\x00\x00"
+     "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+     "\x7a\x00\x00\x00\x00\x00\x00\x00\xb6\x00\x00\x00\x00\x00\x00\x00"
+     "\x9f\x01\x00\x00\x00\x00\x00\x00\xa7\x01\x00\x00\x00\x00\x00\x00"
+     "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+     "\x7a\x00\x00\x00\x00\x00\x00\x00\xa9\x00\x00\x00\x00\x00\x00\x00"
+     "\x9f\x01\x00\x00\x00\x00\x00\x00\xa7\x01\x00\x00\x00\x00\x00\x00"
+     "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"),
+    672,
+    ("\x78\x9c\x3b\x23\xc8\x00\x06\x57\x85\x21\xb4\x8c\x08\x84\x2e\x82"
+     "\xd2\x73\xa1\xf4\x55\x28\x8d\x0e\x7e\x0b\x41\x68\x4e\xa8\x7e\x1e"
+     "\x28\x7d\x1a\x4a\x6b\x42\xf5\xf9\x91\x69\x5e\x3a\x9a\x79\x84\xf4"
+     "\xc7\x73\x43\xe8\x1c\x28\x5d\x0b\xa5\xeb\x78\x20\xb4\x05\x3f\x84"
+     "\x8e\xe1\xc7\xae\xbf\x19\xaa\xee\x17\x94\xfe\xcb\x0b\xa1\xdf\xf3"
+     "\x41\x68\x11\x7e\x54\x73\xe6\x43\xe9\x35\x50\xfa\x36\x94\xfe\x8f"
+     "\xc3\x7c\x98\x79\x37\xf8\xc8\xd3\x0f\x73\xd7\x2b\x1c\xee\x8a\x21"
+     "\xd2\x5d\x3a\x02\xd8\xcd\x4f\x80\xa6\x87\x8b\x62\x10\xda\x81\x1b"
+     "\xbf\xfa\x2a\x28\xbd\x0d\x4a\xcf\x67\x84\xd0\xcb\x19\xf1\xab\x5f"
+     "\x49\xa4\x7a\x00\x48\x97\x29\xd4"),
+    152,
+  }
+};
+
+/* Test the hand coded samples.  */
+
+static void
+test_samples (struct backtrace_state *state)
+{
+  size_t i;
+
+  for (i = 0; i < sizeof tests / sizeof tests[0]; ++i)
+    {
+      char *p;
+      size_t v;
+      size_t j;
+      unsigned char *uncompressed;
+      size_t uncompressed_len;
+
+      p = malloc (12 + tests[i].compressed_len);
+      memcpy (p, "ZLIB", 4);
+      v = tests[i].uncompressed_len;
+      if (v == 0)
+	v = strlen (tests[i].uncompressed);
+      for (j = 0; j < 8; ++j)
+	p[j + 4] = (v >> ((7 - j) * 8)) & 0xff;
+      memcpy (p + 12, tests[i].compressed, tests[i].compressed_len);
+      uncompressed = NULL;
+      uncompressed_len = 0;
+      if (!backtrace_uncompress_zdebug (state, (unsigned char *) p,
+					tests[i].compressed_len + 12,
+					error_callback_compress, NULL,
+					&uncompressed, &uncompressed_len))
+	{
+	  fprintf (stderr, "test %s: uncompress failed\n", tests[i].name);
+	  ++failures;
+	}
+      else
+	{
+	  if (uncompressed_len != v)
+	    {
+	      fprintf (stderr,
+		       "test %s: got uncompressed length %zu, want %zu\n",
+		       tests[i].name, uncompressed_len, v);
+	      ++failures;
+	    }
+	  else if (memcmp (tests[i].uncompressed, uncompressed, v) != 0)
+	    {
+	      size_t j;
+
+	      fprintf (stderr, "test %s: uncompressed data mismatch\n",
+		       tests[i].name);
+	      for (j = 0; j < v; ++j)
+		if (tests[i].uncompressed[j] != uncompressed[j])
+		  fprintf (stderr, "  %zu: got %#x want %#x\n", j,
+			   uncompressed[j], tests[i].uncompressed[j]);
+	      ++failures;
+	    }
+	  else
+	    printf ("PASS: inflate %s\n", tests[i].name);
+
+	  backtrace_free (state, uncompressed, uncompressed_len,
+			  error_callback_compress, NULL);
+	}
+    }
+}
+
+#ifdef HAVE_ZLIB
+
+/* Given a set of TRIALS timings, discard the lowest and highest
+   values and return the mean average of the rest.  */
+
+static size_t
+average_time (const size_t *times, size_t trials)
+{
+  size_t imax;
+  size_t max;
+  size_t imin;
+  size_t min;
+  size_t i;
+  size_t sum;
+
+  imin = 0;
+  imax = 0;
+  min = times[0];
+  max = times[0];
+  for (i = 1; i < trials; ++i)
+    {
+      if (times[i] < min)
+	{
+	  imin = i;
+	  min = times[i];
+	}
+      if (times[i] > max)
+	{
+	  imax = i;
+	  max = times[i];
+	}
+    }
+
+  sum = 0;
+  for (i = 0; i < trials; ++i)
+    {
+      if (i != imax && i != imin)
+	sum += times[i];
+    }
+  return sum / (trials - 2);
+}
+
+#endif
+
+/* Test a larger text, if available.  */
+
+static void
+test_large (struct backtrace_state *state)
+{
+#ifdef HAVE_ZLIB
+  unsigned char *orig_buf;
+  size_t orig_bufsize;
+  size_t i;
+  char *compressed_buf;
+  size_t compressed_bufsize;
+  unsigned long compress_sizearg;
+  unsigned char *uncompressed_buf;
+  size_t uncompressed_bufsize;
+  int r;
+  clockid_t cid;
+  struct timespec ts1;
+  struct timespec ts2;
+  size_t ctime;
+  size_t ztime;
+  const size_t trials = 16;
+  size_t ctimes[16];
+  size_t ztimes[16];
+  static const char * const names[] = {
+    "Mark.Twain-Tom.Sawyer.txt",
+    "../libgo/go/compress/testdata/Mark.Twain-Tom.Sawyer.txt"
+  };
+
+  orig_buf = NULL;
+  orig_bufsize = 0;
+  uncompressed_buf = NULL;
+  compressed_buf = NULL;
+
+  for (i = 0; i < sizeof names / sizeof names[0]; ++i)
+    {
+      size_t len;
+      char *namebuf;
+      FILE *e;
+      struct stat st;
+      char *rbuf;
+      size_t got;
+
+      len = strlen (SRCDIR) + strlen (names[i]) + 2;
+      namebuf = malloc (len);
+      if (namebuf == NULL)
+	{
+	  perror ("malloc");
+	  goto fail;
+	}
+      snprintf (namebuf, len, "%s/%s", SRCDIR, names[i]);
+      e = fopen (namebuf, "r");
+      free (namebuf);
+      if (e == NULL)
+	continue;
+      if (fstat (fileno (e), &st) < 0)
+	{
+	  perror ("fstat");
+	  fclose (e);
+	  continue;
+	}
+      rbuf = malloc (st.st_size);
+      if (rbuf == NULL)
+	{
+	  perror ("malloc");
+	  goto fail;
+	}
+      got = fread (rbuf, 1, st.st_size, e);
+      fclose (e);
+      if (got > 0)
+	{
+	  orig_buf = rbuf;
+	  orig_bufsize = got;
+	  break;
+	}
+      free (rbuf);
+    }
+
+  if (orig_buf == NULL)
+    {
+      /* We couldn't find an input file.  */
+      printf ("UNSUPPORTED: inflate large\n");
+      return;
+    }
+
+  compressed_bufsize = compressBound (orig_bufsize) + 12;
+  compressed_buf = malloc (compressed_bufsize);
+  if (compressed_buf == NULL)
+    {
+      perror ("malloc");
+      goto fail;
+    }
+
+  compress_sizearg = compressed_bufsize - 12;
+  r = compress (compressed_buf + 12, &compress_sizearg,
+		orig_buf, orig_bufsize);
+  if (r != Z_OK)
+    {
+      fprintf (stderr, "zlib compress failed: %d\n", r);
+      goto fail;
+    }
+
+  compressed_bufsize = compress_sizearg + 12;
+
+  /* Prepare the header that our library expects.  */
+  memcpy (compressed_buf, "ZLIB", 4);
+  for (i = 0; i < 8; ++i)
+    compressed_buf[i + 4] = (orig_bufsize >> ((7 - i) * 8)) & 0xff;
+
+  uncompressed_buf = malloc (orig_bufsize);
+  if (uncompressed_buf == NULL)
+    {
+      perror ("malloc");
+      goto fail;
+    }
+  uncompressed_bufsize = orig_bufsize;
+
+  if (!backtrace_uncompress_zdebug (state, compressed_buf, compressed_bufsize,
+				    error_callback_compress, NULL,
+				    &uncompressed_buf, &uncompressed_bufsize))
+    {
+      fprintf (stderr, "inflate large: backtrace_uncompress_zdebug failed\n");
+      goto fail;
+    }
+
+  if (uncompressed_bufsize != orig_bufsize)
+    {
+      fprintf (stderr,
+	       "inflate large: got uncompressed length %zu, want %zu\n",
+	       uncompressed_bufsize, orig_bufsize);
+      goto fail;
+    }
+
+  if (memcmp (uncompressed_buf, orig_buf, uncompressed_bufsize) != 0)
+    {
+      fprintf (stderr, "inflate large: uncompressed data mismatch\n");
+      goto fail;
+    }
+
+  printf ("PASS: inflate large\n");
+
+  for (i = 0; i < trials; ++i)
+    {
+      unsigned long uncompress_sizearg;
+
+      cid = ZLIB_CLOCK_GETTIME_ARG;
+      if (clock_gettime (cid, &ts1) < 0)
+	{
+	  if (errno == EINVAL)
+	    return;
+	  perror ("clock_gettime");
+	  return;
+	}
+
+      if (!backtrace_uncompress_zdebug (state, compressed_buf,
+					compressed_bufsize,
+					error_callback_compress, NULL,
+					&uncompressed_buf,
+					&uncompressed_bufsize))
+	{
+	  fprintf (stderr,
+		   ("inflate large: "
+		    "benchmark backtrace_uncompress_zdebug failed\n"));
+	  return;
+	}
+
+      if (clock_gettime (cid, &ts2) < 0)
+	{
+	  perror ("clock_gettime");
+	  return;
+	}
+
+      ctime = (ts2.tv_sec - ts1.tv_sec) * 1000000000;
+      ctime += ts2.tv_nsec - ts1.tv_nsec;
+      ctimes[i] = ctime;
+
+      if (clock_gettime (cid, &ts1) < 0)
+	{
+	  perror("clock_gettime");
+	  return;
+	}
+
+      uncompress_sizearg = uncompressed_bufsize;
+      r = uncompress (uncompressed_buf, &uncompress_sizearg,
+		      compressed_buf + 12, compressed_bufsize - 12);
+
+      if (clock_gettime (cid, &ts2) < 0)
+	{
+	  perror ("clock_gettime");
+	  return;
+	}
+
+      if (r != Z_OK)
+	{
+	  fprintf (stderr,
+		   "inflate large: benchmark zlib uncompress failed: %d\n",
+		   r);
+	  return;
+	}
+
+      ztime = (ts2.tv_sec - ts1.tv_sec) * 1000000000;
+      ztime += ts2.tv_nsec - ts1.tv_nsec;
+      ztimes[i] = ztime;
+    }
+
+  /* Toss the highest and lowest times and average the rest.  */
+  ctime = average_time (ctimes, trials);
+  ztime = average_time (ztimes, trials);
+
+  printf ("backtrace: %zu ns\n", ctime);
+  printf ("zlib     : %zu ns\n", ztime);
+  printf ("ratio    : %g\n", (double) ztime / (double) ctime);
+
+  return;
+
+ fail:
+  printf ("FAIL: inflate large\n");
+  ++failures;
+
+  if (orig_buf != NULL)
+    free (orig_buf);
+  if (compressed_buf != NULL)
+    free (compressed_buf);
+  if (uncompressed_buf != NULL)
+    free (uncompressed_buf);
+
+#else /* !HAVE_ZLIB */
+
+ printf ("UNSUPPORTED: inflate large\n");
+
+#endif /* !HAVE_ZLIB */
+}
+
+int
+main (int argc ATTRIBUTE_UNUSED, char **argv)
+{
+  struct backtrace_state *state;
+
+  state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,
+				  error_callback_create, NULL);
+
+  test_samples (state);
+  test_large (state);
+
+  exit (failures != 0 ? EXIT_FAILURE : EXIT_SUCCESS);
+}
diff --git a/third_party/rust_crates/vendor/backtrace/.cargo-checksum.json b/third_party/rust_crates/vendor/backtrace/.cargo-checksum.json
index a487ffe..00d9049 100644
--- a/third_party/rust_crates/vendor/backtrace/.cargo-checksum.json
+++ b/third_party/rust_crates/vendor/backtrace/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"c97b88d6abe6886c23820cf213e5ea3023a978f0a83cd65cb57fd52a913d137b","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"633f9db18c7121e890a1b76d73506acfeaf536fd4b04fd2f1e4344e31ddbadeb","appveyor.yml":"38f8e674bc29b852da95ba18294c43299f5dc3c5bfbb90380756ffdcfc4ea416","build.rs":"06f7c4ddf43b3f9d0dd94dd000211dce13b38ab3f258fe28795d803402cf2678","ci/android-ndk.sh":"89fafa41d08ff477f949bfc163d04d1eb34fdee370f7a695cfba4ef34c164a55","ci/docker/aarch64-linux-android/Dockerfile":"c97f23fe2892f406d3deb7479c89e1c1dbbdbd0db456ac699f9399852300348d","ci/docker/aarch64-unknown-linux-gnu/Dockerfile":"97fa8f20c6899ee36b47371d485b64a2e96b626a2746b5f434c01eae9168b2a1","ci/docker/arm-linux-androideabi/Dockerfile":"11f6963365de062cf0ac81debec00aee29932df2714d8505f9f6383722d211a8","ci/docker/arm-unknown-linux-gnueabihf/Dockerfile":"41133d712ef13f05e67796857db86476b3ed9c6355d5eb56115575b06d739e04","ci/docker/armv7-linux-androideabi/Dockerfile":"39038d17a423683e0af27a050b34dea610729fb0085814ec6c81726a7f52556f","ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile":"2a216244baad705491f249278083994bf68744a2759f51e768b2f92e0da7c360","ci/docker/i586-unknown-linux-gnu/Dockerfile":"ef898c914590d721488ca11e62f3d7c26852346e1612deb0f3e12ab011187109","ci/docker/i686-linux-android/Dockerfile":"9181e5fe5503077652659bc3353c3c21fcf4fc6b03730430fb40d6adc3096079","ci/docker/i686-unknown-linux-gnu/Dockerfile":"ef898c914590d721488ca11e62f3d7c26852346e1612deb0f3e12ab011187109","ci/docker/powerpc-unknown-linux-gnu/Dockerfile":"83e0e3adbb2d6f2398e70d2c8f71ee301fe99e24554f902602c2f2bb067c2f2c","ci/docker/powerpc64-unknown-linux-gnu/Dockerfile":"828b657e1748bcd8d331794624d5fc1cd07087a051e507eb9206757985194bf1","ci/docker/x86_64-linux-android/Dockerfile":"074bb2906ba587466490ab9d802eb817b9f23eb54aa095ee53e1a33be5569328","ci/docker/x86_64-pc-windows-gnu/Dockerfile":"0822e270108ec39a6b93721598156031a0469ed680e62ce4acd13bbb1a952b9d","ci/docker/x86_64-unknown-linux-gnu/Dockerfile":"e1c202a6831b17e017b4737e80d5b992905895b086bbc06285fc9c337cadbc23","ci/docker/x86_64-unknown-linux-musl/Dockerfile":"2efbba08cc8fff8d2431dde92517df7d122dc754c778820c668f1ac29a885290","ci/run-docker.sh":"517db62fa790712734a1410b27995134ec88c613a0cae548382fb0d3f0b55080","ci/run.sh":"30a3807c195cd86d8b8884e1228cd061aa112b26c54277beebf5108777a36fe9","examples/backtrace.rs":"fd6e1cc6c3378ec7d41cd03b2bef187051298dceb01147e71f207dbb8a0c4867","examples/raw.rs":"f07be26d1f97cd7ac79290ac99d19c4eec5d27031fe270ab5364c25d9c2ad9e0","src/backtrace/dbghelp.rs":"d2a2a8225287190aa4d4b3ffcc73ef6cafff64ab43465461c23fbeb25ec67915","src/backtrace/libunwind.rs":"0c83046b7186de2007c3a30beeaa21c132ddf40b61804b8d7caee14f337b6d5d","src/backtrace/mod.rs":"486cd5557ae39bff0f5f292bc2e436cf72c92d8a48b059362958a6e93afc819c","src/backtrace/noop.rs":"7b477dfaa32111bd6f01afa602d1482ece36ae7d68537ed300d2c49a41c46c46","src/backtrace/unix_backtrace.rs":"848c97afa93e0ea54062ff4639a83d14ef4d59b3065d6f0daf34811d388cbc6e","src/capture.rs":"a896a223298bba0fbae016915ceb260a7430d0bfceab2c9aaad1f29bc06e82fd","src/dylib.rs":"4eed51dbe3e14b5f9736c320228ee85fb68d8431061fa895b6873b63ced36aa2","src/lib.rs":"46e4f18452d137260e7c5a9cb44dbe5f2106066c242008ec4cefa10558f681d9","src/symbolize/coresymbolication.rs":"e7e35304b603b8d7feefe382ae2cc45060965d93cad726e199d9d1d337b0b1a2","src/symbolize/dbghelp.rs":"403bf1d1e277524e38d48f0d605506e35fa034e93a6521018f0207f71e6066f7","src/symbolize/dladdr.rs":"96f4a8a79ad4c62cb53220f8161cd8bfb6ecb9965fb69dcafc43505f9db593f9","src/symbolize/gimli.rs":"4a673804b4f15864a737fe40868957eb981849e7cb3a526880633cbdd532946e","src/symbolize/libbacktrace.rs":"bde430c380d3b3c357c88b1f8d2c1bdea2dc48b1136b797a7bf6cf8d87f76a4f","src/symbolize/mod.rs":"d92ee83c3c3f8ff247249e7af4c24e19a7df03a2ae3c01c79dec5385dd0f5c09","src/symbolize/noop.rs":"b98fc6987e0a5a6a9f19bee4bb09843be1974dd00db1518565ced06eeb34d3b5","src/types.rs":"c25241673e9035294f13a8413ec2fd05f19ae5f0f16986028c9a51286f06cdec","tests/long_fn_name.rs":"2a61a3829e543b21f4c162be34e633aa63d0c0ef8eb13b075f51234519672bea","tests/skip_inner_frames.rs":"c5dee2bbae9b19fa77f92cec076b5f915fb95003a24ea0046de13d7ff978a227","tests/smoke.rs":"16f3306f12e0ef185f03d16f50d81904e22e50b6e5c46acab407c298f8a88b64"},"package":"b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5"}
\ No newline at end of file
+{"files":{"Cargo.lock":"a2716255607997af5683457cd6f0593e53415a86e71861811bc1b2cc4e5e9b3d","Cargo.toml":"3982168ace9c9ef0bb836a0b8d7c3f873f878842ab8c2c7414a3a17bae17952d","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"5038903e047ac0287b2a16218109171c99a8b67242bdeaff52db51bd60b68fb0","benches/benchmarks.rs":"ce5763576fa8aeb722d3b8bcdb294d8a31e80e3c5272da25525fdcc392ccc6cc","ci/android-ndk.sh":"89fafa41d08ff477f949bfc163d04d1eb34fdee370f7a695cfba4ef34c164a55","ci/android-sdk.sh":"3269ef90675e8d4c2031e542cd3a55d9e060b2a094105cde982b282185936dda","ci/docker/aarch64-linux-android/Dockerfile":"cb5c55f17fcb0d65713086b8796de070657440cbcb6c2eded34b61b957b7bce8","ci/docker/aarch64-unknown-linux-gnu/Dockerfile":"97fa8f20c6899ee36b47371d485b64a2e96b626a2746b5f434c01eae9168b2a1","ci/docker/arm-linux-androideabi/Dockerfile":"3fe712b0927fd8fb05c1f733f0bf0d8a139bfc5a0108ba5515bd6b499976f1ab","ci/docker/arm-unknown-linux-gnueabihf/Dockerfile":"41133d712ef13f05e67796857db86476b3ed9c6355d5eb56115575b06d739e04","ci/docker/armv7-linux-androideabi/Dockerfile":"10783c6d22e727c38b2483ed5d941aeb8f1099025e263183f1598c604924ffa6","ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile":"2a216244baad705491f249278083994bf68744a2759f51e768b2f92e0da7c360","ci/docker/i586-unknown-linux-gnu/Dockerfile":"ef898c914590d721488ca11e62f3d7c26852346e1612deb0f3e12ab011187109","ci/docker/i686-linux-android/Dockerfile":"1a2119c2119a2213cf22a825166cd7bb75386fa057c7fabb2f572fc1e65f1870","ci/docker/i686-unknown-linux-gnu/Dockerfile":"ef898c914590d721488ca11e62f3d7c26852346e1612deb0f3e12ab011187109","ci/docker/powerpc64-unknown-linux-gnu/Dockerfile":"7cd511302c4624f0ee3944a6f5e4f5f25bb727ba2623d1e6b8f288a4d8cec30c","ci/docker/x86_64-linux-android/Dockerfile":"37f0bdcfed3d9382e09056e1f32351cbf6a901810d58060a4384a42303f2f7a3","ci/docker/x86_64-pc-windows-gnu/Dockerfile":"cbde261d7bcea43059e341363d57a00a83d9ebe4501aca2c1c6ba834e0ea9eb9","ci/docker/x86_64-unknown-linux-gnu/Dockerfile":"e1c202a6831b17e017b4737e80d5b992905895b086bbc06285fc9c337cadbc23","ci/docker/x86_64-unknown-linux-musl/Dockerfile":"2efbba08cc8fff8d2431dde92517df7d122dc754c778820c668f1ac29a885290","ci/run-docker.sh":"c4efad39c65a38c89e90d61a9ef15136903dd4cf01a6ae8079aa005b882d751e","ci/run.sh":"30a3807c195cd86d8b8884e1228cd061aa112b26c54277beebf5108777a36fe9","ci/runtest-android.rs":"be2e49bb296b92a8e3643a6c0a70917fe7b130fa43b71a29c4e7514f45c00e7e","examples/backtrace.rs":"fd6e1cc6c3378ec7d41cd03b2bef187051298dceb01147e71f207dbb8a0c4867","examples/raw.rs":"81fb66bd0f71010f9a954f667d92bf792cfd1ac90fa3a09c362767d866dc8374","src/backtrace/dbghelp.rs":"d5f56dc97d1e7cf2bed05ac6e922ca5be96aaab2f1098601343affd22241fa38","src/backtrace/libunwind.rs":"d006cdb883919d9dd138132216c83398987016264f67c714d07abdbf3383362a","src/backtrace/mod.rs":"8d9c7f5ab5cacc00b766d811fb6a38c57c78b42894c2499cd02ec802bb593b4c","src/backtrace/noop.rs":"9d9a93a890cef988b691232d9d1e7d114768ada58e9591345826135cb380f01a","src/backtrace/unix_backtrace.rs":"293c6ac31e9eb8e32dc7d219f4cf5dbeb9b66bdc42dcc949d1de63233dea2666","src/capture.rs":"c7c9f0a55312c9687d43118b69d4416d9c8eac1f7eaeb542807bc5e23bc18ce0","src/dbghelp.rs":"c33788eeef29bb78a1cdd7cf7f3e034b82d3686ba87d76a920692db19b26212b","src/lib.rs":"881e140db1f7e19bf3eb139881f102801aa9c06344282417b9b1e2c67534466a","src/print.rs":"a74ba3a97c07045997c282b8066cd6b9ac3b755122cafb9dbe0e6479752065e0","src/print/fuchsia.rs":"4620968941adda90cec97d3cdfe06937327cdee5882f1b98bc933efaac68ef7a","src/symbolize/coresymbolication.rs":"f5442333d8c58188fe3c7749783336bd2e096ed9940d77c19ce4295dd592fb0b","src/symbolize/dbghelp.rs":"649d5ff1656e8fd84ab1088bb48054f6ea7cd0c50a09af09f72d562c17e52b6b","src/symbolize/dladdr.rs":"4b420b07f345f7c4e545c43f68d1b2d1f419a9228712097f35eae875b182b349","src/symbolize/dladdr_resolve.rs":"ec3bc5c8462cce48e97136e4867dd08a5f1b0c133e45d511745c1c3197e78405","src/symbolize/gimli.rs":"7232bc02c14af59db4296266965d4839c359a08679b9a7f02a55275ff87ac864","src/symbolize/libbacktrace.rs":"d3f18a85fd13c32f949226e2d5cde3c40f60d73d32c46e91bf670cb202cf5f3b","src/symbolize/mod.rs":"aec85aee8ff3e00a532f7d1ab8739802d6e2df369aecfe045fe6d8b6a4004c11","src/symbolize/noop.rs":"a8581b117e1065236c12f0a4a4c49f4c1929c4e6a3283f2253bb1fd0c77e4f7a","src/types.rs":"85dac420ee8791281f4cdec78e86be056c84ffecc0e5e5821d91862fc0e23444","src/windows.rs":"4a025bd064d22134185441859ab5337e31a33d39af212801fd7ada374595fd41","tests/accuracy/auxiliary.rs":"8bcf4a3a15ebed82f878c440910a07866efbc5eacea8b74f482dae297c779226","tests/accuracy/main.rs":"db2870e7fa51df01a5176e59bd87d205d83cad1599f374f273e11baf5efd41bb","tests/concurrent-panics.rs":"7c37df054c57c0c6694265bcaa596c1418a90cce65a569699e1b0c56bcd4bdfa","tests/long_fn_name.rs":"ca2480a72e8d2c02c678f047c202cdec7efafeb2fb32d94a327c669b7c81807a","tests/skip_inner_frames.rs":"b5c9137723c8648da46396c4c631e4b7d9933cac33397ae3da588a4692322212","tests/smoke.rs":"0330093fa76bd83851f2b8efb37330ce1c1c48d2be99313074d9c727491377f7"},"package":"b4b1549d804b6c73f4817df2ba073709e96e426f12987127c48e6745568c350b"}
\ No newline at end of file
diff --git a/third_party/rust_crates/vendor/backtrace/Cargo.lock b/third_party/rust_crates/vendor/backtrace/Cargo.lock
new file mode 100644
index 0000000..8fdde07
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace/Cargo.lock
@@ -0,0 +1,314 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "addr2line"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "fallible-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gimli 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "arrayvec"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "backtrace"
+version = "0.3.42"
+dependencies = [
+ "addr2line 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cpp_demangle 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "findshlibs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "goblin 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-std-workspace-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "backtrace-sys"
+version = "0.1.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-std-workspace-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "byteorder"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "cc"
+version = "1.0.50"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "cfg-if"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "compiler_builtins 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-std-workspace-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "compiler_builtins"
+version = "0.1.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "cpp_demangle"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "fallible-iterator"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "findshlibs"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "gimli"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fallible-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "glob"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "goblin"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scroll 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "lazycell"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "libc"
+version = "0.2.66"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rustc-std-workspace-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "log"
+version = "0.4.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "memmap"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "plain"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "compiler_builtins 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-std-workspace-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rustc-serialize"
+version = "0.3.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "rustc-std-workspace-core"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "scroll"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "scroll_derive 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "scroll_derive"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "serde"
+version = "1.0.104"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.104"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "smallvec"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "stable_deref_trait"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "syn"
+version = "1.0.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[metadata]
+"checksum addr2line 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1c4e698660ed2d0f625c39bb877332b4269668720e330e2aa3d67bb1187a656a"
+"checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"
+"checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491"
+"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
+"checksum cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)" = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd"
+"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
+"checksum compiler_builtins 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b9975aefa63997ef75ca9cf013ff1bb81487aaa0b622c21053afd3b92979a7af"
+"checksum cpp_demangle 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4115af6f575a7bc82c613e9e0ed7cc36a5e4fc3a8b54920dc0c820823a31a0d6"
+"checksum fallible-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
+"checksum findshlibs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1260d61e4fe2a6ab845ffdc426a0bd68ffb240b91cf0ec5a8d1170cec535bd8"
+"checksum gimli 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81dd6190aad0f05ddbbf3245c54ed14ca4aa6dd32f22312b70d8f168c3e3e633"
+"checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
+"checksum goblin 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3081214398d39e4bd7f2c1975f0488ed04614ffdd976c6fc7a0708278552c0da"
+"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
+"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
+"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
+"checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
+"checksum plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
+"checksum proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0319972dcae462681daf4da1adeeaa066e3ebd29c69be96c6abb1259d2ee2bcc"
+"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
+"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
+"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
+"checksum rustc-std-workspace-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1956f5517128a2b6f23ab2dadf1a976f4f5b27962e7724c2bf3d45e539ec098c"
+"checksum scroll 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "abb2332cb595d33f7edd5700f4cbf94892e680c7f0ae56adab58a35190b66cb1"
+"checksum scroll_derive 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8584eea9b9ff42825b46faf46a8c24d2cff13ec152fa2a50df788b87c07ee28"
+"checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449"
+"checksum serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64"
+"checksum smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44e59e0c9fa00817912ae6e4e6e3c4fe04455e75699d06eedc7d85917ed8e8f4"
+"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
+"checksum syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1e4ff033220a41d1a57d8125eab57bf5263783dfdcc18688b1dacc6ce9651ef8"
+"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
+"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
+"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/third_party/rust_crates/vendor/backtrace/Cargo.toml b/third_party/rust_crates/vendor/backtrace/Cargo.toml
index 6c28ae6..a9846d6 100644
--- a/third_party/rust_crates/vendor/backtrace/Cargo.toml
+++ b/third_party/rust_crates/vendor/backtrace/Cargo.toml
@@ -3,7 +3,7 @@
 # When uploading crates to the registry Cargo will automatically
 # "normalize" Cargo.toml files for maximal compatibility
 # with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g. crates.io) dependencies
+# to registry (e.g., crates.io) dependencies
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
@@ -11,17 +11,18 @@
 # will likely look very different (and much more reasonable)
 
 [package]
+edition = "2018"
 name = "backtrace"
-version = "0.3.13"
-authors = ["Alex Crichton <alex@alexcrichton.com>", "The Rust Project Developers"]
+version = "0.3.42"
+authors = ["The Rust Project Developers"]
 autoexamples = true
 autotests = true
 description = "A library to acquire a stack trace (backtrace) at runtime in a Rust program.\n"
-homepage = "https://github.com/alexcrichton/backtrace-rs"
+homepage = "https://github.com/rust-lang/backtrace-rs"
 documentation = "https://docs.rs/backtrace"
 readme = "README.md"
 license = "MIT/Apache-2.0"
-repository = "https://github.com/alexcrichton/backtrace-rs"
+repository = "https://github.com/rust-lang/backtrace-rs"
 
 [[example]]
 name = "backtrace"
@@ -42,34 +43,62 @@
 [[test]]
 name = "smoke"
 required-features = ["std"]
+edition = "2018"
+
+[[test]]
+name = "accuracy"
+required-features = ["std", "dbghelp", "libbacktrace", "libunwind"]
+edition = "2018"
+
+[[test]]
+name = "concurrent-panics"
+harness = false
+required-features = ["std"]
 [dependencies.addr2line]
-version = "0.7.0"
+version = "0.11.0"
+features = ["std"]
+optional = true
+default-features = false
+
+[dependencies.backtrace-sys]
+version = "0.1.32"
 optional = true
 
 [dependencies.cfg-if]
 version = "0.1.6"
 
+[dependencies.compiler_builtins]
+version = "0.1.2"
+optional = true
+
+[dependencies.core]
+version = "1.0.0"
+optional = true
+package = "rustc-std-workspace-core"
+
 [dependencies.cpp_demangle]
 version = "0.2.3"
 optional = true
 default-features = false
 
 [dependencies.findshlibs]
-version = "0.4.0"
+version = "0.5.0"
 optional = true
 
-[dependencies.gimli]
-version = "0.16.0"
+[dependencies.goblin]
+version = "0.1.3"
+features = ["elf32", "elf64", "mach32", "mach64", "pe32", "pe64", "std"]
 optional = true
+default-features = false
+
+[dependencies.libc]
+version = "0.2.45"
+default-features = false
 
 [dependencies.memmap]
 version = "0.7.0"
 optional = true
 
-[dependencies.object]
-version = "0.9.0"
-optional = true
-
 [dependencies.rustc-demangle]
 version = "0.1.4"
 
@@ -79,33 +108,24 @@
 
 [dependencies.serde]
 version = "1.0"
+features = ["derive"]
 optional = true
 
-[dependencies.serde_derive]
-version = "1.0"
-optional = true
-[build-dependencies.autocfg]
-version = "0.1"
-
 [features]
 coresymbolication = []
 dbghelp = []
-default = ["std", "libunwind", "libbacktrace", "coresymbolication", "dladdr", "dbghelp"]
+default = ["std", "libunwind", "libbacktrace", "dladdr", "dbghelp"]
 dladdr = []
-gimli-symbolize = ["addr2line", "findshlibs", "gimli", "memmap", "object"]
+gimli-symbolize = ["addr2line", "findshlibs", "memmap", "goblin"]
 kernel32 = []
-libbacktrace = ["backtrace-sys", "std"]
+libbacktrace = ["backtrace-sys"]
 libunwind = []
+rustc-dep-of-std = ["backtrace-sys/rustc-dep-of-std", "cfg-if/rustc-dep-of-std", "core", "compiler_builtins", "libc/rustc-dep-of-std", "rustc-demangle/rustc-dep-of-std"]
 serialize-rustc = ["rustc-serialize"]
-serialize-serde = ["serde", "serde_derive"]
+serialize-serde = ["serde"]
 std = []
 unix-backtrace = []
-[target."cfg(all(unix, not(target_os = \"fuchsia\"), not(target_os = \"emscripten\"), not(target_os = \"macos\"), not(target_os = \"ios\")))".dependencies.backtrace-sys]
-version = "0.1.17"
-optional = true
-[target."cfg(unix)".dependencies.libc]
-version = "0.2.45"
-default-features = false
+verify-winapi = ["winapi/dbghelp", "winapi/handleapi", "winapi/libloaderapi", "winapi/minwindef", "winapi/processthreadsapi", "winapi/synchapi", "winapi/winbase", "winapi/winnt"]
 [target."cfg(windows)".dependencies.winapi]
 version = "0.3.3"
-features = ["dbghelp", "processthreadsapi", "winnt", "minwindef"]
+optional = true
diff --git a/third_party/rust_crates/vendor/backtrace/README.md b/third_party/rust_crates/vendor/backtrace/README.md
index de8c8a0..9713f0c 100644
--- a/third_party/rust_crates/vendor/backtrace/README.md
+++ b/third_party/rust_crates/vendor/backtrace/README.md
@@ -1,13 +1,11 @@
 # backtrace-rs
 
-[![Build Status](https://travis-ci.org/alexcrichton/backtrace-rs.svg?branch=master)](https://travis-ci.org/alexcrichton/backtrace-rs)
-[![Build status](https://ci.appveyor.com/api/projects/status/v4l9oj4aqbbgyx44?svg=true)](https://ci.appveyor.com/project/alexcrichton/backtrace-rs)
-
 [Documentation](https://docs.rs/backtrace)
 
 A library for acquiring backtraces at runtime for Rust. This library aims to
-enhance the support of the standard library by providing a more stable and
-programmatic interface.
+enhance the support of the standard library by providing a programmatic
+interface to work with, but it also supports simply easily printing the current
+backtrace like libstd's panics.
 
 ## Install
 
@@ -16,12 +14,9 @@
 backtrace = "0.3"
 ```
 
-```rust
-extern crate backtrace;
-```
-
-Note that this crate requires `make`, `objcopy`, and `ar` to be present on Linux
-systems.
+Note that this crate requires `cc` and `ar` to be present on Unix systems when
+`libbacktrace` is used (which is the default). For configuring C compilers see
+the [`cc` crate documentation](https://github.com/alexcrichton/cc-rs).
 
 ## Usage
 
@@ -54,7 +49,7 @@
         let symbol_address = frame.symbol_address();
 
         // Resolve this instruction pointer to a symbol name
-        backtrace::resolve(ip, |symbol| {
+        backtrace::resolve_frame(frame, |symbol| {
             if let Some(name) = symbol.name() {
                 // ...
             }
@@ -68,11 +63,6 @@
 }
 ```
 
-## Platform Support
-
-This library currently supports OSX, Linux, and Windows. Support for other
-platforms is always welcome!
-
 # License
 
 This project is licensed under either of
diff --git a/third_party/rust_crates/vendor/backtrace/appveyor.yml b/third_party/rust_crates/vendor/backtrace/appveyor.yml
deleted file mode 100644
index 33e8aa3..0000000
--- a/third_party/rust_crates/vendor/backtrace/appveyor.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-environment:
-  matrix:
-    - TARGET: x86_64-pc-windows-gnu
-      MSYS_BITS: 64
-    - TARGET: i686-pc-windows-gnu
-      MSYS_BITS: 32
-    - TARGET: x86_64-pc-windows-msvc
-    - TARGET: i686-pc-windows-msvc
-install:
-  - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe"
-  - rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust"
-  - set PATH=%PATH%;C:\Program Files (x86)\Rust\bin
-  - if defined MSYS_BITS set PATH=%PATH%;C:\msys64\mingw%MSYS_BITS%\bin
-  - rustc -V
-  - cargo -V
-
-build: false
-
-test_script:
-  - cargo test --target %TARGET%
-  - cargo build --target %TARGET% --no-default-features
-  - cargo build --target %TARGET% --no-default-features --features dbghelp
-
-branches:
-  only:
-    - master
diff --git a/third_party/rust_crates/vendor/backtrace/benches/benchmarks.rs b/third_party/rust_crates/vendor/backtrace/benches/benchmarks.rs
new file mode 100644
index 0000000..ad55788
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace/benches/benchmarks.rs
@@ -0,0 +1,94 @@
+#![feature(test)]
+
+extern crate test;
+
+extern crate backtrace;
+
+#[cfg(feature = "std")]
+use backtrace::Backtrace;
+
+#[bench]
+#[cfg(feature = "std")]
+fn trace(b: &mut test::Bencher) {
+    #[inline(never)]
+    fn the_function() {
+        backtrace::trace(|frame| {
+            let ip = frame.ip();
+            test::black_box(ip);
+            true
+        });
+    }
+    b.iter(the_function);
+}
+
+#[bench]
+#[cfg(feature = "std")]
+fn trace_and_resolve_callback(b: &mut test::Bencher) {
+    #[inline(never)]
+    fn the_function() {
+        backtrace::trace(|frame| {
+            backtrace::resolve(frame.ip(), |symbol| {
+                let addr = symbol.addr();
+                test::black_box(addr);
+            });
+            true
+        });
+    }
+    b.iter(the_function);
+}
+
+#[bench]
+#[cfg(feature = "std")]
+fn trace_and_resolve_separate(b: &mut test::Bencher) {
+    #[inline(never)]
+    fn the_function(frames: &mut Vec<*mut std::ffi::c_void>) {
+        backtrace::trace(|frame| {
+            frames.push(frame.ip());
+            true
+        });
+        frames.iter().for_each(|frame_ip| {
+            backtrace::resolve(*frame_ip, |symbol| {
+                test::black_box(symbol);
+            });
+        });
+    }
+    let mut frames = Vec::with_capacity(1024);
+    b.iter(|| {
+        the_function(&mut frames);
+        frames.clear();
+    });
+}
+
+#[bench]
+#[cfg(feature = "std")]
+fn new_unresolved(b: &mut test::Bencher) {
+    #[inline(never)]
+    fn the_function() {
+        let bt = Backtrace::new_unresolved();
+        test::black_box(bt);
+    }
+    b.iter(the_function);
+}
+
+#[bench]
+#[cfg(feature = "std")]
+fn new(b: &mut test::Bencher) {
+    #[inline(never)]
+    fn the_function() {
+        let bt = Backtrace::new();
+        test::black_box(bt);
+    }
+    b.iter(the_function);
+}
+
+#[bench]
+#[cfg(feature = "std")]
+fn new_unresolved_and_resolve_separate(b: &mut test::Bencher) {
+    #[inline(never)]
+    fn the_function() {
+        let mut bt = Backtrace::new_unresolved();
+        bt.resolve();
+        test::black_box(bt);
+    }
+    b.iter(the_function);
+}
diff --git a/third_party/rust_crates/vendor/backtrace/build.rs b/third_party/rust_crates/vendor/backtrace/build.rs
deleted file mode 100644
index a648ea1..0000000
--- a/third_party/rust_crates/vendor/backtrace/build.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-extern crate autocfg;
-
-fn main() {
-    let ac = autocfg::new();
-
-    // ffi types moved from `std` to `core` in Rust 1.30, so we need to adjust imports based on
-    // this.
-    //
-    // <https://github.com/rust-lang/rust/pull/53910>
-    ac.emit_rustc_version(1, 30);
-
-    println!("cargo:rerun-if-changed=build.rs");
-}
diff --git a/third_party/rust_crates/vendor/backtrace/ci/android-sdk.sh b/third_party/rust_crates/vendor/backtrace/ci/android-sdk.sh
new file mode 100755
index 0000000..aee133e
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace/ci/android-sdk.sh
@@ -0,0 +1,74 @@
+#!/usr/bin/env sh
+# Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+# file at the top-level directory of this distribution and at
+# http://rust-lang.org/COPYRIGHT.
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+set -ex
+
+# Prep the SDK and emulator
+#
+# Note that the update process requires that we accept a bunch of licenses, and
+# we can't just pipe `yes` into it for some reason, so we take the same strategy
+# located in https://github.com/appunite/docker by just wrapping it in a script
+# which apparently magically accepts the licenses.
+
+SDK=4333796
+mkdir sdk
+curl --retry 20 https://dl.google.com/android/repository/sdk-tools-linux-${SDK}.zip -O
+unzip -q -d sdk sdk-tools-linux-${SDK}.zip
+
+case "$1" in
+  arm | armv7)
+    api=24
+    image="system-images;android-${api};google_apis;armeabi-v7a"
+    ;;
+  aarch64)
+    api=24
+    image="system-images;android-${api};google_apis;arm64-v8a"
+    ;;
+  i686)
+    api=28
+    image="system-images;android-${api};default;x86"
+    ;;
+  x86_64)
+    api=28
+    image="system-images;android-${api};default;x86_64"
+    ;;
+  *)
+    echo "invalid arch: $1"
+    exit 1
+    ;;
+esac;
+
+# Try to fix warning about missing file.
+# See https://askubuntu.com/a/1078784
+mkdir -p /root/.android/
+echo '### User Sources for Android SDK Manager' >> /root/.android/repositories.cfg
+echo '#Fri Nov 03 10:11:27 CET 2017 count=0' >> /root/.android/repositories.cfg
+
+# Print all available packages
+# yes | ./sdk/tools/bin/sdkmanager --list --verbose
+
+# --no_https avoids
+# javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: No trusted certificate found
+#
+# | grep -v = || true    removes the progress bar output from the sdkmanager
+# which produces an insane amount of output.
+yes | ./sdk/tools/bin/sdkmanager --licenses --no_https | grep -v = || true
+yes | ./sdk/tools/bin/sdkmanager --no_https \
+        "emulator" \
+        "platform-tools" \
+        "platforms;android-${api}" \
+        "${image}" | grep -v = || true
+
+echo "no" |
+    ./sdk/tools/bin/avdmanager create avd \
+        --name "${1}" \
+        --package "${image}" | grep -v = || true
+
diff --git a/third_party/rust_crates/vendor/backtrace/ci/docker/aarch64-linux-android/Dockerfile b/third_party/rust_crates/vendor/backtrace/ci/docker/aarch64-linux-android/Dockerfile
index b9026c0..81c8208 100644
--- a/third_party/rust_crates/vendor/backtrace/ci/docker/aarch64-linux-android/Dockerfile
+++ b/third_party/rust_crates/vendor/backtrace/ci/docker/aarch64-linux-android/Dockerfile
@@ -15,4 +15,4 @@
 
 # TODO: run tests in an emulator eventually
 ENV CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER=aarch64-linux-android-gcc \
-    CARGO_TARGET_AARCH64_LINUX_ANDROID_RUNNER="true"
+    CARGO_TARGET_AARCH64_LINUX_ANDROID_RUNNER=echo
diff --git a/third_party/rust_crates/vendor/backtrace/ci/docker/arm-linux-androideabi/Dockerfile b/third_party/rust_crates/vendor/backtrace/ci/docker/arm-linux-androideabi/Dockerfile
index 1079997..7cfdae6 100644
--- a/third_party/rust_crates/vendor/backtrace/ci/docker/arm-linux-androideabi/Dockerfile
+++ b/third_party/rust_crates/vendor/backtrace/ci/docker/arm-linux-androideabi/Dockerfile
@@ -11,8 +11,27 @@
 
 COPY android-ndk.sh /
 RUN /android-ndk.sh arm
-ENV PATH=$PATH:/android-toolchain/bin
+WORKDIR /android
+COPY android-sdk.sh /android/sdk.sh
+RUN ./sdk.sh arm
+RUN mv /root/.android /tmp
+RUN chmod 777 -R /tmp/.android
+RUN chmod 755 /android/sdk/tools/* /android/sdk/emulator/qemu/linux-x86_64/*
+ENV PATH=$PATH:/android-toolchain/bin:/android/sdk/platform-tools
 
 # TODO: run tests in an emulator eventually
 ENV CARGO_TARGET_ARM_LINUX_ANDROIDEABI_LINKER=arm-linux-androideabi-gcc \
-    CARGO_TARGET_ARM_LINUX_ANDROIDEABI_RUNNER="true"
+    CARGO_TARGET_ARM_LINUX_ANDROIDEABI_RUNNER=/tmp/runtest \
+    HOME=/tmp
+
+ADD runtest-android.rs /tmp/runtest.rs
+ENTRYPOINT [ \
+  "bash", \
+  "-c", \
+  # set SHELL so android can detect a 64bits system, see
+  # http://stackoverflow.com/a/41789144
+  "SHELL=/bin/dash /android/sdk/emulator/emulator @arm -no-window & \
+   /rust/bin/rustc /tmp/runtest.rs -o /tmp/runtest && \
+   exec \"$@\"", \
+  "--" \
+]
diff --git a/third_party/rust_crates/vendor/backtrace/ci/docker/armv7-linux-androideabi/Dockerfile b/third_party/rust_crates/vendor/backtrace/ci/docker/armv7-linux-androideabi/Dockerfile
index 9696677..c738716 100644
--- a/third_party/rust_crates/vendor/backtrace/ci/docker/armv7-linux-androideabi/Dockerfile
+++ b/third_party/rust_crates/vendor/backtrace/ci/docker/armv7-linux-androideabi/Dockerfile
@@ -15,4 +15,4 @@
 
 # TODO: run tests in an emulator eventually
 ENV CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER=arm-linux-androideabi-gcc \
-    CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_RUNNER="true"
+    CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_RUNNER=echo
diff --git a/third_party/rust_crates/vendor/backtrace/ci/docker/i686-linux-android/Dockerfile b/third_party/rust_crates/vendor/backtrace/ci/docker/i686-linux-android/Dockerfile
index c4946ad..ef4752c 100644
--- a/third_party/rust_crates/vendor/backtrace/ci/docker/i686-linux-android/Dockerfile
+++ b/third_party/rust_crates/vendor/backtrace/ci/docker/i686-linux-android/Dockerfile
@@ -15,4 +15,4 @@
 
 # TODO: run tests in an emulator eventually
 ENV CARGO_TARGET_I686_LINUX_ANDROID_LINKER=i686-linux-android-gcc \
-    CARGO_TARGET_I686_LINUX_ANDROID_RUNNER="true"
+    CARGO_TARGET_I686_LINUX_ANDROID_RUNNER=echo
diff --git a/third_party/rust_crates/vendor/backtrace/ci/docker/powerpc-unknown-linux-gnu/Dockerfile b/third_party/rust_crates/vendor/backtrace/ci/docker/powerpc-unknown-linux-gnu/Dockerfile
deleted file mode 100644
index 7323e85..0000000
--- a/third_party/rust_crates/vendor/backtrace/ci/docker/powerpc-unknown-linux-gnu/Dockerfile
+++ /dev/null
@@ -1,9 +0,0 @@
-FROM ubuntu:18.04
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
-        gcc libc6-dev qemu-user ca-certificates \
-        gcc-powerpc-linux-gnu libc6-dev-powerpc-cross \
-        qemu-system-ppc
-
-ENV CARGO_TARGET_POWERPC_UNKNOWN_LINUX_GNU_LINKER=powerpc-linux-gnu-gcc \
-    CARGO_TARGET_POWERPC_UNKNOWN_LINUX_GNU_RUNNER="qemu-ppc -cpu Vger -L /usr/powerpc-linux-gnu"
diff --git a/third_party/rust_crates/vendor/backtrace/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile b/third_party/rust_crates/vendor/backtrace/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile
index 5e22a9f..b4f5d8a 100644
--- a/third_party/rust_crates/vendor/backtrace/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile
+++ b/third_party/rust_crates/vendor/backtrace/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile
@@ -12,5 +12,5 @@
 ENV CARGO_TARGET_POWERPC64_UNKNOWN_LINUX_GNU_LINKER=powerpc64-linux-gnu-gcc \
     # TODO: should actually run these tests
     #CARGO_TARGET_POWERPC64_UNKNOWN_LINUX_GNU_RUNNER="qemu-ppc64 -L /usr/powerpc64-linux-gnu" \
-    CARGO_TARGET_POWERPC64_UNKNOWN_LINUX_GNU_RUNNER=true \
+    CARGO_TARGET_POWERPC64_UNKNOWN_LINUX_GNU_RUNNER=echo \
     CC=powerpc64-linux-gnu-gcc
diff --git a/third_party/rust_crates/vendor/backtrace/ci/docker/x86_64-linux-android/Dockerfile b/third_party/rust_crates/vendor/backtrace/ci/docker/x86_64-linux-android/Dockerfile
index 6ed4a65..7fea8a1 100644
--- a/third_party/rust_crates/vendor/backtrace/ci/docker/x86_64-linux-android/Dockerfile
+++ b/third_party/rust_crates/vendor/backtrace/ci/docker/x86_64-linux-android/Dockerfile
@@ -15,4 +15,4 @@
 
 # TODO: run tests in an emulator eventually
 ENV CARGO_TARGET_X86_64_LINUX_ANDROID_LINKER=x86_64-linux-android-gcc \
-    CARGO_TARGET_X86_64_LINUX_ANDROID_RUNNER="true"
+    CARGO_TARGET_X86_64_LINUX_ANDROID_RUNNER=echo
diff --git a/third_party/rust_crates/vendor/backtrace/ci/docker/x86_64-pc-windows-gnu/Dockerfile b/third_party/rust_crates/vendor/backtrace/ci/docker/x86_64-pc-windows-gnu/Dockerfile
index 48db219..7a8fbf4 100644
--- a/third_party/rust_crates/vendor/backtrace/ci/docker/x86_64-pc-windows-gnu/Dockerfile
+++ b/third_party/rust_crates/vendor/backtrace/ci/docker/x86_64-pc-windows-gnu/Dockerfile
@@ -6,5 +6,5 @@
   gcc-mingw-w64-x86-64
 
 # No need to run tests, we're just testing that it compiles
-ENV CARGO_TARGET_X86_64_PC_WINDOWS_GNU_RUNNER=true \
+ENV CARGO_TARGET_X86_64_PC_WINDOWS_GNU_RUNNER=echo \
     CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER=x86_64-w64-mingw32-gcc
diff --git a/third_party/rust_crates/vendor/backtrace/ci/run-docker.sh b/third_party/rust_crates/vendor/backtrace/ci/run-docker.sh
index abce99e..5a9934b 100755
--- a/third_party/rust_crates/vendor/backtrace/ci/run-docker.sh
+++ b/third_party/rust_crates/vendor/backtrace/ci/run-docker.sh
@@ -10,7 +10,7 @@
       --user `id -u`:`id -g` \
       --rm \
       --init \
-      --volume $HOME/.cargo:/cargo \
+      --volume $(dirname $(dirname `which cargo`)):/cargo \
       --env CARGO_HOME=/cargo \
       --volume `rustc --print sysroot`:/rust:ro \
       --env TARGET=$1 \
diff --git a/third_party/rust_crates/vendor/backtrace/ci/runtest-android.rs b/third_party/rust_crates/vendor/backtrace/ci/runtest-android.rs
new file mode 100644
index 0000000..dc70121
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace/ci/runtest-android.rs
@@ -0,0 +1,50 @@
+use std::env;
+use std::process::Command;
+use std::path::{Path, PathBuf};
+
+fn main() {
+    let args = env::args_os()
+        .skip(1)
+        .filter(|arg| arg != "--quiet")
+        .collect::<Vec<_>>();
+    assert_eq!(args.len(), 1);
+    let test = PathBuf::from(&args[0]);
+    let dst = Path::new("/data/local/tmp").join(test.file_name().unwrap());
+
+    println!("waiting for device to come online...");
+    let status = Command::new("adb")
+        .arg("wait-for-device")
+        .status()
+        .expect("failed to run: adb wait-for-device");
+    assert!(status.success());
+
+    println!("pushing executable...");
+    let status = Command::new("adb")
+        .arg("push")
+        .arg(&test)
+        .arg(&dst)
+        .status()
+        .expect("failed to run: adb pushr");
+    assert!(status.success());
+
+    println!("executing tests...");
+    let output = Command::new("adb")
+        .arg("shell")
+        .arg(&dst)
+        .output()
+        .expect("failed to run: adb shell");
+    assert!(status.success());
+
+    println!("status: {}\nstdout ---\n{}\nstderr ---\n{}",
+             output.status,
+             String::from_utf8_lossy(&output.stdout),
+             String::from_utf8_lossy(&output.stderr));
+
+    let stdout = String::from_utf8_lossy(&output.stdout);
+    stdout.lines().find(|l|
+        (l.starts_with("PASSED ") && l.contains(" tests")) ||
+        l.starts_with("test result: ok")
+    ).unwrap_or_else(|| {
+        panic!("failed to find successful test run");
+    });
+}
diff --git a/third_party/rust_crates/vendor/backtrace/examples/raw.rs b/third_party/rust_crates/vendor/backtrace/examples/raw.rs
index 40a6b12..b43cab8 100644
--- a/third_party/rust_crates/vendor/backtrace/examples/raw.rs
+++ b/third_party/rust_crates/vendor/backtrace/examples/raw.rs
@@ -4,12 +4,20 @@
     foo();
 }
 
-fn foo() { bar() }
-fn bar() { baz() }
-fn baz() { print() }
+fn foo() {
+    bar()
+}
+fn bar() {
+    baz()
+}
+fn baz() {
+    print()
+}
 
-#[cfg(target_pointer_width = "32")] const HEX_WIDTH: usize = 10;
-#[cfg(target_pointer_width = "64")] const HEX_WIDTH: usize = 20;
+#[cfg(target_pointer_width = "32")]
+const HEX_WIDTH: usize = 10;
+#[cfg(target_pointer_width = "64")]
+const HEX_WIDTH: usize = 20;
 
 fn print() {
     let mut cnt = 0;
@@ -33,12 +41,10 @@
             }
             if let Some(file) = symbol.filename() {
                 if let Some(l) = symbol.lineno() {
-                    print!("\n{:13}{:4$}@ {}:{}", "", "", file.display(), l,
-                           HEX_WIDTH);
+                    print!("\n{:13}{:4$}@ {}:{}", "", "", file.display(), l, HEX_WIDTH);
                 }
             }
             println!("");
-
         });
         if !resolved {
             println!(" - <no info>");
diff --git a/third_party/rust_crates/vendor/backtrace/src/backtrace/dbghelp.rs b/third_party/rust_crates/vendor/backtrace/src/backtrace/dbghelp.rs
index dc1aab1..40de143 100644
--- a/third_party/rust_crates/vendor/backtrace/src/backtrace/dbghelp.rs
+++ b/third_party/rust_crates/vendor/backtrace/src/backtrace/dbghelp.rs
@@ -8,31 +8,71 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+//! Backtrace strategy for MSVC platforms.
+//!
+//! This module contains the ability to generate a backtrace on MSVC using one
+//! of two possible methods. The `StackWalkEx` function is primarily used if
+//! possible, but not all systems have that. Failing that the `StackWalk64`
+//! function is used instead. Note that `StackWalkEx` is favored because it
+//! handles debuginfo internally and returns inline frame information.
+//!
+//! Note that all dbghelp support is loaded dynamically, see `src/dbghelp.rs`
+//! for more information about that.
+
 #![allow(bad_style)]
 
+use crate::dbghelp;
+use crate::windows::*;
+use core::ffi::c_void;
 use core::mem;
-use core::prelude::v1::*;
 
-use winapi::shared::minwindef::*;
-use winapi::um::processthreadsapi;
-use winapi::um::winnt::{self, CONTEXT};
-use winapi::um::dbghelp;
-use winapi::um::dbghelp::*;
-
-use types::c_void;
-
-pub struct Frame {
-    inner: STACKFRAME64,
+#[derive(Clone, Copy)]
+pub enum Frame {
+    New(STACKFRAME_EX),
+    Old(STACKFRAME64),
 }
 
+// we're just sending around raw pointers and reading them, never interpreting
+// them so this should be safe to both send and share across threads.
+unsafe impl Send for Frame {}
+unsafe impl Sync for Frame {}
+
 impl Frame {
     pub fn ip(&self) -> *mut c_void {
-        self.inner.AddrPC.Offset as *mut _
+        self.addr_pc().Offset as *mut _
     }
 
     pub fn symbol_address(&self) -> *mut c_void {
         self.ip()
     }
+
+    fn addr_pc(&self) -> &ADDRESS64 {
+        match self {
+            Frame::New(new) => &new.AddrPC,
+            Frame::Old(old) => &old.AddrPC,
+        }
+    }
+
+    fn addr_pc_mut(&mut self) -> &mut ADDRESS64 {
+        match self {
+            Frame::New(new) => &mut new.AddrPC,
+            Frame::Old(old) => &mut old.AddrPC,
+        }
+    }
+
+    fn addr_frame_mut(&mut self) -> &mut ADDRESS64 {
+        match self {
+            Frame::New(new) => &mut new.AddrFrame,
+            Frame::Old(old) => &mut old.AddrFrame,
+        }
+    }
+
+    fn addr_stack_mut(&mut self) -> &mut ADDRESS64 {
+        match self {
+            Frame::New(new) => &mut new.AddrStack,
+            Frame::Old(old) => &mut old.AddrStack,
+        }
+    }
 }
 
 #[repr(C, align(16))] // required by `CONTEXT`, is a FIXME in winapi right now
@@ -41,59 +81,153 @@
 #[inline(always)]
 pub unsafe fn trace(cb: &mut FnMut(&super::Frame) -> bool) {
     // Allocate necessary structures for doing the stack walk
-    let process = processthreadsapi::GetCurrentProcess();
-    let thread = processthreadsapi::GetCurrentThread();
+    let process = GetCurrentProcess();
+    let thread = GetCurrentThread();
 
     let mut context = mem::zeroed::<MyContext>();
-    winnt::RtlCaptureContext(&mut context.0);
-    let mut frame = super::Frame {
-        inner: Frame { inner: mem::zeroed() },
+    RtlCaptureContext(&mut context.0);
+
+    // Ensure this process's symbols are initialized
+    let dbghelp = match dbghelp::init() {
+        Ok(dbghelp) => dbghelp,
+        Err(()) => return, // oh well...
     };
-    let image = init_frame(&mut frame.inner.inner, &context.0);
 
-    // Initialize this process's symbols
-    let _c = ::dbghelp_init();
+    // On x86_64 and ARM64 we opt to not use the default `Sym*` functions from
+    // dbghelp for getting the function table and module base. Instead we use
+    // the `RtlLookupFunctionEntry` function in kernel32 which will account for
+    // JIT compiler frames as well. These should be equivalent, but using
+    // `Rtl*` allows us to backtrace through JIT frames.
+    //
+    // Note that `RtlLookupFunctionEntry` only works for in-process backtraces,
+    // but that's all we support anyway, so it all lines up well.
+    cfg_if::cfg_if! {
+        if #[cfg(target_pointer_width = "64")] {
+            use core::ptr;
 
-    // And now that we're done with all the setup, do the stack walking!
-    while dbghelp::StackWalk64(image as DWORD,
-                               process,
-                               thread,
-                               &mut frame.inner.inner,
-                               &mut context.0 as *mut CONTEXT as *mut _,
-                               None,
-                               Some(dbghelp::SymFunctionTableAccess64),
-                               Some(dbghelp::SymGetModuleBase64),
-                               None) == TRUE {
-        if frame.inner.inner.AddrPC.Offset == frame.inner.inner.AddrReturn.Offset ||
-            frame.inner.inner.AddrPC.Offset == 0 ||
-                frame.inner.inner.AddrReturn.Offset == 0 {
-                    break
+            unsafe extern "system" fn function_table_access(_process: HANDLE, addr: DWORD64) -> PVOID {
+                let mut base = 0;
+                RtlLookupFunctionEntry(addr, &mut base, ptr::null_mut()).cast()
+            }
+
+            unsafe extern "system" fn get_module_base(_process: HANDLE, addr: DWORD64) -> DWORD64 {
+                let mut base = 0;
+                RtlLookupFunctionEntry(addr, &mut base, ptr::null_mut());
+                base
+            }
+        } else {
+            let function_table_access = dbghelp.SymFunctionTableAccess64();
+            let get_module_base = dbghelp.SymGetModuleBase64();
+        }
+    }
+
+    // Attempt to use `StackWalkEx` if we can, but fall back to `StackWalk64`
+    // since it's in theory supported on more systems.
+    match (*dbghelp.dbghelp()).StackWalkEx() {
+        Some(StackWalkEx) => {
+            let mut frame = super::Frame {
+                inner: Frame::New(mem::zeroed()),
+            };
+            let image = init_frame(&mut frame.inner, &context.0);
+            let frame_ptr = match &mut frame.inner {
+                Frame::New(ptr) => ptr as *mut STACKFRAME_EX,
+                _ => unreachable!(),
+            };
+
+            while StackWalkEx(
+                image as DWORD,
+                process,
+                thread,
+                frame_ptr,
+                &mut context.0 as *mut CONTEXT as *mut _,
+                None,
+                Some(function_table_access),
+                Some(get_module_base),
+                None,
+                0,
+            ) == TRUE
+            {
+                if !cb(&frame) {
+                    break;
                 }
+            }
+        }
+        None => {
+            let mut frame = super::Frame {
+                inner: Frame::Old(mem::zeroed()),
+            };
+            let image = init_frame(&mut frame.inner, &context.0);
+            let frame_ptr = match &mut frame.inner {
+                Frame::Old(ptr) => ptr as *mut STACKFRAME64,
+                _ => unreachable!(),
+            };
 
-        if !cb(&frame) {
-            break
+            while dbghelp.StackWalk64()(
+                image as DWORD,
+                process,
+                thread,
+                frame_ptr,
+                &mut context.0 as *mut CONTEXT as *mut _,
+                None,
+                Some(function_table_access),
+                Some(get_module_base),
+                None,
+            ) == TRUE
+            {
+                if !cb(&frame) {
+                    break;
+                }
+            }
         }
     }
 }
 
 #[cfg(target_arch = "x86_64")]
-fn init_frame(frame: &mut STACKFRAME64, ctx: &CONTEXT) -> WORD {
-    frame.AddrPC.Offset = ctx.Rip as u64;
-    frame.AddrPC.Mode = AddrModeFlat;
-    frame.AddrStack.Offset = ctx.Rsp as u64;
-    frame.AddrStack.Mode = AddrModeFlat;
-    frame.AddrFrame.Offset = ctx.Rbp as u64;
-    frame.AddrFrame.Mode = AddrModeFlat;
-    winnt::IMAGE_FILE_MACHINE_AMD64
+fn init_frame(frame: &mut Frame, ctx: &CONTEXT) -> WORD {
+    frame.addr_pc_mut().Offset = ctx.Rip as u64;
+    frame.addr_pc_mut().Mode = AddrModeFlat;
+    frame.addr_stack_mut().Offset = ctx.Rsp as u64;
+    frame.addr_stack_mut().Mode = AddrModeFlat;
+    frame.addr_frame_mut().Offset = ctx.Rbp as u64;
+    frame.addr_frame_mut().Mode = AddrModeFlat;
+
+    IMAGE_FILE_MACHINE_AMD64
 }
 
 #[cfg(target_arch = "x86")]
-fn init_frame(frame: &mut STACKFRAME64, ctx: &CONTEXT) -> WORD {
-    frame.AddrPC.Offset = ctx.Eip as u64;
-    frame.AddrPC.Mode = AddrModeFlat;
-    frame.AddrStack.Offset = ctx.Esp as u64;
-    frame.AddrStack.Mode = AddrModeFlat;
-    frame.AddrFrame.Offset = ctx.Ebp as u64;
-    frame.AddrFrame.Mode = AddrModeFlat;
-    winnt::IMAGE_FILE_MACHINE_I386
+fn init_frame(frame: &mut Frame, ctx: &CONTEXT) -> WORD {
+    frame.addr_pc_mut().Offset = ctx.Eip as u64;
+    frame.addr_pc_mut().Mode = AddrModeFlat;
+    frame.addr_stack_mut().Offset = ctx.Esp as u64;
+    frame.addr_stack_mut().Mode = AddrModeFlat;
+    frame.addr_frame_mut().Offset = ctx.Ebp as u64;
+    frame.addr_frame_mut().Mode = AddrModeFlat;
+
+    IMAGE_FILE_MACHINE_I386
+}
+
+#[cfg(target_arch = "aarch64")]
+fn init_frame(frame: &mut Frame, ctx: &CONTEXT) -> WORD {
+    frame.addr_pc_mut().Offset = ctx.Pc as u64;
+    frame.addr_pc_mut().Mode = AddrModeFlat;
+    frame.addr_stack_mut().Offset = ctx.Sp as u64;
+    frame.addr_stack_mut().Mode = AddrModeFlat;
+    unsafe {
+        frame.addr_frame_mut().Offset = ctx.u.s().Fp as u64;
+    }
+    frame.addr_frame_mut().Mode = AddrModeFlat;
+    IMAGE_FILE_MACHINE_ARM64
+}
+
+#[cfg(target_arch = "arm")]
+fn init_frame(frame: &mut Frame, ctx: &CONTEXT) -> WORD {
+    frame.addr_pc_mut().Offset = ctx.Pc as u64;
+    frame.addr_pc_mut().Mode = AddrModeFlat;
+    frame.addr_stack_mut().Offset = ctx.Sp as u64;
+    frame.addr_stack_mut().Mode = AddrModeFlat;
+    unsafe {
+        frame.addr_frame_mut().Offset = ctx.R11 as u64;
+    }
+    frame.addr_frame_mut().Mode = AddrModeFlat;
+    IMAGE_FILE_MACHINE_ARMNT
 }
diff --git a/third_party/rust_crates/vendor/backtrace/src/backtrace/libunwind.rs b/third_party/rust_crates/vendor/backtrace/src/backtrace/libunwind.rs
index b2d6fa6..21af00c 100644
--- a/third_party/rust_crates/vendor/backtrace/src/backtrace/libunwind.rs
+++ b/third_party/rust_crates/vendor/backtrace/src/backtrace/libunwind.rs
@@ -8,37 +8,62 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use types::c_void;
+//! Backtrace support using libunwind/gcc_s/etc APIs.
+//!
+//! This module contains the ability to unwind the stack using libunwind-style
+//! APIs. Note that there's a whole bunch of implementations of the
+//! libunwind-like API, and this is just trying to be compatible with most of
+//! them all at once instead of being picky.
+//!
+//! The libunwind API is powered by `_Unwind_Backtrace` and is in practice very
+//! reliable at generating a backtrace. It's not entirely clear how it does it
+//! (frame pointers? eh_frame info? both?) but it seems to work!
+//!
+//! Most of the complexity of this module is handling the various platform
+//! differences across libunwind implementations. Otherwise this is a pretty
+//! straightforward Rust binding to the libunwind APIs.
+//!
+//! This is the default unwinding API for all non-Windows platforms currently.
 
-pub struct Frame {
-    ctx: *mut uw::_Unwind_Context,
+use core::ffi::c_void;
+
+pub enum Frame {
+    Raw(*mut uw::_Unwind_Context),
+    Cloned {
+        ip: *mut c_void,
+        symbol_address: *mut c_void,
+    },
 }
 
+// With a raw libunwind pointer it should only ever be access in a readonly
+// threadsafe fashion, so it's `Sync`. When sending to other threads via `Clone`
+// we always switch to a version which doesn't retain interior pointers, so we
+// should be `Send` as well.
+unsafe impl Send for Frame {}
+unsafe impl Sync for Frame {}
+
 impl Frame {
     pub fn ip(&self) -> *mut c_void {
-        let mut ip_before_insn = 0;
-        let mut ip = unsafe {
-            uw::_Unwind_GetIPInfo(self.ctx, &mut ip_before_insn) as *mut c_void
+        let ctx = match *self {
+            Frame::Raw(ctx) => ctx,
+            Frame::Cloned { ip, .. } => return ip,
         };
-        if !ip.is_null() && ip_before_insn == 0 {
-            // this is a non-signaling frame, so `ip` refers to the address
-            // after the calling instruction. account for that.
-            ip = (ip as usize - 1) as *mut _;
-        }
-        return ip
+        unsafe { uw::_Unwind_GetIP(ctx) as *mut c_void }
     }
 
     pub fn symbol_address(&self) -> *mut c_void {
-        // dladdr() on osx gets whiny when we use FindEnclosingFunction, and
-        // it appears to work fine without it, so we only use
-        // FindEnclosingFunction on non-osx platforms. In doing so, we get a
-        // slightly more accurate stack trace in the process.
+        if let Frame::Cloned { symbol_address, .. } = *self {
+            return symbol_address;
+        }
+
+        // It seems that on OSX `_Unwind_FindEnclosingFunction` returns a
+        // pointer to... something that's unclear. It's definitely not always
+        // the enclosing function for whatever reason. It's not entirely clear
+        // to me what's going on here, so pessimize this for now and just always
+        // return the ip.
         //
-        // This is often because panic involves the last instruction of a
-        // function being "call std::rt::begin_unwind", with no ret
-        // instructions after it. This means that the return instruction
-        // pointer points *outside* of the calling function, and by
-        // unwinding it we go back to the original function.
+        // Note the `skip_inner_frames.rs` test is skipped on OSX due to this
+        // clause, and if this is fixed that test in theory can be run on OSX!
         if cfg!(target_os = "macos") || cfg!(target_os = "ios") {
             self.ip()
         } else {
@@ -47,18 +72,29 @@
     }
 }
 
+impl Clone for Frame {
+    fn clone(&self) -> Frame {
+        Frame::Cloned {
+            ip: self.ip(),
+            symbol_address: self.symbol_address(),
+        }
+    }
+}
+
 #[inline(always)]
 pub unsafe fn trace(mut cb: &mut FnMut(&super::Frame) -> bool) {
     uw::_Unwind_Backtrace(trace_fn, &mut cb as *mut _ as *mut _);
 
-    extern fn trace_fn(ctx: *mut uw::_Unwind_Context,
-                       arg: *mut c_void) -> uw::_Unwind_Reason_Code {
+    extern "C" fn trace_fn(
+        ctx: *mut uw::_Unwind_Context,
+        arg: *mut c_void,
+    ) -> uw::_Unwind_Reason_Code {
         let cb = unsafe { &mut *(arg as *mut &mut FnMut(&super::Frame) -> bool) };
         let cx = super::Frame {
-            inner: Frame { ctx: ctx },
+            inner: Frame::Raw(ctx),
         };
 
-        let mut bomb = ::Bomb { enabled: true };
+        let mut bomb = crate::Bomb { enabled: true };
         let keep_going = cb(&cx);
         bomb.enabled = false;
 
@@ -81,8 +117,7 @@
 mod uw {
     pub use self::_Unwind_Reason_Code::*;
 
-    use libc::{self, c_int};
-    use types::c_void;
+    use core::ffi::c_void;
 
     #[repr(C)]
     pub enum _Unwind_Reason_Code {
@@ -101,34 +136,40 @@
     pub enum _Unwind_Context {}
 
     pub type _Unwind_Trace_Fn =
-            extern fn(ctx: *mut _Unwind_Context,
-                      arg: *mut c_void) -> _Unwind_Reason_Code;
+        extern "C" fn(ctx: *mut _Unwind_Context, arg: *mut c_void) -> _Unwind_Reason_Code;
 
-    extern {
+    extern "C" {
         // No native _Unwind_Backtrace on iOS
         #[cfg(not(all(target_os = "ios", target_arch = "arm")))]
-        pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
-                                 trace_argument: *mut c_void)
-                    -> _Unwind_Reason_Code;
+        pub fn _Unwind_Backtrace(
+            trace: _Unwind_Trace_Fn,
+            trace_argument: *mut c_void,
+        ) -> _Unwind_Reason_Code;
 
         // available since GCC 4.2.0, should be fine for our purpose
-        #[cfg(all(not(all(target_os = "android", target_arch = "arm")),
-                  not(all(target_os = "linux", target_arch = "arm"))))]
-        pub fn _Unwind_GetIPInfo(ctx: *mut _Unwind_Context,
-                                 ip_before_insn: *mut c_int)
-                    -> libc::uintptr_t;
+        #[cfg(all(
+            not(all(target_os = "android", target_arch = "arm")),
+            not(all(target_os = "freebsd", target_arch = "arm")),
+            not(all(target_os = "linux", target_arch = "arm"))
+        ))]
+        pub fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> libc::uintptr_t;
 
-        #[cfg(all(not(target_os = "android"),
-                  not(all(target_os = "linux", target_arch = "arm"))))]
-        pub fn _Unwind_FindEnclosingFunction(pc: *mut c_void)
-            -> *mut c_void;
+        #[cfg(all(
+            not(target_os = "android"),
+            not(all(target_os = "freebsd", target_arch = "arm")),
+            not(all(target_os = "linux", target_arch = "arm"))
+        ))]
+        pub fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void;
     }
 
     // On android, the function _Unwind_GetIP is a macro, and this is the
     // expansion of the macro. This is all copy/pasted directly from the
     // header file with the definition of _Unwind_GetIP.
-    #[cfg(any(all(target_os = "android", target_arch = "arm"),
-              all(target_os = "linux", target_arch = "arm")))]
+    #[cfg(any(
+        all(target_os = "android", target_arch = "arm"),
+        all(target_os = "freebsd", target_arch = "arm"),
+        all(target_os = "linux", target_arch = "arm")
+    ))]
     pub unsafe fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> libc::uintptr_t {
         #[repr(C)]
         enum _Unwind_VRS_Result {
@@ -155,44 +196,36 @@
         }
 
         type _Unwind_Word = libc::c_uint;
-        extern {
-            fn _Unwind_VRS_Get(ctx: *mut _Unwind_Context,
-                               klass: _Unwind_VRS_RegClass,
-                               word: _Unwind_Word,
-                               repr: _Unwind_VRS_DataRepresentation,
-                               data: *mut c_void)
-                -> _Unwind_VRS_Result;
+        extern "C" {
+            fn _Unwind_VRS_Get(
+                ctx: *mut _Unwind_Context,
+                klass: _Unwind_VRS_RegClass,
+                word: _Unwind_Word,
+                repr: _Unwind_VRS_DataRepresentation,
+                data: *mut c_void,
+            ) -> _Unwind_VRS_Result;
         }
 
         let mut val: _Unwind_Word = 0;
         let ptr = &mut val as *mut _Unwind_Word;
-        let _ = _Unwind_VRS_Get(ctx, _Unwind_VRS_RegClass::_UVRSC_CORE, 15,
-                                _Unwind_VRS_DataRepresentation::_UVRSD_UINT32,
-                                ptr as *mut c_void);
+        let _ = _Unwind_VRS_Get(
+            ctx,
+            _Unwind_VRS_RegClass::_UVRSC_CORE,
+            15,
+            _Unwind_VRS_DataRepresentation::_UVRSD_UINT32,
+            ptr as *mut c_void,
+        );
         (val & !1) as libc::uintptr_t
     }
 
-    // This function doesn't exist on Android or ARM/Linux, so make it same
-    // to _Unwind_GetIP
-    #[cfg(any(all(target_os = "android", target_arch = "arm"),
-              all(target_os = "linux", target_arch = "arm")))]
-    pub unsafe fn _Unwind_GetIPInfo(ctx: *mut _Unwind_Context,
-                                    ip_before_insn: *mut c_int)
-        -> libc::uintptr_t
-    {
-        *ip_before_insn = 0;
-        _Unwind_GetIP(ctx)
-    }
-
     // This function also doesn't exist on Android or ARM/Linux, so make it
     // a no-op
-    #[cfg(any(target_os = "android",
-              all(target_os = "linux", target_arch = "arm")))]
-    pub unsafe fn _Unwind_FindEnclosingFunction(pc: *mut c_void)
-        -> *mut c_void
-    {
+    #[cfg(any(
+        target_os = "android",
+        all(target_os = "freebsd", target_arch = "arm"),
+        all(target_os = "linux", target_arch = "arm")
+    ))]
+    pub unsafe fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void {
         pc
     }
 }
-
-
diff --git a/third_party/rust_crates/vendor/backtrace/src/backtrace/mod.rs b/third_party/rust_crates/vendor/backtrace/src/backtrace/mod.rs
index da7af74..204974e 100644
--- a/third_party/rust_crates/vendor/backtrace/src/backtrace/mod.rs
+++ b/third_party/rust_crates/vendor/backtrace/src/backtrace/mod.rs
@@ -1,5 +1,5 @@
+use core::ffi::c_void;
 use core::fmt;
-use types::c_void;
 
 /// Inspects the current call-stack, passing all active frames into the closure
 /// provided to calculate a stack trace.
@@ -27,6 +27,13 @@
 /// This function requires the `std` feature of the `backtrace` crate to be
 /// enabled, and the `std` feature is enabled by default.
 ///
+/// # Panics
+///
+/// This function strives to never panic, but if the `cb` provided panics then
+/// some platforms will force a double panic to abort the process. Some
+/// platforms use a C library which internally uses callbacks which cannot be
+/// unwound through, so panicking from `cb` may trigger a process abort.
+///
 /// # Example
 ///
 /// ```
@@ -40,10 +47,9 @@
 ///     });
 /// }
 /// ```
-#[inline(always)]
 #[cfg(feature = "std")]
 pub fn trace<F: FnMut(&Frame) -> bool>(cb: F) {
-    let _guard = ::lock::lock();
+    let _guard = crate::lock::lock();
     unsafe { trace_unsynchronized(cb) }
 }
 
@@ -52,20 +58,23 @@
 /// This function does not have synchronization guarentees but is available
 /// when the `std` feature of this crate isn't compiled in. See the `trace`
 /// function for more documentation and examples.
-#[inline(never)]
+///
+/// # Panics
+///
+/// See information on `trace` for caveats on `cb` panicking.
 pub unsafe fn trace_unsynchronized<F: FnMut(&Frame) -> bool>(mut cb: F) {
     trace_imp(&mut cb)
 }
 
-
 /// A trait representing one frame of a backtrace, yielded to the `trace`
 /// function of this crate.
 ///
 /// The tracing function's closure will be yielded frames, and the frame is
 /// virtually dispatched as the underlying implementation is not always known
 /// until runtime.
+#[derive(Clone)]
 pub struct Frame {
-    inner: FrameImp,
+    pub(crate) inner: FrameImp,
 }
 
 impl Frame {
@@ -103,27 +112,41 @@
     }
 }
 
-cfg_if! {
-    if #[cfg(all(unix,
-                 not(target_os = "emscripten"),
-                 not(all(target_os = "ios", target_arch = "arm")),
-                 feature = "libunwind"))] {
+cfg_if::cfg_if! {
+    if #[cfg(
+        any(
+            all(
+                unix,
+                not(target_os = "emscripten"),
+                not(all(target_os = "ios", target_arch = "arm")),
+                feature = "libunwind",
+            ),
+            all(
+                target_env = "sgx",
+                target_vendor = "fortanix",
+            ),
+        )
+    )] {
         mod libunwind;
         use self::libunwind::trace as trace_imp;
-        use self::libunwind::Frame as FrameImp;
-    } else if #[cfg(all(unix,
-                        not(target_os = "emscripten"),
-                        feature = "unix-backtrace"))] {
+        pub(crate) use self::libunwind::Frame as FrameImp;
+    } else if #[cfg(
+        all(
+            unix,
+            not(target_os = "emscripten"),
+            feature = "unix-backtrace",
+        )
+    )] {
         mod unix_backtrace;
         use self::unix_backtrace::trace as trace_imp;
-        use self::unix_backtrace::Frame as FrameImp;
-    } else if #[cfg(all(windows, feature = "dbghelp"))] {
+        pub(crate) use self::unix_backtrace::Frame as FrameImp;
+    } else if #[cfg(all(windows, feature = "dbghelp", not(target_vendor = "uwp")))] {
         mod dbghelp;
         use self::dbghelp::trace as trace_imp;
-        use self::dbghelp::Frame as FrameImp;
+        pub(crate) use self::dbghelp::Frame as FrameImp;
     } else {
         mod noop;
         use self::noop::trace as trace_imp;
-        use self::noop::Frame as FrameImp;
+        pub(crate) use self::noop::Frame as FrameImp;
     }
 }
diff --git a/third_party/rust_crates/vendor/backtrace/src/backtrace/noop.rs b/third_party/rust_crates/vendor/backtrace/src/backtrace/noop.rs
index 4ad79cc..bc2eb0d 100644
--- a/third_party/rust_crates/vendor/backtrace/src/backtrace/noop.rs
+++ b/third_party/rust_crates/vendor/backtrace/src/backtrace/noop.rs
@@ -1,8 +1,12 @@
-use types::c_void;
+//! Empty implementation of unwinding used when no other implementation is
+//! appropriate.
+
+use core::ffi::c_void;
 
 #[inline(always)]
 pub fn trace(_cb: &mut FnMut(&super::Frame) -> bool) {}
 
+#[derive(Clone)]
 pub struct Frame;
 
 impl Frame {
diff --git a/third_party/rust_crates/vendor/backtrace/src/backtrace/unix_backtrace.rs b/third_party/rust_crates/vendor/backtrace/src/backtrace/unix_backtrace.rs
index a64d71d..7e3375a 100644
--- a/third_party/rust_crates/vendor/backtrace/src/backtrace/unix_backtrace.rs
+++ b/third_party/rust_crates/vendor/backtrace/src/backtrace/unix_backtrace.rs
@@ -8,21 +8,33 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+//! Unwinding through the `backtrace` function provided in Unix.
+//!
+//! This is an alternative unwinding strategy for Unix platforms which don't
+//! have support for libunwind but do have support for `backtrace`. Currently
+//! there's not a whole lot of those though. This module is a relatively
+//! straightforward binding of the `backtrace` API to the `Frame` API that we'd
+//! like to have.
+
+use core::ffi::c_void;
 use core::mem;
 use libc::c_int;
 
-use types::c_void;
-
+#[derive(Clone)]
 pub struct Frame {
-    addr: *mut c_void,
+    addr: usize,
 }
 
 impl Frame {
-    pub fn ip(&self) -> *mut c_void { self.addr }
-    pub fn symbol_address(&self) -> *mut c_void { self.addr }
+    pub fn ip(&self) -> *mut c_void {
+        self.addr as *mut c_void
+    }
+    pub fn symbol_address(&self) -> *mut c_void {
+        self.ip()
+    }
 }
 
-extern {
+extern "C" {
     fn backtrace(buf: *mut *mut c_void, sz: c_int) -> c_int;
 }
 
@@ -38,10 +50,12 @@
 
     for addr in buf[..cnt as usize].iter() {
         let cx = super::Frame {
-            inner: Frame { addr: *addr },
+            inner: Frame {
+                addr: *addr as usize,
+            },
         };
         if !cb(&cx) {
-            return
+            return;
         }
     }
 }
diff --git a/third_party/rust_crates/vendor/backtrace/src/capture.rs b/third_party/rust_crates/vendor/backtrace/src/capture.rs
index 99044a7..7b37bd1 100644
--- a/third_party/rust_crates/vendor/backtrace/src/capture.rs
+++ b/third_party/rust_crates/vendor/backtrace/src/capture.rs
@@ -1,9 +1,12 @@
-use std::prelude::v1::*;
+use crate::PrintFmt;
+use crate::{resolve, resolve_frame, trace, BacktraceFmt, Symbol, SymbolName};
+use std::ffi::c_void;
 use std::fmt;
 use std::path::{Path, PathBuf};
+use std::prelude::v1::*;
 
-use {trace, resolve, SymbolName};
-use types::c_void;
+#[cfg(feature = "serde")]
+use serde::{Deserialize, Serialize};
 
 /// Representation of an owned and self-contained backtrace.
 ///
@@ -12,9 +15,14 @@
 ///
 /// `Backtrace` supports pretty-printing of backtraces through its `Debug`
 /// implementation.
+///
+/// # Required features
+///
+/// This function requires the `std` feature of the `backtrace` crate to be
+/// enabled, and the `std` feature is enabled by default.
 #[derive(Clone)]
 #[cfg_attr(feature = "serialize-rustc", derive(RustcDecodable, RustcEncodable))]
-#[cfg_attr(feature = "serialize-serde", derive(Deserialize, Serialize))]
+#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
 pub struct Backtrace {
     // Frames here are listed from top-to-bottom of the stack
     frames: Vec<BacktraceFrame>,
@@ -23,26 +31,64 @@
     actual_start_index: usize,
 }
 
+fn _assert_send_sync() {
+    fn _assert<T: Send + Sync>() {}
+    _assert::<Backtrace>();
+}
+
 /// Captured version of a frame in a backtrace.
 ///
 /// This type is returned as a list from `Backtrace::frames` and represents one
 /// stack frame in a captured backtrace.
+///
+/// # Required features
+///
+/// This function requires the `std` feature of the `backtrace` crate to be
+/// enabled, and the `std` feature is enabled by default.
 #[derive(Clone)]
-#[cfg_attr(feature = "serialize-rustc", derive(RustcDecodable, RustcEncodable))]
-#[cfg_attr(feature = "serialize-serde", derive(Deserialize, Serialize))]
 pub struct BacktraceFrame {
-    ip: usize,
-    symbol_address: usize,
+    frame: Frame,
     symbols: Option<Vec<BacktraceSymbol>>,
 }
 
+#[derive(Clone)]
+enum Frame {
+    Raw(crate::Frame),
+    #[allow(dead_code)]
+    Deserialized {
+        ip: usize,
+        symbol_address: usize,
+    },
+}
+
+impl Frame {
+    fn ip(&self) -> *mut c_void {
+        match *self {
+            Frame::Raw(ref f) => f.ip(),
+            Frame::Deserialized { ip, .. } => ip as *mut c_void,
+        }
+    }
+
+    fn symbol_address(&self) -> *mut c_void {
+        match *self {
+            Frame::Raw(ref f) => f.symbol_address(),
+            Frame::Deserialized { symbol_address, .. } => symbol_address as *mut c_void,
+        }
+    }
+}
+
 /// Captured version of a symbol in a backtrace.
 ///
 /// This type is returned as a list from `BacktraceFrame::symbols` and
 /// represents the metadata for a symbol in a backtrace.
+///
+/// # Required features
+///
+/// This function requires the `std` feature of the `backtrace` crate to be
+/// enabled, and the `std` feature is enabled by default.
 #[derive(Clone)]
 #[cfg_attr(feature = "serialize-rustc", derive(RustcDecodable, RustcEncodable))]
-#[cfg_attr(feature = "serialize-serde", derive(Deserialize, Serialize))]
+#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
 pub struct BacktraceSymbol {
     name: Option<Vec<u8>>,
     addr: Option<usize>,
@@ -59,6 +105,12 @@
     /// elsewhere, and the purpose of this value is to be entirely self
     /// contained.
     ///
+    /// Note that on some platforms acquiring a full backtrace and resolving it
+    /// can be extremely expensive. If the cost is too much for your application
+    /// it's recommended to instead use `Backtrace::new_unresolved()` which
+    /// avoids the symbol resolution step (which typically takes the longest)
+    /// and allows deferring that to a later date.
+    ///
     /// # Examples
     ///
     /// ```
@@ -66,6 +118,11 @@
     ///
     /// let current_backtrace = Backtrace::new();
     /// ```
+    ///
+    /// # Required features
+    ///
+    /// This function requires the `std` feature of the `backtrace` crate to be
+    /// enabled, and the `std` feature is enabled by default.
     #[inline(never)] // want to make sure there's a frame here to remove
     pub fn new() -> Backtrace {
         let mut bt = Self::create(Self::new as usize);
@@ -91,30 +148,26 @@
     /// current_backtrace.resolve();
     /// println!("{:?}", current_backtrace); // symbol names now present
     /// ```
+    ///
+    /// # Required features
+    ///
+    /// This function requires the `std` feature of the `backtrace` crate to be
+    /// enabled, and the `std` feature is enabled by default.
     #[inline(never)] // want to make sure there's a frame here to remove
     pub fn new_unresolved() -> Backtrace {
         Self::create(Self::new_unresolved as usize)
     }
 
     fn create(ip: usize) -> Backtrace {
-        let ip_lo = ip;
-        let ip_hi = ip + 128;
-
         let mut frames = Vec::new();
         let mut actual_start_index = None;
         trace(|frame| {
-            let ip = frame.ip() as usize;
             frames.push(BacktraceFrame {
-                ip,
-                symbol_address: frame.symbol_address() as usize,
+                frame: Frame::Raw(frame.clone()),
                 symbols: None,
             });
 
-            if cfg!(not(all(target_os = "windows", target_arch = "x86"))) &&
-                ip >= ip_lo &&
-                ip <= ip_hi &&
-                actual_start_index.is_none()
-            {
+            if frame.symbol_address() as usize == ip && actual_start_index.is_none() {
                 actual_start_index = Some(frames.len());
             }
             true
@@ -131,6 +184,11 @@
     /// The first entry of this slice is likely the function `Backtrace::new`,
     /// and the last frame is likely something about how this thread or the main
     /// function started.
+    ///
+    /// # Required features
+    ///
+    /// This function requires the `std` feature of the `backtrace` crate to be
+    /// enabled, and the `std` feature is enabled by default.
     pub fn frames(&self) -> &[BacktraceFrame] {
         &self.frames[self.actual_start_index..]
     }
@@ -140,17 +198,30 @@
     ///
     /// If this backtrace has been previously resolved or was created through
     /// `new`, this function does nothing.
+    ///
+    /// # Required features
+    ///
+    /// This function requires the `std` feature of the `backtrace` crate to be
+    /// enabled, and the `std` feature is enabled by default.
     pub fn resolve(&mut self) {
         for frame in self.frames.iter_mut().filter(|f| f.symbols.is_none()) {
             let mut symbols = Vec::new();
-            resolve(frame.ip as *mut _, |symbol| {
-                symbols.push(BacktraceSymbol {
-                    name: symbol.name().map(|m| m.as_bytes().to_vec()),
-                    addr: symbol.addr().map(|a| a as usize),
-                    filename: symbol.filename().map(|m| m.to_owned()),
-                    lineno: symbol.lineno(),
-                });
-            });
+            {
+                let sym = |symbol: &Symbol| {
+                    symbols.push(BacktraceSymbol {
+                        name: symbol.name().map(|m| m.as_bytes().to_vec()),
+                        addr: symbol.addr().map(|a| a as usize),
+                        filename: symbol.filename().map(|m| m.to_owned()),
+                        lineno: symbol.lineno(),
+                    });
+                };
+                match frame.frame {
+                    Frame::Raw(ref f) => resolve_frame(f, sym),
+                    Frame::Deserialized { ip, .. } => {
+                        resolve(ip as *mut c_void, sym);
+                    }
+                }
+            }
             frame.symbols = Some(symbols);
         }
     }
@@ -173,13 +244,23 @@
 
 impl BacktraceFrame {
     /// Same as `Frame::ip`
+    ///
+    /// # Required features
+    ///
+    /// This function requires the `std` feature of the `backtrace` crate to be
+    /// enabled, and the `std` feature is enabled by default.
     pub fn ip(&self) -> *mut c_void {
-        self.ip as *mut c_void
+        self.frame.ip() as *mut c_void
     }
 
     /// Same as `Frame::symbol_address`
+    ///
+    /// # Required features
+    ///
+    /// This function requires the `std` feature of the `backtrace` crate to be
+    /// enabled, and the `std` feature is enabled by default.
     pub fn symbol_address(&self) -> *mut c_void {
-        self.symbol_address as *mut c_void
+        self.frame.symbol_address() as *mut c_void
     }
 
     /// Returns the list of symbols that this frame corresponds to.
@@ -191,6 +272,11 @@
     ///
     /// Note that if this frame came from an unresolved backtrace then this will
     /// return an empty list.
+    ///
+    /// # Required features
+    ///
+    /// This function requires the `std` feature of the `backtrace` crate to be
+    /// enabled, and the `std` feature is enabled by default.
     pub fn symbols(&self) -> &[BacktraceSymbol] {
         self.symbols.as_ref().map(|s| &s[..]).unwrap_or(&[])
     }
@@ -198,21 +284,41 @@
 
 impl BacktraceSymbol {
     /// Same as `Symbol::name`
+    ///
+    /// # Required features
+    ///
+    /// This function requires the `std` feature of the `backtrace` crate to be
+    /// enabled, and the `std` feature is enabled by default.
     pub fn name(&self) -> Option<SymbolName> {
         self.name.as_ref().map(|s| SymbolName::new(s))
     }
 
     /// Same as `Symbol::addr`
+    ///
+    /// # Required features
+    ///
+    /// This function requires the `std` feature of the `backtrace` crate to be
+    /// enabled, and the `std` feature is enabled by default.
     pub fn addr(&self) -> Option<*mut c_void> {
         self.addr.map(|s| s as *mut c_void)
     }
 
     /// Same as `Symbol::filename`
+    ///
+    /// # Required features
+    ///
+    /// This function requires the `std` feature of the `backtrace` crate to be
+    /// enabled, and the `std` feature is enabled by default.
     pub fn filename(&self) -> Option<&Path> {
         self.filename.as_ref().map(|p| &**p)
     }
 
     /// Same as `Symbol::lineno`
+    ///
+    /// # Required features
+    ///
+    /// This function requires the `std` feature of the `backtrace` crate to be
+    /// enabled, and the `std` feature is enabled by default.
     pub fn lineno(&self) -> Option<u32> {
         self.lineno
     }
@@ -220,51 +326,36 @@
 
 impl fmt::Debug for Backtrace {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        write!(fmt, "stack backtrace:")?;
-
-        let iter = if fmt.alternate() {
-            self.frames.iter()
+        let full = fmt.alternate();
+        let (frames, style) = if full {
+            (&self.frames[..], PrintFmt::Full)
         } else {
-            self.frames[self.actual_start_index..].iter()
+            (&self.frames[self.actual_start_index..], PrintFmt::Short)
         };
 
-        for (idx, frame) in iter.enumerate() {
-            let ip = frame.ip();
-            write!(fmt, "\n{:4}: ", idx)?;
-
-            let symbols = match frame.symbols {
-                Some(ref s) => s,
-                None => {
-                    write!(fmt, "<unresolved> ({:?})", ip)?;
-                    continue
-                }
-            };
-            if symbols.len() == 0 {
-                write!(fmt, "<no info> ({:?})", ip)?;
-                continue;
-            }
-
-            for (idx, symbol) in symbols.iter().enumerate() {
-                if idx != 0 {
-                    write!(fmt, "\n      ")?;
-                }
-
-                if let Some(name) = symbol.name() {
-                    write!(fmt, "{}", name)?;
-                } else {
-                    write!(fmt, "<unknown>")?;
-                }
-
-                if idx == 0 {
-                    write!(fmt, " ({:?})", ip)?;
-                }
-
-                if let (Some(file), Some(line)) = (symbol.filename(), symbol.lineno()) {
-                    write!(fmt, "\n             at {}:{}", file.display(), line)?;
+        // When printing paths we try to strip the cwd if it exists, otherwise
+        // we just print the path as-is. Note that we also only do this for the
+        // short format, because if it's full we presumably want to print
+        // everything.
+        let cwd = std::env::current_dir();
+        let mut print_path = move |fmt: &mut fmt::Formatter, path: crate::BytesOrWideString| {
+            let path = path.into_path_buf();
+            if !full {
+                if let Ok(cwd) = &cwd {
+                    if let Ok(suffix) = path.strip_prefix(cwd) {
+                        return fmt::Display::fmt(&suffix.display(), fmt);
+                    }
                 }
             }
+            fmt::Display::fmt(&path.display(), fmt)
+        };
+
+        let mut f = BacktraceFmt::new(fmt, style, &mut print_path);
+        f.add_context()?;
+        for frame in frames {
+            f.frame().backtrace_frame(frame)?;
         }
-
+        f.finish()?;
         Ok(())
     }
 }
@@ -274,3 +365,115 @@
         Backtrace::new()
     }
 }
+
+impl fmt::Debug for BacktraceFrame {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        fmt.debug_struct("BacktraceFrame")
+            .field("ip", &self.ip())
+            .field("symbol_address", &self.symbol_address())
+            .finish()
+    }
+}
+
+impl fmt::Debug for BacktraceSymbol {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        fmt.debug_struct("BacktraceSymbol")
+            .field("name", &self.name())
+            .field("addr", &self.addr())
+            .field("filename", &self.filename())
+            .field("lineno", &self.lineno())
+            .finish()
+    }
+}
+
+#[cfg(feature = "serialize-rustc")]
+mod rustc_serialize_impls {
+    use super::*;
+    use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
+
+    #[derive(RustcEncodable, RustcDecodable)]
+    struct SerializedFrame {
+        ip: usize,
+        symbol_address: usize,
+        symbols: Option<Vec<BacktraceSymbol>>,
+    }
+
+    impl Decodable for BacktraceFrame {
+        fn decode<D>(d: &mut D) -> Result<Self, D::Error>
+        where
+            D: Decoder,
+        {
+            let frame: SerializedFrame = SerializedFrame::decode(d)?;
+            Ok(BacktraceFrame {
+                frame: Frame::Deserialized {
+                    ip: frame.ip,
+                    symbol_address: frame.symbol_address,
+                },
+                symbols: frame.symbols,
+            })
+        }
+    }
+
+    impl Encodable for BacktraceFrame {
+        fn encode<E>(&self, e: &mut E) -> Result<(), E::Error>
+        where
+            E: Encoder,
+        {
+            let BacktraceFrame { frame, symbols } = self;
+            SerializedFrame {
+                ip: frame.ip() as usize,
+                symbol_address: frame.symbol_address() as usize,
+                symbols: symbols.clone(),
+            }
+            .encode(e)
+        }
+    }
+}
+
+#[cfg(feature = "serde")]
+mod serde_impls {
+    extern crate serde;
+
+    use self::serde::de::Deserializer;
+    use self::serde::ser::Serializer;
+    use self::serde::{Deserialize, Serialize};
+    use super::*;
+
+    #[derive(Serialize, Deserialize)]
+    struct SerializedFrame {
+        ip: usize,
+        symbol_address: usize,
+        symbols: Option<Vec<BacktraceSymbol>>,
+    }
+
+    impl Serialize for BacktraceFrame {
+        fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
+        where
+            S: Serializer,
+        {
+            let BacktraceFrame { frame, symbols } = self;
+            SerializedFrame {
+                ip: frame.ip() as usize,
+                symbol_address: frame.symbol_address() as usize,
+                symbols: symbols.clone(),
+            }
+            .serialize(s)
+        }
+    }
+
+    impl<'a> Deserialize<'a> for BacktraceFrame {
+        fn deserialize<D>(d: D) -> Result<Self, D::Error>
+        where
+            D: Deserializer<'a>,
+        {
+            let frame: SerializedFrame = SerializedFrame::deserialize(d)?;
+            Ok(BacktraceFrame {
+                frame: Frame::Deserialized {
+                    ip: frame.ip,
+                    symbol_address: frame.symbol_address,
+                },
+                symbols: frame.symbols,
+            })
+        }
+    }
+}
diff --git a/third_party/rust_crates/vendor/backtrace/src/dbghelp.rs b/third_party/rust_crates/vendor/backtrace/src/dbghelp.rs
new file mode 100644
index 0000000..05ffef2
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace/src/dbghelp.rs
@@ -0,0 +1,370 @@
+//! A module to assist in managing dbghelp bindings on Windows
+//!
+//! Backtraces on Windows (at least for MSVC) are largely powered through
+//! `dbghelp.dll` and the various functions that it contains. These functions
+//! are currently loaded *dynamically* rather than linking to `dbghelp.dll`
+//! statically. This is currently done by the standard library (and is in theory
+//! required there), but is an effort to help reduce the static dll dependencies
+//! of a library since backtraces are typically pretty optional. That being
+//! said, `dbghelp.dll` almost always successfully loads on Windows.
+//!
+//! Note though that since we're loading all this support dynamically we can't
+//! actually use the raw definitions in `winapi`, but rather we need to define
+//! the function pointer types ourselves and use that. We don't really want to
+//! be in the business of duplicating winapi, so we have a Cargo feature
+//! `verify-winapi` which asserts that all bindings match those in winapi and
+//! this feature is enabled on CI.
+//!
+//! Finally, you'll note here that the dll for `dbghelp.dll` is never unloaded,
+//! and that's currently intentional. The thinking is that we can globally cache
+//! it and use it between calls to the API, avoiding expensive loads/unloads. If
+//! this is a problem for leak detectors or something like that we can cross the
+//! bridge when we get there.
+
+#![allow(non_snake_case)]
+
+use crate::windows::*;
+use core::mem;
+use core::ptr;
+
+// Work around `SymGetOptions` and `SymSetOptions` not being present in winapi
+// itself. Otherwise this is only used when we're double-checking types against
+// winapi.
+#[cfg(feature = "verify-winapi")]
+mod dbghelp {
+    use crate::windows::*;
+    pub use winapi::um::dbghelp::{
+        StackWalk64, SymCleanup, SymFromAddrW, SymFunctionTableAccess64, SymGetLineFromAddrW64,
+        SymGetModuleBase64, SymInitializeW,
+    };
+
+    extern "system" {
+        // Not defined in winapi yet
+        pub fn SymGetOptions() -> u32;
+        pub fn SymSetOptions(_: u32);
+
+        // This is defined in winapi, but it's incorrect (FIXME winapi-rs#768)
+        pub fn StackWalkEx(
+            MachineType: DWORD,
+            hProcess: HANDLE,
+            hThread: HANDLE,
+            StackFrame: LPSTACKFRAME_EX,
+            ContextRecord: PVOID,
+            ReadMemoryRoutine: PREAD_PROCESS_MEMORY_ROUTINE64,
+            FunctionTableAccessRoutine: PFUNCTION_TABLE_ACCESS_ROUTINE64,
+            GetModuleBaseRoutine: PGET_MODULE_BASE_ROUTINE64,
+            TranslateAddress: PTRANSLATE_ADDRESS_ROUTINE64,
+            Flags: DWORD,
+        ) -> BOOL;
+
+        // Not defined in winapi yet
+        pub fn SymFromInlineContextW(
+            hProcess: HANDLE,
+            Address: DWORD64,
+            InlineContext: ULONG,
+            Displacement: PDWORD64,
+            Symbol: PSYMBOL_INFOW,
+        ) -> BOOL;
+        pub fn SymGetLineFromInlineContextW(
+            hProcess: HANDLE,
+            dwAddr: DWORD64,
+            InlineContext: ULONG,
+            qwModuleBaseAddress: DWORD64,
+            pdwDisplacement: PDWORD,
+            Line: PIMAGEHLP_LINEW64,
+        ) -> BOOL;
+    }
+
+    pub fn assert_equal_types<T>(a: T, _b: T) -> T {
+        a
+    }
+}
+
+// This macro is used to define a `Dbghelp` structure which internally contains
+// all the function pointers that we might load.
+macro_rules! dbghelp {
+    (extern "system" {
+        $(fn $name:ident($($arg:ident: $argty:ty),*) -> $ret: ty;)*
+    }) => (
+        pub struct Dbghelp {
+            /// The loaded DLL for `dbghelp.dll`
+            dll: HMODULE,
+
+            // Each function pointer for each function we might use
+            $($name: usize,)*
+        }
+
+        static mut DBGHELP: Dbghelp = Dbghelp {
+            // Initially we haven't loaded the DLL
+            dll: 0 as *mut _,
+            // Initiall all functions are set to zero to say they need to be
+            // dynamically loaded.
+            $($name: 0,)*
+        };
+
+        // Convenience typedef for each function type.
+        $(pub type $name = unsafe extern "system" fn($($argty),*) -> $ret;)*
+
+        impl Dbghelp {
+            /// Attempts to open `dbghelp.dll`. Returns success if it works or
+            /// error if `LoadLibraryW` fails.
+            ///
+            /// Panics if library is already loaded.
+            fn ensure_open(&mut self) -> Result<(), ()> {
+                if !self.dll.is_null() {
+                    return Ok(())
+                }
+                let lib = b"dbghelp.dll\0";
+                unsafe {
+                    self.dll = LoadLibraryA(lib.as_ptr() as *const i8);
+                    if self.dll.is_null() {
+                        Err(())
+                    }  else {
+                        Ok(())
+                    }
+                }
+            }
+
+            // Function for each method we'd like to use. When called it will
+            // either read the cached function pointer or load it and return the
+            // loaded value. Loads are asserted to succeed.
+            $(pub fn $name(&mut self) -> Option<$name> {
+                unsafe {
+                    if self.$name == 0 {
+                        let name = concat!(stringify!($name), "\0");
+                        self.$name = self.symbol(name.as_bytes())?;
+                    }
+                    let ret = mem::transmute::<usize, $name>(self.$name);
+                    #[cfg(feature = "verify-winapi")]
+                    dbghelp::assert_equal_types(ret, dbghelp::$name);
+                    Some(ret)
+                }
+            })*
+
+            fn symbol(&self, symbol: &[u8]) -> Option<usize> {
+                unsafe {
+                    match GetProcAddress(self.dll, symbol.as_ptr() as *const _) as usize {
+                        0 => None,
+                        n => Some(n),
+                    }
+                }
+            }
+        }
+
+        // Convenience proxy to use the cleanup locks to reference dbghelp
+        // functions.
+        #[allow(dead_code)]
+        impl Init {
+            $(pub fn $name(&self) -> $name {
+                unsafe {
+                    DBGHELP.$name().unwrap()
+                }
+            })*
+
+            pub fn dbghelp(&self) -> *mut Dbghelp {
+                unsafe {
+                    &mut DBGHELP
+                }
+            }
+        }
+    )
+
+}
+
+const SYMOPT_DEFERRED_LOADS: DWORD = 0x00000004;
+
+dbghelp! {
+    extern "system" {
+        fn SymGetOptions() -> DWORD;
+        fn SymSetOptions(options: DWORD) -> ();
+        fn SymInitializeW(
+            handle: HANDLE,
+            path: PCWSTR,
+            invade: BOOL
+        ) -> BOOL;
+        fn SymCleanup(handle: HANDLE) -> BOOL;
+        fn StackWalk64(
+            MachineType: DWORD,
+            hProcess: HANDLE,
+            hThread: HANDLE,
+            StackFrame: LPSTACKFRAME64,
+            ContextRecord: PVOID,
+            ReadMemoryRoutine: PREAD_PROCESS_MEMORY_ROUTINE64,
+            FunctionTableAccessRoutine: PFUNCTION_TABLE_ACCESS_ROUTINE64,
+            GetModuleBaseRoutine: PGET_MODULE_BASE_ROUTINE64,
+            TranslateAddress: PTRANSLATE_ADDRESS_ROUTINE64
+        ) -> BOOL;
+        fn SymFunctionTableAccess64(
+            hProcess: HANDLE,
+            AddrBase: DWORD64
+        ) -> PVOID;
+        fn SymGetModuleBase64(
+            hProcess: HANDLE,
+            AddrBase: DWORD64
+        ) -> DWORD64;
+        fn SymFromAddrW(
+            hProcess: HANDLE,
+            Address: DWORD64,
+            Displacement: PDWORD64,
+            Symbol: PSYMBOL_INFOW
+        ) -> BOOL;
+        fn SymGetLineFromAddrW64(
+            hProcess: HANDLE,
+            dwAddr: DWORD64,
+            pdwDisplacement: PDWORD,
+            Line: PIMAGEHLP_LINEW64
+        ) -> BOOL;
+        fn StackWalkEx(
+            MachineType: DWORD,
+            hProcess: HANDLE,
+            hThread: HANDLE,
+            StackFrame: LPSTACKFRAME_EX,
+            ContextRecord: PVOID,
+            ReadMemoryRoutine: PREAD_PROCESS_MEMORY_ROUTINE64,
+            FunctionTableAccessRoutine: PFUNCTION_TABLE_ACCESS_ROUTINE64,
+            GetModuleBaseRoutine: PGET_MODULE_BASE_ROUTINE64,
+            TranslateAddress: PTRANSLATE_ADDRESS_ROUTINE64,
+            Flags: DWORD
+        ) -> BOOL;
+        fn SymFromInlineContextW(
+            hProcess: HANDLE,
+            Address: DWORD64,
+            InlineContext: ULONG,
+            Displacement: PDWORD64,
+            Symbol: PSYMBOL_INFOW
+        ) -> BOOL;
+        fn SymGetLineFromInlineContextW(
+            hProcess: HANDLE,
+            dwAddr: DWORD64,
+            InlineContext: ULONG,
+            qwModuleBaseAddress: DWORD64,
+            pdwDisplacement: PDWORD,
+            Line: PIMAGEHLP_LINEW64
+        ) -> BOOL;
+    }
+}
+
+pub struct Init {
+    lock: HANDLE,
+}
+
+/// Initialize all support necessary to access `dbghelp` API functions from this
+/// crate.
+///
+/// Note that this function is **safe**, it internally has its own
+/// synchronization. Also note that it is safe to call this function multiple
+/// times recursively.
+#[cfg(all(windows, feature = "dbghelp"))]
+pub fn init() -> Result<Init, ()> {
+    use core::sync::atomic::{AtomicUsize, Ordering::SeqCst};
+
+    unsafe {
+        // First thing we need to do is to synchronize this function. This can
+        // be called concurrently from other threads or recursively within one
+        // thread. Note that it's trickier than that though because what we're
+        // using here, `dbghelp`, *also* needs to be synchronized with all other
+        // callers to `dbghelp` in this process.
+        //
+        // Typically there aren't really that many calls to `dbghelp` within the
+        // same process and we can probably safely assume that we're the only
+        // ones accessing it. There is, however, one primary other user we have
+        // to worry about which is ironically ourselves, but in the standard
+        // library. The Rust standard library depends on this crate for
+        // backtrace support, and this crate also exists on crates.io. This
+        // means that if the standard library is printing a panic backtrace it
+        // may race with this crate coming from crates.io, causing segfaults.
+        //
+        // To help solve this synchronization problem we employ a
+        // Windows-specific trick here (it is, after all, a Windows-specific
+        // restriction about synchronization). We create a *session-local* named
+        // mutex to protect this call. The intention here is that the standard
+        // library and this crate don't have to share Rust-level APIs to
+        // synchronize here but can instead work behind the scenes to make sure
+        // they're synchronizing with one another. That way when this function
+        // is called through the standard library or through crates.io we can be
+        // sure that the same mutex is being acquired.
+        //
+        // So all of that is to say that the first thing we do here is we
+        // atomically create a `HANDLE` which is a named mutex on Windows. We
+        // synchronize a bit with other threads sharing this function
+        // specifically and ensure that only one handle is created per instance
+        // of this function. Note that the handle is never closed once it's
+        // stored in the global.
+        //
+        // After we've actually go the lock we simply acquire it, and our `Init`
+        // handle we hand out will be responsible for dropping it eventually.
+        static LOCK: AtomicUsize = AtomicUsize::new(0);
+        let mut lock = LOCK.load(SeqCst);
+        if lock == 0 {
+            lock = CreateMutexA(
+                ptr::null_mut(),
+                0,
+                "Local\\RustBacktraceMutex\0".as_ptr() as _,
+            ) as usize;
+            if lock == 0 {
+                return Err(());
+            }
+            if let Err(other) = LOCK.compare_exchange(0, lock, SeqCst, SeqCst) {
+                debug_assert!(other != 0);
+                CloseHandle(lock as HANDLE);
+                lock = other;
+            }
+        }
+        debug_assert!(lock != 0);
+        let lock = lock as HANDLE;
+        let r = WaitForSingleObjectEx(lock, INFINITE, FALSE);
+        debug_assert_eq!(r, 0);
+        let ret = Init { lock };
+
+        // Ok, phew! Now that we're all safely synchronized, let's actually
+        // start processing everything. First up we need to ensure that
+        // `dbghelp.dll` is actually loaded in this process. We do this
+        // dynamically to avoid a static dependency. This has historically been
+        // done to work around weird linking issues and is intended at making
+        // binaries a bit more portable since this is largely just a debugging
+        // utility.
+        //
+        // Once we've opened `dbghelp.dll` we need to call some initialization
+        // functions in it, and that's detailed more below. We only do this
+        // once, though, so we've got a global boolean indicating whether we're
+        // done yet or not.
+        DBGHELP.ensure_open()?;
+
+        static mut INITIALIZED: bool = false;
+        if INITIALIZED {
+            return Ok(ret);
+        }
+
+        let orig = DBGHELP.SymGetOptions().unwrap()();
+
+        // Ensure that the `SYMOPT_DEFERRED_LOADS` flag is set, because
+        // according to MSVC's own docs about this: "This is the fastest, most
+        // efficient way to use the symbol handler.", so let's do that!
+        DBGHELP.SymSetOptions().unwrap()(orig | SYMOPT_DEFERRED_LOADS);
+
+        // Actually initialize symbols with MSVC. Note that this can fail, but we
+        // ignore it. There's not a ton of prior art for this per se, but LLVM
+        // internally seems to ignore the return value here and one of the
+        // sanitizer libraries in LLVM prints a scary warning if this fails but
+        // basically ignores it in the long run.
+        //
+        // One case this comes up a lot for Rust is that the standard library and
+        // this crate on crates.io both want to compete for `SymInitializeW`. The
+        // standard library historically wanted to initialize then cleanup most of
+        // the time, but now that it's using this crate it means that someone will
+        // get to initialization first and the other will pick up that
+        // initialization.
+        DBGHELP.SymInitializeW().unwrap()(GetCurrentProcess(), ptr::null_mut(), TRUE);
+        INITIALIZED = true;
+        Ok(ret)
+    }
+}
+
+impl Drop for Init {
+    fn drop(&mut self) {
+        unsafe {
+            let r = ReleaseMutex(self.lock);
+            debug_assert!(r != 0);
+        }
+    }
+}
diff --git a/third_party/rust_crates/vendor/backtrace/src/dylib.rs b/third_party/rust_crates/vendor/backtrace/src/dylib.rs
deleted file mode 100644
index b1dd6c3..0000000
--- a/third_party/rust_crates/vendor/backtrace/src/dylib.rs
+++ /dev/null
@@ -1,69 +0,0 @@
-use core::marker;
-use core::mem;
-use core::sync::atomic::{AtomicUsize, Ordering};
-
-use libc::{self, c_char, c_void};
-
-pub struct Dylib {
-    pub init: AtomicUsize,
-}
-
-pub struct Symbol<T> {
-    pub name: &'static str,
-    pub addr: AtomicUsize,
-    pub _marker: marker::PhantomData<T>,
-}
-
-impl Dylib {
-    pub unsafe fn get<'a, T>(&self, sym: &'a Symbol<T>) -> Option<&'a T> {
-        self.load().and_then(|handle| {
-            sym.get(handle)
-        })
-    }
-
-    pub unsafe fn init(&self, path: &str) -> bool {
-        if self.init.load(Ordering::SeqCst) != 0 {
-            return true
-        }
-        assert!(path.as_bytes()[path.len() - 1] == 0);
-        let ptr = libc::dlopen(path.as_ptr() as *const c_char, libc::RTLD_LAZY);
-        if ptr.is_null() {
-            return false
-        }
-        match self.init.compare_and_swap(0, ptr as usize, Ordering::SeqCst) {
-            0 => {}
-            _ => { libc::dlclose(ptr); }
-        }
-        return true
-    }
-
-    unsafe fn load(&self) -> Option<*mut c_void> {
-        match self.init.load(Ordering::SeqCst) {
-            0 => None,
-            n => Some(n as *mut c_void),
-        }
-    }
-}
-
-impl<T> Symbol<T> {
-    unsafe fn get(&self, handle: *mut c_void) -> Option<&T> {
-        assert_eq!(mem::size_of::<T>(), mem::size_of_val(&self.addr));
-        if self.addr.load(Ordering::SeqCst) == 0 {
-            self.addr.store(fetch(handle, self.name.as_ptr()), Ordering::SeqCst)
-        }
-        if self.addr.load(Ordering::SeqCst) == 1 {
-            None
-        } else {
-            mem::transmute::<&AtomicUsize, Option<&T>>(&self.addr)
-        }
-    }
-}
-
-unsafe fn fetch(handle: *mut c_void, name: *const u8) -> usize {
-    let ptr = libc::dlsym(handle, name as *const _);
-    if ptr.is_null() {
-        1
-    } else {
-        ptr as usize
-    }
-}
diff --git a/third_party/rust_crates/vendor/backtrace/src/lib.rs b/third_party/rust_crates/vendor/backtrace/src/lib.rs
index 49e75f0..69a283e 100644
--- a/third_party/rust_crates/vendor/backtrace/src/lib.rs
+++ b/third_party/rust_crates/vendor/backtrace/src/lib.rs
@@ -17,12 +17,6 @@
 //! of defaults is chosen for the current platform, but the features activated
 //! can also be controlled at a finer granularity.
 //!
-//! # Platform Support
-//!
-//! Currently this library is verified to work on Linux, OSX, and Windows, but
-//! it may work on other platforms as well. Note that the quality of the
-//! backtrace may vary across platforms.
-//!
 //! # API Principles
 //!
 //! This library attempts to be as flexible as possible to accommodate different
@@ -37,7 +31,7 @@
 //!
 //! ```toml
 //! [dependencies]
-//! backtrace = "0.2"
+//! backtrace = "0.3"
 //! ```
 //!
 //! Next:
@@ -53,7 +47,7 @@
 //!         let symbol_address = frame.symbol_address();
 //!
 //!         // Resolve this instruction pointer to a symbol name
-//!         backtrace::resolve(ip, |symbol| {
+//!         backtrace::resolve_frame(frame, |symbol| {
 //!             if let Some(name) = symbol.name() {
 //!                 // ...
 //!             }
@@ -71,59 +65,38 @@
 #![doc(html_root_url = "https://docs.rs/backtrace")]
 #![deny(missing_docs)]
 #![no_std]
+#![cfg_attr(
+    all(feature = "std", target_env = "sgx", target_vendor = "fortanix"),
+    feature(sgx_platform)
+)]
+#![allow(bare_trait_objects)] // TODO: remove when updating to 2018 edition
+#![allow(rust_2018_idioms)] // TODO: remove when updating to 2018 edition
 
 #[cfg(feature = "std")]
-#[macro_use] extern crate std;
-
-#[cfg(unix)]
-extern crate libc;
-#[cfg(windows)]
-extern crate winapi;
-
-#[cfg(feature = "serde_derive")]
-#[cfg_attr(feature = "serde_derive", macro_use)]
-extern crate serde_derive;
-
-#[cfg(feature = "rustc-serialize")]
-extern crate rustc_serialize;
-
 #[macro_use]
-extern crate cfg_if;
+extern crate std;
 
-extern crate rustc_demangle;
-
-#[cfg(feature = "cpp_demangle")]
-extern crate cpp_demangle;
-
-cfg_if! {
-    if #[cfg(all(feature = "gimli-symbolize", unix, target_os = "linux"))] {
-        extern crate addr2line;
-        extern crate findshlibs;
-        extern crate gimli;
-        extern crate memmap;
-        extern crate object;
-    }
-}
-
-#[allow(dead_code)] // not used everywhere
-#[cfg(unix)]
-#[macro_use]
-mod dylib;
-
-pub use backtrace::{trace_unsynchronized, Frame};
+pub use crate::backtrace::{trace_unsynchronized, Frame};
 mod backtrace;
 
-pub use symbolize::{resolve_unsynchronized, Symbol, SymbolName};
+pub use crate::symbolize::resolve_frame_unsynchronized;
+pub use crate::symbolize::{resolve_unsynchronized, Symbol, SymbolName};
 mod symbolize;
 
-pub use types::BytesOrWideString;
+pub use crate::types::BytesOrWideString;
 mod types;
 
-cfg_if! {
+#[cfg(feature = "std")]
+pub use crate::symbolize::clear_symbol_cache;
+
+mod print;
+pub use print::{BacktraceFmt, BacktraceFrameFmt, PrintFmt};
+
+cfg_if::cfg_if! {
     if #[cfg(feature = "std")] {
-        pub use backtrace::trace;
-        pub use symbolize::resolve;
-        pub use capture::{Backtrace, BacktraceFrame, BacktraceSymbol};
+        pub use crate::backtrace::trace;
+        pub use crate::symbolize::{resolve, resolve_frame};
+        pub use crate::capture::{Backtrace, BacktraceFrame, BacktraceSymbol};
         mod capture;
     }
 }
@@ -145,51 +118,42 @@
 #[allow(dead_code)]
 #[cfg(feature = "std")]
 mod lock {
-    use std::cell::Cell;
     use std::boxed::Box;
-    use std::sync::{Once, Mutex, MutexGuard, ONCE_INIT};
+    use std::cell::Cell;
+    use std::sync::{Mutex, MutexGuard, Once};
 
-    pub struct LockGuard(MutexGuard<'static, ()>);
+    pub struct LockGuard(Option<MutexGuard<'static, ()>>);
 
     static mut LOCK: *mut Mutex<()> = 0 as *mut _;
-    static INIT: Once = ONCE_INIT;
+    static INIT: Once = Once::new();
     thread_local!(static LOCK_HELD: Cell<bool> = Cell::new(false));
 
     impl Drop for LockGuard {
         fn drop(&mut self) {
-            LOCK_HELD.with(|slot| {
-                assert!(slot.get());
-                slot.set(false);
-            });
+            if self.0.is_some() {
+                LOCK_HELD.with(|slot| {
+                    assert!(slot.get());
+                    slot.set(false);
+                });
+            }
         }
     }
 
-    pub fn lock() -> Option<LockGuard> {
+    pub fn lock() -> LockGuard {
         if LOCK_HELD.with(|l| l.get()) {
-            return None
+            return LockGuard(None);
         }
         LOCK_HELD.with(|s| s.set(true));
         unsafe {
             INIT.call_once(|| {
                 LOCK = Box::into_raw(Box::new(Mutex::new(())));
             });
-            Some(LockGuard((*LOCK).lock().unwrap()))
+            LockGuard(Some((*LOCK).lock().unwrap()))
         }
     }
 }
 
-// requires external synchronization
-#[cfg(all(windows, feature = "dbghelp"))]
-unsafe fn dbghelp_init() {
-    use winapi::shared::minwindef;
-    use winapi::um::{dbghelp, processthreadsapi};
-
-    static mut INITIALIZED: bool = false;
-
-    if !INITIALIZED {
-        dbghelp::SymInitializeW(processthreadsapi::GetCurrentProcess(),
-                                0 as *mut _,
-                                minwindef::TRUE);
-        INITIALIZED = true;
-    }
-}
+#[cfg(all(windows, feature = "dbghelp", not(target_vendor = "uwp")))]
+mod dbghelp;
+#[cfg(windows)]
+mod windows;
diff --git a/third_party/rust_crates/vendor/backtrace/src/print.rs b/third_party/rust_crates/vendor/backtrace/src/print.rs
new file mode 100644
index 0000000..ce26f96
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace/src/print.rs
@@ -0,0 +1,268 @@
+use crate::BytesOrWideString;
+use core::ffi::c_void;
+use core::fmt;
+
+const HEX_WIDTH: usize = 2 + 2 * core::mem::size_of::<usize>();
+
+#[cfg(target_os = "fuchsia")]
+mod fuchsia;
+
+/// A formatter for backtraces.
+///
+/// This type can be used to print a backtrace regardless of where the backtrace
+/// itself comes from. If you have a `Backtrace` type then its `Debug`
+/// implementation already uses this printing format.
+pub struct BacktraceFmt<'a, 'b> {
+    fmt: &'a mut fmt::Formatter<'b>,
+    frame_index: usize,
+    format: PrintFmt,
+    print_path: &'a mut (FnMut(&mut fmt::Formatter, BytesOrWideString) -> fmt::Result + 'b),
+}
+
+/// The styles of printing that we can print
+#[derive(Copy, Clone, Eq, PartialEq)]
+pub enum PrintFmt {
+    /// Prints a terser backtrace which ideally only contains relevant information
+    Short,
+    /// Prints a backtrace that contains all possible information
+    Full,
+    #[doc(hidden)]
+    __Nonexhaustive,
+}
+
+impl<'a, 'b> BacktraceFmt<'a, 'b> {
+    /// Create a new `BacktraceFmt` which will write output to the provided
+    /// `fmt`.
+    ///
+    /// The `format` argument will control the style in which the backtrace is
+    /// printed, and the `print_path` argument will be used to print the
+    /// `BytesOrWideString` instances of filenames. This type itself doesn't do
+    /// any printing of filenames, but this callback is required to do so.
+    pub fn new(
+        fmt: &'a mut fmt::Formatter<'b>,
+        format: PrintFmt,
+        print_path: &'a mut (FnMut(&mut fmt::Formatter, BytesOrWideString) -> fmt::Result + 'b),
+    ) -> Self {
+        BacktraceFmt {
+            fmt,
+            frame_index: 0,
+            format,
+            print_path,
+        }
+    }
+
+    /// Prints a preamble for the backtrace about to be printed.
+    ///
+    /// This is required on some platforms for backtraces to be fully
+    /// sumbolicated later, and otherwise this should just be the first method
+    /// you call after creating a `BacktraceFmt`.
+    pub fn add_context(&mut self) -> fmt::Result {
+        self.fmt.write_str("stack backtrace:\n")?;
+        #[cfg(target_os = "fuchsia")]
+        fuchsia::print_dso_context(self.fmt)?;
+        Ok(())
+    }
+
+    /// Adds a frame to the backtrace output.
+    ///
+    /// This commit returns an RAII instance of a `BacktraceFrameFmt` which can be used
+    /// to actually print a frame, and on destruction it will increment the
+    /// frame counter.
+    pub fn frame(&mut self) -> BacktraceFrameFmt<'_, 'a, 'b> {
+        BacktraceFrameFmt {
+            fmt: self,
+            symbol_index: 0,
+        }
+    }
+
+    /// Completes the backtrace output.
+    ///
+    /// This is currently a no-op but is added for future compatibility with
+    /// backtrace formats.
+    pub fn finish(&mut self) -> fmt::Result {
+        // Currently a no-op-- including this hook to allow for future additions.
+        Ok(())
+    }
+}
+
+/// A formatter for just one frame of a backtrace.
+///
+/// This type is created by the `BacktraceFmt::frame` function.
+pub struct BacktraceFrameFmt<'fmt, 'a, 'b> {
+    fmt: &'fmt mut BacktraceFmt<'a, 'b>,
+    symbol_index: usize,
+}
+
+impl BacktraceFrameFmt<'_, '_, '_> {
+    /// Prints a `BacktraceFrame` with this frame formatter.
+    ///
+    /// This will recusrively print all `BacktraceSymbol` instances within the
+    /// `BacktraceFrame`.
+    ///
+    /// # Required features
+    ///
+    /// This function requires the `std` feature of the `backtrace` crate to be
+    /// enabled, and the `std` feature is enabled by default.
+    #[cfg(feature = "std")]
+    pub fn backtrace_frame(&mut self, frame: &crate::BacktraceFrame) -> fmt::Result {
+        let symbols = frame.symbols();
+        for symbol in symbols {
+            self.backtrace_symbol(frame, symbol)?;
+        }
+        if symbols.is_empty() {
+            self.print_raw(frame.ip(), None, None, None)?;
+        }
+        Ok(())
+    }
+
+    /// Prints a `BacktraceSymbol` within a `BacktraceFrame`.
+    ///
+    /// # Required features
+    ///
+    /// This function requires the `std` feature of the `backtrace` crate to be
+    /// enabled, and the `std` feature is enabled by default.
+    #[cfg(feature = "std")]
+    pub fn backtrace_symbol(
+        &mut self,
+        frame: &crate::BacktraceFrame,
+        symbol: &crate::BacktraceSymbol,
+    ) -> fmt::Result {
+        self.print_raw(
+            frame.ip(),
+            symbol.name(),
+            // TODO: this isn't great that we don't end up printing anything
+            // with non-utf8 filenames. Thankfully almost everything is utf8 so
+            // this shouldn't be too too bad.
+            symbol
+                .filename()
+                .and_then(|p| Some(BytesOrWideString::Bytes(p.to_str()?.as_bytes()))),
+            symbol.lineno(),
+        )?;
+        Ok(())
+    }
+
+    /// Prints a raw traced `Frame` and `Symbol`, typically from within the raw
+    /// callbacks of this crate.
+    pub fn symbol(&mut self, frame: &crate::Frame, symbol: &crate::Symbol) -> fmt::Result {
+        self.print_raw(
+            frame.ip(),
+            symbol.name(),
+            symbol.filename_raw(),
+            symbol.lineno(),
+        )?;
+        Ok(())
+    }
+
+    /// Adds a raw frame to the backtrace output.
+    ///
+    /// This method, unlike the previous, takes the raw arguments in case
+    /// they're being source from different locations. Note that this may be
+    /// called multiple times for one frame.
+    pub fn print_raw(
+        &mut self,
+        frame_ip: *mut c_void,
+        symbol_name: Option<crate::SymbolName>,
+        filename: Option<BytesOrWideString>,
+        lineno: Option<u32>,
+    ) -> fmt::Result {
+        // Fuchsia is unable to symbolize within a process so it has a special
+        // format which can be used to symbolize later. Print that instead of
+        // printing addresses in our own format here.
+        if cfg!(target_os = "fuchsia") {
+            self.print_raw_fuchsia(frame_ip)?;
+        } else {
+            self.print_raw_generic(frame_ip, symbol_name, filename, lineno)?;
+        }
+        self.symbol_index += 1;
+        Ok(())
+    }
+
+    #[allow(unused_mut)]
+    fn print_raw_generic(
+        &mut self,
+        mut frame_ip: *mut c_void,
+        symbol_name: Option<crate::SymbolName>,
+        filename: Option<BytesOrWideString>,
+        lineno: Option<u32>,
+    ) -> fmt::Result {
+        // No need to print "null" frames, it basically just means that the
+        // system backtrace was a bit eager to trace back super far.
+        if let PrintFmt::Short = self.fmt.format {
+            if frame_ip.is_null() {
+                return Ok(());
+            }
+        }
+
+        // To reduce TCB size in Sgx enclave, we do not want to implement symbol
+        // resolution functionality.  Rather, we can print the offset of the
+        // address here, which could be later mapped to correct function.
+        #[cfg(all(feature = "std", target_env = "sgx", target_vendor = "fortanix"))]
+        {
+            let image_base = std::os::fortanix_sgx::mem::image_base();
+            frame_ip = usize::wrapping_sub(frame_ip as usize, image_base as _) as _;
+        }
+
+        // Print the index of the frame as well as the optional instruction
+        // pointer of the frame. If we're beyond the first symbol of this frame
+        // though we just print appropriate whitespace.
+        if self.symbol_index == 0 {
+            write!(self.fmt.fmt, "{:4}: ", self.fmt.frame_index)?;
+            if let PrintFmt::Full = self.fmt.format {
+                write!(self.fmt.fmt, "{:1$?} - ", frame_ip, HEX_WIDTH)?;
+            }
+        } else {
+            write!(self.fmt.fmt, "      ")?;
+            if let PrintFmt::Full = self.fmt.format {
+                write!(self.fmt.fmt, "{:1$}", "", HEX_WIDTH + 3)?;
+            }
+        }
+
+        // Next up write out the symbol name, using the alternate formatting for
+        // more information if we're a full backtrace. Here we also handle
+        // symbols which don't have a name,
+        match (symbol_name, &self.fmt.format) {
+            (Some(name), PrintFmt::Short) => write!(self.fmt.fmt, "{:#}", name)?,
+            (Some(name), PrintFmt::Full) => write!(self.fmt.fmt, "{}", name)?,
+            (None, _) | (_, PrintFmt::__Nonexhaustive) => write!(self.fmt.fmt, "<unknown>")?,
+        }
+        self.fmt.fmt.write_str("\n")?;
+
+        // And last up, print out the filename/line number if they're available.
+        if let (Some(file), Some(line)) = (filename, lineno) {
+            self.print_fileline(file, line)?;
+        }
+
+        Ok(())
+    }
+
+    fn print_fileline(&mut self, file: BytesOrWideString, line: u32) -> fmt::Result {
+        // Filename/line are printed on lines under the symbol name, so print
+        // some appropriate whitespace to sort of right-align ourselves.
+        if let PrintFmt::Full = self.fmt.format {
+            write!(self.fmt.fmt, "{:1$}", "", HEX_WIDTH)?;
+        }
+        write!(self.fmt.fmt, "             at ")?;
+
+        // Delegate to our internal callback to print the filename and then
+        // print out the line number.
+        (self.fmt.print_path)(self.fmt.fmt, file)?;
+        write!(self.fmt.fmt, ":{}\n", line)?;
+        Ok(())
+    }
+
+    fn print_raw_fuchsia(&mut self, frame_ip: *mut c_void) -> fmt::Result {
+        // We only care about the first symbol of a frame
+        if self.symbol_index == 0 {
+            self.fmt.fmt.write_str("{{{bt:")?;
+            write!(self.fmt.fmt, "{}:{:?}", self.fmt.frame_index, frame_ip)?;
+            self.fmt.fmt.write_str("}}}\n")?;
+        }
+        Ok(())
+    }
+}
+
+impl Drop for BacktraceFrameFmt<'_, '_, '_> {
+    fn drop(&mut self) {
+        self.fmt.frame_index += 1;
+    }
+}
diff --git a/third_party/rust_crates/vendor/backtrace/src/print/fuchsia.rs b/third_party/rust_crates/vendor/backtrace/src/print/fuchsia.rs
new file mode 100644
index 0000000..787954a
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace/src/print/fuchsia.rs
@@ -0,0 +1,432 @@
+use core::fmt::{self, Write};
+use core::mem::{size_of, transmute};
+use core::slice::from_raw_parts;
+use libc::c_char;
+
+extern "C" {
+    // dl_iterate_phdr takes a callback that will receive a dl_phdr_info pointer
+    // for every DSO that has been linked into the process. dl_iterate_phdr also
+    // ensures that the dynamic linker is locked from start to finish of the
+    // iteration. If the callback returns a non-zero value the iteration is
+    // terminated early. 'data' will be passed as the third argument to the
+    // callback on each call. 'size' gives the size of the dl_phdr_info.
+    #[allow(improper_ctypes)]
+    fn dl_iterate_phdr(
+        f: extern "C" fn(info: &dl_phdr_info, size: usize, data: &mut DsoPrinter) -> i32,
+        data: &mut DsoPrinter,
+    ) -> i32;
+}
+
+// We need to parse out the build ID and some basic program header data
+// which means that we need a bit of stuff from the ELF spec as well.
+
+const PT_LOAD: u32 = 1;
+const PT_NOTE: u32 = 4;
+
+// Now we have to replicate, bit for bit, the structure of the dl_phdr_info
+// type used by fuchsia's current dynamic linker. Chromium also has this ABI
+// boundary as well as crashpad. Eventully we'd like to move these cases to
+// use elf-search but we'd need to provide that in the SDK and that has not
+// yet been done. Thus we (and they) are stuck having to use this method
+// which incurs a tight coupling with the fuchsia libc.
+
+#[allow(non_camel_case_types)]
+#[repr(C)]
+struct dl_phdr_info {
+    addr: *const u8,
+    name: *const c_char,
+    phdr: *const Elf_Phdr,
+    phnum: u16,
+    adds: u64,
+    subs: u64,
+    tls_modid: usize,
+    tls_data: *const u8,
+}
+
+impl dl_phdr_info {
+    fn program_headers(&self) -> PhdrIter<'_> {
+        PhdrIter {
+            phdrs: self.phdr_slice(),
+            base: self.addr,
+        }
+    }
+    // We have no way of knowing of checking if e_phoff and e_phnum are valid.
+    // libc should ensure this for us however so it's safe to form a slice here.
+    fn phdr_slice(&self) -> &[Elf_Phdr] {
+        unsafe { from_raw_parts(self.phdr, self.phnum as usize) }
+    }
+}
+
+struct PhdrIter<'a> {
+    phdrs: &'a [Elf_Phdr],
+    base: *const u8,
+}
+
+impl<'a> Iterator for PhdrIter<'a> {
+    type Item = Phdr<'a>;
+    fn next(&mut self) -> Option<Self::Item> {
+        self.phdrs.split_first().map(|(phdr, new_phdrs)| {
+            self.phdrs = new_phdrs;
+            Phdr {
+                phdr,
+                base: self.base,
+            }
+        })
+    }
+}
+
+// Elf_Phdr represents a 64-bit ELF program header in the endianness of the target
+// architecture.
+#[allow(non_camel_case_types)]
+#[derive(Clone, Debug)]
+#[repr(C)]
+struct Elf_Phdr {
+    p_type: u32,
+    p_flags: u32,
+    p_offset: u64,
+    p_vaddr: u64,
+    p_paddr: u64,
+    p_filesz: u64,
+    p_memsz: u64,
+    p_align: u64,
+}
+
+// Phdr represents a valid ELF program header and its contents.
+struct Phdr<'a> {
+    phdr: &'a Elf_Phdr,
+    base: *const u8,
+}
+
+impl<'a> Phdr<'a> {
+    // We have no way of checking if p_addr or p_memsz are valid. Fuchsia's libc
+    // parses the notes first however so by virtue of being here these headers
+    // must be valid. NoteIter does not require the underlying data to be valid
+    // but it does require the bounds to be valid. We trust that libc has ensured
+    // that this is the case for us here.
+    fn notes(&self) -> NoteIter<'a> {
+        unsafe {
+            NoteIter::new(
+                self.base.add(self.phdr.p_offset as usize),
+                self.phdr.p_memsz as usize,
+            )
+        }
+    }
+}
+
+// The note type for build IDs.
+const NT_GNU_BUILD_ID: u32 = 3;
+
+// Elf_Nhdr represents an ELF note header in the endianness of the target.
+#[allow(non_camel_case_types)]
+#[repr(C)]
+struct Elf_Nhdr {
+    n_namesz: u32,
+    n_descsz: u32,
+    n_type: u32,
+}
+
+// Note represents an ELF note (header + contents). The name is left as a u8
+// slice because it is not always null terminated and rust makes it easy enough
+// to check that the bytes match eitherway.
+struct Note<'a> {
+    name: &'a [u8],
+    desc: &'a [u8],
+    tipe: u32,
+}
+
+// NoteIter lets you safely iterate over a note segment. It terminates as soon
+// as an error occurs or there are no more notes. If you iterate over invalid
+// data it will function as though no notes were found.
+struct NoteIter<'a> {
+    base: &'a [u8],
+    error: bool,
+}
+
+impl<'a> NoteIter<'a> {
+    // It is an invariant of function that the pointer and size given denote a
+    // valid range of bytes that can all be read. The contents of these bytes
+    // can be anything but the range must be valid for this to be safe.
+    unsafe fn new(base: *const u8, size: usize) -> Self {
+        NoteIter {
+            base: from_raw_parts(base, size),
+            error: false,
+        }
+    }
+}
+
+// align_to aligns 'x' to 'to'-byte alignment assuming 'to' is a power of 2.
+// This follows a standard pattern in C/C++ ELF parsing code where
+// (x + to - 1) & -to is used. Rust does not let you negate usize so I use
+// 2's-complement conversion to recreate that.
+fn align_to(x: usize, to: usize) -> usize {
+    (x + to - 1) & (!to + 1)
+}
+
+// take_bytes_align4 consumes num bytes from the slice (if present) and
+// additionally ensures that the final slice is properlly aligned. If an
+// either the number of bytes requested is too large or the slice can't be
+// realigned afterwards due to not enough remaining bytes existing, None is
+// returned and the slice is not modified.
+fn take_bytes_align4<'a>(num: usize, bytes: &mut &'a [u8]) -> Option<&'a [u8]> {
+    if bytes.len() < align_to(num, 4) {
+        return None;
+    }
+    let (out, bytes_new) = bytes.split_at(num);
+    *bytes = &bytes_new[align_to(num, 4) - num..];
+    Some(out)
+}
+
+// This function has no real invariants the caller must uphold other than
+// perhaps that 'bytes' should be aligned for performance (and on some
+// architectures correctness). The values in the Elf_Nhdr fields might
+// be nonsense but this function ensures no such thing.
+fn take_nhdr<'a>(bytes: &mut &'a [u8]) -> Option<&'a Elf_Nhdr> {
+    if size_of::<Elf_Nhdr>() > bytes.len() {
+        return None;
+    }
+    // This is safe as long as there is enough space and we just confirmed that
+    // in the if statement above so this should not be unsafe.
+    let out = unsafe { transmute::<*const u8, &'a Elf_Nhdr>(bytes.as_ptr()) };
+    // Note that sice_of::<Elf_Nhdr>() is always 4-byte aligned.
+    *bytes = &bytes[size_of::<Elf_Nhdr>()..];
+    Some(out)
+}
+
+impl<'a> Iterator for NoteIter<'a> {
+    type Item = Note<'a>;
+    fn next(&mut self) -> Option<Self::Item> {
+        // Check if we've reached the end.
+        if self.base.len() == 0 || self.error {
+            return None;
+        }
+        // We transmute out an nhdr but we carefully consider the resulting
+        // struct. We don't trust the namesz or descsz and we make no unsafe
+        // decisions based on the type. So even if we get out complete garbage
+        // we should still be safe.
+        let nhdr = take_nhdr(&mut self.base)?;
+        let name = take_bytes_align4(nhdr.n_namesz as usize, &mut self.base)?;
+        let desc = take_bytes_align4(nhdr.n_descsz as usize, &mut self.base)?;
+        Some(Note {
+            name: name,
+            desc: desc,
+            tipe: nhdr.n_type,
+        })
+    }
+}
+
+struct Perm(u32);
+
+/// Indicates that a segment is executable.
+const PERM_X: u32 = 0b00000001;
+/// Indicates that a segment is writable.
+const PERM_W: u32 = 0b00000010;
+/// Indicates that a segment is readable.
+const PERM_R: u32 = 0b00000100;
+
+impl core::fmt::Display for Perm {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let v = self.0;
+        if v & PERM_R != 0 {
+            f.write_char('r')?
+        }
+        if v & PERM_W != 0 {
+            f.write_char('w')?
+        }
+        if v & PERM_X != 0 {
+            f.write_char('x')?
+        }
+        Ok(())
+    }
+}
+
+/// Represents an ELF segment at runtime.
+struct Segment {
+    /// Gives the runtime virtual address of this segment's contents.
+    addr: usize,
+    /// Gives the memory size of this segment's contents.
+    size: usize,
+    /// Gives the module virtual address of this segment with the ELF file.
+    mod_rel_addr: usize,
+    /// Gives the permissions found in the ELF file. These permissions are not
+    /// necessarily the permissions present at runtime however.
+    flags: Perm,
+}
+
+/// Lets one iterate over Segments from a DSO.
+struct SegmentIter<'a> {
+    phdrs: &'a [Elf_Phdr],
+    base: usize,
+}
+
+impl Iterator for SegmentIter<'_> {
+    type Item = Segment;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.phdrs.split_first().and_then(|(phdr, new_phdrs)| {
+            self.phdrs = new_phdrs;
+            if phdr.p_type != PT_LOAD {
+                self.next()
+            } else {
+                Some(Segment {
+                    addr: phdr.p_vaddr as usize + self.base,
+                    size: phdr.p_memsz as usize,
+                    mod_rel_addr: phdr.p_vaddr as usize,
+                    flags: Perm(phdr.p_flags),
+                })
+            }
+        })
+    }
+}
+
+/// Represents an ELF DSO (Dynamic Shared Object). This type references
+/// the data stored in the actual DSO rather than making its own copy.
+struct Dso<'a> {
+    /// The dynamic linker always gives us a name, even if the name is empty.
+    /// In the case of the main executable this name will be empty. In the case
+    /// of a shared object it will be the soname (see DT_SONAME).
+    name: &'a str,
+    /// On Fuchsia virtually all binaries have build IDs but this is not a strict
+    /// requierment. There's no way to match up DSO information with a real ELF
+    /// file afterwards if there is no build_id so we require that every DSO
+    /// have one here. DSO's without a build_id are ignored.
+    build_id: &'a [u8],
+
+    base: usize,
+    phdrs: &'a [Elf_Phdr],
+}
+
+impl Dso<'_> {
+    /// Returns an iterator over Segments in this DSO.
+    fn segments(&self) -> SegmentIter<'_> {
+        SegmentIter {
+            phdrs: self.phdrs.as_ref(),
+            base: self.base,
+        }
+    }
+}
+
+struct HexSlice<'a> {
+    bytes: &'a [u8],
+}
+
+impl fmt::Display for HexSlice<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        for byte in self.bytes {
+            write!(f, "{:02x}", byte)?;
+        }
+        Ok(())
+    }
+}
+
+fn get_build_id<'a>(info: &'a dl_phdr_info) -> Option<&'a [u8]> {
+    for phdr in info.program_headers() {
+        if phdr.phdr.p_type == PT_NOTE {
+            for note in phdr.notes() {
+                if note.tipe == NT_GNU_BUILD_ID && (note.name == b"GNU\0" || note.name == b"GNU") {
+                    return Some(note.desc);
+                }
+            }
+        }
+    }
+    None
+}
+
+/// These errors encode issues that arise while parsing information about
+/// each DSO.
+enum Error {
+    /// NameError means that an error occurred while converting a C style string
+    /// into a rust string.
+    NameError(core::str::Utf8Error),
+    /// BuildIDError means that we didn't find a build ID. This could either be
+    /// because the DSO had no build ID or because the segment containing the
+    /// build ID was malformed.
+    BuildIDError,
+}
+
+/// Calls either 'dso' or 'error' for each DSO linked into the process by the
+/// dynamic linker.
+///
+/// # Arguments
+///
+/// * `visitor` - A DsoPrinter that will have one of eats methods called foreach DSO.
+fn for_each_dso(mut visitor: &mut DsoPrinter) {
+    extern "C" fn callback(info: &dl_phdr_info, _size: usize, visitor: &mut DsoPrinter) -> i32 {
+        // dl_iterate_phdr ensures that info.name will point to a valid
+        // location.
+        let name_len = unsafe { libc::strlen(info.name) };
+        let name_slice: &[u8] =
+            unsafe { core::slice::from_raw_parts(info.name as *const u8, name_len) };
+        let name = match core::str::from_utf8(name_slice) {
+            Ok(name) => name,
+            Err(err) => {
+                return visitor.error(Error::NameError(err)) as i32;
+            }
+        };
+        let build_id = match get_build_id(info) {
+            Some(build_id) => build_id,
+            None => {
+                return visitor.error(Error::BuildIDError) as i32;
+            }
+        };
+        visitor.dso(Dso {
+            name: name,
+            build_id: build_id,
+            phdrs: info.phdr_slice(),
+            base: info.addr as usize,
+        }) as i32
+    }
+    unsafe { dl_iterate_phdr(callback, &mut visitor) };
+}
+
+struct DsoPrinter<'a, 'b> {
+    writer: &'a mut core::fmt::Formatter<'b>,
+    module_count: usize,
+    error: core::fmt::Result,
+}
+
+impl DsoPrinter<'_, '_> {
+    fn dso(&mut self, dso: Dso<'_>) -> bool {
+        let mut write = || {
+            write!(
+                self.writer,
+                "{{{{{{module:{:#x}:{}:elf:{}}}}}}}\n",
+                self.module_count,
+                dso.name,
+                HexSlice {
+                    bytes: dso.build_id.as_ref()
+                }
+            )?;
+            for seg in dso.segments() {
+                write!(
+                    self.writer,
+                    "{{{{{{mmap:{:#x}:{:#x}:load:{:#x}:{}:{:#x}}}}}}}\n",
+                    seg.addr, seg.size, self.module_count, seg.flags, seg.mod_rel_addr
+                )?;
+            }
+            self.module_count += 1;
+            Ok(())
+        };
+        match write() {
+            Ok(()) => false,
+            Err(err) => {
+                self.error = Err(err);
+                true
+            }
+        }
+    }
+    fn error(&mut self, _error: Error) -> bool {
+        false
+    }
+}
+
+/// This function prints the Fuchsia symbolizer markup for all information contained in a DSO.
+pub fn print_dso_context(out: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+    out.write_str("{{{reset}}}\n")?;
+    let mut visitor = DsoPrinter {
+        writer: out,
+        module_count: 0,
+        error: Ok(()),
+    };
+    for_each_dso(&mut visitor);
+    visitor.error
+}
diff --git a/third_party/rust_crates/vendor/backtrace/src/symbolize/coresymbolication.rs b/third_party/rust_crates/vendor/backtrace/src/symbolize/coresymbolication.rs
index f3c176f..24dc11a8e 100644
--- a/third_party/rust_crates/vendor/backtrace/src/symbolize/coresymbolication.rs
+++ b/third_party/rust_crates/vendor/backtrace/src/symbolize/coresymbolication.rs
@@ -8,25 +8,38 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+//! Symbolication strategy that's OSX-specific and uses the `CoreSymbolication`
+//! framework, if possible.
+//!
+//! This strategy uses internal private APIs that are somewhat undocumented but
+//! seem to be widely used on OSX. This is the default symbolication strategy
+//! for OSX, but is turned off in release builds for iOS due to reports of apps
+//! being rejected due to using these APIs.
+//!
+//! This would probably be good to get official one day and not using private
+//! APIs, but for now it should largely suffice.
+//!
+//! Note that this module will dynamically load `CoreSymbolication` and its APIs
+//! through dlopen/dlsym, and if the loading fails this falls back to `dladdr`
+//! as a symbolication strategy.
+
 #![allow(bad_style)]
 
+use crate::symbolize::dladdr;
+use crate::symbolize::ResolveWhat;
+use crate::types::BytesOrWideString;
+use crate::SymbolName;
+use core::ffi::c_void;
 use core::mem;
 use core::ptr;
 use core::slice;
-use core::sync::atomic::ATOMIC_USIZE_INIT;
-
-use libc::{self, Dl_info, c_char, c_int};
-
-use SymbolName;
-use dylib::Dylib;
-use dylib::Symbol as DylibSymbol;
-use types::{BytesOrWideString, c_void};
+use libc::{c_char, c_int};
 
 #[repr(C)]
 #[derive(Copy, Clone, PartialEq)]
 pub struct CSTypeRef {
     cpp_data: *const c_void,
-    cpp_obj: *const c_void
+    cpp_obj: *const c_void,
 }
 
 const CS_NOW: u64 = 0x80000000;
@@ -35,21 +48,21 @@
     cpp_obj: 0 as *const c_void,
 };
 
-pub enum Symbol {
+pub enum Symbol<'a> {
     Core {
         path: *const c_char,
         lineno: u32,
         name: *const c_char,
         addr: *mut c_void,
     },
-    Dladdr(Dl_info),
+    Dladdr(dladdr::Symbol<'a>),
 }
 
-impl Symbol {
+impl Symbol<'_> {
     pub fn name(&self) -> Option<SymbolName> {
         let name = match *self {
             Symbol::Core { name, .. } => name,
-            Symbol::Dladdr(ref info) => info.dli_sname,
+            Symbol::Dladdr(ref info) => return info.name(),
         };
         if name.is_null() {
             None
@@ -64,26 +77,39 @@
     pub fn addr(&self) -> Option<*mut c_void> {
         match *self {
             Symbol::Core { addr, .. } => Some(addr),
-            Symbol::Dladdr(ref info) => Some(info.dli_saddr as *mut _),
+            Symbol::Dladdr(ref info) => info.addr(),
         }
     }
 
-    pub fn filename_raw(&self) -> Option<BytesOrWideString> {
+    fn filename_bytes(&self) -> Option<&[u8]> {
         match *self {
             Symbol::Core { path, .. } => {
                 if path.is_null() {
                     None
                 } else {
-                    Some(BytesOrWideString::Bytes(unsafe {
+                    Some(unsafe {
                         let len = libc::strlen(path);
                         slice::from_raw_parts(path as *const u8, len)
-                    }))
+                    })
                 }
             }
             Symbol::Dladdr(_) => None,
         }
     }
 
+    pub fn filename_raw(&self) -> Option<BytesOrWideString> {
+        self.filename_bytes().map(BytesOrWideString::Bytes)
+    }
+
+    #[cfg(feature = "std")]
+    pub fn filename(&self) -> Option<&::std::path::Path> {
+        use std::ffi::OsStr;
+        use std::os::unix::prelude::*;
+        use std::path::Path;
+
+        self.filename_bytes().map(OsStr::from_bytes).map(Path::new)
+    }
+
     pub fn lineno(&self) -> Option<u32> {
         match *self {
             Symbol::Core { lineno: 0, .. } => None,
@@ -93,25 +119,75 @@
     }
 }
 
-static CORESYMBOLICATION: Dylib = Dylib { init: ATOMIC_USIZE_INIT };
+macro_rules! coresymbolication {
+    (#[load_path = $path:tt] extern "C" {
+        $(fn $name:ident($($arg:ident: $argty:ty),*) -> $ret: ty;)*
+    }) => (
+        pub struct CoreSymbolication {
+            // The loaded dynamic library
+            dll: *mut c_void,
 
-macro_rules! dlsym {
-    (extern {
-        $(fn $name:ident($($arg:ident: $t:ty),*) -> $ret:ty;)*
-    }) => ($(
-        static $name: ::dylib::Symbol<unsafe extern fn($($t),*) -> $ret> =
-            ::dylib::Symbol {
-                name: concat!(stringify!($name), "\0"),
-                addr: ::core::sync::atomic::ATOMIC_USIZE_INIT,
-                _marker: ::core::marker::PhantomData,
-            };
-    )*)
+            // Each function pointer for each function we might use
+            $($name: usize,)*
+        }
+
+        static mut CORESYMBOLICATION: CoreSymbolication = CoreSymbolication {
+            // Initially we haven't loaded the dynamic library
+            dll: 0 as *mut _,
+            // Initiall all functions are set to zero to say they need to be
+            // dynamically loaded.
+            $($name: 0,)*
+        };
+
+        // Convenience typedef for each function type.
+        $(pub type $name = unsafe extern "C" fn($($argty),*) -> $ret;)*
+
+        impl CoreSymbolication {
+            /// Attempts to open `dbghelp.dll`. Returns `true` if it works or
+            /// `false` if `dlopen` fails.
+            fn open(&mut self) -> bool {
+                if !self.dll.is_null() {
+                    return true;
+                }
+                let lib = concat!($path, "\0").as_bytes();
+                unsafe {
+                    self.dll = libc::dlopen(lib.as_ptr() as *const _, libc::RTLD_LAZY);
+                    !self.dll.is_null()
+                }
+            }
+
+            // Function for each method we'd like to use. When called it will
+            // either read the cached function pointer or load it and return the
+            // loaded value. Loads are asserted to succeed.
+            $(pub fn $name(&mut self) -> $name {
+                unsafe {
+                    if self.$name == 0 {
+                        let name = concat!(stringify!($name), "\0");
+                        self.$name = self.symbol(name.as_bytes())
+                            .expect(concat!("symbol ", stringify!($name), " is missing"));
+                    }
+                    mem::transmute::<usize, $name>(self.$name)
+                }
+            })*
+
+            fn symbol(&self, symbol: &[u8]) -> Option<usize> {
+                unsafe {
+                    match libc::dlsym(self.dll, symbol.as_ptr() as *const _) as usize {
+                        0 => None,
+                        n => Some(n),
+                    }
+                }
+            }
+        }
+    )
 }
 
-dlsym! {
-    extern {
+coresymbolication! {
+    #[load_path = "/System/Library/PrivateFrameworks/CoreSymbolication.framework\
+                 /Versions/A/CoreSymbolication"]
+    extern "C" {
         fn CSSymbolicatorCreateWithPid(pid: c_int) -> CSTypeRef;
-        fn CSRelease(rf: CSTypeRef) -> c_void;
+        fn CSRelease(rf: CSTypeRef) -> ();
         fn CSSymbolicatorGetSymbolWithAddressAtTime(
             cs: CSTypeRef, addr: *const c_void, time: u64) -> CSTypeRef;
         fn CSSymbolicatorGetSourceInfoWithAddressAtTime(
@@ -125,66 +201,77 @@
     }
 }
 
-unsafe fn get<T>(sym: &DylibSymbol<T>) -> &T {
-    CORESYMBOLICATION.get(sym).unwrap()
-}
-
 unsafe fn try_resolve(addr: *mut c_void, cb: &mut FnMut(&super::Symbol)) -> bool {
-    let path = "/System/Library/PrivateFrameworks/CoreSymbolication.framework\
-                /Versions/A/CoreSymbolication\0";
-    if !CORESYMBOLICATION.init(path) {
+    // Note that this is externally synchronized so there's no need for
+    // synchronization here, making this `static mut` safer.
+    let lib = &mut CORESYMBOLICATION;
+    if !lib.open() {
         return false;
     }
 
-    let cs = get(&CSSymbolicatorCreateWithPid)(libc::getpid());
+    let cs = lib.CSSymbolicatorCreateWithPid()(libc::getpid());
     if cs == CSREF_NULL {
-        return false
+        return false;
     }
-
-    let info = get(&CSSymbolicatorGetSourceInfoWithAddressAtTime)(
-        cs, addr, CS_NOW);
-    let sym = if info == CSREF_NULL {
-        get(&CSSymbolicatorGetSymbolWithAddressAtTime)(cs, addr, CS_NOW)
-    } else {
-        get(&CSSourceInfoGetSymbol)(info)
+    let _dtor = OwnedCSTypeRef {
+        ptr: cs,
+        CSRelease: lib.CSRelease(),
     };
 
-    let mut rv = false;
-    if sym != CSREF_NULL {
-        let owner = get(&CSSymbolGetSymbolOwner)(sym);
-        if owner != CSREF_NULL {
-            cb(&super::Symbol {
-                inner: Symbol::Core {
-                    path: if info != CSREF_NULL {
-                        get(&CSSourceInfoGetPath)(info)
-                    } else {
-                        ptr::null()
-                    },
-                    lineno: if info != CSREF_NULL {
-                        get(&CSSourceInfoGetLineNumber)(info) as u32
-                    } else {
-                        0
-                    },
-                    name: get(&CSSymbolGetMangledName)(sym),
-                    addr: get(&CSSymbolOwnerGetBaseAddress)(owner),
-                },
-            });
-            rv = true;
-        }
+    let info = lib.CSSymbolicatorGetSourceInfoWithAddressAtTime()(cs, addr, CS_NOW);
+    let sym = if info == CSREF_NULL {
+        lib.CSSymbolicatorGetSymbolWithAddressAtTime()(cs, addr, CS_NOW)
+    } else {
+        lib.CSSourceInfoGetSymbol()(info)
+    };
+    if sym == CSREF_NULL {
+        return false;
     }
-    get(&CSRelease)(cs);
+    let owner = lib.CSSymbolGetSymbolOwner()(sym);
+    if owner == CSREF_NULL {
+        return false;
+    }
 
-    rv
+    cb(&super::Symbol {
+        inner: Symbol::Core {
+            path: if info != CSREF_NULL {
+                lib.CSSourceInfoGetPath()(info)
+            } else {
+                ptr::null()
+            },
+            lineno: if info != CSREF_NULL {
+                lib.CSSourceInfoGetLineNumber()(info) as u32
+            } else {
+                0
+            },
+            name: lib.CSSymbolGetMangledName()(sym),
+            addr: lib.CSSymbolOwnerGetBaseAddress()(owner),
+        },
+    });
+    true
 }
 
-pub unsafe fn resolve(addr: *mut c_void, cb: &mut FnMut(&super::Symbol)) {
+struct OwnedCSTypeRef {
+    ptr: CSTypeRef,
+    CSRelease: unsafe extern "C" fn(CSTypeRef),
+}
+
+impl Drop for OwnedCSTypeRef {
+    fn drop(&mut self) {
+        unsafe {
+            (self.CSRelease)(self.ptr);
+        }
+    }
+}
+
+pub unsafe fn resolve(what: ResolveWhat, cb: &mut FnMut(&super::Symbol)) {
+    let addr = what.address_or_ip();
     if try_resolve(addr, cb) {
-        return
+        return;
     }
-    let mut info: Dl_info = mem::zeroed();
-    if libc::dladdr(addr as *mut _, &mut info) != 0 {
+    dladdr::resolve(addr, &mut |sym| {
         cb(&super::Symbol {
-            inner: Symbol::Dladdr(info),
-        });
-    }
+            inner: Symbol::Dladdr(sym),
+        })
+    })
 }
diff --git a/third_party/rust_crates/vendor/backtrace/src/symbolize/dbghelp.rs b/third_party/rust_crates/vendor/backtrace/src/symbolize/dbghelp.rs
index abc8986..7afcee7 100644
--- a/third_party/rust_crates/vendor/backtrace/src/symbolize/dbghelp.rs
+++ b/third_party/rust_crates/vendor/backtrace/src/symbolize/dbghelp.rs
@@ -8,33 +8,39 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+//! Symbolication strategy using `dbghelp.dll` on Windows, only used for MSVC
+//!
+//! This symbolication strategy, like with backtraces, uses dynamically loaded
+//! information from `dbghelp.dll`. (see `src/dbghelp.rs` for info about why
+//! it's dynamically loaded).
+//!
+//! This API selects its resolution strategy based on the frame provided or the
+//! information we have at hand. If a frame from `StackWalkEx` is given to us
+//! then we use similar APIs to generate correct information about inlined
+//! functions. Otherwise if all we have is an address or an older stack frame
+//! from `StackWalk64` we use the older APIs for symbolication.
+//!
+//! There's a good deal of support in this module, but a good chunk of it is
+//! converting back and forth between Windows types and Rust types. For example
+//! symbols come to us as wide strings which we then convert to utf-8 strings if
+//! we can.
+
 #![allow(bad_style)]
 
-// This is a hack for compatibility with rustc 1.25.0. The no_std mode of this
-// crate is not supported pre-1.30.0, but in std mode the `char` module here
-// moved in rustc 1.26.0 (ish). As a result, in std mode we use `std::char` to
-// retain compatibility with rustc 1.25.0, but in `no_std` mode (which is
-// 1.30.0+ already) we use `core::char`.
-#[cfg(feature = "std")]
-use std::char;
-#[cfg(not(feature = "std"))]
+use crate::backtrace::FrameImp as Frame;
+use crate::dbghelp;
+use crate::symbolize::ResolveWhat;
+use crate::types::BytesOrWideString;
+use crate::windows::*;
+use crate::SymbolName;
 use core::char;
-
+use core::ffi::c_void;
+use core::marker;
 use core::mem;
 use core::slice;
 
-use winapi::ctypes::*;
-use winapi::shared::basetsd::*;
-use winapi::shared::minwindef::*;
-use winapi::um::processthreadsapi;
-use winapi::um::dbghelp;
-use winapi::um::dbghelp::*;
-
-use SymbolName;
-use types::BytesOrWideString;
-
 // Store an OsString on std so we can provide the symbol name and filename.
-pub struct Symbol {
+pub struct Symbol<'a> {
     name: *const [u8],
     addr: *mut c_void,
     line: Option<u32>,
@@ -43,9 +49,10 @@
     _filename_cache: Option<::std::ffi::OsString>,
     #[cfg(not(feature = "std"))]
     _filename_cache: (),
+    _marker: marker::PhantomData<&'a i32>,
 }
 
-impl Symbol {
+impl Symbol<'_> {
     pub fn name(&self) -> Option<SymbolName> {
         Some(SymbolName::new(unsafe { &*self.name }))
     }
@@ -55,11 +62,8 @@
     }
 
     pub fn filename_raw(&self) -> Option<BytesOrWideString> {
-        self.filename.map(|slice| {
-            unsafe {
-                BytesOrWideString::Wide(&*slice)
-            }
-        })
+        self.filename
+            .map(|slice| unsafe { BytesOrWideString::Wide(&*slice) })
     }
 
     pub fn lineno(&self) -> Option<u32> {
@@ -67,15 +71,78 @@
     }
 
     #[cfg(feature = "std")]
-    pub fn filename(&self) -> Option<&::std::ffi::OsString> {
-        self._filename_cache.as_ref()
+    pub fn filename(&self) -> Option<&::std::path::Path> {
+        use std::path::Path;
+
+        self._filename_cache.as_ref().map(Path::new)
     }
 }
 
 #[repr(C, align(8))]
 struct Aligned8<T>(T);
 
-pub unsafe fn resolve(addr: *mut c_void, cb: &mut FnMut(&super::Symbol)) {
+pub unsafe fn resolve(what: ResolveWhat, cb: &mut FnMut(&super::Symbol)) {
+    // Ensure this process's symbols are initialized
+    let dbghelp = match dbghelp::init() {
+        Ok(dbghelp) => dbghelp,
+        Err(()) => return, // oh well...
+    };
+
+    match what {
+        ResolveWhat::Address(_) => resolve_without_inline(&dbghelp, what.address_or_ip(), cb),
+        ResolveWhat::Frame(frame) => match &frame.inner {
+            Frame::New(frame) => resolve_with_inline(&dbghelp, frame, cb),
+            Frame::Old(_) => resolve_without_inline(&dbghelp, frame.ip(), cb),
+        },
+    }
+}
+
+unsafe fn resolve_with_inline(
+    dbghelp: &dbghelp::Init,
+    frame: &STACKFRAME_EX,
+    cb: &mut FnMut(&super::Symbol),
+) {
+    do_resolve(
+        |info| {
+            dbghelp.SymFromInlineContextW()(
+                GetCurrentProcess(),
+                super::adjust_ip(frame.AddrPC.Offset as *mut _) as u64,
+                frame.InlineFrameContext,
+                &mut 0,
+                info,
+            )
+        },
+        |line| {
+            dbghelp.SymGetLineFromInlineContextW()(
+                GetCurrentProcess(),
+                super::adjust_ip(frame.AddrPC.Offset as *mut _) as u64,
+                frame.InlineFrameContext,
+                0,
+                &mut 0,
+                line,
+            )
+        },
+        cb,
+    )
+}
+
+unsafe fn resolve_without_inline(
+    dbghelp: &dbghelp::Init,
+    addr: *mut c_void,
+    cb: &mut FnMut(&super::Symbol),
+) {
+    do_resolve(
+        |info| dbghelp.SymFromAddrW()(GetCurrentProcess(), addr as DWORD64, &mut 0, info),
+        |line| dbghelp.SymGetLineFromAddrW64()(GetCurrentProcess(), addr as DWORD64, &mut 0, line),
+        cb,
+    )
+}
+
+unsafe fn do_resolve(
+    sym_from_addr: impl FnOnce(*mut SYMBOL_INFOW) -> BOOL,
+    get_line_from_addr: impl FnOnce(&mut IMAGEHLP_LINEW64) -> BOOL,
+    cb: &mut FnMut(&super::Symbol),
+) {
     const SIZE: usize = 2 * MAX_SYM_NAME + mem::size_of::<SYMBOL_INFOW>();
     let mut data = Aligned8([0u8; SIZE]);
     let data = &mut data.0;
@@ -86,22 +153,14 @@
     // due to struct alignment.
     info.SizeOfStruct = 88;
 
-    let _c = ::dbghelp_init();
-
-    let mut displacement = 0u64;
-    let ret = dbghelp::SymFromAddrW(processthreadsapi::GetCurrentProcess(),
-                                    addr as DWORD64,
-                                    &mut displacement,
-                                    info);
-    if ret != TRUE {
-        return
+    if sym_from_addr(info) != TRUE {
+        return;
     }
 
     // If the symbol name is greater than MaxNameLen, SymFromAddrW will
     // give a buffer of (MaxNameLen - 1) characters and set NameLen to
     // the real value.
-    let name_len = ::core::cmp::min(info.NameLen as usize,
-                                    info.MaxNameLen as usize - 1);
+    let name_len = ::core::cmp::min(info.NameLen as usize, info.MaxNameLen as usize - 1);
     let name_ptr = info.Name.as_ptr() as *const u16;
     let name = slice::from_raw_parts(name_ptr, name_len);
 
@@ -120,7 +179,7 @@
                 remaining = &mut tmp[len..];
                 name_len += len;
             } else {
-                break
+                break;
             }
         }
     }
@@ -128,15 +187,10 @@
 
     let mut line = mem::zeroed::<IMAGEHLP_LINEW64>();
     line.SizeOfStruct = mem::size_of::<IMAGEHLP_LINEW64>() as DWORD;
-    let mut displacement = 0;
-    let ret = dbghelp::SymGetLineFromAddrW64(processthreadsapi::GetCurrentProcess(),
-                                             addr as DWORD64,
-                                             &mut displacement,
-                                             &mut line);
 
     let mut filename = None;
     let mut lineno = None;
-    if ret == TRUE {
+    if get_line_from_addr(&mut line) == TRUE {
         lineno = Some(line.LineNumber as u32);
 
         let base = line.FileName;
@@ -150,7 +204,6 @@
         filename = Some(slice::from_raw_parts(base, len) as *const [u16]);
     }
 
-
     cb(&super::Symbol {
         inner: Symbol {
             name,
@@ -158,6 +211,7 @@
             line: lineno,
             filename,
             _filename_cache: cache(filename),
+            _marker: marker::PhantomData,
         },
     })
 }
@@ -165,11 +219,8 @@
 #[cfg(feature = "std")]
 unsafe fn cache(filename: Option<*const [u16]>) -> Option<::std::ffi::OsString> {
     use std::os::windows::ffi::OsStringExt;
-    filename.map(|f| {
-        ::std::ffi::OsString::from_wide(&*f)
-    })
+    filename.map(|f| ::std::ffi::OsString::from_wide(&*f))
 }
 
 #[cfg(not(feature = "std"))]
-unsafe fn cache(_filename: Option<*const [u16]>) {
-}
+unsafe fn cache(_filename: Option<*const [u16]>) {}
diff --git a/third_party/rust_crates/vendor/backtrace/src/symbolize/dladdr.rs b/third_party/rust_crates/vendor/backtrace/src/symbolize/dladdr.rs
index 470b8fb..9509e99 100644
--- a/third_party/rust_crates/vendor/backtrace/src/symbolize/dladdr.rs
+++ b/third_party/rust_crates/vendor/backtrace/src/symbolize/dladdr.rs
@@ -8,50 +8,105 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use core::{mem, slice};
+//! Common support for resolving with `dladdr`, often used as a fallback if
+//! other strategies don't work.
 
-use types::{BytesOrWideString, c_void};
-use libc::{self, Dl_info};
+#![allow(dead_code)]
 
-use SymbolName;
+cfg_if::cfg_if! {
+    if #[cfg(all(unix, not(target_os = "emscripten"), feature = "dladdr"))] {
+        use core::ffi::c_void;
+        use core::marker;
+        use core::{mem, slice};
+        use crate::SymbolName;
+        use crate::types::BytesOrWideString;
+        use libc::{self, Dl_info};
 
-pub struct Symbol {
-    inner: Dl_info,
-}
+        pub struct Symbol<'a> {
+            inner: Dl_info,
+            _marker: marker::PhantomData<&'a i32>,
+        }
 
-impl Symbol {
-    pub fn name(&self) -> Option<SymbolName> {
-        if self.inner.dli_sname.is_null() {
-            None
-        } else {
-            let ptr = self.inner.dli_sname as *const u8;
-            unsafe {
-                let len = libc::strlen(self.inner.dli_sname);
-                Some(SymbolName::new(slice::from_raw_parts(ptr, len)))
+        impl Symbol<'_> {
+            pub fn name(&self) -> Option<SymbolName> {
+                if self.inner.dli_sname.is_null() {
+                    None
+                } else {
+                    let ptr = self.inner.dli_sname as *const u8;
+                    unsafe {
+                        let len = libc::strlen(self.inner.dli_sname);
+                        Some(SymbolName::new(slice::from_raw_parts(ptr, len)))
+                    }
+                }
+            }
+
+            pub fn addr(&self) -> Option<*mut c_void> {
+                Some(self.inner.dli_saddr as *mut _)
+            }
+
+            pub fn filename_raw(&self) -> Option<BytesOrWideString> {
+                None
+            }
+
+            #[cfg(feature = "std")]
+            pub fn filename(&self) -> Option<&::std::path::Path> {
+                None
+            }
+
+            pub fn lineno(&self) -> Option<u32> {
+                None
             }
         }
-    }
 
-    pub fn addr(&self) -> Option<*mut c_void> {
-        Some(self.inner.dli_saddr as *mut _)
-    }
+        pub unsafe fn resolve(addr: *mut c_void, cb: &mut FnMut(Symbol<'static>)) {
+            let mut info = Symbol {
+                inner: mem::zeroed(),
+                _marker: marker::PhantomData,
+            };
+            // Skip null addresses to avoid calling into libc and having it do
+            // things with the dynamic symbol table for no reason.
+            if !addr.is_null() && libc::dladdr(addr as *mut _, &mut info.inner) != 0 {
+                cb(info)
+            }
+        }
+    } else {
+        use core::ffi::c_void;
+        use core::marker;
+        use crate::symbolize::SymbolName;
+        use crate::types::BytesOrWideString;
 
-    pub fn filename_raw(&self) -> Option<BytesOrWideString> {
-        None
-    }
+        pub struct Symbol<'a> {
+            a: Void,
+            _b: marker::PhantomData<&'a i32>,
+        }
 
-    pub fn lineno(&self) -> Option<u32> {
-        None
-    }
-}
+        enum Void {}
 
-pub unsafe fn resolve(addr: *mut c_void, cb: &mut FnMut(&super::Symbol)) {
-    let mut info: super::Symbol = super::Symbol {
-        inner: Symbol {
-            inner: mem::zeroed(),
-        },
-    };
-    if libc::dladdr(addr as *mut _, &mut info.inner.inner) != 0 {
-        cb(&info)
+        impl Symbol<'_> {
+            pub fn name(&self) -> Option<SymbolName> {
+                match self.a {}
+            }
+
+            pub fn addr(&self) -> Option<*mut c_void> {
+                match self.a {}
+            }
+
+            pub fn filename_raw(&self) -> Option<BytesOrWideString> {
+                match self.a {}
+            }
+
+            #[cfg(feature = "std")]
+            pub fn filename(&self) -> Option<&::std::path::Path> {
+                match self.a {}
+            }
+
+            pub fn lineno(&self) -> Option<u32> {
+                match self.a {}
+            }
+        }
+
+        pub unsafe fn resolve(addr: *mut c_void, cb: &mut FnMut(Symbol<'static>)) {
+            drop((addr, cb));
+        }
     }
 }
diff --git a/third_party/rust_crates/vendor/backtrace/src/symbolize/dladdr_resolve.rs b/third_party/rust_crates/vendor/backtrace/src/symbolize/dladdr_resolve.rs
new file mode 100644
index 0000000..7790703f
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace/src/symbolize/dladdr_resolve.rs
@@ -0,0 +1,50 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Symbolication strategy using `dladdr`
+//!
+//! The `dladdr` API is available on most Unix implementations but it's quite
+//! basic, not handling inline frame information at all. Since it's so prevalent
+//! though we have an option to use it!
+
+use crate::symbolize::{dladdr, ResolveWhat, SymbolName};
+use crate::types::BytesOrWideString;
+use core::ffi::c_void;
+
+pub struct Symbol<'a>(dladdr::Symbol<'a>);
+
+impl Symbol<'_> {
+    pub fn name(&self) -> Option<SymbolName> {
+        self.0.name()
+    }
+
+    pub fn addr(&self) -> Option<*mut c_void> {
+        self.0.addr()
+    }
+
+    pub fn filename_raw(&self) -> Option<BytesOrWideString> {
+        self.0.filename_raw()
+    }
+
+    #[cfg(feature = "std")]
+    pub fn filename(&self) -> Option<&::std::path::Path> {
+        self.0.filename()
+    }
+
+    pub fn lineno(&self) -> Option<u32> {
+        self.0.lineno()
+    }
+}
+
+pub unsafe fn resolve(what: ResolveWhat, cb: &mut FnMut(&super::Symbol)) {
+    dladdr::resolve(what.address_or_ip(), &mut |sym| {
+        cb(&super::Symbol { inner: Symbol(sym) })
+    });
+}
diff --git a/third_party/rust_crates/vendor/backtrace/src/symbolize/gimli.rs b/third_party/rust_crates/vendor/backtrace/src/symbolize/gimli.rs
index 464bd99..1529a90 100644
--- a/third_party/rust_crates/vendor/backtrace/src/symbolize/gimli.rs
+++ b/third_party/rust_crates/vendor/backtrace/src/symbolize/gimli.rs
@@ -1,83 +1,488 @@
-use addr2line;
-use findshlibs::{self, Segment, SharedLibrary};
-use gimli;
-use memmap::Mmap;
-use object::{self, Object};
-use std::cell::RefCell;
-use std::env;
-use std::fs::File;
-use std::mem;
-use libc::c_void;
-use std::path::PathBuf;
-use std::u32;
-use std::prelude::v1::*;
+//! Support for symbolication using the `gimli` crate on crates.io
+//!
+//! This implementation is largely a work in progress and is off by default for
+//! all platforms, but it's hoped to be developed over time! Long-term this is
+//! intended to wholesale replace the `libbacktrace.rs` implementation.
 
-use SymbolName;
-use types::BytesOrWideString;
+use self::gimli::read::EndianSlice;
+use self::gimli::LittleEndian as Endian;
+use crate::symbolize::dladdr;
+use crate::symbolize::ResolveWhat;
+use crate::types::BytesOrWideString;
+use crate::SymbolName;
+use addr2line::gimli;
+use core::mem;
+use core::u32;
+use findshlibs::{self, Segment, SharedLibrary};
+use libc::c_void;
+use memmap::Mmap;
+use std::env;
+use std::ffi::OsString;
+use std::fs::File;
+use std::path::Path;
+use std::prelude::v1::*;
 
 const MAPPINGS_CACHE_SIZE: usize = 4;
 
-type Dwarf = addr2line::Context<gimli::EndianRcSlice<gimli::RunTimeEndian>>;
-type Symbols<'map> = object::SymbolMap<'map>;
+struct Context<'a> {
+    dwarf: addr2line::Context<EndianSlice<'a, Endian>>,
+    object: Object<'a>,
+}
 
 struct Mapping {
-    dwarf: Dwarf,
     // 'static lifetime is a lie to hack around lack of support for self-referential structs.
-    symbols: Symbols<'static>,
+    cx: Context<'static>,
     _map: Mmap,
 }
 
-impl Mapping {
-    fn new(path: &PathBuf) -> Option<Mapping> {
-        let file = File::open(path).ok()?;
-        // TODO: not completely safe, see https://github.com/danburkert/memmap-rs/issues/25
-        let map = unsafe { Mmap::map(&file).ok()? };
-        let (dwarf, symbols) = {
-            let object = object::File::parse(&*map).ok()?;
-            let dwarf = addr2line::Context::new(&object).ok()?;
-            let symbols = object.symbol_map();
-            // Convert to 'static lifetimes.
-            (dwarf, unsafe { mem::transmute(symbols) })
-        };
-        Some(Mapping {
-            dwarf,
-            symbols,
-            _map: map,
-        })
-    }
-
-    // Ensure the 'static lifetimes don't leak.
-    fn rent<F>(&self, mut f: F)
+fn cx<'data>(object: Object<'data>) -> Option<Context<'data>> {
+    fn load_section<'data, S>(obj: &Object<'data>) -> S
     where
-        F: FnMut(&Dwarf, &Symbols),
+        S: gimli::Section<gimli::EndianSlice<'data, Endian>>,
     {
-        f(&self.dwarf, &self.symbols)
+        let data = obj.section(S::section_name()).unwrap_or(&[]);
+        S::from(EndianSlice::new(data, Endian))
+    }
+
+    let dwarf = addr2line::Context::from_sections(
+        load_section(&object),
+        load_section(&object),
+        load_section(&object),
+        load_section(&object),
+        load_section(&object),
+        load_section(&object),
+        load_section(&object),
+        load_section(&object),
+        load_section(&object),
+        gimli::EndianSlice::new(&[], Endian),
+    )
+    .ok()?;
+    Some(Context { dwarf, object })
+}
+
+fn assert_lifetimes<'a>(_: &'a Mmap, _: &Context<'a>) {}
+
+macro_rules! mk {
+    (Mapping { $map:expr, $inner:expr }) => {{
+        assert_lifetimes(&$map, &$inner);
+        Mapping {
+            // Convert to 'static lifetimes since the symbols should
+            // only borrow `map` and we're preserving `map` below.
+            cx: unsafe { mem::transmute::<Context<'_>, Context<'static>>($inner) },
+            _map: $map,
+        }
+    }};
+}
+
+fn mmap(path: &Path) -> Option<Mmap> {
+    let file = File::open(path).ok()?;
+    // TODO: not completely safe, see https://github.com/danburkert/memmap-rs/issues/25
+    unsafe { Mmap::map(&file).ok() }
+}
+
+cfg_if::cfg_if! {
+    if #[cfg(windows)] {
+        use goblin::pe::{self, PE};
+        use goblin::strtab::Strtab;
+        use std::cmp;
+        use std::convert::TryFrom;
+
+        struct Object<'a> {
+            pe: PE<'a>,
+            data: &'a [u8],
+            symbols: Vec<(usize, pe::symbol::Symbol)>,
+            strtab: Strtab<'a>,
+        }
+
+        impl<'a> Object<'a> {
+            fn parse(data: &'a [u8]) -> Option<Object<'a>> {
+                let pe = PE::parse(data).ok()?;
+                let syms = pe.header.coff_header.symbols(data).ok()?;
+                let strtab = pe.header.coff_header.strings(data).ok()?;
+
+                // Collect all the symbols into a local vector which is sorted
+                // by address and contains enough data to learn about the symbol
+                // name. Note that we only look at function symbols and also
+                // note that the sections are 1-indexed because the zero section
+                // is special (apparently).
+                let mut symbols = Vec::new();
+                for (_, _, sym) in syms.iter() {
+                    if sym.derived_type() != pe::symbol::IMAGE_SYM_DTYPE_FUNCTION
+                        || sym.section_number == 0
+                    {
+                        continue;
+                    }
+                    let addr = usize::try_from(sym.value).ok()?;
+                    let section = pe.sections.get(usize::try_from(sym.section_number).ok()? - 1)?;
+                    let va = usize::try_from(section.virtual_address).ok()?;
+                    symbols.push((addr + va + pe.image_base, sym));
+                }
+                symbols.sort_unstable_by_key(|x| x.0);
+                Some(Object { pe, data, symbols, strtab })
+            }
+
+            fn section(&self, name: &str) -> Option<&'a [u8]> {
+                let section = self.pe
+                    .sections
+                    .iter()
+                    .find(|section| section.name().ok() == Some(name));
+                section
+                    .and_then(|section| {
+                        let offset = section.pointer_to_raw_data as usize;
+                        let size = cmp::min(section.virtual_size, section.size_of_raw_data) as usize;
+                        self.data.get(offset..).and_then(|data| data.get(..size))
+                    })
+            }
+
+            fn search_symtab<'b>(&'b self, addr: u64) -> Option<&'b [u8]> {
+                // Note that unlike other formats COFF doesn't embed the size of
+                // each symbol. As a last ditch effort search for the *closest*
+                // symbol to a particular address and return that one. This gets
+                // really wonky once symbols start getting removed because the
+                // symbols returned here can be totally incorrect, but we have
+                // no idea of knowing how to detect that.
+                let addr = usize::try_from(addr).ok()?;
+                let i = match self.symbols.binary_search_by_key(&addr, |p| p.0) {
+                    Ok(i) => i,
+                    // typically `addr` isn't in the array, but `i` is where
+                    // we'd insert it, so the previous position must be the
+                    // greatest less than `addr`
+                    Err(i) => i.checked_sub(1)?,
+                };
+                Some(self.symbols[i].1.name(&self.strtab).ok()?.as_bytes())
+            }
+        }
+    } else if #[cfg(target_os = "macos")] {
+        use goblin::mach::MachO;
+
+        struct Object<'a> {
+            macho: MachO<'a>,
+            dwarf: Option<usize>,
+        }
+
+        impl<'a> Object<'a> {
+            fn parse(macho: MachO<'a>) -> Option<Object<'a>> {
+                if !macho.little_endian {
+                    return None;
+                }
+                let dwarf = macho
+                    .segments
+                    .iter()
+                    .enumerate()
+                    .find(|(_, segment)| segment.name().ok() == Some("__DWARF"))
+                    .map(|p| p.0);
+                Some(Object { macho, dwarf })
+            }
+
+            fn section(&self, name: &str) -> Option<&'a [u8]> {
+                let dwarf = self.dwarf?;
+                let dwarf = &self.macho.segments[dwarf];
+                dwarf
+                    .into_iter()
+                    .filter_map(|s| s.ok())
+                    .find(|(section, _data)| {
+                        let section_name = match section.name() {
+                            Ok(s) => s,
+                            Err(_) => return false,
+                        };
+                        &section_name[..] == name || {
+                            section_name.starts_with("__")
+                                && name.starts_with(".")
+                                && &section_name[2..] == &name[1..]
+                        }
+                    })
+                    .map(|p| p.1)
+            }
+
+            fn search_symtab<'b>(&'b self, _addr: u64) -> Option<&'b [u8]> {
+                // So far it seems that we don't need to implement this. Maybe
+                // `dladdr` on OSX has us covered? Maybe there's not much in the
+                // symbol table? In any case our relevant tests are passing
+                // without this being implemented, so let's skip it for now.
+                None
+            }
+        }
+    } else {
+        use goblin::elf::Elf;
+
+        struct Object<'a> {
+            elf: Elf<'a>,
+            data: &'a [u8],
+            // List of pre-parsed and sorted symbols by base address. The
+            // boolean indicates whether it comes from the dynamic symbol table
+            // or the normal symbol table, affecting where it's symbolicated.
+            syms: Vec<(goblin::elf::Sym, bool)>,
+        }
+
+        impl<'a> Object<'a> {
+            fn parse(data: &'a [u8]) -> Option<Object<'a>> {
+                let elf = Elf::parse(data).ok()?;
+                if !elf.little_endian {
+                    return None;
+                }
+                let mut syms = elf
+                    .syms
+                    .iter()
+                    .map(|s| (s, false))
+                    .chain(elf.dynsyms.iter().map(|s| (s, true)))
+                    // Only look at function/object symbols. This mirrors what
+                    // libbacktrace does and in general we're only symbolicating
+                    // function addresses in theory. Object symbols correspond
+                    // to data, and maybe someone's crazy enough to have a
+                    // function go into static data?
+                    .filter(|(s, _)| {
+                        s.is_function() || s.st_type() == goblin::elf::sym::STT_OBJECT
+                    })
+                    // skip anything that's in an undefined section header,
+                    // since it means it's an imported function and we're only
+                    // symbolicating with locally defined functions.
+                    .filter(|(s, _)| {
+                        s.st_shndx != goblin::elf::section_header::SHN_UNDEF as usize
+                    })
+                    .collect::<Vec<_>>();
+                syms.sort_unstable_by_key(|s| s.0.st_value);
+                Some(Object {
+                    syms,
+                    elf,
+                    data,
+                })
+            }
+
+            fn section(&self, name: &str) -> Option<&'a [u8]> {
+                let section = self.elf.section_headers.iter().find(|section| {
+                    match self.elf.shdr_strtab.get(section.sh_name) {
+                        Some(Ok(section_name)) => section_name == name,
+                        _ => false,
+                    }
+                });
+                section
+                    .and_then(|section| {
+                        self.data.get(section.sh_offset as usize..)
+                            .and_then(|data| data.get(..section.sh_size as usize))
+                    })
+            }
+
+            fn search_symtab<'b>(&'b self, addr: u64) -> Option<&'b [u8]> {
+                // Same sort of binary search as Windows above
+                let i = match self.syms.binary_search_by_key(&addr, |s| s.0.st_value) {
+                    Ok(i) => i,
+                    Err(i) => i.checked_sub(1)?,
+                };
+                let (sym, dynamic) = self.syms.get(i)?;
+                if sym.st_value <= addr && addr <= sym.st_value + sym.st_size {
+                    let strtab = if *dynamic {
+                        &self.elf.dynstrtab
+                    } else {
+                        &self.elf.strtab
+                    };
+                    Some(strtab.get(sym.st_name)?.ok()?.as_bytes())
+                } else {
+                    None
+                }
+            }
+        }
     }
 }
 
-thread_local! {
-    // A very small, very simple LRU cache for debug info mappings.
-    //
-    // The hit rate should be very high, since the typical stack doesn't cross
-    // between many shared libraries.
-    //
-    // The `addr2line::Context` structures are pretty expensive to create. Its
-    // cost is expected to be amortized by subsequent `locate` queries, which
-    // leverage the structures built when constructing `addr2line::Context`s to
-    // get nice speedups. If we didn't have this cache, that amortization would
-    // never happen, and symbolicating backtraces would be ssssllllooooowwww.
-    static MAPPINGS_CACHE: RefCell<Vec<(PathBuf, Mapping)>>
-        = RefCell::new(Vec::with_capacity(MAPPINGS_CACHE_SIZE));
+impl Mapping {
+    #[cfg(not(target_os = "macos"))]
+    fn new(path: &Path) -> Option<Mapping> {
+        let map = mmap(path)?;
+        let cx = cx(Object::parse(&map)?)?;
+        Some(mk!(Mapping { map, cx }))
+    }
+
+    // The loading path for OSX is is so different we just have a completely
+    // different implementation of the function here. On OSX we need to go
+    // probing the filesystem for a bunch of files.
+    #[cfg(target_os = "macos")]
+    fn new(path: &Path) -> Option<Mapping> {
+        // First up we need to load the unique UUID which is stored in the macho
+        // header of the file we're reading, specified at `path`.
+        let map = mmap(path)?;
+        let macho = MachO::parse(&map, 0).ok()?;
+        let uuid = find_uuid(&macho)?;
+
+        // Next we need to look for a `*.dSYM` file. For now we just probe the
+        // containing directory and look around for something that matches
+        // `*.dSYM`. Once it's found we root through the dwarf resources that it
+        // contains and try to find a macho file which has a matching UUID as
+        // the one of our own file. If we find a match that's the dwarf file we
+        // want to return.
+        let parent = path.parent()?;
+        for entry in parent.read_dir().ok()? {
+            let entry = entry.ok()?;
+            let filename = match entry.file_name().into_string() {
+                Ok(name) => name,
+                Err(_) => continue,
+            };
+            if !filename.ends_with(".dSYM") {
+                continue;
+            }
+            let candidates = entry.path().join("Contents/Resources/DWARF");
+            if let Some(mapping) = load_dsym(&candidates, &uuid) {
+                return Some(mapping);
+            }
+        }
+
+        // Looks like nothing matched our UUID, so let's at least return our own
+        // file. This should have the symbol table for at least some
+        // symbolication purposes.
+        let inner = cx(Object::parse(macho)?)?;
+        return Some(mk!(Mapping { map, inner }));
+
+        fn load_dsym(dir: &Path, uuid: &[u8; 16]) -> Option<Mapping> {
+            for entry in dir.read_dir().ok()? {
+                let entry = entry.ok()?;
+                let map = mmap(&entry.path())?;
+                let macho = MachO::parse(&map, 0).ok()?;
+                let entry_uuid = find_uuid(&macho)?;
+                if entry_uuid != uuid {
+                    continue;
+                }
+                if let Some(cx) = Object::parse(macho).and_then(cx) {
+                    return Some(mk!(Mapping { map, cx }));
+                }
+            }
+
+            None
+        }
+
+        fn find_uuid<'a>(object: &'a MachO) -> Option<&'a [u8; 16]> {
+            use goblin::mach::load_command::CommandVariant;
+
+            object
+                .load_commands
+                .iter()
+                .filter_map(|cmd| match &cmd.command {
+                    CommandVariant::Uuid(u) => Some(&u.uuid),
+                    _ => None,
+                })
+                .next()
+        }
+    }
 }
 
-fn with_mapping_for_path<F>(path: PathBuf, f: F)
-where
-    F: FnMut(&Dwarf, &Symbols),
-{
-    MAPPINGS_CACHE.with(|cache| {
-        let mut cache = cache.borrow_mut();
+#[derive(Default)]
+struct Cache {
+    /// All known shared libraries that have been loaded.
+    libraries: Vec<Library>,
 
-        let idx = cache.iter().position(|&(ref p, _)| p == &path);
+    /// Mappings cache where we retain parsed dwarf information.
+    ///
+    /// This list has a fixed capacity for its entire liftime which never
+    /// increases. The `usize` element of each pair is an index into `libraries`
+    /// above where `usize::max_value()` represents the current executable. The
+    /// `Mapping` is corresponding parsed dwarf information.
+    ///
+    /// Note that this is basically an LRU cache and we'll be shifting things
+    /// around in here as we symbolize addresses.
+    mappings: Vec<(usize, Mapping)>,
+}
+
+struct Library {
+    name: OsString,
+    segments: Vec<LibrarySegment>,
+    bias: findshlibs::Bias,
+}
+
+struct LibrarySegment {
+    len: usize,
+    stated_virtual_memory_address: findshlibs::Svma,
+}
+
+// unsafe because this is required to be externally synchronized
+pub unsafe fn clear_symbol_cache() {
+    Cache::with_global(|cache| cache.mappings.clear());
+}
+
+impl Cache {
+    fn new() -> Cache {
+        let mut libraries = Vec::new();
+        // Iterate over all loaded shared libraries and cache information we
+        // learn about them. This way we only load information here once instead
+        // of once per symbol.
+        findshlibs::TargetSharedLibrary::each(|so| {
+            use findshlibs::IterationControl::*;
+            libraries.push(Library {
+                name: so.name().to_owned(),
+                segments: so
+                    .segments()
+                    .map(|s| LibrarySegment {
+                        len: s.len(),
+                        stated_virtual_memory_address: s.stated_virtual_memory_address(),
+                    })
+                    .collect(),
+                bias: so.virtual_memory_bias(),
+            });
+            Continue
+        });
+
+        Cache {
+            mappings: Vec::with_capacity(MAPPINGS_CACHE_SIZE),
+            libraries,
+        }
+    }
+
+    // unsafe because this is required to be externally synchronized
+    unsafe fn with_global(f: impl FnOnce(&mut Self)) {
+        // A very small, very simple LRU cache for debug info mappings.
+        //
+        // The hit rate should be very high, since the typical stack doesn't cross
+        // between many shared libraries.
+        //
+        // The `addr2line::Context` structures are pretty expensive to create. Its
+        // cost is expected to be amortized by subsequent `locate` queries, which
+        // leverage the structures built when constructing `addr2line::Context`s to
+        // get nice speedups. If we didn't have this cache, that amortization would
+        // never happen, and symbolicating backtraces would be ssssllllooooowwww.
+        static mut MAPPINGS_CACHE: Option<Cache> = None;
+
+        f(MAPPINGS_CACHE.get_or_insert_with(|| Cache::new()))
+    }
+
+    fn avma_to_svma(&self, addr: *const u8) -> Option<(usize, findshlibs::Svma)> {
+        // Note that for now `findshlibs` is unimplemented on Windows, so we
+        // just unhelpfully assume that the address is an SVMA. Surprisingly it
+        // seems to at least somewhat work on Wine on Linux though...
+        //
+        // This probably means ASLR on Windows is busted.
+        if cfg!(windows) {
+            let addr = findshlibs::Svma(addr);
+            return Some((usize::max_value(), addr));
+        }
+
+        self.libraries
+            .iter()
+            .enumerate()
+            .filter_map(|(i, lib)| {
+                // First up, test if this `lib` has any segment containing the
+                // `addr` (handling relocation). If this check passes then we
+                // can continue below and actually translate the address.
+                //
+                // Note that this is an inlining of `contains_avma` in the
+                // `findshlibs` crate here.
+                if !lib.segments.iter().any(|s| {
+                    let svma = s.stated_virtual_memory_address;
+                    let start = unsafe { svma.0.offset(lib.bias.0) as usize };
+                    let end = start + s.len;
+                    let address = addr as usize;
+                    start <= address && address < end
+                }) {
+                    return None;
+                }
+
+                // Now that we know `lib` contains `addr`, do the equiavlent of
+                // `avma_to_svma` in the `findshlibs` crate.
+                let reverse_bias = -lib.bias.0;
+                let svma = findshlibs::Svma(unsafe { addr.offset(reverse_bias) });
+                Some((i, svma))
+            })
+            .next()
+    }
+
+    fn mapping_for_lib<'a>(&'a mut self, lib: usize) -> Option<&'a Context<'a>> {
+        let idx = self.mappings.iter().position(|(idx, _)| *idx == lib);
 
         // Invariant: after this conditional completes without early returning
         // from an error, the cache entry for this path is at index 0.
@@ -85,142 +490,176 @@
         if let Some(idx) = idx {
             // When the mapping is already in the cache, move it to the front.
             if idx != 0 {
-                let entry = cache.remove(idx);
-                cache.insert(0, entry);
+                let entry = self.mappings.remove(idx);
+                self.mappings.insert(0, entry);
             }
         } else {
             // When the mapping is not in the cache, create a new mapping,
             // insert it into the front of the cache, and evict the oldest cache
             // entry if necessary.
-            let mapping = match Mapping::new(&path) {
-                None => return,
-                Some(m) => m,
+            let storage;
+            let path = match self.libraries.get(lib) {
+                Some(lib) => &lib.name,
+                None => {
+                    storage = env::current_exe().ok()?.into();
+                    &storage
+                }
             };
+            let mapping = Mapping::new(path.as_ref())?;
 
-            if cache.len() == MAPPINGS_CACHE_SIZE {
-                cache.pop();
+            if self.mappings.len() == MAPPINGS_CACHE_SIZE {
+                self.mappings.pop();
             }
 
-            cache.insert(0, (path, mapping));
+            self.mappings.insert(0, (lib, mapping));
         }
 
-        cache[0].1.rent(f);
-    });
+        let cx: &'a Context<'static> = &self.mappings[0].1.cx;
+        // don't leak the `'static` lifetime, make sure it's scoped to just
+        // ourselves
+        Some(unsafe { mem::transmute::<&'a Context<'static>, &'a Context<'a>>(cx) })
+    }
 }
 
-pub fn resolve(addr: *mut c_void, cb: &mut FnMut(&super::Symbol)) {
-    // First, find the file containing the segment that the given AVMA (after
-    // relocation) address falls within. Use the containing segment to compute
-    // the SVMA (before relocation) address.
-    //
-    // Note that the OS APIs that `SharedLibrary::each` is implemented with hold
-    // a lock for the duration of the `each` call, so we want to keep this
-    // section as short as possible to avoid contention with other threads
-    // capturing backtraces.
-    let addr = findshlibs::Avma(addr as *mut u8 as *const u8);
-    let mut so_info = None;
-    findshlibs::TargetSharedLibrary::each(|so| {
-        use findshlibs::IterationControl::*;
-
-        for segment in so.segments() {
-            if segment.contains_avma(so, addr) {
-                let addr = so.avma_to_svma(addr);
-                let path = so.name().to_string_lossy();
-                so_info = Some((addr, path.to_string()));
-                return Break;
-            }
-        }
-
-        Continue
-    });
-    let (addr, path) = match so_info {
-        None => return,
-        Some((a, p)) => (a, p),
+pub unsafe fn resolve(what: ResolveWhat, cb: &mut FnMut(&super::Symbol)) {
+    let addr = what.address_or_ip();
+    let mut cb = DladdrFallback {
+        cb,
+        addr,
+        called: false,
     };
 
-    // Second, fixup the path. Empty path means that this address falls within
-    // the main executable, not a shared library.
-    let path = if path.is_empty() {
-        match env::current_exe() {
-            Err(_) => return,
-            Ok(p) => p,
-        }
-    } else {
-        PathBuf::from(path)
-    };
+    Cache::with_global(|cache| {
+        let (lib, addr) = match cache.avma_to_svma(addr as *const u8) {
+            Some(pair) => pair,
+            None => return,
+        };
 
-    // Finally, get a cached mapping or create a new mapping for this file, and
-    // evaluate the DWARF info to find the file/line/name for this address.
-    with_mapping_for_path(path, |dwarf, symbols| {
-        let mut found_sym = false;
-        if let Ok(mut frames) = dwarf.find_frames(addr.0 as u64) {
+        // Finally, get a cached mapping or create a new mapping for this file, and
+        // evaluate the DWARF info to find the file/line/name for this address.
+        let cx = match cache.mapping_for_lib(lib) {
+            Some(cx) => cx,
+            None => return,
+        };
+        if let Ok(mut frames) = cx.dwarf.find_frames(addr.0 as u64) {
             while let Ok(Some(frame)) = frames.next() {
-                let (file, line) = frame
-                    .location
-                    .map(|l| (l.file, l.line))
-                    .unwrap_or((None, None));
-                let name = frame
-                    .function
-                    .and_then(|f| f.raw_name().ok().map(|f| f.to_string()));
-                let sym = super::Symbol {
-                    inner: Symbol::new(addr.0 as usize, file, line, name),
-                };
-                cb(&sym);
-                found_sym = true;
+                cb.call(Symbol::Frame {
+                    addr: addr.0 as *mut c_void,
+                    location: frame.location,
+                    name: frame.function.map(|f| f.name.slice()),
+                });
             }
         }
 
-        // No DWARF info found, so fallback to the symbol table.
-        if !found_sym {
-            if let Some(name) = symbols.get(addr.0 as u64).and_then(|x| x.name()) {
-                let sym = super::Symbol {
-                    inner: Symbol::new(addr.0 as usize, None, None, Some(name.to_string())),
-                };
-                cb(&sym);
+        if !cb.called {
+            if let Some(name) = cx.object.search_symtab(addr.0 as u64) {
+                cb.call(Symbol::Symtab {
+                    addr: addr.0 as *mut c_void,
+                    name,
+                });
             }
         }
     });
+
+    drop(cb);
 }
 
-pub struct Symbol {
-    addr: usize,
-    file: Option<String>,
-    line: Option<u64>,
-    name: Option<String>,
+struct DladdrFallback<'a, 'b> {
+    addr: *mut c_void,
+    called: bool,
+    cb: &'a mut (FnMut(&super::Symbol) + 'b),
 }
 
-impl Symbol {
-    fn new(addr: usize,
-           file: Option<String>,
-           line: Option<u64>,
-           name: Option<String>)
-           -> Symbol {
-        Symbol {
-            addr,
-            file,
-            line,
-            name,
+impl DladdrFallback<'_, '_> {
+    fn call(&mut self, sym: Symbol) {
+        self.called = true;
+
+        // Extend the lifetime of `sym` to `'static` since we are unfortunately
+        // required to here, but it's ony ever going out as a reference so no
+        // reference to it should be persisted beyond this frame anyway.
+        let sym = unsafe { mem::transmute::<Symbol, Symbol<'static>>(sym) };
+        (self.cb)(&super::Symbol { inner: sym });
+    }
+}
+
+impl Drop for DladdrFallback<'_, '_> {
+    fn drop(&mut self) {
+        if self.called {
+            return;
+        }
+        unsafe {
+            dladdr::resolve(self.addr, &mut |sym| {
+                (self.cb)(&super::Symbol {
+                    inner: Symbol::Dladdr(sym),
+                })
+            });
         }
     }
+}
 
+pub enum Symbol<'a> {
+    /// We were able to locate frame information for this symbol, and
+    /// `addr2line`'s frame internally has all the nitty gritty details.
+    Frame {
+        addr: *mut c_void,
+        location: Option<addr2line::Location<'a>>,
+        name: Option<&'a [u8]>,
+    },
+    /// Couldn't find debug information, but we found it in the symbol table of
+    /// the elf executable.
+    Symtab { addr: *mut c_void, name: &'a [u8] },
+    /// We weren't able to find anything in the original file, so we had to fall
+    /// back to using `dladdr` which had a hit.
+    Dladdr(dladdr::Symbol<'a>),
+}
+
+impl Symbol<'_> {
     pub fn name(&self) -> Option<SymbolName> {
-        self.name.as_ref().map(|s| SymbolName::new(s.as_bytes()))
+        match self {
+            Symbol::Dladdr(s) => s.name(),
+            Symbol::Frame { name, .. } => {
+                let name = name.as_ref()?;
+                Some(SymbolName::new(name))
+            }
+            Symbol::Symtab { name, .. } => Some(SymbolName::new(name)),
+        }
     }
 
     pub fn addr(&self) -> Option<*mut c_void> {
-        Some(self.addr as *mut c_void)
+        match self {
+            Symbol::Dladdr(s) => s.addr(),
+            Symbol::Frame { addr, .. } => Some(*addr),
+            Symbol::Symtab { .. } => None,
+        }
     }
 
     pub fn filename_raw(&self) -> Option<BytesOrWideString> {
-        self.file.as_ref().map(|f| BytesOrWideString::Bytes(f.as_bytes()))
+        match self {
+            Symbol::Dladdr(s) => return s.filename_raw(),
+            Symbol::Frame { location, .. } => {
+                let file = location.as_ref()?.file?;
+                Some(BytesOrWideString::Bytes(file.as_bytes()))
+            }
+            Symbol::Symtab { .. } => None,
+        }
+    }
+
+    pub fn filename(&self) -> Option<&Path> {
+        match self {
+            Symbol::Dladdr(s) => return s.filename(),
+            Symbol::Frame { location, .. } => {
+                let file = location.as_ref()?.file?;
+                Some(Path::new(file))
+            }
+            Symbol::Symtab { .. } => None,
+        }
     }
 
     pub fn lineno(&self) -> Option<u32> {
-        self.line
-            .and_then(|l| if l > (u32::MAX as u64) {
-                None
-            } else {
-                Some(l as u32)
-            })
+        match self {
+            Symbol::Dladdr(s) => return s.lineno(),
+            Symbol::Frame { location, .. } => location.as_ref()?.line,
+            Symbol::Symtab { .. } => None,
+        }
     }
 }
diff --git a/third_party/rust_crates/vendor/backtrace/src/symbolize/libbacktrace.rs b/third_party/rust_crates/vendor/backtrace/src/symbolize/libbacktrace.rs
index 395395f..4318789 100644
--- a/third_party/rust_crates/vendor/backtrace/src/symbolize/libbacktrace.rs
+++ b/third_party/rust_crates/vendor/backtrace/src/symbolize/libbacktrace.rs
@@ -8,21 +8,41 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+//! Symbolication strategy using the DWARF-parsing code in libbacktrace.
+//!
+//! The libbacktrace C library, typically distributed with gcc, supports not
+//! only generating a backtrace (which we don't actually use) but also
+//! symbolicating the backtrace and handling dwarf debug information about
+//! things like inlined frames and whatnot.
+//!
+//! This is relatively complicated due to lots of various concerns here, but the
+//! basic idea is:
+//!
+//! * First we call `backtrace_syminfo`. This gets symbol information from the
+//!   dynamic symbol table if we can.
+//! * Next we call `backtrace_pcinfo`. This will parse debuginfo tables if
+//!   they're available and allow us to recover information about inline frames,
+//!   filenames, line numbers, etc.
+//!
+//! There's lots of trickery about getting the dwarf tables into libbacktrace,
+//! but hopefully it's not the end of the world and is clear enough when reading
+//! below.
+//!
+//! This is the default symbolication strategy for non-MSVC and non-OSX
+//! platforms. In libstd though this is the default strategy for OSX.
+
 #![allow(bad_style)]
 
 extern crate backtrace_sys as bt;
 
-use std::ffi::CStr;
-use std::{ptr, slice};
-use std::sync::{ONCE_INIT, Once};
-
+use core::{ptr, slice};
 use libc::{self, c_char, c_int, c_void, uintptr_t};
 
-use SymbolName;
+use crate::symbolize::dladdr;
+use crate::symbolize::{ResolveWhat, SymbolName};
+use crate::types::BytesOrWideString;
 
-use types::BytesOrWideString;
-
-pub enum Symbol {
+pub enum Symbol<'a> {
     Syminfo {
         pc: uintptr_t,
         symname: *const c_char,
@@ -32,19 +52,44 @@
         filename: *const c_char,
         lineno: c_int,
         function: *const c_char,
+        symname: *const c_char,
     },
+    Dladdr(dladdr::Symbol<'a>),
 }
 
-impl Symbol {
+impl Symbol<'_> {
     pub fn name(&self) -> Option<SymbolName> {
-        let ptr = match *self {
-            Symbol::Syminfo { symname, .. } => symname,
-            Symbol::Pcinfo { function, .. } => function,
+        let symbol = |ptr: *const c_char| unsafe {
+            if ptr.is_null() {
+                None
+            } else {
+                let len = libc::strlen(ptr);
+                Some(SymbolName::new(slice::from_raw_parts(
+                    ptr as *const u8,
+                    len,
+                )))
+            }
         };
-        if ptr.is_null() {
-            None
-        } else {
-            Some(SymbolName::new(unsafe { CStr::from_ptr(ptr).to_bytes() }))
+        match *self {
+            Symbol::Syminfo { symname, .. } => symbol(symname),
+            Symbol::Pcinfo {
+                function, symname, ..
+            } => {
+                // If possible prefer the `function` name which comes from
+                // debuginfo and can typically be more accurate for inline
+                // frames for example. If that's not present though fall back to
+                // the symbol table name specified in `symname`.
+                //
+                // Note that sometimes `function` can feel somewhat less
+                // accurate, for example being listed as `try<i32,closure>`
+                // isntead of `std::panicking::try::do_call`. It's not really
+                // clear why, but overall the `function` name seems more accurate.
+                if let Some(sym) = symbol(function) {
+                    return Some(sym);
+                }
+                symbol(symname)
+            }
+            Symbol::Dladdr(ref s) => s.name(),
         }
     }
 
@@ -52,77 +97,150 @@
         let pc = match *self {
             Symbol::Syminfo { pc, .. } => pc,
             Symbol::Pcinfo { pc, .. } => pc,
+            Symbol::Dladdr(ref s) => return s.addr(),
         };
-        if pc == 0 {None} else {Some(pc as *mut _)}
+        if pc == 0 {
+            None
+        } else {
+            Some(pc as *mut _)
+        }
     }
 
-    pub fn filename_raw(&self) -> Option<BytesOrWideString> {
+    fn filename_bytes(&self) -> Option<&[u8]> {
         match *self {
             Symbol::Syminfo { .. } => None,
             Symbol::Pcinfo { filename, .. } => {
                 let ptr = filename as *const u8;
                 unsafe {
                     let len = libc::strlen(filename);
-                    Some(BytesOrWideString::Bytes(slice::from_raw_parts(ptr, len)))
+                    Some(slice::from_raw_parts(ptr, len))
                 }
             }
+            Symbol::Dladdr(_) => None,
         }
     }
 
+    pub fn filename_raw(&self) -> Option<BytesOrWideString> {
+        self.filename_bytes().map(BytesOrWideString::Bytes)
+    }
+
+    #[cfg(feature = "std")]
+    pub fn filename(&self) -> Option<&::std::path::Path> {
+        use std::path::Path;
+
+        #[cfg(unix)]
+        fn bytes2path(bytes: &[u8]) -> Option<&Path> {
+            use std::ffi::OsStr;
+            use std::os::unix::prelude::*;
+            Some(Path::new(OsStr::from_bytes(bytes)))
+        }
+
+        #[cfg(windows)]
+        fn bytes2path(bytes: &[u8]) -> Option<&Path> {
+            use std::str;
+            str::from_utf8(bytes).ok().map(Path::new)
+        }
+
+        self.filename_bytes().and_then(bytes2path)
+    }
+
     pub fn lineno(&self) -> Option<u32> {
         match *self {
             Symbol::Syminfo { .. } => None,
             Symbol::Pcinfo { lineno, .. } => Some(lineno as u32),
+            Symbol::Dladdr(ref s) => s.lineno(),
         }
     }
 }
 
-extern fn error_cb(_data: *mut c_void, _msg: *const c_char,
-                   _errnum: c_int) {
+extern "C" fn error_cb(_data: *mut c_void, _msg: *const c_char, _errnum: c_int) {
     // do nothing for now
 }
 
-extern fn syminfo_cb(data: *mut c_void,
-                     pc: uintptr_t,
-                     symname: *const c_char,
-                     _symval: uintptr_t,
-                     _symsize: uintptr_t) {
-    unsafe {
-        call(data, &super::Symbol {
-            inner: Symbol::Syminfo {
-                pc: pc,
-                symname: symname,
-            },
-        });
-    }
+/// Type of the `data` pointer passed into `syminfo_cb`
+struct SyminfoState<'a> {
+    cb: &'a mut (FnMut(&super::Symbol) + 'a),
+    pc: usize,
 }
 
-extern fn pcinfo_cb(data: *mut c_void,
-                    pc: uintptr_t,
-                    filename: *const c_char,
-                    lineno: c_int,
-                    function: *const c_char) -> c_int {
+extern "C" fn syminfo_cb(
+    data: *mut c_void,
+    pc: uintptr_t,
+    symname: *const c_char,
+    _symval: uintptr_t,
+    _symsize: uintptr_t,
+) {
+    let mut bomb = crate::Bomb { enabled: true };
+
+    // Once this callback is invoked from `backtrace_syminfo` when we start
+    // resolving we go further to call `backtrace_pcinfo`. The
+    // `backtrace_pcinfo` function will consult debug information and attemp tto
+    // do things like recover file/line information as well as inlined frames.
+    // Note though that `backtrace_pcinfo` can fail or not do much if there's
+    // not debug info, so if that happens we're sure to call the callback with
+    // at least one symbol from the `syminfo_cb`.
     unsafe {
-        if filename.is_null() || function.is_null() {
-            return -1
+        let syminfo_state = &mut *(data as *mut SyminfoState);
+        let mut pcinfo_state = PcinfoState {
+            symname,
+            called: false,
+            cb: syminfo_state.cb,
+        };
+        bt::backtrace_pcinfo(
+            init_state(),
+            syminfo_state.pc as uintptr_t,
+            pcinfo_cb,
+            error_cb,
+            &mut pcinfo_state as *mut _ as *mut _,
+        );
+        if !pcinfo_state.called {
+            (pcinfo_state.cb)(&super::Symbol {
+                inner: Symbol::Syminfo {
+                    pc: pc,
+                    symname: symname,
+                },
+            });
         }
-        call(data, &super::Symbol {
+    }
+
+    bomb.enabled = false;
+}
+
+/// Type of the `data` pointer passed into `pcinfo_cb`
+struct PcinfoState<'a> {
+    cb: &'a mut (FnMut(&super::Symbol) + 'a),
+    symname: *const c_char,
+    called: bool,
+}
+
+extern "C" fn pcinfo_cb(
+    data: *mut c_void,
+    pc: uintptr_t,
+    filename: *const c_char,
+    lineno: c_int,
+    function: *const c_char,
+) -> c_int {
+    if filename.is_null() || function.is_null() {
+        return -1;
+    }
+    let mut bomb = crate::Bomb { enabled: true };
+
+    unsafe {
+        let state = &mut *(data as *mut PcinfoState);
+        state.called = true;
+        (state.cb)(&super::Symbol {
             inner: Symbol::Pcinfo {
                 pc: pc,
                 filename: filename,
                 lineno: lineno,
-                function: function,
+                symname: state.symname,
+                function,
             },
         });
-        return 0
     }
-}
 
-unsafe fn call(data: *mut c_void, sym: &super::Symbol) {
-    let cb = data as *mut &mut FnMut(&super::Symbol);
-    let mut bomb = ::Bomb { enabled: true };
-    (*cb)(sym);
     bomb.enabled = false;
+    return 0;
 }
 
 // The libbacktrace API supports creating a state, but it does not
@@ -136,44 +254,236 @@
 // that is calculated the first time this is requested. Remember that
 // backtracing all happens serially (one global lock).
 //
-// Things don't work so well on not-Linux since libbacktrace can't track down
-// that executable this is. We at one point used env::current_exe but it turns
-// out that there are some serious security issues with that approach.
-//
-// Specifically, on certain platforms like BSDs, a malicious actor can cause an
-// arbitrary file to be placed at the path returned by current_exe. libbacktrace
-// does not behave defensively in the presence of ill-formed DWARF information,
-// and has been demonstrated to segfault in at least one case. There is no
-// evidence at the moment to suggest that a more carefully constructed file
-// can't cause arbitrary code execution. As a result of all of this, we don't
-// hint libbacktrace with the path to the current process.
+// Note the lack of synchronization here is due to the requirement that
+// `resolve` is externally synchronized.
 unsafe fn init_state() -> *mut bt::backtrace_state {
     static mut STATE: *mut bt::backtrace_state = 0 as *mut _;
-    static INIT: Once = ONCE_INIT;
-    INIT.call_once(|| {
-        // Our libbacktrace may not have multithreading support, so
-        // set `threaded = 0` and synchronize ourselves.
-        STATE = bt::backtrace_create_state(ptr::null(), 0, error_cb,
-                                           ptr::null_mut());
-    });
 
-    STATE
+    if !STATE.is_null() {
+        return STATE;
+    }
+
+    STATE = bt::backtrace_create_state(
+        load_filename(),
+        // Don't exercise threadsafe capabilities of libbacktrace since
+        // we're always calling it in a synchronized fashion.
+        0,
+        error_cb,
+        ptr::null_mut(), // no extra data
+    );
+
+    return STATE;
+
+    // Note that for libbacktrace to operate at all it needs to find the DWARF
+    // debug info for the current executable. It typically does that via a
+    // number of mechanisms including, but not limited to:
+    //
+    // * /proc/self/exe on supported platforms
+    // * The filename passed in explicitly when creating state
+    //
+    // The libbacktrace library is a big wad of C code. This naturally means
+    // it's got memory safety vulnerabilities, especially when handling
+    // malformed debuginfo. Libstd has run into plenty of these historically.
+    //
+    // If /proc/self/exe is used then we can typically ignore these as we
+    // assume that libbacktrace is "mostly correct" and otherwise doesn't do
+    // weird things with "attempted to be correct" dwarf debug info.
+    //
+    // If we pass in a filename, however, then it's possible on some platforms
+    // (like BSDs) where a malicious actor can cause an arbitrary file to be
+    // placed at that location. This means that if we tell libbacktrace about a
+    // filename it may be using an arbitrary file, possibly causing segfaults.
+    // If we don't tell libbacktrace anything though then it won't do anything
+    // on platforms that don't support paths like /proc/self/exe!
+    //
+    // Given all that we try as hard as possible to *not* pass in a filename,
+    // but we must on platforms that don't support /proc/self/exe at all.
+    cfg_if::cfg_if! {
+        if #[cfg(any(target_os = "macos", target_os = "ios"))] {
+            // Note that ideally we'd use `std::env::current_exe`, but we can't
+            // require `std` here.
+            //
+            // Use `_NSGetExecutablePath` to load the current executable path
+            // into a static area (which if it's too small just give up).
+            //
+            // Note that we're seriously trusting libbacktrace here to not die
+            // on corrupt executables, but it surely does...
+            unsafe fn load_filename() -> *const libc::c_char {
+                const N: usize = 256;
+                static mut BUF: [u8; N] = [0; N];
+                extern {
+                    fn _NSGetExecutablePath(
+                        buf: *mut libc::c_char,
+                        bufsize: *mut u32,
+                    ) -> libc::c_int;
+                }
+                let mut sz: u32 = BUF.len() as u32;
+                let ptr = BUF.as_mut_ptr() as *mut libc::c_char;
+                if _NSGetExecutablePath(ptr, &mut sz) == 0 {
+                    ptr
+                } else {
+                    ptr::null()
+                }
+            }
+        } else if #[cfg(windows)] {
+            use crate::windows::*;
+
+            // Windows has a mode of opening files where after it's opened it
+            // can't be deleted. That's in general what we want here because we
+            // want to ensure that our executable isn't changing out from under
+            // us after we hand it off to libbacktrace, hopefully mitigating the
+            // ability to pass in arbitrary data into libbacktrace (which may be
+            // mishandled).
+            //
+            // Given that we do a bit of a dance here to attempt to get a sort
+            // of lock on our own image:
+            //
+            // * Get a handle to the current process, load its filename.
+            // * Open a file to that filename with the right flags.
+            // * Reload the current process's filename, making sure it's the same
+            //
+            // If that all passes we in theory have indeed opened our process's
+            // file and we're guaranteed it won't change. FWIW a bunch of this
+            // is copied from libstd historically, so this is my best
+            // interpretation of what was happening.
+            unsafe fn load_filename() -> *const libc::c_char {
+                load_filename_opt().unwrap_or(ptr::null())
+            }
+
+            unsafe fn load_filename_opt() -> Result<*const libc::c_char, ()> {
+                const N: usize = 256;
+                // This lives in static memory so we can return it..
+                static mut BUF: [i8; N] = [0; N];
+                // ... and this lives on the stack since it's temporary
+                let mut stack_buf = [0; N];
+                let name1 = query_full_name(&mut BUF)?;
+
+                let handle = CreateFileA(
+                    name1.as_ptr(),
+                    GENERIC_READ,
+                    FILE_SHARE_READ | FILE_SHARE_WRITE,
+                    ptr::null_mut(),
+                    OPEN_EXISTING,
+                    0,
+                    ptr::null_mut(),
+                );
+                if handle.is_null() {
+                    return Err(());
+                }
+
+                let name2 = query_full_name(&mut stack_buf)?;
+                if name1 != name2 {
+                    CloseHandle(handle);
+                    return Err(())
+                }
+                // intentionally leak `handle` here because having that open
+                // should preserve our lock on this file name.
+                Ok(name1.as_ptr())
+            }
+
+            unsafe fn query_full_name(buf: &mut [i8]) -> Result<&[i8], ()> {
+                let dll = GetModuleHandleA(b"kernel32.dll\0".as_ptr() as *const i8);
+                if dll.is_null() {
+                    return Err(())
+                }
+                let ptrQueryFullProcessImageNameA =
+                    GetProcAddress(dll, b"QueryFullProcessImageNameA\0".as_ptr() as *const _) as usize;
+                if ptrQueryFullProcessImageNameA == 0
+                {
+                    return Err(());
+                }
+                use core::mem;
+                let p1 = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId());
+                let mut len = buf.len() as u32;
+                let pfnQueryFullProcessImageNameA : extern "system" fn(
+                    hProcess: HANDLE,
+                    dwFlags: DWORD,
+                    lpExeName: LPSTR,
+                    lpdwSize: PDWORD,
+                ) -> BOOL = mem::transmute(ptrQueryFullProcessImageNameA);
+
+                let rc = pfnQueryFullProcessImageNameA(p1, 0, buf.as_mut_ptr(), &mut len);
+                CloseHandle(p1);
+
+                // We want to return a slice that is nul-terminated, so if
+                // everything was filled in and it equals the total length
+                // then equate that to failure.
+                //
+                // Otherwise when returning success make sure the nul byte is
+                // included in the slice.
+                if rc == 0 || len == buf.len() as u32 {
+                    Err(())
+                } else {
+                    assert_eq!(buf[len as usize], 0);
+                    Ok(&buf[..(len + 1) as usize])
+                }
+            }
+        } else if #[cfg(target_os = "vxworks")] {
+            unsafe fn load_filename() -> *const libc::c_char {
+                use libc;
+                use core::mem;
+
+                const N: usize = libc::VX_RTP_NAME_LENGTH as usize + 1;
+                static mut BUF: [libc::c_char; N] = [0; N];
+
+                let mut rtp_desc : libc::RTP_DESC = mem::zeroed();
+                if (libc::rtpInfoGet(0, &mut rtp_desc as *mut libc::RTP_DESC) == 0) {
+                    BUF.copy_from_slice(&rtp_desc.pathName);
+                    BUF.as_ptr()
+                } else {
+                    ptr::null()
+                }
+            }
+        } else {
+            unsafe fn load_filename() -> *const libc::c_char {
+                ptr::null()
+            }
+        }
+    }
 }
 
-pub unsafe fn resolve(symaddr: *mut c_void, mut cb: &mut FnMut(&super::Symbol))
-{
+pub unsafe fn resolve(what: ResolveWhat, cb: &mut FnMut(&super::Symbol)) {
+    let symaddr = what.address_or_ip() as usize;
+
     // backtrace errors are currently swept under the rug
     let state = init_state();
     if state.is_null() {
-        return
+        return dladdr_fallback(what.address_or_ip(), cb);
     }
 
-    let ret = bt::backtrace_pcinfo(state, symaddr as uintptr_t,
-                                   pcinfo_cb, error_cb,
-                                   &mut cb as *mut _ as *mut _);
-    if ret != 0 {
-        bt::backtrace_syminfo(state, symaddr as uintptr_t,
-                              syminfo_cb, error_cb,
-                              &mut cb as *mut _ as *mut _);
+    // Call the `backtrace_syminfo` API first. This is (from reading the code)
+    // guaranteed to call `syminfo_cb` exactly once (or fail with an error
+    // presumably). We then handle more within the `syminfo_cb`.
+    //
+    // Note that we do this since `syminfo` will consult the symbol table,
+    // finding symbol names even if there's no debug information in the binary.
+    let mut called = false;
+    {
+        let mut syminfo_state = SyminfoState {
+            pc: symaddr,
+            cb: &mut |sym| {
+                called = true;
+                cb(sym);
+            },
+        };
+        bt::backtrace_syminfo(
+            state,
+            symaddr as uintptr_t,
+            syminfo_cb,
+            error_cb,
+            &mut syminfo_state as *mut _ as *mut _,
+        );
     }
+
+    if !called {
+        dladdr_fallback(what.address_or_ip(), cb);
+    }
+}
+
+unsafe fn dladdr_fallback(addr: *mut c_void, cb: &mut FnMut(&super::Symbol)) {
+    dladdr::resolve(addr, &mut |sym| {
+        cb(&super::Symbol {
+            inner: Symbol::Dladdr(sym),
+        })
+    });
 }
diff --git a/third_party/rust_crates/vendor/backtrace/src/symbolize/mod.rs b/third_party/rust_crates/vendor/backtrace/src/symbolize/mod.rs
index f4edba6..7f8919b 100644
--- a/third_party/rust_crates/vendor/backtrace/src/symbolize/mod.rs
+++ b/third_party/rust_crates/vendor/backtrace/src/symbolize/mod.rs
@@ -1,13 +1,15 @@
 use core::{fmt, str};
 
-cfg_if! {
+cfg_if::cfg_if! {
     if #[cfg(feature = "std")] {
         use std::path::Path;
         use std::prelude::v1::*;
     }
 }
 
-use types::{BytesOrWideString, c_void};
+use crate::backtrace::Frame;
+use crate::types::BytesOrWideString;
+use core::ffi::c_void;
 use rustc_demangle::{try_demangle, Demangle};
 
 /// Resolve an address to a symbol, passing the symbol to the specified
@@ -23,11 +25,21 @@
 /// Symbols yielded represent the execution at the specified `addr`, returning
 /// file/line pairs for that address (if available).
 ///
+/// Note that if you have a `Frame` then it's recommended to use the
+/// `resolve_frame` function instead of this one.
+///
 /// # Required features
 ///
 /// This function requires the `std` feature of the `backtrace` crate to be
 /// enabled, and the `std` feature is enabled by default.
 ///
+/// # Panics
+///
+/// This function strives to never panic, but if the `cb` provided panics then
+/// some platforms will force a double panic to abort the process. Some
+/// platforms use a C library which internally uses callbacks which cannot be
+/// unwound through, so panicking from `cb` may trigger a process abort.
+///
 /// # Example
 ///
 /// ```
@@ -47,21 +59,124 @@
 /// ```
 #[cfg(feature = "std")]
 pub fn resolve<F: FnMut(&Symbol)>(addr: *mut c_void, cb: F) {
-    let _guard = ::lock::lock();
+    let _guard = crate::lock::lock();
     unsafe { resolve_unsynchronized(addr, cb) }
 }
 
+/// Resolve a previously capture frame to a symbol, passing the symbol to the
+/// specified closure.
+///
+/// This functin performs the same function as `resolve` except that it takes a
+/// `Frame` as an argument instead of an address. This can allow some platform
+/// implementations of backtracing to provide more accurate symbol information
+/// or information about inline frames for example. It's recommended to use this
+/// if you can.
+///
+/// # Required features
+///
+/// This function requires the `std` feature of the `backtrace` crate to be
+/// enabled, and the `std` feature is enabled by default.
+///
+/// # Panics
+///
+/// This function strives to never panic, but if the `cb` provided panics then
+/// some platforms will force a double panic to abort the process. Some
+/// platforms use a C library which internally uses callbacks which cannot be
+/// unwound through, so panicking from `cb` may trigger a process abort.
+///
+/// # Example
+///
+/// ```
+/// extern crate backtrace;
+///
+/// fn main() {
+///     backtrace::trace(|frame| {
+///         backtrace::resolve_frame(frame, |symbol| {
+///             // ...
+///         });
+///
+///         false // only look at the top frame
+///     });
+/// }
+/// ```
+#[cfg(feature = "std")]
+pub fn resolve_frame<F: FnMut(&Symbol)>(frame: &Frame, cb: F) {
+    let _guard = crate::lock::lock();
+    unsafe { resolve_frame_unsynchronized(frame, cb) }
+}
+
+pub enum ResolveWhat<'a> {
+    Address(*mut c_void),
+    Frame(&'a Frame),
+}
+
+impl<'a> ResolveWhat<'a> {
+    #[allow(dead_code)]
+    fn address_or_ip(&self) -> *mut c_void {
+        match self {
+            ResolveWhat::Address(a) => adjust_ip(*a),
+            ResolveWhat::Frame(f) => adjust_ip(f.ip()),
+        }
+    }
+}
+
+// IP values from stack frames are typically (always?) the instruction
+// *after* the call that's the actual stack trace. Symbolizing this on
+// causes the filename/line number to be one ahead and perhaps into
+// the void if it's near the end of the function.
+//
+// This appears to basically always be the case on all platforms, so we always
+// subtract one from a resolved ip to resolve it to the previous call
+// instruction instead of the instruction being returned to.
+//
+// Ideally we would not do this. Ideally we would require callers of the
+// `resolve` APIs here to manually do the -1 and account that they want location
+// information for the *previous* instruction, not the current. Ideally we'd
+// also expose on `Frame` if we are indeed the address of the next instruction
+// or the current.
+//
+// For now though this is a pretty niche concern so we just internally always
+// subtract one. Consumers should keep working and getting pretty good results,
+// so we should be good enough.
+fn adjust_ip(a: *mut c_void) -> *mut c_void {
+    if a.is_null() {
+        a
+    } else {
+        (a as usize - 1) as *mut c_void
+    }
+}
+
 /// Same as `resolve`, only unsafe as it's unsynchronized.
 ///
 /// This function does not have synchronization guarentees but is available when
 /// the `std` feature of this crate isn't compiled in. See the `resolve`
 /// function for more documentation and examples.
+///
+/// # Panics
+///
+/// See information on `resolve` for caveats on `cb` panicking.
 pub unsafe fn resolve_unsynchronized<F>(addr: *mut c_void, mut cb: F)
-    where F: FnMut(&Symbol)
+where
+    F: FnMut(&Symbol),
 {
-    resolve_imp(addr as *mut _, &mut cb)
+    resolve_imp(ResolveWhat::Address(addr), &mut cb)
 }
 
+/// Same as `resolve_frame`, only unsafe as it's unsynchronized.
+///
+/// This function does not have synchronization guarentees but is available
+/// when the `std` feature of this crate isn't compiled in. See the
+/// `resolve_frame` function for more documentation and examples.
+///
+/// # Panics
+///
+/// See information on `resolve_frame` for caveats on `cb` panicking.
+pub unsafe fn resolve_frame_unsynchronized<F>(frame: &Frame, mut cb: F)
+where
+    F: FnMut(&Symbol),
+{
+    resolve_imp(ResolveWhat::Frame(frame), &mut cb)
+}
 
 /// A trait representing the resolution of a symbol in a file.
 ///
@@ -73,7 +188,10 @@
 /// name, filename, line number, precise address, etc. Not all information is
 /// always available in a symbol, however, so all methods return an `Option`.
 pub struct Symbol {
-    inner: SymbolImp,
+    // TODO: this lifetime bound needs to be persisted eventually to `Symbol`,
+    // but that's currently a breaking change. For now this is safe since
+    // `Symbol` is only ever handed out by reference and can't be cloned.
+    inner: SymbolImp<'static>,
 }
 
 impl Symbol {
@@ -101,7 +219,6 @@
         self.inner.filename_raw()
     }
 
-
     /// Returns the line number for where this symbol is currently executing.
     ///
     /// This return value is typically `Some` if `filename` returns `Some`, and
@@ -117,30 +234,14 @@
     /// debuginfo. If neither of these conditions is met then this will likely
     /// return `None`.
     ///
-    /// This function requires the `std` feature to be enabled for this crate.
+    /// # Required features
+    ///
+    /// This function requires the `std` feature of the `backtrace` crate to be
+    /// enabled, and the `std` feature is enabled by default.
     #[cfg(feature = "std")]
+    #[allow(unreachable_code)]
     pub fn filename(&self) -> Option<&Path> {
-        #[cfg(unix)]
-        {
-            use std::ffi::OsStr;
-            use std::os::unix::ffi::OsStrExt;
-
-            match self.filename_raw() {
-                Some(BytesOrWideString::Bytes(slice)) => {
-                    Some(Path::new(OsStr::from_bytes(slice)))
-                }
-                None => None,
-                _ => unreachable!(),
-            }
-        }
-        #[cfg(windows)]
-        {
-            self.inner.filename().map(Path::new)
-        }
-        #[cfg(all(not(windows), not(unix)))]
-        {
-            None
-        }
+        self.inner.filename()
     }
 }
 
@@ -154,7 +255,8 @@
             d.field("addr", &addr);
         }
 
-        #[cfg(feature = "std")] {
+        #[cfg(feature = "std")]
+        {
             if let Some(filename) = self.filename() {
                 d.field("filename", &filename);
             }
@@ -167,7 +269,7 @@
     }
 }
 
-cfg_if! {
+cfg_if::cfg_if! {
     if #[cfg(feature = "cpp_demangle")] {
         // Maybe a parsed C++ symbol, if parsing the mangled symbol as Rust
         // failed.
@@ -230,14 +332,14 @@
         }
     }
 
-    /// Returns the raw symbol name as a `str` if the symbols is valid utf-8.
+    /// Returns the raw (mangled) symbol name as a `str` if the symbol is valid utf-8.
+    ///
+    /// Use the `Display` implementation if you want the demangled version.
     pub fn as_str(&self) -> Option<&'a str> {
         self.demangled
             .as_ref()
             .map(|s| s.as_str())
-            .or_else(|| {
-                str::from_utf8(self.bytes).ok()
-            })
+            .or_else(|| str::from_utf8(self.bytes).ok())
     }
 
     /// Returns the raw symbol name as a list of bytes
@@ -246,16 +348,16 @@
     }
 }
 
-fn format_symbol_name(fmt: fn(&str, &mut fmt::Formatter) -> fmt::Result,
-                      mut bytes: &[u8],
-                      f: &mut fmt::Formatter)
-    -> fmt::Result
-{
+fn format_symbol_name(
+    fmt: fn(&str, &mut fmt::Formatter) -> fmt::Result,
+    mut bytes: &[u8],
+    f: &mut fmt::Formatter,
+) -> fmt::Result {
     while bytes.len() > 0 {
         match str::from_utf8(bytes) {
             Ok(name) => {
                 fmt(name, f)?;
-                break
+                break;
             }
             Err(err) => {
                 fmt("\u{FFFD}", f)?;
@@ -270,7 +372,7 @@
     Ok(())
 }
 
-cfg_if! {
+cfg_if::cfg_if! {
     if #[cfg(feature = "cpp_demangle")] {
         impl<'a> fmt::Display for SymbolName<'a> {
             fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -296,7 +398,7 @@
     }
 }
 
-cfg_if! {
+cfg_if::cfg_if! {
     if #[cfg(all(feature = "std", feature = "cpp_demangle"))] {
         impl<'a> fmt::Debug for SymbolName<'a> {
             fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -332,28 +434,48 @@
     }
 }
 
-cfg_if! {
-    if #[cfg(all(windows, feature = "dbghelp"))] {
+/// Attempt to reclaim that cached memory used to symbolicate addresses.
+///
+/// This method will attempt to release any global data structures that have
+/// otherwise been cached globally or in the thread which typically represent
+/// parsed DWARF information or similar.
+///
+/// # Caveats
+///
+/// While this function is always available it doesn't actually do anything on
+/// most implementations. Libraries like dbghelp or libbacktrace do not provide
+/// facilities to deallocate state and manage the allocated memory. For now the
+/// `gimli-symbolize` feature of this crate is the only feature where this
+/// function has any effect.
+#[cfg(feature = "std")]
+pub fn clear_symbol_cache() {
+    let _guard = crate::lock::lock();
+    unsafe {
+        clear_symbol_cache_imp();
+    }
+}
+
+mod dladdr;
+
+cfg_if::cfg_if! {
+    if #[cfg(all(windows, target_env = "msvc", feature = "dbghelp", not(target_vendor = "uwp")))] {
         mod dbghelp;
         use self::dbghelp::resolve as resolve_imp;
         use self::dbghelp::Symbol as SymbolImp;
-    } else if #[cfg(all(feature = "std",
-                        feature = "gimli-symbolize",
-                        unix,
-                        target_os = "linux"))] {
+        unsafe fn clear_symbol_cache_imp() {}
+    } else if #[cfg(all(
+        feature = "std",
+        feature = "gimli-symbolize",
+        any(
+            target_os = "linux",
+            target_os = "macos",
+            windows,
+        ),
+    ))] {
         mod gimli;
         use self::gimli::resolve as resolve_imp;
         use self::gimli::Symbol as SymbolImp;
-    } else if #[cfg(all(feature = "libbacktrace",
-                        unix,
-                        not(target_os = "fuchsia"),
-                        not(target_os = "emscripten"),
-                        not(target_os = "macos"),
-                        not(target_os = "ios")))] {
-        mod libbacktrace;
-        use self::libbacktrace::resolve as resolve_imp;
-        use self::libbacktrace::Symbol as SymbolImp;
-
+        use self::gimli::clear_symbol_cache as clear_symbol_cache_imp;
     // Note that we only enable coresymbolication on iOS when debug assertions
     // are enabled because it's helpful in debug mode but it looks like apps get
     // rejected from the app store if they use this API, see #92 for more info
@@ -363,15 +485,28 @@
         mod coresymbolication;
         use self::coresymbolication::resolve as resolve_imp;
         use self::coresymbolication::Symbol as SymbolImp;
+        unsafe fn clear_symbol_cache_imp() {}
+    } else if #[cfg(all(feature = "libbacktrace",
+                        any(unix, all(windows, not(target_vendor = "uwp"), target_env = "gnu")),
+                        not(target_os = "fuchsia"),
+                        not(target_os = "emscripten")))] {
+        mod libbacktrace;
+        use self::libbacktrace::resolve as resolve_imp;
+        use self::libbacktrace::Symbol as SymbolImp;
+        unsafe fn clear_symbol_cache_imp() {}
     } else if #[cfg(all(unix,
                         not(target_os = "emscripten"),
+                        not(target_os = "fuchsia"),
                         feature = "dladdr"))] {
-        mod dladdr;
-        use self::dladdr::resolve as resolve_imp;
-        use self::dladdr::Symbol as SymbolImp;
+        mod dladdr_resolve;
+        use self::dladdr_resolve::resolve as resolve_imp;
+        use self::dladdr_resolve::Symbol as SymbolImp;
+        unsafe fn clear_symbol_cache_imp() {}
     } else {
         mod noop;
         use self::noop::resolve as resolve_imp;
         use self::noop::Symbol as SymbolImp;
+        #[allow(unused)]
+        unsafe fn clear_symbol_cache_imp() {}
     }
 }
diff --git a/third_party/rust_crates/vendor/backtrace/src/symbolize/noop.rs b/third_party/rust_crates/vendor/backtrace/src/symbolize/noop.rs
index 1730d57..5c115d5 100644
--- a/third_party/rust_crates/vendor/backtrace/src/symbolize/noop.rs
+++ b/third_party/rust_crates/vendor/backtrace/src/symbolize/noop.rs
@@ -1,12 +1,19 @@
-use types::{BytesOrWideString, c_void};
-use SymbolName;
+//! Empty symbolication strategy used to compile for platforms that have no
+//! support.
 
-pub unsafe fn resolve(_addr: *mut c_void, _cb: &mut FnMut(&super::Symbol)) {
+use crate::symbolize::ResolveWhat;
+use crate::types::BytesOrWideString;
+use crate::SymbolName;
+use core::ffi::c_void;
+use core::marker;
+
+pub unsafe fn resolve(_addr: ResolveWhat, _cb: &mut FnMut(&super::Symbol)) {}
+
+pub struct Symbol<'a> {
+    _marker: marker::PhantomData<&'a i32>,
 }
 
-pub struct Symbol;
-
-impl Symbol {
+impl Symbol<'_> {
     pub fn name(&self) -> Option<SymbolName> {
         None
     }
@@ -19,6 +26,11 @@
         None
     }
 
+    #[cfg(feature = "std")]
+    pub fn filename(&self) -> Option<&::std::path::Path> {
+        None
+    }
+
     pub fn lineno(&self) -> Option<u32> {
         None
     }
diff --git a/third_party/rust_crates/vendor/backtrace/src/types.rs b/third_party/rust_crates/vendor/backtrace/src/types.rs
index a0c8058..f7bcb17 100644
--- a/third_party/rust_crates/vendor/backtrace/src/types.rs
+++ b/third_party/rust_crates/vendor/backtrace/src/types.rs
@@ -1,16 +1,12 @@
 //! Platform dependent types.
 
-cfg_if! {
+cfg_if::cfg_if! {
     if #[cfg(feature = "std")] {
-        pub use std::os::raw::c_void;
         use std::borrow::Cow;
         use std::fmt;
         use std::path::PathBuf;
         use std::prelude::v1::*;
-    } else if #[cfg(rustc_1_30)] {
-        pub use core::ffi::c_void;
-    } else {
-        compile_error!("`backtrace` requires Rust >=1.30.0 to support `no_std`.");
+        use std::str;
     }
 }
 
@@ -29,6 +25,11 @@
 impl<'a> BytesOrWideString<'a> {
     /// Lossy converts to a `Cow<str>`, will allocate if `Bytes` is not valid
     /// UTF-8 or if `BytesOrWideString` is `Wide`.
+    ///
+    /// # Required features
+    ///
+    /// This function requires the `std` feature of the `backtrace` crate to be
+    /// enabled, and the `std` feature is enabled by default.
     pub fn to_str_lossy(&self) -> Cow<'a, str> {
         use self::BytesOrWideString::*;
 
@@ -39,35 +40,38 @@
     }
 
     /// Provides a `Path` representation of `BytesOrWideString`.
+    ///
+    /// # Required features
+    ///
+    /// This function requires the `std` feature of the `backtrace` crate to be
+    /// enabled, and the `std` feature is enabled by default.
     pub fn into_path_buf(self) -> PathBuf {
         #[cfg(unix)]
         {
-            use self::BytesOrWideString::*;
             use std::ffi::OsStr;
             use std::os::unix::ffi::OsStrExt;
 
-            match self {
-                Bytes(slice) => PathBuf::from(OsStr::from_bytes(slice)),
-                _ => unreachable!(),
+            if let BytesOrWideString::Bytes(slice) = self {
+                return PathBuf::from(OsStr::from_bytes(slice));
             }
         }
 
         #[cfg(windows)]
         {
-            use self::BytesOrWideString::*;
             use std::ffi::OsString;
             use std::os::windows::ffi::OsStringExt;
 
-            match self {
-                Wide(slice) => PathBuf::from(OsString::from_wide(slice)),
-                _ => unreachable!(),
+            if let BytesOrWideString::Wide(slice) = self {
+                return PathBuf::from(OsString::from_wide(slice));
             }
         }
 
-        #[cfg(all(not(windows), not(unix)))]
-        {
-            unreachable!()
+        if let BytesOrWideString::Bytes(b) = self {
+            if let Ok(s) = str::from_utf8(b) {
+                return PathBuf::from(s);
+            }
         }
+        unreachable!()
     }
 }
 
diff --git a/third_party/rust_crates/vendor/backtrace/src/windows.rs b/third_party/rust_crates/vendor/backtrace/src/windows.rs
new file mode 100644
index 0000000..9672af0
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace/src/windows.rs
@@ -0,0 +1,637 @@
+//! A module to define the FFI definitions we use on Windows for `dbghelp.dll`
+//!
+//! This module uses a custom macro, `ffi!`, to wrap all definitions to
+//! automatically generate tests to assert that our definitions here are the
+//! same as `winapi`.
+//!
+//! This module largely exists to integrate into libstd itself where winapi is
+//! not currently available.
+
+#![allow(bad_style, dead_code)]
+
+cfg_if::cfg_if! {
+    if #[cfg(feature = "verify-winapi")] {
+        pub use self::winapi::c_void;
+        pub use self::winapi::HINSTANCE;
+        pub use self::winapi::FARPROC;
+        pub use self::winapi::LPSECURITY_ATTRIBUTES;
+        #[cfg(target_pointer_width = "64")]
+        pub use self::winapi::PUNWIND_HISTORY_TABLE;
+        #[cfg(target_pointer_width = "64")]
+        pub use self::winapi::PRUNTIME_FUNCTION;
+
+        mod winapi {
+            pub use winapi::ctypes::*;
+            pub use winapi::shared::basetsd::*;
+            pub use winapi::shared::minwindef::*;
+            pub use winapi::um::dbghelp::*;
+            pub use winapi::um::handleapi::*;
+            pub use winapi::um::libloaderapi::*;
+            pub use winapi::um::processthreadsapi::*;
+            pub use winapi::um::winbase::*;
+            pub use winapi::um::winnt::*;
+            pub use winapi::um::fileapi::*;
+            pub use winapi::um::minwinbase::*;
+            pub use winapi::um::synchapi::*;
+        }
+    } else {
+        pub use core::ffi::c_void;
+        pub type HINSTANCE = *mut c_void;
+        pub type FARPROC = *mut c_void;
+        pub type LPSECURITY_ATTRIBUTES = *mut c_void;
+        #[cfg(target_pointer_width = "64")]
+        pub type PRUNTIME_FUNCTION = *mut c_void;
+        #[cfg(target_pointer_width = "64")]
+        pub type PUNWIND_HISTORY_TABLE = *mut c_void;
+    }
+}
+
+macro_rules! ffi {
+	() => ();
+
+    (#[repr($($r:tt)*)] pub struct $name:ident { $(pub $field:ident: $ty:ty,)* } $($rest:tt)*) => (
+        #[repr($($r)*)]
+        #[cfg(not(feature = "verify-winapi"))]
+        #[derive(Copy, Clone)]
+        pub struct $name {
+            $(pub $field: $ty,)*
+        }
+
+        #[cfg(feature = "verify-winapi")]
+        pub use self::winapi::$name;
+
+        #[test]
+        #[cfg(feature = "verify-winapi")]
+        fn $name() {
+            use core::mem;
+
+            #[repr($($r)*)]
+            pub struct $name {
+                $(pub $field: $ty,)*
+            }
+
+            assert_eq!(
+                mem::size_of::<$name>(),
+                mem::size_of::<winapi::$name>(),
+                concat!("size of ", stringify!($name), " is wrong"),
+            );
+            assert_eq!(
+                mem::align_of::<$name>(),
+                mem::align_of::<winapi::$name>(),
+                concat!("align of ", stringify!($name), " is wrong"),
+            );
+
+            type Winapi = winapi::$name;
+
+            fn assert_same<T>(_: T, _: T) {}
+
+            unsafe {
+                let a = &*(mem::align_of::<$name>() as *const $name);
+                let b = &*(mem::align_of::<Winapi>() as *const Winapi);
+
+                $(
+                    ffi!(@test_fields a b $field $ty);
+                )*
+            }
+        }
+
+        ffi!($($rest)*);
+    );
+
+    // Handling verification against unions in winapi requires some special care
+    (@test_fields $a:ident $b:ident FltSave $ty:ty) => (
+        // Skip this field on x86_64 `CONTEXT` since it's a union and a bit funny
+    );
+    (@test_fields $a:ident $b:ident D $ty:ty) => ({
+        let a = &$a.D;
+        let b = $b.D();
+        assert_same(a, b);
+        assert_eq!(a as *const $ty, b as *const $ty, "misplaced field D");
+    });
+    (@test_fields $a:ident $b:ident s $ty:ty) => ({
+        let a = &$a.s;
+        let b = $b.s();
+        assert_same(a, b);
+        assert_eq!(a as *const $ty, b as *const $ty, "misplaced field s");
+    });
+
+    // Otherwise test all fields normally.
+    (@test_fields $a:ident $b:ident $field:ident $ty:ty) => ({
+        let a = &$a.$field;
+        let b = &$b.$field;
+        assert_same(a, b);
+        assert_eq!(a as *const $ty, b as *const $ty,
+                   concat!("misplaced field ", stringify!($field)));
+    });
+
+    (pub type $name:ident = $ty:ty; $($rest:tt)*) => (
+        pub type $name = $ty;
+
+        #[cfg(feature = "verify-winapi")]
+        #[allow(dead_code)]
+        const $name: () = {
+            fn _foo() {
+                trait SameType {}
+                impl<T> SameType for (T, T) {}
+                fn assert_same<T: SameType>() {}
+
+                assert_same::<($name, winapi::$name)>();
+            }
+        };
+
+        ffi!($($rest)*);
+    );
+
+    (pub const $name:ident: $ty:ty = $val:expr; $($rest:tt)*) => (
+        pub const $name: $ty = $val;
+
+        #[cfg(feature = "verify-winapi")]
+        #[allow(unused_imports)]
+        mod $name {
+            use super::*;
+            #[test]
+            fn assert_valid() {
+                let x: $ty = winapi::$name;
+                assert_eq!(x, $val);
+            }
+        }
+
+
+        ffi!($($rest)*);
+    );
+
+    (extern "system" { $(pub fn $name:ident($($args:tt)*) -> $ret:ty;)* } $($rest:tt)*) => (
+        extern "system" {
+            $(pub fn $name($($args)*) -> $ret;)*
+        }
+
+        $(
+            #[cfg(feature = "verify-winapi")]
+            mod $name {
+                #[test]
+                fn assert_same() {
+                    use super::*;
+
+                    assert_eq!($name as usize, winapi::$name as usize);
+                    let mut x: unsafe extern "system" fn($($args)*) -> $ret;
+                    x = $name;
+                    drop(x);
+                    x = winapi::$name;
+                    drop(x);
+                }
+            }
+        )*
+
+        ffi!($($rest)*);
+    );
+
+    (impl $name:ident { $($i:tt)* } $($rest:tt)*) => (
+        #[cfg(not(feature = "verify-winapi"))]
+        impl $name {
+            $($i)*
+        }
+
+        ffi!($($rest)*);
+    );
+}
+
+ffi! {
+    #[repr(C)]
+    pub struct STACKFRAME64 {
+        pub AddrPC: ADDRESS64,
+        pub AddrReturn: ADDRESS64,
+        pub AddrFrame: ADDRESS64,
+        pub AddrStack: ADDRESS64,
+        pub AddrBStore: ADDRESS64,
+        pub FuncTableEntry: PVOID,
+        pub Params: [DWORD64; 4],
+        pub Far: BOOL,
+        pub Virtual: BOOL,
+        pub Reserved: [DWORD64; 3],
+        pub KdHelp: KDHELP64,
+    }
+
+    pub type LPSTACKFRAME64 = *mut STACKFRAME64;
+
+    #[repr(C)]
+    pub struct STACKFRAME_EX {
+        pub AddrPC: ADDRESS64,
+        pub AddrReturn: ADDRESS64,
+        pub AddrFrame: ADDRESS64,
+        pub AddrStack: ADDRESS64,
+        pub AddrBStore: ADDRESS64,
+        pub FuncTableEntry: PVOID,
+        pub Params: [DWORD64; 4],
+        pub Far: BOOL,
+        pub Virtual: BOOL,
+        pub Reserved: [DWORD64; 3],
+        pub KdHelp: KDHELP64,
+        pub StackFrameSize: DWORD,
+        pub InlineFrameContext: DWORD,
+    }
+
+    pub type LPSTACKFRAME_EX = *mut STACKFRAME_EX;
+
+    #[repr(C)]
+    pub struct IMAGEHLP_LINEW64 {
+        pub SizeOfStruct: DWORD,
+        pub Key: PVOID,
+        pub LineNumber: DWORD,
+        pub FileName: PWSTR,
+        pub Address: DWORD64,
+    }
+
+    pub type PIMAGEHLP_LINEW64 = *mut IMAGEHLP_LINEW64;
+
+    #[repr(C)]
+    pub struct SYMBOL_INFOW {
+        pub SizeOfStruct: ULONG,
+        pub TypeIndex: ULONG,
+        pub Reserved: [ULONG64; 2],
+        pub Index: ULONG,
+        pub Size: ULONG,
+        pub ModBase: ULONG64,
+        pub Flags: ULONG,
+        pub Value: ULONG64,
+        pub Address: ULONG64,
+        pub Register: ULONG,
+        pub Scope: ULONG,
+        pub Tag: ULONG,
+        pub NameLen: ULONG,
+        pub MaxNameLen: ULONG,
+        pub Name: [WCHAR; 1],
+    }
+
+    pub type PSYMBOL_INFOW = *mut SYMBOL_INFOW;
+
+    pub type PTRANSLATE_ADDRESS_ROUTINE64 = Option<
+        unsafe extern "system" fn(hProcess: HANDLE, hThread: HANDLE, lpaddr: LPADDRESS64) -> DWORD64,
+    >;
+    pub type PGET_MODULE_BASE_ROUTINE64 =
+        Option<unsafe extern "system" fn(hProcess: HANDLE, Address: DWORD64) -> DWORD64>;
+    pub type PFUNCTION_TABLE_ACCESS_ROUTINE64 =
+        Option<unsafe extern "system" fn(ahProcess: HANDLE, AddrBase: DWORD64) -> PVOID>;
+    pub type PREAD_PROCESS_MEMORY_ROUTINE64 = Option<
+        unsafe extern "system" fn(
+            hProcess: HANDLE,
+            qwBaseAddress: DWORD64,
+            lpBuffer: PVOID,
+            nSize: DWORD,
+            lpNumberOfBytesRead: LPDWORD,
+        ) -> BOOL,
+    >;
+
+    #[repr(C)]
+    pub struct ADDRESS64 {
+        pub Offset: DWORD64,
+        pub Segment: WORD,
+        pub Mode: ADDRESS_MODE,
+    }
+
+    pub type LPADDRESS64 = *mut ADDRESS64;
+
+    pub type ADDRESS_MODE = u32;
+
+    #[repr(C)]
+    pub struct KDHELP64 {
+        pub Thread: DWORD64,
+        pub ThCallbackStack: DWORD,
+        pub ThCallbackBStore: DWORD,
+        pub NextCallback: DWORD,
+        pub FramePointer: DWORD,
+        pub KiCallUserMode: DWORD64,
+        pub KeUserCallbackDispatcher: DWORD64,
+        pub SystemRangeStart: DWORD64,
+        pub KiUserExceptionDispatcher: DWORD64,
+        pub StackBase: DWORD64,
+        pub StackLimit: DWORD64,
+        pub BuildVersion: DWORD,
+        pub Reserved0: DWORD,
+        pub Reserved1: [DWORD64; 4],
+    }
+
+    pub const MAX_SYM_NAME: usize = 2000;
+    pub const AddrModeFlat: ADDRESS_MODE = 3;
+    pub const TRUE: BOOL = 1;
+    pub const FALSE: BOOL = 0;
+    pub const PROCESS_QUERY_INFORMATION: DWORD = 0x400;
+    pub const IMAGE_FILE_MACHINE_ARM64: u16 = 43620;
+    pub const IMAGE_FILE_MACHINE_AMD64: u16 = 34404;
+    pub const IMAGE_FILE_MACHINE_I386: u16 = 332;
+    pub const IMAGE_FILE_MACHINE_ARMNT: u16 = 452;
+    pub const FILE_SHARE_READ: DWORD = 0x1;
+    pub const FILE_SHARE_WRITE: DWORD = 0x2;
+    pub const OPEN_EXISTING: DWORD = 0x3;
+    pub const GENERIC_READ: DWORD = 0x80000000;
+    pub const INFINITE: DWORD = !0;
+
+    pub type DWORD = u32;
+    pub type PDWORD = *mut u32;
+    pub type BOOL = i32;
+    pub type DWORD64 = u64;
+    pub type PDWORD64 = *mut u64;
+    pub type HANDLE = *mut c_void;
+    pub type PVOID = HANDLE;
+    pub type PCWSTR = *const u16;
+    pub type LPSTR = *mut i8;
+    pub type LPCSTR = *const i8;
+    pub type PWSTR = *mut u16;
+    pub type WORD = u16;
+    pub type ULONG = u32;
+    pub type ULONG64 = u64;
+    pub type WCHAR = u16;
+    pub type PCONTEXT = *mut CONTEXT;
+    pub type LPDWORD = *mut DWORD;
+    pub type DWORDLONG = u64;
+    pub type HMODULE = HINSTANCE;
+
+    extern "system" {
+        pub fn GetCurrentProcess() -> HANDLE;
+        pub fn GetCurrentThread() -> HANDLE;
+        pub fn RtlCaptureContext(ContextRecord: PCONTEXT) -> ();
+        pub fn LoadLibraryA(a: *const i8) -> HMODULE;
+        pub fn GetProcAddress(h: HMODULE, name: *const i8) -> FARPROC;
+        pub fn GetModuleHandleA(name: *const i8) -> HMODULE;
+        pub fn OpenProcess(
+            dwDesiredAccess: DWORD,
+            bInheitHandle: BOOL,
+            dwProcessId: DWORD,
+        ) -> HANDLE;
+        pub fn GetCurrentProcessId() -> DWORD;
+        pub fn CloseHandle(h: HANDLE) -> BOOL;
+        pub fn CreateFileA(
+            lpFileName: LPCSTR,
+            dwDesiredAccess: DWORD,
+            dwShareMode: DWORD,
+            lpSecurityAttributes: LPSECURITY_ATTRIBUTES,
+            dwCreationDisposition: DWORD,
+            dwFlagsAndAttributes: DWORD,
+            hTemplateFile: HANDLE,
+        ) -> HANDLE;
+        pub fn CreateMutexA(
+            attrs: LPSECURITY_ATTRIBUTES,
+            initial: BOOL,
+            name: LPCSTR,
+        ) -> HANDLE;
+        pub fn ReleaseMutex(hMutex: HANDLE) -> BOOL;
+        pub fn WaitForSingleObjectEx(
+            hHandle: HANDLE,
+            dwMilliseconds: DWORD,
+            bAlertable: BOOL,
+        ) -> DWORD;
+    }
+}
+
+#[cfg(target_pointer_width = "64")]
+ffi! {
+    extern "system" {
+        pub fn RtlLookupFunctionEntry(
+            ControlPc: DWORD64,
+            ImageBase: PDWORD64,
+            HistoryTable: PUNWIND_HISTORY_TABLE,
+        ) -> PRUNTIME_FUNCTION;
+    }
+}
+
+#[cfg(target_arch = "aarch64")]
+ffi! {
+    #[repr(C, align(16))]
+    pub struct CONTEXT {
+        pub ContextFlags: DWORD,
+        pub Cpsr: DWORD,
+        pub u: CONTEXT_u,
+        pub Sp: u64,
+        pub Pc: u64,
+        pub V: [ARM64_NT_NEON128; 32],
+        pub Fpcr: DWORD,
+        pub Fpsr: DWORD,
+        pub Bcr: [DWORD; ARM64_MAX_BREAKPOINTS],
+        pub Bvr: [DWORD64; ARM64_MAX_BREAKPOINTS],
+        pub Wcr: [DWORD; ARM64_MAX_WATCHPOINTS],
+        pub Wvr: [DWORD64; ARM64_MAX_WATCHPOINTS],
+    }
+
+    #[repr(C)]
+    pub struct CONTEXT_u {
+        pub s: CONTEXT_u_s,
+    }
+
+    impl CONTEXT_u {
+        pub unsafe fn s(&self) -> &CONTEXT_u_s {
+            &self.s
+        }
+    }
+
+    #[repr(C)]
+    pub struct CONTEXT_u_s {
+        pub X0: u64,
+        pub X1: u64,
+        pub X2: u64,
+        pub X3: u64,
+        pub X4: u64,
+        pub X5: u64,
+        pub X6: u64,
+        pub X7: u64,
+        pub X8: u64,
+        pub X9: u64,
+        pub X10: u64,
+        pub X11: u64,
+        pub X12: u64,
+        pub X13: u64,
+        pub X14: u64,
+        pub X15: u64,
+        pub X16: u64,
+        pub X17: u64,
+        pub X18: u64,
+        pub X19: u64,
+        pub X20: u64,
+        pub X21: u64,
+        pub X22: u64,
+        pub X23: u64,
+        pub X24: u64,
+        pub X25: u64,
+        pub X26: u64,
+        pub X27: u64,
+        pub X28: u64,
+        pub Fp: u64,
+        pub Lr: u64,
+    }
+
+    pub const ARM64_MAX_BREAKPOINTS: usize = 8;
+    pub const ARM64_MAX_WATCHPOINTS: usize = 2;
+
+    #[repr(C)]
+    pub struct ARM64_NT_NEON128 {
+        pub D: [f64; 2],
+    }
+}
+
+#[cfg(target_arch = "x86")]
+ffi! {
+    #[repr(C)]
+    pub struct CONTEXT {
+        pub ContextFlags: DWORD,
+        pub Dr0: DWORD,
+        pub Dr1: DWORD,
+        pub Dr2: DWORD,
+        pub Dr3: DWORD,
+        pub Dr6: DWORD,
+        pub Dr7: DWORD,
+        pub FloatSave: FLOATING_SAVE_AREA,
+        pub SegGs: DWORD,
+        pub SegFs: DWORD,
+        pub SegEs: DWORD,
+        pub SegDs: DWORD,
+        pub Edi: DWORD,
+        pub Esi: DWORD,
+        pub Ebx: DWORD,
+        pub Edx: DWORD,
+        pub Ecx: DWORD,
+        pub Eax: DWORD,
+        pub Ebp: DWORD,
+        pub Eip: DWORD,
+        pub SegCs: DWORD,
+        pub EFlags: DWORD,
+        pub Esp: DWORD,
+        pub SegSs: DWORD,
+        pub ExtendedRegisters: [u8; 512],
+    }
+
+    #[repr(C)]
+    pub struct FLOATING_SAVE_AREA {
+        pub ControlWord: DWORD,
+        pub StatusWord: DWORD,
+        pub TagWord: DWORD,
+        pub ErrorOffset: DWORD,
+        pub ErrorSelector: DWORD,
+        pub DataOffset: DWORD,
+        pub DataSelector: DWORD,
+        pub RegisterArea: [u8; 80],
+        pub Spare0: DWORD,
+    }
+}
+
+#[cfg(target_arch = "x86_64")]
+ffi! {
+    #[repr(C, align(8))]
+    pub struct CONTEXT {
+        pub P1Home: DWORDLONG,
+        pub P2Home: DWORDLONG,
+        pub P3Home: DWORDLONG,
+        pub P4Home: DWORDLONG,
+        pub P5Home: DWORDLONG,
+        pub P6Home: DWORDLONG,
+
+        pub ContextFlags: DWORD,
+        pub MxCsr: DWORD,
+
+        pub SegCs: WORD,
+        pub SegDs: WORD,
+        pub SegEs: WORD,
+        pub SegFs: WORD,
+        pub SegGs: WORD,
+        pub SegSs: WORD,
+        pub EFlags: DWORD,
+
+        pub Dr0: DWORDLONG,
+        pub Dr1: DWORDLONG,
+        pub Dr2: DWORDLONG,
+        pub Dr3: DWORDLONG,
+        pub Dr6: DWORDLONG,
+        pub Dr7: DWORDLONG,
+
+        pub Rax: DWORDLONG,
+        pub Rcx: DWORDLONG,
+        pub Rdx: DWORDLONG,
+        pub Rbx: DWORDLONG,
+        pub Rsp: DWORDLONG,
+        pub Rbp: DWORDLONG,
+        pub Rsi: DWORDLONG,
+        pub Rdi: DWORDLONG,
+        pub R8:  DWORDLONG,
+        pub R9:  DWORDLONG,
+        pub R10: DWORDLONG,
+        pub R11: DWORDLONG,
+        pub R12: DWORDLONG,
+        pub R13: DWORDLONG,
+        pub R14: DWORDLONG,
+        pub R15: DWORDLONG,
+
+        pub Rip: DWORDLONG,
+
+        pub FltSave: FLOATING_SAVE_AREA,
+
+        pub VectorRegister: [M128A; 26],
+        pub VectorControl: DWORDLONG,
+
+        pub DebugControl: DWORDLONG,
+        pub LastBranchToRip: DWORDLONG,
+        pub LastBranchFromRip: DWORDLONG,
+        pub LastExceptionToRip: DWORDLONG,
+        pub LastExceptionFromRip: DWORDLONG,
+    }
+
+    #[repr(C)]
+    pub struct M128A {
+        pub Low: u64,
+        pub High: i64,
+    }
+}
+
+#[repr(C)]
+#[cfg(target_arch = "x86_64")]
+#[derive(Copy, Clone)]
+pub struct FLOATING_SAVE_AREA {
+    _Dummy: [u8; 512],
+}
+
+#[cfg(target_arch = "arm")]
+ffi! {
+    // #[repr(C)]
+    // pub struct NEON128 {
+    //     pub Low: ULONG64,
+    //     pub High: LONG64,
+    // }
+
+    // pub type PNEON128 = *mut NEON128;
+
+    #[repr(C)]
+    pub struct CONTEXT_u {
+        // pub Q: [NEON128; 16],
+        pub D: [ULONG64; 32],
+        // pub S: [DWORD; 32],
+    }
+
+    pub const ARM_MAX_BREAKPOINTS: usize = 8;
+    pub const ARM_MAX_WATCHPOINTS: usize = 1;
+
+    #[repr(C)]
+    pub struct CONTEXT {
+        pub ContextFlags: DWORD,
+        pub R0: DWORD,
+        pub R1: DWORD,
+        pub R2: DWORD,
+        pub R3: DWORD,
+        pub R4: DWORD,
+        pub R5: DWORD,
+        pub R6: DWORD,
+        pub R7: DWORD,
+        pub R8: DWORD,
+        pub R9: DWORD,
+        pub R10: DWORD,
+        pub R11: DWORD,
+        pub R12: DWORD,
+        pub Sp: DWORD,
+        pub Lr: DWORD,
+        pub Pc: DWORD,
+        pub Cpsr: DWORD,
+        pub Fpsrc: DWORD,
+        pub Padding: DWORD,
+        pub u: CONTEXT_u,
+        pub Bvr: [DWORD; ARM_MAX_BREAKPOINTS],
+        pub Bcr: [DWORD; ARM_MAX_BREAKPOINTS],
+        pub Wvr: [DWORD; ARM_MAX_WATCHPOINTS],
+        pub Wcr: [DWORD; ARM_MAX_WATCHPOINTS],
+        pub Padding2: [DWORD; 2],
+    }
+} // IFDEF(arm)
diff --git a/third_party/rust_crates/vendor/backtrace/tests/accuracy/auxiliary.rs b/third_party/rust_crates/vendor/backtrace/tests/accuracy/auxiliary.rs
new file mode 100644
index 0000000..7d04570
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace/tests/accuracy/auxiliary.rs
@@ -0,0 +1,16 @@
+#[inline(never)]
+pub fn callback<F>(f: F)
+where
+    F: FnOnce((&'static str, u32)),
+{
+    f((file!(), line!()))
+}
+
+#[inline(always)]
+#[cfg_attr(feature = "coresymbolication", inline(never))]
+pub fn callback_inlined<F>(f: F)
+where
+    F: FnOnce((&'static str, u32)),
+{
+    f((file!(), line!()))
+}
diff --git a/third_party/rust_crates/vendor/backtrace/tests/accuracy/main.rs b/third_party/rust_crates/vendor/backtrace/tests/accuracy/main.rs
new file mode 100644
index 0000000..7c484a2
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace/tests/accuracy/main.rs
@@ -0,0 +1,92 @@
+mod auxiliary;
+
+macro_rules! pos {
+    () => {
+        (file!(), line!())
+    };
+}
+
+macro_rules! check {
+    ($($pos:expr),*) => ({
+        verify(&[$($pos,)* pos!()]);
+    })
+}
+
+type Pos = (&'static str, u32);
+
+#[test]
+fn doit() {
+    outer(pos!());
+}
+
+#[inline(never)]
+fn outer(main_pos: Pos) {
+    inner(main_pos, pos!());
+    inner_inlined(main_pos, pos!());
+}
+
+#[inline(never)]
+#[rustfmt::skip]
+fn inner(main_pos: Pos, outer_pos: Pos) {
+    check!(main_pos, outer_pos);
+    check!(main_pos, outer_pos);
+    let inner_pos = pos!(); auxiliary::callback(|aux_pos| {
+        check!(main_pos, outer_pos, inner_pos, aux_pos);
+    });
+    let inner_pos = pos!(); auxiliary::callback_inlined(|aux_pos| {
+        check!(main_pos, outer_pos, inner_pos, aux_pos);
+    });
+}
+
+#[inline(always)]
+#[cfg_attr(feature = "coresymbolication", inline(never))]
+#[rustfmt::skip]
+fn inner_inlined(main_pos: Pos, outer_pos: Pos) {
+    check!(main_pos, outer_pos);
+    check!(main_pos, outer_pos);
+
+    #[inline(always)]
+    #[cfg_attr(feature = "coresymbolication", inline(never))]
+    fn inner_further_inlined(main_pos: Pos, outer_pos: Pos, inner_pos: Pos) {
+        check!(main_pos, outer_pos, inner_pos);
+    }
+    inner_further_inlined(main_pos, outer_pos, pos!());
+
+    let inner_pos = pos!(); auxiliary::callback(|aux_pos| {
+        check!(main_pos, outer_pos, inner_pos, aux_pos);
+    });
+    let inner_pos = pos!(); auxiliary::callback_inlined(|aux_pos| {
+        check!(main_pos, outer_pos, inner_pos, aux_pos);
+    });
+
+    // this tests a distinction between two independent calls to the inlined function.
+    // (un)fortunately, LLVM somehow merges two consecutive such calls into one node.
+    inner_further_inlined(main_pos, outer_pos, pos!());
+}
+
+fn verify(filelines: &[Pos]) {
+    let trace = backtrace::Backtrace::new();
+    println!("-----------------------------------");
+    println!("looking for:");
+    for (file, line) in filelines.iter().rev() {
+        println!("\t{}:{}", file, line);
+    }
+    println!("found:\n{:?}", trace);
+    let mut symbols = trace.frames().iter().flat_map(|frame| frame.symbols());
+    let mut iter = filelines.iter().rev();
+    while let Some((file, line)) = iter.next() {
+        loop {
+            let sym = match symbols.next() {
+                Some(sym) => sym,
+                None => panic!("failed to find {}:{}", file, line),
+            };
+            if let Some(filename) = sym.filename() {
+                if let Some(lineno) = sym.lineno() {
+                    if filename.ends_with(file) && lineno == *line {
+                        break;
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/third_party/rust_crates/vendor/backtrace/tests/concurrent-panics.rs b/third_party/rust_crates/vendor/backtrace/tests/concurrent-panics.rs
new file mode 100644
index 0000000..ac1d61d
--- /dev/null
+++ b/third_party/rust_crates/vendor/backtrace/tests/concurrent-panics.rs
@@ -0,0 +1,72 @@
+use std::env;
+use std::panic;
+use std::process::Command;
+use std::sync::atomic::{AtomicBool, Ordering::SeqCst};
+use std::sync::Arc;
+use std::thread;
+
+const PANICS: usize = 100;
+const THREADS: usize = 8;
+const VAR: &str = "__THE_TEST_YOU_ARE_LUKE";
+
+fn main() {
+    // These run in docker containers on CI where they can't re-exec the test,
+    // so just skip these for CI. No other reason this can't run on those
+    // platforms though.
+    if cfg!(unix) && (cfg!(target_arch = "arm") || cfg!(target_arch = "aarch64")) {
+        println!("test result: ok");
+        return;
+    }
+
+    if env::var(VAR).is_err() {
+        parent();
+    } else {
+        child();
+    }
+}
+
+fn parent() {
+    let me = env::current_exe().unwrap();
+    let result = Command::new(&me)
+        .env("RUST_BACKTRACE", "1")
+        .env(VAR, "1")
+        .output()
+        .unwrap();
+    if result.status.success() {
+        println!("test result: ok");
+        return;
+    }
+    println!("stdout:\n{}", String::from_utf8_lossy(&result.stdout));
+    println!("stderr:\n{}", String::from_utf8_lossy(&result.stderr));
+    println!("code: {}", result.status);
+    panic!();
+}
+
+fn child() {
+    let done = Arc::new(AtomicBool::new(false));
+    let done2 = done.clone();
+    let a = thread::spawn(move || {
+        while !done2.load(SeqCst) {
+            format!("{:?}", backtrace::Backtrace::new());
+        }
+    });
+
+    let threads = (0..THREADS)
+        .map(|_| {
+            thread::spawn(|| {
+                for _ in 0..PANICS {
+                    assert!(panic::catch_unwind(|| {
+                        panic!();
+                    })
+                    .is_err());
+                }
+            })
+        })
+        .collect::<Vec<_>>();
+    for thread in threads {
+        thread.join().unwrap();
+    }
+
+    done.store(true, SeqCst);
+    a.join().unwrap();
+}
diff --git a/third_party/rust_crates/vendor/backtrace/tests/long_fn_name.rs b/third_party/rust_crates/vendor/backtrace/tests/long_fn_name.rs
index 862b62e..a565734 100644
--- a/third_party/rust_crates/vendor/backtrace/tests/long_fn_name.rs
+++ b/third_party/rust_crates/vendor/backtrace/tests/long_fn_name.rs
@@ -1,8 +1,5 @@
 extern crate backtrace;
 
-#[cfg(all(windows, feature = "dbghelp"))]
-extern crate winapi;
-
 use backtrace::Backtrace;
 
 // 50-character module name
@@ -12,8 +9,8 @@
     pub struct _234567890_234567890_234567890_234567890_234567890<T>(T);
     impl<T> _234567890_234567890_234567890_234567890_234567890<T> {
         #[allow(dead_code)]
-        pub fn new() -> ::Backtrace {
-            ::Backtrace::new()
+        pub fn new() -> crate::Backtrace {
+            crate::Backtrace::new()
         }
     }
 }
@@ -23,9 +20,7 @@
 #[test]
 #[cfg(all(windows, feature = "dbghelp", target_env = "msvc"))]
 fn test_long_fn_name() {
-    use winapi::um::dbghelp;
-    use _234567890_234567890_234567890_234567890_234567890::
-        _234567890_234567890_234567890_234567890_234567890 as S;
+    use _234567890_234567890_234567890_234567890_234567890::_234567890_234567890_234567890_234567890_234567890 as S;
 
     // 10 repetitions of struct name, so fully qualified function name is
     // atleast 10 * (50 + 50) * 2 = 2000 characters long.
@@ -44,9 +39,7 @@
 
         if let Some(function_name) = symbols[0].name() {
             let function_name = function_name.as_str().unwrap();
-            if function_name.contains(
-                "::_234567890_234567890_234567890_234567890_234567890")
-            {
+            if function_name.contains("::_234567890_234567890_234567890_234567890_234567890") {
                 found_long_name_frame = true;
                 assert!(function_name.len() > 200);
             }
diff --git a/third_party/rust_crates/vendor/backtrace/tests/skip_inner_frames.rs b/third_party/rust_crates/vendor/backtrace/tests/skip_inner_frames.rs
index a7608bc..f5043ee 100644
--- a/third_party/rust_crates/vendor/backtrace/tests/skip_inner_frames.rs
+++ b/third_party/rust_crates/vendor/backtrace/tests/skip_inner_frames.rs
@@ -2,36 +2,48 @@
 
 use backtrace::Backtrace;
 
-const FRAME_RANGE: usize = 128; // should be close enough not to give false positives
+// This test only works on platforms which have a working `symbol_address`
+// function for frames which reports the starting address of a symbol. As a
+// result it's only enabled on a few platforms.
+const ENABLED: bool = cfg!(all(
+    // Windows hasn't really been tested, and OSX doesn't support actually
+    // finding an enclosing frame, so disable this
+    target_os = "linux",
+    // This is the only method currently that supports accurate enough
+    // backtraces for this test to work.
+    feature = "libunwind",
+    // On ARM finding the enclosing function is simply returning the ip itself.
+    not(target_arch = "arm"),
+));
 
 #[test]
-#[cfg_attr(any(not(any(feature = "libunwind", feature = "unix-backtrace", feature = "dbghelp")), all(target_os = "windows", target_arch = "x86")), ignore)]
 fn backtrace_new_unresolved_should_start_with_call_site_trace() {
+    if !ENABLED {
+        return;
+    }
     let mut b = Backtrace::new_unresolved();
     b.resolve();
-	println!("{:?}", b);
-	println!("{:#?}", b);
+    println!("{:?}", b);
 
     assert!(!b.frames().is_empty());
 
     let this_ip = backtrace_new_unresolved_should_start_with_call_site_trace as usize;
-    let frame_ip = b.frames().first().unwrap().ip() as usize;
-
-    assert!(frame_ip >= this_ip);
-    assert!(frame_ip <= this_ip + FRAME_RANGE);
+    println!("this_ip: {:?}", this_ip as *const usize);
+    let frame_ip = b.frames().first().unwrap().symbol_address() as usize;
+    assert_eq!(this_ip, frame_ip);
 }
 
 #[test]
-#[cfg_attr(any(not(any(feature = "libunwind", feature = "unix-backtrace", feature = "dbghelp")), all(target_os = "windows", target_arch = "x86")), ignore)]
 fn backtrace_new_should_start_with_call_site_trace() {
+    if !ENABLED {
+        return;
+    }
     let b = Backtrace::new();
     println!("{:?}", b);
 
     assert!(!b.frames().is_empty());
 
     let this_ip = backtrace_new_should_start_with_call_site_trace as usize;
-    let frame_ip = b.frames().first().unwrap().ip() as usize;
-
-    assert!(frame_ip >= this_ip);
-    assert!(frame_ip <= this_ip + FRAME_RANGE);
+    let frame_ip = b.frames().first().unwrap().symbol_address() as usize;
+    assert_eq!(this_ip, frame_ip);
 }
diff --git a/third_party/rust_crates/vendor/backtrace/tests/smoke.rs b/third_party/rust_crates/vendor/backtrace/tests/smoke.rs
index 6d15b284..7f90d294 100644
--- a/third_party/rust_crates/vendor/backtrace/tests/smoke.rs
+++ b/third_party/rust_crates/vendor/backtrace/tests/smoke.rs
@@ -1,25 +1,24 @@
 extern crate backtrace;
 
-use std::os::raw::c_void;
+use backtrace::Frame;
 use std::thread;
 
 static LIBUNWIND: bool = cfg!(all(unix, feature = "libunwind"));
 static UNIX_BACKTRACE: bool = cfg!(all(unix, feature = "unix-backtrace"));
-static LIBBACKTRACE: bool = cfg!(all(unix, feature = "libbacktrace")) &&
-                            !cfg!(target_os = "fuchsia") && !cfg!(target_os = "macos") &&
-                            !cfg!(target_os = "ios");
-static CORESYMBOLICATION: bool = cfg!(all(any(target_os = "macos", target_os = "ios"),
-                                          feature = "coresymbolication"));
+static LIBBACKTRACE: bool = cfg!(feature = "libbacktrace") && !cfg!(target_os = "fuchsia");
+static CORESYMBOLICATION: bool = cfg!(all(
+    any(target_os = "macos", target_os = "ios"),
+    feature = "coresymbolication"
+));
 static DLADDR: bool = cfg!(all(unix, feature = "dladdr")) && !cfg!(target_os = "fuchsia");
 static DBGHELP: bool = cfg!(all(windows, feature = "dbghelp"));
 static MSVC: bool = cfg!(target_env = "msvc");
-static GIMLI_SYMBOLIZE: bool = cfg!(all(feature = "gimli-symbolize",
-                                        unix,
-                                        target_os = "linux"));
+static GIMLI_SYMBOLIZE: bool = cfg!(all(feature = "gimli-symbolize", unix, target_os = "linux"));
 
 #[test]
 // FIXME: shouldn't ignore this test on i686-msvc, unsure why it's failing
 #[cfg_attr(all(target_arch = "x86", target_env = "msvc"), ignore)]
+#[rustfmt::skip] // we care about line numbers here
 fn smoke_test_frames() {
     frame_1(line!());
     #[inline(never)] fn frame_1(start_line: u32) { frame_2(start_line) }
@@ -28,7 +27,7 @@
     #[inline(never)] fn frame_4(start_line: u32) {
         let mut v = Vec::new();
         backtrace::trace(|cx| {
-            v.push((cx.ip(), cx.symbol_address()));
+            v.push(cx.clone());
             true
         });
 
@@ -36,40 +35,99 @@
             assert!(!LIBUNWIND);
             assert!(!UNIX_BACKTRACE);
             assert!(!DBGHELP);
-            return
+            return;
         }
 
-        // On 32-bit windows apparently the first frame isn't our backtrace
-        // frame but it's actually this frame. I'm not entirely sure why, but at
-        // least it seems consistent?
-        let o = if cfg!(all(windows, target_pointer_width = "32")) {1} else {0};
-        // frame offset 0 is the `backtrace::trace` function, but that's generic
-        assert_frame(&v, o, 1, frame_4 as usize, "frame_4",
-                     "tests/smoke.rs", start_line + 6);
-        assert_frame(&v, o, 2, frame_3 as usize, "frame_3", "tests/smoke.rs",
-                     start_line + 3);
-        assert_frame(&v, o, 3, frame_2 as usize, "frame_2", "tests/smoke.rs",
-                     start_line + 2);
-        assert_frame(&v, o, 4, frame_1 as usize, "frame_1", "tests/smoke.rs",
-                     start_line + 1);
-        assert_frame(&v, o, 5, smoke_test_frames as usize,
-                     "smoke_test_frames", "", 0);
+        // Various platforms have various bits of weirdness about their
+        // backtraces. To find a good starting spot let's search through the
+        // frames
+        let target = frame_4 as usize;
+        let offset = v
+            .iter()
+            .map(|frame| frame.symbol_address() as usize)
+            .enumerate()
+            .filter_map(|(i, sym)| {
+                if sym >= target {
+                    Some((sym, i))
+                } else {
+                    None
+                }
+            })
+            .min()
+            .unwrap()
+            .1;
+        let mut frames = v[offset..].iter();
+
+        assert_frame(
+            frames.next().unwrap(),
+            frame_4 as usize,
+            "frame_4",
+            "tests/smoke.rs",
+            start_line + 6,
+        );
+        assert_frame(
+            frames.next().unwrap(),
+            frame_3 as usize,
+            "frame_3",
+            "tests/smoke.rs",
+            start_line + 3,
+        );
+        assert_frame(
+            frames.next().unwrap(),
+            frame_2 as usize,
+            "frame_2",
+            "tests/smoke.rs",
+            start_line + 2,
+        );
+        assert_frame(
+            frames.next().unwrap(),
+            frame_1 as usize,
+            "frame_1",
+            "tests/smoke.rs",
+            start_line + 1,
+        );
+        assert_frame(
+            frames.next().unwrap(),
+            smoke_test_frames as usize,
+            "smoke_test_frames",
+            "",
+            0,
+        );
     }
 
-    fn assert_frame(syms: &[(*mut c_void, *mut c_void)],
-                    offset: usize,
-                    idx: usize,
-                    actual_fn_pointer: usize,
-                    expected_name: &str,
-                    expected_file: &str,
-                    expected_line: u32) {
-        if offset > idx { return }
-        println!("frame: {}", idx);
-        let (ip, sym) = syms[idx - offset];
-        let ip = ip as usize;
-        let sym = sym as usize;
+    fn assert_frame(
+        frame: &Frame,
+        actual_fn_pointer: usize,
+        expected_name: &str,
+        expected_file: &str,
+        expected_line: u32,
+    ) {
+        backtrace::resolve_frame(frame, |sym| {
+            print!("symbol  ip:{:?} address:{:?} ", frame.ip(), frame.symbol_address());
+            if let Some(name) = sym.name() {
+                print!("name:{} ", name);
+            }
+            if let Some(file) = sym.filename() {
+                print!("file:{} ", file.display());
+            }
+            if let Some(lineno) = sym.lineno() {
+                print!("lineno:{} ", lineno);
+            }
+            println!();
+        });
+
+        let ip = frame.ip() as usize;
+        let sym = frame.symbol_address() as usize;
         assert!(ip >= sym);
-        assert!(sym >= actual_fn_pointer);
+        assert!(
+            sym >= actual_fn_pointer,
+            "{:?} < {:?} ({} {}:{})",
+            sym as *const usize,
+            actual_fn_pointer as *const usize,
+            expected_name,
+            expected_file,
+            expected_line,
+        );
 
         // windows dbghelp is *quite* liberal (and wrong) in many of its reports
         // right now...
@@ -86,13 +144,12 @@
         let mut addr = None;
         let mut line = None;
         let mut file = None;
-        backtrace::resolve(ip as *mut c_void, |sym| {
+        backtrace::resolve_frame(frame, |sym| {
             resolved += 1;
             name = sym.name().map(|v| v.to_string());
             addr = sym.addr();
             line = sym.lineno();
             file = sym.filename().map(|v| v.to_path_buf());
-            println!("  sym: {:?}", name);
         });
 
         // dbghelp doesn't always resolve symbols right now
@@ -103,17 +160,18 @@
 
         // * linux dladdr doesn't work (only consults local symbol table)
         // * windows dbghelp isn't great for GNU
-        if can_resolve &&
-           !(cfg!(target_os = "linux") && DLADDR) &&
-           !(DBGHELP && !MSVC)
-        {
+        if can_resolve && !(cfg!(target_os = "linux") && DLADDR) && !(DBGHELP && !MSVC) {
             let name = name.expect("didn't find a name");
 
             // in release mode names get weird as functions can get merged
             // together with `mergefunc`, so only assert this in debug mode
             if cfg!(debug_assertions) {
-                assert!(name.contains(expected_name),
-                        "didn't find `{}` in `{}`", expected_name, name);
+                assert!(
+                    name.contains(expected_name),
+                    "didn't find `{}` in `{}`",
+                    expected_name,
+                    name
+                );
             }
         }
 
@@ -125,13 +183,21 @@
             let line = line.expect("didn't find a line number");
             let file = file.expect("didn't find a line number");
             if !expected_file.is_empty() {
-                assert!(file.ends_with(expected_file),
-                        "{:?} didn't end with {:?}", file, expected_file);
+                assert!(
+                    file.ends_with(expected_file),
+                    "{:?} didn't end with {:?}",
+                    file,
+                    expected_file
+                );
             }
             if expected_line != 0 {
-                assert!(line == expected_line,
-                        "bad line number on frame for `{}`: {} != {}",
-                        expected_name, line, expected_line);
+                assert!(
+                    line == expected_line,
+                    "bad line number on frame for `{}`: {} != {}",
+                    expected_name,
+                    line,
+                    expected_line
+                );
             }
         }
     }
@@ -139,18 +205,20 @@
 
 #[test]
 fn many_threads() {
-    let threads = (0..16).map(|_| {
-        thread::spawn(|| {
-            for _ in 0..16 {
-                backtrace::trace(|frame| {
-                    backtrace::resolve(frame.ip(), |symbol| {
-                        let _s = symbol.name().map(|s| s.to_string());
+    let threads = (0..16)
+        .map(|_| {
+            thread::spawn(|| {
+                for _ in 0..16 {
+                    backtrace::trace(|frame| {
+                        backtrace::resolve(frame.ip(), |symbol| {
+                            let _s = symbol.name().map(|s| s.to_string());
+                        });
+                        true
                     });
-                    true
-                });
-            }
+                }
+            })
         })
-    }).collect::<Vec<_>>();
+        .collect::<Vec<_>>();
 
     for t in threads {
         t.join().unwrap()
diff --git a/third_party/rust_crates/vendor/enum-as-inner/.cargo-checksum.json b/third_party/rust_crates/vendor/enum-as-inner/.cargo-checksum.json
new file mode 100644
index 0000000..5ad0174
--- /dev/null
+++ b/third_party/rust_crates/vendor/enum-as-inner/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"CODE_OF_CONDUCT.md":"2f1fafd9800e137225d209140dad71c50db0073174f56866a087211e6fc7bc0a","Cargo.toml":"28e3d010300b5ed34785e0852a39efb7774896c5eac30de72163f91ee4095205","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"10d73bf26900fa6dd6f2613bb962b7bd8fa1e66618fcf0f9f899aa071a4ee200","README.md":"3a0b9393a326e92a91fee03ca84a9388ca416e618839e2855b75eaba9a4d208c","copyright.txt":"b54db71f7d0b1f62c8c1b6b297347b81f7c217b4ce7e58223a20d2275535cd17","src/lib.rs":"d77d09a4ce2ce709e43549ab5611063ca5897b945b58b116e011cc7db547525f","tests/basic.rs":"08aa002d55eb0ba75c0891fe1a0ae900eb548d1fdba83b4e61fd0e17e2251175","tests/named.rs":"992ab85c0be143a98f5ed3fb2e8a33aa4633f404f01bfd4504df9459238f90de","tests/snake_case.rs":"7c7aa322813247410ad0533cf5c8a8d2de0d0fad974cba2393124f186928faac","tests/unit.rs":"2a3d522f40735c9ce02bab0448c17c828158c681a70199e3c42ba6c9714b42f3","tests/unnamed.rs":"e6d03aba8041c91cee83c0ff8c8e715c9cb85cd7368f7a44ab2260ecc6d599df"},"package":"900a6c7fbe523f4c2884eaf26b57b81bb69b6810a01a236390a7ac021d09492e"}
\ No newline at end of file
diff --git a/third_party/rust_crates/vendor/enum-as-inner/CODE_OF_CONDUCT.md b/third_party/rust_crates/vendor/enum-as-inner/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000..4055613
--- /dev/null
+++ b/third_party/rust_crates/vendor/enum-as-inner/CODE_OF_CONDUCT.md
@@ -0,0 +1,46 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at benjaminfry@me.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
+
+[homepage]: http://contributor-covenant.org
+[version]: http://contributor-covenant.org/version/1/4/
diff --git a/third_party/rust_crates/vendor/enum-as-inner/Cargo.toml b/third_party/rust_crates/vendor/enum-as-inner/Cargo.toml
new file mode 100644
index 0000000..5f16819
--- /dev/null
+++ b/third_party/rust_crates/vendor/enum-as-inner/Cargo.toml
@@ -0,0 +1,36 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+edition = "2018"
+name = "enum-as-inner"
+version = "0.3.0"
+authors = ["Benjamin Fry <benjaminfry@me.com>"]
+description = "A proc-macro for deriving inner field accessor functions on enums.\n"
+documentation = "https://docs.rs/enum-as-inner"
+readme = "README.md"
+license = "MIT/Apache-2.0"
+repository = "https://github.com/bluejekyll/enum-as-inner"
+
+[lib]
+proc-macro = true
+[dependencies.heck]
+version = "0.3"
+
+[dependencies.proc-macro2]
+version = "1.0"
+
+[dependencies.quote]
+version = "1.0"
+
+[dependencies.syn]
+version = "1.0"
diff --git a/third_party/rust_crates/vendor/enum-as-inner/LICENSE-APACHE b/third_party/rust_crates/vendor/enum-as-inner/LICENSE-APACHE
new file mode 100644
index 0000000..8f71f43
--- /dev/null
+++ b/third_party/rust_crates/vendor/enum-as-inner/LICENSE-APACHE
@@ -0,0 +1,202 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "{}"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright {yyyy} {name of copyright owner}
+
+   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.
+
diff --git a/third_party/rust_crates/vendor/enum-as-inner/LICENSE-MIT b/third_party/rust_crates/vendor/enum-as-inner/LICENSE-MIT
new file mode 100644
index 0000000..b497b09
--- /dev/null
+++ b/third_party/rust_crates/vendor/enum-as-inner/LICENSE-MIT
@@ -0,0 +1,20 @@
+Copyright (c) 2015 The trust-dns Developers
+Copyright (c) 2017 Google LLC.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/third_party/rust_crates/vendor/enum-as-inner/README.md b/third_party/rust_crates/vendor/enum-as-inner/README.md
new file mode 100644
index 0000000..a1ffa57
--- /dev/null
+++ b/third_party/rust_crates/vendor/enum-as-inner/README.md
@@ -0,0 +1,104 @@
+# enum-as-inner
+
+A deriving proc-macro for generating functions to automatically give access to the inner members of enum.
+
+## Basic unnamed field case
+
+The basic case is meant for single item enums, like:
+
+```rust
+#[macro_use]
+extern crate enum_as_inner;
+
+#[derive(Debug, EnumAsInner)]
+enum OneEnum {
+    One(u32),
+}
+```
+
+where the inner item can be retrieved with the `as_*()` or with the `into_*()` functions:
+
+```rust
+let one = OneEnum::One(1);
+
+assert_eq!(*one.as_one().unwrap(), 1);
+assert_eq!(one.into_one().unwrap(), 1);
+```
+
+where the result is either a reference for inner items or a tuple containing the inner items.
+
+## Unit case
+
+This will return copy's of the value of the unit variant, as `isize`:
+
+```rust
+#[macro_use]
+extern crate enum_as_inner;
+
+#[derive(EnumAsInner)]
+enum UnitVariants {
+    Zero,
+    One,
+    Two,
+}
+```
+
+These are not references:
+
+```rust
+let unit = UnitVariants::Two;
+
+assert_eq!(unit.as_two().unwrap(), ());
+```
+
+Note that for unit enums there is no `into_*()` function generated.
+
+## Mutliple, unnamed field case
+
+This will return a tuple of the inner types:
+
+```rust
+#[macro_use]
+extern crate enum_as_inner;
+
+#[derive(Debug, EnumAsInner)]
+enum ManyVariants {
+    One(u32),
+    Two(u32, i32),
+    Three(bool, u32, i64),
+}
+```
+
+And can be accessed like:
+
+```rust
+let many = ManyVariants::Three(true, 1, 2);
+
+assert_eq!(many.as_three().unwrap(), (&true, &1_u32, &2_i64));
+assert_eq!(many.into_three().unwrap(), (true, 1_u32, 2_i64));
+```
+
+## Multiple, named field case
+
+This will return a tuple of the inner types, like the unnamed option:
+
+```rust
+#[macro_use]
+extern crate enum_as_inner;
+
+#[derive(Debug, EnumAsInner)]
+enum ManyVariants {
+    One{ one: u32 },
+    Two{ one: u32, two: i32 },
+    Three{ one: bool, two: u32, three: i64 },
+}
+```
+
+And can be accessed like:
+
+```rust
+let many = ManyVariants::Three{ one: true, two: 1, three: 2 };
+
+assert_eq!(many.as_three().unwrap(), (&true, &1_u32, &2_i64));
+assert_eq!(many.into_three().unwrap(), (true, 1_u32, 2_i64));
+```
\ No newline at end of file
diff --git a/third_party/rust_crates/vendor/enum-as-inner/copyright.txt b/third_party/rust_crates/vendor/enum-as-inner/copyright.txt
new file mode 100644
index 0000000..cdf7e65
--- /dev/null
+++ b/third_party/rust_crates/vendor/enum-as-inner/copyright.txt
@@ -0,0 +1,6 @@
+// Copyright 2015-2018 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
diff --git a/third_party/rust_crates/vendor/enum-as-inner/src/lib.rs b/third_party/rust_crates/vendor/enum-as-inner/src/lib.rs
new file mode 100644
index 0000000..3904ca5
--- /dev/null
+++ b/third_party/rust_crates/vendor/enum-as-inner/src/lib.rs
@@ -0,0 +1,363 @@
+// Copyright 2015-2018 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! # enum-as-inner
+//!
+//! A deriving proc-macro for generating functions to automatically give access to the inner members of enum.
+//!
+//! ## Basic unnamed field case
+//!
+//! The basic case is meant for single item enums, like:
+//!
+//! ```rust
+//! # #[macro_use] extern crate enum_as_inner;
+//! # fn main() {
+//!
+//! #[derive(Debug, EnumAsInner)]
+//! enum OneEnum {
+//!     One(u32),
+//! }
+//!
+//! let one = OneEnum::One(1);
+//!
+//! assert_eq!(*one.as_one().unwrap(), 1);
+//! assert_eq!(one.into_one().unwrap(), 1);
+//! # }
+//! ```
+//!
+//! where the result is either a reference for inner items or a tuple containing the inner items.
+//!
+//! ## Unit case
+//!
+//! This will return copy's of the value of the unit variant, as `isize`:
+//!
+//! ```rust
+//! # #[macro_use] extern crate enum_as_inner;
+//! # fn main() {
+//!
+//! #[derive(EnumAsInner)]
+//! enum UnitVariants {
+//!     Zero,
+//!     One,
+//!     Two,
+//! }
+//!
+//! let unit = UnitVariants::Two;
+//!
+//! assert_eq!(unit.as_two().unwrap(), ());
+//! # }
+//! ```
+//!
+//! Note that for unit enums there is no `into_*()` function generated.
+//!
+//! ## Mutliple, unnamed field case
+//!
+//! This will return a tuple of the inner types:
+//!
+//! ```rust
+//! # #[macro_use] extern crate enum_as_inner;
+//! # fn main() {
+//!
+//! #[derive(Debug, EnumAsInner)]
+//! enum ManyVariants {
+//!     One(u32),
+//!     Two(u32, i32),
+//!     Three(bool, u32, i64),
+//! }
+//!
+//! let many = ManyVariants::Three(true, 1, 2);
+//!
+//! assert_eq!(many.as_three().unwrap(), (&true, &1_u32, &2_i64));
+//! assert_eq!(many.into_three().unwrap(), (true, 1_u32, 2_i64));
+//! # }
+//! ```
+//!
+//! ## Multiple, named field case
+//!
+//! This will return a tuple of the inner types, like the unnamed option:
+//!
+//! ```rust
+//! # #[macro_use] extern crate enum_as_inner;
+//! # fn main() {
+//!
+//! #[derive(Debug, EnumAsInner)]
+//! enum ManyVariants {
+//!     One { one: u32 },
+//!     Two { one: u32, two: i32 },
+//!     Three { one: bool, two: u32, three: i64 },
+//! }
+//!
+//! let many = ManyVariants::Three { one: true, two: 1, three: 2 };
+//!
+//! assert_eq!(many.as_three().unwrap(), (&true, &1_u32, &2_i64));
+//! assert_eq!(many.into_three().unwrap(), (true, 1_u32, 2_i64));
+//! # }
+//! ```
+
+extern crate proc_macro;
+extern crate proc_macro2;
+#[macro_use]
+extern crate syn;
+#[macro_use]
+extern crate quote;
+
+use heck::SnakeCase;
+use proc_macro2::{Ident, Span, TokenStream};
+use syn::DeriveInput;
+
+/// returns first the types to return, the match names, and then tokens to the field accesses
+fn unit_fields_return(
+    name: &syn::Ident,
+    variant_name: &syn::Ident,
+    function_name: &Ident,
+    doc: &str,
+) -> TokenStream {
+    quote!(
+        #[doc = #doc ]
+        pub fn #function_name(&self) -> Option<()> {
+            match self {
+                #name::#variant_name => {
+                    Some(())
+                }
+                _ => None
+            }
+        }
+    )
+}
+
+/// returns first the types to return, the match names, and then tokens to the field accesses
+fn unnamed_fields_return(
+    name: &syn::Ident,
+    variant_name: &syn::Ident,
+    (function_name_ref, doc_ref): (&Ident, &str),
+    (function_name_val, doc_val): (&Ident, &str),
+    fields: &syn::FieldsUnnamed,
+) -> TokenStream {
+    let (returns_ref, returns_val, matches, accesses_ref, accesses_val) = match fields.unnamed.len()
+    {
+        1 => {
+            let field = fields.unnamed.first().expect("no fields on type");
+
+            let returns = &field.ty;
+            let returns_ref = quote!(&#returns);
+            let returns_val = quote!(#returns);
+            let matches = quote!(inner);
+            let accesses_ref = quote!(&inner);
+            let accesses_val = quote!(inner);
+
+            (
+                returns_ref,
+                returns_val,
+                matches,
+                accesses_ref,
+                accesses_val,
+            )
+        }
+        0 => (quote!(()), quote!(()), quote!(), quote!(()), quote!(())),
+        _ => {
+            let mut returns_ref = TokenStream::new();
+            let mut returns_val = TokenStream::new();
+            let mut matches = TokenStream::new();
+            let mut accesses_ref = TokenStream::new();
+            let mut accesses_val = TokenStream::new();
+
+            for (i, field) in fields.unnamed.iter().enumerate() {
+                let rt = &field.ty;
+                let match_name = Ident::new(&format!("match_{}", i), Span::call_site());
+                returns_ref.extend(quote!(&#rt,));
+                returns_val.extend(quote!(#rt,));
+                matches.extend(quote!(#match_name,));
+                accesses_ref.extend(quote!(&#match_name,));
+                accesses_val.extend(quote!(#match_name,));
+            }
+
+            (
+                quote!((#returns_ref)),
+                quote!((#returns_val)),
+                quote!(#matches),
+                quote!((#accesses_ref)),
+                quote!((#accesses_val)),
+            )
+        }
+    };
+
+    quote!(
+        #[doc = #doc_ref ]
+        pub fn #function_name_ref(&self) -> Option<#returns_ref> {
+            match self {
+                #name::#variant_name(#matches) => {
+                    Some(#accesses_ref)
+                }
+                _ => None
+            }
+        }
+
+        #[doc = #doc_val ]
+        pub fn #function_name_val(self) -> ::core::result::Result<#returns_val, Self> {
+            match self {
+                #name::#variant_name(#matches) => {
+                    Ok(#accesses_val)
+                },
+                _ => Err(self)
+            }
+        }
+    )
+}
+
+/// returns first the types to return, the match names, and then tokens to the field accesses
+fn named_fields_return(
+    name: &syn::Ident,
+    variant_name: &syn::Ident,
+    (function_name_ref, doc_ref): (&Ident, &str),
+    (function_name_val, doc_val): (&Ident, &str),
+    fields: &syn::FieldsNamed,
+) -> TokenStream {
+    let (returns_ref, returns_val, matches, accesses_ref, accesses_val) = match fields.named.len() {
+        1 => {
+            let field = fields.named.first().expect("no fields on type");
+            let match_name = field.ident.as_ref().expect("expected a named field");
+
+            let returns = &field.ty;
+            let returns_ref = quote!(&#returns);
+            let returns_val = quote!(#returns);
+            let matches = quote!(#match_name);
+            let accesses_ref = quote!(&#match_name);
+            let accesses_val = quote!(#match_name);
+
+            (
+                returns_ref,
+                returns_val,
+                matches,
+                accesses_ref,
+                accesses_val,
+            )
+        }
+        0 => (quote!(()), quote!(()), quote!(), quote!(()), quote!(())),
+        _ => {
+            let mut returns_ref = TokenStream::new();
+            let mut returns_val = TokenStream::new();
+            let mut matches = TokenStream::new();
+            let mut accesses_ref = TokenStream::new();
+            let mut accesses_val = TokenStream::new();
+
+            for field in fields.named.iter() {
+                let rt = &field.ty;
+                let match_name = field.ident.as_ref().expect("expected a named field");
+
+                returns_ref.extend(quote!(&#rt,));
+                returns_val.extend(quote!(#rt,));
+                matches.extend(quote!(#match_name,));
+                accesses_ref.extend(quote!(&#match_name,));
+                accesses_val.extend(quote!(#match_name,));
+            }
+
+            (
+                quote!((#returns_ref)),
+                quote!((#returns_val)),
+                quote!(#matches),
+                quote!((#accesses_ref)),
+                quote!((#accesses_val)),
+            )
+        }
+    };
+
+    quote!(
+        #[doc = #doc_ref ]
+        pub fn #function_name_ref(&self) -> Option<#returns_ref> {
+            match self {
+                #name::#variant_name{ #matches } => {
+                    Some(#accesses_ref)
+                }
+                _ => None
+            }
+        }
+
+        #[doc = #doc_val ]
+        pub fn #function_name_val(self) -> ::core::result::Result<#returns_val, Self> {
+            match self {
+                #name::#variant_name{ #matches } => {
+                    Ok(#accesses_val)
+                }
+                _ => Err(self)
+            }
+        }
+    )
+}
+
+fn impl_all_as_fns(ast: &DeriveInput) -> TokenStream {
+    let name = &ast.ident;
+
+    let enum_data = if let syn::Data::Enum(data) = &ast.data {
+        data
+    } else {
+        panic!("{} is not an enum", name);
+    };
+
+    let mut stream = TokenStream::new();
+
+    for variant_data in &enum_data.variants {
+        let variant_name = &variant_data.ident;
+        let function_name_ref = Ident::new(
+            &format!("as_{}", variant_name).to_snake_case(),
+            Span::call_site(),
+        );
+        let doc_ref = format!(
+            "Optionally returns references to the inner fields if this is a `{}::{}`, otherwise `None`",
+            name,
+            variant_name,
+        );
+        let function_name_val = Ident::new(
+            &format!("into_{}", variant_name).to_snake_case(),
+            Span::call_site(),
+        );
+        let doc_val = format!(
+            "Returns the inner fields if this is a `{}::{}`, otherwise returns back the enum in the `Err` case of the result",
+            name,
+            variant_name,
+        );
+
+        let tokens = match &variant_data.fields {
+            syn::Fields::Unit => {
+                unit_fields_return(name, variant_name, &function_name_ref, &doc_ref)
+            }
+            syn::Fields::Unnamed(unnamed) => unnamed_fields_return(
+                name,
+                variant_name,
+                (&function_name_ref, &doc_ref),
+                (&function_name_val, &doc_val),
+                &unnamed,
+            ),
+            syn::Fields::Named(named) => named_fields_return(
+                name,
+                variant_name,
+                (&function_name_ref, &doc_ref),
+                (&function_name_val, &doc_val),
+                &named,
+            ),
+        };
+
+        stream.extend(tokens);
+    }
+
+    quote!(
+        impl #name {
+            #stream
+        }
+    )
+}
+
+#[proc_macro_derive(EnumAsInner)]
+pub fn enum_as_inner(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
+    // get a usable token stream
+    let ast: DeriveInput = parse_macro_input!(input as DeriveInput);
+
+    // Build the impl
+    let expanded: TokenStream = impl_all_as_fns(&ast);
+
+    // Return the generated impl
+    proc_macro::TokenStream::from(expanded)
+}
diff --git a/third_party/rust_crates/vendor/enum-as-inner/tests/basic.rs b/third_party/rust_crates/vendor/enum-as-inner/tests/basic.rs
new file mode 100644
index 0000000..ba9c89d
--- /dev/null
+++ b/third_party/rust_crates/vendor/enum-as-inner/tests/basic.rs
@@ -0,0 +1,50 @@
+use enum_as_inner::EnumAsInner;
+
+#[derive(Debug, EnumAsInner)]
+enum EmptyTest {}
+
+#[test]
+fn test_empty() {
+    let empty = None::<EmptyTest>;
+
+    assert!(empty.is_none());
+}
+
+#[derive(Debug, EnumAsInner)]
+enum EmptyParendsTest {
+    Empty(),
+}
+
+#[test]
+fn test_empty_parends() {
+    let empty = EmptyParendsTest::Empty();
+
+    assert_eq!(empty.as_empty().unwrap(), ());
+    assert_eq!(empty.into_empty().unwrap(), ());
+}
+
+#[derive(Debug, EnumAsInner)]
+enum OneTest {
+    One(u32),
+}
+
+#[test]
+fn test_one() {
+    let empty = OneTest::One(1);
+
+    assert_eq!(*empty.as_one().unwrap(), 1);
+    assert_eq!(empty.into_one().unwrap(), 1);
+}
+
+#[derive(Debug, EnumAsInner)]
+enum MultiTest {
+    Multi(u32, u32),
+}
+
+#[test]
+fn test_multi() {
+    let multi = MultiTest::Multi(1, 1);
+
+    assert_eq!(multi.as_multi().unwrap(), (&1_u32, &1_u32));
+    assert_eq!(multi.into_multi().unwrap(), (1_u32, 1_u32));
+}
diff --git a/third_party/rust_crates/vendor/enum-as-inner/tests/named.rs b/third_party/rust_crates/vendor/enum-as-inner/tests/named.rs
new file mode 100644
index 0000000..c73bae1f
--- /dev/null
+++ b/third_party/rust_crates/vendor/enum-as-inner/tests/named.rs
@@ -0,0 +1,47 @@
+use enum_as_inner::EnumAsInner;
+
+#[derive(Debug, EnumAsInner)]
+enum ManyVariants {
+    One { one: u32 },
+    Two { one: u32, two: i32 },
+    Three { one: bool, two: u32, three: i64 },
+}
+
+#[test]
+fn test_one_named() {
+    let many = ManyVariants::One { one: 1 };
+
+    assert!(many.as_one().is_some());
+    assert!(many.as_two().is_none());
+    assert!(many.as_three().is_none());
+
+    assert_eq!(*many.as_one().unwrap(), 1_u32);
+}
+
+#[test]
+fn test_two_named() {
+    let many = ManyVariants::Two { one: 1, two: 2 };
+
+    assert!(many.as_one().is_none());
+    assert!(many.as_two().is_some());
+    assert!(many.as_three().is_none());
+
+    assert_eq!(many.as_two().unwrap(), (&1_u32, &2_i32));
+    assert_eq!(many.into_two().unwrap(), (1_u32, 2_i32));
+}
+
+#[test]
+fn test_three_named() {
+    let many = ManyVariants::Three {
+        one: true,
+        two: 1,
+        three: 2,
+    };
+
+    assert!(many.as_one().is_none());
+    assert!(many.as_two().is_none());
+    assert!(many.as_three().is_some());
+
+    assert_eq!(many.as_three().unwrap(), (&true, &1_u32, &2_i64));
+    assert_eq!(many.into_three().unwrap(), (true, 1_u32, 2_i64));
+}
diff --git a/third_party/rust_crates/vendor/enum-as-inner/tests/snake_case.rs b/third_party/rust_crates/vendor/enum-as-inner/tests/snake_case.rs
new file mode 100644
index 0000000..31db713
--- /dev/null
+++ b/third_party/rust_crates/vendor/enum-as-inner/tests/snake_case.rs
@@ -0,0 +1,46 @@
+use enum_as_inner::EnumAsInner;
+
+#[derive(Debug, EnumAsInner)]
+enum MixedCaseVariants {
+    XMLIsNotCool,
+    #[allow(non_camel_case_types)]
+    Rust_IsCoolThough(u32),
+    YMCA {
+        named: i16,
+    },
+}
+
+#[test]
+fn test_xml_unit() {
+    let mixed = MixedCaseVariants::XMLIsNotCool;
+
+    assert!(mixed.as_xml_is_not_cool().is_some());
+    assert!(mixed.as_rust_is_cool_though().is_none());
+    assert!(mixed.as_ymca().is_none());
+
+    assert_eq!(mixed.as_xml_is_not_cool().unwrap(), ());
+}
+
+#[test]
+fn test_rust_unnamed() {
+    let mixed = MixedCaseVariants::Rust_IsCoolThough(42);
+
+    assert!(mixed.as_xml_is_not_cool().is_none());
+    assert!(mixed.as_rust_is_cool_though().is_some());
+    assert!(mixed.as_ymca().is_none());
+
+    assert_eq!(*mixed.as_rust_is_cool_though().unwrap(), 42);
+    assert_eq!(mixed.into_rust_is_cool_though().unwrap(), 42);
+}
+
+#[test]
+fn test_ymca_named() {
+    let mixed = MixedCaseVariants::YMCA { named: -32_768 };
+
+    assert!(mixed.as_xml_is_not_cool().is_none());
+    assert!(mixed.as_rust_is_cool_though().is_none());
+    assert!(mixed.as_ymca().is_some());
+
+    assert_eq!(*mixed.as_ymca().unwrap(), (-32_768));
+    assert_eq!(mixed.into_ymca().unwrap(), (-32_768));
+}
diff --git a/third_party/rust_crates/vendor/enum-as-inner/tests/unit.rs b/third_party/rust_crates/vendor/enum-as-inner/tests/unit.rs
new file mode 100644
index 0000000..f6c765b
--- /dev/null
+++ b/third_party/rust_crates/vendor/enum-as-inner/tests/unit.rs
@@ -0,0 +1,41 @@
+use enum_as_inner::EnumAsInner;
+
+#[derive(EnumAsInner)]
+enum UnitVariants {
+    Zero,
+    One,
+    Two,
+}
+
+#[test]
+fn test_zero_unit() {
+    let unit = UnitVariants::Zero;
+
+    assert!(unit.as_zero().is_some());
+    assert!(unit.as_one().is_none());
+    assert!(unit.as_two().is_none());
+
+    assert_eq!(unit.as_zero().unwrap(), ());
+}
+
+#[test]
+fn test_one_unit() {
+    let unit = UnitVariants::One;
+
+    assert!(unit.as_zero().is_none());
+    assert!(unit.as_one().is_some());
+    assert!(unit.as_two().is_none());
+
+    assert_eq!(unit.as_one().unwrap(), ());
+}
+
+#[test]
+fn test_two_unit() {
+    let unit = UnitVariants::Two;
+
+    assert!(unit.as_zero().is_none());
+    assert!(unit.as_one().is_none());
+    assert!(unit.as_two().is_some());
+
+    assert_eq!(unit.as_two().unwrap(), ());
+}
diff --git a/third_party/rust_crates/vendor/enum-as-inner/tests/unnamed.rs b/third_party/rust_crates/vendor/enum-as-inner/tests/unnamed.rs
new file mode 100644
index 0000000..15c6efa
--- /dev/null
+++ b/third_party/rust_crates/vendor/enum-as-inner/tests/unnamed.rs
@@ -0,0 +1,44 @@
+use enum_as_inner::EnumAsInner;
+
+#[derive(Debug, EnumAsInner)]
+enum ManyVariants {
+    One(u32),
+    Two(u32, i32),
+    Three(bool, u32, i64),
+}
+
+#[test]
+fn test_one_unnamed() {
+    let many = ManyVariants::One(1);
+
+    assert!(many.as_one().is_some());
+    assert!(many.as_two().is_none());
+    assert!(many.as_three().is_none());
+
+    assert_eq!(*many.as_one().unwrap(), 1_u32);
+    assert_eq!(many.into_one().unwrap(), 1_u32);
+}
+
+#[test]
+fn test_two_unnamed() {
+    let many = ManyVariants::Two(1, 2);
+
+    assert!(many.as_one().is_none());
+    assert!(many.as_two().is_some());
+    assert!(many.as_three().is_none());
+
+    assert_eq!(many.as_two().unwrap(), (&1_u32, &2_i32));
+    assert_eq!(many.into_two().unwrap(), (1_u32, 2_i32));
+}
+
+#[test]
+fn test_three_unnamed() {
+    let many = ManyVariants::Three(true, 1, 2);
+
+    assert!(many.as_one().is_none());
+    assert!(many.as_two().is_none());
+    assert!(many.as_three().is_some());
+
+    assert_eq!(many.as_three().unwrap(), (&true, &1_u32, &2_i64));
+    assert_eq!(many.into_three().unwrap(), (true, 1_u32, 2_i64));
+}
diff --git a/third_party/rust_crates/vendor/fuchsia-zircon-sys/src/definitions.rs b/third_party/rust_crates/vendor/fuchsia-zircon-sys/src/definitions.rs
index 3c51c9b..956313d 100644
--- a/third_party/rust_crates/vendor/fuchsia-zircon-sys/src/definitions.rs
+++ b/third_party/rust_crates/vendor/fuchsia-zircon-sys/src/definitions.rs
@@ -302,12 +302,6 @@
         count: u32
         ) -> zx_status_t;
 
-    pub fn zx_job_set_critical(
-        job: zx_handle_t,
-        options: u32,
-        process: zx_handle_t,
-        ) -> zx_status_t;
-
     pub fn zx_task_bind_exception_port(
         object: zx_handle_t,
         eport: zx_handle_t,
@@ -904,4 +898,6 @@
         b: isize,
         c: isize
         ) -> zx_status_t;
+
+
 }
diff --git a/third_party/rust_crates/vendor/fuchsia-zircon/examples/BUILD.gn b/third_party/rust_crates/vendor/fuchsia-zircon/examples/BUILD.gn
index 1d8913a..dee61f5 100644
--- a/third_party/rust_crates/vendor/fuchsia-zircon/examples/BUILD.gn
+++ b/third_party/rust_crates/vendor/fuchsia-zircon/examples/BUILD.gn
@@ -7,11 +7,11 @@
 package("zircon_rust_examples") {
   system_image = true
 
-  deps = [ "zx_toy" ]
-
-  binaries = [
-    {
-      name = "example_zx_toy"
-    },
+  deps = [
+    "zx_toy",
   ]
+
+  binaries = [ {
+        name = "example_zx_toy"
+      } ]
 }
diff --git a/third_party/rust_crates/vendor/linked-hash-map/.cargo-checksum.json b/third_party/rust_crates/vendor/linked-hash-map/.cargo-checksum.json
new file mode 100644
index 0000000..e1f0ce5
--- /dev/null
+++ b/third_party/rust_crates/vendor/linked-hash-map/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"c3a69bd037a26899920087f3bfbb077f6d618db2a2ff53da2fe8c3475ebfd46b","LICENSE-APACHE":"8173d5c29b4f956d532781d2b86e4e30f83e6b7878dce18c919451d6ba707c90","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"0e489f044f04ca322c451a12c6721496e9b0305036be443c52772622c7e5ef51","src/heapsize.rs":"fe098aa1f79f11af271cb9c0db89d89f45d4e7429d2b6afb5cc18edfd8128a47","src/lib.rs":"d167aec9e73328a27e02ba7ceff81d50e37ecd0d5d8b81c1dc7cdf0a1b16981f","src/serde.rs":"74756da5be8aa5464d4d556964a5839cf0d91b10f5cd9dc724ef0d4f9329c1b4","tests/heapsize.rs":"2d211acb210b675119fd82baa5549c625b939bb9180149aa6c7644715419cdab","tests/serde.rs":"7b9903b5b825eb876c0cc3f979835f27103604a6173c01d6724cfbdb4238266e","tests/test.rs":"3db1290ab859932ed485257076052e1d3512ad78d2788278bb61cd0626ac9fdd"},"package":"ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83"}
\ No newline at end of file
diff --git a/third_party/rust_crates/vendor/linked-hash-map/Cargo.toml b/third_party/rust_crates/vendor/linked-hash-map/Cargo.toml
new file mode 100644
index 0000000..cded159
--- /dev/null
+++ b/third_party/rust_crates/vendor/linked-hash-map/Cargo.toml
@@ -0,0 +1,44 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "linked-hash-map"
+version = "0.5.2"
+authors = ["Stepan Koltsov <stepan.koltsov@gmail.com>", "Andrew Paseltiner <apaseltiner@gmail.com>"]
+exclude = ["/.travis.yml", "/deploy-docs.sh"]
+description = "A HashMap wrapper that holds key-value pairs in insertion order"
+homepage = "https://github.com/contain-rs/linked-hash-map"
+documentation = "https://contain-rs.github.io/linked-hash-map/linked_hash_map"
+readme = "README.md"
+keywords = ["data-structures"]
+license = "MIT/Apache-2.0"
+repository = "https://github.com/contain-rs/linked-hash-map"
+[dependencies.clippy]
+version = "0.*"
+optional = true
+
+[dependencies.heapsize]
+version = "0.4"
+optional = true
+
+[dependencies.serde]
+version = "1.0"
+optional = true
+
+[dependencies.serde_test]
+version = "1.0"
+optional = true
+
+[features]
+heapsize_impl = ["heapsize"]
+nightly = []
+serde_impl = ["serde", "serde_test"]
diff --git a/third_party/rust_crates/vendor/linked-hash-map/LICENSE-APACHE b/third_party/rust_crates/vendor/linked-hash-map/LICENSE-APACHE
new file mode 100644
index 0000000..11069ed
--- /dev/null
+++ b/third_party/rust_crates/vendor/linked-hash-map/LICENSE-APACHE
@@ -0,0 +1,201 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+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.
diff --git a/third_party/rust_crates/vendor/linked-hash-map/LICENSE-MIT b/third_party/rust_crates/vendor/linked-hash-map/LICENSE-MIT
new file mode 100644
index 0000000..e69282e
--- /dev/null
+++ b/third_party/rust_crates/vendor/linked-hash-map/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2015 The Rust Project Developers
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/third_party/rust_crates/vendor/linked-hash-map/README.md b/third_party/rust_crates/vendor/linked-hash-map/README.md
new file mode 100644
index 0000000..fb701eb
--- /dev/null
+++ b/third_party/rust_crates/vendor/linked-hash-map/README.md
@@ -0,0 +1,15 @@
+**WARNING: THIS PROJECT IS IN MAINTENANCE MODE, DUE TO INSUFFICIENT MAINTAINER RESOURCES**
+
+It works fine, but will generally no longer be improved.
+
+We are currently only accepting changes which:
+
+* keep this compiling with the latest versions of Rust or its dependencies.
+* have minimal review requirements, such as documentation changes (so not totally new APIs).
+
+------
+
+
+A HashMap wrapper that holds key-value pairs in insertion order.
+
+Documentation is available at https://contain-rs.github.io/linked-hash-map/linked_hash_map.
diff --git a/third_party/rust_crates/vendor/linked-hash-map/src/heapsize.rs b/third_party/rust_crates/vendor/linked-hash-map/src/heapsize.rs
new file mode 100644
index 0000000..386b787
--- /dev/null
+++ b/third_party/rust_crates/vendor/linked-hash-map/src/heapsize.rs
@@ -0,0 +1,49 @@
+extern crate heapsize;
+
+use self::heapsize::{HeapSizeOf, heap_size_of};
+use std::hash::{Hash, BuildHasher};
+
+use {LinkedHashMap, KeyRef, Node};
+
+impl<K> HeapSizeOf for KeyRef<K> {
+    fn heap_size_of_children(&self) -> usize {
+        0
+    }
+}
+
+impl<K, V> HeapSizeOf for Node<K, V>
+    where K: HeapSizeOf,
+          V: HeapSizeOf
+{
+    fn heap_size_of_children(&self) -> usize {
+        self.key.heap_size_of_children() + self.value.heap_size_of_children()
+    }
+}
+
+impl<K, V, S> HeapSizeOf for LinkedHashMap<K, V, S>
+    where K: HeapSizeOf + Hash + Eq,
+          V: HeapSizeOf,
+          S: BuildHasher
+{
+    fn heap_size_of_children(&self) -> usize {
+        unsafe {
+            let mut size = self.map.heap_size_of_children();
+            for &value in self.map.values() {
+                size += (*value).heap_size_of_children();
+                size += heap_size_of(value as *const _ as *const _);
+            }
+
+            if !self.head.is_null() {
+                size += heap_size_of(self.head as *const _ as *const _);
+            }
+
+            let mut free = self.free;
+            while !free.is_null() {
+                size += heap_size_of(free as *const _ as *const _);
+                free = (*free).next
+            }
+
+            size
+        }
+    }
+}
diff --git a/third_party/rust_crates/vendor/linked-hash-map/src/lib.rs b/third_party/rust_crates/vendor/linked-hash-map/src/lib.rs
new file mode 100644
index 0000000..98ccdb1
--- /dev/null
+++ b/third_party/rust_crates/vendor/linked-hash-map/src/lib.rs
@@ -0,0 +1,1343 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! A `HashMap` wrapper that holds key-value pairs in insertion order.
+//!
+//! # Examples
+//!
+//! ```
+//! use linked_hash_map::LinkedHashMap;
+//!
+//! let mut map = LinkedHashMap::new();
+//! map.insert(2, 20);
+//! map.insert(1, 10);
+//! map.insert(3, 30);
+//! assert_eq!(map[&1], 10);
+//! assert_eq!(map[&2], 20);
+//! assert_eq!(map[&3], 30);
+//!
+//! let items: Vec<(i32, i32)> = map.iter().map(|t| (*t.0, *t.1)).collect();
+//! assert_eq!(items, [(2, 20), (1, 10), (3, 30)]);
+//! ```
+
+#![forbid(missing_docs)]
+#![cfg_attr(all(feature = "nightly", test), feature(test))]
+
+#![cfg_attr(feature = "clippy", feature(plugin))]
+#![cfg_attr(feature = "clippy", plugin(clippy))]
+#![cfg_attr(feature = "clippy", deny(clippy))]
+
+// Optional Serde support
+#[cfg(feature = "serde_impl")]
+pub mod serde;
+// Optional Heapsize support
+#[cfg(feature = "heapsize_impl")]
+mod heapsize;
+
+use std::borrow::Borrow;
+use std::cmp::Ordering;
+use std::collections::hash_map::{self, HashMap};
+use std::fmt;
+use std::hash::{BuildHasher, Hash, Hasher};
+use std::iter;
+use std::marker;
+use std::mem;
+use std::ops::{Index, IndexMut};
+use std::ptr;
+
+struct KeyRef<K> { k: *const K }
+
+struct Node<K, V> {
+    next: *mut Node<K, V>,
+    prev: *mut Node<K, V>,
+    key: K,
+    value: V,
+}
+
+/// A linked hash map.
+pub struct LinkedHashMap<K, V, S = hash_map::RandomState> {
+    map: HashMap<KeyRef<K>, *mut Node<K, V>, S>,
+    head: *mut Node<K, V>,
+    free: *mut Node<K, V>,
+}
+
+impl<K: Hash> Hash for KeyRef<K> {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        unsafe { (*self.k).hash(state) }
+    }
+}
+
+impl<K: PartialEq> PartialEq for KeyRef<K> {
+    fn eq(&self, other: &Self) -> bool {
+        unsafe{ (*self.k).eq(&*other.k) }
+    }
+}
+
+impl<K: Eq> Eq for KeyRef<K> {}
+
+// This type exists only to support borrowing `KeyRef`s, which cannot be borrowed to `Q` directly
+// due to conflicting implementations of `Borrow`. The layout of `&Qey<Q>` must be identical to
+// `&Q` in order to support transmuting in the `Qey::from_ref` method.
+#[derive(Hash, PartialEq, Eq)]
+struct Qey<Q: ?Sized>(Q);
+
+impl<Q: ?Sized> Qey<Q> {
+    fn from_ref(q: &Q) -> &Self { unsafe { mem::transmute(q) } }
+}
+
+impl<K, Q: ?Sized> Borrow<Qey<Q>> for KeyRef<K> where K: Borrow<Q> {
+    fn borrow(&self) -> &Qey<Q> {
+        Qey::from_ref(unsafe { (*self.k).borrow() })
+    }
+}
+
+impl<K, V> Node<K, V> {
+    fn new(k: K, v: V) -> Self {
+        Node {
+            key: k,
+            value: v,
+            next: ptr::null_mut(),
+            prev: ptr::null_mut(),
+        }
+    }
+}
+
+unsafe fn drop_empty_node<K, V>(the_box: *mut Node<K, V>) {
+    // Prevent compiler from trying to drop the un-initialized key and values in the node.
+    let Node { key, value, .. } = *Box::from_raw(the_box);
+    mem::forget(key);
+    mem::forget(value);
+}
+
+impl<K: Hash + Eq, V> LinkedHashMap<K, V> {
+    /// Creates a linked hash map.
+    pub fn new() -> Self { Self::with_map(HashMap::new()) }
+
+    /// Creates an empty linked hash map with the given initial capacity.
+    pub fn with_capacity(capacity: usize) -> Self {
+        Self::with_map(HashMap::with_capacity(capacity))
+    }
+}
+
+impl<K, V, S> LinkedHashMap<K, V, S> {
+    #[inline]
+    fn detach(&mut self, node: *mut Node<K, V>) {
+        unsafe {
+            (*(*node).prev).next = (*node).next;
+            (*(*node).next).prev = (*node).prev;
+        }
+    }
+
+    #[inline]
+    fn attach(&mut self, node: *mut Node<K, V>) {
+        unsafe {
+            (*node).next = (*self.head).next;
+            (*node).prev = self.head;
+            (*self.head).next = node;
+            (*(*node).next).prev = node;
+        }
+    }
+
+    // Caller must check `!self.head.is_null()`
+    unsafe fn drop_entries(&mut self) {
+        let mut cur = (*self.head).next;
+        while cur != self.head {
+            let next = (*cur).next;
+            Box::from_raw(cur);
+            cur = next;
+        }
+    }
+
+    fn clear_free_list(&mut self) {
+        unsafe {
+            let mut free = self.free;
+            while ! free.is_null() {
+                let next_free = (*free).next;
+                drop_empty_node(free);
+                free = next_free;
+            }
+            self.free = ptr::null_mut();
+        }
+    }
+
+    fn ensure_guard_node(&mut self) {
+        if self.head.is_null() {
+            // allocate the guard node if not present
+            unsafe {
+                self.head = Box::into_raw(Box::new(mem::uninitialized()));
+                (*self.head).next = self.head;
+                (*self.head).prev = self.head;
+            }
+        }
+    }
+}
+
+impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
+    fn with_map(map: HashMap<KeyRef<K>, *mut Node<K, V>, S>) -> Self {
+        LinkedHashMap {
+            map: map,
+            head: ptr::null_mut(),
+            free: ptr::null_mut(),
+        }
+    }
+
+    /// Creates an empty linked hash map with the given initial hash builder.
+    pub fn with_hasher(hash_builder: S) -> Self {
+        Self::with_map(HashMap::with_hasher(hash_builder))
+    }
+
+    /// Creates an empty linked hash map with the given initial capacity and hash builder.
+    pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> Self {
+        Self::with_map(HashMap::with_capacity_and_hasher(capacity, hash_builder))
+    }
+
+    /// Reserves capacity for at least `additional` more elements to be inserted into the map. The
+    /// map may reserve more space to avoid frequent allocations.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the new allocation size overflows `usize.`
+    pub fn reserve(&mut self, additional: usize) { self.map.reserve(additional); }
+
+    /// Shrinks the capacity of the map as much as possible. It will drop down as much as possible
+    /// while maintaining the internal rules and possibly leaving some space in accordance with the
+    /// resize policy.
+    pub fn shrink_to_fit(&mut self) {
+        self.map.shrink_to_fit();
+        self.clear_free_list();
+    }
+
+    /// Gets the given key's corresponding entry in the map for in-place manipulation.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use linked_hash_map::LinkedHashMap;
+    ///
+    /// let mut letters = LinkedHashMap::new();
+    ///
+    /// for ch in "a short treatise on fungi".chars() {
+    ///     let counter = letters.entry(ch).or_insert(0);
+    ///     *counter += 1;
+    /// }
+    ///
+    /// assert_eq!(letters[&'s'], 2);
+    /// assert_eq!(letters[&'t'], 3);
+    /// assert_eq!(letters[&'u'], 1);
+    /// assert_eq!(letters.get(&'y'), None);
+    /// ```
+    pub fn entry(&mut self, k: K) -> Entry<K, V, S> {
+        let self_ptr: *mut Self = self;
+
+        if let Some(entry) = self.map.get_mut(&KeyRef{k: &k}) {
+            return Entry::Occupied(OccupiedEntry {
+                entry: *entry,
+                map: self_ptr,
+                marker: marker::PhantomData,
+            });
+        }
+
+        Entry::Vacant(VacantEntry {
+            key: k,
+            map: self,
+        })
+    }
+
+    /// Returns an iterator visiting all entries in insertion order.
+    /// Iterator element type is `OccupiedEntry<K, V, S>`. Allows for removal
+    /// as well as replacing the entry.
+    ///
+    /// # Examples
+    /// ```
+    /// use linked_hash_map::LinkedHashMap;
+    ///
+    /// let mut map = LinkedHashMap::new();
+    /// map.insert("a", 10);
+    /// map.insert("c", 30);
+    /// map.insert("b", 20);
+    ///
+    /// {
+    ///     let mut iter = map.entries();
+    ///     let mut entry = iter.next().unwrap();
+    ///     assert_eq!(&"a", entry.key());
+    ///     *entry.get_mut() = 17;
+    /// }
+    ///
+    /// assert_eq!(&17, map.get(&"a").unwrap());
+    /// ```
+    pub fn entries(&mut self) -> Entries<K, V, S> {
+        let head = if ! self.head.is_null() {
+            unsafe { (*self.head).prev }
+        } else {
+            ptr::null_mut()
+        };
+        Entries {
+            map: self,
+            head: head,
+            remaining: self.len(),
+            marker: marker::PhantomData,
+        }
+    }
+
+    /// Inserts a key-value pair into the map. If the key already existed, the old value is
+    /// returned.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use linked_hash_map::LinkedHashMap;
+    /// let mut map = LinkedHashMap::new();
+    ///
+    /// map.insert(1, "a");
+    /// map.insert(2, "b");
+    /// assert_eq!(map[&1], "a");
+    /// assert_eq!(map[&2], "b");
+    /// ```
+    pub fn insert(&mut self, k: K, v: V) -> Option<V> {
+        self.ensure_guard_node();
+
+        let (node, old_val) = match self.map.get(&KeyRef{k: &k}) {
+            Some(node) => {
+                let old_val = unsafe { ptr::replace(&mut (**node).value, v) };
+                (*node, Some(old_val))
+            }
+            None => {
+                let node = if self.free.is_null() {
+                    Box::into_raw(Box::new(Node::new(k, v)))
+                } else {
+                    // use a recycled box
+                    unsafe {
+                        let free = self.free;
+                        self.free = (*free).next;
+                        ptr::write(free, Node::new(k, v));
+                        free
+                    }
+                };
+                (node, None)
+            }
+        };
+        match old_val {
+            Some(_) => {
+                // Existing node, just update LRU position
+                self.detach(node);
+                self.attach(node);
+            }
+            None => {
+                let keyref = unsafe { &(*node).key };
+                self.map.insert(KeyRef{k: keyref}, node);
+                self.attach(node);
+            }
+        }
+        old_val
+    }
+
+    /// Checks if the map contains the given key.
+    pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool where K: Borrow<Q>, Q: Eq + Hash {
+        self.map.contains_key(Qey::from_ref(k))
+    }
+
+    /// Returns the value corresponding to the key in the map.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use linked_hash_map::LinkedHashMap;
+    /// let mut map = LinkedHashMap::new();
+    ///
+    /// map.insert(1, "a");
+    /// map.insert(2, "b");
+    /// map.insert(2, "c");
+    /// map.insert(3, "d");
+    ///
+    /// assert_eq!(map.get(&1), Some(&"a"));
+    /// assert_eq!(map.get(&2), Some(&"c"));
+    /// ```
+    pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V> where K: Borrow<Q>, Q: Eq + Hash {
+        self.map.get(Qey::from_ref(k)).map(|e| unsafe { &(**e).value })
+    }
+
+    /// Returns the mutable reference corresponding to the key in the map.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use linked_hash_map::LinkedHashMap;
+    /// let mut map = LinkedHashMap::new();
+    ///
+    /// map.insert(1, "a");
+    /// map.insert(2, "b");
+    ///
+    /// *map.get_mut(&1).unwrap() = "c";
+    /// assert_eq!(map.get(&1), Some(&"c"));
+    /// ```
+    pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V> where K: Borrow<Q>, Q: Eq + Hash {
+        self.map.get(Qey::from_ref(k)).map(|e| unsafe { &mut (**e).value })
+    }
+
+    /// Returns the value corresponding to the key in the map.
+    ///
+    /// If value is found, it is moved to the end of the list.
+    /// This operation can be used in implemenation of LRU cache.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use linked_hash_map::LinkedHashMap;
+    /// let mut map = LinkedHashMap::new();
+    ///
+    /// map.insert(1, "a");
+    /// map.insert(2, "b");
+    /// map.insert(3, "d");
+    ///
+    /// assert_eq!(map.get_refresh(&2), Some(&mut "b"));
+    ///
+    /// assert_eq!((&2, &"b"), map.iter().rev().next().unwrap());
+    /// ```
+    pub fn get_refresh<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V> where K: Borrow<Q>, Q: Eq + Hash {
+        let (value, node_ptr_opt) = match self.map.get(Qey::from_ref(k)) {
+            None => (None, None),
+            Some(node) => {
+                (Some(unsafe { &mut (**node).value }), Some(*node))
+            }
+        };
+        if let Some(node_ptr) = node_ptr_opt {
+            self.detach(node_ptr);
+            self.attach(node_ptr);
+        }
+        value
+    }
+
+    /// Removes and returns the value corresponding to the key from the map.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use linked_hash_map::LinkedHashMap;
+    /// let mut map = LinkedHashMap::new();
+    ///
+    /// map.insert(2, "a");
+    ///
+    /// assert_eq!(map.remove(&1), None);
+    /// assert_eq!(map.remove(&2), Some("a"));
+    /// assert_eq!(map.remove(&2), None);
+    /// assert_eq!(map.len(), 0);
+    /// ```
+    pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V> where K: Borrow<Q>, Q: Eq + Hash {
+        let removed = self.map.remove(Qey::from_ref(k));
+        removed.map(|node| {
+            self.detach(node);
+            unsafe {
+                // add to free list
+                (*node).next = self.free;
+                self.free = node;
+                // drop the key and return the value
+                drop(ptr::read(&(*node).key));
+                ptr::read(&(*node).value)
+            }
+        })
+    }
+
+    /// Returns the maximum number of key-value pairs the map can hold without reallocating.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use linked_hash_map::LinkedHashMap;
+    /// let mut map: LinkedHashMap<i32, &str> = LinkedHashMap::new();
+    /// let capacity = map.capacity();
+    /// ```
+    pub fn capacity(&self) -> usize {
+        self.map.capacity()
+    }
+
+    /// Removes the first entry.
+    ///
+    /// Can be used in implementation of LRU cache.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use linked_hash_map::LinkedHashMap;
+    /// let mut map = LinkedHashMap::new();
+    /// map.insert(1, 10);
+    /// map.insert(2, 20);
+    /// map.pop_front();
+    /// assert_eq!(map.get(&1), None);
+    /// assert_eq!(map.get(&2), Some(&20));
+    /// ```
+    #[inline]
+    pub fn pop_front(&mut self) -> Option<(K, V)> {
+        if self.is_empty() {
+            return None
+        }
+        let lru = unsafe { (*self.head).prev };
+        self.detach(lru);
+        self.map
+            .remove(&KeyRef{k: unsafe { &(*lru).key }})
+            .map(|e| {
+                let e = *unsafe { Box::from_raw(e) };
+                (e.key, e.value)
+            })
+    }
+
+    /// Gets the first entry.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use linked_hash_map::LinkedHashMap;
+    /// let mut map = LinkedHashMap::new();
+    /// map.insert(1, 10);
+    /// map.insert(2, 20);
+    /// assert_eq!(map.front(), Some((&1, &10)));
+    /// ```
+    #[inline]
+    pub fn front(&self) -> Option<(&K, &V)> {
+        if self.is_empty() {
+            return None
+        }
+        let lru = unsafe { (*self.head).prev };
+        self.map
+            .get(&KeyRef{k: unsafe { &(*lru).key }})
+            .map(|e| unsafe { (&(**e).key, &(**e).value) })
+    }
+
+    /// Removes the last entry.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use linked_hash_map::LinkedHashMap;
+    /// let mut map = LinkedHashMap::new();
+    /// map.insert(1, 10);
+    /// map.insert(2, 20);
+    /// map.pop_back();
+    /// assert_eq!(map.get(&1), Some(&10));
+    /// assert_eq!(map.get(&2), None);
+    /// ```
+    #[inline]
+    pub fn pop_back(&mut self) -> Option<(K, V)> {
+        if self.is_empty() {
+            return None
+        }
+        let mru = unsafe { (*self.head).next };
+        self.detach(mru);
+        self.map
+            .remove(&KeyRef{k: unsafe { &(*mru).key }})
+            .map(|e| {
+                let e = *unsafe { Box::from_raw(e) };
+                (e.key, e.value)
+            })
+    }
+
+    /// Gets the last entry.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use linked_hash_map::LinkedHashMap;
+    /// let mut map = LinkedHashMap::new();
+    /// map.insert(1, 10);
+    /// map.insert(2, 20);
+    /// assert_eq!(map.back(), Some((&2, &20)));
+    /// ```
+    #[inline]
+    pub fn back(&mut self) -> Option<(&K, &V)> {
+        if self.is_empty() {
+            return None
+        }
+        let mru = unsafe { (*self.head).next };
+        self.map
+            .get(&KeyRef{k: unsafe { &(*mru).key }})
+            .map(|e| unsafe { (&(**e).key, &(**e).value) })
+    }
+
+    /// Returns the number of key-value pairs in the map.
+    pub fn len(&self) -> usize { self.map.len() }
+
+    /// Returns whether the map is currently empty.
+    pub fn is_empty(&self) -> bool { self.len() == 0 }
+
+    /// Returns a reference to the map's hasher.
+    pub fn hasher(&self) -> &S {
+        self.map.hasher()
+    }
+
+    /// Clears the map of all key-value pairs.
+    pub fn clear(&mut self) {
+        self.map.clear();
+        // update the guard node if present
+        if ! self.head.is_null() {
+            unsafe {
+                self.drop_entries();
+                (*self.head).prev = self.head;
+                (*self.head).next = self.head;
+            }
+        }
+    }
+
+    /// Returns a double-ended iterator visiting all key-value pairs in order of insertion.
+    /// Iterator element type is `(&'a K, &'a V)`
+    ///
+    /// # Examples
+    /// ```
+    /// use linked_hash_map::LinkedHashMap;
+    ///
+    /// let mut map = LinkedHashMap::new();
+    /// map.insert("a", 10);
+    /// map.insert("c", 30);
+    /// map.insert("b", 20);
+    ///
+    /// let mut iter = map.iter();
+    /// assert_eq!((&"a", &10), iter.next().unwrap());
+    /// assert_eq!((&"c", &30), iter.next().unwrap());
+    /// assert_eq!((&"b", &20), iter.next().unwrap());
+    /// assert_eq!(None, iter.next());
+    /// ```
+    pub fn iter(&self) -> Iter<K, V> {
+        let head = if self.head.is_null() {
+            ptr::null_mut()
+        } else {
+            unsafe { (*self.head).prev }
+        };
+        Iter {
+            head: head,
+            tail: self.head,
+            remaining: self.len(),
+            marker: marker::PhantomData,
+        }
+    }
+
+    /// Returns a double-ended iterator visiting all key-value pairs in order of insertion.
+    /// Iterator element type is `(&'a K, &'a mut V)`
+    /// # Examples
+    /// ```
+    /// use linked_hash_map::LinkedHashMap;
+    ///
+    /// let mut map = LinkedHashMap::new();
+    /// map.insert("a", 10);
+    /// map.insert("c", 30);
+    /// map.insert("b", 20);
+    ///
+    /// {
+    ///     let mut iter = map.iter_mut();
+    ///     let mut entry = iter.next().unwrap();
+    ///     assert_eq!(&"a", entry.0);
+    ///     *entry.1 = 17;
+    /// }
+    ///
+    /// assert_eq!(&17, map.get(&"a").unwrap());
+    /// ```
+    pub fn iter_mut(&mut self) -> IterMut<K, V> {
+        let head = if self.head.is_null() {
+            ptr::null_mut()
+        } else {
+            unsafe { (*self.head).prev }
+        };
+        IterMut {
+            head: head,
+            tail: self.head,
+            remaining: self.len(),
+            marker: marker::PhantomData,
+        }
+    }
+
+    /// Returns a double-ended iterator visiting all key in order of insertion.
+    ///
+    /// # Examples
+    /// ```
+    /// use linked_hash_map::LinkedHashMap;
+    ///
+    /// let mut map = LinkedHashMap::new();
+    /// map.insert('a', 10);
+    /// map.insert('c', 30);
+    /// map.insert('b', 20);
+    ///
+    /// let mut keys = map.keys();
+    /// assert_eq!(&'a', keys.next().unwrap());
+    /// assert_eq!(&'c', keys.next().unwrap());
+    /// assert_eq!(&'b', keys.next().unwrap());
+    /// assert_eq!(None, keys.next());
+    /// ```
+    pub fn keys(&self) -> Keys<K, V> {
+        Keys { inner: self.iter() }
+    }
+
+    /// Returns a double-ended iterator visiting all values in order of insertion.
+    ///
+    /// # Examples
+    /// ```
+    /// use linked_hash_map::LinkedHashMap;
+    ///
+    /// let mut map = LinkedHashMap::new();
+    /// map.insert('a', 10);
+    /// map.insert('c', 30);
+    /// map.insert('b', 20);
+    ///
+    /// let mut values = map.values();
+    /// assert_eq!(&10, values.next().unwrap());
+    /// assert_eq!(&30, values.next().unwrap());
+    /// assert_eq!(&20, values.next().unwrap());
+    /// assert_eq!(None, values.next());
+    /// ```
+    pub fn values(&self) -> Values<K, V> {
+        Values { inner: self.iter() }
+    }
+}
+
+impl<'a, K, V, S, Q: ?Sized> Index<&'a Q> for LinkedHashMap<K, V, S>
+    where K: Hash + Eq + Borrow<Q>, S: BuildHasher, Q: Eq + Hash
+{
+    type Output = V;
+
+    fn index(&self, index: &'a Q) -> &V {
+        self.get(index).expect("no entry found for key")
+    }
+}
+
+impl<'a, K, V, S, Q: ?Sized> IndexMut<&'a Q> for LinkedHashMap<K, V, S>
+    where K: Hash + Eq + Borrow<Q>, S: BuildHasher, Q: Eq + Hash
+{
+    fn index_mut(&mut self, index: &'a Q) -> &mut V {
+        self.get_mut(index).expect("no entry found for key")
+    }
+}
+
+impl<K: Hash + Eq + Clone, V: Clone, S: BuildHasher + Clone> Clone for LinkedHashMap<K, V, S> {
+    fn clone(&self) -> Self {
+        let mut map = Self::with_hasher(self.map.hasher().clone());
+        map.extend(self.iter().map(|(k, v)| (k.clone(), v.clone())));
+        map
+    }
+}
+
+impl<K: Hash + Eq, V, S: BuildHasher + Default> Default for LinkedHashMap<K, V, S> {
+    fn default() -> Self { Self::with_hasher(S::default()) }
+}
+
+impl<K: Hash + Eq, V, S: BuildHasher> Extend<(K, V)> for LinkedHashMap<K, V, S> {
+    fn extend<I: IntoIterator<Item=(K, V)>>(&mut self, iter: I) {
+        for (k, v) in iter {
+            self.insert(k, v);
+        }
+    }
+}
+
+impl<'a, K, V, S> Extend<(&'a K, &'a V)> for LinkedHashMap<K, V, S>
+    where K: 'a + Hash + Eq + Copy, V: 'a + Copy, S: BuildHasher,
+{
+    fn extend<I: IntoIterator<Item = (&'a K, &'a V)>>(&mut self, iter: I) {
+        for (&k, &v) in iter {
+            self.insert(k, v);
+        }
+    }
+}
+
+impl<K: Hash + Eq, V, S: BuildHasher + Default> iter::FromIterator<(K, V)> for LinkedHashMap<K, V, S> {
+    fn from_iter<I: IntoIterator<Item=(K, V)>>(iter: I) -> Self {
+        let iter = iter.into_iter();
+        let mut map = Self::with_capacity_and_hasher(iter.size_hint().0, S::default());
+        map.extend(iter);
+        map
+    }
+}
+
+impl<A: fmt::Debug + Hash + Eq, B: fmt::Debug, S: BuildHasher> fmt::Debug for LinkedHashMap<A, B, S> {
+    /// Returns a string that lists the key-value pairs in insertion order.
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_map().entries(self).finish()
+    }
+}
+
+impl<K: Hash + Eq, V: PartialEq, S: BuildHasher> PartialEq for LinkedHashMap<K, V, S> {
+    fn eq(&self, other: &Self) -> bool {
+        self.len() == other.len() && self.iter().eq(other)
+    }
+}
+
+impl<K: Hash + Eq, V: Eq, S: BuildHasher> Eq for LinkedHashMap<K, V, S> {}
+
+impl<K: Hash + Eq + PartialOrd, V: PartialOrd, S: BuildHasher> PartialOrd for LinkedHashMap<K, V, S> {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        self.iter().partial_cmp(other)
+    }
+
+    fn lt(&self, other: &Self) -> bool {
+        self.iter().lt(other)
+    }
+
+    fn le(&self, other: &Self) -> bool {
+        self.iter().le(other)
+    }
+
+    fn ge(&self, other: &Self) -> bool {
+        self.iter().ge(other)
+    }
+
+    fn gt(&self, other: &Self) -> bool {
+        self.iter().gt(other)
+    }
+}
+
+impl<K: Hash + Eq + Ord, V: Ord, S: BuildHasher> Ord for LinkedHashMap<K, V, S> {
+    fn cmp(&self, other: &Self) -> Ordering {
+        self.iter().cmp(other)
+    }
+}
+
+impl<K: Hash + Eq, V: Hash, S: BuildHasher> Hash for LinkedHashMap<K, V, S> {
+    fn hash<H: Hasher>(&self, h: &mut H) { for e in self.iter() { e.hash(h); } }
+}
+
+unsafe impl<K: Send, V: Send, S: Send> Send for LinkedHashMap<K, V, S> {}
+
+unsafe impl<K: Sync, V: Sync, S: Sync> Sync for LinkedHashMap<K, V, S> {}
+
+impl<K, V, S> Drop for LinkedHashMap<K, V, S> {
+    fn drop(&mut self) {
+        if !self.head.is_null() {
+            unsafe {
+                self.drop_entries();
+                drop_empty_node(self.head);
+            }
+        }
+        self.clear_free_list();
+    }
+}
+
+/// An insertion-order iterator over a `LinkedHashMap`'s entries, with immutable references to the
+/// values.
+pub struct Iter<'a, K: 'a, V: 'a> {
+    head: *const Node<K, V>,
+    tail: *const Node<K, V>,
+    remaining: usize,
+    marker: marker::PhantomData<(&'a K, &'a V)>,
+}
+
+/// An insertion-order iterator over a `LinkedHashMap`'s entries, with mutable references to the
+/// values.
+pub struct IterMut<'a, K: 'a, V: 'a> {
+    head: *mut Node<K, V>,
+    tail: *mut Node<K, V>,
+    remaining: usize,
+    marker: marker::PhantomData<(&'a K, &'a mut V)>,
+}
+
+/// A consuming insertion-order iterator over a `LinkedHashMap`'s entries.
+pub struct IntoIter<K, V> {
+    head: *mut Node<K, V>,
+    tail: *mut Node<K, V>,
+    remaining: usize,
+    marker: marker::PhantomData<(K, V)>,
+}
+
+/// An insertion-order iterator over a `LinkedHashMap`'s entries represented as
+/// an `OccupiedEntry`.
+pub struct Entries<'a, K: 'a, V: 'a, S: 'a = hash_map::RandomState> {
+    map: *mut LinkedHashMap<K, V, S>,
+    head: *mut Node<K, V>,
+    remaining: usize,
+    marker: marker::PhantomData<(&'a K, &'a mut V, &'a S)>,
+}
+
+unsafe impl<'a, K, V> Send for Iter<'a, K, V> where K: Send, V: Send {}
+
+unsafe impl<'a, K, V> Send for IterMut<'a, K, V> where K: Send, V: Send {}
+
+unsafe impl<K, V> Send for IntoIter<K, V> where K: Send, V: Send {}
+
+unsafe impl<'a, K, V, S> Send for Entries<'a, K, V, S> where K: Send, V: Send, S: Send {}
+
+unsafe impl<'a, K, V> Sync for Iter<'a, K, V> where K: Sync, V: Sync {}
+
+unsafe impl<'a, K, V> Sync for IterMut<'a, K, V> where K: Sync, V: Sync {}
+
+unsafe impl<K, V> Sync for IntoIter<K, V> where K: Sync, V: Sync {}
+
+unsafe impl<'a, K, V, S> Sync for Entries<'a, K, V, S> where K: Sync, V: Sync, S: Sync {}
+
+impl<'a, K, V> Clone for Iter<'a, K, V> {
+    fn clone(&self) -> Self { Iter { ..*self } }
+}
+
+impl<K, V> Clone for IntoIter<K, V> where K: Clone, V: Clone {
+    fn clone(&self) -> Self {
+        if self.remaining == 0 {
+            return IntoIter { ..*self }
+        }
+
+        fn clone_node<K, V>(e: *mut Node<K, V>) -> *mut Node<K, V>
+            where K: Clone, V: Clone,
+        {
+            Box::into_raw(Box::new(Node::new(
+                unsafe { (*e).key.clone() }, unsafe { (*e).value.clone() }
+            )))
+        }
+
+        let mut cur = self.head;
+        let head = clone_node(cur);
+        let mut tail = head;
+        for _ in 1..self.remaining {
+            unsafe {
+                (*tail).prev = clone_node((*cur).prev);
+                (*(*tail).prev).next = tail;
+                tail = (*tail).prev;
+                cur = (*cur).prev;
+            }
+        }
+
+        IntoIter {
+            head: head,
+            tail: tail,
+            remaining: self.remaining,
+            marker: marker::PhantomData,
+        }
+    }
+}
+
+impl<'a, K, V> Iterator for Iter<'a, K, V> {
+    type Item = (&'a K, &'a V);
+
+    fn next(&mut self) -> Option<(&'a K, &'a V)> {
+        if self.head == self.tail {
+            None
+        } else {
+            self.remaining -= 1;
+            unsafe {
+                let r = Some((&(*self.head).key, &(*self.head).value));
+                self.head = (*self.head).prev;
+                r
+            }
+        }
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (self.remaining, Some(self.remaining))
+    }
+}
+
+impl<'a, K, V> Iterator for IterMut<'a, K, V> {
+    type Item = (&'a K, &'a mut V);
+
+    fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
+        if self.head == self.tail {
+            None
+        } else {
+            self.remaining -= 1;
+            unsafe {
+                let r = Some((&(*self.head).key, &mut (*self.head).value));
+                self.head = (*self.head).prev;
+                r
+            }
+        }
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (self.remaining, Some(self.remaining))
+    }
+}
+
+impl<K, V> Iterator for IntoIter<K, V> {
+    type Item = (K, V);
+
+    fn next(&mut self) -> Option<(K, V)> {
+        if self.remaining == 0 {
+            return None
+        }
+        self.remaining -= 1;
+        unsafe {
+            let prev = (*self.head).prev;
+            let e = *Box::from_raw(self.head);
+            self.head = prev;
+            Some((e.key, e.value))
+        }
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (self.remaining, Some(self.remaining))
+    }
+}
+
+impl<'a, K, V, S: BuildHasher> Iterator for Entries<'a, K, V, S> {
+    type Item = OccupiedEntry<'a, K, V, S>;
+
+    fn next(&mut self) -> Option<OccupiedEntry<'a, K, V, S>> {
+        if self.remaining == 0 {
+            None
+        } else {
+            self.remaining -= 1;
+            unsafe {
+                let r = Some(OccupiedEntry {
+                    map: self.map,
+                    entry: self.head,
+                    marker: marker::PhantomData,
+                });
+
+                self.head = (*self.head).prev;
+                r
+            }
+        }
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (self.remaining, Some(self.remaining))
+    }
+}
+
+impl<'a, K, V> DoubleEndedIterator for Iter<'a, K, V> {
+    fn next_back(&mut self) -> Option<(&'a K, &'a V)> {
+        if self.head == self.tail {
+            None
+        } else {
+            self.remaining -= 1;
+            unsafe {
+                self.tail = (*self.tail).next;
+                Some((&(*self.tail).key, &(*self.tail).value))
+            }
+        }
+    }
+}
+
+impl<'a, K, V> DoubleEndedIterator for IterMut<'a, K, V> {
+    fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> {
+        if self.head == self.tail {
+            None
+        } else {
+            self.remaining -= 1;
+            unsafe {
+                self.tail = (*self.tail).next;
+                Some((&(*self.tail).key, &mut (*self.tail).value))
+            }
+        }
+    }
+}
+
+impl<K, V> DoubleEndedIterator for IntoIter<K, V> {
+    fn next_back(&mut self) -> Option<(K, V)> {
+        if self.remaining == 0 {
+            return None
+        }
+        self.remaining -= 1;
+        unsafe {
+            let next = (*self.tail).next;
+            let e = *Box::from_raw(self.tail);
+            self.tail = next;
+            Some((e.key, e.value))
+        }
+    }
+}
+
+impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {
+    fn len(&self) -> usize { self.remaining }
+}
+
+impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> {
+    fn len(&self) -> usize { self.remaining }
+}
+
+impl<K, V> ExactSizeIterator for IntoIter<K, V> {
+    fn len(&self) -> usize { self.remaining }
+}
+
+impl<K, V> Drop for IntoIter<K, V> {
+    fn drop(&mut self) {
+        for _ in 0..self.remaining {
+            unsafe {
+                let next = (*self.tail).next;
+                Box::from_raw(self.tail);
+                self.tail = next;
+            }
+        }
+    }
+}
+
+/// An insertion-order iterator over a `LinkedHashMap`'s keys.
+pub struct Keys<'a, K: 'a, V: 'a> {
+    inner: Iter<'a, K, V>,
+}
+
+impl<'a, K, V> Clone for Keys<'a, K, V> {
+    fn clone(&self) -> Self { Keys { inner: self.inner.clone() } }
+}
+
+impl<'a, K, V> Iterator for Keys<'a, K, V> {
+    type Item = &'a K;
+
+    #[inline] fn next(&mut self) -> Option<&'a K> { self.inner.next().map(|e| e.0) }
+    #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+}
+
+impl<'a, K, V> DoubleEndedIterator for Keys<'a, K, V> {
+    #[inline] fn next_back(&mut self) -> Option<&'a K> { self.inner.next_back().map(|e| e.0) }
+}
+
+impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> {
+    fn len(&self) -> usize { self.inner.len() }
+}
+
+/// An insertion-order iterator over a `LinkedHashMap`'s values.
+pub struct Values<'a, K: 'a, V: 'a> {
+    inner: Iter<'a, K, V>,
+}
+
+impl<'a, K, V> Clone for Values<'a, K, V> {
+    fn clone(&self) -> Self { Values { inner: self.inner.clone() } }
+}
+
+impl<'a, K, V> Iterator for Values<'a, K, V> {
+    type Item = &'a V;
+
+    #[inline] fn next(&mut self) -> Option<&'a V> { self.inner.next().map(|e| e.1) }
+    #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+}
+
+impl<'a, K, V> DoubleEndedIterator for Values<'a, K, V> {
+    #[inline] fn next_back(&mut self) -> Option<&'a V> { self.inner.next_back().map(|e| e.1) }
+}
+
+impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> {
+    fn len(&self) -> usize { self.inner.len() }
+}
+
+impl<'a, K: Hash + Eq, V, S: BuildHasher> IntoIterator for &'a LinkedHashMap<K, V, S> {
+    type Item = (&'a K, &'a V);
+    type IntoIter = Iter<'a, K, V>;
+    fn into_iter(self) -> Iter<'a, K, V> { self.iter() }
+}
+
+impl<'a, K: Hash + Eq, V, S: BuildHasher> IntoIterator for &'a mut LinkedHashMap<K, V, S> {
+    type Item = (&'a K, &'a mut V);
+    type IntoIter = IterMut<'a, K, V>;
+    fn into_iter(self) -> IterMut<'a, K, V> { self.iter_mut() }
+}
+
+impl<K: Hash + Eq, V, S: BuildHasher> IntoIterator for LinkedHashMap<K, V, S> {
+    type Item = (K, V);
+    type IntoIter = IntoIter<K, V>;
+    fn into_iter(mut self) -> IntoIter<K, V> {
+        let (head, tail) = if !self.head.is_null() {
+            unsafe { ((*self.head).prev, (*self.head).next) }
+        } else {
+            (ptr::null_mut(), ptr::null_mut())
+        };
+        let len = self.len();
+
+        if !self.head.is_null() {
+            unsafe { drop_empty_node(self.head) }
+        }
+        self.clear_free_list();
+        // drop the HashMap but not the LinkedHashMap
+        self.map = unsafe { mem::uninitialized() };
+        mem::forget(self);
+
+        IntoIter {
+            head: head,
+            tail: tail,
+            remaining: len,
+            marker: marker::PhantomData,
+        }
+    }
+}
+
+/// A view into a single location in a map, which may be vacant or occupied.
+pub enum Entry<'a, K: 'a, V: 'a, S: 'a = hash_map::RandomState> {
+    /// An occupied Entry.
+    Occupied(OccupiedEntry<'a, K, V, S>),
+    /// A vacant Entry.
+    Vacant(VacantEntry<'a, K, V, S>),
+}
+
+/// A view into a single occupied location in a `LinkedHashMap`.
+pub struct OccupiedEntry<'a, K: 'a, V: 'a, S: 'a = hash_map::RandomState> {
+    entry: *mut Node<K, V>,
+    map: *mut LinkedHashMap<K, V, S>,
+    marker: marker::PhantomData<&'a K>,
+}
+
+/// A view into a single empty location in a `LinkedHashMap`.
+pub struct VacantEntry<'a, K: 'a, V: 'a, S: 'a = hash_map::RandomState> {
+    key: K,
+    map: &'a mut LinkedHashMap<K, V, S>,
+}
+
+impl<'a, K: Hash + Eq, V, S: BuildHasher> Entry<'a, K, V, S> {
+    /// Returns the entry key
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use linked_hash_map::LinkedHashMap;
+    ///
+    /// let mut map = LinkedHashMap::<String, u32>::new();
+    ///
+    /// assert_eq!("hello", map.entry("hello".to_string()).key());
+    /// ```
+    pub fn key(&self) -> &K {
+        match *self {
+            Entry::Occupied(ref e) => e.key(),
+            Entry::Vacant(ref e) => e.key(),
+        }
+    }
+
+    /// Ensures a value is in the entry by inserting the default if empty, and returns
+    /// a mutable reference to the value in the entry.
+    pub fn or_insert(self, default: V) -> &'a mut V {
+        match self {
+            Entry::Occupied(entry) => entry.into_mut(),
+            Entry::Vacant(entry) => entry.insert(default),
+        }
+    }
+
+    /// Ensures a value is in the entry by inserting the result of the default function if empty,
+    /// and returns a mutable reference to the value in the entry.
+    pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
+        match self {
+            Entry::Occupied(entry) => entry.into_mut(),
+            Entry::Vacant(entry) => entry.insert(default()),
+        }
+    }
+}
+
+impl<'a, K: Hash + Eq, V, S: BuildHasher> OccupiedEntry<'a, K, V, S> {
+    /// Gets a reference to the entry key
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use linked_hash_map::LinkedHashMap;
+    ///
+    /// let mut map = LinkedHashMap::new();
+    ///
+    /// map.insert("foo".to_string(), 1);
+    /// assert_eq!("foo", map.entry("foo".to_string()).key());
+    /// ```
+    pub fn key(&self) -> &K {
+        unsafe { &(*self.entry).key }
+    }
+
+    /// Gets a reference to the value in the entry.
+    pub fn get(&self) -> &V {
+        unsafe { &(*self.entry).value }
+    }
+
+    /// Gets a mutable reference to the value in the entry.
+    pub fn get_mut(&mut self) -> &mut V {
+        unsafe { &mut (*self.entry).value }
+    }
+
+    /// Converts the OccupiedEntry into a mutable reference to the value in the entry
+    /// with a lifetime bound to the map itself
+    pub fn into_mut(self) -> &'a mut V {
+        unsafe { &mut (*self.entry).value }
+    }
+
+    /// Sets the value of the entry, and returns the entry's old value
+    pub fn insert(&mut self, value: V) -> V {
+        unsafe {
+            (*self.map).ensure_guard_node();
+
+            let old_val = mem::replace(&mut (*self.entry).value, value);
+            let node_ptr: *mut Node<K, V> = self.entry;
+
+            // Existing node, just update LRU position
+            (*self.map).detach(node_ptr);
+            (*self.map).attach(node_ptr);
+
+            old_val
+        }
+    }
+
+    /// Takes the value out of the entry, and returns it
+    pub fn remove(self) -> V {
+        unsafe { (*self.map).remove(&(*self.entry).key) }.unwrap()
+    }
+}
+
+impl<'a, K: 'a + Hash + Eq, V: 'a, S: BuildHasher> VacantEntry<'a, K, V, S> {
+    /// Gets a reference to the entry key
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use linked_hash_map::LinkedHashMap;
+    ///
+    /// let mut map = LinkedHashMap::<String, u32>::new();
+    ///
+    /// assert_eq!("foo", map.entry("foo".to_string()).key());
+    /// ```
+    pub fn key(&self) -> &K {
+        &self.key
+    }
+
+    /// Sets the value of the entry with the VacantEntry's key,
+    /// and returns a mutable reference to it
+    pub fn insert(self, value: V) -> &'a mut V {
+        self.map.ensure_guard_node();
+
+        let node = if self.map.free.is_null() {
+            Box::into_raw(Box::new(Node::new(self.key, value)))
+        } else {
+            // use a recycled box
+            unsafe {
+                let free = self.map.free;
+                self.map.free = (*free).next;
+                ptr::write(free, Node::new(self.key, value));
+                free
+            }
+        };
+
+        let keyref = unsafe { &(*node).key };
+
+        self.map.attach(node);
+
+        let ret = self.map.map.entry(KeyRef{k: keyref}).or_insert(node);
+        unsafe { &mut (**ret).value }
+    }
+}
+
+#[cfg(all(feature = "nightly", test))]
+mod bench {
+    extern crate test;
+
+    use super::LinkedHashMap;
+
+    #[bench]
+    fn not_recycled_cycling(b: &mut test::Bencher) {
+        let mut hash_map = LinkedHashMap::with_capacity(1000);
+        for i in 0usize..1000 {
+            hash_map.insert(i, i);
+        }
+        b.iter(|| {
+            for i in 0usize..1000 {
+                hash_map.remove(&i);
+            }
+            hash_map.clear_free_list();
+            for i in 0usize..1000 {
+                hash_map.insert(i, i);
+            }
+        })
+    }
+
+    #[bench]
+    fn recycled_cycling(b: &mut test::Bencher) {
+        let mut hash_map = LinkedHashMap::with_capacity(1000);
+        for i in 0usize..1000 {
+            hash_map.insert(i, i);
+        }
+        b.iter(|| {
+            for i in 0usize..1000 {
+                hash_map.remove(&i);
+            }
+            for i in 0usize..1000 {
+                hash_map.insert(i, i);
+            }
+        })
+    }
+}
diff --git a/third_party/rust_crates/vendor/linked-hash-map/src/serde.rs b/third_party/rust_crates/vendor/linked-hash-map/src/serde.rs
new file mode 100644
index 0000000..1062776
--- /dev/null
+++ b/third_party/rust_crates/vendor/linked-hash-map/src/serde.rs
@@ -0,0 +1,94 @@
+//! An optional implementation of serialization/deserialization.
+
+extern crate serde;
+
+use std::fmt::{Formatter, Result as FmtResult};
+use std::marker::PhantomData;
+use std::hash::{BuildHasher, Hash};
+
+use super::LinkedHashMap;
+
+use self::serde::{Serialize, Serializer, Deserialize, Deserializer};
+use self::serde::ser::SerializeMap;
+use self::serde::de::{Visitor, MapAccess, Error};
+
+impl<K, V, S> Serialize for LinkedHashMap<K, V, S>
+    where K: Serialize + Eq + Hash,
+          V: Serialize,
+          S: BuildHasher
+{
+    #[inline]
+    fn serialize<T>(&self, serializer:T) -> Result<T::Ok, T::Error>
+        where T: Serializer,
+    {
+        let mut map_serializer = try!(serializer.serialize_map(Some(self.len())));
+        for (k, v) in self {
+            try!(map_serializer.serialize_key(k));
+            try!(map_serializer.serialize_value(v));
+        }
+        map_serializer.end()
+    }
+}
+
+#[derive(Debug)]
+/// `serde::de::Visitor` for a linked hash map.
+pub struct LinkedHashMapVisitor<K, V> {
+    marker: PhantomData<LinkedHashMap<K, V>>,
+}
+
+impl<K, V> LinkedHashMapVisitor<K, V> {
+    /// Creates a new visitor for a linked hash map.
+    pub fn new() -> Self {
+        LinkedHashMapVisitor {
+            marker: PhantomData,
+        }
+    }
+}
+
+impl<K, V> Default for LinkedHashMapVisitor<K, V> {
+    fn default() -> Self {
+        LinkedHashMapVisitor::new()
+    }
+}
+
+impl<'de, K, V> Visitor<'de> for LinkedHashMapVisitor<K, V>
+    where K: Deserialize<'de> + Eq + Hash,
+          V: Deserialize<'de>,
+{
+    type Value = LinkedHashMap<K, V>;
+
+    fn expecting(&self, formatter: &mut Formatter) -> FmtResult {
+        write!(formatter, "a map")
+    }
+
+    #[inline]
+    fn visit_unit<E>(self) -> Result<Self::Value, E>
+        where E: Error,
+    {
+        Ok(LinkedHashMap::new())
+    }
+
+    #[inline]
+    fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
+        where M: MapAccess<'de>,
+    {
+        let mut values = LinkedHashMap::with_capacity(map.size_hint().unwrap_or(0));
+
+        while let Some((key, value)) = map.next_entry()? {
+            values.insert(key, value);
+        }
+
+        Ok(values)
+    }
+}
+
+impl<'de, K, V> Deserialize<'de> for LinkedHashMap<K, V>
+    where K: Deserialize<'de> + Eq + Hash,
+          V: Deserialize<'de>,
+{
+    fn deserialize<D>(deserializer: D) -> Result<LinkedHashMap<K, V>, D::Error>
+        where D: Deserializer<'de>,
+    {
+        deserializer.deserialize_map(LinkedHashMapVisitor::new())
+    }
+}
diff --git a/third_party/rust_crates/vendor/linked-hash-map/tests/heapsize.rs b/third_party/rust_crates/vendor/linked-hash-map/tests/heapsize.rs
new file mode 100644
index 0000000..583c30e
--- /dev/null
+++ b/third_party/rust_crates/vendor/linked-hash-map/tests/heapsize.rs
@@ -0,0 +1,23 @@
+#![cfg(feature = "heapsize_impl")]
+
+extern crate heapsize;
+extern crate linked_hash_map;
+
+use linked_hash_map::LinkedHashMap;
+use heapsize::HeapSizeOf;
+
+#[test]
+fn empty() {
+    assert_eq!(LinkedHashMap::<String, String>::new().heap_size_of_children(), 0);
+}
+
+#[test]
+fn nonempty() {
+    let mut map = LinkedHashMap::new();
+    map.insert("hello".to_string(), "world".to_string());
+    map.insert("hola".to_string(), "mundo".to_string());
+    map.insert("bonjour".to_string(), "monde".to_string());
+    map.remove("hello");
+
+    assert!(map.heap_size_of_children() != 0);
+}
diff --git a/third_party/rust_crates/vendor/linked-hash-map/tests/serde.rs b/third_party/rust_crates/vendor/linked-hash-map/tests/serde.rs
new file mode 100644
index 0000000..e6d5c6f
--- /dev/null
+++ b/third_party/rust_crates/vendor/linked-hash-map/tests/serde.rs
@@ -0,0 +1,38 @@
+#![cfg(feature = "serde_impl")]
+
+extern crate linked_hash_map;
+use linked_hash_map::LinkedHashMap;
+
+extern crate serde_test;
+use serde_test::{Token, assert_tokens};
+
+#[test]
+fn test_ser_de_empty() {
+    let map = LinkedHashMap::<char, u32>::new();
+
+    assert_tokens(&map, &[
+        Token::Map { len: Some(0) },
+        Token::MapEnd,
+    ]);
+}
+
+#[test]
+fn test_ser_de() {
+    let mut map = LinkedHashMap::new();
+    map.insert('b', 20);
+    map.insert('a', 10);
+    map.insert('c', 30);
+
+    assert_tokens(&map, &[
+        Token::Map { len: Some(3) },
+            Token::Char('b'),
+            Token::I32(20),
+
+            Token::Char('a'),
+            Token::I32(10),
+
+            Token::Char('c'),
+            Token::I32(30),
+        Token::MapEnd,
+    ]);
+}
diff --git a/third_party/rust_crates/vendor/linked-hash-map/tests/test.rs b/third_party/rust_crates/vendor/linked-hash-map/tests/test.rs
new file mode 100644
index 0000000..7f34b01
--- /dev/null
+++ b/third_party/rust_crates/vendor/linked-hash-map/tests/test.rs
@@ -0,0 +1,426 @@
+extern crate linked_hash_map;
+
+use linked_hash_map::{LinkedHashMap, Entry};
+
+fn assert_opt_eq<V: PartialEq>(opt: Option<&V>, v: V) {
+    assert!(opt.is_some());
+    assert!(opt.unwrap() == &v);
+}
+
+#[test]
+fn test_insert_and_get() {
+    let mut map = LinkedHashMap::new();
+    map.insert(1, 10);
+    map.insert(2, 20);
+    assert_opt_eq(map.get(&1), 10);
+    assert_opt_eq(map.get(&2), 20);
+    assert_eq!(map.len(), 2);
+}
+
+#[test]
+fn test_index() {
+    let mut map = LinkedHashMap::new();
+    map.insert(1, 10);
+    map.insert(2, 20);
+    assert_eq!(10, map[&1]);
+    map[&2] = 22;
+    assert_eq!(22, map[&2]);
+}
+
+#[test]
+fn test_insert_update() {
+    let mut map = LinkedHashMap::new();
+    map.insert("1".to_string(), vec![10, 10]);
+    map.insert("1".to_string(), vec![10, 19]);
+    assert_opt_eq(map.get(&"1".to_string()), vec![10, 19]);
+    assert_eq!(map.len(), 1);
+}
+
+#[test]
+fn test_entry_insert_vacant() {
+    let mut map = LinkedHashMap::new();
+    match map.entry("1".to_string()) {
+        Entry::Vacant(e) => {
+            assert_eq!(*e.insert(vec![10, 10]), vec![10, 10]);
+        }
+        _ => panic!("fail"),
+    }
+    assert!(map.contains_key("1"));
+    assert_eq!(map["1"], vec![10, 10]);
+
+    match map.entry("1".to_string()) {
+        Entry::Occupied(mut e) => {
+            assert_eq!(*e.get(), vec![10, 10]);
+            assert_eq!(e.insert(vec![10, 16]), vec![10, 10]);
+        }
+        _ => panic!("fail"),
+    }
+
+    assert!(map.contains_key("1"));
+    assert_eq!(map["1"], vec![10, 16]);
+
+    match map.entry("1".to_string()) {
+        Entry::Occupied(e) => {
+            assert_eq!(e.remove(), vec![10, 16]);
+        }
+        _ => panic!("fail"),
+    }
+}
+
+#[test]
+fn test_entries_replacing() {
+    let mut map = LinkedHashMap::new();
+    map.insert("a", 10);
+
+    {
+        let mut iter = map.entries();
+        let mut entry = iter.next().unwrap();
+        assert_eq!(entry.insert(20), 10);
+        assert!(iter.next().is_none());
+    }
+
+    assert_eq!(map["a"], 20);
+}
+
+#[test]
+fn test_entries_remove() {
+    let mut map = LinkedHashMap::new();
+    map.insert("a", 10);
+    map.insert("b", 20);
+    map.insert("c", 30);
+    map.insert("d", 40);
+
+    // remove middle
+    {
+        let mut iter = map.entries();
+        iter.next().unwrap();
+        let b = iter.next().unwrap();
+        assert_eq!(*b.key(), "b");
+        assert_eq!(b.remove(), 20);
+        assert_eq!(*iter.next().unwrap().key(), "c");
+    }
+
+    assert_eq!(map.len(), 3);
+    assert_eq!(map["a"], 10);
+    assert_eq!(map["c"], 30);
+    assert_eq!(map["d"], 40);
+
+    // remove first
+    {
+        let mut iter = map.entries();
+        let a = iter.next().unwrap();
+        assert_eq!(*a.key(), "a");
+        assert_eq!(a.remove(), 10);
+    }
+
+    assert_eq!(map.len(), 2);
+    assert_eq!(map["c"], 30);
+    assert_eq!(map["d"], 40);
+
+    // remove last
+    {
+        let mut iter = map.entries();
+        iter.next().unwrap();
+        let d = iter.next().unwrap();
+        assert_eq!(*d.key(), "d");
+        assert_eq!(d.remove(), 40);
+        assert!(iter.next().is_none());
+    }
+
+    assert_eq!(map.len(), 1);
+    assert_eq!(map["c"], 30);
+
+    // remove only
+    {
+        let mut iter = map.entries();
+        let c = iter.next().unwrap();
+        assert_eq!(*c.key(), "c");
+        assert_eq!(c.remove(), 30);
+    }
+
+    assert!(map.is_empty());
+}
+#[test]
+fn entries_insert() {
+    let mut map = LinkedHashMap::new();
+    map.insert(0, 0);
+    map.insert(1, 1);
+
+    let mut iter = map.entries();
+
+    iter.next().unwrap().insert(0);
+    iter.next().unwrap(); // 1
+    assert!(iter.next().is_none());
+}
+
+#[test]
+fn test_debug() {
+    let mut map = LinkedHashMap::new();
+    assert_eq!(format!("{:?}", map), "{}");
+    map.insert(1, 10);
+    map.insert(2, 20);
+    map.insert(3, 30);
+    assert_eq!(format!("{:?}", map), "{1: 10, 2: 20, 3: 30}");
+    map.insert(2, 22);
+    assert_eq!(format!("{:?}", map), "{1: 10, 3: 30, 2: 22}");
+    map.get(&3);
+    assert_eq!(format!("{:?}", map), "{1: 10, 3: 30, 2: 22}");
+    map.get_refresh(&mut 3);
+    assert_eq!(format!("{:?}", map), "{1: 10, 2: 22, 3: 30}");
+    map.clear();
+    assert_eq!(format!("{:?}", map), "{}");
+}
+
+#[test]
+fn test_remove() {
+    let mut map = LinkedHashMap::new();
+    map.insert(1, 10);
+    map.insert(2, 20);
+    map.insert(3, 30);
+    map.insert(4, 40);
+    map.insert(5, 50);
+    map.remove(&3);
+    map.remove(&4);
+    assert!(map.get(&3).is_none());
+    assert!(map.get(&4).is_none());
+    map.insert(6, 60);
+    map.insert(7, 70);
+    map.insert(8, 80);
+    assert_opt_eq(map.get(&6), 60);
+    assert_opt_eq(map.get(&7), 70);
+    assert_opt_eq(map.get(&8), 80);
+}
+
+
+#[test]
+fn test_pop() {
+    let mut map = LinkedHashMap::new();
+    map.insert(1, 10);
+    map.insert(2, 20);
+    map.insert(3, 30);
+    map.insert(4, 40);
+    map.insert(5, 50);
+    assert_eq!(map.pop_front(), Some((1, 10)));
+    assert!(map.get(&1).is_none());
+    assert_eq!(map.pop_back(), Some((5, 50)));
+    assert!(map.get(&5).is_none());
+    map.insert(6, 60);
+    map.insert(7, 70);
+    map.insert(8, 80);
+    assert_eq!(map.pop_front(), Some((2, 20)));
+    assert!(map.get(&2).is_none());
+    assert_eq!(map.pop_back(), Some((8, 80)));
+    assert!(map.get(&8).is_none());
+    map.insert(3, 30);
+    assert_eq!(map.pop_front(), Some((4, 40)));
+    assert!(map.get(&4).is_none());
+    assert_eq!(map.pop_back(), Some((3, 30)));
+    assert!(map.get(&3).is_none());
+}
+
+#[test]
+fn test_clear() {
+    let mut map = LinkedHashMap::new();
+    map.insert(1, 10);
+    map.insert(2, 20);
+    map.clear();
+    assert!(map.get(&1).is_none());
+    assert!(map.get(&2).is_none());
+    assert_eq!(format!("{:?}", map), "{}");
+}
+
+#[test]
+fn test_iter() {
+    let mut map = LinkedHashMap::new();
+
+    // empty iter
+    assert_eq!(None, map.iter().next());
+
+    map.insert("a", 10);
+    map.insert("b", 20);
+    map.insert("c", 30);
+
+    // regular iter
+    let mut iter = map.iter();
+    assert_eq!((&"a", &10), iter.next().unwrap());
+    assert_eq!((&"b", &20), iter.next().unwrap());
+    assert_eq!((&"c", &30), iter.next().unwrap());
+    assert_eq!(None, iter.next());
+    assert_eq!(None, iter.next());
+
+    // reversed iter
+    let mut rev_iter = map.iter().rev();
+    assert_eq!((&"c", &30), rev_iter.next().unwrap());
+    assert_eq!((&"b", &20), rev_iter.next().unwrap());
+    assert_eq!((&"a", &10), rev_iter.next().unwrap());
+    assert_eq!(None, rev_iter.next());
+    assert_eq!(None, rev_iter.next());
+
+    // mixed
+    let mut mixed_iter = map.iter();
+    assert_eq!((&"a", &10), mixed_iter.next().unwrap());
+    assert_eq!((&"c", &30), mixed_iter.next_back().unwrap());
+    assert_eq!((&"b", &20), mixed_iter.next().unwrap());
+    assert_eq!(None, mixed_iter.next());
+    assert_eq!(None, mixed_iter.next_back());
+}
+
+#[test]
+fn test_iter_mut() {
+    let mut map = LinkedHashMap::new();
+    map.insert("a", 10);
+    map.insert("c", 30);
+    map.insert("b", 20);
+
+    {
+        let mut iter = map.iter_mut();
+        let entry = iter.next().unwrap();
+        assert_eq!(&"a", entry.0);
+        *entry.1 = 17;
+
+        // reverse iterator
+        let mut iter = iter.rev();
+        let entry = iter.next().unwrap();
+        assert_eq!(&"b", entry.0);
+        *entry.1 = 23;
+
+        let entry = iter.next().unwrap();
+        assert_eq!(&"c", entry.0);
+        assert_eq!(None, iter.next());
+        assert_eq!(None, iter.next());
+    }
+
+    assert_eq!(17, map[&"a"]);
+    assert_eq!(23, map[&"b"]);
+}
+
+#[test]
+fn test_consuming_iter() {
+    let map = {
+        let mut map = LinkedHashMap::new();
+        map.insert("a", 10);
+        map.insert("c", 30);
+        map.insert("b", 20);
+        map
+    };
+
+    let mut iter = map.into_iter();
+    assert_eq!(Some(("a", 10)), iter.next());
+
+    let clone = iter.clone();
+    for iter in &mut [iter, clone] {
+        assert_eq!(Some(("b", 20)), iter.next_back());
+        assert_eq!(1, iter.len());
+        assert_eq!(Some(("c", 30)), iter.next());
+        assert_eq!(None, iter.next());
+    }
+}
+
+#[test]
+fn test_consuming_iter_empty() {
+    let map = LinkedHashMap::<&str, i32>::new();
+    let mut iter = map.into_iter();
+    assert_eq!(None, iter.next());
+    let mut clone = iter.clone();
+    assert_eq!(None, clone.next());
+}
+
+#[test]
+fn test_consuming_iter_with_free_list() {
+    let mut map = LinkedHashMap::new();
+    map.insert("a", 10);
+    map.insert("c", 30);
+    map.insert("b", 20);
+    map.remove("a");
+    map.remove("b");
+
+    let mut iter = map.into_iter();
+    assert_eq!(Some(("c", 30)), iter.next());
+    assert_eq!(None, iter.next());
+}
+
+#[test]
+fn test_into_iter_drop() {
+    struct Counter<'a>(&'a mut usize);
+
+    impl<'a> Drop for Counter<'a> {
+        fn drop(&mut self) {
+            *self.0 += 1;
+        }
+    }
+
+    let mut a = 0;
+    let mut b = 0;
+    let mut c = 0;
+
+    {
+        let mut map = LinkedHashMap::new();
+        map.insert("a", Counter(&mut a));
+        map.insert("b", Counter(&mut b));
+        map.insert("c", Counter(&mut c));
+
+        let mut iter = map.into_iter();
+        iter.next();
+        iter.next_back();
+    }
+
+    assert_eq!(a, 1);
+    assert_eq!(b, 1);
+    assert_eq!(c, 1);
+}
+
+#[test]
+fn test_borrow() {
+    #[derive(PartialEq, Eq, Hash)] struct Foo(Bar);
+    #[derive(PartialEq, Eq, Hash)] struct Bar(i32);
+
+    impl ::std::borrow::Borrow<Bar> for Foo {
+        fn borrow(&self) -> &Bar { &self.0 }
+    }
+
+    let mut map = LinkedHashMap::new();
+    map.insert(Foo(Bar(1)), "a");
+    map.insert(Foo(Bar(2)), "b");
+
+    assert!(map.contains_key(&Bar(1)));
+    assert!(map.contains_key(&Bar(2)));
+    assert!(map.contains_key(&Foo(Bar(1))));
+    assert!(map.contains_key(&Foo(Bar(2))));
+
+    assert_eq!(map.get(&Bar(1)), Some(&"a"));
+    assert_eq!(map.get(&Bar(2)), Some(&"b"));
+    assert_eq!(map.get(&Foo(Bar(1))), Some(&"a"));
+    assert_eq!(map.get(&Foo(Bar(2))), Some(&"b"));
+
+    assert_eq!(map.get_refresh(&Bar(1)), Some(&mut "a"));
+    assert_eq!(map.get_refresh(&Bar(2)), Some(&mut "b"));
+    assert_eq!(map.get_refresh(&Foo(Bar(1))), Some(&mut "a"));
+    assert_eq!(map.get_refresh(&Foo(Bar(2))), Some(&mut "b"));
+
+    assert_eq!(map.get_mut(&Bar(1)), Some(&mut "a"));
+    assert_eq!(map.get_mut(&Bar(2)), Some(&mut "b"));
+    assert_eq!(map.get_mut(&Foo(Bar(1))), Some(&mut "a"));
+    assert_eq!(map.get_mut(&Foo(Bar(2))), Some(&mut "b"));
+
+    assert_eq!(map[&Bar(1)], "a");
+    assert_eq!(map[&Bar(2)], "b");
+    assert_eq!(map[&Foo(Bar(1))], "a");
+    assert_eq!(map[&Foo(Bar(2))], "b");
+
+    assert_eq!(map.remove(&Bar(1)), Some("a"));
+    assert_eq!(map.remove(&Bar(2)), Some("b"));
+    assert_eq!(map.remove(&Foo(Bar(1))), None);
+    assert_eq!(map.remove(&Foo(Bar(2))), None);
+}
+
+#[test]
+fn test_send_sync() {
+    fn is_send_sync<T: Send + Sync>() {}
+
+    is_send_sync::<LinkedHashMap<u32, i32>>();
+    is_send_sync::<linked_hash_map::Iter<u32, i32>>();
+    is_send_sync::<linked_hash_map::IterMut<u32, i32>>();
+    is_send_sync::<linked_hash_map::IntoIter<u32, i32>>();
+    is_send_sync::<linked_hash_map::Keys<u32, i32>>();
+    is_send_sync::<linked_hash_map::Values<u32, i32>>();
+}
diff --git a/third_party/rust_crates/vendor/lru-cache/.cargo-checksum.json b/third_party/rust_crates/vendor/lru-cache/.cargo-checksum.json
new file mode 100644
index 0000000..5a89380
--- /dev/null
+++ b/third_party/rust_crates/vendor/lru-cache/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"a6cddb148a1939f1ce36f826ec9a6015b585e56ad897c6377272948ef6f5a264","LICENSE-APACHE":"8173d5c29b4f956d532781d2b86e4e30f83e6b7878dce18c919451d6ba707c90","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"37bfe6f9b2322624f03ce495dc81bc3f935e59795bf8e0c3540f77e32ece15d0","deploy-docs.sh":"7b66111b124c1c7e59cb84cf110d98b5cb783bd35a676e970d9b3035e55f7dfd","src/heapsize.rs":"9f4d536de20f8f09a94d74b098c6469f9b6fde29f911abee371d41f53f0808a8","src/lib.rs":"7f0f18bb13d0bde102eca0aa8b99408f06f7dad48c68e1f13995453edb7f2ecd"},"package":"31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c"}
\ No newline at end of file
diff --git a/third_party/rust_crates/vendor/lru-cache/Cargo.toml b/third_party/rust_crates/vendor/lru-cache/Cargo.toml
new file mode 100644
index 0000000..25bcbf4
--- /dev/null
+++ b/third_party/rust_crates/vendor/lru-cache/Cargo.toml
@@ -0,0 +1,32 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "lru-cache"
+version = "0.1.2"
+authors = ["Stepan Koltsov <stepan.koltsov@gmail.com>"]
+description = "A cache that holds a limited number of key-value pairs"
+homepage = "https://github.com/contain-rs/lru-cache"
+documentation = "https://contain-rs.github.io/lru-cache/lru_cache"
+readme = "README.md"
+keywords = ["data-structures"]
+license = "MIT/Apache-2.0"
+repository = "https://github.com/contain-rs/lru-cache"
+[dependencies.heapsize]
+version = "0.4"
+optional = true
+
+[dependencies.linked-hash-map]
+version = "0.5"
+
+[features]
+heapsize_impl = ["heapsize", "linked-hash-map/heapsize_impl"]
diff --git a/third_party/rust_crates/vendor/lru-cache/LICENSE-APACHE b/third_party/rust_crates/vendor/lru-cache/LICENSE-APACHE
new file mode 100644
index 0000000..11069ed
--- /dev/null
+++ b/third_party/rust_crates/vendor/lru-cache/LICENSE-APACHE
@@ -0,0 +1,201 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+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.
diff --git a/third_party/rust_crates/vendor/lru-cache/LICENSE-MIT b/third_party/rust_crates/vendor/lru-cache/LICENSE-MIT
new file mode 100644
index 0000000..e69282e
--- /dev/null
+++ b/third_party/rust_crates/vendor/lru-cache/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2015 The Rust Project Developers
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/third_party/rust_crates/vendor/lru-cache/README.md b/third_party/rust_crates/vendor/lru-cache/README.md
new file mode 100644
index 0000000..d835d6e
--- /dev/null
+++ b/third_party/rust_crates/vendor/lru-cache/README.md
@@ -0,0 +1,14 @@
+**WARNING: THIS PROJECT IS IN MAINTENANCE MODE, DUE TO INSUFFICIENT MAINTAINER RESOURCES**
+
+It works fine, but will generally no longer be improved.
+
+We are currently only accepting changes which:
+
+* keep this compiling with the latest versions of Rust or its dependencies.
+* have minimal review requirements, such as documentation changes (so not totally new APIs).
+
+------
+
+A cache that holds a limited number of key-value pairs.
+
+Documentation is available at https://contain-rs.github.io/lru-cache/lru_cache.
diff --git a/third_party/rust_crates/vendor/lru-cache/deploy-docs.sh b/third_party/rust_crates/vendor/lru-cache/deploy-docs.sh
new file mode 100755
index 0000000..c8f25ee
--- /dev/null
+++ b/third_party/rust_crates/vendor/lru-cache/deploy-docs.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+set -o errexit -o nounset
+
+rev=$(git rev-parse --short HEAD)
+
+cd target/doc
+
+git init
+git config user.email 'FlashCat@users.noreply.github.com'
+git config user.name 'FlashCat'
+git remote add upstream "https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git"
+git fetch upstream gh-pages
+git reset upstream/gh-pages
+
+touch .
+
+git add -A .
+git commit -m "rebuild pages at ${rev}"
+git push -q upstream HEAD:gh-pages
diff --git a/third_party/rust_crates/vendor/lru-cache/src/heapsize.rs b/third_party/rust_crates/vendor/lru-cache/src/heapsize.rs
new file mode 100644
index 0000000..ff0170f
--- /dev/null
+++ b/third_party/rust_crates/vendor/lru-cache/src/heapsize.rs
@@ -0,0 +1,12 @@
+extern crate heapsize;
+
+use self::heapsize::HeapSizeOf;
+use std::hash::{Hash, BuildHasher};
+
+use LruCache;
+
+impl<K: Eq + Hash + HeapSizeOf, V: HeapSizeOf, S: BuildHasher> HeapSizeOf for LruCache<K, V, S> {
+    fn heap_size_of_children(&self) -> usize {
+        self.map.heap_size_of_children()
+    }
+}
diff --git a/third_party/rust_crates/vendor/lru-cache/src/lib.rs b/third_party/rust_crates/vendor/lru-cache/src/lib.rs
new file mode 100644
index 0000000..fcf9b61
--- /dev/null
+++ b/third_party/rust_crates/vendor/lru-cache/src/lib.rs
@@ -0,0 +1,567 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! A cache that holds a limited number of key-value pairs. When the
+//! capacity of the cache is exceeded, the least-recently-used
+//! (where "used" means a look-up or putting the pair into the cache)
+//! pair is automatically removed.
+//!
+//! # Examples
+//!
+//! ```
+//! use lru_cache::LruCache;
+//!
+//! let mut cache = LruCache::new(2);
+//!
+//! cache.insert(1, 10);
+//! cache.insert(2, 20);
+//! cache.insert(3, 30);
+//! assert!(cache.get_mut(&1).is_none());
+//! assert_eq!(*cache.get_mut(&2).unwrap(), 20);
+//! assert_eq!(*cache.get_mut(&3).unwrap(), 30);
+//!
+//! cache.insert(2, 22);
+//! assert_eq!(*cache.get_mut(&2).unwrap(), 22);
+//!
+//! cache.insert(6, 60);
+//! assert!(cache.get_mut(&3).is_none());
+//!
+//! cache.set_capacity(1);
+//! assert!(cache.get_mut(&2).is_none());
+//! ```
+
+extern crate linked_hash_map;
+
+use std::borrow::Borrow;
+use std::collections::hash_map::RandomState;
+use std::fmt;
+use std::hash::{Hash, BuildHasher};
+
+use linked_hash_map::LinkedHashMap;
+
+#[cfg(feature = "heapsize_impl")]
+mod heapsize;
+
+// FIXME(conventions): implement indexing?
+
+/// An LRU cache.
+#[derive(Clone)]
+pub struct LruCache<K: Eq + Hash, V, S: BuildHasher = RandomState> {
+    map: LinkedHashMap<K, V, S>,
+    max_size: usize,
+}
+
+impl<K: Eq + Hash, V> LruCache<K, V> {
+    /// Creates an empty cache that can hold at most `capacity` items.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use lru_cache::LruCache;
+    /// let mut cache: LruCache<i32, &str> = LruCache::new(10);
+    /// ```
+    pub fn new(capacity: usize) -> Self {
+        LruCache {
+            map: LinkedHashMap::new(),
+            max_size: capacity,
+        }
+    }
+}
+
+impl<K: Eq + Hash, V, S: BuildHasher> LruCache<K, V, S> {
+    /// Creates an empty cache that can hold at most `capacity` items with the given hash builder.
+    pub fn with_hasher(capacity: usize, hash_builder: S) -> Self {
+        LruCache { map: LinkedHashMap::with_hasher(hash_builder), max_size: capacity }
+    }
+
+    /// Checks if the map contains the given key.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use lru_cache::LruCache;
+    ///
+    /// let mut cache = LruCache::new(1);
+    ///
+    /// cache.insert(1, "a");
+    /// assert_eq!(cache.contains_key(&1), true);
+    /// ```
+    pub fn contains_key<Q: ?Sized>(&mut self, key: &Q) -> bool
+        where K: Borrow<Q>,
+              Q: Hash + Eq
+    {
+        self.get_mut(key).is_some()
+    }
+
+    /// Inserts a key-value pair into the cache. If the key already existed, the old value is
+    /// returned.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use lru_cache::LruCache;
+    ///
+    /// let mut cache = LruCache::new(2);
+    ///
+    /// cache.insert(1, "a");
+    /// cache.insert(2, "b");
+    /// assert_eq!(cache.get_mut(&1), Some(&mut "a"));
+    /// assert_eq!(cache.get_mut(&2), Some(&mut "b"));
+    /// ```
+    pub fn insert(&mut self, k: K, v: V) -> Option<V> {
+        let old_val = self.map.insert(k, v);
+        if self.len() > self.capacity() {
+            self.remove_lru();
+        }
+        old_val
+    }
+
+    /// Returns a mutable reference to the value corresponding to the given key in the cache, if
+    /// any.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use lru_cache::LruCache;
+    ///
+    /// let mut cache = LruCache::new(2);
+    ///
+    /// cache.insert(1, "a");
+    /// cache.insert(2, "b");
+    /// cache.insert(2, "c");
+    /// cache.insert(3, "d");
+    ///
+    /// assert_eq!(cache.get_mut(&1), None);
+    /// assert_eq!(cache.get_mut(&2), Some(&mut "c"));
+    /// ```
+    pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
+        where K: Borrow<Q>,
+              Q: Hash + Eq
+    {
+        self.map.get_refresh(k)
+    }
+
+    /// Removes the given key from the cache and returns its corresponding value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use lru_cache::LruCache;
+    ///
+    /// let mut cache = LruCache::new(2);
+    ///
+    /// cache.insert(2, "a");
+    ///
+    /// assert_eq!(cache.remove(&1), None);
+    /// assert_eq!(cache.remove(&2), Some("a"));
+    /// assert_eq!(cache.remove(&2), None);
+    /// assert_eq!(cache.len(), 0);
+    /// ```
+    pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
+        where K: Borrow<Q>,
+              Q: Hash + Eq
+    {
+        self.map.remove(k)
+    }
+
+    /// Returns the maximum number of key-value pairs the cache can hold.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use lru_cache::LruCache;
+    /// let mut cache: LruCache<i32, &str> = LruCache::new(2);
+    /// assert_eq!(cache.capacity(), 2);
+    /// ```
+    pub fn capacity(&self) -> usize {
+        self.max_size
+    }
+
+    /// Sets the number of key-value pairs the cache can hold. Removes
+    /// least-recently-used key-value pairs if necessary.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use lru_cache::LruCache;
+    ///
+    /// let mut cache = LruCache::new(2);
+    ///
+    /// cache.insert(1, "a");
+    /// cache.insert(2, "b");
+    /// cache.insert(3, "c");
+    ///
+    /// assert_eq!(cache.get_mut(&1), None);
+    /// assert_eq!(cache.get_mut(&2), Some(&mut "b"));
+    /// assert_eq!(cache.get_mut(&3), Some(&mut "c"));
+    ///
+    /// cache.set_capacity(3);
+    /// cache.insert(1, "a");
+    /// cache.insert(2, "b");
+    ///
+    /// assert_eq!(cache.get_mut(&1), Some(&mut "a"));
+    /// assert_eq!(cache.get_mut(&2), Some(&mut "b"));
+    /// assert_eq!(cache.get_mut(&3), Some(&mut "c"));
+    ///
+    /// cache.set_capacity(1);
+    ///
+    /// assert_eq!(cache.get_mut(&1), None);
+    /// assert_eq!(cache.get_mut(&2), None);
+    /// assert_eq!(cache.get_mut(&3), Some(&mut "c"));
+    /// ```
+    pub fn set_capacity(&mut self, capacity: usize) {
+        for _ in capacity..self.len() {
+            self.remove_lru();
+        }
+        self.max_size = capacity;
+    }
+
+    /// Removes and returns the least recently used key-value pair as a tuple.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use lru_cache::LruCache;
+    ///
+    /// let mut cache = LruCache::new(2);
+    ///
+    /// cache.insert(1, "a");
+    /// cache.insert(2, "b");
+    ///
+    /// assert_eq!(cache.remove_lru(), Some((1, "a")));
+    /// assert_eq!(cache.len(), 1);
+    /// ```
+    #[inline]
+    pub fn remove_lru(&mut self) -> Option<(K, V)> {
+        self.map.pop_front()
+    }
+
+    /// Returns the number of key-value pairs in the cache.
+    pub fn len(&self) -> usize { self.map.len() }
+
+    /// Returns `true` if the cache contains no key-value pairs.
+    pub fn is_empty(&self) -> bool { self.map.is_empty() }
+
+    /// Removes all key-value pairs from the cache.
+    pub fn clear(&mut self) { self.map.clear(); }
+
+    /// Returns an iterator over the cache's key-value pairs in least- to most-recently-used order.
+    ///
+    /// Accessing the cache through the iterator does _not_ affect the cache's LRU state.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use lru_cache::LruCache;
+    ///
+    /// let mut cache = LruCache::new(2);
+    ///
+    /// cache.insert(1, 10);
+    /// cache.insert(2, 20);
+    /// cache.insert(3, 30);
+    ///
+    /// let kvs: Vec<_> = cache.iter().collect();
+    /// assert_eq!(kvs, [(&2, &20), (&3, &30)]);
+    /// ```
+    pub fn iter(&self) -> Iter<K, V> { Iter(self.map.iter()) }
+
+    /// Returns an iterator over the cache's key-value pairs in least- to most-recently-used order,
+    /// with mutable references to the values.
+    ///
+    /// Accessing the cache through the iterator does _not_ affect the cache's LRU state.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use lru_cache::LruCache;
+    ///
+    /// let mut cache = LruCache::new(2);
+    ///
+    /// cache.insert(1, 10);
+    /// cache.insert(2, 20);
+    /// cache.insert(3, 30);
+    ///
+    /// let mut n = 2;
+    ///
+    /// for (k, v) in cache.iter_mut() {
+    ///     assert_eq!(*k, n);
+    ///     assert_eq!(*v, n * 10);
+    ///     *v *= 10;
+    ///     n += 1;
+    /// }
+    ///
+    /// assert_eq!(n, 4);
+    /// assert_eq!(cache.get_mut(&2), Some(&mut 200));
+    /// assert_eq!(cache.get_mut(&3), Some(&mut 300));
+    /// ```
+    pub fn iter_mut(&mut self) -> IterMut<K, V> { IterMut(self.map.iter_mut()) }
+}
+
+impl<K: Eq + Hash, V, S: BuildHasher> Extend<(K, V)> for LruCache<K, V, S> {
+    fn extend<I: IntoIterator<Item=(K, V)>>(&mut self, iter: I) {
+        for (k, v) in iter {
+            self.insert(k, v);
+        }
+    }
+}
+
+impl<K: fmt::Debug + Eq + Hash, V: fmt::Debug, S: BuildHasher> fmt::Debug for LruCache<K, V, S> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_map().entries(self.iter().rev()).finish()
+    }
+}
+
+impl<K: Eq + Hash, V, S: BuildHasher> IntoIterator for LruCache<K, V, S> {
+    type Item = (K, V);
+    type IntoIter = IntoIter<K, V>;
+
+    fn into_iter(self) -> IntoIter<K, V> {
+        IntoIter(self.map.into_iter())
+    }
+}
+
+impl<'a, K: Eq + Hash, V, S: BuildHasher> IntoIterator for &'a LruCache<K, V, S> {
+    type Item = (&'a K, &'a V);
+    type IntoIter = Iter<'a, K, V>;
+    fn into_iter(self) -> Iter<'a, K, V> { self.iter() }
+}
+
+impl<'a, K: Eq + Hash, V, S: BuildHasher> IntoIterator for &'a mut LruCache<K, V, S> {
+    type Item = (&'a K, &'a mut V);
+    type IntoIter = IterMut<'a, K, V>;
+    fn into_iter(self) -> IterMut<'a, K, V> { self.iter_mut() }
+}
+
+/// An iterator over a cache's key-value pairs in least- to most-recently-used order.
+///
+/// # Examples
+///
+/// ```
+/// use lru_cache::LruCache;
+///
+/// let mut cache = LruCache::new(2);
+///
+/// cache.insert(1, 10);
+/// cache.insert(2, 20);
+/// cache.insert(3, 30);
+///
+/// let mut n = 2;
+///
+/// for (k, v) in cache {
+///     assert_eq!(k, n);
+///     assert_eq!(v, n * 10);
+///     n += 1;
+/// }
+///
+/// assert_eq!(n, 4);
+/// ```
+#[derive(Clone)]
+pub struct IntoIter<K, V>(linked_hash_map::IntoIter<K, V>);
+
+impl<K, V> Iterator for IntoIter<K, V> {
+    type Item = (K, V);
+
+    fn next(&mut self) -> Option<(K, V)> {
+        self.0.next()
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.0.size_hint()
+    }
+}
+
+impl<K, V> DoubleEndedIterator for IntoIter<K, V> {
+    fn next_back(&mut self) -> Option<(K, V)> {
+        self.0.next_back()
+    }
+}
+
+impl<K, V> ExactSizeIterator for IntoIter<K, V> {
+    fn len(&self) -> usize {
+        self.0.len()
+    }
+}
+
+/// An iterator over a cache's key-value pairs in least- to most-recently-used order.
+///
+/// Accessing a cache through the iterator does _not_ affect the cache's LRU state.
+pub struct Iter<'a, K: 'a, V: 'a>(linked_hash_map::Iter<'a, K, V>);
+
+impl<'a, K, V> Clone for Iter<'a, K, V> {
+    fn clone(&self) -> Iter<'a, K, V> { Iter(self.0.clone()) }
+}
+
+impl<'a, K, V> Iterator for Iter<'a, K, V> {
+    type Item = (&'a K, &'a V);
+    fn next(&mut self) -> Option<(&'a K, &'a V)> { self.0.next() }
+    fn size_hint(&self) -> (usize, Option<usize>) { self.0.size_hint() }
+}
+
+impl<'a, K, V> DoubleEndedIterator for Iter<'a, K, V> {
+    fn next_back(&mut self) -> Option<(&'a K, &'a V)> { self.0.next_back() }
+}
+
+impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {
+    fn len(&self) -> usize { self.0.len() }
+}
+
+/// An iterator over a cache's key-value pairs in least- to most-recently-used order with mutable
+/// references to the values.
+///
+/// Accessing a cache through the iterator does _not_ affect the cache's LRU state.
+pub struct IterMut<'a, K: 'a, V: 'a>(linked_hash_map::IterMut<'a, K, V>);
+
+impl<'a, K, V> Iterator for IterMut<'a, K, V> {
+    type Item = (&'a K, &'a mut V);
+    fn next(&mut self) -> Option<(&'a K, &'a mut V)> { self.0.next() }
+    fn size_hint(&self) -> (usize, Option<usize>) { self.0.size_hint() }
+}
+
+impl<'a, K, V> DoubleEndedIterator for IterMut<'a, K, V> {
+    fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> { self.0.next_back() }
+}
+
+impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> {
+    fn len(&self) -> usize { self.0.len() }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::LruCache;
+
+    #[test]
+    fn test_put_and_get() {
+        let mut cache = LruCache::new(2);
+        cache.insert(1, 10);
+        cache.insert(2, 20);
+        assert_eq!(cache.get_mut(&1), Some(&mut 10));
+        assert_eq!(cache.get_mut(&2), Some(&mut 20));
+        assert_eq!(cache.len(), 2);
+    }
+
+    #[test]
+    fn test_put_update() {
+        let mut cache = LruCache::new(1);
+        cache.insert("1", 10);
+        cache.insert("1", 19);
+        assert_eq!(cache.get_mut("1"), Some(&mut 19));
+        assert_eq!(cache.len(), 1);
+    }
+
+    #[test]
+    fn test_contains_key() {
+        let mut cache = LruCache::new(1);
+        cache.insert("1", 10);
+        assert_eq!(cache.contains_key("1"), true);
+    }
+
+    #[test]
+    fn test_expire_lru() {
+        let mut cache = LruCache::new(2);
+        cache.insert("foo1", "bar1");
+        cache.insert("foo2", "bar2");
+        cache.insert("foo3", "bar3");
+        assert!(cache.get_mut("foo1").is_none());
+        cache.insert("foo2", "bar2update");
+        cache.insert("foo4", "bar4");
+        assert!(cache.get_mut("foo3").is_none());
+    }
+
+    #[test]
+    fn test_pop() {
+        let mut cache = LruCache::new(2);
+        cache.insert(1, 10);
+        cache.insert(2, 20);
+        assert_eq!(cache.len(), 2);
+        let opt1 = cache.remove(&1);
+        assert!(opt1.is_some());
+        assert_eq!(opt1.unwrap(), 10);
+        assert!(cache.get_mut(&1).is_none());
+        assert_eq!(cache.len(), 1);
+    }
+
+    #[test]
+    fn test_change_capacity() {
+        let mut cache = LruCache::new(2);
+        assert_eq!(cache.capacity(), 2);
+        cache.insert(1, 10);
+        cache.insert(2, 20);
+        cache.set_capacity(1);
+        assert!(cache.get_mut(&1).is_none());
+        assert_eq!(cache.capacity(), 1);
+    }
+
+    #[test]
+    fn test_debug() {
+        let mut cache = LruCache::new(3);
+        cache.insert(1, 10);
+        cache.insert(2, 20);
+        cache.insert(3, 30);
+        assert_eq!(format!("{:?}", cache), "{3: 30, 2: 20, 1: 10}");
+        cache.insert(2, 22);
+        assert_eq!(format!("{:?}", cache), "{2: 22, 3: 30, 1: 10}");
+        cache.insert(6, 60);
+        assert_eq!(format!("{:?}", cache), "{6: 60, 2: 22, 3: 30}");
+        cache.get_mut(&3);
+        assert_eq!(format!("{:?}", cache), "{3: 30, 6: 60, 2: 22}");
+        cache.set_capacity(2);
+        assert_eq!(format!("{:?}", cache), "{3: 30, 6: 60}");
+    }
+
+    #[test]
+    fn test_remove() {
+        let mut cache = LruCache::new(3);
+        cache.insert(1, 10);
+        cache.insert(2, 20);
+        cache.insert(3, 30);
+        cache.insert(4, 40);
+        cache.insert(5, 50);
+        cache.remove(&3);
+        cache.remove(&4);
+        assert!(cache.get_mut(&3).is_none());
+        assert!(cache.get_mut(&4).is_none());
+        cache.insert(6, 60);
+        cache.insert(7, 70);
+        cache.insert(8, 80);
+        assert!(cache.get_mut(&5).is_none());
+        assert_eq!(cache.get_mut(&6), Some(&mut 60));
+        assert_eq!(cache.get_mut(&7), Some(&mut 70));
+        assert_eq!(cache.get_mut(&8), Some(&mut 80));
+    }
+
+    #[test]
+    fn test_clear() {
+        let mut cache = LruCache::new(2);
+        cache.insert(1, 10);
+        cache.insert(2, 20);
+        cache.clear();
+        assert!(cache.get_mut(&1).is_none());
+        assert!(cache.get_mut(&2).is_none());
+        assert_eq!(format!("{:?}", cache), "{}");
+    }
+
+    #[test]
+    fn test_iter() {
+        let mut cache = LruCache::new(3);
+        cache.insert(1, 10);
+        cache.insert(2, 20);
+        cache.insert(3, 30);
+        cache.insert(4, 40);
+        cache.insert(5, 50);
+        assert_eq!(cache.iter().collect::<Vec<_>>(),
+                   [(&3, &30), (&4, &40), (&5, &50)]);
+        assert_eq!(cache.iter_mut().collect::<Vec<_>>(),
+                   [(&3, &mut 30), (&4, &mut 40), (&5, &mut 50)]);
+        assert_eq!(cache.iter().rev().collect::<Vec<_>>(),
+                   [(&5, &50), (&4, &40), (&3, &30)]);
+        assert_eq!(cache.iter_mut().rev().collect::<Vec<_>>(),
+                   [(&5, &mut 50), (&4, &mut 40), (&3, &mut 30)]);
+    }
+}
diff --git a/third_party/rust_crates/vendor/smallvec-0.6.13/.cargo-checksum.json b/third_party/rust_crates/vendor/smallvec-0.6.13/.cargo-checksum.json
new file mode 100644
index 0000000..5ef6f73
--- /dev/null
+++ b/third_party/rust_crates/vendor/smallvec-0.6.13/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"9b9dd0b09c80450d9b16308948eef9675bec260a4cd738572ff67e8d7d271f9c","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0b28172679e0009b655da42797c03fd163a3379d5cfa67ba1f1655e974a2a1a9","README.md":"38eef4ebde6fe6effa12a2dbca3bd69d6446b2935f19a329ac4926f1cb2e5013","benches/bench.rs":"9dca7122a3dcb2c099e49807e4d3b8f01d9220e2b3db0a54e9901ee74392866f","lib.rs":"f2f9c0f77e63672496591328cb90358d1a7d664aae8e7dee59cd0525010649cb","scripts/run_miri.sh":"cd645dfecf19cc77141ecaf698e58a3a743ad69aca5e5d25c8e5d3911e031322","specialization.rs":"b29ac094999b94cc193dde52432e8cd8d17a299192822b3485c27bf6a1bdc397"},"package":"f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6"}
\ No newline at end of file
diff --git a/third_party/rust_crates/vendor/smallvec-0.6.13/Cargo.toml b/third_party/rust_crates/vendor/smallvec-0.6.13/Cargo.toml
new file mode 100644
index 0000000..6d1679e
--- /dev/null
+++ b/third_party/rust_crates/vendor/smallvec-0.6.13/Cargo.toml
@@ -0,0 +1,42 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "smallvec"
+version = "0.6.13"
+authors = ["Simon Sapin <simon.sapin@exyr.org>"]
+description = "'Small vector' optimization: store up to a small number of items on the stack"
+documentation = "https://doc.servo.org/smallvec/"
+readme = "README.md"
+keywords = ["small", "vec", "vector", "stack", "no_std"]
+categories = ["data-structures"]
+license = "MIT/Apache-2.0"
+repository = "https://github.com/servo/rust-smallvec"
+
+[lib]
+name = "smallvec"
+path = "lib.rs"
+[dependencies.maybe-uninit]
+version = "2.0"
+
+[dependencies.serde]
+version = "1"
+optional = true
+[dev-dependencies.bincode]
+version = "1.0.1"
+
+[features]
+default = ["std"]
+may_dangle = []
+specialization = []
+std = []
+union = []
diff --git a/third_party/rust_crates/vendor/smallvec-0.6.13/LICENSE-APACHE b/third_party/rust_crates/vendor/smallvec-0.6.13/LICENSE-APACHE
new file mode 100644
index 0000000..16fe87b
--- /dev/null
+++ b/third_party/rust_crates/vendor/smallvec-0.6.13/LICENSE-APACHE
@@ -0,0 +1,201 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+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.
diff --git a/third_party/rust_crates/vendor/smallvec-0.6.13/LICENSE-MIT b/third_party/rust_crates/vendor/smallvec-0.6.13/LICENSE-MIT
new file mode 100644
index 0000000..9729c12
--- /dev/null
+++ b/third_party/rust_crates/vendor/smallvec-0.6.13/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2018 The Servo Project Developers
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/third_party/rust_crates/vendor/smallvec-0.6.13/README.md b/third_party/rust_crates/vendor/smallvec-0.6.13/README.md
new file mode 100644
index 0000000..fda7fd4
--- /dev/null
+++ b/third_party/rust_crates/vendor/smallvec-0.6.13/README.md
@@ -0,0 +1,8 @@
+rust-smallvec
+=============
+
+[Documentation](https://docs.rs/smallvec/)
+
+[Release notes](https://github.com/servo/rust-smallvec/releases)
+
+"Small vector" optimization for Rust: store up to a small number of items on the stack
diff --git a/third_party/rust_crates/vendor/smallvec-0.6.13/benches/bench.rs b/third_party/rust_crates/vendor/smallvec-0.6.13/benches/bench.rs
new file mode 100644
index 0000000..36cb133
--- /dev/null
+++ b/third_party/rust_crates/vendor/smallvec-0.6.13/benches/bench.rs
@@ -0,0 +1,295 @@
+#![feature(test)]
+
+#[macro_use]
+extern crate smallvec;
+extern crate test;
+
+use self::test::Bencher;
+use smallvec::{ExtendFromSlice, SmallVec};
+
+const VEC_SIZE: usize = 16;
+const SPILLED_SIZE: usize = 100;
+
+trait Vector<T>: for<'a> From<&'a [T]> + Extend<T> + ExtendFromSlice<T> {
+    fn new() -> Self;
+    fn push(&mut self, val: T);
+    fn pop(&mut self) -> Option<T>;
+    fn remove(&mut self, p: usize) -> T;
+    fn insert(&mut self, n: usize, val: T);
+    fn from_elem(val: T, n: usize) -> Self;
+    fn from_elems(val: &[T]) -> Self;
+}
+
+impl<T: Copy> Vector<T> for Vec<T> {
+    fn new() -> Self {
+        Self::with_capacity(VEC_SIZE)
+    }
+
+    fn push(&mut self, val: T) {
+        self.push(val)
+    }
+
+    fn pop(&mut self) -> Option<T> {
+        self.pop()
+    }
+
+    fn remove(&mut self, p: usize) -> T {
+        self.remove(p)
+    }
+
+    fn insert(&mut self, n: usize, val: T) {
+        self.insert(n, val)
+    }
+
+    fn from_elem(val: T, n: usize) -> Self {
+        vec![val; n]
+    }
+
+    fn from_elems(val: &[T]) -> Self {
+        val.to_owned()
+    }
+}
+
+impl<T: Copy> Vector<T> for SmallVec<[T; VEC_SIZE]> {
+    fn new() -> Self {
+        Self::new()
+    }
+
+    fn push(&mut self, val: T) {
+        self.push(val)
+    }
+
+    fn pop(&mut self) -> Option<T> {
+        self.pop()
+    }
+
+    fn remove(&mut self, p: usize) -> T {
+        self.remove(p)
+    }
+
+    fn insert(&mut self, n: usize, val: T) {
+        self.insert(n, val)
+    }
+
+    fn from_elem(val: T, n: usize) -> Self {
+        smallvec![val; n]
+    }
+
+    fn from_elems(val: &[T]) -> Self {
+        SmallVec::from_slice(val)
+    }
+}
+
+macro_rules! make_benches {
+    ($typ:ty { $($b_name:ident => $g_name:ident($($args:expr),*),)* }) => {
+        $(
+            #[bench]
+            fn $b_name(b: &mut Bencher) {
+                $g_name::<$typ>($($args,)* b)
+            }
+        )*
+    }
+}
+
+make_benches! {
+    SmallVec<[u64; VEC_SIZE]> {
+        bench_push => gen_push(SPILLED_SIZE as _),
+        bench_push_small => gen_push(VEC_SIZE as _),
+        bench_insert => gen_insert(SPILLED_SIZE as _),
+        bench_insert_small => gen_insert(VEC_SIZE as _),
+        bench_remove => gen_remove(SPILLED_SIZE as _),
+        bench_remove_small => gen_remove(VEC_SIZE as _),
+        bench_extend => gen_extend(SPILLED_SIZE as _),
+        bench_extend_small => gen_extend(VEC_SIZE as _),
+        bench_from_iter => gen_from_iter(SPILLED_SIZE as _),
+        bench_from_iter_small => gen_from_iter(VEC_SIZE as _),
+        bench_from_slice => gen_from_slice(SPILLED_SIZE as _),
+        bench_from_slice_small => gen_from_slice(VEC_SIZE as _),
+        bench_extend_from_slice => gen_extend_from_slice(SPILLED_SIZE as _),
+        bench_extend_from_slice_small => gen_extend_from_slice(VEC_SIZE as _),
+        bench_macro_from_elem => gen_from_elem(SPILLED_SIZE as _),
+        bench_macro_from_elem_small => gen_from_elem(VEC_SIZE as _),
+        bench_pushpop => gen_pushpop(),
+    }
+}
+
+make_benches! {
+    Vec<u64> {
+        bench_push_vec => gen_push(SPILLED_SIZE as _),
+        bench_push_vec_small => gen_push(VEC_SIZE as _),
+        bench_insert_vec => gen_insert(SPILLED_SIZE as _),
+        bench_insert_vec_small => gen_insert(VEC_SIZE as _),
+        bench_remove_vec => gen_remove(SPILLED_SIZE as _),
+        bench_remove_vec_small => gen_remove(VEC_SIZE as _),
+        bench_extend_vec => gen_extend(SPILLED_SIZE as _),
+        bench_extend_vec_small => gen_extend(VEC_SIZE as _),
+        bench_from_iter_vec => gen_from_iter(SPILLED_SIZE as _),
+        bench_from_iter_vec_small => gen_from_iter(VEC_SIZE as _),
+        bench_from_slice_vec => gen_from_slice(SPILLED_SIZE as _),
+        bench_from_slice_vec_small => gen_from_slice(VEC_SIZE as _),
+        bench_extend_from_slice_vec => gen_extend_from_slice(SPILLED_SIZE as _),
+        bench_extend_from_slice_vec_small => gen_extend_from_slice(VEC_SIZE as _),
+        bench_macro_from_elem_vec => gen_from_elem(SPILLED_SIZE as _),
+        bench_macro_from_elem_vec_small => gen_from_elem(VEC_SIZE as _),
+        bench_pushpop_vec => gen_pushpop(),
+    }
+}
+
+fn gen_push<V: Vector<u64>>(n: u64, b: &mut Bencher) {
+    #[inline(never)]
+    fn push_noinline<V: Vector<u64>>(vec: &mut V, x: u64) {
+        vec.push(x);
+    }
+
+    b.iter(|| {
+        let mut vec = V::new();
+        for x in 0..n {
+            push_noinline(&mut vec, x);
+        }
+        vec
+    });
+}
+
+fn gen_insert<V: Vector<u64>>(n: u64, b: &mut Bencher) {
+    #[inline(never)]
+    fn insert_noinline<V: Vector<u64>>(vec: &mut V, p: usize, x: u64) {
+        vec.insert(p, x)
+    }
+
+    b.iter(|| {
+        let mut vec = V::new();
+        // Add one element, with each iteration we insert one before the end.
+        // This means that we benchmark the insertion operation and not the
+        // time it takes to `ptr::copy` the data.
+        vec.push(0);
+        for x in 0..n {
+            insert_noinline(&mut vec, x as _, x);
+        }
+        vec
+    });
+}
+
+fn gen_remove<V: Vector<u64>>(n: usize, b: &mut Bencher) {
+    #[inline(never)]
+    fn remove_noinline<V: Vector<u64>>(vec: &mut V, p: usize) -> u64 {
+        vec.remove(p)
+    }
+
+    b.iter(|| {
+        let mut vec = V::from_elem(0, n as _);
+
+        for x in (0..n - 1).rev() {
+            remove_noinline(&mut vec, x);
+        }
+    });
+}
+
+fn gen_extend<V: Vector<u64>>(n: u64, b: &mut Bencher) {
+    b.iter(|| {
+        let mut vec = V::new();
+        vec.extend(0..n);
+        vec
+    });
+}
+
+fn gen_from_iter<V: Vector<u64>>(n: u64, b: &mut Bencher) {
+    let v: Vec<u64> = (0..n).collect();
+    b.iter(|| {
+        let vec = V::from(&v);
+        vec
+    });
+}
+
+fn gen_from_slice<V: Vector<u64>>(n: u64, b: &mut Bencher) {
+    let v: Vec<u64> = (0..n).collect();
+    b.iter(|| {
+        let vec = V::from_elems(&v);
+        vec
+    });
+}
+
+fn gen_extend_from_slice<V: Vector<u64>>(n: u64, b: &mut Bencher) {
+    let v: Vec<u64> = (0..n).collect();
+    b.iter(|| {
+        let mut vec = V::new();
+        vec.extend_from_slice(&v);
+        vec
+    });
+}
+
+fn gen_pushpop<V: Vector<u64>>(b: &mut Bencher) {
+    #[inline(never)]
+    fn pushpop_noinline<V: Vector<u64>>(vec: &mut V, x: u64) -> Option<u64> {
+        vec.push(x);
+        vec.pop()
+    }
+
+    b.iter(|| {
+        let mut vec = V::new();
+        for x in 0..SPILLED_SIZE as _ {
+            pushpop_noinline(&mut vec, x);
+        }
+        vec
+    });
+}
+
+fn gen_from_elem<V: Vector<u64>>(n: usize, b: &mut Bencher) {
+    b.iter(|| {
+        let vec = V::from_elem(42, n);
+        vec
+    });
+}
+
+#[bench]
+fn bench_insert_many(b: &mut Bencher) {
+    #[inline(never)]
+    fn insert_many_noinline<I: IntoIterator<Item = u64>>(
+        vec: &mut SmallVec<[u64; VEC_SIZE]>,
+        index: usize,
+        iterable: I,
+    ) {
+        vec.insert_many(index, iterable)
+    }
+
+    b.iter(|| {
+        let mut vec = SmallVec::<[u64; VEC_SIZE]>::new();
+        insert_many_noinline(&mut vec, 0, 0..SPILLED_SIZE as _);
+        insert_many_noinline(&mut vec, 0, 0..SPILLED_SIZE as _);
+        vec
+    });
+}
+
+#[bench]
+fn bench_insert_from_slice(b: &mut Bencher) {
+    let v: Vec<u64> = (0..SPILLED_SIZE as _).collect();
+    b.iter(|| {
+        let mut vec = SmallVec::<[u64; VEC_SIZE]>::new();
+        vec.insert_from_slice(0, &v);
+        vec.insert_from_slice(0, &v);
+        vec
+    });
+}
+
+#[bench]
+fn bench_macro_from_list(b: &mut Bencher) {
+    b.iter(|| {
+        let vec: SmallVec<[u64; 16]> = smallvec![
+            0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32, 36, 0x40, 0x80,
+            0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000,
+            0x80000, 0x100000,
+        ];
+        vec
+    });
+}
+
+#[bench]
+fn bench_macro_from_list_vec(b: &mut Bencher) {
+    b.iter(|| {
+        let vec: Vec<u64> = vec![
+            0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32, 36, 0x40, 0x80,
+            0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000,
+            0x80000, 0x100000,
+        ];
+        vec
+    });
+}
diff --git a/third_party/rust_crates/vendor/smallvec-0.6.13/lib.rs b/third_party/rust_crates/vendor/smallvec-0.6.13/lib.rs
new file mode 100644
index 0000000..55278ad
--- /dev/null
+++ b/third_party/rust_crates/vendor/smallvec-0.6.13/lib.rs
@@ -0,0 +1,2374 @@
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Small vectors in various sizes. These store a certain number of elements inline, and fall back
+//! to the heap for larger allocations.  This can be a useful optimization for improving cache
+//! locality and reducing allocator traffic for workloads that fit within the inline buffer.
+//!
+//! ## no_std support
+//!
+//! By default, `smallvec` depends on `libstd`. However, it can be configured to use the unstable
+//! `liballoc` API instead, for use on platforms that have `liballoc` but not `libstd`.  This
+//! configuration is currently unstable and is not guaranteed to work on all versions of Rust.
+//!
+//! To depend on `smallvec` without `libstd`, use `default-features = false` in the `smallvec`
+//! section of Cargo.toml to disable its `"std"` feature.
+//!
+//! ## `union` feature
+//!
+//! When the `union` feature is enabled `smallvec` will track its state (inline or spilled)
+//! without the use of an enum tag, reducing the size of the `smallvec` by one machine word.
+//! This means that there is potentially no space overhead compared to `Vec`.
+//! Note that `smallvec` can still be larger than `Vec` if the inline buffer is larger than two
+//! machine words.
+//!
+//! To use this feature add `features = ["union"]` in the `smallvec` section of Cargo.toml.
+//! Note that this feature requires a nightly compiler (for now).
+
+#![cfg_attr(not(feature = "std"), no_std)]
+#![cfg_attr(feature = "union", feature(untagged_unions))]
+#![cfg_attr(feature = "specialization", feature(specialization))]
+#![cfg_attr(feature = "may_dangle", feature(dropck_eyepatch))]
+#![deny(missing_docs)]
+
+
+#[cfg(not(feature = "std"))]
+#[macro_use]
+extern crate alloc;
+
+#[cfg(not(feature = "std"))]
+use alloc::vec::Vec;
+
+#[cfg(feature = "serde")]
+extern crate serde;
+
+extern crate maybe_uninit;
+
+#[cfg(not(feature = "std"))]
+mod std {
+    pub use core::*;
+}
+
+use maybe_uninit::MaybeUninit;
+
+use std::borrow::{Borrow, BorrowMut};
+use std::cmp;
+use std::fmt;
+use std::hash::{Hash, Hasher};
+use std::iter::{IntoIterator, FromIterator, repeat};
+use std::mem;
+use std::ops;
+use std::ptr;
+use std::slice;
+#[cfg(feature = "std")]
+use std::io;
+#[cfg(feature = "serde")]
+use serde::ser::{Serialize, Serializer, SerializeSeq};
+#[cfg(feature = "serde")]
+use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor};
+#[cfg(feature = "serde")]
+use std::marker::PhantomData;
+
+/// Creates a [`SmallVec`] containing the arguments.
+///
+/// `smallvec!` allows `SmallVec`s to be defined with the same syntax as array expressions.
+/// There are two forms of this macro:
+///
+/// - Create a [`SmallVec`] containing a given list of elements:
+///
+/// ```
+/// # #[macro_use] extern crate smallvec;
+/// # use smallvec::SmallVec;
+/// # fn main() {
+/// let v: SmallVec<[_; 128]> = smallvec![1, 2, 3];
+/// assert_eq!(v[0], 1);
+/// assert_eq!(v[1], 2);
+/// assert_eq!(v[2], 3);
+/// # }
+/// ```
+///
+/// - Create a [`SmallVec`] from a given element and size:
+///
+/// ```
+/// # #[macro_use] extern crate smallvec;
+/// # use smallvec::SmallVec;
+/// # fn main() {
+/// let v: SmallVec<[_; 0x8000]> = smallvec![1; 3];
+/// assert_eq!(v, SmallVec::from_buf([1, 1, 1]));
+/// # }
+/// ```
+///
+/// Note that unlike array expressions this syntax supports all elements
+/// which implement [`Clone`] and the number of elements doesn't have to be
+/// a constant.
+///
+/// This will use `clone` to duplicate an expression, so one should be careful
+/// using this with types having a nonstandard `Clone` implementation. For
+/// example, `smallvec![Rc::new(1); 5]` will create a vector of five references
+/// to the same boxed integer value, not five references pointing to independently
+/// boxed integers.
+
+#[macro_export]
+macro_rules! smallvec {
+    // count helper: transform any expression into 1
+    (@one $x:expr) => (1usize);
+    ($elem:expr; $n:expr) => ({
+        $crate::SmallVec::from_elem($elem, $n)
+    });
+    ($($x:expr),*$(,)*) => ({
+        let count = 0usize $(+ smallvec!(@one $x))*;
+        let mut vec = $crate::SmallVec::new();
+        if count <= vec.inline_size() {
+            $(vec.push($x);)*
+            vec
+        } else {
+            $crate::SmallVec::from_vec(vec![$($x,)*])
+        }
+    });
+}
+
+/// Hint to the optimizer that any code path which calls this function is
+/// statically unreachable and can be removed.
+///
+/// Equivalent to `std::hint::unreachable_unchecked` but works in older versions of Rust.
+#[inline]
+pub unsafe fn unreachable() -> ! {
+    enum Void {}
+    let x: &Void = mem::transmute(1usize);
+    match *x {}
+}
+
+/// `panic!()` in debug builds, optimization hint in release.
+#[cfg(not(feature = "union"))]
+macro_rules! debug_unreachable {
+    () => { debug_unreachable!("entered unreachable code") };
+    ($e:expr) => {
+        if cfg!(not(debug_assertions)) {
+            unreachable();
+        } else {
+            panic!($e);
+        }
+    }
+}
+
+/// Common operations implemented by both `Vec` and `SmallVec`.
+///
+/// This can be used to write generic code that works with both `Vec` and `SmallVec`.
+///
+/// ## Example
+///
+/// ```rust
+/// use smallvec::{VecLike, SmallVec};
+///
+/// fn initialize<V: VecLike<u8>>(v: &mut V) {
+///     for i in 0..5 {
+///         v.push(i);
+///     }
+/// }
+///
+/// let mut vec = Vec::new();
+/// initialize(&mut vec);
+///
+/// let mut small_vec = SmallVec::<[u8; 8]>::new();
+/// initialize(&mut small_vec);
+/// ```
+#[deprecated(note = "Use `Extend` and `Deref<[T]>` instead")]
+pub trait VecLike<T>:
+        ops::Index<usize, Output=T> +
+        ops::IndexMut<usize> +
+        ops::Index<ops::Range<usize>, Output=[T]> +
+        ops::IndexMut<ops::Range<usize>> +
+        ops::Index<ops::RangeFrom<usize>, Output=[T]> +
+        ops::IndexMut<ops::RangeFrom<usize>> +
+        ops::Index<ops::RangeTo<usize>, Output=[T]> +
+        ops::IndexMut<ops::RangeTo<usize>> +
+        ops::Index<ops::RangeFull, Output=[T]> +
+        ops::IndexMut<ops::RangeFull> +
+        ops::DerefMut<Target = [T]> +
+        Extend<T> {
+
+    /// Append an element to the vector.
+    fn push(&mut self, value: T);
+}
+
+#[allow(deprecated)]
+impl<T> VecLike<T> for Vec<T> {
+    #[inline]
+    fn push(&mut self, value: T) {
+        Vec::push(self, value);
+    }
+}
+
+/// Trait to be implemented by a collection that can be extended from a slice
+///
+/// ## Example
+///
+/// ```rust
+/// use smallvec::{ExtendFromSlice, SmallVec};
+///
+/// fn initialize<V: ExtendFromSlice<u8>>(v: &mut V) {
+///     v.extend_from_slice(b"Test!");
+/// }
+///
+/// let mut vec = Vec::new();
+/// initialize(&mut vec);
+/// assert_eq!(&vec, b"Test!");
+///
+/// let mut small_vec = SmallVec::<[u8; 8]>::new();
+/// initialize(&mut small_vec);
+/// assert_eq!(&small_vec as &[_], b"Test!");
+/// ```
+pub trait ExtendFromSlice<T> {
+    /// Extends a collection from a slice of its element type
+    fn extend_from_slice(&mut self, other: &[T]);
+}
+
+impl<T: Clone> ExtendFromSlice<T> for Vec<T> {
+    fn extend_from_slice(&mut self, other: &[T]) {
+        Vec::extend_from_slice(self, other)
+    }
+}
+
+unsafe fn deallocate<T>(ptr: *mut T, capacity: usize) {
+    let _vec: Vec<T> = Vec::from_raw_parts(ptr, 0, capacity);
+    // Let it drop.
+}
+
+/// An iterator that removes the items from a `SmallVec` and yields them by value.
+///
+/// Returned from [`SmallVec::drain`][1].
+///
+/// [1]: struct.SmallVec.html#method.drain
+pub struct Drain<'a, T: 'a> {
+    iter: slice::IterMut<'a,T>,
+}
+
+impl<'a, T: 'a> Iterator for Drain<'a,T> {
+    type Item = T;
+
+    #[inline]
+    fn next(&mut self) -> Option<T> {
+        self.iter.next().map(|reference| unsafe { ptr::read(reference) })
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.iter.size_hint()
+    }
+}
+
+impl<'a, T: 'a> DoubleEndedIterator for Drain<'a, T> {
+    #[inline]
+    fn next_back(&mut self) -> Option<T> {
+        self.iter.next_back().map(|reference| unsafe { ptr::read(reference) })
+    }
+}
+
+impl<'a, T> ExactSizeIterator for Drain<'a, T> { }
+
+impl<'a, T: 'a> Drop for Drain<'a,T> {
+    fn drop(&mut self) {
+        // Destroy the remaining elements.
+        for _ in self.by_ref() {}
+    }
+}
+
+#[cfg(feature = "union")]
+union SmallVecData<A: Array> {
+    inline: MaybeUninit<A>,
+    heap: (*mut A::Item, usize),
+}
+
+#[cfg(feature = "union")]
+impl<A: Array> SmallVecData<A> {
+    #[inline]
+    unsafe fn inline(&self) -> *const A::Item {
+        self.inline.as_ptr() as *const A::Item
+    }
+    #[inline]
+    unsafe fn inline_mut(&mut self) -> *mut A::Item {
+        self.inline.as_mut_ptr() as *mut A::Item
+    }
+    #[inline]
+    fn from_inline(inline: MaybeUninit<A>) -> SmallVecData<A> {
+        SmallVecData { inline }
+    }
+    #[inline]
+    unsafe fn into_inline(self) -> MaybeUninit<A> {
+        self.inline
+    }
+    #[inline]
+    unsafe fn heap(&self) -> (*mut A::Item, usize) {
+        self.heap
+    }
+    #[inline]
+    unsafe fn heap_mut(&mut self) -> &mut (*mut A::Item, usize) {
+        &mut self.heap
+    }
+    #[inline]
+    fn from_heap(ptr: *mut A::Item, len: usize) -> SmallVecData<A> {
+        SmallVecData { heap: (ptr, len) }
+    }
+}
+
+#[cfg(not(feature = "union"))]
+enum SmallVecData<A: Array> {
+    Inline(MaybeUninit<A>),
+    Heap((*mut A::Item, usize)),
+}
+
+#[cfg(not(feature = "union"))]
+impl<A: Array> SmallVecData<A> {
+    #[inline]
+    unsafe fn inline(&self) -> *const A::Item {
+        match *self {
+            SmallVecData::Inline(ref a) => a.as_ptr() as *const A::Item,
+            _ => debug_unreachable!(),
+        }
+    }
+    #[inline]
+    unsafe fn inline_mut(&mut self) -> *mut A::Item {
+        match *self {
+            SmallVecData::Inline(ref mut a) => a.as_mut_ptr() as *mut A::Item,
+            _ => debug_unreachable!(),
+        }
+    }
+    #[inline]
+    fn from_inline(inline: MaybeUninit<A>) -> SmallVecData<A> {
+        SmallVecData::Inline(inline)
+    }
+    #[inline]
+    unsafe fn into_inline(self) -> MaybeUninit<A> {
+        match self {
+            SmallVecData::Inline(a) => a,
+            _ => debug_unreachable!(),
+        }
+    }
+    #[inline]
+    unsafe fn heap(&self) -> (*mut A::Item, usize) {
+        match *self {
+            SmallVecData::Heap(data) => data,
+            _ => debug_unreachable!(),
+        }
+    }
+    #[inline]
+    unsafe fn heap_mut(&mut self) -> &mut (*mut A::Item, usize) {
+        match *self {
+            SmallVecData::Heap(ref mut data) => data,
+            _ => debug_unreachable!(),
+        }
+    }
+    #[inline]
+    fn from_heap(ptr: *mut A::Item, len: usize) -> SmallVecData<A> {
+        SmallVecData::Heap((ptr, len))
+    }
+}
+
+unsafe impl<A: Array + Send> Send for SmallVecData<A> {}
+unsafe impl<A: Array + Sync> Sync for SmallVecData<A> {}
+
+/// A `Vec`-like container that can store a small number of elements inline.
+///
+/// `SmallVec` acts like a vector, but can store a limited amount of data inline within the
+/// `SmallVec` struct rather than in a separate allocation.  If the data exceeds this limit, the
+/// `SmallVec` will "spill" its data onto the heap, allocating a new buffer to hold it.
+///
+/// The amount of data that a `SmallVec` can store inline depends on its backing store. The backing
+/// store can be any type that implements the `Array` trait; usually it is a small fixed-sized
+/// array.  For example a `SmallVec<[u64; 8]>` can hold up to eight 64-bit integers inline.
+///
+/// ## Example
+///
+/// ```rust
+/// use smallvec::SmallVec;
+/// let mut v = SmallVec::<[u8; 4]>::new(); // initialize an empty vector
+///
+/// // The vector can hold up to 4 items without spilling onto the heap.
+/// v.extend(0..4);
+/// assert_eq!(v.len(), 4);
+/// assert!(!v.spilled());
+///
+/// // Pushing another element will force the buffer to spill:
+/// v.push(4);
+/// assert_eq!(v.len(), 5);
+/// assert!(v.spilled());
+/// ```
+pub struct SmallVec<A: Array> {
+    // The capacity field is used to determine which of the storage variants is active:
+    // If capacity <= A::size() then the inline variant is used and capacity holds the current length of the vector (number of elements actually in use).
+    // If capacity > A::size() then the heap variant is used and capacity holds the size of the memory allocation.
+    capacity: usize,
+    data: SmallVecData<A>,
+}
+
+impl<A: Array> SmallVec<A> {
+    /// Construct an empty vector
+    #[inline]
+    pub fn new() -> SmallVec<A> {
+        // Try to detect invalid custom implementations of `Array`. Hopefuly,
+        // this check should be optimized away entirely for valid ones.
+        assert!(
+            mem::size_of::<A>() == A::size() * mem::size_of::<A::Item>()
+                && mem::align_of::<A>() >= mem::align_of::<A::Item>()
+        );
+        SmallVec {
+            capacity: 0,
+            data: SmallVecData::from_inline(MaybeUninit::uninit()),
+        }
+    }
+
+    /// Construct an empty vector with enough capacity pre-allocated to store at least `n`
+    /// elements.
+    ///
+    /// Will create a heap allocation only if `n` is larger than the inline capacity.
+    ///
+    /// ```
+    /// # use smallvec::SmallVec;
+    ///
+    /// let v: SmallVec<[u8; 3]> = SmallVec::with_capacity(100);
+    ///
+    /// assert!(v.is_empty());
+    /// assert!(v.capacity() >= 100);
+    /// ```
+    #[inline]
+    pub fn with_capacity(n: usize) -> Self {
+        let mut v = SmallVec::new();
+        v.reserve_exact(n);
+        v
+    }
+
+    /// Construct a new `SmallVec` from a `Vec<A::Item>`.
+    ///
+    /// Elements will be copied to the inline buffer if vec.capacity() <= A::size().
+    ///
+    /// ```rust
+    /// use smallvec::SmallVec;
+    ///
+    /// let vec = vec![1, 2, 3, 4, 5];
+    /// let small_vec: SmallVec<[_; 3]> = SmallVec::from_vec(vec);
+    ///
+    /// assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]);
+    /// ```
+    #[inline]
+    pub fn from_vec(mut vec: Vec<A::Item>) -> SmallVec<A> {
+        if vec.capacity() <= A::size() {
+            unsafe {
+                let mut data = SmallVecData::<A>::from_inline(MaybeUninit::uninit());
+                let len = vec.len();
+                vec.set_len(0);
+                ptr::copy_nonoverlapping(vec.as_ptr(), data.inline_mut(), len);
+
+                SmallVec {
+                    capacity: len,
+                    data,
+                }
+            }
+        } else {
+            let (ptr, cap, len) = (vec.as_mut_ptr(), vec.capacity(), vec.len());
+            mem::forget(vec);
+
+            SmallVec {
+                capacity: cap,
+                data: SmallVecData::from_heap(ptr, len),
+            }
+        }
+    }
+
+    /// Constructs a new `SmallVec` on the stack from an `A` without
+    /// copying elements.
+    ///
+    /// ```rust
+    /// use smallvec::SmallVec;
+    ///
+    /// let buf = [1, 2, 3, 4, 5];
+    /// let small_vec: SmallVec<_> = SmallVec::from_buf(buf);
+    ///
+    /// assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]);
+    /// ```
+    #[inline]
+    pub fn from_buf(buf: A) -> SmallVec<A> {
+        SmallVec {
+            capacity: A::size(),
+            data: SmallVecData::from_inline(MaybeUninit::new(buf)),
+        }
+    }
+
+    /// Constructs a new `SmallVec` on the stack from an `A` without
+    /// copying elements. Also sets the length, which must be less or
+    /// equal to the size of `buf`.
+    ///
+    /// ```rust
+    /// use smallvec::SmallVec;
+    ///
+    /// let buf = [1, 2, 3, 4, 5, 0, 0, 0];
+    /// let small_vec: SmallVec<_> = SmallVec::from_buf_and_len(buf, 5);
+    ///
+    /// assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]);
+    /// ```
+    #[inline]
+    pub fn from_buf_and_len(buf: A, len: usize) -> SmallVec<A> {
+        assert!(len <= A::size());
+        unsafe { SmallVec::from_buf_and_len_unchecked(buf, len) }
+    }
+
+    /// Constructs a new `SmallVec` on the stack from an `A` without
+    /// copying elements. Also sets the length. The user is responsible
+    /// for ensuring that `len <= A::size()`.
+    ///
+    /// ```rust
+    /// use smallvec::SmallVec;
+    ///
+    /// let buf = [1, 2, 3, 4, 5, 0, 0, 0];
+    /// let small_vec: SmallVec<_> = unsafe {
+    ///     SmallVec::from_buf_and_len_unchecked(buf, 5)
+    /// };
+    ///
+    /// assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]);
+    /// ```
+    #[inline]
+    pub unsafe fn from_buf_and_len_unchecked(buf: A, len: usize) -> SmallVec<A> {
+        SmallVec {
+            capacity: len,
+            data: SmallVecData::from_inline(MaybeUninit::new(buf)),
+        }
+    }
+
+
+    /// Sets the length of a vector.
+    ///
+    /// This will explicitly set the size of the vector, without actually
+    /// modifying its buffers, so it is up to the caller to ensure that the
+    /// vector is actually the specified size.
+    pub unsafe fn set_len(&mut self, new_len: usize) {
+        let (_, len_ptr, _) = self.triple_mut();
+        *len_ptr = new_len;
+    }
+
+    /// The maximum number of elements this vector can hold inline
+    #[inline]
+    pub fn inline_size(&self) -> usize {
+        A::size()
+    }
+
+    /// The number of elements stored in the vector
+    #[inline]
+    pub fn len(&self) -> usize {
+        self.triple().1
+    }
+
+    /// Returns `true` if the vector is empty
+    #[inline]
+    pub fn is_empty(&self) -> bool {
+        self.len() == 0
+    }
+
+    /// The number of items the vector can hold without reallocating
+    #[inline]
+    pub fn capacity(&self) -> usize {
+        self.triple().2
+    }
+
+    /// Returns a tuple with (data ptr, len, capacity)
+    /// Useful to get all SmallVec properties with a single check of the current storage variant.
+    #[inline]
+    fn triple(&self) -> (*const A::Item, usize, usize) {
+        unsafe {
+            if self.spilled() {
+                let (ptr, len) = self.data.heap();
+                (ptr, len, self.capacity)
+            } else {
+                (self.data.inline(), self.capacity, A::size())
+            }
+        }
+    }
+
+    /// Returns a tuple with (data ptr, len ptr, capacity)
+    #[inline]
+    fn triple_mut(&mut self) -> (*mut A::Item, &mut usize, usize) {
+        unsafe {
+            if self.spilled() {
+                let &mut (ptr, ref mut len_ptr) = self.data.heap_mut();
+                (ptr, len_ptr, self.capacity)
+            } else {
+                (self.data.inline_mut(), &mut self.capacity, A::size())
+            }
+        }
+    }
+
+    /// Returns `true` if the data has spilled into a separate heap-allocated buffer.
+    #[inline]
+    pub fn spilled(&self) -> bool {
+        self.capacity > A::size()
+    }
+
+    /// Empty the vector and return an iterator over its former contents.
+    pub fn drain(&mut self) -> Drain<A::Item> {
+        unsafe {
+            let ptr = self.as_mut_ptr();
+
+            let current_len = self.len();
+            self.set_len(0);
+
+            let slice = slice::from_raw_parts_mut(ptr, current_len);
+
+            Drain {
+                iter: slice.iter_mut(),
+            }
+        }
+    }
+
+    /// Append an item to the vector.
+    #[inline]
+    pub fn push(&mut self, value: A::Item) {
+        unsafe {
+            let (_, &mut len, cap) = self.triple_mut();
+            if len == cap {
+                self.reserve(1);
+            }
+            let (ptr, len_ptr, _) = self.triple_mut();
+            *len_ptr = len + 1;
+            ptr::write(ptr.offset(len as isize), value);
+        }
+    }
+
+    /// Remove an item from the end of the vector and return it, or None if empty.
+    #[inline]
+    pub fn pop(&mut self) -> Option<A::Item> {
+        unsafe {
+            let (ptr, len_ptr, _) = self.triple_mut();
+            if *len_ptr == 0 {
+                return None;
+            }
+            let last_index = *len_ptr - 1;
+            *len_ptr = last_index;
+            Some(ptr::read(ptr.offset(last_index as isize)))
+        }
+    }
+
+    /// Re-allocate to set the capacity to `max(new_cap, inline_size())`.
+    ///
+    /// Panics if `new_cap` is less than the vector's length.
+    pub fn grow(&mut self, new_cap: usize) {
+        unsafe {
+            let (ptr, &mut len, cap) = self.triple_mut();
+            let unspilled = !self.spilled();
+            assert!(new_cap >= len);
+            if new_cap <= self.inline_size() {
+                if unspilled {
+                    return;
+                }
+                self.data = SmallVecData::from_inline(MaybeUninit::uninit());
+                ptr::copy_nonoverlapping(ptr, self.data.inline_mut(), len);
+                self.capacity = len;
+            } else if new_cap != cap {
+                let mut vec = Vec::with_capacity(new_cap);
+                let new_alloc = vec.as_mut_ptr();
+                mem::forget(vec);
+                ptr::copy_nonoverlapping(ptr, new_alloc, len);
+                self.data = SmallVecData::from_heap(new_alloc, len);
+                self.capacity = new_cap;
+                if unspilled {
+                    return;
+                }
+            } else {
+                return;
+            }
+            deallocate(ptr, cap);
+        }
+    }
+
+    /// Reserve capacity for `additional` more elements to be inserted.
+    ///
+    /// May reserve more space to avoid frequent reallocations.
+    ///
+    /// If the new capacity would overflow `usize` then it will be set to `usize::max_value()`
+    /// instead. (This means that inserting `additional` new elements is not guaranteed to be
+    /// possible after calling this function.)
+    #[inline]
+    pub fn reserve(&mut self, additional: usize) {
+        // prefer triple_mut() even if triple() would work
+        // so that the optimizer removes duplicated calls to it
+        // from callers like insert()
+        let (_, &mut len, cap) = self.triple_mut();
+        if cap - len < additional {
+            let new_cap = len.checked_add(additional).
+                and_then(usize::checked_next_power_of_two).
+                unwrap_or(usize::max_value());
+            self.grow(new_cap);
+        }
+    }
+
+    /// Reserve the minimum capacity for `additional` more elements to be inserted.
+    ///
+    /// Panics if the new capacity overflows `usize`.
+    pub fn reserve_exact(&mut self, additional: usize) {
+        let (_, &mut len, cap) = self.triple_mut();
+        if cap - len < additional {
+            match len.checked_add(additional) {
+                Some(cap) => self.grow(cap),
+                None => panic!("reserve_exact overflow"),
+            }
+        }
+    }
+
+    /// Shrink the capacity of the vector as much as possible.
+    ///
+    /// When possible, this will move data from an external heap buffer to the vector's inline
+    /// storage.
+    pub fn shrink_to_fit(&mut self) {
+        if !self.spilled() {
+            return;
+        }
+        let len = self.len();
+        if self.inline_size() >= len {
+            unsafe {
+                let (ptr, len) = self.data.heap();
+                self.data = SmallVecData::from_inline(MaybeUninit::uninit());
+                ptr::copy_nonoverlapping(ptr, self.data.inline_mut(), len);
+                deallocate(ptr, self.capacity);
+                self.capacity = len;
+            }
+        } else if self.capacity() > len {
+            self.grow(len);
+        }
+    }
+
+    /// Shorten the vector, keeping the first `len` elements and dropping the rest.
+    ///
+    /// If `len` is greater than or equal to the vector's current length, this has no
+    /// effect.
+    ///
+    /// This does not re-allocate.  If you want the vector's capacity to shrink, call
+    /// `shrink_to_fit` after truncating.
+    pub fn truncate(&mut self, len: usize) {
+        unsafe {
+            let (ptr, len_ptr, _) = self.triple_mut();
+            while len < *len_ptr {
+                let last_index = *len_ptr - 1;
+                *len_ptr = last_index;
+                ptr::drop_in_place(ptr.offset(last_index as isize));
+            }
+        }
+    }
+
+    /// Extracts a slice containing the entire vector.
+    ///
+    /// Equivalent to `&s[..]`.
+    pub fn as_slice(&self) -> &[A::Item] {
+        self
+    }
+
+    /// Extracts a mutable slice of the entire vector.
+    ///
+    /// Equivalent to `&mut s[..]`.
+    pub fn as_mut_slice(&mut self) -> &mut [A::Item] {
+        self
+    }
+
+    /// Remove the element at position `index`, replacing it with the last element.
+    ///
+    /// This does not preserve ordering, but is O(1).
+    ///
+    /// Panics if `index` is out of bounds.
+    #[inline]
+    pub fn swap_remove(&mut self, index: usize) -> A::Item {
+        let len = self.len();
+        self.swap(len - 1, index);
+        self.pop().unwrap_or_else(|| unsafe { unreachable() })
+    }
+
+    /// Remove all elements from the vector.
+    #[inline]
+    pub fn clear(&mut self) {
+        self.truncate(0);
+    }
+
+    /// Remove and return the element at position `index`, shifting all elements after it to the
+    /// left.
+    ///
+    /// Panics if `index` is out of bounds.
+    pub fn remove(&mut self, index: usize) -> A::Item {
+        unsafe {
+            let (mut ptr, len_ptr, _) = self.triple_mut();
+            let len = *len_ptr;
+            assert!(index < len);
+            *len_ptr = len - 1;
+            ptr = ptr.offset(index as isize);
+            let item = ptr::read(ptr);
+            ptr::copy(ptr.offset(1), ptr, len - index - 1);
+            item
+        }
+    }
+
+    /// Insert an element at position `index`, shifting all elements after it to the right.
+    ///
+    /// Panics if `index` is out of bounds.
+    pub fn insert(&mut self, index: usize, element: A::Item) {
+        self.reserve(1);
+
+        unsafe {
+            let (mut ptr, len_ptr, _) = self.triple_mut();
+            let len = *len_ptr;
+            assert!(index <= len);
+            *len_ptr = len + 1;
+            ptr = ptr.offset(index as isize);
+            ptr::copy(ptr, ptr.offset(1), len - index);
+            ptr::write(ptr, element);
+        }
+    }
+
+    /// Insert multiple elements at position `index`, shifting all following elements toward the
+    /// back.
+    pub fn insert_many<I: IntoIterator<Item=A::Item>>(&mut self, index: usize, iterable: I) {
+        let iter = iterable.into_iter();
+        if index == self.len() {
+            return self.extend(iter);
+        }
+
+        let (lower_size_bound, _) = iter.size_hint();
+        assert!(lower_size_bound <= std::isize::MAX as usize);  // Ensure offset is indexable
+        assert!(index + lower_size_bound >= index);  // Protect against overflow
+        self.reserve(lower_size_bound);
+
+        unsafe {
+            let old_len = self.len();
+            assert!(index <= old_len);
+            let mut ptr = self.as_mut_ptr().offset(index as isize);
+
+            // Move the trailing elements.
+            ptr::copy(ptr, ptr.offset(lower_size_bound as isize), old_len - index);
+
+            // In case the iterator panics, don't double-drop the items we just copied above.
+            self.set_len(index);
+
+            let mut num_added = 0;
+            for element in iter {
+                let mut cur = ptr.offset(num_added as isize);
+                if num_added >= lower_size_bound {
+                    // Iterator provided more elements than the hint.  Move trailing items again.
+                    self.reserve(1);
+                    ptr = self.as_mut_ptr().offset(index as isize);
+                    cur = ptr.offset(num_added as isize);
+                    ptr::copy(cur, cur.offset(1), old_len - index);
+                }
+                ptr::write(cur, element);
+                num_added += 1;
+            }
+            if num_added < lower_size_bound {
+                // Iterator provided fewer elements than the hint
+                ptr::copy(ptr.offset(lower_size_bound as isize), ptr.offset(num_added as isize), old_len - index);
+            }
+
+            self.set_len(old_len + num_added);
+        }
+    }
+
+    /// Convert a SmallVec to a Vec, without reallocating if the SmallVec has already spilled onto
+    /// the heap.
+    pub fn into_vec(self) -> Vec<A::Item> {
+        if self.spilled() {
+            unsafe {
+                let (ptr, len) = self.data.heap();
+                let v = Vec::from_raw_parts(ptr, len, self.capacity);
+                mem::forget(self);
+                v
+            }
+        } else {
+            self.into_iter().collect()
+        }
+    }
+
+    /// Convert the SmallVec into an `A` if possible. Otherwise return `Err(Self)`.
+    ///
+    /// This method returns `Err(Self)` if the SmallVec is too short (and the `A` contains uninitialized elements),
+    /// or if the SmallVec is too long (and all the elements were spilled to the heap).
+    pub fn into_inner(self) -> Result<A, Self> {
+        if self.spilled() || self.len() != A::size() {
+            Err(self)
+        } else {
+            unsafe {
+                let data = ptr::read(&self.data);
+                mem::forget(self);
+                Ok(data.into_inline().assume_init())
+            }
+        }
+    }
+
+    /// Retains only the elements specified by the predicate.
+    ///
+    /// In other words, remove all elements `e` such that `f(&e)` returns `false`.
+    /// This method operates in place and preserves the order of the retained
+    /// elements.
+    pub fn retain<F: FnMut(&mut A::Item) -> bool>(&mut self, mut f: F) {
+        let mut del = 0;
+        let len = self.len();
+        for i in 0..len {
+            if !f(&mut self[i]) {
+                del += 1;
+            } else if del > 0 {
+                self.swap(i - del, i);
+            }
+        }
+        self.truncate(len - del);
+    }
+
+    /// Removes consecutive duplicate elements.
+    pub fn dedup(&mut self) where A::Item: PartialEq<A::Item> {
+        self.dedup_by(|a, b| a == b);
+    }
+
+    /// Removes consecutive duplicate elements using the given equality relation.
+    pub fn dedup_by<F>(&mut self, mut same_bucket: F)
+        where F: FnMut(&mut A::Item, &mut A::Item) -> bool
+    {
+        // See the implementation of Vec::dedup_by in the
+        // standard library for an explanation of this algorithm.
+        let len = self.len();
+        if len <= 1 {
+            return;
+        }
+
+        let ptr = self.as_mut_ptr();
+        let mut w: usize = 1;
+
+        unsafe {
+            for r in 1..len {
+                let p_r = ptr.offset(r as isize);
+                let p_wm1 = ptr.offset((w - 1) as isize);
+                if !same_bucket(&mut *p_r, &mut *p_wm1) {
+                    if r != w {
+                        let p_w = p_wm1.offset(1);
+                        mem::swap(&mut *p_r, &mut *p_w);
+                    }
+                    w += 1;
+                }
+            }
+        }
+
+        self.truncate(w);
+    }
+
+    /// Removes consecutive elements that map to the same key.
+    pub fn dedup_by_key<F, K>(&mut self, mut key: F)
+        where F: FnMut(&mut A::Item) -> K,
+              K: PartialEq<K>
+    {
+        self.dedup_by(|a, b| key(a) == key(b));
+    }
+
+    /// Creates a `SmallVec` directly from the raw components of another
+    /// `SmallVec`.
+    ///
+    /// # Safety
+    ///
+    /// This is highly unsafe, due to the number of invariants that aren't
+    /// checked:
+    ///
+    /// * `ptr` needs to have been previously allocated via `SmallVec` for its
+    ///   spilled storage (at least, it's highly likely to be incorrect if it
+    ///   wasn't).
+    /// * `ptr`'s `A::Item` type needs to be the same size and alignment that
+    ///   it was allocated with
+    /// * `length` needs to be less than or equal to `capacity`.
+    /// * `capacity` needs to be the capacity that the pointer was allocated
+    ///   with.
+    ///
+    /// Violating these may cause problems like corrupting the allocator's
+    /// internal data structures.
+    ///
+    /// Additionally, `capacity` must be greater than the amount of inline
+    /// storage `A` has; that is, the new `SmallVec` must need to spill over
+    /// into heap allocated storage. This condition is asserted against.
+    ///
+    /// The ownership of `ptr` is effectively transferred to the
+    /// `SmallVec` which may then deallocate, reallocate or change the
+    /// contents of memory pointed to by the pointer at will. Ensure
+    /// that nothing else uses the pointer after calling this
+    /// function.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # #[macro_use] extern crate smallvec;
+    /// # use smallvec::SmallVec;
+    /// use std::mem;
+    /// use std::ptr;
+    ///
+    /// fn main() {
+    ///     let mut v: SmallVec<[_; 1]> = smallvec![1, 2, 3];
+    ///
+    ///     // Pull out the important parts of `v`.
+    ///     let p = v.as_mut_ptr();
+    ///     let len = v.len();
+    ///     let cap = v.capacity();
+    ///     let spilled = v.spilled();
+    ///
+    ///     unsafe {
+    ///         // Forget all about `v`. The heap allocation that stored the
+    ///         // three values won't be deallocated.
+    ///         mem::forget(v);
+    ///
+    ///         // Overwrite memory with [4, 5, 6].
+    ///         //
+    ///         // This is only safe if `spilled` is true! Otherwise, we are
+    ///         // writing into the old `SmallVec`'s inline storage on the
+    ///         // stack.
+    ///         assert!(spilled);
+    ///         for i in 0..len as isize {
+    ///             ptr::write(p.offset(i), 4 + i);
+    ///         }
+    ///
+    ///         // Put everything back together into a SmallVec with a different
+    ///         // amount of inline storage, but which is still less than `cap`.
+    ///         let rebuilt = SmallVec::<[_; 2]>::from_raw_parts(p, len, cap);
+    ///         assert_eq!(&*rebuilt, &[4, 5, 6]);
+    ///     }
+    /// }
+    pub unsafe fn from_raw_parts(
+        ptr: *mut A::Item,
+        length: usize,
+        capacity: usize,
+    ) -> SmallVec<A> {
+        assert!(capacity > A::size());
+        SmallVec {
+            capacity,
+            data: SmallVecData::from_heap(ptr, length),
+        }
+    }
+}
+
+impl<A: Array> SmallVec<A> where A::Item: Copy {
+    /// Copy the elements from a slice into a new `SmallVec`.
+    ///
+    /// For slices of `Copy` types, this is more efficient than `SmallVec::from(slice)`.
+    pub fn from_slice(slice: &[A::Item]) -> Self {
+        let len = slice.len();
+        if len <= A::size() {
+            SmallVec {
+                capacity: len,
+                data: SmallVecData::from_inline(unsafe {
+                    let mut data: MaybeUninit<A> = MaybeUninit::uninit();
+                    ptr::copy_nonoverlapping(
+                        slice.as_ptr(),
+                        data.as_mut_ptr() as *mut A::Item,
+                        len,
+                    );
+                    data
+                })
+            }
+        } else {
+            let mut b = slice.to_vec();
+            let (ptr, cap) = (b.as_mut_ptr(), b.capacity());
+            mem::forget(b);
+            SmallVec {
+                capacity: cap,
+                data: SmallVecData::from_heap(ptr, len),
+            }
+        }
+    }
+
+    /// Copy elements from a slice into the vector at position `index`, shifting any following
+    /// elements toward the back.
+    ///
+    /// For slices of `Copy` types, this is more efficient than `insert`.
+    pub fn insert_from_slice(&mut self, index: usize, slice: &[A::Item]) {
+        self.reserve(slice.len());
+
+        let len = self.len();
+        assert!(index <= len);
+
+        unsafe {
+            let slice_ptr = slice.as_ptr();
+            let ptr = self.as_mut_ptr().offset(index as isize);
+            ptr::copy(ptr, ptr.offset(slice.len() as isize), len - index);
+            ptr::copy_nonoverlapping(slice_ptr, ptr, slice.len());
+            self.set_len(len + slice.len());
+        }
+    }
+
+    /// Copy elements from a slice and append them to the vector.
+    ///
+    /// For slices of `Copy` types, this is more efficient than `extend`.
+    #[inline]
+    pub fn extend_from_slice(&mut self, slice: &[A::Item]) {
+        let len = self.len();
+        self.insert_from_slice(len, slice);
+    }
+}
+
+impl<A: Array> SmallVec<A> where A::Item: Clone {
+    /// Resizes the vector so that its length is equal to `len`.
+    ///
+    /// If `len` is less than the current length, the vector simply truncated.
+    ///
+    /// If `len` is greater than the current length, `value` is appended to the
+    /// vector until its length equals `len`.
+    pub fn resize(&mut self, len: usize, value: A::Item) {
+        let old_len = self.len();
+
+        if len > old_len {
+            self.extend(repeat(value).take(len - old_len));
+        } else {
+            self.truncate(len);
+        }
+    }
+
+    /// Creates a `SmallVec` with `n` copies of `elem`.
+    /// ```
+    /// use smallvec::SmallVec;
+    ///
+    /// let v = SmallVec::<[char; 128]>::from_elem('d', 2);
+    /// assert_eq!(v, SmallVec::from_buf(['d', 'd']));
+    /// ```
+    pub fn from_elem(elem: A::Item, n: usize) -> Self {
+        if n > A::size() {
+            vec![elem; n].into()
+        } else {
+            let mut v = SmallVec::<A>::new();
+            unsafe {
+                let (ptr, len_ptr, _) = v.triple_mut();
+                let mut local_len = SetLenOnDrop::new(len_ptr);
+
+                for i in 0..n as isize {
+                    ::std::ptr::write(ptr.offset(i), elem.clone());
+                    local_len.increment_len(1);
+                }
+            }
+            v
+        }
+    }
+}
+
+impl<A: Array> ops::Deref for SmallVec<A> {
+    type Target = [A::Item];
+    #[inline]
+    fn deref(&self) -> &[A::Item] {
+        unsafe {
+            let (ptr, len, _) = self.triple();
+            slice::from_raw_parts(ptr, len)
+        }
+    }
+}
+
+impl<A: Array> ops::DerefMut for SmallVec<A> {
+    #[inline]
+    fn deref_mut(&mut self) -> &mut [A::Item] {
+        unsafe {
+            let (ptr, &mut len, _) = self.triple_mut();
+            slice::from_raw_parts_mut(ptr, len)
+        }
+    }
+}
+
+impl<A: Array> AsRef<[A::Item]> for SmallVec<A> {
+    #[inline]
+    fn as_ref(&self) -> &[A::Item] {
+        self
+    }
+}
+
+impl<A: Array> AsMut<[A::Item]> for SmallVec<A> {
+    #[inline]
+    fn as_mut(&mut self) -> &mut [A::Item] {
+        self
+    }
+}
+
+impl<A: Array> Borrow<[A::Item]> for SmallVec<A> {
+    #[inline]
+    fn borrow(&self) -> &[A::Item] {
+        self
+    }
+}
+
+impl<A: Array> BorrowMut<[A::Item]> for SmallVec<A> {
+    #[inline]
+    fn borrow_mut(&mut self) -> &mut [A::Item] {
+        self
+    }
+}
+
+#[cfg(feature = "std")]
+impl<A: Array<Item = u8>> io::Write for SmallVec<A> {
+    #[inline]
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        self.extend_from_slice(buf);
+        Ok(buf.len())
+    }
+
+    #[inline]
+    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
+        self.extend_from_slice(buf);
+        Ok(())
+    }
+
+    #[inline]
+    fn flush(&mut self) -> io::Result<()> {
+        Ok(())
+    }
+}
+
+#[cfg(feature = "serde")]
+impl<A: Array> Serialize for SmallVec<A> where A::Item: Serialize {
+    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
+        let mut state = serializer.serialize_seq(Some(self.len()))?;
+        for item in self {
+            state.serialize_element(&item)?;
+        }
+        state.end()
+    }
+}
+
+#[cfg(feature = "serde")]
+impl<'de, A: Array> Deserialize<'de> for SmallVec<A> where A::Item: Deserialize<'de> {
+    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
+        deserializer.deserialize_seq(SmallVecVisitor{phantom: PhantomData})
+    }
+}
+
+#[cfg(feature = "serde")]
+struct SmallVecVisitor<A> {
+    phantom: PhantomData<A>
+}
+
+#[cfg(feature = "serde")]
+impl<'de, A: Array> Visitor<'de> for SmallVecVisitor<A>
+where A::Item: Deserialize<'de>,
+{
+    type Value = SmallVec<A>;
+
+    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        formatter.write_str("a sequence")
+    }
+
+    fn visit_seq<B>(self, mut seq: B) -> Result<Self::Value, B::Error>
+        where
+            B: SeqAccess<'de>,
+    {
+        let len = seq.size_hint().unwrap_or(0);
+        let mut values = SmallVec::with_capacity(len);
+
+        while let Some(value) = seq.next_element()? {
+            values.push(value);
+        }
+
+        Ok(values)
+    }
+}
+
+
+#[cfg(feature = "specialization")]
+trait SpecFrom<A: Array, S> {
+    fn spec_from(slice: S) -> SmallVec<A>;
+}
+
+#[cfg(feature = "specialization")]
+mod specialization;
+
+#[cfg(feature = "specialization")]
+impl<'a, A: Array> SpecFrom<A, &'a [A::Item]> for SmallVec<A> where A::Item: Copy {
+    #[inline]
+    fn spec_from(slice: &'a [A::Item]) -> SmallVec<A> {
+        SmallVec::from_slice(slice)
+    }
+}
+
+impl<'a, A: Array> From<&'a [A::Item]> for SmallVec<A> where A::Item: Clone {
+    #[cfg(not(feature = "specialization"))]
+    #[inline]
+    fn from(slice: &'a [A::Item]) -> SmallVec<A> {
+        slice.into_iter().cloned().collect()
+    }
+
+    #[cfg(feature = "specialization")]
+    #[inline]
+    fn from(slice: &'a [A::Item]) -> SmallVec<A> {
+        SmallVec::spec_from(slice)
+    }
+}
+
+impl<A: Array> From<Vec<A::Item>> for SmallVec<A> {
+    #[inline]
+    fn from(vec: Vec<A::Item>) -> SmallVec<A> {
+        SmallVec::from_vec(vec)
+    }
+}
+
+impl<A: Array> From<A> for SmallVec<A> {
+    #[inline]
+    fn from(array: A) -> SmallVec<A> {
+        SmallVec::from_buf(array)
+    }
+}
+
+macro_rules! impl_index {
+    ($index_type: ty, $output_type: ty) => {
+        impl<A: Array> ops::Index<$index_type> for SmallVec<A> {
+            type Output = $output_type;
+            #[inline]
+            fn index(&self, index: $index_type) -> &$output_type {
+                &(&**self)[index]
+            }
+        }
+
+        impl<A: Array> ops::IndexMut<$index_type> for SmallVec<A> {
+            #[inline]
+            fn index_mut(&mut self, index: $index_type) -> &mut $output_type {
+                &mut (&mut **self)[index]
+            }
+        }
+    }
+}
+
+impl_index!(usize, A::Item);
+impl_index!(ops::Range<usize>, [A::Item]);
+impl_index!(ops::RangeFrom<usize>, [A::Item]);
+impl_index!(ops::RangeTo<usize>, [A::Item]);
+impl_index!(ops::RangeFull, [A::Item]);
+
+impl<A: Array> ExtendFromSlice<A::Item> for SmallVec<A> where A::Item: Copy {
+    fn extend_from_slice(&mut self, other: &[A::Item]) {
+        SmallVec::extend_from_slice(self, other)
+    }
+}
+
+#[allow(deprecated)]
+impl<A: Array> VecLike<A::Item> for SmallVec<A> {
+    #[inline]
+    fn push(&mut self, value: A::Item) {
+        SmallVec::push(self, value);
+    }
+}
+
+impl<A: Array> FromIterator<A::Item> for SmallVec<A> {
+    fn from_iter<I: IntoIterator<Item=A::Item>>(iterable: I) -> SmallVec<A> {
+        let mut v = SmallVec::new();
+        v.extend(iterable);
+        v
+    }
+}
+
+impl<A: Array> Extend<A::Item> for SmallVec<A> {
+    fn extend<I: IntoIterator<Item=A::Item>>(&mut self, iterable: I) {
+        let mut iter = iterable.into_iter();
+        let (lower_size_bound, _) = iter.size_hint();
+        self.reserve(lower_size_bound);
+
+        unsafe {
+            let (ptr, len_ptr, cap) = self.triple_mut();
+            let mut len = SetLenOnDrop::new(len_ptr);
+            while len.get() < cap {
+                if let Some(out) = iter.next() {
+                    ptr::write(ptr.offset(len.get() as isize), out);
+                    len.increment_len(1);
+                } else {
+                    return;
+                }
+            }
+        }
+
+        for elem in iter {
+            self.push(elem);
+        }
+    }
+}
+
+impl<A: Array> fmt::Debug for SmallVec<A> where A::Item: fmt::Debug {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_list().entries(self.iter()).finish()
+    }
+}
+
+impl<A: Array> Default for SmallVec<A> {
+    #[inline]
+    fn default() -> SmallVec<A> {
+        SmallVec::new()
+    }
+}
+
+#[cfg(feature = "may_dangle")]
+unsafe impl<#[may_dangle] A: Array> Drop for SmallVec<A> {
+    fn drop(&mut self) {
+        unsafe {
+            if self.spilled() {
+                let (ptr, len) = self.data.heap();
+                Vec::from_raw_parts(ptr, len, self.capacity);
+            } else {
+                ptr::drop_in_place(&mut self[..]);
+            }
+        }
+    }
+}
+
+#[cfg(not(feature = "may_dangle"))]
+impl<A: Array> Drop for SmallVec<A> {
+    fn drop(&mut self) {
+        unsafe {
+            if self.spilled() {
+                let (ptr, len) = self.data.heap();
+                Vec::from_raw_parts(ptr, len, self.capacity);
+            } else {
+                ptr::drop_in_place(&mut self[..]);
+            }
+        }
+    }
+}
+
+impl<A: Array> Clone for SmallVec<A> where A::Item: Clone {
+    fn clone(&self) -> SmallVec<A> {
+        let mut new_vector = SmallVec::with_capacity(self.len());
+        for element in self.iter() {
+            new_vector.push((*element).clone())
+        }
+        new_vector
+    }
+}
+
+impl<A: Array, B: Array> PartialEq<SmallVec<B>> for SmallVec<A>
+    where A::Item: PartialEq<B::Item> {
+    #[inline]
+    fn eq(&self, other: &SmallVec<B>) -> bool { self[..] == other[..] }
+    #[inline]
+    fn ne(&self, other: &SmallVec<B>) -> bool { self[..] != other[..] }
+}
+
+impl<A: Array> Eq for SmallVec<A> where A::Item: Eq {}
+
+impl<A: Array> PartialOrd for SmallVec<A> where A::Item: PartialOrd {
+    #[inline]
+    fn partial_cmp(&self, other: &SmallVec<A>) -> Option<cmp::Ordering> {
+        PartialOrd::partial_cmp(&**self, &**other)
+    }
+}
+
+impl<A: Array> Ord for SmallVec<A> where A::Item: Ord {
+    #[inline]
+    fn cmp(&self, other: &SmallVec<A>) -> cmp::Ordering {
+        Ord::cmp(&**self, &**other)
+    }
+}
+
+impl<A: Array> Hash for SmallVec<A> where A::Item: Hash {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        (**self).hash(state)
+    }
+}
+
+unsafe impl<A: Array> Send for SmallVec<A> where A::Item: Send {}
+
+/// An iterator that consumes a `SmallVec` and yields its items by value.
+///
+/// Returned from [`SmallVec::into_iter`][1].
+///
+/// [1]: struct.SmallVec.html#method.into_iter
+pub struct IntoIter<A: Array> {
+    data: SmallVec<A>,
+    current: usize,
+    end: usize,
+}
+
+impl<A: Array> Drop for IntoIter<A> {
+    fn drop(&mut self) {
+        for _ in self { }
+    }
+}
+
+impl<A: Array> Iterator for IntoIter<A> {
+    type Item = A::Item;
+
+    #[inline]
+    fn next(&mut self) -> Option<A::Item> {
+        if self.current == self.end {
+            None
+        }
+        else {
+            unsafe {
+                let current = self.current as isize;
+                self.current += 1;
+                Some(ptr::read(self.data.as_ptr().offset(current)))
+            }
+        }
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let size = self.end - self.current;
+        (size, Some(size))
+    }
+}
+
+impl<A: Array> DoubleEndedIterator for IntoIter<A> {
+    #[inline]
+    fn next_back(&mut self) -> Option<A::Item> {
+        if self.current == self.end {
+            None
+        }
+        else {
+            unsafe {
+                self.end -= 1;
+                Some(ptr::read(self.data.as_ptr().offset(self.end as isize)))
+            }
+        }
+    }
+}
+
+impl<A: Array> ExactSizeIterator for IntoIter<A> { }
+
+impl<A: Array> IntoIterator for SmallVec<A> {
+    type IntoIter = IntoIter<A>;
+    type Item = A::Item;
+    fn into_iter(mut self) -> Self::IntoIter {
+        unsafe {
+            // Set SmallVec len to zero as `IntoIter` drop handles dropping of the elements
+            let len = self.len();
+            self.set_len(0);
+            IntoIter {
+                data: self,
+                current: 0,
+                end: len,
+            }
+        }
+    }
+}
+
+impl<'a, A: Array> IntoIterator for &'a SmallVec<A> {
+    type IntoIter = slice::Iter<'a, A::Item>;
+    type Item = &'a A::Item;
+    fn into_iter(self) -> Self::IntoIter {
+        self.iter()
+    }
+}
+
+impl<'a, A: Array> IntoIterator for &'a mut SmallVec<A> {
+    type IntoIter = slice::IterMut<'a, A::Item>;
+    type Item = &'a mut A::Item;
+    fn into_iter(self) -> Self::IntoIter {
+        self.iter_mut()
+    }
+}
+
+/// Types that can be used as the backing store for a SmallVec
+pub unsafe trait Array {
+    /// The type of the array's elements.
+    type Item;
+    /// Returns the number of items the array can hold.
+    fn size() -> usize;
+    /// Returns a pointer to the first element of the array.
+    fn ptr(&self) -> *const Self::Item;
+    /// Returns a mutable pointer to the first element of the array.
+    fn ptr_mut(&mut self) -> *mut Self::Item;
+}
+
+/// Set the length of the vec when the `SetLenOnDrop` value goes out of scope.
+///
+/// Copied from https://github.com/rust-lang/rust/pull/36355
+struct SetLenOnDrop<'a> {
+    len: &'a mut usize,
+    local_len: usize,
+}
+
+impl<'a> SetLenOnDrop<'a> {
+    #[inline]
+    fn new(len: &'a mut usize) -> Self {
+        SetLenOnDrop { local_len: *len, len: len }
+    }
+
+    #[inline]
+    fn get(&self) -> usize {
+        self.local_len
+    }
+
+    #[inline]
+    fn increment_len(&mut self, increment: usize) {
+        self.local_len += increment;
+    }
+}
+
+impl<'a> Drop for SetLenOnDrop<'a> {
+    #[inline]
+    fn drop(&mut self) {
+        *self.len = self.local_len;
+    }
+}
+
+macro_rules! impl_array(
+    ($($size:expr),+) => {
+        $(
+            unsafe impl<T> Array for [T; $size] {
+                type Item = T;
+                fn size() -> usize { $size }
+                fn ptr(&self) -> *const T { unimplemented!() }
+                fn ptr_mut(&mut self) -> *mut T { unimplemented!() }
+            }
+        )+
+    }
+);
+
+impl_array!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32, 36,
+            0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000,
+            0x10000, 0x20000, 0x40000, 0x80000, 0x100000);
+
+#[cfg(test)]
+mod tests {
+    use SmallVec;
+
+    use std::iter::FromIterator;
+
+    #[cfg(feature = "std")]
+    use std::borrow::ToOwned;
+    #[cfg(not(feature = "std"))]
+    use alloc::borrow::ToOwned;
+    #[cfg(feature = "std")]
+    use std::rc::Rc;
+    #[cfg(not(feature = "std"))]
+    use alloc::rc::Rc;
+    #[cfg(not(feature = "std"))]
+    use alloc::boxed::Box;
+    #[cfg(not(feature = "std"))]
+    use alloc::vec::Vec;
+
+    #[test]
+    pub fn test_zero() {
+        let mut v = SmallVec::<[_; 0]>::new();
+        assert!(!v.spilled());
+        v.push(0usize);
+        assert!(v.spilled());
+        assert_eq!(&*v, &[0]);
+    }
+
+    // We heap allocate all these strings so that double frees will show up under valgrind.
+
+    #[test]
+    pub fn test_inline() {
+        let mut v = SmallVec::<[_; 16]>::new();
+        v.push("hello".to_owned());
+        v.push("there".to_owned());
+        assert_eq!(&*v, &[
+            "hello".to_owned(),
+            "there".to_owned(),
+        ][..]);
+    }
+
+    #[test]
+    pub fn test_spill() {
+        let mut v = SmallVec::<[_; 2]>::new();
+        v.push("hello".to_owned());
+        assert_eq!(v[0], "hello");
+        v.push("there".to_owned());
+        v.push("burma".to_owned());
+        assert_eq!(v[0], "hello");
+        v.push("shave".to_owned());
+        assert_eq!(&*v, &[
+            "hello".to_owned(),
+            "there".to_owned(),
+            "burma".to_owned(),
+            "shave".to_owned(),
+        ][..]);
+    }
+
+    #[test]
+    pub fn test_double_spill() {
+        let mut v = SmallVec::<[_; 2]>::new();
+        v.push("hello".to_owned());
+        v.push("there".to_owned());
+        v.push("burma".to_owned());
+        v.push("shave".to_owned());
+        v.push("hello".to_owned());
+        v.push("there".to_owned());
+        v.push("burma".to_owned());
+        v.push("shave".to_owned());
+        assert_eq!(&*v, &[
+            "hello".to_owned(),
+            "there".to_owned(),
+            "burma".to_owned(),
+            "shave".to_owned(),
+            "hello".to_owned(),
+            "there".to_owned(),
+            "burma".to_owned(),
+            "shave".to_owned(),
+        ][..]);
+    }
+
+    /// https://github.com/servo/rust-smallvec/issues/4
+    #[test]
+    fn issue_4() {
+        SmallVec::<[Box<u32>; 2]>::new();
+    }
+
+    /// https://github.com/servo/rust-smallvec/issues/5
+    #[test]
+    fn issue_5() {
+        assert!(Some(SmallVec::<[&u32; 2]>::new()).is_some());
+    }
+
+    #[test]
+    fn test_with_capacity() {
+        let v: SmallVec<[u8; 3]> = SmallVec::with_capacity(1);
+        assert!(v.is_empty());
+        assert!(!v.spilled());
+        assert_eq!(v.capacity(), 3);
+
+        let v: SmallVec<[u8; 3]> = SmallVec::with_capacity(10);
+        assert!(v.is_empty());
+        assert!(v.spilled());
+        assert_eq!(v.capacity(), 10);
+    }
+
+    #[test]
+    fn drain() {
+        let mut v: SmallVec<[u8; 2]> = SmallVec::new();
+        v.push(3);
+        assert_eq!(v.drain().collect::<Vec<_>>(), &[3]);
+
+        // spilling the vec
+        v.push(3);
+        v.push(4);
+        v.push(5);
+        assert_eq!(v.drain().collect::<Vec<_>>(), &[3, 4, 5]);
+    }
+
+    #[test]
+    fn drain_rev() {
+        let mut v: SmallVec<[u8; 2]> = SmallVec::new();
+        v.push(3);
+        assert_eq!(v.drain().rev().collect::<Vec<_>>(), &[3]);
+
+        // spilling the vec
+        v.push(3);
+        v.push(4);
+        v.push(5);
+        assert_eq!(v.drain().rev().collect::<Vec<_>>(), &[5, 4, 3]);
+    }
+
+    #[test]
+    fn into_iter() {
+        let mut v: SmallVec<[u8; 2]> = SmallVec::new();
+        v.push(3);
+        assert_eq!(v.into_iter().collect::<Vec<_>>(), &[3]);
+
+        // spilling the vec
+        let mut v: SmallVec<[u8; 2]> = SmallVec::new();
+        v.push(3);
+        v.push(4);
+        v.push(5);
+        assert_eq!(v.into_iter().collect::<Vec<_>>(), &[3, 4, 5]);
+    }
+
+    #[test]
+    fn into_iter_rev() {
+        let mut v: SmallVec<[u8; 2]> = SmallVec::new();
+        v.push(3);
+        assert_eq!(v.into_iter().rev().collect::<Vec<_>>(), &[3]);
+
+        // spilling the vec
+        let mut v: SmallVec<[u8; 2]> = SmallVec::new();
+        v.push(3);
+        v.push(4);
+        v.push(5);
+        assert_eq!(v.into_iter().rev().collect::<Vec<_>>(), &[5, 4, 3]);
+    }
+
+    #[test]
+    fn into_iter_drop() {
+        use std::cell::Cell;
+
+        struct DropCounter<'a>(&'a Cell<i32>);
+
+        impl<'a> Drop for DropCounter<'a> {
+            fn drop(&mut self) {
+                self.0.set(self.0.get() + 1);
+            }
+        }
+
+        {
+            let cell = Cell::new(0);
+            let mut v: SmallVec<[DropCounter; 2]> = SmallVec::new();
+            v.push(DropCounter(&cell));
+            v.into_iter();
+            assert_eq!(cell.get(), 1);
+        }
+
+        {
+            let cell = Cell::new(0);
+            let mut v: SmallVec<[DropCounter; 2]> = SmallVec::new();
+            v.push(DropCounter(&cell));
+            v.push(DropCounter(&cell));
+            assert!(v.into_iter().next().is_some());
+            assert_eq!(cell.get(), 2);
+        }
+
+        {
+            let cell = Cell::new(0);
+            let mut v: SmallVec<[DropCounter; 2]> = SmallVec::new();
+            v.push(DropCounter(&cell));
+            v.push(DropCounter(&cell));
+            v.push(DropCounter(&cell));
+            assert!(v.into_iter().next().is_some());
+            assert_eq!(cell.get(), 3);
+        }
+        {
+            let cell = Cell::new(0);
+            let mut v: SmallVec<[DropCounter; 2]> = SmallVec::new();
+            v.push(DropCounter(&cell));
+            v.push(DropCounter(&cell));
+            v.push(DropCounter(&cell));
+            {
+                let mut it = v.into_iter();
+                assert!(it.next().is_some());
+                assert!(it.next_back().is_some());
+            }
+            assert_eq!(cell.get(), 3);
+        }
+    }
+
+    #[test]
+    fn test_capacity() {
+        let mut v: SmallVec<[u8; 2]> = SmallVec::new();
+        v.reserve(1);
+        assert_eq!(v.capacity(), 2);
+        assert!(!v.spilled());
+
+        v.reserve_exact(0x100);
+        assert!(v.capacity() >= 0x100);
+
+        v.push(0);
+        v.push(1);
+        v.push(2);
+        v.push(3);
+
+        v.shrink_to_fit();
+        assert!(v.capacity() < 0x100);
+    }
+
+    #[test]
+    fn test_truncate() {
+        let mut v: SmallVec<[Box<u8>; 8]> = SmallVec::new();
+
+        for x in 0..8 {
+            v.push(Box::new(x));
+        }
+        v.truncate(4);
+
+        assert_eq!(v.len(), 4);
+        assert!(!v.spilled());
+
+        assert_eq!(*v.swap_remove(1), 1);
+        assert_eq!(*v.remove(1), 3);
+        v.insert(1, Box::new(3));
+
+        assert_eq!(&v.iter().map(|v| **v).collect::<Vec<_>>(), &[0, 3, 2]);
+    }
+
+    #[test]
+    fn test_insert_many() {
+        let mut v: SmallVec<[u8; 8]> = SmallVec::new();
+        for x in 0..4 {
+            v.push(x);
+        }
+        assert_eq!(v.len(), 4);
+        v.insert_many(1, [5, 6].iter().cloned());
+        assert_eq!(&v.iter().map(|v| *v).collect::<Vec<_>>(), &[0, 5, 6, 1, 2, 3]);
+    }
+
+    struct MockHintIter<T: Iterator>{x: T, hint: usize}
+    impl<T: Iterator> Iterator for MockHintIter<T> {
+        type Item = T::Item;
+        fn next(&mut self) -> Option<Self::Item> {self.x.next()}
+        fn size_hint(&self) -> (usize, Option<usize>) {(self.hint, None)}
+    }
+
+    #[test]
+    fn test_insert_many_short_hint() {
+        let mut v: SmallVec<[u8; 8]> = SmallVec::new();
+        for x in 0..4 {
+            v.push(x);
+        }
+        assert_eq!(v.len(), 4);
+        v.insert_many(1, MockHintIter{x: [5, 6].iter().cloned(), hint: 5});
+        assert_eq!(&v.iter().map(|v| *v).collect::<Vec<_>>(), &[0, 5, 6, 1, 2, 3]);
+    }
+
+    #[test]
+    fn test_insert_many_long_hint() {
+        let mut v: SmallVec<[u8; 8]> = SmallVec::new();
+        for x in 0..4 {
+            v.push(x);
+        }
+        assert_eq!(v.len(), 4);
+        v.insert_many(1, MockHintIter{x: [5, 6].iter().cloned(), hint: 1});
+        assert_eq!(&v.iter().map(|v| *v).collect::<Vec<_>>(), &[0, 5, 6, 1, 2, 3]);
+    }
+
+    #[cfg(all(feature = "std", not(miri)))] // Miri currently does not support unwinding
+    #[test]
+    // https://github.com/servo/rust-smallvec/issues/96
+    fn test_insert_many_panic() {
+        struct PanicOnDoubleDrop {
+            dropped: Box<bool>
+        }
+
+        impl Drop for PanicOnDoubleDrop {
+            fn drop(&mut self) {
+                assert!(!*self.dropped, "already dropped");
+                *self.dropped = true;
+            }
+        }
+
+        struct BadIter;
+        impl Iterator for BadIter {
+            type Item = PanicOnDoubleDrop;
+            fn size_hint(&self) -> (usize, Option<usize>) { (1, None) }
+            fn next(&mut self) -> Option<Self::Item> { panic!() }
+        }
+
+        let mut vec: SmallVec<[PanicOnDoubleDrop; 0]> = vec![
+            PanicOnDoubleDrop { dropped: Box::new(false) },
+            PanicOnDoubleDrop { dropped: Box::new(false) },
+        ].into();
+        let result = ::std::panic::catch_unwind(move || {
+            vec.insert_many(0, BadIter);
+        });
+        assert!(result.is_err());
+    }
+
+    #[test]
+    #[should_panic]
+    fn test_invalid_grow() {
+        let mut v: SmallVec<[u8; 8]> = SmallVec::new();
+        v.extend(0..8);
+        v.grow(5);
+    }
+
+    #[test]
+    fn test_insert_from_slice() {
+        let mut v: SmallVec<[u8; 8]> = SmallVec::new();
+        for x in 0..4 {
+            v.push(x);
+        }
+        assert_eq!(v.len(), 4);
+        v.insert_from_slice(1, &[5, 6]);
+        assert_eq!(&v.iter().map(|v| *v).collect::<Vec<_>>(), &[0, 5, 6, 1, 2, 3]);
+    }
+
+    #[test]
+    fn test_extend_from_slice() {
+        let mut v: SmallVec<[u8; 8]> = SmallVec::new();
+        for x in 0..4 {
+            v.push(x);
+        }
+        assert_eq!(v.len(), 4);
+        v.extend_from_slice(&[5, 6]);
+        assert_eq!(&v.iter().map(|v| *v).collect::<Vec<_>>(), &[0, 1, 2, 3, 5, 6]);
+    }
+
+    #[test]
+    #[should_panic]
+    fn test_drop_panic_smallvec() {
+        // This test should only panic once, and not double panic,
+        // which would mean a double drop
+        struct DropPanic;
+
+        impl Drop for DropPanic {
+            fn drop(&mut self) {
+                panic!("drop");
+            }
+        }
+
+        let mut v = SmallVec::<[_; 1]>::new();
+        v.push(DropPanic);
+    }
+
+    #[test]
+    fn test_eq() {
+        let mut a: SmallVec<[u32; 2]> = SmallVec::new();
+        let mut b: SmallVec<[u32; 2]> = SmallVec::new();
+        let mut c: SmallVec<[u32; 2]> = SmallVec::new();
+        // a = [1, 2]
+        a.push(1);
+        a.push(2);
+        // b = [1, 2]
+        b.push(1);
+        b.push(2);
+        // c = [3, 4]
+        c.push(3);
+        c.push(4);
+
+        assert!(a == b);
+        assert!(a != c);
+    }
+
+    #[test]
+    fn test_ord() {
+        let mut a: SmallVec<[u32; 2]> = SmallVec::new();
+        let mut b: SmallVec<[u32; 2]> = SmallVec::new();
+        let mut c: SmallVec<[u32; 2]> = SmallVec::new();
+        // a = [1]
+        a.push(1);
+        // b = [1, 1]
+        b.push(1);
+        b.push(1);
+        // c = [1, 2]
+        c.push(1);
+        c.push(2);
+
+        assert!(a < b);
+        assert!(b > a);
+        assert!(b < c);
+        assert!(c > b);
+    }
+
+    #[cfg(feature = "std")]
+    #[test]
+    fn test_hash() {
+        use std::hash::Hash;
+        use std::collections::hash_map::DefaultHasher;
+
+        {
+            let mut a: SmallVec<[u32; 2]> = SmallVec::new();
+            let b = [1, 2];
+            a.extend(b.iter().cloned());
+            let mut hasher = DefaultHasher::new();
+            assert_eq!(a.hash(&mut hasher), b.hash(&mut hasher));
+        }
+        {
+            let mut a: SmallVec<[u32; 2]> = SmallVec::new();
+            let b = [1, 2, 11, 12];
+            a.extend(b.iter().cloned());
+            let mut hasher = DefaultHasher::new();
+            assert_eq!(a.hash(&mut hasher), b.hash(&mut hasher));
+        }
+    }
+
+    #[test]
+    fn test_as_ref() {
+        let mut a: SmallVec<[u32; 2]> = SmallVec::new();
+        a.push(1);
+        assert_eq!(a.as_ref(), [1]);
+        a.push(2);
+        assert_eq!(a.as_ref(), [1, 2]);
+        a.push(3);
+        assert_eq!(a.as_ref(), [1, 2, 3]);
+    }
+
+    #[test]
+    fn test_as_mut() {
+        let mut a: SmallVec<[u32; 2]> = SmallVec::new();
+        a.push(1);
+        assert_eq!(a.as_mut(), [1]);
+        a.push(2);
+        assert_eq!(a.as_mut(), [1, 2]);
+        a.push(3);
+        assert_eq!(a.as_mut(), [1, 2, 3]);
+        a.as_mut()[1] = 4;
+        assert_eq!(a.as_mut(), [1, 4, 3]);
+    }
+
+    #[test]
+    fn test_borrow() {
+        use std::borrow::Borrow;
+
+        let mut a: SmallVec<[u32; 2]> = SmallVec::new();
+        a.push(1);
+        assert_eq!(a.borrow(), [1]);
+        a.push(2);
+        assert_eq!(a.borrow(), [1, 2]);
+        a.push(3);
+        assert_eq!(a.borrow(), [1, 2, 3]);
+    }
+
+    #[test]
+    fn test_borrow_mut() {
+        use std::borrow::BorrowMut;
+
+        let mut a: SmallVec<[u32; 2]> = SmallVec::new();
+        a.push(1);
+        assert_eq!(a.borrow_mut(), [1]);
+        a.push(2);
+        assert_eq!(a.borrow_mut(), [1, 2]);
+        a.push(3);
+        assert_eq!(a.borrow_mut(), [1, 2, 3]);
+        BorrowMut::<[u32]>::borrow_mut(&mut a)[1] = 4;
+        assert_eq!(a.borrow_mut(), [1, 4, 3]);
+    }
+
+    #[test]
+    fn test_from() {
+        assert_eq!(&SmallVec::<[u32; 2]>::from(&[1][..])[..], [1]);
+        assert_eq!(&SmallVec::<[u32; 2]>::from(&[1, 2, 3][..])[..], [1, 2, 3]);
+
+        let vec = vec![];
+        let small_vec: SmallVec<[u8; 3]> = SmallVec::from(vec);
+        assert_eq!(&*small_vec, &[]);
+        drop(small_vec);
+
+        let vec = vec![1, 2, 3, 4, 5];
+        let small_vec: SmallVec<[u8; 3]> = SmallVec::from(vec);
+        assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]);
+        drop(small_vec);
+
+        let vec = vec![1, 2, 3, 4, 5];
+        let small_vec: SmallVec<[u8; 1]> = SmallVec::from(vec);
+        assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]);
+        drop(small_vec);
+
+        let array = [1];
+        let small_vec: SmallVec<[u8; 1]> = SmallVec::from(array);
+        assert_eq!(&*small_vec, &[1]);
+        drop(small_vec);
+
+        let array = [99; 128];
+        let small_vec: SmallVec<[u8; 128]> = SmallVec::from(array);
+        assert_eq!(&*small_vec, vec![99u8; 128].as_slice());
+        drop(small_vec);
+    }
+
+    #[test]
+    fn test_from_slice() {
+        assert_eq!(&SmallVec::<[u32; 2]>::from_slice(&[1][..])[..], [1]);
+        assert_eq!(&SmallVec::<[u32; 2]>::from_slice(&[1, 2, 3][..])[..], [1, 2, 3]);
+    }
+
+    #[test]
+    fn test_exact_size_iterator() {
+        let mut vec = SmallVec::<[u32; 2]>::from(&[1, 2, 3][..]);
+        assert_eq!(vec.clone().into_iter().len(), 3);
+        assert_eq!(vec.drain().len(), 3);
+    }
+
+    #[test]
+    #[allow(deprecated)]
+    fn veclike_deref_slice() {
+        use super::VecLike;
+
+        fn test<T: VecLike<i32>>(vec: &mut T) {
+            assert!(!vec.is_empty());
+            assert_eq!(vec.len(), 3);
+
+            vec.sort();
+            assert_eq!(&vec[..], [1, 2, 3]);
+        }
+
+        let mut vec = SmallVec::<[i32; 2]>::from(&[3, 1, 2][..]);
+        test(&mut vec);
+    }
+
+    #[test]
+    fn shrink_to_fit_unspill() {
+        let mut vec = SmallVec::<[u8; 2]>::from_iter(0..3);
+        vec.pop();
+        assert!(vec.spilled());
+        vec.shrink_to_fit();
+        assert!(!vec.spilled(), "shrink_to_fit will un-spill if possible");
+    }
+
+    #[test]
+    fn test_into_vec() {
+        let vec = SmallVec::<[u8; 2]>::from_iter(0..2);
+        assert_eq!(vec.into_vec(), vec![0, 1]);
+
+        let vec = SmallVec::<[u8; 2]>::from_iter(0..3);
+        assert_eq!(vec.into_vec(), vec![0, 1, 2]);
+    }
+
+    #[test]
+    fn test_into_inner() {
+        let vec = SmallVec::<[u8; 2]>::from_iter(0..2);
+        assert_eq!(vec.into_inner(), Ok([0, 1]));
+
+        let vec = SmallVec::<[u8; 2]>::from_iter(0..1);
+        assert_eq!(vec.clone().into_inner(), Err(vec));
+
+        let vec = SmallVec::<[u8; 2]>::from_iter(0..3);
+        assert_eq!(vec.clone().into_inner(), Err(vec));
+    }
+
+    #[test]
+    fn test_from_vec() {
+        let vec = vec![];
+        let small_vec: SmallVec<[u8; 3]> = SmallVec::from_vec(vec);
+        assert_eq!(&*small_vec, &[]);
+        drop(small_vec);
+
+        let vec = vec![];
+        let small_vec: SmallVec<[u8; 1]> = SmallVec::from_vec(vec);
+        assert_eq!(&*small_vec, &[]);
+        drop(small_vec);
+
+        let vec = vec![1];
+        let small_vec: SmallVec<[u8; 3]> = SmallVec::from_vec(vec);
+        assert_eq!(&*small_vec, &[1]);
+        drop(small_vec);
+
+        let vec = vec![1, 2, 3];
+        let small_vec: SmallVec<[u8; 3]> = SmallVec::from_vec(vec);
+        assert_eq!(&*small_vec, &[1, 2, 3]);
+        drop(small_vec);
+
+        let vec = vec![1, 2, 3, 4, 5];
+        let small_vec: SmallVec<[u8; 3]> = SmallVec::from_vec(vec);
+        assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]);
+        drop(small_vec);
+
+        let vec = vec![1, 2, 3, 4, 5];
+        let small_vec: SmallVec<[u8; 1]> = SmallVec::from_vec(vec);
+        assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]);
+        drop(small_vec);
+    }
+
+    #[test]
+    fn test_retain() {
+        // Test inline data storate
+        let mut sv: SmallVec<[i32; 5]> = SmallVec::from_slice(&[1, 2, 3, 3, 4]);
+        sv.retain(|&mut i| i != 3);
+        assert_eq!(sv.pop(), Some(4));
+        assert_eq!(sv.pop(), Some(2));
+        assert_eq!(sv.pop(), Some(1));
+        assert_eq!(sv.pop(), None);
+
+        // Test spilled data storage
+        let mut sv: SmallVec<[i32; 3]> = SmallVec::from_slice(&[1, 2, 3, 3, 4]);
+        sv.retain(|&mut i| i != 3);
+        assert_eq!(sv.pop(), Some(4));
+        assert_eq!(sv.pop(), Some(2));
+        assert_eq!(sv.pop(), Some(1));
+        assert_eq!(sv.pop(), None);
+
+        // Test that drop implementations are called for inline.
+        let one = Rc::new(1);
+        let mut sv: SmallVec<[Rc<i32>; 3]> = SmallVec::new();
+        sv.push(Rc::clone(&one));
+        assert_eq!(Rc::strong_count(&one), 2);
+        sv.retain(|_| false);
+        assert_eq!(Rc::strong_count(&one), 1);
+
+        // Test that drop implementations are called for spilled data.
+        let mut sv: SmallVec<[Rc<i32>; 1]> = SmallVec::new();
+        sv.push(Rc::clone(&one));
+        sv.push(Rc::new(2));
+        assert_eq!(Rc::strong_count(&one), 2);
+        sv.retain(|_| false);
+        assert_eq!(Rc::strong_count(&one), 1);
+    }
+
+    #[test]
+    fn test_dedup() {
+        let mut dupes: SmallVec<[i32; 5]> = SmallVec::from_slice(&[1, 1, 2, 3, 3]);
+        dupes.dedup();
+        assert_eq!(&*dupes, &[1, 2, 3]);
+
+        let mut empty: SmallVec<[i32; 5]> = SmallVec::new();
+        empty.dedup();
+        assert!(empty.is_empty());
+
+        let mut all_ones: SmallVec<[i32; 5]> = SmallVec::from_slice(&[1, 1, 1, 1, 1]);
+        all_ones.dedup();
+        assert_eq!(all_ones.len(), 1);
+
+        let mut no_dupes: SmallVec<[i32; 5]> = SmallVec::from_slice(&[1, 2, 3, 4, 5]);
+        no_dupes.dedup();
+        assert_eq!(no_dupes.len(), 5);
+    }
+
+    #[test]
+    fn test_resize() {
+        let mut v: SmallVec<[i32; 8]> = SmallVec::new();
+        v.push(1);
+        v.resize(5, 0);
+        assert_eq!(v[..], [1, 0, 0, 0, 0][..]);
+
+        v.resize(2, -1);
+        assert_eq!(v[..], [1, 0][..]);
+    }
+
+    #[cfg(feature = "std")]
+    #[test]
+    fn test_write() {
+        use io::Write;
+
+        let data = [1, 2, 3, 4, 5];
+
+        let mut small_vec: SmallVec<[u8; 2]> = SmallVec::new();
+        let len = small_vec.write(&data[..]).unwrap();
+        assert_eq!(len, 5);
+        assert_eq!(small_vec.as_ref(), data.as_ref());
+
+        let mut small_vec: SmallVec<[u8; 2]> = SmallVec::new();
+        small_vec.write_all(&data[..]).unwrap();
+        assert_eq!(small_vec.as_ref(), data.as_ref());
+    }
+
+    #[cfg(feature = "serde")]
+    extern crate bincode;
+
+    #[cfg(feature = "serde")]
+    #[test]
+    fn test_serde() {
+        use self::bincode::{config, deserialize};
+        let mut small_vec: SmallVec<[i32; 2]> = SmallVec::new();
+        small_vec.push(1);
+        let encoded = config().limit(100).serialize(&small_vec).unwrap();
+        let decoded: SmallVec<[i32; 2]> = deserialize(&encoded).unwrap();
+        assert_eq!(small_vec, decoded);
+        small_vec.push(2);
+        // Spill the vec
+        small_vec.push(3);
+        small_vec.push(4);
+        // Check again after spilling.
+        let encoded = config().limit(100).serialize(&small_vec).unwrap();
+        let decoded: SmallVec<[i32; 2]> = deserialize(&encoded).unwrap();
+        assert_eq!(small_vec, decoded);
+    }
+
+    #[test]
+    fn grow_to_shrink() {
+        let mut v: SmallVec<[u8; 2]> = SmallVec::new();
+        v.push(1);
+        v.push(2);
+        v.push(3);
+        assert!(v.spilled());
+        v.clear();
+        // Shrink to inline.
+        v.grow(2);
+        assert!(!v.spilled());
+        assert_eq!(v.capacity(), 2);
+        assert_eq!(v.len(), 0);
+        v.push(4);
+        assert_eq!(v[..], [4]);
+    }
+
+    #[test]
+    fn resumable_extend() {
+        let s = "a b c";
+        // This iterator yields: (Some('a'), None, Some('b'), None, Some('c')), None
+        let it = s
+            .chars()
+            .scan(0, |_, ch| if ch.is_whitespace() { None } else { Some(ch) });
+        let mut v: SmallVec<[char; 4]> = SmallVec::new();
+        v.extend(it);
+        assert_eq!(v[..], ['a']);
+    }
+
+    // #139
+    #[test]
+    fn uninhabited() {
+        enum Void {}
+        let _sv = SmallVec::<[Void; 8]>::new();
+    }
+
+    #[test]
+    fn grow_spilled_same_size() {
+        let mut v: SmallVec<[u8; 2]> = SmallVec::new();
+        v.push(0);
+        v.push(1);
+        v.push(2);
+        assert!(v.spilled());
+        assert_eq!(v.capacity(), 4);
+        // grow with the same capacity
+        v.grow(4);
+        assert_eq!(v.capacity(), 4);
+        assert_eq!(v[..], [0, 1, 2]);
+    }
+}
diff --git a/third_party/rust_crates/vendor/smallvec-0.6.13/scripts/run_miri.sh b/third_party/rust_crates/vendor/smallvec-0.6.13/scripts/run_miri.sh
new file mode 100644
index 0000000..42f2884
--- /dev/null
+++ b/third_party/rust_crates/vendor/smallvec-0.6.13/scripts/run_miri.sh
@@ -0,0 +1,21 @@
+#!/usr/bin/bash
+
+set -ex
+
+# Clean out our target dir, which may have artifacts compiled by a version of
+# rust different from the one we're about to download.
+cargo clean
+
+# Install and run the latest version of nightly where miri built successfully.
+# Taken from: https://github.com/rust-lang/miri#running-miri-on-ci
+
+MIRI_NIGHTLY=nightly-$(curl -s https://rust-lang.github.io/rustup-components-history/x86_64-unknown-linux-gnu/miri)
+echo "Installing latest nightly with Miri: $MIRI_NIGHTLY"
+rustup default "$MIRI_NIGHTLY"
+
+rustup component add miri
+cargo miri setup
+
+cargo miri test --verbose -- -- -Zunstable-options --exclude-should-panic
+cargo miri test --verbose --features union -- -- -Zunstable-options --exclude-should-panic
+cargo miri test --verbose --all-features -- -- -Zunstable-options --exclude-should-panic
diff --git a/third_party/rust_crates/vendor/smallvec-0.6.13/specialization.rs b/third_party/rust_crates/vendor/smallvec-0.6.13/specialization.rs
new file mode 100644
index 0000000..2e7bb1e
--- /dev/null
+++ b/third_party/rust_crates/vendor/smallvec-0.6.13/specialization.rs
@@ -0,0 +1,16 @@
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Implementations that require `default fn`.
+
+use super::{SpecFrom, SmallVec, Array};
+
+impl<'a, A: Array> SpecFrom<A, &'a [A::Item]> for SmallVec<A> where A::Item: Clone {
+    #[inline]
+    default fn spec_from(slice: &'a [A::Item]) -> SmallVec<A> {
+        slice.into_iter().cloned().collect()
+    }
+}
diff --git a/third_party/rust_crates/vendor/smallvec/.cargo-checksum.json b/third_party/rust_crates/vendor/smallvec/.cargo-checksum.json
index 5ef6f73..3940f46 100644
--- a/third_party/rust_crates/vendor/smallvec/.cargo-checksum.json
+++ b/third_party/rust_crates/vendor/smallvec/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"9b9dd0b09c80450d9b16308948eef9675bec260a4cd738572ff67e8d7d271f9c","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0b28172679e0009b655da42797c03fd163a3379d5cfa67ba1f1655e974a2a1a9","README.md":"38eef4ebde6fe6effa12a2dbca3bd69d6446b2935f19a329ac4926f1cb2e5013","benches/bench.rs":"9dca7122a3dcb2c099e49807e4d3b8f01d9220e2b3db0a54e9901ee74392866f","lib.rs":"f2f9c0f77e63672496591328cb90358d1a7d664aae8e7dee59cd0525010649cb","scripts/run_miri.sh":"cd645dfecf19cc77141ecaf698e58a3a743ad69aca5e5d25c8e5d3911e031322","specialization.rs":"b29ac094999b94cc193dde52432e8cd8d17a299192822b3485c27bf6a1bdc397"},"package":"f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6"}
\ No newline at end of file
+{"files":{"Cargo.toml":"75e4a48c2331b7cf4af796f68ed7ff4352c297e173f20280df5f7e71a4181a96","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0b28172679e0009b655da42797c03fd163a3379d5cfa67ba1f1655e974a2a1a9","README.md":"a01127c37308457e8d396b176fb790846be0978c173be3f13260b62efcef011b","benches/bench.rs":"9dca7122a3dcb2c099e49807e4d3b8f01d9220e2b3db0a54e9901ee74392866f","lib.rs":"5ef274f69f82ba8ba833b0d20cfb0eb963d266b323e5ec681cf53d2240a0b0cc","scripts/run_miri.sh":"2e83d153efc16cbc3c41589e306faa0624c8b9a0feecea3baae6e34f4563ac42","specialization.rs":"46433586203399251cba496d67b88d34e1be3c2b591986b77463513da1c66471"},"package":"44e59e0c9fa00817912ae6e4e6e3c4fe04455e75699d06eedc7d85917ed8e8f4"}
\ No newline at end of file
diff --git a/third_party/rust_crates/vendor/smallvec/Cargo.toml b/third_party/rust_crates/vendor/smallvec/Cargo.toml
index 6d1679e..ac713f8 100644
--- a/third_party/rust_crates/vendor/smallvec/Cargo.toml
+++ b/third_party/rust_crates/vendor/smallvec/Cargo.toml
@@ -11,11 +11,12 @@
 # will likely look very different (and much more reasonable)
 
 [package]
+edition = "2018"
 name = "smallvec"
-version = "0.6.13"
+version = "1.1.0"
 authors = ["Simon Sapin <simon.sapin@exyr.org>"]
 description = "'Small vector' optimization: store up to a small number of items on the stack"
-documentation = "https://doc.servo.org/smallvec/"
+documentation = "https://docs.rs/smallvec/"
 readme = "README.md"
 keywords = ["small", "vec", "vector", "stack", "no_std"]
 categories = ["data-structures"]
@@ -25,9 +26,6 @@
 [lib]
 name = "smallvec"
 path = "lib.rs"
-[dependencies.maybe-uninit]
-version = "2.0"
-
 [dependencies.serde]
 version = "1"
 optional = true
@@ -35,8 +33,7 @@
 version = "1.0.1"
 
 [features]
-default = ["std"]
 may_dangle = []
 specialization = []
-std = []
 union = []
+write = []
diff --git a/third_party/rust_crates/vendor/smallvec/README.md b/third_party/rust_crates/vendor/smallvec/README.md
index fda7fd4..724637c 100644
--- a/third_party/rust_crates/vendor/smallvec/README.md
+++ b/third_party/rust_crates/vendor/smallvec/README.md
@@ -6,3 +6,21 @@
 [Release notes](https://github.com/servo/rust-smallvec/releases)
 
 "Small vector" optimization for Rust: store up to a small number of items on the stack
+
+## Example
+
+```rust
+use smallvec::{SmallVec, smallvec};
+    
+// This SmallVec can hold up to 4 items on the stack:
+let mut v: SmallVec<[i32; 4]> = smallvec![1, 2, 3, 4];
+
+// It will automatically move its contents to the heap if
+// contains more than four items:
+v.push(5);
+
+// SmallVec points to a slice, so you can use normal slice
+// indexing and other methods to access its contents:
+v[0] = v[1] + v[2];
+v.sort();
+```
diff --git a/third_party/rust_crates/vendor/smallvec/lib.rs b/third_party/rust_crates/vendor/smallvec/lib.rs
index 55278ad..83fcf94 100644
--- a/third_party/rust_crates/vendor/smallvec/lib.rs
+++ b/third_party/rust_crates/vendor/smallvec/lib.rs
@@ -8,14 +8,11 @@
 //! to the heap for larger allocations.  This can be a useful optimization for improving cache
 //! locality and reducing allocator traffic for workloads that fit within the inline buffer.
 //!
-//! ## no_std support
+//! ## `no_std` support
 //!
-//! By default, `smallvec` depends on `libstd`. However, it can be configured to use the unstable
-//! `liballoc` API instead, for use on platforms that have `liballoc` but not `libstd`.  This
-//! configuration is currently unstable and is not guaranteed to work on all versions of Rust.
-//!
-//! To depend on `smallvec` without `libstd`, use `default-features = false` in the `smallvec`
-//! section of Cargo.toml to disable its `"std"` feature.
+//! By default, `smallvec` does not depend on `std`.  However, the optional
+//! `write` feature implements the `std::io::Write` trait for vectors of `u8`.
+//! When this feature is enabled, `smallvec` depends on `std`.
 //!
 //! ## `union` feature
 //!
@@ -28,49 +25,43 @@
 //! To use this feature add `features = ["union"]` in the `smallvec` section of Cargo.toml.
 //! Note that this feature requires a nightly compiler (for now).
 
-#![cfg_attr(not(feature = "std"), no_std)]
+#![no_std]
 #![cfg_attr(feature = "union", feature(untagged_unions))]
 #![cfg_attr(feature = "specialization", feature(specialization))]
 #![cfg_attr(feature = "may_dangle", feature(dropck_eyepatch))]
 #![deny(missing_docs)]
 
-
-#[cfg(not(feature = "std"))]
 #[macro_use]
 extern crate alloc;
 
-#[cfg(not(feature = "std"))]
+#[cfg(any(test, feature = "write"))]
+extern crate std;
+
+use alloc::boxed::Box;
 use alloc::vec::Vec;
+use core::borrow::{Borrow, BorrowMut};
+use core::cmp;
+use core::fmt;
+use core::hash::{Hash, Hasher};
+use core::hint::unreachable_unchecked;
+use core::iter::{repeat, FromIterator, FusedIterator, IntoIterator};
+use core::mem;
+use core::mem::MaybeUninit;
+use core::ops::{self, RangeBounds};
+use core::ptr::{self, NonNull};
+use core::slice::{self, SliceIndex};
 
 #[cfg(feature = "serde")]
-extern crate serde;
+use serde::{
+    de::{Deserialize, Deserializer, SeqAccess, Visitor},
+    ser::{Serialize, SerializeSeq, Serializer},
+};
 
-extern crate maybe_uninit;
+#[cfg(feature = "serde")]
+use core::marker::PhantomData;
 
-#[cfg(not(feature = "std"))]
-mod std {
-    pub use core::*;
-}
-
-use maybe_uninit::MaybeUninit;
-
-use std::borrow::{Borrow, BorrowMut};
-use std::cmp;
-use std::fmt;
-use std::hash::{Hash, Hasher};
-use std::iter::{IntoIterator, FromIterator, repeat};
-use std::mem;
-use std::ops;
-use std::ptr;
-use std::slice;
-#[cfg(feature = "std")]
+#[cfg(feature = "write")]
 use std::io;
-#[cfg(feature = "serde")]
-use serde::ser::{Serialize, Serializer, SerializeSeq};
-#[cfg(feature = "serde")]
-use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor};
-#[cfg(feature = "serde")]
-use std::marker::PhantomData;
 
 /// Creates a [`SmallVec`] containing the arguments.
 ///
@@ -130,76 +121,19 @@
     });
 }
 
-/// Hint to the optimizer that any code path which calls this function is
-/// statically unreachable and can be removed.
-///
-/// Equivalent to `std::hint::unreachable_unchecked` but works in older versions of Rust.
-#[inline]
-pub unsafe fn unreachable() -> ! {
-    enum Void {}
-    let x: &Void = mem::transmute(1usize);
-    match *x {}
-}
-
 /// `panic!()` in debug builds, optimization hint in release.
 #[cfg(not(feature = "union"))]
 macro_rules! debug_unreachable {
-    () => { debug_unreachable!("entered unreachable code") };
+    () => {
+        debug_unreachable!("entered unreachable code")
+    };
     ($e:expr) => {
         if cfg!(not(debug_assertions)) {
-            unreachable();
+            unreachable_unchecked();
         } else {
             panic!($e);
         }
-    }
-}
-
-/// Common operations implemented by both `Vec` and `SmallVec`.
-///
-/// This can be used to write generic code that works with both `Vec` and `SmallVec`.
-///
-/// ## Example
-///
-/// ```rust
-/// use smallvec::{VecLike, SmallVec};
-///
-/// fn initialize<V: VecLike<u8>>(v: &mut V) {
-///     for i in 0..5 {
-///         v.push(i);
-///     }
-/// }
-///
-/// let mut vec = Vec::new();
-/// initialize(&mut vec);
-///
-/// let mut small_vec = SmallVec::<[u8; 8]>::new();
-/// initialize(&mut small_vec);
-/// ```
-#[deprecated(note = "Use `Extend` and `Deref<[T]>` instead")]
-pub trait VecLike<T>:
-        ops::Index<usize, Output=T> +
-        ops::IndexMut<usize> +
-        ops::Index<ops::Range<usize>, Output=[T]> +
-        ops::IndexMut<ops::Range<usize>> +
-        ops::Index<ops::RangeFrom<usize>, Output=[T]> +
-        ops::IndexMut<ops::RangeFrom<usize>> +
-        ops::Index<ops::RangeTo<usize>, Output=[T]> +
-        ops::IndexMut<ops::RangeTo<usize>> +
-        ops::Index<ops::RangeFull, Output=[T]> +
-        ops::IndexMut<ops::RangeFull> +
-        ops::DerefMut<Target = [T]> +
-        Extend<T> {
-
-    /// Append an element to the vector.
-    fn push(&mut self, value: T);
-}
-
-#[allow(deprecated)]
-impl<T> VecLike<T> for Vec<T> {
-    #[inline]
-    fn push(&mut self, value: T) {
-        Vec::push(self, value);
-    }
+    };
 }
 
 /// Trait to be implemented by a collection that can be extended from a slice
@@ -242,16 +176,33 @@
 /// Returned from [`SmallVec::drain`][1].
 ///
 /// [1]: struct.SmallVec.html#method.drain
-pub struct Drain<'a, T: 'a> {
-    iter: slice::IterMut<'a,T>,
+pub struct Drain<'a, T: 'a + Array> {
+    tail_start: usize,
+    tail_len: usize,
+    iter: slice::Iter<'a, T::Item>,
+    vec: NonNull<SmallVec<T>>,
 }
 
-impl<'a, T: 'a> Iterator for Drain<'a,T> {
-    type Item = T;
+impl<'a, T: 'a + Array> fmt::Debug for Drain<'a, T>
+where
+    T::Item: fmt::Debug,
+{
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_tuple("Drain").field(&self.iter.as_slice()).finish()
+    }
+}
+
+unsafe impl<'a, T: Sync + Array> Sync for Drain<'a, T> {}
+unsafe impl<'a, T: Send + Array> Send for Drain<'a, T> {}
+
+impl<'a, T: 'a + Array> Iterator for Drain<'a, T> {
+    type Item = T::Item;
 
     #[inline]
-    fn next(&mut self) -> Option<T> {
-        self.iter.next().map(|reference| unsafe { ptr::read(reference) })
+    fn next(&mut self) -> Option<T::Item> {
+        self.iter
+            .next()
+            .map(|reference| unsafe { ptr::read(reference) })
     }
 
     #[inline]
@@ -260,19 +211,43 @@
     }
 }
 
-impl<'a, T: 'a> DoubleEndedIterator for Drain<'a, T> {
+impl<'a, T: 'a + Array> DoubleEndedIterator for Drain<'a, T> {
     #[inline]
-    fn next_back(&mut self) -> Option<T> {
-        self.iter.next_back().map(|reference| unsafe { ptr::read(reference) })
+    fn next_back(&mut self) -> Option<T::Item> {
+        self.iter
+            .next_back()
+            .map(|reference| unsafe { ptr::read(reference) })
     }
 }
 
-impl<'a, T> ExactSizeIterator for Drain<'a, T> { }
+impl<'a, T: Array> ExactSizeIterator for Drain<'a, T> {
+    #[inline]
+    fn len(&self) -> usize {
+        self.iter.len()
+    }
+}
 
-impl<'a, T: 'a> Drop for Drain<'a,T> {
+impl<'a, T: Array> FusedIterator for Drain<'a, T> {}
+
+impl<'a, T: 'a + Array> Drop for Drain<'a, T> {
     fn drop(&mut self) {
-        // Destroy the remaining elements.
-        for _ in self.by_ref() {}
+        self.for_each(drop);
+
+        if self.tail_len > 0 {
+            unsafe {
+                let source_vec = self.vec.as_mut();
+
+                // memmove back untouched tail, update to new length
+                let start = source_vec.len();
+                let tail = self.tail_start;
+                if tail != start {
+                    let src = source_vec.as_ptr().add(tail);
+                    let dst = source_vec.as_mut_ptr().add(start);
+                    ptr::copy(src, dst, self.tail_len);
+                }
+                source_vec.set_len(start + self.tail_len);
+            }
+        }
     }
 }
 
@@ -324,15 +299,15 @@
 impl<A: Array> SmallVecData<A> {
     #[inline]
     unsafe fn inline(&self) -> *const A::Item {
-        match *self {
-            SmallVecData::Inline(ref a) => a.as_ptr() as *const A::Item,
+        match self {
+            SmallVecData::Inline(a) => a.as_ptr() as *const A::Item,
             _ => debug_unreachable!(),
         }
     }
     #[inline]
     unsafe fn inline_mut(&mut self) -> *mut A::Item {
-        match *self {
-            SmallVecData::Inline(ref mut a) => a.as_mut_ptr() as *mut A::Item,
+        match self {
+            SmallVecData::Inline(a) => a.as_mut_ptr() as *mut A::Item,
             _ => debug_unreachable!(),
         }
     }
@@ -349,15 +324,15 @@
     }
     #[inline]
     unsafe fn heap(&self) -> (*mut A::Item, usize) {
-        match *self {
-            SmallVecData::Heap(data) => data,
+        match self {
+            SmallVecData::Heap(data) => *data,
             _ => debug_unreachable!(),
         }
     }
     #[inline]
     unsafe fn heap_mut(&mut self) -> &mut (*mut A::Item, usize) {
-        match *self {
-            SmallVecData::Heap(ref mut data) => data,
+        match self {
+            SmallVecData::Heap(data) => data,
             _ => debug_unreachable!(),
         }
     }
@@ -511,7 +486,7 @@
     #[inline]
     pub fn from_buf_and_len(buf: A, len: usize) -> SmallVec<A> {
         assert!(len <= A::size());
-        unsafe { SmallVec::from_buf_and_len_unchecked(buf, len) }
+        unsafe { SmallVec::from_buf_and_len_unchecked(MaybeUninit::new(buf), len) }
     }
 
     /// Constructs a new `SmallVec` on the stack from an `A` without
@@ -520,23 +495,23 @@
     ///
     /// ```rust
     /// use smallvec::SmallVec;
+    /// use std::mem::MaybeUninit;
     ///
     /// let buf = [1, 2, 3, 4, 5, 0, 0, 0];
     /// let small_vec: SmallVec<_> = unsafe {
-    ///     SmallVec::from_buf_and_len_unchecked(buf, 5)
+    ///     SmallVec::from_buf_and_len_unchecked(MaybeUninit::new(buf), 5)
     /// };
     ///
     /// assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]);
     /// ```
     #[inline]
-    pub unsafe fn from_buf_and_len_unchecked(buf: A, len: usize) -> SmallVec<A> {
+    pub unsafe fn from_buf_and_len_unchecked(buf: MaybeUninit<A>, len: usize) -> SmallVec<A> {
         SmallVec {
             capacity: len,
-            data: SmallVecData::from_inline(MaybeUninit::new(buf)),
+            data: SmallVecData::from_inline(buf),
         }
     }
 
-
     /// Sets the length of a vector.
     ///
     /// This will explicitly set the size of the vector, without actually
@@ -604,18 +579,50 @@
         self.capacity > A::size()
     }
 
-    /// Empty the vector and return an iterator over its former contents.
-    pub fn drain(&mut self) -> Drain<A::Item> {
+    /// Creates a draining iterator that removes the specified range in the vector
+    /// and yields the removed items.
+    ///
+    /// Note 1: The element range is removed even if the iterator is only
+    /// partially consumed or not consumed at all.
+    ///
+    /// Note 2: It is unspecified how many elements are removed from the vector
+    /// if the `Drain` value is leaked.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the starting point is greater than the end point or if
+    /// the end point is greater than the length of the vector.
+    pub fn drain<R>(&mut self, range: R) -> Drain<'_, A>
+    where
+        R: RangeBounds<usize>,
+    {
+        use core::ops::Bound::*;
+
+        let len = self.len();
+        let start = match range.start_bound() {
+            Included(&n) => n,
+            Excluded(&n) => n + 1,
+            Unbounded => 0,
+        };
+        let end = match range.end_bound() {
+            Included(&n) => n + 1,
+            Excluded(&n) => n,
+            Unbounded => len,
+        };
+
+        assert!(start <= end);
+        assert!(end <= len);
+
         unsafe {
-            let ptr = self.as_mut_ptr();
+            self.set_len(start);
 
-            let current_len = self.len();
-            self.set_len(0);
-
-            let slice = slice::from_raw_parts_mut(ptr, current_len);
+            let range_slice = slice::from_raw_parts_mut(self.as_mut_ptr().add(start), end - start);
 
             Drain {
-                iter: slice.iter_mut(),
+                tail_start: end,
+                tail_len: len - end,
+                iter: range_slice.iter(),
+                vec: NonNull::from(self),
             }
         }
     }
@@ -630,7 +637,7 @@
             }
             let (ptr, len_ptr, _) = self.triple_mut();
             *len_ptr = len + 1;
-            ptr::write(ptr.offset(len as isize), value);
+            ptr::write(ptr.add(len), value);
         }
     }
 
@@ -644,7 +651,7 @@
             }
             let last_index = *len_ptr - 1;
             *len_ptr = last_index;
-            Some(ptr::read(ptr.offset(last_index as isize)))
+            Some(ptr::read(ptr.add(last_index)))
         }
     }
 
@@ -694,9 +701,10 @@
         // from callers like insert()
         let (_, &mut len, cap) = self.triple_mut();
         if cap - len < additional {
-            let new_cap = len.checked_add(additional).
-                and_then(usize::checked_next_power_of_two).
-                unwrap_or(usize::max_value());
+            let new_cap = len
+                .checked_add(additional)
+                .and_then(usize::checked_next_power_of_two)
+                .unwrap_or(usize::max_value());
             self.grow(new_cap);
         }
     }
@@ -749,7 +757,7 @@
             while len < *len_ptr {
                 let last_index = *len_ptr - 1;
                 *len_ptr = last_index;
-                ptr::drop_in_place(ptr.offset(last_index as isize));
+                ptr::drop_in_place(ptr.add(last_index));
             }
         }
     }
@@ -777,7 +785,8 @@
     pub fn swap_remove(&mut self, index: usize) -> A::Item {
         let len = self.len();
         self.swap(len - 1, index);
-        self.pop().unwrap_or_else(|| unsafe { unreachable() })
+        self.pop()
+            .unwrap_or_else(|| unsafe { unreachable_unchecked() })
     }
 
     /// Remove all elements from the vector.
@@ -796,9 +805,9 @@
             let len = *len_ptr;
             assert!(index < len);
             *len_ptr = len - 1;
-            ptr = ptr.offset(index as isize);
+            ptr = ptr.add(index);
             let item = ptr::read(ptr);
-            ptr::copy(ptr.offset(1), ptr, len - index - 1);
+            ptr::copy(ptr.add(1), ptr, len - index - 1);
             item
         }
     }
@@ -814,52 +823,56 @@
             let len = *len_ptr;
             assert!(index <= len);
             *len_ptr = len + 1;
-            ptr = ptr.offset(index as isize);
-            ptr::copy(ptr, ptr.offset(1), len - index);
+            ptr = ptr.add(index);
+            ptr::copy(ptr, ptr.add(1), len - index);
             ptr::write(ptr, element);
         }
     }
 
     /// Insert multiple elements at position `index`, shifting all following elements toward the
     /// back.
-    pub fn insert_many<I: IntoIterator<Item=A::Item>>(&mut self, index: usize, iterable: I) {
+    pub fn insert_many<I: IntoIterator<Item = A::Item>>(&mut self, index: usize, iterable: I) {
         let iter = iterable.into_iter();
         if index == self.len() {
             return self.extend(iter);
         }
 
         let (lower_size_bound, _) = iter.size_hint();
-        assert!(lower_size_bound <= std::isize::MAX as usize);  // Ensure offset is indexable
-        assert!(index + lower_size_bound >= index);  // Protect against overflow
+        assert!(lower_size_bound <= core::isize::MAX as usize); // Ensure offset is indexable
+        assert!(index + lower_size_bound >= index); // Protect against overflow
         self.reserve(lower_size_bound);
 
         unsafe {
             let old_len = self.len();
             assert!(index <= old_len);
-            let mut ptr = self.as_mut_ptr().offset(index as isize);
+            let mut ptr = self.as_mut_ptr().add(index);
 
             // Move the trailing elements.
-            ptr::copy(ptr, ptr.offset(lower_size_bound as isize), old_len - index);
+            ptr::copy(ptr, ptr.add(lower_size_bound), old_len - index);
 
             // In case the iterator panics, don't double-drop the items we just copied above.
             self.set_len(index);
 
             let mut num_added = 0;
             for element in iter {
-                let mut cur = ptr.offset(num_added as isize);
+                let mut cur = ptr.add(num_added);
                 if num_added >= lower_size_bound {
                     // Iterator provided more elements than the hint.  Move trailing items again.
                     self.reserve(1);
-                    ptr = self.as_mut_ptr().offset(index as isize);
-                    cur = ptr.offset(num_added as isize);
-                    ptr::copy(cur, cur.offset(1), old_len - index);
+                    ptr = self.as_mut_ptr().add(index);
+                    cur = ptr.add(num_added);
+                    ptr::copy(cur, cur.add(1), old_len - index);
                 }
                 ptr::write(cur, element);
                 num_added += 1;
             }
             if num_added < lower_size_bound {
                 // Iterator provided fewer elements than the hint
-                ptr::copy(ptr.offset(lower_size_bound as isize), ptr.offset(num_added as isize), old_len - index);
+                ptr::copy(
+                    ptr.add(lower_size_bound),
+                    ptr.add(num_added),
+                    old_len - index,
+                );
             }
 
             self.set_len(old_len + num_added);
@@ -881,6 +894,14 @@
         }
     }
 
+    /// Converts a `SmallVec` into a `Box<[T]>` without reallocating if the `SmallVec` has already spilled
+    /// onto the heap.
+    ///
+    /// Note that this will drop any excess capacity.
+    pub fn into_boxed_slice(self) -> Box<[A::Item]> {
+        self.into_vec().into_boxed_slice()
+    }
+
     /// Convert the SmallVec into an `A` if possible. Otherwise return `Err(Self)`.
     ///
     /// This method returns `Err(Self)` if the SmallVec is too short (and the `A` contains uninitialized elements),
@@ -916,13 +937,17 @@
     }
 
     /// Removes consecutive duplicate elements.
-    pub fn dedup(&mut self) where A::Item: PartialEq<A::Item> {
+    pub fn dedup(&mut self)
+    where
+        A::Item: PartialEq<A::Item>,
+    {
         self.dedup_by(|a, b| a == b);
     }
 
     /// Removes consecutive duplicate elements using the given equality relation.
     pub fn dedup_by<F>(&mut self, mut same_bucket: F)
-        where F: FnMut(&mut A::Item, &mut A::Item) -> bool
+    where
+        F: FnMut(&mut A::Item, &mut A::Item) -> bool,
     {
         // See the implementation of Vec::dedup_by in the
         // standard library for an explanation of this algorithm.
@@ -936,11 +961,11 @@
 
         unsafe {
             for r in 1..len {
-                let p_r = ptr.offset(r as isize);
-                let p_wm1 = ptr.offset((w - 1) as isize);
+                let p_r = ptr.add(r);
+                let p_wm1 = ptr.add(w - 1);
                 if !same_bucket(&mut *p_r, &mut *p_wm1) {
                     if r != w {
-                        let p_w = p_wm1.offset(1);
+                        let p_w = p_wm1.add(1);
                         mem::swap(&mut *p_r, &mut *p_w);
                     }
                     w += 1;
@@ -953,8 +978,9 @@
 
     /// Removes consecutive elements that map to the same key.
     pub fn dedup_by_key<F, K>(&mut self, mut key: F)
-        where F: FnMut(&mut A::Item) -> K,
-              K: PartialEq<K>
+    where
+        F: FnMut(&mut A::Item) -> K,
+        K: PartialEq<K>,
     {
         self.dedup_by(|a, b| key(a) == key(b));
     }
@@ -1017,8 +1043,8 @@
     ///         // writing into the old `SmallVec`'s inline storage on the
     ///         // stack.
     ///         assert!(spilled);
-    ///         for i in 0..len as isize {
-    ///             ptr::write(p.offset(i), 4 + i);
+    ///         for i in 0..len {
+    ///             ptr::write(p.add(i), 4 + i);
     ///         }
     ///
     ///         // Put everything back together into a SmallVec with a different
@@ -1027,11 +1053,7 @@
     ///         assert_eq!(&*rebuilt, &[4, 5, 6]);
     ///     }
     /// }
-    pub unsafe fn from_raw_parts(
-        ptr: *mut A::Item,
-        length: usize,
-        capacity: usize,
-    ) -> SmallVec<A> {
+    pub unsafe fn from_raw_parts(ptr: *mut A::Item, length: usize, capacity: usize) -> SmallVec<A> {
         assert!(capacity > A::size());
         SmallVec {
             capacity,
@@ -1040,7 +1062,10 @@
     }
 }
 
-impl<A: Array> SmallVec<A> where A::Item: Copy {
+impl<A: Array> SmallVec<A>
+where
+    A::Item: Copy,
+{
     /// Copy the elements from a slice into a new `SmallVec`.
     ///
     /// For slices of `Copy` types, this is more efficient than `SmallVec::from(slice)`.
@@ -1057,7 +1082,7 @@
                         len,
                     );
                     data
-                })
+                }),
             }
         } else {
             let mut b = slice.to_vec();
@@ -1082,8 +1107,8 @@
 
         unsafe {
             let slice_ptr = slice.as_ptr();
-            let ptr = self.as_mut_ptr().offset(index as isize);
-            ptr::copy(ptr, ptr.offset(slice.len() as isize), len - index);
+            let ptr = self.as_mut_ptr().add(index);
+            ptr::copy(ptr, ptr.add(slice.len()), len - index);
             ptr::copy_nonoverlapping(slice_ptr, ptr, slice.len());
             self.set_len(len + slice.len());
         }
@@ -1099,7 +1124,10 @@
     }
 }
 
-impl<A: Array> SmallVec<A> where A::Item: Clone {
+impl<A: Array> SmallVec<A>
+where
+    A::Item: Clone,
+{
     /// Resizes the vector so that its length is equal to `len`.
     ///
     /// If `len` is less than the current length, the vector simply truncated.
@@ -1132,8 +1160,8 @@
                 let (ptr, len_ptr, _) = v.triple_mut();
                 let mut local_len = SetLenOnDrop::new(len_ptr);
 
-                for i in 0..n as isize {
-                    ::std::ptr::write(ptr.offset(i), elem.clone());
+                for i in 0..n {
+                    ::core::ptr::write(ptr.add(i), elem.clone());
                     local_len.increment_len(1);
                 }
             }
@@ -1191,7 +1219,7 @@
     }
 }
 
-#[cfg(feature = "std")]
+#[cfg(feature = "write")]
 impl<A: Array<Item = u8>> io::Write for SmallVec<A> {
     #[inline]
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
@@ -1212,7 +1240,10 @@
 }
 
 #[cfg(feature = "serde")]
-impl<A: Array> Serialize for SmallVec<A> where A::Item: Serialize {
+impl<A: Array> Serialize for SmallVec<A>
+where
+    A::Item: Serialize,
+{
     fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
         let mut state = serializer.serialize_seq(Some(self.len()))?;
         for item in self {
@@ -1223,30 +1254,36 @@
 }
 
 #[cfg(feature = "serde")]
-impl<'de, A: Array> Deserialize<'de> for SmallVec<A> where A::Item: Deserialize<'de> {
+impl<'de, A: Array> Deserialize<'de> for SmallVec<A>
+where
+    A::Item: Deserialize<'de>,
+{
     fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
-        deserializer.deserialize_seq(SmallVecVisitor{phantom: PhantomData})
+        deserializer.deserialize_seq(SmallVecVisitor {
+            phantom: PhantomData,
+        })
     }
 }
 
 #[cfg(feature = "serde")]
 struct SmallVecVisitor<A> {
-    phantom: PhantomData<A>
+    phantom: PhantomData<A>,
 }
 
 #[cfg(feature = "serde")]
 impl<'de, A: Array> Visitor<'de> for SmallVecVisitor<A>
-where A::Item: Deserialize<'de>,
+where
+    A::Item: Deserialize<'de>,
 {
     type Value = SmallVec<A>;
 
-    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
         formatter.write_str("a sequence")
     }
 
     fn visit_seq<B>(self, mut seq: B) -> Result<Self::Value, B::Error>
-        where
-            B: SeqAccess<'de>,
+    where
+        B: SeqAccess<'de>,
     {
         let len = seq.size_hint().unwrap_or(0);
         let mut values = SmallVec::with_capacity(len);
@@ -1259,7 +1296,6 @@
     }
 }
 
-
 #[cfg(feature = "specialization")]
 trait SpecFrom<A: Array, S> {
     fn spec_from(slice: S) -> SmallVec<A>;
@@ -1269,18 +1305,24 @@
 mod specialization;
 
 #[cfg(feature = "specialization")]
-impl<'a, A: Array> SpecFrom<A, &'a [A::Item]> for SmallVec<A> where A::Item: Copy {
+impl<'a, A: Array> SpecFrom<A, &'a [A::Item]> for SmallVec<A>
+where
+    A::Item: Copy,
+{
     #[inline]
     fn spec_from(slice: &'a [A::Item]) -> SmallVec<A> {
         SmallVec::from_slice(slice)
     }
 }
 
-impl<'a, A: Array> From<&'a [A::Item]> for SmallVec<A> where A::Item: Clone {
+impl<'a, A: Array> From<&'a [A::Item]> for SmallVec<A>
+where
+    A::Item: Clone,
+{
     #[cfg(not(feature = "specialization"))]
     #[inline]
     fn from(slice: &'a [A::Item]) -> SmallVec<A> {
-        slice.into_iter().cloned().collect()
+        slice.iter().cloned().collect()
     }
 
     #[cfg(feature = "specialization")]
@@ -1304,47 +1346,31 @@
     }
 }
 
-macro_rules! impl_index {
-    ($index_type: ty, $output_type: ty) => {
-        impl<A: Array> ops::Index<$index_type> for SmallVec<A> {
-            type Output = $output_type;
-            #[inline]
-            fn index(&self, index: $index_type) -> &$output_type {
-                &(&**self)[index]
-            }
-        }
+impl<A: Array, I: SliceIndex<[A::Item]>> ops::Index<I> for SmallVec<A> {
+    type Output = I::Output;
 
-        impl<A: Array> ops::IndexMut<$index_type> for SmallVec<A> {
-            #[inline]
-            fn index_mut(&mut self, index: $index_type) -> &mut $output_type {
-                &mut (&mut **self)[index]
-            }
-        }
+    fn index(&self, index: I) -> &I::Output {
+        &(**self)[index]
     }
 }
 
-impl_index!(usize, A::Item);
-impl_index!(ops::Range<usize>, [A::Item]);
-impl_index!(ops::RangeFrom<usize>, [A::Item]);
-impl_index!(ops::RangeTo<usize>, [A::Item]);
-impl_index!(ops::RangeFull, [A::Item]);
+impl<A: Array, I: SliceIndex<[A::Item]>> ops::IndexMut<I> for SmallVec<A> {
+    fn index_mut(&mut self, index: I) -> &mut I::Output {
+        &mut (&mut **self)[index]
+    }
+}
 
-impl<A: Array> ExtendFromSlice<A::Item> for SmallVec<A> where A::Item: Copy {
+impl<A: Array> ExtendFromSlice<A::Item> for SmallVec<A>
+where
+    A::Item: Copy,
+{
     fn extend_from_slice(&mut self, other: &[A::Item]) {
         SmallVec::extend_from_slice(self, other)
     }
 }
 
-#[allow(deprecated)]
-impl<A: Array> VecLike<A::Item> for SmallVec<A> {
-    #[inline]
-    fn push(&mut self, value: A::Item) {
-        SmallVec::push(self, value);
-    }
-}
-
 impl<A: Array> FromIterator<A::Item> for SmallVec<A> {
-    fn from_iter<I: IntoIterator<Item=A::Item>>(iterable: I) -> SmallVec<A> {
+    fn from_iter<I: IntoIterator<Item = A::Item>>(iterable: I) -> SmallVec<A> {
         let mut v = SmallVec::new();
         v.extend(iterable);
         v
@@ -1352,7 +1378,7 @@
 }
 
 impl<A: Array> Extend<A::Item> for SmallVec<A> {
-    fn extend<I: IntoIterator<Item=A::Item>>(&mut self, iterable: I) {
+    fn extend<I: IntoIterator<Item = A::Item>>(&mut self, iterable: I) {
         let mut iter = iterable.into_iter();
         let (lower_size_bound, _) = iter.size_hint();
         self.reserve(lower_size_bound);
@@ -1362,7 +1388,7 @@
             let mut len = SetLenOnDrop::new(len_ptr);
             while len.get() < cap {
                 if let Some(out) = iter.next() {
-                    ptr::write(ptr.offset(len.get() as isize), out);
+                    ptr::write(ptr.add(len.get()), out);
                     len.increment_len(1);
                 } else {
                     return;
@@ -1376,8 +1402,11 @@
     }
 }
 
-impl<A: Array> fmt::Debug for SmallVec<A> where A::Item: fmt::Debug {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+impl<A: Array> fmt::Debug for SmallVec<A>
+where
+    A::Item: fmt::Debug,
+{
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_list().entries(self.iter()).finish()
     }
 }
@@ -1417,7 +1446,10 @@
     }
 }
 
-impl<A: Array> Clone for SmallVec<A> where A::Item: Clone {
+impl<A: Array> Clone for SmallVec<A>
+where
+    A::Item: Clone,
+{
     fn clone(&self) -> SmallVec<A> {
         let mut new_vector = SmallVec::with_capacity(self.len());
         for element in self.iter() {
@@ -1428,30 +1460,41 @@
 }
 
 impl<A: Array, B: Array> PartialEq<SmallVec<B>> for SmallVec<A>
-    where A::Item: PartialEq<B::Item> {
+where
+    A::Item: PartialEq<B::Item>,
+{
     #[inline]
-    fn eq(&self, other: &SmallVec<B>) -> bool { self[..] == other[..] }
-    #[inline]
-    fn ne(&self, other: &SmallVec<B>) -> bool { self[..] != other[..] }
+    fn eq(&self, other: &SmallVec<B>) -> bool {
+        self[..] == other[..]
+    }
 }
 
 impl<A: Array> Eq for SmallVec<A> where A::Item: Eq {}
 
-impl<A: Array> PartialOrd for SmallVec<A> where A::Item: PartialOrd {
+impl<A: Array> PartialOrd for SmallVec<A>
+where
+    A::Item: PartialOrd,
+{
     #[inline]
     fn partial_cmp(&self, other: &SmallVec<A>) -> Option<cmp::Ordering> {
         PartialOrd::partial_cmp(&**self, &**other)
     }
 }
 
-impl<A: Array> Ord for SmallVec<A> where A::Item: Ord {
+impl<A: Array> Ord for SmallVec<A>
+where
+    A::Item: Ord,
+{
     #[inline]
     fn cmp(&self, other: &SmallVec<A>) -> cmp::Ordering {
         Ord::cmp(&**self, &**other)
     }
 }
 
-impl<A: Array> Hash for SmallVec<A> where A::Item: Hash {
+impl<A: Array> Hash for SmallVec<A>
+where
+    A::Item: Hash,
+{
     fn hash<H: Hasher>(&self, state: &mut H) {
         (**self).hash(state)
     }
@@ -1470,9 +1513,18 @@
     end: usize,
 }
 
+impl<A: Array + Clone> Clone for IntoIter<A>
+where
+    A::Item: Clone,
+{
+    fn clone(&self) -> IntoIter<A> {
+        SmallVec::from(self.as_slice()).into_iter()
+    }
+}
+
 impl<A: Array> Drop for IntoIter<A> {
     fn drop(&mut self) {
-        for _ in self { }
+        for _ in self {}
     }
 }
 
@@ -1483,12 +1535,11 @@
     fn next(&mut self) -> Option<A::Item> {
         if self.current == self.end {
             None
-        }
-        else {
+        } else {
             unsafe {
-                let current = self.current as isize;
+                let current = self.current;
                 self.current += 1;
-                Some(ptr::read(self.data.as_ptr().offset(current)))
+                Some(ptr::read(self.data.as_ptr().add(current)))
             }
         }
     }
@@ -1505,17 +1556,31 @@
     fn next_back(&mut self) -> Option<A::Item> {
         if self.current == self.end {
             None
-        }
-        else {
+        } else {
             unsafe {
                 self.end -= 1;
-                Some(ptr::read(self.data.as_ptr().offset(self.end as isize)))
+                Some(ptr::read(self.data.as_ptr().add(self.end)))
             }
         }
     }
 }
 
-impl<A: Array> ExactSizeIterator for IntoIter<A> { }
+impl<A: Array> ExactSizeIterator for IntoIter<A> {}
+impl<A: Array> FusedIterator for IntoIter<A> {}
+
+impl<A: Array> IntoIter<A> {
+    /// Returns the remaining items of this iterator as a slice.
+    pub fn as_slice(&self) -> &[A::Item] {
+        let len = self.end - self.current;
+        unsafe { core::slice::from_raw_parts(self.data.as_ptr().add(self.current), len) }
+    }
+
+    /// Returns the remaining items of this iterator as a mutable slice.
+    pub fn as_mut_slice(&mut self) -> &mut [A::Item] {
+        let len = self.end - self.current;
+        unsafe { core::slice::from_raw_parts_mut(self.data.as_mut_ptr().add(self.current), len) }
+    }
+}
 
 impl<A: Array> IntoIterator for SmallVec<A> {
     type IntoIter = IntoIter<A>;
@@ -1556,10 +1621,6 @@
     type Item;
     /// Returns the number of items the array can hold.
     fn size() -> usize;
-    /// Returns a pointer to the first element of the array.
-    fn ptr(&self) -> *const Self::Item;
-    /// Returns a mutable pointer to the first element of the array.
-    fn ptr_mut(&mut self) -> *mut Self::Item;
 }
 
 /// Set the length of the vec when the `SetLenOnDrop` value goes out of scope.
@@ -1573,7 +1634,10 @@
 impl<'a> SetLenOnDrop<'a> {
     #[inline]
     fn new(len: &'a mut usize) -> Self {
-        SetLenOnDrop { local_len: *len, len: len }
+        SetLenOnDrop {
+            local_len: *len,
+            len,
+        }
     }
 
     #[inline]
@@ -1600,34 +1664,26 @@
             unsafe impl<T> Array for [T; $size] {
                 type Item = T;
                 fn size() -> usize { $size }
-                fn ptr(&self) -> *const T { unimplemented!() }
-                fn ptr_mut(&mut self) -> *mut T { unimplemented!() }
             }
         )+
     }
 );
 
-impl_array!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32, 36,
-            0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000,
-            0x10000, 0x20000, 0x40000, 0x80000, 0x100000);
+impl_array!(
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32, 36, 0x40, 0x60, 0x80,
+    0x100, 0x200, 0x400, 0x600, 0x800, 0x1000, 0x2000, 0x4000, 0x6000, 0x8000, 0x10000, 0x20000,
+    0x40000, 0x60000, 0x80000, 0x10_0000
+);
 
 #[cfg(test)]
 mod tests {
-    use SmallVec;
+    use crate::SmallVec;
 
     use std::iter::FromIterator;
 
-    #[cfg(feature = "std")]
-    use std::borrow::ToOwned;
-    #[cfg(not(feature = "std"))]
     use alloc::borrow::ToOwned;
-    #[cfg(feature = "std")]
-    use std::rc::Rc;
-    #[cfg(not(feature = "std"))]
-    use alloc::rc::Rc;
-    #[cfg(not(feature = "std"))]
     use alloc::boxed::Box;
-    #[cfg(not(feature = "std"))]
+    use alloc::rc::Rc;
     use alloc::vec::Vec;
 
     #[test]
@@ -1646,10 +1702,7 @@
         let mut v = SmallVec::<[_; 16]>::new();
         v.push("hello".to_owned());
         v.push("there".to_owned());
-        assert_eq!(&*v, &[
-            "hello".to_owned(),
-            "there".to_owned(),
-        ][..]);
+        assert_eq!(&*v, &["hello".to_owned(), "there".to_owned(),][..]);
     }
 
     #[test]
@@ -1661,12 +1714,15 @@
         v.push("burma".to_owned());
         assert_eq!(v[0], "hello");
         v.push("shave".to_owned());
-        assert_eq!(&*v, &[
-            "hello".to_owned(),
-            "there".to_owned(),
-            "burma".to_owned(),
-            "shave".to_owned(),
-        ][..]);
+        assert_eq!(
+            &*v,
+            &[
+                "hello".to_owned(),
+                "there".to_owned(),
+                "burma".to_owned(),
+                "shave".to_owned(),
+            ][..]
+        );
     }
 
     #[test]
@@ -1680,16 +1736,19 @@
         v.push("there".to_owned());
         v.push("burma".to_owned());
         v.push("shave".to_owned());
-        assert_eq!(&*v, &[
-            "hello".to_owned(),
-            "there".to_owned(),
-            "burma".to_owned(),
-            "shave".to_owned(),
-            "hello".to_owned(),
-            "there".to_owned(),
-            "burma".to_owned(),
-            "shave".to_owned(),
-        ][..]);
+        assert_eq!(
+            &*v,
+            &[
+                "hello".to_owned(),
+                "there".to_owned(),
+                "burma".to_owned(),
+                "shave".to_owned(),
+                "hello".to_owned(),
+                "there".to_owned(),
+                "burma".to_owned(),
+                "shave".to_owned(),
+            ][..]
+        );
     }
 
     /// https://github.com/servo/rust-smallvec/issues/4
@@ -1721,26 +1780,36 @@
     fn drain() {
         let mut v: SmallVec<[u8; 2]> = SmallVec::new();
         v.push(3);
-        assert_eq!(v.drain().collect::<Vec<_>>(), &[3]);
+        assert_eq!(v.drain(..).collect::<Vec<_>>(), &[3]);
 
         // spilling the vec
         v.push(3);
         v.push(4);
         v.push(5);
-        assert_eq!(v.drain().collect::<Vec<_>>(), &[3, 4, 5]);
+        let old_capacity = v.capacity();
+        assert_eq!(v.drain(1..).collect::<Vec<_>>(), &[4, 5]);
+        // drain should not change the capacity
+        assert_eq!(v.capacity(), old_capacity);
     }
 
     #[test]
     fn drain_rev() {
         let mut v: SmallVec<[u8; 2]> = SmallVec::new();
         v.push(3);
-        assert_eq!(v.drain().rev().collect::<Vec<_>>(), &[3]);
+        assert_eq!(v.drain(..).rev().collect::<Vec<_>>(), &[3]);
 
         // spilling the vec
         v.push(3);
         v.push(4);
         v.push(5);
-        assert_eq!(v.drain().rev().collect::<Vec<_>>(), &[5, 4, 3]);
+        assert_eq!(v.drain(..).rev().collect::<Vec<_>>(), &[5, 4, 3]);
+    }
+
+    #[test]
+    fn drain_forget() {
+        let mut v: SmallVec<[u8; 1]> = smallvec![0, 1, 2, 3, 4, 5, 6, 7];
+        std::mem::forget(v.drain(2..5));
+        assert_eq!(v.len(), 2);
     }
 
     #[test]
@@ -1785,7 +1854,7 @@
 
         {
             let cell = Cell::new(0);
-            let mut v: SmallVec<[DropCounter; 2]> = SmallVec::new();
+            let mut v: SmallVec<[DropCounter<'_>; 2]> = SmallVec::new();
             v.push(DropCounter(&cell));
             v.into_iter();
             assert_eq!(cell.get(), 1);
@@ -1793,7 +1862,7 @@
 
         {
             let cell = Cell::new(0);
-            let mut v: SmallVec<[DropCounter; 2]> = SmallVec::new();
+            let mut v: SmallVec<[DropCounter<'_>; 2]> = SmallVec::new();
             v.push(DropCounter(&cell));
             v.push(DropCounter(&cell));
             assert!(v.into_iter().next().is_some());
@@ -1802,7 +1871,7 @@
 
         {
             let cell = Cell::new(0);
-            let mut v: SmallVec<[DropCounter; 2]> = SmallVec::new();
+            let mut v: SmallVec<[DropCounter<'_>; 2]> = SmallVec::new();
             v.push(DropCounter(&cell));
             v.push(DropCounter(&cell));
             v.push(DropCounter(&cell));
@@ -1811,7 +1880,7 @@
         }
         {
             let cell = Cell::new(0);
-            let mut v: SmallVec<[DropCounter; 2]> = SmallVec::new();
+            let mut v: SmallVec<[DropCounter<'_>; 2]> = SmallVec::new();
             v.push(DropCounter(&cell));
             v.push(DropCounter(&cell));
             v.push(DropCounter(&cell));
@@ -1870,14 +1939,24 @@
         }
         assert_eq!(v.len(), 4);
         v.insert_many(1, [5, 6].iter().cloned());
-        assert_eq!(&v.iter().map(|v| *v).collect::<Vec<_>>(), &[0, 5, 6, 1, 2, 3]);
+        assert_eq!(
+            &v.iter().map(|v| *v).collect::<Vec<_>>(),
+            &[0, 5, 6, 1, 2, 3]
+        );
     }
 
-    struct MockHintIter<T: Iterator>{x: T, hint: usize}
+    struct MockHintIter<T: Iterator> {
+        x: T,
+        hint: usize,
+    }
     impl<T: Iterator> Iterator for MockHintIter<T> {
         type Item = T::Item;
-        fn next(&mut self) -> Option<Self::Item> {self.x.next()}
-        fn size_hint(&self) -> (usize, Option<usize>) {(self.hint, None)}
+        fn next(&mut self) -> Option<Self::Item> {
+            self.x.next()
+        }
+        fn size_hint(&self) -> (usize, Option<usize>) {
+            (self.hint, None)
+        }
     }
 
     #[test]
@@ -1887,8 +1966,17 @@
             v.push(x);
         }
         assert_eq!(v.len(), 4);
-        v.insert_many(1, MockHintIter{x: [5, 6].iter().cloned(), hint: 5});
-        assert_eq!(&v.iter().map(|v| *v).collect::<Vec<_>>(), &[0, 5, 6, 1, 2, 3]);
+        v.insert_many(
+            1,
+            MockHintIter {
+                x: [5, 6].iter().cloned(),
+                hint: 5,
+            },
+        );
+        assert_eq!(
+            &v.iter().map(|v| *v).collect::<Vec<_>>(),
+            &[0, 5, 6, 1, 2, 3]
+        );
     }
 
     #[test]
@@ -1898,16 +1986,24 @@
             v.push(x);
         }
         assert_eq!(v.len(), 4);
-        v.insert_many(1, MockHintIter{x: [5, 6].iter().cloned(), hint: 1});
-        assert_eq!(&v.iter().map(|v| *v).collect::<Vec<_>>(), &[0, 5, 6, 1, 2, 3]);
+        v.insert_many(
+            1,
+            MockHintIter {
+                x: [5, 6].iter().cloned(),
+                hint: 1,
+            },
+        );
+        assert_eq!(
+            &v.iter().map(|v| *v).collect::<Vec<_>>(),
+            &[0, 5, 6, 1, 2, 3]
+        );
     }
 
-    #[cfg(all(feature = "std", not(miri)))] // Miri currently does not support unwinding
     #[test]
     // https://github.com/servo/rust-smallvec/issues/96
     fn test_insert_many_panic() {
         struct PanicOnDoubleDrop {
-            dropped: Box<bool>
+            dropped: Box<bool>,
         }
 
         impl Drop for PanicOnDoubleDrop {
@@ -1920,14 +2016,23 @@
         struct BadIter;
         impl Iterator for BadIter {
             type Item = PanicOnDoubleDrop;
-            fn size_hint(&self) -> (usize, Option<usize>) { (1, None) }
-            fn next(&mut self) -> Option<Self::Item> { panic!() }
+            fn size_hint(&self) -> (usize, Option<usize>) {
+                (1, None)
+            }
+            fn next(&mut self) -> Option<Self::Item> {
+                panic!()
+            }
         }
 
         let mut vec: SmallVec<[PanicOnDoubleDrop; 0]> = vec![
-            PanicOnDoubleDrop { dropped: Box::new(false) },
-            PanicOnDoubleDrop { dropped: Box::new(false) },
-        ].into();
+            PanicOnDoubleDrop {
+                dropped: Box::new(false),
+            },
+            PanicOnDoubleDrop {
+                dropped: Box::new(false),
+            },
+        ]
+        .into();
         let result = ::std::panic::catch_unwind(move || {
             vec.insert_many(0, BadIter);
         });
@@ -1950,7 +2055,10 @@
         }
         assert_eq!(v.len(), 4);
         v.insert_from_slice(1, &[5, 6]);
-        assert_eq!(&v.iter().map(|v| *v).collect::<Vec<_>>(), &[0, 5, 6, 1, 2, 3]);
+        assert_eq!(
+            &v.iter().map(|v| *v).collect::<Vec<_>>(),
+            &[0, 5, 6, 1, 2, 3]
+        );
     }
 
     #[test]
@@ -1961,7 +2069,10 @@
         }
         assert_eq!(v.len(), 4);
         v.extend_from_slice(&[5, 6]);
-        assert_eq!(&v.iter().map(|v| *v).collect::<Vec<_>>(), &[0, 1, 2, 3, 5, 6]);
+        assert_eq!(
+            &v.iter().map(|v| *v).collect::<Vec<_>>(),
+            &[0, 1, 2, 3, 5, 6]
+        );
     }
 
     #[test]
@@ -2020,11 +2131,10 @@
         assert!(c > b);
     }
 
-    #[cfg(feature = "std")]
     #[test]
     fn test_hash() {
-        use std::hash::Hash;
         use std::collections::hash_map::DefaultHasher;
+        use std::hash::Hash;
 
         {
             let mut a: SmallVec<[u32; 2]> = SmallVec::new();
@@ -2128,31 +2238,63 @@
     #[test]
     fn test_from_slice() {
         assert_eq!(&SmallVec::<[u32; 2]>::from_slice(&[1][..])[..], [1]);
-        assert_eq!(&SmallVec::<[u32; 2]>::from_slice(&[1, 2, 3][..])[..], [1, 2, 3]);
+        assert_eq!(
+            &SmallVec::<[u32; 2]>::from_slice(&[1, 2, 3][..])[..],
+            [1, 2, 3]
+        );
     }
 
     #[test]
     fn test_exact_size_iterator() {
         let mut vec = SmallVec::<[u32; 2]>::from(&[1, 2, 3][..]);
         assert_eq!(vec.clone().into_iter().len(), 3);
-        assert_eq!(vec.drain().len(), 3);
+        assert_eq!(vec.drain(..2).len(), 2);
+        assert_eq!(vec.into_iter().len(), 1);
     }
 
     #[test]
-    #[allow(deprecated)]
-    fn veclike_deref_slice() {
-        use super::VecLike;
+    fn test_into_iter_as_slice() {
+        let vec = SmallVec::<[u32; 2]>::from(&[1, 2, 3][..]);
+        let mut iter = vec.clone().into_iter();
+        assert_eq!(iter.as_slice(), &[1, 2, 3]);
+        assert_eq!(iter.as_mut_slice(), &[1, 2, 3]);
+        iter.next();
+        assert_eq!(iter.as_slice(), &[2, 3]);
+        assert_eq!(iter.as_mut_slice(), &[2, 3]);
+        iter.next_back();
+        assert_eq!(iter.as_slice(), &[2]);
+        assert_eq!(iter.as_mut_slice(), &[2]);
+    }
 
-        fn test<T: VecLike<i32>>(vec: &mut T) {
-            assert!(!vec.is_empty());
-            assert_eq!(vec.len(), 3);
-
-            vec.sort();
-            assert_eq!(&vec[..], [1, 2, 3]);
+    #[test]
+    fn test_into_iter_clone() {
+        // Test that the cloned iterator yields identical elements and that it owns its own copy
+        // (i.e. no use after move errors).
+        let mut iter = SmallVec::<[u8; 2]>::from_iter(0..3).into_iter();
+        let mut clone_iter = iter.clone();
+        while let Some(x) = iter.next() {
+            assert_eq!(x, clone_iter.next().unwrap());
         }
+        assert_eq!(clone_iter.next(), None);
+    }
 
-        let mut vec = SmallVec::<[i32; 2]>::from(&[3, 1, 2][..]);
-        test(&mut vec);
+    #[test]
+    fn test_into_iter_clone_partially_consumed_iterator() {
+        // Test that the cloned iterator only contains the remaining elements of the original iterator.
+        let mut iter = SmallVec::<[u8; 2]>::from_iter(0..3).into_iter().skip(1);
+        let mut clone_iter = iter.clone();
+        while let Some(x) = iter.next() {
+            assert_eq!(x, clone_iter.next().unwrap());
+        }
+        assert_eq!(clone_iter.next(), None);
+    }
+
+    #[test]
+    fn test_into_iter_clone_empty_smallvec() {
+        let mut iter = SmallVec::<[u8; 2]>::new().into_iter();
+        let mut clone_iter = iter.clone();
+        assert_eq!(iter.next(), None);
+        assert_eq!(clone_iter.next(), None);
     }
 
     #[test]
@@ -2283,10 +2425,10 @@
         assert_eq!(v[..], [1, 0][..]);
     }
 
-    #[cfg(feature = "std")]
+    #[cfg(feature = "write")]
     #[test]
     fn test_write() {
-        use io::Write;
+        use std::io::Write;
 
         let data = [1, 2, 3, 4, 5];
 
diff --git a/third_party/rust_crates/vendor/smallvec/scripts/run_miri.sh b/third_party/rust_crates/vendor/smallvec/scripts/run_miri.sh
index 42f2884..c5e5376 100644
--- a/third_party/rust_crates/vendor/smallvec/scripts/run_miri.sh
+++ b/third_party/rust_crates/vendor/smallvec/scripts/run_miri.sh
@@ -16,6 +16,6 @@
 rustup component add miri
 cargo miri setup
 
-cargo miri test --verbose -- -- -Zunstable-options --exclude-should-panic
-cargo miri test --verbose --features union -- -- -Zunstable-options --exclude-should-panic
-cargo miri test --verbose --all-features -- -- -Zunstable-options --exclude-should-panic
+cargo miri test --verbose -- -Zmiri-ignore-leaks
+cargo miri test --verbose --features union -- -Zmiri-ignore-leaks
+cargo miri test --verbose --all-features -- -Zmiri-ignore-leaks
diff --git a/third_party/rust_crates/vendor/smallvec/specialization.rs b/third_party/rust_crates/vendor/smallvec/specialization.rs
index 2e7bb1e..658fa77 100644
--- a/third_party/rust_crates/vendor/smallvec/specialization.rs
+++ b/third_party/rust_crates/vendor/smallvec/specialization.rs
@@ -6,9 +6,12 @@
 
 //! Implementations that require `default fn`.
 
-use super::{SpecFrom, SmallVec, Array};
+use super::{Array, SmallVec, SpecFrom};
 
-impl<'a, A: Array> SpecFrom<A, &'a [A::Item]> for SmallVec<A> where A::Item: Clone {
+impl<'a, A: Array> SpecFrom<A, &'a [A::Item]> for SmallVec<A>
+where
+    A::Item: Clone,
+{
     #[inline]
     default fn spec_from(slice: &'a [A::Item]) -> SmallVec<A> {
         slice.into_iter().cloned().collect()
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/.cargo-checksum.json b/third_party/rust_crates/vendor/trust-dns-proto/.cargo-checksum.json
new file mode 100644
index 0000000..397a4b9
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"f7d4f592ff696e9d17291a18fa3717aceb4943ab6b56c02a5dbc80e739cbff1a","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"10d73bf26900fa6dd6f2613bb962b7bd8fa1e66618fcf0f9f899aa071a4ee200","README.md":"ecc776860d7e7616e55a82488e27cb3785b37d89167abfa89c94c5356a2826d0","benches/lib.rs":"fc4dc5a10d65b9a46fdaf22a0cbe47b17ed768d22cb816652d8c26d37da5522d","benches/name_benches.rs":"3ba9302e3bca394dba5fe71949b0e409da3c3df74c2b70a6101d7abe47c3427d","src/error.rs":"ddc158399fea16dbb89023733124f4e6dfed4313fd1e0efd91bc521e45c0e921","src/lib.rs":"f3bbf860db2a3da9dde246fc6c78c497423fe2dcf7f9abbc272768db765e775e","src/multicast/mdns_client_stream.rs":"109108c26660ef40b11a3ab3c23977c1c99c2c1d3c9c03a01d0c85579ea6e5fb","src/multicast/mdns_stream.rs":"b416ad8dce6bf74464833b4fdc8a1733f4c2901067770ce55fbc63d7a4543ed0","src/multicast/mod.rs":"81377921f4e341ce90f0fcd5a3d248643c6b4efc3440f6631260d4475e80cb95","src/op/edns.rs":"d8e324021079c25a22a4290f878a3175b374733ed0f5b13398bffb1ff3ab415a","src/op/header.rs":"ae18e34e90cfdddf3958e72d2dd1a1aa18b19093522554d1fa7b7466be2bc95a","src/op/message.rs":"4a055bd8a4fdf18cec4c2682629a390f9b1a629413d0ef08bd238682a40344db","src/op/mod.rs":"81f68be0fdaf9a637e6d901996ba45f3c98381833677dd7516404ef54f5251d4","src/op/op_code.rs":"f4305189ffbddf310c8696461d64ecbcbe6b03b14a10ae4b7330d80b28bcf043","src/op/query.rs":"35391bd19881aa665b8f0f35a0362537576c019eee6d55f10934a2edc0ca7c5a","src/op/response_code.rs":"38d73e0278a253f3233ecfe9039e4f87ecfba79c5c27147ce2cb8b9e93d99bf4","src/rr/dns_class.rs":"a532fb6435fe44937cb680e921785f31363c2787209f4589c0b1c88bc5d2d9ca","src/rr/dnssec/algorithm.rs":"f96596e1ffde5a63e00da27770d1adc3b02c03f12248a3c640f2f0f8d3a2a082","src/rr/dnssec/digest_type.rs":"550657da67af2d401cbd9e31b2d3bfe0a161d995c24d7b2b94434385019f7852","src/rr/dnssec/ec_public_key.rs":"17dd730ed83c9c73f28d9e31ac0ccbcfbb68e9f6465db003913b15ac91cdd34e","src/rr/dnssec/mod.rs":"3478c66bac0237f5c09acf23285cf72ed8a6fa73dd2823ae0fd96a19e7c2c397","src/rr/dnssec/nsec3.rs":"a720e2c6eb6149b60fef35310580dff6e23e24825d85ac4cb7fd3f2518b123fd","src/rr/dnssec/public_key.rs":"89dc9d867cb271701d2d5ae2d424bcef774c65d970561ae9212e2b958e733084","src/rr/dnssec/rdata/dnskey.rs":"3302034711ef2c9b65434fae3dada71ae6e335fee70c7043a2ecb2189746c550","src/rr/dnssec/rdata/ds.rs":"426fff922566a58342da46afd7ae177c16c26f288fe61e65b872cbcb88edf4a0","src/rr/dnssec/rdata/key.rs":"a51dc8ecaa9f5306c20b9a0b1d424aa2027ffe3c4033421d47563db5fd624504","src/rr/dnssec/rdata/mod.rs":"b2ccb1d3729f5c3be2e62ffdbdd60d9f9b9f84fe834d8e4b153b28e7edf11406","src/rr/dnssec/rdata/nsec.rs":"2fb0446d6f9c07a40de9a048f3e548f222f1362e4bca091686b8eb2bb10a0497","src/rr/dnssec/rdata/nsec3.rs":"e078d146d1b43d958b234f81e476f8c70b5bc7f04a25067484e9b84209eb6b19","src/rr/dnssec/rdata/nsec3param.rs":"61e87b00ad3f02880d6b874e37b09ca167901fca9a8f5ceaab885f5ad780dc2a","src/rr/dnssec/rdata/sig.rs":"2e4ce816f3e35ef84f1420d8357e444e3f6e99f3b6cae092b98d70adbfd0796c","src/rr/dnssec/roots/19036.rsa":"067eb224a294bd0f6165ac74d1fbdee9cf361d058836481e9786e4fc9b86b7a7","src/rr/dnssec/roots/20326.rsa":"d6b602bc8f107abe8e9b68c2d0afbfe1ca655767063b1d20c31a6398f3521d2e","src/rr/dnssec/roots/README.md":"5c2d1a0fd94373031bb43b58b2c4f46c1f34b813253f751b929955aead174e59","src/rr/dnssec/rsa_public_key.rs":"635d440c372203d8e2bdd184edb33efd33c84f10921b458f72143cb0ea6b99b1","src/rr/dnssec/supported_algorithm.rs":"f4d42f8b66dd10887e3c1c2d6ecc7a4b649d286752907cd5f336071e4e870c48","src/rr/dnssec/tbs.rs":"5afd117d40dadf4eaa6cfe679d643620233bbbeeae6620ba80e27ac66aeb38cb","src/rr/dnssec/trust_anchor.rs":"3a89300cf5f55f7024b3dfaa41aa44913bf04256a08d17e2d8dc2b89fc876dac","src/rr/dnssec/verifier.rs":"47d0b36592fa19b2d35ca9400e4a896fc1d1bd45194744fbc9da6e672d0b5dde","src/rr/domain/label.rs":"eefdb39ec18f3ff1b32c6b0dc5f70ea194f55a3252411532281b856d1e66732c","src/rr/domain/mod.rs":"5711bfc28ca5787d177b2f7fb6de745b20bff680a6bdc6957ae815c9d50dc865","src/rr/domain/name.rs":"76d27a95e28680795bd95cb9c240609101ae264ccc7922fa54611fe8d9562ea3","src/rr/domain/try_parse_ip.rs":"e2083009558f3c71bf2846f5ecfa40db15f31a16f1669c1d24c8f6cb2bbf9b0d","src/rr/domain/usage.rs":"af35b9a33c63096bb610ae19883cb3800bca38b09d648086a4dd3197be235cb5","src/rr/mod.rs":"c33de71f04984b22095b59a588a31aae764de397c57bc845f6330a00c76a02a7","src/rr/rdata/a.rs":"0bd3a9bdde9753605ed40b6d0813cd9a6e9f64417d290569b3c7d1f5e4789b27","src/rr/rdata/aaaa.rs":"7fcd86c64dd2c60d52d0708bb451d21112460754a246d18b231eb4c7283ac998","src/rr/rdata/caa.rs":"ee5cc889205dc0af3f28b58c0e069fb0c67f2724322f54ea72ba17fbfbded221","src/rr/rdata/mod.rs":"6517234d66f6c3e8fb5f8c41725d7142e533e931d915aaf8bd1e6a9061882f98","src/rr/rdata/mx.rs":"91c4553e8c5bfd88a16b9611e346237a0b704a8413715d730e236d9246b5fee3","src/rr/rdata/name.rs":"8a60d8e4b1025147d49d9587acf1df204dad80d48456c3d81987003e33c946f7","src/rr/rdata/naptr.rs":"bf3a2a2013137af8201ae964d94a2d5e131087c8b2e15ef04d8b9887ffa55d19","src/rr/rdata/null.rs":"2a270abb336067524b7764b882ac16d74be0971a2ca44593d108afbfae3b24bd","src/rr/rdata/openpgpkey.rs":"b99b55bbfe2f6a6e89ae13b156c6f986d2d261df14a5dba0e1ddd5df484911d7","src/rr/rdata/opt.rs":"b7256ec1cd362c3e45fa3c01b106920f575b4d51d3c496761db1b5b6c9305ee4","src/rr/rdata/soa.rs":"8b237069a16fab5eb0a30150ca0884b4b2b975466c29b285246d7e805f91c70f","src/rr/rdata/srv.rs":"c1c1c18b769202342e06f3fdc1a58d36896fd14d0d7423dcf7be664a35d40d78","src/rr/rdata/sshfp.rs":"ef21a87276426983917d1f693928dc89bb5a9ad0b822a64315c191eb3c11b130","src/rr/rdata/tlsa.rs":"481c9d9ce8786302d6ab043b677a64211412e4069990125e9e4217f117135c20","src/rr/rdata/txt.rs":"0f3b428e0d7ea67a3e80f51d7d8cb6e478bf87fb7420c39f68f51e1e3fa04eba","src/rr/record_data.rs":"7807a12defb56764ff16a25019dbef12710d050157b26171dc28fca8e88e8b9e","src/rr/record_type.rs":"f5139c8e4b2a3d44d868181f1b435441d49caf17a5faa5f6ffc803106addc62c","src/rr/resource.rs":"e41865c454e00f0aad3722974c4812c23dba97b5547c562e34c52a6742277ab3","src/rr/rr_set.rs":"cac4a37a6d7fcb5a23378c203d59f24c192faa682bf32917723b5e6a8203cffb","src/serialize/binary/bin_tests.rs":"87acfd2d4b5a94e4bd140b43a51525e49587568a4673ca570b73a379d79ce0d9","src/serialize/binary/decoder.rs":"ba128672a85ded6f5fd67b157884e9113fad1d38289a3013ae09e14878052d12","src/serialize/binary/encoder.rs":"dbf9535622fa6f8e35254e73f895ebd8054dbebf55cc0de77311effbe14f950e","src/serialize/binary/mod.rs":"5d18ab6d578644fa2eac0e3cb75843c3a31e8369bf574f260c93f11da6e076a5","src/serialize/binary/restrict.rs":"605336655137e32ab4141806773ad4f5838c7c71e56fb65bbfec29e6d65a655b","src/serialize/mod.rs":"17d8844af8237014fbb10104877d225b8ea56a2daeb8f5f5e140ad0b7eb50f30","src/tcp/mod.rs":"c73cc9e56bb9241fb756d33de77fde2f21e1eb6a7c9de203b1cafebac1c2a1f4","src/tcp/tcp_client_stream.rs":"396c4f5842ada428da0c0217f7c440df3261519d6d88cc080c1dcc056f23451d","src/tcp/tcp_stream.rs":"3ca9291c7718b6910d70b882ed15c60c5d2f017a8aef6f3fe5b39bff57c596ee","src/tests/mod.rs":"b00b36d6ff6fbeebfe010866bd1764424e72bd81d09ede84390223aa0a5dea78","src/tests/tcp.rs":"8652c01f2dc712d3159375cd1cc82b04e2882fdfbeade850b73b26f75b8b08a7","src/tests/udp.rs":"a197548179af9fadf59b9ab256bd9ab5a2eee3aa5cdc892bf2ab78d9d31661f0","src/udp/mod.rs":"80be6cd754d1f6a7f88903050e8af2160a0fb0c8cd94b5eeabc9750ca2af4f4e","src/udp/udp_client_stream.rs":"d2f9730afaaa28f1ce439769d520f18c317b5de1287c9185f46740f679de9d83","src/udp/udp_stream.rs":"b4caa9d76a2e4a6285e7a278a9bab7cd030dec65e6f2a782662b187202ca8b5b","src/xfer/dns_exchange.rs":"a40ed3dea10033085eedf1435e0b420d592e10a1089eb306bb39b114d0d85f85","src/xfer/dns_handle.rs":"726144514e98809035c6eef21be808ff88f3474014612f4a44253ec56ef0a5f3","src/xfer/dns_multiplexer.rs":"4dc84148fd4704eabde2a0722ef10ed33df1134b3c98a4421219ca8595ff4f22","src/xfer/dns_request.rs":"6e14c4a623739cd752604c5cdc8ec7efec6df58b7fb51cba0741432b278298a4","src/xfer/dns_response.rs":"906f8b5efeeb30c3b43457a6afe466be1298e4f17458e785d7f3a253d08c5d99","src/xfer/dnssec_dns_handle.rs":"9a030064f79059c6c94d972d65804b7f6e58d1983d8787e39685b491d6e5cb54","src/xfer/mod.rs":"b86278282ba94ba331a0876f0c3e0540eb56042738042bc822ab415baabb0990","src/xfer/retry_dns_handle.rs":"6536796cd623abe2db3ac6aa535e518ce7b1b51d5149eea703b4d0cd35f801d1","src/xfer/serial_message.rs":"696f2d247662799715ccf9072d46f27f276afa14ee4092a699669a533e93de7e"},"package":"da8316d3a7fa285971a602e42ec6d31639cc3744e77694d89fea42152968063b"}
\ No newline at end of file
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/Cargo.toml b/third_party/rust_crates/vendor/trust-dns-proto/Cargo.toml
new file mode 100644
index 0000000..dd74145
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/Cargo.toml
@@ -0,0 +1,120 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+edition = "2018"
+name = "trust-dns-proto"
+version = "0.19.2"
+authors = ["Benjamin Fry <benjaminfry@me.com>"]
+description = "Trust-DNS is a safe and secure DNS library. This is the foundational DNS protocol library for all Trust-DNS projects.\n"
+homepage = "http://www.trust-dns.org/index.html"
+documentation = "https://docs.rs/trust-dns-proto"
+readme = "README.md"
+keywords = ["DNS", "BIND", "dig", "named", "dnssec"]
+categories = ["network-programming"]
+license = "MIT/Apache-2.0"
+repository = "https://github.com/bluejekyll/trust-dns"
+
+[lib]
+name = "trust_dns_proto"
+path = "src/lib.rs"
+[dependencies.async-trait]
+version = "0.1.22"
+
+[dependencies.backtrace]
+version = "0.3.40"
+
+[dependencies.data-encoding]
+version = "2.1.0"
+optional = true
+
+[dependencies.enum-as-inner]
+version = "0.3"
+
+[dependencies.futures]
+version = "0.3.0"
+
+[dependencies.idna]
+version = "0.2.0"
+
+[dependencies.js-sys]
+version = "0.3.35"
+optional = true
+
+[dependencies.lazy_static]
+version = "1.0"
+
+[dependencies.log]
+version = "0.4"
+
+[dependencies.openssl]
+version = "0.10"
+features = ["v102", "v110"]
+optional = true
+
+[dependencies.rand]
+version = "0.7"
+
+[dependencies.ring]
+version = "0.16"
+features = ["std"]
+optional = true
+
+[dependencies.serde]
+version = "1.0"
+optional = true
+
+[dependencies.smallvec]
+version = "1.0"
+
+[dependencies.socket2]
+version = "0.3.10"
+optional = true
+
+[dependencies.thiserror]
+version = "1.0.9"
+
+[dependencies.tokio]
+version = "0.2.1"
+optional = true
+
+[dependencies.url]
+version = "2.1.0"
+
+[dependencies.wasm-bindgen-crate]
+version = "0.2.58"
+optional = true
+package = "wasm-bindgen"
+[dev-dependencies.env_logger]
+version = "0.7"
+
+[dev-dependencies.tokio]
+version = "0.2.1"
+features = ["rt-core", "time"]
+
+[features]
+default = ["tokio-runtime"]
+dnssec = ["data-encoding"]
+dnssec-openssl = ["dnssec", "openssl"]
+dnssec-ring = ["dnssec", "ring"]
+mdns = ["socket2/reuseport"]
+serde-config = ["serde"]
+testing = []
+tokio-runtime = ["tokio/rt-core", "tokio/udp", "tokio/tcp", "tokio/time"]
+wasm-bindgen = ["wasm-bindgen-crate", "js-sys"]
+[badges.codecov]
+branch = "master"
+repository = "bluejekyll/trust-dns"
+service = "github"
+
+[badges.maintenance]
+status = "actively-developed"
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/LICENSE-APACHE b/third_party/rust_crates/vendor/trust-dns-proto/LICENSE-APACHE
new file mode 100644
index 0000000..8f71f43
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/LICENSE-APACHE
@@ -0,0 +1,202 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "{}"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright {yyyy} {name of copyright owner}
+
+   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.
+
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/LICENSE-MIT b/third_party/rust_crates/vendor/trust-dns-proto/LICENSE-MIT
new file mode 100644
index 0000000..b497b09
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/LICENSE-MIT
@@ -0,0 +1,20 @@
+Copyright (c) 2015 The trust-dns Developers
+Copyright (c) 2017 Google LLC.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/README.md b/third_party/rust_crates/vendor/trust-dns-proto/README.md
new file mode 100644
index 0000000..a502823
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/README.md
@@ -0,0 +1,13 @@
+# Overview
+
+Trust-DNS Proto is the foundational DNS protocol library and implementation for Trust-DNS. It is not expected to be used directly. Please see Trust-DNS [Resolver](https://crates.io/crates/trust-dns-resolver), [Client](https://crates.io/crates/trust-dns-client), or [Server](https://crates.io/crates/trust-dns-server) for higher level interfaces.
+
+*WARNING* The Proto crate is designed as an internal layer in the Trust-DNS ecosystem, it will change potentially in breaking ways, and should not generally be used directly. Please see the Resolver, Client or Server for more stable interfaces.
+
+## Minimum Rust Version
+
+The current minimum rustc version for this project is `1.39`
+
+## Versioning
+
+Trust-DNS does it's best job to follow semver. Trust-DNS will be promoted to 1.0 upon stabilization of the publicly exposed APIs. This does not mean that Trust-DNS will necessarily break on upgrades between 0.x updates. Whenever possible, old APIs will be deprecated with notes on what replaced those deprecations. Trust-DNS will make a best effort to never break software which depends on it due to API changes, though this can not be guaranteed. Deprecated interfaces will be maintained for at minimum one major release after that in which they were deprecated (where possible), with the exception of the upgrade to 1.0 where all deprecated interfaces will be planned to be removed.
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/benches/lib.rs b/third_party/rust_crates/vendor/trust-dns-proto/benches/lib.rs
new file mode 100644
index 0000000..7e16eeb
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/benches/lib.rs
@@ -0,0 +1,123 @@
+#![feature(test)]
+
+extern crate test;
+
+use trust_dns_proto::op::{Header, Message, MessageType, OpCode, ResponseCode};
+use trust_dns_proto::rr::Record;
+use trust_dns_proto::serialize::binary::{BinDecodable, BinDecoder, BinEncodable, BinEncoder};
+
+use test::Bencher;
+
+#[bench]
+fn bench_emit_header(b: &mut Bencher) {
+    let header = Header::new();
+    b.iter(|| {
+        // we need to create the vector here, otherwise its length is already big enough and the
+        // encoder does not need to resize it
+        let mut bytes = Vec::with_capacity(512);
+        let mut encoder = BinEncoder::new(&mut bytes);
+        header.emit(&mut encoder)
+    })
+}
+
+// TODO:
+// This is a bit silly, because everywhere in the codebase, we reserve 512 bytes for the buffer.
+// But what we want to measure here is the cost of reserving more space, which can happen for big
+// messages exceeding 512 bytes. A better benchmark would be to emit such a big message.
+#[bench]
+fn bench_parse_header_no_reservation(b: &mut Bencher) {
+    let header = Header::new();
+    b.iter(|| {
+        let mut bytes = Vec::with_capacity(0);
+        let mut encoder = BinEncoder::new(&mut bytes);
+        header.emit(&mut encoder)
+    })
+}
+
+#[bench]
+fn bench_parse_header(b: &mut Bencher) {
+    let byte_vec = vec![
+        0x01, 0x10, 0xAA, 0x83, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11,
+    ];
+    b.iter(|| {
+        let mut decoder = BinDecoder::new(&byte_vec);
+        Header::read(&mut decoder)
+    })
+}
+
+#[bench]
+fn bench_emit_message(b: &mut Bencher) {
+    let mut message = Message::new();
+    message
+        .set_id(10)
+        .set_message_type(MessageType::Response)
+        .set_op_code(OpCode::Update)
+        .set_authoritative(true)
+        .set_truncated(true)
+        .set_recursion_desired(true)
+        .set_recursion_available(true)
+        .set_authentic_data(true)
+        .set_checking_disabled(true)
+        .set_response_code(ResponseCode::ServFail);
+    message.add_answer(Record::new());
+    message.add_name_server(Record::new());
+    message.add_additional(Record::new());
+    b.iter(|| {
+        let mut byte_vec: Vec<u8> = Vec::with_capacity(512);
+        let mut encoder = BinEncoder::new(&mut byte_vec);
+        message.emit(&mut encoder)
+    })
+}
+
+#[bench]
+fn bench_emit_message_no_reservation(b: &mut Bencher) {
+    let mut message = Message::new();
+    message
+        .set_id(10)
+        .set_message_type(MessageType::Response)
+        .set_op_code(OpCode::Update)
+        .set_authoritative(true)
+        .set_truncated(true)
+        .set_recursion_desired(true)
+        .set_recursion_available(true)
+        .set_authentic_data(true)
+        .set_checking_disabled(true)
+        .set_response_code(ResponseCode::ServFail);
+    message.add_answer(Record::new());
+    message.add_name_server(Record::new());
+    message.add_additional(Record::new());
+    b.iter(|| {
+        let mut byte_vec: Vec<u8> = Vec::with_capacity(0);
+        let mut encoder = BinEncoder::new(&mut byte_vec);
+        message.emit(&mut encoder)
+    })
+}
+
+#[bench]
+fn bench_parse_message(b: &mut Bencher) {
+    let mut message = Message::new();
+    message
+        .set_id(10)
+        .set_message_type(MessageType::Response)
+        .set_op_code(OpCode::Update)
+        .set_authoritative(true)
+        .set_truncated(true)
+        .set_recursion_desired(true)
+        .set_recursion_available(true)
+        .set_authentic_data(true)
+        .set_checking_disabled(true)
+        .set_response_code(ResponseCode::ServFail);
+
+    message.add_answer(Record::new());
+    message.add_name_server(Record::new());
+    message.add_additional(Record::new());
+    let mut byte_vec: Vec<u8> = Vec::with_capacity(512);
+    {
+        let mut encoder = BinEncoder::new(&mut byte_vec);
+        message.emit(&mut encoder).unwrap();
+    }
+    b.iter(|| {
+        let mut decoder = BinDecoder::new(&byte_vec);
+        Message::read(&mut decoder)
+    })
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/benches/name_benches.rs b/third_party/rust_crates/vendor/trust-dns-proto/benches/name_benches.rs
new file mode 100644
index 0000000..3bcfc14
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/benches/name_benches.rs
@@ -0,0 +1,159 @@
+#![feature(test)]
+
+extern crate test;
+
+use std::cmp::Ordering;
+
+use test::Bencher;
+
+use trust_dns_proto::rr::*;
+
+#[bench]
+fn name_cmp_short(b: &mut Bencher) {
+    let name1 = Name::from_ascii("com").unwrap();
+    let name2 = Name::from_ascii("COM").unwrap();
+
+    b.iter(|| {
+        assert_eq!(name1.cmp(&name2), Ordering::Equal);
+    });
+}
+
+#[bench]
+fn name_cmp_short_not_eq(b: &mut Bencher) {
+    let name1 = Name::from_ascii("com").unwrap();
+    let name2 = Name::from_ascii("COM").unwrap();
+
+    b.iter(|| {
+        assert_ne!(name1.cmp_case(&name2), Ordering::Equal);
+    });
+}
+
+#[bench]
+fn name_cmp_short_case(b: &mut Bencher) {
+    let name1 = Name::from_ascii("com").unwrap();
+    let name2 = Name::from_ascii("com").unwrap();
+
+    b.iter(|| {
+        assert_eq!(name1.cmp_case(&name2), Ordering::Equal);
+    });
+}
+
+#[bench]
+fn name_cmp_medium(b: &mut Bencher) {
+    let name1 = Name::from_ascii("www.example.com").unwrap();
+    let name2 = Name::from_ascii("www.EXAMPLE.com").unwrap();
+
+    b.iter(|| {
+        assert_eq!(name1.cmp(&name2), Ordering::Equal);
+    });
+}
+
+#[bench]
+fn name_cmp_medium_not_eq(b: &mut Bencher) {
+    let name1 = Name::from_ascii("www.example.com").unwrap();
+    let name2 = Name::from_ascii("www.EXAMPLE.com").unwrap();
+
+    b.iter(|| {
+        assert_ne!(name1.cmp_case(&name2), Ordering::Equal);
+    });
+}
+
+#[bench]
+fn name_cmp_medium_case(b: &mut Bencher) {
+    let name1 = Name::from_ascii("www.example.com").unwrap();
+    let name2 = Name::from_ascii("www.example.com").unwrap();
+
+    b.iter(|| {
+        assert_eq!(name1.cmp_case(&name2), Ordering::Equal);
+    });
+}
+
+#[bench]
+fn name_cmp_long(b: &mut Bencher) {
+    let name1 = Name::from_ascii("a.crazy.really.long.example.com").unwrap();
+    let name2 = Name::from_ascii("a.crazy.really.long.EXAMPLE.com").unwrap();
+
+    b.iter(|| {
+        assert_eq!(name1.cmp(&name2), Ordering::Equal);
+    });
+}
+
+#[bench]
+fn name_cmp_long_not_eq(b: &mut Bencher) {
+    let name1 = Name::from_ascii("a.crazy.really.long.example.com").unwrap();
+    let name2 = Name::from_ascii("a.crazy.really.long.EXAMPLE.com").unwrap();
+
+    b.iter(|| {
+        assert_ne!(name1.cmp_case(&name2), Ordering::Equal);
+    });
+}
+
+#[bench]
+fn name_cmp_long_case(b: &mut Bencher) {
+    let name1 = Name::from_ascii("a.crazy.really.long.example.com").unwrap();
+    let name2 = Name::from_ascii("a.crazy.really.long.example.com").unwrap();
+
+    b.iter(|| {
+        assert_eq!(name1.cmp_case(&name2), Ordering::Equal);
+    });
+}
+
+#[bench]
+fn name_to_lower_short(b: &mut Bencher) {
+    let name1 = Name::from_ascii("COM").unwrap();
+
+    b.iter(|| {
+        let lower = name1.to_lowercase();
+        assert_eq!(lower.num_labels(), 1);
+    });
+}
+
+#[bench]
+fn name_to_lower_medium(b: &mut Bencher) {
+    let name1 = Name::from_ascii("example.COM").unwrap();
+
+    b.iter(|| {
+        let lower = name1.to_lowercase();
+        assert_eq!(lower.num_labels(), 2);
+    });
+}
+
+#[bench]
+fn name_to_lower_long(b: &mut Bencher) {
+    let name1 = Name::from_ascii("www.EXAMPLE.com").unwrap();
+
+    b.iter(|| {
+        let lower = name1.to_lowercase();
+        assert_eq!(lower.num_labels(), 3);
+    });
+}
+
+#[bench]
+fn name_no_lower_short(b: &mut Bencher) {
+    let name1 = Name::from_ascii("com").unwrap();
+
+    b.iter(|| {
+        let lower = name1.to_lowercase();
+        assert_eq!(lower.num_labels(), 1);
+    });
+}
+
+#[bench]
+fn name_no_lower_medium(b: &mut Bencher) {
+    let name1 = Name::from_ascii("example.com").unwrap();
+
+    b.iter(|| {
+        let lower = name1.to_lowercase();
+        assert_eq!(lower.num_labels(), 2);
+    });
+}
+
+#[bench]
+fn name_no_lower_long(b: &mut Bencher) {
+    let name1 = Name::from_ascii("www.example.com").unwrap();
+
+    b.iter(|| {
+        let lower = name1.to_lowercase();
+        assert_eq!(lower.num_labels(), 3);
+    });
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/error.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/error.rs
new file mode 100644
index 0000000..457343e
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/error.rs
@@ -0,0 +1,413 @@
+// Copyright 2015-2020 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! Error types for the crate
+
+#![deny(missing_docs)]
+
+use std::{fmt, io, sync};
+
+#[cfg(not(feature = "openssl"))]
+use self::not_openssl::SslErrorStack;
+#[cfg(not(feature = "ring"))]
+use self::not_ring::Unspecified;
+pub use backtrace::Backtrace as ExtBacktrace;
+use lazy_static::lazy_static;
+#[cfg(feature = "openssl")]
+use openssl::error::ErrorStack as SslErrorStack;
+#[cfg(feature = "ring")]
+use ring::error::Unspecified;
+use thiserror::Error;
+
+use crate::rr::{Name, RecordType};
+
+lazy_static! {
+    /// Boolean for checking if backtrace is enabled at runtime
+    pub static ref ENABLE_BACKTRACE: bool = {
+        use std::env;
+        let bt = env::var("RUST_BACKTRACE");
+        match bt.as_ref().map(|s| s as &str) {
+            Ok("full") | Ok("1") => true,
+            _ => false,
+        }
+    };
+}
+
+/// Generate a backtrace
+///
+/// If RUST_BACKTRACE is 1 or full then this will return Some(Backtrace), otherwise, NONE.
+#[macro_export]
+macro_rules! trace {
+    () => {{
+        use $crate::error::ExtBacktrace as Backtrace;
+
+        if *$crate::error::ENABLE_BACKTRACE {
+            Some(Backtrace::new())
+        } else {
+            None
+        }
+    }};
+}
+
+/// An alias for results returned by functions of this crate
+pub type ProtoResult<T> = ::std::result::Result<T, ProtoError>;
+
+/// The error kind for errors that get returned in the crate
+#[derive(Debug, Error)]
+pub enum ProtoErrorKind {
+    /// An error caused by a canceled future
+    #[error("future was canceled: {0:?}")]
+    Canceled(futures::channel::oneshot::Canceled),
+
+    /// Character data length exceeded the limit
+    #[error("char data length exceeds {max}: {len}")]
+    CharacterDataTooLong {
+        /// Specified maximum
+        max: usize,
+        /// Actual length
+        len: usize,
+    },
+
+    /// Overlapping labels
+    #[error("overlapping labels name {label} other {other}")]
+    LabelOverlapsWithOther {
+        /// Start of the label that is overlaps
+        label: usize,
+        /// Start of the other label
+        other: usize,
+    },
+
+    /// DNS protocol version doesn't have the expected version 3
+    #[error("dns key value unknown, must be 3: {0}")]
+    DnsKeyProtocolNot3(u8),
+
+    /// A domain name was too long
+    #[error("name label data exceed 255: {0}")]
+    DomainNameTooLong(usize),
+
+    /// EDNS resource record label is not the root label, although required
+    #[error("edns resource record label must be the root label (.): {0}")]
+    EdnsNameNotRoot(crate::rr::Name),
+
+    /// The length of rdata read was not as expected
+    #[error("incorrect rdata length read: {read} expected: {len}")]
+    IncorrectRDataLengthRead {
+        /// The amount of read data
+        read: usize,
+        /// The expected length of the data
+        len: usize,
+    },
+
+    /// Label bytes exceeded the limit of 63
+    #[error("label bytes exceed 63: {0}")]
+    LabelBytesTooLong(usize),
+
+    /// Label bytes exceeded the limit of 63
+    #[error("label points to data not prior to idx: {idx} ptr: {ptr}")]
+    PointerNotPriorToLabel {
+        /// index of the label containing this pointer
+        idx: usize,
+        /// location to which the pointer is directing
+        ptr: u16,
+    },
+
+    /// The maximum buffer size was exceeded
+    #[error("maximum buffer size exceeded: {0}")]
+    MaxBufferSizeExceeded(usize),
+
+    /// An error with an arbitrary message, referenced as &'static str
+    #[error("{0}")]
+    Message(&'static str),
+
+    /// An error with an arbitrary message, stored as String
+    #[error("{0}")]
+    Msg(String),
+
+    /// No error was specified
+    #[error("no error specified")]
+    NoError,
+
+    /// Not all records were able to be written
+    #[error("not all records could be written, wrote: {count}")]
+    NotAllRecordsWritten {
+        /// Number of records that were written before the error
+        count: usize,
+    },
+
+    /// Missing rrsigs
+    #[error("rrsigs are not present for record set name: {name} record_type: {record_type}")]
+    RrsigsNotPresent {
+        /// The record set name
+        name: Name,
+        /// The record type
+        record_type: RecordType,
+    },
+
+    /// An unknown algorithm type was found
+    #[error("algorithm type value unknown: {0}")]
+    UnknownAlgorithmTypeValue(u8),
+
+    /// An unknown dns class was found
+    #[error("dns class string unknown: {0}")]
+    UnknownDnsClassStr(String),
+
+    /// An unknown dns class value was found
+    #[error("dns class value unknown: {0}")]
+    UnknownDnsClassValue(u16),
+
+    /// An unknown record type string was found
+    #[error("record type string unknown: {0}")]
+    UnknownRecordTypeStr(String),
+
+    /// An unknown record type value was found
+    #[error("record type value unknown: {0}")]
+    UnknownRecordTypeValue(u16),
+
+    /// An unrecognized label code was found
+    #[error("unrecognized label code: {0:b}")]
+    UnrecognizedLabelCode(u8),
+
+    /// Unrecognized nsec3 flags were found
+    #[error("nsec3 flags should be 0b0000000*: {0:b}")]
+    UnrecognizedNsec3Flags(u8),
+
+    // foreign
+    /// An error got returned from IO
+    #[error("io error: {0}")]
+    Io(#[from] io::Error),
+
+    /// Any sync poised error
+    #[error("lock poisoned error")]
+    Poisoned,
+
+    /// A ring error
+    #[error("ring error: {0}")]
+    Ring(#[from] Unspecified),
+
+    /// An ssl error
+    #[error("ssl error: {0}")]
+    SSL(#[from] SslErrorStack),
+
+    /// A tokio timer error
+    #[error("timer error")]
+    Timer,
+
+    /// A request timed out
+    #[error("request timed out")]
+    Timeout,
+
+    /// An url parsing error
+    #[error("url parsing error")]
+    UrlParsing(#[from] url::ParseError),
+
+    /// A utf8 parsing error
+    #[error("error parsing utf8 string")]
+    Utf8(#[from] std::str::Utf8Error),
+}
+
+/// The error type for errors that get returned in the crate
+#[derive(Error, Clone, Debug)]
+pub struct ProtoError {
+    kind: ProtoErrorKind,
+    backtrack: Option<ExtBacktrace>,
+}
+
+impl ProtoError {
+    /// Get the kind of the error
+    pub fn kind(&self) -> &ProtoErrorKind {
+        &self.kind
+    }
+}
+
+impl fmt::Display for ProtoError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        if let Some(ref backtrace) = self.backtrack {
+            fmt::Display::fmt(&self.kind, f)?;
+            fmt::Debug::fmt(backtrace, f)
+        } else {
+            fmt::Display::fmt(&self.kind, f)
+        }
+    }
+}
+
+impl From<ProtoErrorKind> for ProtoError {
+    fn from(kind: ProtoErrorKind) -> ProtoError {
+        ProtoError {
+            kind,
+            backtrack: trace!(),
+        }
+    }
+}
+
+impl From<&'static str> for ProtoError {
+    fn from(msg: &'static str) -> ProtoError {
+        ProtoErrorKind::Message(msg).into()
+    }
+}
+
+impl From<String> for ProtoError {
+    fn from(msg: String) -> ProtoError {
+        ProtoErrorKind::Msg(msg).into()
+    }
+}
+
+impl From<io::Error> for ProtoError {
+    fn from(e: io::Error) -> ProtoError {
+        match e.kind() {
+            io::ErrorKind::TimedOut => ProtoErrorKind::Timeout.into(),
+            _ => ProtoErrorKind::from(e).into(),
+        }
+    }
+}
+
+impl<T> From<sync::PoisonError<T>> for ProtoError {
+    fn from(_e: sync::PoisonError<T>) -> ProtoError {
+        ProtoErrorKind::Poisoned.into()
+    }
+}
+
+impl From<Unspecified> for ProtoError {
+    fn from(e: Unspecified) -> ProtoError {
+        ProtoErrorKind::from(e).into()
+    }
+}
+
+impl From<SslErrorStack> for ProtoError {
+    fn from(e: SslErrorStack) -> ProtoError {
+        ProtoErrorKind::from(e).into()
+    }
+}
+
+impl From<url::ParseError> for ProtoError {
+    fn from(e: url::ParseError) -> ProtoError {
+        ProtoErrorKind::from(e).into()
+    }
+}
+
+impl From<std::str::Utf8Error> for ProtoError {
+    fn from(e: std::str::Utf8Error) -> ProtoError {
+        ProtoErrorKind::from(e).into()
+    }
+}
+
+/// Stubs for running without OpenSSL
+#[cfg(not(feature = "openssl"))]
+pub mod not_openssl {
+    use std;
+
+    /// SslErrorStac stub
+    #[derive(Debug)]
+    pub struct SslErrorStack;
+
+    impl std::fmt::Display for SslErrorStack {
+        fn fmt(&self, _: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
+            Ok(())
+        }
+    }
+
+    impl std::error::Error for SslErrorStack {
+        fn description(&self) -> &str {
+            "openssl feature not enabled"
+        }
+    }
+}
+
+/// Types used without ring
+#[cfg(not(feature = "ring"))]
+pub mod not_ring {
+    use std;
+
+    /// The Unspecified error replacement
+    #[derive(Debug)]
+    pub struct Unspecified;
+
+    impl std::fmt::Display for Unspecified {
+        fn fmt(&self, _: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
+            Ok(())
+        }
+    }
+
+    impl std::error::Error for Unspecified {
+        fn description(&self) -> &str {
+            "ring feature not enabled"
+        }
+    }
+}
+
+impl From<ProtoError> for io::Error {
+    fn from(e: ProtoError) -> Self {
+        match *e.kind() {
+            ProtoErrorKind::Timeout => io::Error::new(io::ErrorKind::TimedOut, e),
+            _ => io::Error::new(io::ErrorKind::Other, e),
+        }
+    }
+}
+
+impl From<ProtoError> for String {
+    fn from(e: ProtoError) -> Self {
+        e.to_string()
+    }
+}
+
+#[cfg(feature = "wasm-bindgen")]
+impl From<ProtoError> for wasm_bindgen_crate::JsValue {
+    fn from(e: ProtoError) -> Self {
+        js_sys::Error::new(&e.to_string()).into()
+    }
+}
+
+impl Clone for ProtoErrorKind {
+    fn clone(&self) -> Self {
+        use self::ProtoErrorKind::*;
+        match *self {
+            Canceled(ref c) => Canceled(*c),
+            CharacterDataTooLong { max, len } => CharacterDataTooLong { max, len },
+            LabelOverlapsWithOther { label, other } => LabelOverlapsWithOther { label, other },
+            DnsKeyProtocolNot3(protocol) => DnsKeyProtocolNot3(protocol),
+            DomainNameTooLong(len) => DomainNameTooLong(len),
+            EdnsNameNotRoot(ref found) => EdnsNameNotRoot(found.clone()),
+            IncorrectRDataLengthRead { read, len } => IncorrectRDataLengthRead { read, len },
+            LabelBytesTooLong(len) => LabelBytesTooLong(len),
+            PointerNotPriorToLabel { idx, ptr } => PointerNotPriorToLabel { idx, ptr },
+            MaxBufferSizeExceeded(max) => MaxBufferSizeExceeded(max),
+            Message(msg) => Message(msg),
+            Msg(ref msg) => Msg(msg.clone()),
+            NoError => NoError,
+            NotAllRecordsWritten { count } => NotAllRecordsWritten { count },
+            RrsigsNotPresent {
+                ref name,
+                ref record_type,
+            } => RrsigsNotPresent {
+                name: name.clone(),
+                record_type: *record_type,
+            },
+            UnknownAlgorithmTypeValue(value) => UnknownAlgorithmTypeValue(value),
+            UnknownDnsClassStr(ref value) => UnknownDnsClassStr(value.clone()),
+            UnknownDnsClassValue(value) => UnknownDnsClassValue(value),
+            UnknownRecordTypeStr(ref value) => UnknownRecordTypeStr(value.clone()),
+            UnknownRecordTypeValue(value) => UnknownRecordTypeValue(value),
+            UnrecognizedLabelCode(value) => UnrecognizedLabelCode(value),
+            UnrecognizedNsec3Flags(flags) => UnrecognizedNsec3Flags(flags),
+
+            // foreign
+            Io(ref e) => Io(io::Error::from(e.kind())),
+            Poisoned => Poisoned,
+            Ring(ref _e) => Ring(Unspecified),
+            SSL(ref e) => Msg(format!("there was an SSL error: {}", e)),
+            Timeout => Timeout,
+            Timer => Timer,
+            UrlParsing(ref e) => UrlParsing(*e),
+            Utf8(ref e) => Utf8(*e),
+        }
+    }
+}
+
+/// A trait marking a type which implements From<ProtoError> and
+/// std::error::Error types as well as Clone + Send
+pub trait FromProtoError: From<ProtoError> + std::error::Error + Clone {}
+
+impl<E> FromProtoError for E where E: From<ProtoError> + std::error::Error + Clone {}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/lib.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/lib.rs
new file mode 100644
index 0000000..065a0e6
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/lib.rs
@@ -0,0 +1,172 @@
+// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
+// Copyright 2017 Google LLC.
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+#![warn(
+    missing_docs,
+    clippy::dbg_macro,
+    clippy::print_stdout,
+    clippy::unimplemented
+)]
+#![recursion_limit = "2048"]
+
+//! Trust-DNS Protocol library
+
+use async_trait::async_trait;
+use futures::Future;
+
+use std::marker::Send;
+use std::time::Duration;
+#[cfg(any(test, feature = "tokio-runtime"))]
+use tokio::runtime::Runtime;
+#[cfg(any(test, feature = "tokio-runtime"))]
+use tokio::task::JoinHandle;
+
+macro_rules! try_ready_stream {
+    ($e:expr) => {{
+        match $e {
+            Poll::Ready(Some(Ok(t))) => t,
+            Poll::Ready(None) => return Poll::Ready(None),
+            Poll::Pending => return Poll::Pending,
+            Poll::Ready(Some(Err(e))) => return Poll::Ready(Some(Err(From::from(e)))),
+        }
+    }};
+}
+
+/// Spawn a background task, if it was present
+#[cfg(any(test, feature = "tokio-runtime"))]
+pub fn spawn_bg<F: Future<Output = R> + Send + 'static, R: Send + 'static>(
+    runtime: &Runtime,
+    background: F,
+) -> JoinHandle<R> {
+    runtime.spawn(background)
+}
+
+pub mod error;
+#[cfg(feature = "mdns")]
+pub mod multicast;
+pub mod op;
+pub mod rr;
+pub mod serialize;
+pub mod tcp;
+#[cfg(any(test, feature = "testing"))]
+pub mod tests;
+pub mod udp;
+pub mod xfer;
+
+#[doc(hidden)]
+pub use crate::xfer::dns_handle::{DnsHandle, DnsStreamHandle, StreamHandle};
+#[doc(hidden)]
+pub use crate::xfer::dns_multiplexer::DnsMultiplexer;
+#[doc(hidden)]
+#[cfg(feature = "dnssec")]
+pub use crate::xfer::dnssec_dns_handle::DnssecDnsHandle;
+#[doc(hidden)]
+pub use crate::xfer::retry_dns_handle::RetryDnsHandle;
+#[doc(hidden)]
+pub use crate::xfer::{BufDnsStreamHandle, BufStreamHandle};
+pub use error::ExtBacktrace;
+
+#[cfg(feature = "tokio-runtime")]
+#[doc(hidden)]
+pub mod iocompat {
+    use std::io;
+    use std::pin::Pin;
+    use std::task::{Context, Poll};
+
+    use futures::io::{AsyncRead, AsyncWrite};
+    use tokio::io::{AsyncRead as AsyncRead02, AsyncWrite as AsyncWrite02};
+
+    /// Conversion from `tokio::io::{AsyncRead, AsyncWrite}` to `std::io::{AsyncRead, AsyncWrite}`
+    pub struct AsyncIo02As03<T>(pub T);
+
+    impl<T> Unpin for AsyncIo02As03<T> {}
+    impl<R: AsyncRead02 + Unpin> AsyncRead for AsyncIo02As03<R> {
+        fn poll_read(
+            mut self: Pin<&mut Self>,
+            cx: &mut Context,
+            buf: &mut [u8],
+        ) -> Poll<io::Result<usize>> {
+            Pin::new(&mut self.0).poll_read(cx, buf)
+        }
+    }
+
+    impl<W: AsyncWrite02 + Unpin> AsyncWrite for AsyncIo02As03<W> {
+        fn poll_write(
+            mut self: Pin<&mut Self>,
+            cx: &mut Context<'_>,
+            buf: &[u8],
+        ) -> Poll<io::Result<usize>> {
+            Pin::new(&mut self.0).poll_write(cx, buf)
+        }
+        fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
+            Pin::new(&mut self.0).poll_flush(cx)
+        }
+        fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
+            Pin::new(&mut self.0).poll_shutdown(cx)
+        }
+    }
+}
+
+/// Generic executor.
+// This trait is created to facilitate running the tests defined in the tests mod using different types of
+// executors. It's used in Fuchsia OS, please be mindful when update it.
+pub trait Executor {
+    /// Create the implementor itself.
+    fn new() -> Self;
+
+    /// Spawns a future object to run synchronously or asynchronously depending on the specific
+    /// executor.
+    fn block_on<F: Future>(&mut self, future: F) -> F::Output;
+}
+
+#[cfg(feature = "tokio-runtime")]
+impl Executor for Runtime {
+    fn new() -> Self {
+        Runtime::new().expect("failed to create tokio runtime")
+    }
+
+    fn block_on<F: Future>(&mut self, future: F) -> F::Output {
+        self.block_on(future)
+    }
+}
+
+/// Generic Time for Delay and Timeout.
+// This trait is created to allow to use different types of time systems. It's used in Fuchsia OS, please be mindful when update it.
+#[async_trait]
+pub trait Time {
+    /// Return a type that implements `Future` that will wait until the specified duration has
+    /// elapsed.
+    async fn delay_for(duration: Duration);
+
+    /// Return a type that implement `Future` to complete before the specified duration has elapsed.
+    async fn timeout<F: 'static + Future + Send>(
+        duration: Duration,
+        future: F,
+    ) -> Result<F::Output, std::io::Error>;
+}
+
+/// New type which is implemented using tokio::time::{Delay, Timeout}
+#[cfg(any(test, feature = "tokio-runtime"))]
+pub struct TokioTime;
+
+#[cfg(any(test, feature = "tokio-runtime"))]
+#[async_trait]
+impl Time for TokioTime {
+    async fn delay_for(duration: Duration) {
+        tokio::time::delay_for(duration).await
+    }
+
+    async fn timeout<F: 'static + Future + Send>(
+        duration: Duration,
+        future: F,
+    ) -> Result<F::Output, std::io::Error> {
+        tokio::time::timeout(duration, future)
+            .await
+            .map_err(move |_| std::io::Error::new(std::io::ErrorKind::TimedOut, "future timed out"))
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/multicast/mdns_client_stream.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/multicast/mdns_client_stream.rs
new file mode 100644
index 0000000..d39c0ea
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/multicast/mdns_client_stream.rs
@@ -0,0 +1,119 @@
+// Copyright 2015-2018 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+use std::fmt::{self, Display};
+use std::net::{Ipv4Addr, SocketAddr};
+use std::pin::Pin;
+use std::task::{Context, Poll};
+
+use futures::stream::{StreamExt, TryStreamExt};
+use futures::{Future, FutureExt, Stream, TryFutureExt};
+
+use crate::error::ProtoError;
+use crate::multicast::mdns_stream::{MDNS_IPV4, MDNS_IPV6};
+use crate::multicast::{MdnsQueryType, MdnsStream};
+use crate::xfer::{DnsClientStream, SerialMessage};
+use crate::{BufDnsStreamHandle, DnsStreamHandle};
+
+/// A UDP client stream of DNS binary packets
+#[must_use = "futures do nothing unless polled"]
+pub struct MdnsClientStream {
+    mdns_stream: MdnsStream,
+}
+
+impl MdnsClientStream {
+    /// associates the socket to the well-known ipv4 multicast address
+    pub fn new_ipv4(
+        mdns_query_type: MdnsQueryType,
+        packet_ttl: Option<u32>,
+        ipv4_if: Option<Ipv4Addr>,
+    ) -> (MdnsClientConnect, Box<dyn DnsStreamHandle + Send>) {
+        Self::new(*MDNS_IPV4, mdns_query_type, packet_ttl, ipv4_if, None)
+    }
+
+    /// associates the socket to the well-known ipv6 multicast address
+    pub fn new_ipv6(
+        mdns_query_type: MdnsQueryType,
+        packet_ttl: Option<u32>,
+        ipv6_if: Option<u32>,
+    ) -> (MdnsClientConnect, Box<dyn DnsStreamHandle + Send>) {
+        Self::new(*MDNS_IPV6, mdns_query_type, packet_ttl, None, ipv6_if)
+    }
+
+    /// it is expected that the resolver wrapper will be responsible for creating and managing
+    ///  new UdpClients such that each new client would have a random port (reduce chance of cache
+    ///  poisoning)
+    ///
+    /// # Return
+    ///
+    /// a tuple of a Future Stream which will handle sending and receiving messages, and a
+    ///  handle which can be used to send messages into the stream.
+    #[allow(clippy::new_ret_no_self)]
+    pub fn new(
+        mdns_addr: SocketAddr,
+        mdns_query_type: MdnsQueryType,
+        packet_ttl: Option<u32>,
+        ipv4_if: Option<Ipv4Addr>,
+        ipv6_if: Option<u32>,
+    ) -> (MdnsClientConnect, Box<dyn DnsStreamHandle + Send>) {
+        let (stream_future, sender) =
+            MdnsStream::new(mdns_addr, mdns_query_type, packet_ttl, ipv4_if, ipv6_if);
+
+        let stream_future = stream_future
+            .map_ok(move |mdns_stream| MdnsClientStream { mdns_stream })
+            .map_err(ProtoError::from);
+
+        let new_future = Box::new(stream_future);
+        let new_future = MdnsClientConnect(new_future);
+
+        let sender = Box::new(BufDnsStreamHandle::new(mdns_addr, sender));
+
+        (new_future, sender)
+    }
+}
+
+impl Display for MdnsClientStream {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+        write!(formatter, "mDNS({})", self.mdns_stream.multicast_addr())
+    }
+}
+
+impl DnsClientStream for MdnsClientStream {
+    fn name_server_addr(&self) -> SocketAddr {
+        self.mdns_stream.multicast_addr()
+    }
+}
+
+impl Stream for MdnsClientStream {
+    type Item = Result<SerialMessage, ProtoError>;
+
+    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
+        let mdns_stream = &mut self.as_mut().mdns_stream;
+        mdns_stream.map_err(ProtoError::from).poll_next_unpin(cx)
+        // match ready!(self.mdns_stream.poll_next_unpin(cx).map_err(ProtoError::from)) {
+        //     Some(serial_message) => {
+        //         // TODO: for mDNS queries could come from anywhere. It's not clear that there is anything
+        //         //       we can validate in this case.
+        //         Poll::Ready(Some(Ok(serial_message)))
+        //     }
+        //     None => Poll::Ready(None),
+        // }
+    }
+}
+
+/// A future that resolves to an MdnsClientStream
+pub struct MdnsClientConnect(
+    Box<dyn Future<Output = Result<MdnsClientStream, ProtoError>> + Send + Unpin>,
+);
+
+impl Future for MdnsClientConnect {
+    type Output = Result<MdnsClientStream, ProtoError>;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+        self.0.as_mut().poll_unpin(cx)
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/multicast/mdns_stream.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/multicast/mdns_stream.rs
new file mode 100644
index 0000000..bf5bc9f
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/multicast/mdns_stream.rs
@@ -0,0 +1,737 @@
+// Copyright 2015-2018 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+use std;
+use std::io;
+use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
+use std::pin::Pin;
+use std::sync::Arc;
+use std::task::{Context, Poll};
+
+use futures::channel::mpsc::unbounded;
+use futures::future;
+use futures::lock::Mutex;
+use futures::ready;
+use futures::stream::{Stream, StreamExt};
+use futures::{Future, FutureExt, TryFutureExt};
+use lazy_static::lazy_static;
+use log::{debug, trace};
+use rand;
+use rand::distributions::{uniform::Uniform, Distribution};
+use socket2::{self, Socket};
+use tokio::net::UdpSocket;
+
+use crate::multicast::MdnsQueryType;
+use crate::udp::UdpStream;
+use crate::xfer::SerialMessage;
+use crate::BufStreamHandle;
+
+pub const MDNS_PORT: u16 = 5353;
+lazy_static! {
+    /// mDNS ipv4 address https://www.iana.org/assignments/multicast-addresses/multicast-addresses.xhtml
+    pub static ref MDNS_IPV4: SocketAddr = SocketAddr::new(Ipv4Addr::new(224,0,0,251).into(), MDNS_PORT);
+    /// link-local mDNS ipv6 address https://www.iana.org/assignments/ipv6-multicast-addresses/ipv6-multicast-addresses.xhtml
+    pub static ref MDNS_IPV6: SocketAddr = SocketAddr::new(Ipv6Addr::new(0xFF02, 0, 0, 0, 0, 0, 0, 0x00FB).into(), MDNS_PORT);
+}
+
+/// A UDP stream of DNS binary packets
+#[must_use = "futures do nothing unless polled"]
+pub struct MdnsStream {
+    /// Multicast address used for mDNS queries
+    multicast_addr: SocketAddr,
+    /// This is used for sending and (directly) receiving messages
+    datagram: Option<UdpStream<UdpSocket>>,
+    // FIXME: like UdpStream, this Arc is unnecessary, only needed for temp async/await capture below
+    /// In one-shot multicast, this will not join the multicast group
+    multicast: Option<Arc<Mutex<UdpSocket>>>,
+    /// Receiving portion of the MdnsStream
+    rcving_mcast: Option<Pin<Box<dyn Future<Output = io::Result<SerialMessage>> + Send>>>,
+}
+
+impl MdnsStream {
+    /// associates the socket to the well-known ipv4 multicast address
+    pub fn new_ipv4(
+        mdns_query_type: MdnsQueryType,
+        packet_ttl: Option<u32>,
+        ipv4_if: Option<Ipv4Addr>,
+    ) -> (
+        Box<dyn Future<Output = Result<MdnsStream, io::Error>> + Send + Unpin>,
+        BufStreamHandle,
+    ) {
+        Self::new(*MDNS_IPV4, mdns_query_type, packet_ttl, ipv4_if, None)
+    }
+
+    /// associates the socket to the well-known ipv6 multicast address
+    pub fn new_ipv6(
+        mdns_query_type: MdnsQueryType,
+        packet_ttl: Option<u32>,
+        ipv6_if: Option<u32>,
+    ) -> (
+        Box<dyn Future<Output = Result<MdnsStream, io::Error>> + Send + Unpin>,
+        BufStreamHandle,
+    ) {
+        Self::new(*MDNS_IPV6, mdns_query_type, packet_ttl, None, ipv6_if)
+    }
+
+    /// Returns the address of the multicast network in use
+    pub fn multicast_addr(&self) -> SocketAddr {
+        self.multicast_addr
+    }
+
+    /// This method is available for specifying a custom Multicast address to use.
+    ///
+    /// In general this operates nearly identically to UDP, except that it automatically joins
+    ///  the default multicast DNS addresses. See https://tools.ietf.org/html/rfc6762#section-5
+    ///  for details.
+    ///
+    /// When sending ipv6 multicast packets, the interface being used is required,
+    ///  this will panic if the interface is not specified for all MdnsQueryType except Passive
+    ///  (which does not allow sending data)
+    ///
+    /// # Arguments
+    ///
+    /// * `multicast_addr` - address to use for multicast requests
+    /// * `mdns_query_type` - true if the querier using this socket will only perform standard DNS queries over multicast.
+    /// * `ipv4_if` - Address to bind to for sending multicast packets, defaults to `0.0.0.0` if not specified (not relevant for ipv6)
+    /// * `ipv6_if` - Interface index for the interface to be used when sending ipv6 packets.
+    ///
+    /// # Return
+    ///
+    /// a tuple of a Future Stream which will handle sending and receiving messages, and a
+    ///  handle which can be used to send messages into the stream.
+    pub fn new(
+        multicast_addr: SocketAddr,
+        mdns_query_type: MdnsQueryType,
+        packet_ttl: Option<u32>,
+        ipv4_if: Option<Ipv4Addr>,
+        ipv6_if: Option<u32>,
+    ) -> (
+        Box<dyn Future<Output = Result<MdnsStream, io::Error>> + Send + Unpin>,
+        BufStreamHandle,
+    ) {
+        let (message_sender, outbound_messages) = unbounded();
+        let message_sender = BufStreamHandle::new(message_sender);
+
+        let multicast_socket = match Self::join_multicast(&multicast_addr, mdns_query_type) {
+            Ok(socket) => socket,
+            Err(err) => return (Box::new(future::err(err)), message_sender),
+        };
+
+        // TODO: allow the bind address to be specified...
+        // constructs a future for getting the next randomly bound port to a UdpSocket
+        let next_socket = Self::next_bound_local_address(
+            &multicast_addr,
+            mdns_query_type,
+            packet_ttl,
+            ipv4_if,
+            ipv6_if,
+        );
+
+        // while 0 is meant to keep the packet on localhost, linux regards this as an error,
+        //   while macOS (BSD?) and Windows allow it.
+        if let Some(ttl) = packet_ttl {
+            assert!(ttl > 0, "TTL must be greater than 0");
+        }
+
+        // This set of futures collapses the next udp socket into a stream which can be used for
+        //  sending and receiving udp packets.
+        let stream = {
+            Box::new(
+                next_socket
+                    .map(move |socket| match socket {
+                        Ok(Some(socket)) => Ok(Some(UdpSocket::from_std(socket)?)),
+                        Ok(None) => Ok(None),
+                        Err(err) => Err(err),
+                    })
+                    .map_ok(move |socket: Option<_>| {
+                        let datagram: Option<_> =
+                            socket.map(|socket| UdpStream::from_parts(socket, outbound_messages));
+                        let multicast: Option<_> = multicast_socket.map(|multicast_socket| {
+                            Arc::new(Mutex::new(
+                                UdpSocket::from_std(multicast_socket).expect("bad handle?"),
+                            ))
+                        });
+
+                        MdnsStream {
+                            multicast_addr,
+                            datagram,
+                            multicast,
+                            rcving_mcast: None,
+                        }
+                    }),
+            )
+        };
+
+        (stream, message_sender)
+    }
+
+    /// On Windows, unlike all Unix variants, it is improper to bind to the multicast address
+    ///
+    /// see https://msdn.microsoft.com/en-us/library/windows/desktop/ms737550(v=vs.85).aspx
+    #[cfg(windows)]
+    fn bind_multicast(socket: &Socket, multicast_addr: &SocketAddr) -> io::Result<()> {
+        let multicast_addr = match *multicast_addr {
+            SocketAddr::V4(addr) => SocketAddr::new(Ipv4Addr::new(0, 0, 0, 0).into(), addr.port()),
+            SocketAddr::V6(addr) => {
+                SocketAddr::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).into(), addr.port())
+            }
+        };
+        socket.bind(&socket2::SockAddr::from(multicast_addr))
+    }
+
+    /// On unixes we bind to the multicast address, which causes multicast packets to be filtered
+    #[cfg(unix)]
+    fn bind_multicast(socket: &Socket, multicast_addr: &SocketAddr) -> io::Result<()> {
+        socket.bind(&socket2::SockAddr::from(*multicast_addr))
+    }
+
+    /// Returns a socket joined to the multicast address
+    fn join_multicast(
+        multicast_addr: &SocketAddr,
+        mdns_query_type: MdnsQueryType,
+    ) -> Result<Option<std::net::UdpSocket>, io::Error> {
+        if !mdns_query_type.join_multicast() {
+            return Ok(None);
+        }
+
+        let ip_addr = multicast_addr.ip();
+        // it's an error to not use a proper mDNS address
+        if !ip_addr.is_multicast() {
+            return Err(io::Error::new(
+                io::ErrorKind::Other,
+                format!("expected multicast address for binding: {}", ip_addr),
+            ));
+        }
+
+        // binding the UdpSocket to the multicast address tells the OS to filter all packets on this socket to just this
+        //   multicast address
+        // TODO: allow the binding interface to be specified
+        let socket = match ip_addr {
+            IpAddr::V4(ref mdns_v4) => {
+                let socket = Socket::new(
+                    socket2::Domain::ipv4(),
+                    socket2::Type::dgram(),
+                    Some(socket2::Protocol::udp()),
+                )?;
+                socket.join_multicast_v4(mdns_v4, &Ipv4Addr::new(0, 0, 0, 0))?;
+                socket
+            }
+            IpAddr::V6(ref mdns_v6) => {
+                let socket = Socket::new(
+                    socket2::Domain::ipv6(),
+                    socket2::Type::dgram(),
+                    Some(socket2::Protocol::udp()),
+                )?;
+
+                socket.set_only_v6(true)?;
+                socket.join_multicast_v6(mdns_v6, 0)?;
+                socket
+            }
+        };
+
+        socket.set_nonblocking(true)?;
+        socket.set_reuse_address(true)?;
+        #[cfg(unix)] // this is currently restricted to Unix's in socket2
+        socket.set_reuse_port(true)?;
+        Self::bind_multicast(&socket, multicast_addr)?;
+
+        debug!("joined {}", multicast_addr);
+        Ok(Some(socket.into_udp_socket()))
+    }
+
+    /// Creates a future for randomly binding to a local socket address for client connections.
+    fn next_bound_local_address(
+        multicast_addr: &SocketAddr,
+        mdns_query_type: MdnsQueryType,
+        packet_ttl: Option<u32>,
+        ipv4_if: Option<Ipv4Addr>,
+        ipv6_if: Option<u32>,
+    ) -> NextRandomUdpSocket {
+        let bind_address: IpAddr = match *multicast_addr {
+            SocketAddr::V4(..) => IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)),
+            SocketAddr::V6(..) => IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)),
+        };
+
+        NextRandomUdpSocket {
+            bind_address,
+            mdns_query_type,
+            packet_ttl,
+            ipv4_if,
+            ipv6_if,
+        }
+    }
+}
+
+impl Stream for MdnsStream {
+    type Item = io::Result<SerialMessage>;
+
+    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
+        assert!(self.datagram.is_some() || self.multicast.is_some());
+
+        // we poll the datagram socket first, if available, since it's a direct response or direct request
+        if let Some(ref mut datagram) = self.as_mut().datagram {
+            match datagram.poll_next_unpin(cx) {
+                Poll::Ready(ready) => return Poll::Ready(ready),
+                Poll::Pending => (), // drop through
+            }
+        }
+
+        loop {
+            let msg = if let Some(ref mut receiving) = self.rcving_mcast {
+                // TODO: should we drop this packet if it's not from the same src as dest?
+                let msg = ready!(receiving.as_mut().poll_unpin(cx))?;
+
+                Some(Poll::Ready(Some(Ok(msg))))
+            } else {
+                None
+            };
+
+            self.rcving_mcast = None;
+
+            if let Some(msg) = msg {
+                return msg;
+            }
+
+            // let socket = Arc::clone(socket);
+            if let Some(ref socket) = self.multicast {
+                let socket = Arc::clone(socket);
+                let receive_future = async {
+                    let socket = socket;
+                    let mut buf = [0u8; 2048];
+                    let mut socket = socket.lock().await;
+                    let (len, src) = socket.recv_from(&mut buf).await?;
+
+                    Ok(SerialMessage::new(
+                        buf.iter().take(len).cloned().collect(),
+                        src,
+                    ))
+                };
+
+                self.rcving_mcast = Some(Box::pin(receive_future.boxed()));
+            }
+        }
+    }
+}
+
+#[must_use = "futures do nothing unless polled"]
+struct NextRandomUdpSocket {
+    bind_address: IpAddr,
+    mdns_query_type: MdnsQueryType,
+    packet_ttl: Option<u32>,
+    ipv4_if: Option<Ipv4Addr>,
+    ipv6_if: Option<u32>,
+}
+
+impl NextRandomUdpSocket {
+    fn prepare_sender(&self, socket: std::net::UdpSocket) -> io::Result<std::net::UdpSocket> {
+        let addr = socket.local_addr()?;
+        debug!("preparing sender on: {}", addr);
+
+        let socket = Socket::from(socket);
+
+        // TODO: TTL doesn't work on ipv6
+        match addr {
+            SocketAddr::V4(..) => {
+                socket.set_multicast_loop_v4(true)?;
+                socket.set_multicast_if_v4(
+                    &self.ipv4_if.unwrap_or_else(|| Ipv4Addr::new(0, 0, 0, 0)),
+                )?;
+                if let Some(ttl) = self.packet_ttl {
+                    socket.set_ttl(ttl)?;
+                    socket.set_multicast_ttl_v4(ttl)?;
+                }
+            }
+            SocketAddr::V6(..) => {
+                let ipv6_if = self.ipv6_if.unwrap_or_else(|| {
+                    panic!("for ipv6 multicasting the interface must be specified")
+                });
+
+                socket.set_multicast_loop_v6(true)?;
+                socket.set_multicast_if_v6(ipv6_if)?;
+                if let Some(ttl) = self.packet_ttl {
+                    socket.set_unicast_hops_v6(ttl)?;
+                    socket.set_multicast_hops_v6(ttl)?;
+                }
+            }
+        }
+
+        Ok(socket.into_udp_socket())
+    }
+}
+
+impl Future for NextRandomUdpSocket {
+    // TODO: clean this up, the RandomUdpSocket shouldnt' care about the query type
+    type Output = io::Result<Option<std::net::UdpSocket>>;
+
+    /// polls until there is an available next random UDP port.
+    ///
+    /// if there is no port available after 10 attempts, returns NotReady
+    fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+        // non-one-shot, i.e. continuous, always use one of the well-known mdns ports and bind to the multicast addr
+        if !self.mdns_query_type.sender() {
+            debug!("skipping sending stream");
+            Poll::Ready(Ok(None))
+        } else if self.mdns_query_type.bind_on_5353() {
+            let addr = SocketAddr::new(self.bind_address, MDNS_PORT);
+            debug!("binding sending stream to {}", addr);
+            let socket = std::net::UdpSocket::bind(&addr)?;
+            let socket = self.prepare_sender(socket)?;
+
+            Poll::Ready(Ok(Some(socket)))
+        } else {
+            // TODO: this is basically identical to UdpStream from here... share some code? (except for the port restriction)
+            // one-shot queries look very similar to UDP socket, but can't listen on 5353
+            let rand_port_range = Uniform::new_inclusive(1025_u16, u16::max_value());
+            let mut rand = rand::thread_rng();
+
+            for attempt in 0..10 {
+                let port = rand_port_range.sample(&mut rand); // the range is [0 ... u16::max]
+
+                // see one_shot usage info: https://tools.ietf.org/html/rfc6762#section-5
+                //  the MDNS_PORT is used to signal to remote processes that this is capable of receiving multicast packets
+                //  i.e. is joined to the multicast address.
+                if port == MDNS_PORT {
+                    trace!("unlucky, got MDNS_PORT");
+                    continue;
+                }
+
+                let addr = SocketAddr::new(self.bind_address, port);
+                debug!("binding sending stream to {}", addr);
+
+                match std::net::UdpSocket::bind(&addr) {
+                    Ok(socket) => {
+                        let socket = self.prepare_sender(socket)?;
+                        return Poll::Ready(Ok(Some(socket)));
+                    }
+                    Err(err) => debug!("unable to bind port, attempt: {}: {}", attempt, err),
+                }
+            }
+
+            debug!("could not get next random port, delaying");
+
+            // TODO: this replaced a task::current().notify, is it correct?
+            cx.waker().wake_by_ref();
+            Poll::Pending
+        }
+    }
+}
+
+#[cfg(test)]
+pub mod tests {
+    #![allow(clippy::dbg_macro, clippy::print_stdout)]
+
+    use super::*;
+    use futures::future::Either;
+    use tokio::runtime;
+
+    // TODO: is there a better way?
+    const BASE_TEST_PORT: u16 = 5379;
+
+    lazy_static! {
+        /// 250 appears to be unused/unregistered
+        static ref TEST_MDNS_IPV4: IpAddr = Ipv4Addr::new(224,0,0,250).into();
+        /// FA appears to be unused/unregistered
+        static ref TEST_MDNS_IPV6: IpAddr = Ipv6Addr::new(0xFF02, 0, 0, 0, 0, 0, 0, 0x00FA).into();
+    }
+
+    // one_shot tests are basically clones from the udp tests
+    #[test]
+    fn test_next_random_socket() {
+        // use env_logger;
+        // env_logger::init();
+
+        let mut io_loop = runtime::Runtime::new().unwrap();
+        let (stream, _) = MdnsStream::new(
+            SocketAddr::new(*TEST_MDNS_IPV4, BASE_TEST_PORT),
+            MdnsQueryType::OneShot,
+            Some(1),
+            None,
+            None,
+        );
+        let result = io_loop.block_on(stream);
+
+        if let Err(error) = result {
+            println!("Random address error: {:#?}", error);
+            panic!("failed to get next random address");
+        }
+    }
+
+    // FIXME: reenable after breakage in async/await
+    #[ignore]
+    #[test]
+    fn test_one_shot_mdns_ipv4() {
+        one_shot_mdns_test(SocketAddr::new(*TEST_MDNS_IPV4, BASE_TEST_PORT + 1));
+    }
+
+    #[test]
+    #[ignore]
+    fn test_one_shot_mdns_ipv6() {
+        one_shot_mdns_test(SocketAddr::new(*TEST_MDNS_IPV6, BASE_TEST_PORT + 2));
+    }
+
+    //   as there are probably unexpected responses coming on the standard addresses
+    fn one_shot_mdns_test(mdns_addr: SocketAddr) {
+        use std::time::Duration;
+
+        let client_done = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false));
+
+        let test_bytes: &'static [u8; 8] = b"DEADBEEF";
+        let send_recv_times = 10;
+        let client_done_clone = client_done.clone();
+
+        // an in and out server
+        let server_handle = std::thread::Builder::new()
+            .name("test_one_shot_mdns:server".to_string())
+            .spawn(move || {
+                let mut server_loop = runtime::Runtime::new().unwrap();
+                let mut timeout =
+                    future::lazy(|_| tokio::time::delay_for(Duration::from_millis(100)))
+                        .flatten()
+                        .boxed();
+
+                // TTLs are 0 so that multicast test packets never leave the test host...
+                // FIXME: this is hardcoded to index 5 for ipv6, which isn't going to be correct in most cases...
+                let (server_stream_future, server_sender) = MdnsStream::new(
+                    mdns_addr,
+                    MdnsQueryType::OneShotJoin,
+                    Some(1),
+                    None,
+                    Some(5),
+                );
+
+                // For one-shot responses we are competing with a system mDNS responder, we will respond from a different port...
+                let mut server_stream = server_loop
+                    .block_on(server_stream_future)
+                    .expect("could not create mDNS listener")
+                    .into_future();
+
+                for _ in 0..=send_recv_times {
+                    if client_done_clone.load(std::sync::atomic::Ordering::Relaxed) {
+                        return;
+                    }
+                    // wait for some bytes...
+                    match server_loop.block_on(
+                        future::lazy(|_| future::select(server_stream, timeout)).flatten(),
+                    ) {
+                        Either::Left((buffer_and_addr_stream_tmp, timeout_tmp)) => {
+                            let (buffer_and_addr, stream_tmp): (
+                                Option<Result<SerialMessage, io::Error>>,
+                                MdnsStream,
+                            ) = buffer_and_addr_stream_tmp;
+
+                            server_stream = stream_tmp.into_future();
+                            timeout = timeout_tmp;
+                            let (buffer, addr) = buffer_and_addr
+                                .expect("no msg received")
+                                .expect("error receiving msg")
+                                .unwrap();
+
+                            assert_eq!(&buffer, test_bytes);
+                            //println!("server got data! {}", addr);
+
+                            // bounce them right back...
+                            server_sender
+                                .unbounded_send(SerialMessage::new(test_bytes.to_vec(), addr))
+                                .expect("could not send to client");
+                        }
+                        Either::Right(((), buffer_and_addr_stream_tmp)) => {
+                            server_stream = buffer_and_addr_stream_tmp;
+                            timeout = future::lazy(|_| {
+                                tokio::time::delay_for(Duration::from_millis(100))
+                            })
+                            .flatten()
+                            .boxed();
+                        }
+                    }
+
+                    // let the server turn for a bit... send the message
+                    server_loop.block_on(tokio::time::delay_for(Duration::from_millis(100)));
+                }
+            })
+            .unwrap();
+
+        // setup the client, which is going to run on the testing thread...
+        let mut io_loop = runtime::Runtime::new().unwrap();
+
+        // FIXME: this is hardcoded to index 5 for ipv6, which isn't going to be correct in most cases...
+        let (stream, sender) =
+            MdnsStream::new(mdns_addr, MdnsQueryType::OneShot, Some(1), None, Some(5));
+        let mut stream = io_loop.block_on(stream).ok().unwrap().into_future();
+        let mut timeout = future::lazy(|_| tokio::time::delay_for(Duration::from_millis(100)))
+            .flatten()
+            .boxed();
+        let mut successes = 0;
+
+        for _ in 0..send_recv_times {
+            // test once
+            sender
+                .unbounded_send(SerialMessage::new(test_bytes.to_vec(), mdns_addr))
+                .unwrap();
+
+            println!("client sending data!");
+
+            // TODO: this lazy isn't needed is it?
+            match io_loop.block_on(future::lazy(|_| future::select(stream, timeout)).flatten()) {
+                Either::Left((buffer_and_addr_stream_tmp, timeout_tmp)) => {
+                    let (buffer_and_addr, stream_tmp) = buffer_and_addr_stream_tmp;
+                    stream = stream_tmp.into_future();
+                    timeout = timeout_tmp;
+
+                    let (buffer, _addr) = buffer_and_addr
+                        .expect("no msg received")
+                        .expect("error receiving msg")
+                        .unwrap();
+                    println!("client got data!");
+
+                    assert_eq!(&buffer, test_bytes);
+                    successes += 1;
+                }
+                Either::Right(((), buffer_and_addr_stream_tmp)) => {
+                    stream = buffer_and_addr_stream_tmp;
+                    timeout = future::lazy(|_| tokio::time::delay_for(Duration::from_millis(100)))
+                        .flatten()
+                        .boxed();
+                }
+            }
+        }
+
+        client_done.store(true, std::sync::atomic::Ordering::Relaxed);
+        println!("successes: {}", successes);
+        assert!(successes >= 1);
+        server_handle.join().expect("server thread failed");
+    }
+
+    // FIXME: reenable after breakage in async/await
+    #[ignore]
+    #[test]
+    fn test_passive_mdns() {
+        passive_mdns_test(
+            MdnsQueryType::Passive,
+            SocketAddr::new(*TEST_MDNS_IPV4, BASE_TEST_PORT + 3),
+        )
+    }
+
+    // FIXME: reenable after breakage in async/await
+    #[ignore]
+    #[test]
+    fn test_oneshot_join_mdns() {
+        passive_mdns_test(
+            MdnsQueryType::OneShotJoin,
+            SocketAddr::new(*TEST_MDNS_IPV4, BASE_TEST_PORT + 4),
+        )
+    }
+
+    //   as there are probably unexpected responses coming on the standard addresses
+    fn passive_mdns_test(mdns_query_type: MdnsQueryType, mdns_addr: SocketAddr) {
+        use std::time::Duration;
+
+        let server_got_packet = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false));
+
+        let test_bytes: &'static [u8; 8] = b"DEADBEEF";
+        let send_recv_times = 10;
+        let server_got_packet_clone = server_got_packet.clone();
+
+        // an in and out server
+        let _server_handle = std::thread::Builder::new()
+            .name("test_one_shot_mdns:server".to_string())
+            .spawn(move || {
+                let mut io_loop = runtime::Runtime::new().unwrap();
+                let mut timeout =
+                    future::lazy(|_| tokio::time::delay_for(Duration::from_millis(100)))
+                        .flatten()
+                        .boxed();
+
+                // TTLs are 0 so that multicast test packets never leave the test host...
+                // FIXME: this is hardcoded to index 5 for ipv6, which isn't going to be correct in most cases...
+                let (server_stream_future, _server_sender) =
+                    MdnsStream::new(mdns_addr, mdns_query_type, Some(1), None, Some(5));
+
+                // For one-shot responses we are competing with a system mDNS responder, we will respond from a different port...
+                let mut server_stream = io_loop
+                    .block_on(server_stream_future)
+                    .expect("could not create mDNS listener")
+                    .into_future();
+
+                for _ in 0..=send_recv_times {
+                    // wait for some bytes...
+                    match io_loop.block_on(
+                        future::lazy(|_| future::select(server_stream, timeout)).flatten(),
+                    ) {
+                        Either::Left((_buffer_and_addr_stream_tmp, _timeout_tmp)) => {
+                            // let (buffer_and_addr, stream_tmp) = buffer_and_addr_stream_tmp;
+
+                            // server_stream = stream_tmp.into_future();
+                            // timeout = timeout_tmp;
+                            // let (buffer, addr) = buffer_and_addr.expect("no buffer received");
+
+                            // assert_eq!(&buffer, test_bytes);
+                            // println!("server got data! {}", addr);
+
+                            server_got_packet_clone
+                                .store(true, std::sync::atomic::Ordering::Relaxed);
+                            return;
+                        }
+                        Either::Right(((), buffer_and_addr_stream_tmp)) => {
+                            server_stream = buffer_and_addr_stream_tmp;
+                            timeout = future::lazy(|_| {
+                                tokio::time::delay_for(Duration::from_millis(100))
+                            })
+                            .flatten()
+                            .boxed();
+                        }
+                    }
+
+                    // let the server turn for a bit... send the message
+                    io_loop.block_on(tokio::time::delay_for(Duration::from_millis(100)));
+                }
+            })
+            .unwrap();
+
+        // setup the client, which is going to run on the testing thread...
+        let mut io_loop = runtime::Runtime::new().unwrap();
+        // FIXME: this is hardcoded to index 5 for ipv6, which isn't going to be correct in most cases...
+        let (stream, sender) =
+            MdnsStream::new(mdns_addr, MdnsQueryType::OneShot, Some(1), None, Some(5));
+        let mut stream = io_loop.block_on(stream).ok().unwrap().into_future();
+        let mut timeout = future::lazy(|_| tokio::time::delay_for(Duration::from_millis(100)))
+            .flatten()
+            .boxed();
+
+        for _ in 0..send_recv_times {
+            // test once
+            sender
+                .unbounded_send(SerialMessage::new(test_bytes.to_vec(), mdns_addr))
+                .unwrap();
+
+            println!("client sending data!");
+
+            // TODO: this lazy is probably unnecessary?
+            let run_result =
+                io_loop.block_on(future::lazy(|_| future::select(stream, timeout)).flatten());
+
+            if server_got_packet.load(std::sync::atomic::Ordering::Relaxed) {
+                return;
+            }
+
+            match run_result {
+                Either::Left((buffer_and_addr_stream_tmp, timeout_tmp)) => {
+                    let (_buffer_and_addr, stream_tmp) = buffer_and_addr_stream_tmp;
+                    stream = stream_tmp.into_future();
+                    timeout = timeout_tmp;
+                }
+                Either::Right(((), buffer_and_addr_stream_tmp)) => {
+                    stream = buffer_and_addr_stream_tmp;
+                    timeout = future::lazy(|_| tokio::time::delay_for(Duration::from_millis(100)))
+                        .flatten()
+                        .boxed();
+                }
+            }
+        }
+
+        panic!("server never got packet.");
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/multicast/mod.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/multicast/mod.rs
new file mode 100644
index 0000000..6a188b5
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/multicast/mod.rs
@@ -0,0 +1,68 @@
+// Copyright 2015-2018 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! Multicast protocol related components for DNS
+
+mod mdns_client_stream;
+mod mdns_stream;
+
+pub use self::mdns_client_stream::{MdnsClientConnect, MdnsClientStream};
+pub use self::mdns_stream::{MdnsStream, MDNS_IPV4, MDNS_IPV6};
+
+/// See [rfc6762](https://tools.ietf.org/html/rfc6762#section-5) details on these different types.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum MdnsQueryType {
+    /// The querier using this socket will only perform standard DNS queries over multicast. (clients only)
+    ///
+    /// Effectively treats mDNS as essentially no different than any other DNS query; one request followed by one response.
+    ///   Only one UDP socket will be created.
+    OneShot,
+    /// The querier is fully compliant with [rfc6762](https://tools.ietf.org/html/rfc6762#section-5). (servers, clients)
+    ///
+    /// mDNS capable clients will sent messages with many queries, and they will expect many responses. Two UDP sockets will be
+    ///   created, one for receiving multicast traffic, the other used for sending queries and direct responses. This requires
+    ///   port 5353 to be available on the system (many modern OSes already have mDNSResponders running taking this port).
+    Continuous,
+    /// The querier operates under the OneShot semantics, but also joins the multicast group. (non-compliant servers, clients)
+    ///
+    /// This is not defined in the mDNS RFC, but allows for a multicast client to join the group, receiving all multicast network
+    ///   traffic. This is useful where listening for all mDNS traffic is of interest, but because another mDNS process may have
+    ///   already taken the known port, 5353. Query responses will come from and to the standard UDP socket with a random port,
+    ///   multicast traffic will come from the multicast socket. This will create two sockets.
+    OneShotJoin,
+    /// The querier operates under the OneShot semantics, but also joins the multicast group. (servers)
+    ///
+    /// Not defined in the RFC, allows for a passive listener to receive all mDNS traffic.
+    Passive,
+}
+
+impl MdnsQueryType {
+    /// This will be sending packets, i.e. a standard UDP socket will be created
+    pub fn sender(self) -> bool {
+        match self {
+            MdnsQueryType::Passive => false,
+            MdnsQueryType::OneShot | MdnsQueryType::OneShotJoin => true,
+            MdnsQueryType::Continuous => true,
+        }
+    }
+
+    /// Returns true if this process can bind to *:5353
+    pub fn bind_on_5353(self) -> bool {
+        match self {
+            MdnsQueryType::OneShot | MdnsQueryType::OneShotJoin | MdnsQueryType::Passive => false,
+            MdnsQueryType::Continuous => true,
+        }
+    }
+
+    /// Returns true if this mDNS client should join, listen, on the multicast address
+    pub fn join_multicast(self) -> bool {
+        match self {
+            MdnsQueryType::OneShot => false,
+            MdnsQueryType::Continuous | MdnsQueryType::OneShotJoin | MdnsQueryType::Passive => true,
+        }
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/op/edns.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/op/edns.rs
new file mode 100644
index 0000000..bae7e9f
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/op/edns.rs
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! Extended DNS options
+
+use crate::error::*;
+use crate::rr::rdata::opt::{self, EdnsCode, EdnsOption};
+use crate::rr::rdata::OPT;
+use crate::rr::{DNSClass, Name, RData, Record, RecordType};
+
+use crate::serialize::binary::{BinEncodable, BinEncoder};
+
+/// Edns implements the higher level concepts for working with extended dns as it is used to create or be
+/// created from OPT record data.
+#[derive(Debug, PartialEq, Clone)]
+pub struct Edns {
+    // high 8 bits that make up the 12 bit total field when included with the 4bit rcode from the
+    //  header (from TTL)
+    rcode_high: u8,
+    // Indicates the implementation level of the setter. (from TTL)
+    version: u8,
+    // Is DNSSec supported (from TTL)
+    dnssec_ok: bool,
+    // max payload size, minimum of 512, (from RR CLASS)
+    max_payload: u16,
+
+    options: OPT,
+}
+
+impl Default for Edns {
+    fn default() -> Self {
+        Edns {
+            rcode_high: 0,
+            version: 0,
+            dnssec_ok: false,
+            max_payload: 512,
+            options: OPT::default(),
+        }
+    }
+}
+
+impl Edns {
+    /// Creates a new extended DNS object.
+    pub fn new() -> Self {
+        Default::default()
+    }
+
+    /// The high order bytes for the response code in the DNS Message
+    pub fn rcode_high(&self) -> u8 {
+        self.rcode_high
+    }
+
+    /// Returns the EDNS version
+    pub fn version(&self) -> u8 {
+        self.version
+    }
+
+    /// Specifies that DNSSec is supported for this Client or Server
+    pub fn dnssec_ok(&self) -> bool {
+        self.dnssec_ok
+    }
+
+    /// Maximum supported size of the DNS payload
+    pub fn max_payload(&self) -> u16 {
+        self.max_payload
+    }
+
+    /// Returns the Option associated with the code
+    pub fn option(&self, code: EdnsCode) -> Option<&EdnsOption> {
+        self.options.get(code)
+    }
+
+    /// Returns the options portion of EDNS
+    pub fn options(&self) -> &OPT {
+        &self.options
+    }
+
+    /// Set the high order bits for the result code.
+    pub fn set_rcode_high(&mut self, rcode_high: u8) {
+        self.rcode_high = rcode_high
+    }
+
+    /// Set the EDNS version
+    pub fn set_version(&mut self, version: u8) {
+        self.version = version
+    }
+
+    /// Set to true if DNSSec is supported
+    pub fn set_dnssec_ok(&mut self, dnssec_ok: bool) {
+        self.dnssec_ok = dnssec_ok
+    }
+
+    /// Set the maximum payload which can be supported
+    /// From RFC 6891: `Values lower than 512 MUST be treated as equal to 512`
+    pub fn set_max_payload(&mut self, max_payload: u16) {
+        self.max_payload = max_payload.max(512);
+    }
+
+    /// Set the specified EDNS option
+    pub fn set_option(&mut self, option: EdnsOption) {
+        self.options.insert(option);
+    }
+}
+
+impl<'a> From<&'a Record> for Edns {
+    fn from(value: &'a Record) -> Self {
+        assert!(value.rr_type() == RecordType::OPT);
+
+        let rcode_high: u8 = ((value.ttl() & 0xFF00_0000u32) >> 24) as u8;
+        let version: u8 = ((value.ttl() & 0x00FF_0000u32) >> 16) as u8;
+        let dnssec_ok: bool = value.ttl() & 0x0000_8000 == 0x0000_8000;
+        let max_payload: u16 = u16::from(value.dns_class());
+
+        let options: OPT = match *value.rdata() {
+            RData::NULL(..) => {
+                // NULL, there was no data in the OPT
+                OPT::default()
+            }
+            RData::OPT(ref option_data) => {
+                option_data.clone() // TODO: Edns should just refer to this, have the same lifetime as the Record
+            }
+            _ => {
+                // this should be a coding error, as opposed to a parsing error.
+                panic!("rr_type doesn't match the RData: {:?}", value.rdata()) // valid panic, never should happen
+            }
+        };
+
+        Edns {
+            rcode_high,
+            version,
+            dnssec_ok,
+            max_payload,
+            options,
+        }
+    }
+}
+
+impl<'a> From<&'a Edns> for Record {
+    /// This returns a Resource Record that is formatted for Edns(0).
+    /// Note: the rcode_high value is only part of the rcode, the rest is part of the base
+    fn from(value: &'a Edns) -> Record {
+        let mut record: Record = Record::new();
+
+        record.set_name(Name::root());
+        record.set_rr_type(RecordType::OPT);
+        record.set_dns_class(DNSClass::for_opt(value.max_payload()));
+
+        // rebuild the TTL field
+        let mut ttl: u32 = u32::from(value.rcode_high()) << 24;
+        ttl |= u32::from(value.version()) << 16;
+
+        if value.dnssec_ok() {
+            ttl |= 0x0000_8000;
+        }
+        record.set_ttl(ttl);
+
+        // now for each option, write out the option array
+        //  also, since this is a hash, there is no guarantee that ordering will be preserved from
+        //  the original binary format.
+        // maybe switch to: https://crates.io/crates/linked-hash-map/
+        record.set_rdata(RData::OPT(value.options().clone()));
+
+        record
+    }
+}
+
+impl BinEncodable for Edns {
+    fn emit(&self, encoder: &mut BinEncoder) -> ProtoResult<()> {
+        encoder.emit(0)?; // Name::root
+        RecordType::OPT.emit(encoder)?; //self.rr_type.emit(encoder)?;
+        DNSClass::for_opt(self.max_payload()).emit(encoder)?; // self.dns_class.emit(encoder)?;
+
+        // rebuild the TTL field
+        let mut ttl: u32 = u32::from(self.rcode_high()) << 24;
+        ttl |= u32::from(self.version()) << 16;
+
+        if self.dnssec_ok() {
+            ttl |= 0x0000_8000;
+        }
+
+        encoder.emit_u32(ttl)?;
+
+        // write the opts as rdata...
+        let place = encoder.place::<u16>()?;
+        opt::emit(encoder, &self.options)?;
+        let len = encoder.len_since_place(&place);
+        assert!(len <= u16::max_value() as usize);
+
+        place.replace(encoder, len as u16)?;
+        Ok(())
+    }
+}
+
+#[cfg(feature = "dnssec")]
+#[test]
+fn test_encode_decode() {
+    use crate::rr::dnssec::SupportedAlgorithms;
+
+    let mut edns: Edns = Edns::new();
+
+    edns.set_dnssec_ok(true);
+    edns.set_max_payload(0x8008);
+    edns.set_version(0x40);
+    edns.set_rcode_high(0x01);
+    edns.set_option(EdnsOption::DAU(SupportedAlgorithms::all()));
+
+    let record: Record = (&edns).into();
+    let edns_decode: Edns = (&record).into();
+
+    assert_eq!(edns.dnssec_ok(), edns_decode.dnssec_ok());
+    assert_eq!(edns.max_payload(), edns_decode.max_payload());
+    assert_eq!(edns.version(), edns_decode.version());
+    assert_eq!(edns.rcode_high(), edns_decode.rcode_high());
+    assert_eq!(edns.options(), edns_decode.options());
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/op/header.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/op/header.rs
new file mode 100644
index 0000000..7bacced
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/op/header.rs
@@ -0,0 +1,542 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! Message metadata
+
+use std::convert::From;
+
+use super::op_code::OpCode;
+use super::response_code::ResponseCode;
+use crate::error::*;
+use crate::serialize::binary::*;
+
+/// Metadata for the `Message` struct.
+///
+/// [RFC 1035, DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION, November 1987](https://tools.ietf.org/html/rfc1035)
+///
+/// ```text
+/// 4.1.1. Header section format
+///
+/// The header contains the following fields
+///
+///                                    1  1  1  1  1  1
+///      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///     |                      ID                       |
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///     |QR|   Opcode  |AA|TC|RD|RA|ZZ|AD|CD|   RCODE   |  /// AD and CD from RFC4035
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///     |                    QDCOUNT / ZCOUNT           |
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///     |                    ANCOUNT / PRCOUNT          |
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///     |                    NSCOUNT / UPCOUNT          |
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///     |                    ARCOUNT / ADCOUNT          |
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///
+/// where
+///
+/// Z               Reserved for future use.  Must be zero in all queries
+///                 and responses.
+///
+/// ```
+///
+#[derive(Clone, Debug, PartialEq, PartialOrd)]
+pub struct Header {
+    id: u16,
+    message_type: MessageType,
+    op_code: OpCode,
+    authoritative: bool,
+    truncation: bool,
+    recursion_desired: bool,
+    recursion_available: bool,
+    authentic_data: bool,
+    checking_disabled: bool,
+    response_code: u8, /* ideally u4 */
+    query_count: u16,
+    answer_count: u16,
+    name_server_count: u16,
+    additional_count: u16,
+}
+
+/// Message types are either Query (also Update) or Response
+#[derive(Debug, PartialEq, PartialOrd, Copy, Clone)]
+pub enum MessageType {
+    /// Queries are Client requests, these are either Queries or Updates
+    Query,
+    /// Response message from the Server or upstream Resolver
+    Response,
+}
+
+impl Default for Header {
+    fn default() -> Self {
+        Header {
+            id: 0,
+            message_type: MessageType::Query,
+            op_code: OpCode::Query,
+            authoritative: false,
+            truncation: false,
+            recursion_desired: false,
+            recursion_available: false,
+            authentic_data: false,
+            checking_disabled: false,
+            response_code: 0,
+            query_count: 0,
+            answer_count: 0,
+            name_server_count: 0,
+            additional_count: 0,
+        }
+    }
+}
+
+impl Header {
+    // TODO: we should make id, message_type and op_code all required and non-editable
+    /// A default Header, not very useful.
+    pub fn new() -> Self {
+        Default::default()
+    }
+
+    /// Length of the header, always 12 bytes
+    #[inline(always)]
+    pub fn len() -> usize {
+        12 /* this is always 12 bytes */
+    }
+
+    /// Sets the id of the message, for queries this should be random.
+    pub fn set_id(&mut self, id: u16) -> &mut Self {
+        self.id = id;
+        self
+    }
+
+    /// Sets the message type, Queries and Updates both use Query.
+    pub fn set_message_type(&mut self, message_type: MessageType) -> &mut Self {
+        self.message_type = message_type;
+        self
+    }
+
+    /// Set the operation code for the message
+    pub fn set_op_code(&mut self, op_code: OpCode) -> &mut Self {
+        self.op_code = op_code;
+        self
+    }
+
+    /// From the server is specifies that it is an authoritative response.
+    pub fn set_authoritative(&mut self, authoritative: bool) -> &mut Self {
+        self.authoritative = authoritative;
+        self
+    }
+
+    /// Specifies that the records were too large for the payload.
+    ///
+    /// See EDNS or TCP for resolutions to truncation.
+    pub fn set_truncated(&mut self, truncated: bool) -> &mut Self {
+        self.truncation = truncated;
+        self
+    }
+
+    /// Specify that the resolver should recursively request data from upstream DNS nodes
+    pub fn set_recursion_desired(&mut self, recursion_desired: bool) -> &mut Self {
+        self.recursion_desired = recursion_desired;
+        self
+    }
+
+    /// Specifies that recursion is available from this or the remote resolver
+    pub fn set_recursion_available(&mut self, recursion_available: bool) -> &mut Self {
+        self.recursion_available = recursion_available;
+        self
+    }
+
+    /// Specifies that the data is authentic, i.e. the resolver believes all data to be valid through DNSSec
+    pub fn set_authentic_data(&mut self, authentic_data: bool) -> &mut Self {
+        self.authentic_data = authentic_data;
+        self
+    }
+
+    /// Used during recursive resolution to specified if a resolver should or should not validate DNSSec signatures
+    pub fn set_checking_disabled(&mut self, checking_disabled: bool) -> &mut Self {
+        self.checking_disabled = checking_disabled;
+        self
+    }
+
+    /// The low response code (original response codes before EDNS extensions)
+    pub fn set_response_code(&mut self, response_code: ResponseCode) -> &mut Self {
+        self.response_code = response_code.low();
+        self
+    }
+
+    /// Number or query records in the message
+    pub fn set_query_count(&mut self, query_count: u16) -> &mut Self {
+        self.query_count = query_count;
+        self
+    }
+
+    /// Number of answer records in the message
+    pub fn set_answer_count(&mut self, answer_count: u16) -> &mut Self {
+        self.answer_count = answer_count;
+        self
+    }
+
+    /// Number of name server records in the message
+    pub fn set_name_server_count(&mut self, name_server_count: u16) -> &mut Self {
+        self.name_server_count = name_server_count;
+        self
+    }
+
+    /// Number of additional records in the message
+    pub fn set_additional_count(&mut self, additional_count: u16) -> &mut Self {
+        self.additional_count = additional_count;
+        self
+    }
+
+    /// ```text
+    /// ID              A 16 bit identifier assigned by the program that
+    ///                 generates any kind of query.  This identifier is copied
+    ///                 the corresponding reply and can be used by the requester
+    ///                 to match up replies to outstanding queries.
+    /// ```
+    pub fn id(&self) -> u16 {
+        self.id
+    }
+
+    /// ```text
+    /// QR              A one bit field that specifies whether this message is a
+    ///                 query (0), or a response (1).
+    /// ```
+    pub fn message_type(&self) -> MessageType {
+        self.message_type
+    }
+
+    /// ```text
+    /// OPCODE          A four bit field that specifies kind of query in this
+    ///                 message.  This value is set by the originator of a query
+    ///                 and copied into the response.  The values are: <see super::op_code>
+    /// ```
+    pub fn op_code(&self) -> OpCode {
+        self.op_code
+    }
+
+    /// ```text
+    /// AA              Authoritative Answer - this bit is valid in responses,
+    ///                 and specifies that the responding name server is an
+    ///                 authority for the domain name in question section.
+    ///
+    ///                 Note that the contents of the answer section may have
+    ///                 multiple owner names because of aliases.  The AA bit
+    ///                 corresponds to the name which matches the query name, or
+    ///                 the first owner name in the answer section.
+    /// ```
+    pub fn authoritative(&self) -> bool {
+        self.authoritative
+    }
+
+    /// ```text
+    /// TC              TrunCation - specifies that this message was truncated
+    ///                 due to length greater than that permitted on the
+    ///                 transmission channel.
+    /// ```
+    pub fn truncated(&self) -> bool {
+        self.truncation
+    }
+
+    /// ```text
+    /// RD              Recursion Desired - this bit may be set in a query and
+    ///                 is copied into the response.  If RD is set, it directs
+    ///                 the name server to pursue the query recursively.
+    ///                 Recursive query support is optional.
+    /// ```
+    pub fn recursion_desired(&self) -> bool {
+        self.recursion_desired
+    }
+
+    /// ```text
+    /// RA              Recursion Available - this be is set or cleared in a
+    ///                 response, and denotes whether recursive query support is
+    ///                 available in the name server.
+    /// ```
+    pub fn recursion_available(&self) -> bool {
+        self.recursion_available
+    }
+
+    /// [RFC 4035, DNSSEC Resource Records, March 2005](https://tools.ietf.org/html/rfc4035#section-3.1.6)
+    ///
+    /// ```text
+    ///
+    /// 3.1.6.  The AD and CD Bits in an Authoritative Response
+    ///
+    ///   The CD and AD bits are designed for use in communication between
+    ///   security-aware resolvers and security-aware recursive name servers.
+    ///   These bits are for the most part not relevant to query processing by
+    ///   security-aware authoritative name servers.
+    ///
+    ///   A security-aware name server does not perform signature validation
+    ///   for authoritative data during query processing, even when the CD bit
+    ///   is clear.  A security-aware name server SHOULD clear the CD bit when
+    ///   composing an authoritative response.
+    ///
+    ///   A security-aware name server MUST NOT set the AD bit in a response
+    ///   unless the name server considers all RRsets in the Answer and
+    ///   Authority sections of the response to be authentic.  A security-aware
+    ///   name server's local policy MAY consider data from an authoritative
+    ///   zone to be authentic without further validation.  However, the name
+    ///   server MUST NOT do so unless the name server obtained the
+    ///   authoritative zone via secure means (such as a secure zone transfer
+    ///   mechanism) and MUST NOT do so unless this behavior has been
+    ///   configured explicitly.
+    ///
+    ///   A security-aware name server that supports recursion MUST follow the
+    ///   rules for the CD and AD bits given in Section 3.2 when generating a
+    ///   response that involves data obtained via recursion.
+    /// ```
+    pub fn authentic_data(&self) -> bool {
+        self.authentic_data
+    }
+
+    /// see `is_authentic_data()`
+    pub fn checking_disabled(&self) -> bool {
+        self.checking_disabled
+    }
+
+    /// ```text
+    /// RCODE           Response code - this 4 bit field is set as part of
+    ///                 responses.  The values have the following
+    ///                 interpretation: <see super::response_code>
+    /// ```
+    pub fn response_code(&self) -> u8 {
+        self.response_code
+    }
+
+    /// ```text
+    /// QDCOUNT         an unsigned 16 bit integer specifying the number of
+    ///                 entries in the question section.
+    /// ```
+    ///
+    /// # Return value
+    ///
+    /// If this is a query, this will return the number of queries in the query section of the
+    //   message, fo updates this represents the zone count (must be no more than 1).
+    pub fn query_count(&self) -> u16 {
+        self.query_count
+    }
+
+    /// ```text
+    /// ANCOUNT         an unsigned 16 bit integer specifying the number of
+    ///                 resource records in the answer section.
+    /// ```
+    ///
+    /// # Return value
+    ///
+    /// For query responses this is the number of records in the answer section, should be 0 for
+    ///  requests, for updates this is the count of prerequisite records.
+    pub fn answer_count(&self) -> u16 {
+        self.answer_count
+    }
+
+    /// for queries this is the nameservers which are authorities for the SOA of the Record
+    /// for updates this is the update record count
+    /// ```text
+    /// NSCOUNT         an unsigned 16 bit integer specifying the number of name
+    ///                 server resource records in the authority records
+    ///                 section.
+    /// ```
+    ///
+    /// # Return value
+    ///
+    /// For query responses this is the number of authorities, or nameservers, in the name server
+    ///  section, for updates this is the number of update records being sent.
+    pub fn name_server_count(&self) -> u16 {
+        self.name_server_count
+    }
+
+    /// ```text
+    /// ARCOUNT         an unsigned 16 bit integer specifying the number of
+    ///                 resource records in the additional records section.
+    /// ```
+    ///
+    /// # Return value
+    ///
+    /// This is the additional record section count, this section may include EDNS options.
+    pub fn additional_count(&self) -> u16 {
+        self.additional_count
+    }
+}
+
+impl BinEncodable for Header {
+    fn emit(&self, encoder: &mut BinEncoder) -> ProtoResult<()> {
+        encoder.reserve(12)?; // the 12 bytes for the following fields;
+
+        // Id
+        encoder.emit_u16(self.id)?;
+
+        // IsQuery, OpCode, Authoritative, Truncation, RecursionDesired
+        let mut q_opcd_a_t_r: u8 = if let MessageType::Response = self.message_type {
+            0x80
+        } else {
+            0x00
+        };
+        q_opcd_a_t_r |= u8::from(self.op_code) << 3;
+        q_opcd_a_t_r |= if self.authoritative { 0x4 } else { 0x0 };
+        q_opcd_a_t_r |= if self.truncation { 0x2 } else { 0x0 };
+        q_opcd_a_t_r |= if self.recursion_desired { 0x1 } else { 0x0 };
+        encoder.emit(q_opcd_a_t_r)?;
+
+        // IsRecursionAvailable, Triple 0's, ResponseCode
+        let mut r_z_ad_cd_rcod: u8 = if self.recursion_available {
+            0b1000_0000
+        } else {
+            0b0000_0000
+        };
+        r_z_ad_cd_rcod |= if self.authentic_data {
+            0b0010_0000
+        } else {
+            0b0000_0000
+        };
+        r_z_ad_cd_rcod |= if self.checking_disabled {
+            0b0001_0000
+        } else {
+            0b0000_0000
+        };
+        r_z_ad_cd_rcod |= self.response_code;
+        encoder.emit(r_z_ad_cd_rcod)?;
+
+        encoder.emit_u16(self.query_count)?;
+        encoder.emit_u16(self.answer_count)?;
+        encoder.emit_u16(self.name_server_count)?;
+        encoder.emit_u16(self.additional_count)?;
+
+        Ok(())
+    }
+}
+
+impl<'r> BinDecodable<'r> for Header {
+    fn read(decoder: &mut BinDecoder<'r>) -> ProtoResult<Self> {
+        let id = decoder.read_u16()?.unverified(/*it is valid for this to be any u16*/);
+
+        let q_opcd_a_t_r = decoder.pop()?.unverified(/*used as a bitfield, this is safe*/);
+        // if the first bit is set
+        let message_type = if (0b1000_0000 & q_opcd_a_t_r) == 0b1000_0000 {
+            MessageType::Response
+        } else {
+            MessageType::Query
+        };
+        // the 4bit opcode, masked and then shifted right 3bits for the u8...
+        let op_code: OpCode = OpCode::from_u8((0b0111_1000 & q_opcd_a_t_r) >> 3)?;
+        let authoritative = (0b0000_0100 & q_opcd_a_t_r) == 0b0000_0100;
+        let truncation = (0b0000_0010 & q_opcd_a_t_r) == 0b0000_0010;
+        let recursion_desired = (0b0000_0001 & q_opcd_a_t_r) == 0b0000_0001;
+
+        let r_z_ad_cd_rcod = decoder.pop()?.unverified(/*used as a bitfield, this is safe*/); // fail fast...
+
+        let recursion_available = (0b1000_0000 & r_z_ad_cd_rcod) == 0b1000_0000;
+        let authentic_data = (0b0010_0000 & r_z_ad_cd_rcod) == 0b0010_0000;
+        let checking_disabled = (0b0001_0000 & r_z_ad_cd_rcod) == 0b0001_0000;
+        let response_code: u8 = 0b0000_1111 & r_z_ad_cd_rcod;
+
+        // TODO: We should pass these restrictions on, they can't be trusted, but that would seriously complicate the Header type..
+        // TODO: perhaps the read methods for BinDecodable should return Restrict?
+        let query_count =
+            decoder.read_u16()?.unverified(/*this must be verified when reading queries*/);
+        let answer_count =
+            decoder.read_u16()?.unverified(/*this must be evaluated when reading records*/);
+        let name_server_count =
+            decoder.read_u16()?.unverified(/*this must be evaluated when reading records*/);
+        let additional_count =
+            decoder.read_u16()?.unverified(/*this must be evaluated when reading records*/);
+
+        // TODO: question, should this use the builder pattern instead? might be cleaner code, but
+        //  this guarantees that the Header is fully instantiated with all values...
+        Ok(Header {
+            id,
+            message_type,
+            op_code,
+            authoritative,
+            truncation,
+            recursion_desired,
+            recursion_available,
+            authentic_data,
+            checking_disabled,
+            response_code,
+            query_count,
+            answer_count,
+            name_server_count,
+            additional_count,
+        })
+    }
+}
+
+#[test]
+fn test_parse() {
+    let byte_vec = vec![
+        0x01, 0x10, 0xAA, 0x83, // 0b1010 1010 1000 0011
+        0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11,
+    ];
+
+    let mut decoder = BinDecoder::new(&byte_vec);
+
+    let expect = Header {
+        id: 0x0110,
+        message_type: MessageType::Response,
+        op_code: OpCode::Update,
+        authoritative: false,
+        truncation: true,
+        recursion_desired: false,
+        recursion_available: true,
+        authentic_data: false,
+        checking_disabled: false,
+        response_code: ResponseCode::NXDomain.low(),
+        query_count: 0x8877,
+        answer_count: 0x6655,
+        name_server_count: 0x4433,
+        additional_count: 0x2211,
+    };
+
+    let got = Header::read(&mut decoder).unwrap();
+
+    assert_eq!(got, expect);
+}
+
+#[test]
+fn test_write() {
+    let header = Header {
+        id: 0x0110,
+        message_type: MessageType::Response,
+        op_code: OpCode::Update,
+        authoritative: false,
+        truncation: true,
+        recursion_desired: false,
+        recursion_available: true,
+        authentic_data: false,
+        checking_disabled: false,
+        response_code: ResponseCode::NXDomain.low(),
+        query_count: 0x8877,
+        answer_count: 0x6655,
+        name_server_count: 0x4433,
+        additional_count: 0x2211,
+    };
+
+    let expect: Vec<u8> = vec![
+        0x01, 0x10, 0xAA, 0x83, // 0b1010 1010 1000 0011
+        0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11,
+    ];
+
+    let mut bytes = Vec::with_capacity(512);
+    {
+        let mut encoder = BinEncoder::new(&mut bytes);
+        header.emit(&mut encoder).unwrap();
+    }
+
+    assert_eq!(bytes, expect);
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/op/message.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/op/message.rs
new file mode 100644
index 0000000..6e5f234
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/op/message.rs
@@ -0,0 +1,934 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! Basic protocol message for DNS
+
+use std::iter;
+use std::mem;
+use std::ops::Deref;
+use std::sync::Arc;
+
+use log::debug;
+
+use super::{Edns, Header, MessageType, OpCode, Query, ResponseCode};
+use crate::error::*;
+use crate::rr::{Record, RecordType};
+use crate::serialize::binary::{BinDecodable, BinDecoder, BinEncodable, BinEncoder, EncodeMode};
+
+#[cfg(feature = "dnssec")]
+use crate::rr::dnssec::rdata::DNSSECRecordType;
+
+/// The basic request and response datastructure, used for all DNS protocols.
+///
+/// [RFC 1035, DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION, November 1987](https://tools.ietf.org/html/rfc1035)
+///
+/// ```text
+/// 4.1. Format
+///
+/// All communications inside of the domain protocol are carried in a single
+/// format called a message.  The top level format of message is divided
+/// into 5 sections (some of which are empty in certain cases) shown below:
+///
+///     +--------------------------+
+///     |        Header            |
+///     +--------------------------+
+///     |  Question / Zone         | the question for the name server
+///     +--------------------------+
+///     |   Answer  / Prerequisite | RRs answering the question
+///     +--------------------------+
+///     | Authority / Update       | RRs pointing toward an authority
+///     +--------------------------+
+///     |      Additional          | RRs holding additional information
+///     +--------------------------+
+///
+/// The header section is always present.  The header includes fields that
+/// specify which of the remaining sections are present, and also specify
+/// whether the message is a query or a response, a standard query or some
+/// other opcode, etc.
+///
+/// The names of the sections after the header are derived from their use in
+/// standard queries.  The question section contains fields that describe a
+/// question to a name server.  These fields are a query type (QTYPE), a
+/// query class (QCLASS), and a query domain name (QNAME).  The last three
+/// sections have the same format: a possibly empty list of concatenated
+/// resource records (RRs).  The answer section contains RRs that answer the
+/// question; the authority section contains RRs that point toward an
+/// authoritative name server; the additional records section contains RRs
+/// which relate to the query, but are not strictly answers for the
+/// question.
+/// ```
+///
+/// By default Message is a Query. Use the Message::as_update() to create and update, or
+///  Message::new_update()
+#[derive(Clone, Debug, PartialEq, Default)]
+pub struct Message {
+    header: Header,
+    queries: Vec<Query>,
+    answers: Vec<Record>,
+    name_servers: Vec<Record>,
+    additionals: Vec<Record>,
+    sig0: Vec<Record>,
+    edns: Option<Edns>,
+}
+
+/// Returns a new Header with accurate counts for each Message section
+pub fn update_header_counts(
+    current_header: &Header,
+    is_truncated: bool,
+    counts: HeaderCounts,
+) -> Header {
+    assert!(counts.query_count <= u16::max_value() as usize);
+    assert!(counts.answer_count <= u16::max_value() as usize);
+    assert!(counts.nameserver_count <= u16::max_value() as usize);
+    assert!(counts.additional_count <= u16::max_value() as usize);
+
+    let mut header = current_header.clone();
+    header.set_query_count(counts.query_count as u16);
+    header.set_answer_count(counts.answer_count as u16);
+    header.set_name_server_count(counts.nameserver_count as u16);
+    header.set_additional_count(counts.additional_count as u16);
+    header.set_truncated(is_truncated);
+
+    header
+}
+
+/// Tracks the counts of the records in the Message.
+///
+/// This is only used internally during serialization.
+pub struct HeaderCounts {
+    /// The number of queries in the Message
+    pub query_count: usize,
+    /// The number of answers in the Message
+    pub answer_count: usize,
+    /// The number of nameservers or authorities in the Message
+    pub nameserver_count: usize,
+    /// The number of additional records in the Message
+    pub additional_count: usize,
+}
+
+impl Message {
+    /// Returns a new "empty" Message
+    pub fn new() -> Self {
+        Message {
+            header: Header::new(),
+            queries: Vec::new(),
+            answers: Vec::new(),
+            name_servers: Vec::new(),
+            additionals: Vec::new(),
+            sig0: Vec::new(),
+            edns: None,
+        }
+    }
+
+    /// Returns a Message constructed with error details to return to a client
+    ///
+    /// # Arguments
+    ///
+    /// * `id` - message id should match the request message id
+    /// * `op_code` - operation of the request
+    /// * `response_code` - the error code for the response
+    pub fn error_msg(id: u16, op_code: OpCode, response_code: ResponseCode) -> Message {
+        let mut message: Message = Message::new();
+        message.set_message_type(MessageType::Response);
+        message.set_id(id);
+        message.set_response_code(response_code);
+        message.set_op_code(op_code);
+
+        message
+    }
+
+    /// Truncates a Message, this blindly removes all response fields and sets truncated to `true`
+    pub fn truncate(&self) -> Self {
+        let mut truncated: Message = Message::new();
+        truncated.set_id(self.id());
+        truncated.set_message_type(self.message_type());
+        truncated.set_op_code(self.op_code());
+        truncated.set_authoritative(self.authoritative());
+        truncated.set_truncated(true);
+        truncated.set_recursion_desired(self.recursion_desired());
+        truncated.set_recursion_available(self.recursion_available());
+        truncated.set_response_code(self.response_code());
+        if self.edns().is_some() {
+            truncated.set_edns(self.edns().unwrap().clone());
+        }
+
+        // TODO, perhaps just quickly add a few response records here? that we know would fit?
+        truncated
+    }
+
+    /// see `Header::set_id`
+    pub fn set_id(&mut self, id: u16) -> &mut Self {
+        self.header.set_id(id);
+        self
+    }
+
+    /// see `Header::set_message_type`
+    pub fn set_message_type(&mut self, message_type: MessageType) -> &mut Self {
+        self.header.set_message_type(message_type);
+        self
+    }
+
+    /// see `Header::set_op_code`
+    pub fn set_op_code(&mut self, op_code: OpCode) -> &mut Self {
+        self.header.set_op_code(op_code);
+        self
+    }
+
+    /// see `Header::set_authoritative`
+    pub fn set_authoritative(&mut self, authoritative: bool) -> &mut Self {
+        self.header.set_authoritative(authoritative);
+        self
+    }
+
+    /// see `Header::set_truncated`
+    pub fn set_truncated(&mut self, truncated: bool) -> &mut Self {
+        self.header.set_truncated(truncated);
+        self
+    }
+
+    /// see `Header::set_recursion_desired`
+    pub fn set_recursion_desired(&mut self, recursion_desired: bool) -> &mut Self {
+        self.header.set_recursion_desired(recursion_desired);
+        self
+    }
+
+    /// see `Header::set_recursion_available`
+    pub fn set_recursion_available(&mut self, recursion_available: bool) -> &mut Self {
+        self.header.set_recursion_available(recursion_available);
+        self
+    }
+
+    /// see `Header::set_authentic_data`
+    pub fn set_authentic_data(&mut self, authentic_data: bool) -> &mut Self {
+        self.header.set_authentic_data(authentic_data);
+        self
+    }
+
+    /// see `Header::set_checking_disabled`
+    pub fn set_checking_disabled(&mut self, checking_disabled: bool) -> &mut Self {
+        self.header.set_checking_disabled(checking_disabled);
+        self
+    }
+
+    /// see `Header::set_response_code`
+    pub fn set_response_code(&mut self, response_code: ResponseCode) -> &mut Self {
+        self.header.set_response_code(response_code);
+        self
+    }
+
+    /// Add a query to the Message, either the query response from the server, or the request Query.
+    pub fn add_query(&mut self, query: Query) -> &mut Self {
+        self.queries.push(query);
+        self
+    }
+
+    /// Adds an iterator over a set of Queries to be added to the message
+    pub fn add_queries<Q, I>(&mut self, queries: Q) -> &mut Self
+    where
+        Q: IntoIterator<Item = Query, IntoIter = I>,
+        I: Iterator<Item = Query>,
+    {
+        for query in queries {
+            self.add_query(query);
+        }
+
+        self
+    }
+
+    /// Add an answer to the Message
+    pub fn add_answer(&mut self, record: Record) -> &mut Self {
+        self.answers.push(record);
+        self
+    }
+
+    /// Add all the records from the iterator to the answers section of the Message
+    pub fn add_answers<R, I>(&mut self, records: R) -> &mut Self
+    where
+        R: IntoIterator<Item = Record, IntoIter = I>,
+        I: Iterator<Item = Record>,
+    {
+        for record in records {
+            self.add_answer(record);
+        }
+
+        self
+    }
+
+    /// Sets the answers to the specified set of Records.
+    ///
+    /// # Panics
+    ///
+    /// Will panic if answer records are already associated to the message.
+    pub fn insert_answers(&mut self, records: Vec<Record>) {
+        assert!(self.answers.is_empty());
+        self.answers = records;
+    }
+
+    /// Add a name server record to the Message
+    pub fn add_name_server(&mut self, record: Record) -> &mut Self {
+        self.name_servers.push(record);
+        self
+    }
+
+    /// Add all the records in the Iterator to the name server section of the message
+    pub fn add_name_servers<R, I>(&mut self, records: R) -> &mut Self
+    where
+        R: IntoIterator<Item = Record, IntoIter = I>,
+        I: Iterator<Item = Record>,
+    {
+        for record in records {
+            self.add_name_server(record);
+        }
+
+        self
+    }
+
+    /// Sets the name_servers to the specified set of Records.
+    ///
+    /// # Panics
+    ///
+    /// Will panic if name_servers records are already associated to the message.
+    pub fn insert_name_servers(&mut self, records: Vec<Record>) {
+        assert!(self.name_servers.is_empty());
+        self.name_servers = records;
+    }
+
+    /// Add an additional Record to the message
+    pub fn add_additional(&mut self, record: Record) -> &mut Self {
+        self.additionals.push(record);
+        self
+    }
+
+    /// Sets the additional to the specified set of Records.
+    ///
+    /// # Panics
+    ///
+    /// Will panic if additional records are already associated to the message.
+    pub fn insert_additionals(&mut self, records: Vec<Record>) {
+        assert!(self.additionals.is_empty());
+        self.additionals = records;
+    }
+
+    /// Add the EDNS section to the Message
+    pub fn set_edns(&mut self, edns: Edns) -> &mut Self {
+        self.edns = Some(edns);
+        self
+    }
+
+    /// Add a SIG0 record, i.e. sign this message
+    ///
+    /// This must be don't only after all records have been associated. Generally this will be handled by the client and not need to be used directly
+    #[cfg(feature = "dnssec")]
+    pub fn add_sig0(&mut self, record: Record) -> &mut Self {
+        assert_eq!(RecordType::DNSSEC(DNSSECRecordType::SIG), record.rr_type());
+        self.sig0.push(record);
+        self
+    }
+
+    /// Gets the header of the Message
+    pub fn header(&self) -> &Header {
+        &self.header
+    }
+
+    /// see `Header::id()`
+    pub fn id(&self) -> u16 {
+        self.header.id()
+    }
+
+    /// see `Header::message_type()`
+    pub fn message_type(&self) -> MessageType {
+        self.header.message_type()
+    }
+
+    /// see `Header::op_code()`
+    pub fn op_code(&self) -> OpCode {
+        self.header.op_code()
+    }
+
+    /// see `Header::authoritative()`
+    pub fn authoritative(&self) -> bool {
+        self.header.authoritative()
+    }
+
+    /// see `Header::truncated()`
+    pub fn truncated(&self) -> bool {
+        self.header.truncated()
+    }
+
+    /// see `Header::recursion_desired()`
+    pub fn recursion_desired(&self) -> bool {
+        self.header.recursion_desired()
+    }
+
+    /// see `Header::recursion_available()`
+    pub fn recursion_available(&self) -> bool {
+        self.header.recursion_available()
+    }
+
+    /// see `Header::authentic_data()`
+    pub fn authentic_data(&self) -> bool {
+        self.header.authentic_data()
+    }
+
+    /// see `Header::checking_disabled()`
+    pub fn checking_disabled(&self) -> bool {
+        self.header.checking_disabled()
+    }
+
+    /// # Return value
+    ///
+    /// The `ResponseCode`, if this is an EDNS message then this will join the section from the OPT
+    ///  record to create the EDNS `ResponseCode`
+    pub fn response_code(&self) -> ResponseCode {
+        ResponseCode::from(
+            self.edns.as_ref().map_or(0, Edns::rcode_high),
+            self.header.response_code(),
+        )
+    }
+
+    /// ```text
+    /// Question        Carries the query name and other query parameters.
+    /// ```
+    pub fn queries(&self) -> &[Query] {
+        &self.queries
+    }
+
+    /// ```text
+    /// Answer          Carries RRs which directly answer the query.
+    /// ```
+    pub fn answers(&self) -> &[Record] {
+        &self.answers
+    }
+
+    /// Removes all the answers from the Message
+    pub fn take_answers(&mut self) -> Vec<Record> {
+        mem::replace(&mut self.answers, vec![])
+    }
+
+    /// ```text
+    /// Authority       Carries RRs which describe other authoritative servers.
+    ///                 May optionally carry the SOA RR for the authoritative
+    ///                 data in the answer section.
+    /// ```
+    pub fn name_servers(&self) -> &[Record] {
+        &self.name_servers
+    }
+
+    /// Remove the name servers from the Message
+    pub fn take_name_servers(&mut self) -> Vec<Record> {
+        mem::replace(&mut self.name_servers, vec![])
+    }
+
+    /// ```text
+    /// Additional      Carries RRs which may be helpful in using the RRs in the
+    ///                 other sections.
+    /// ```
+    pub fn additionals(&self) -> &[Record] {
+        &self.additionals
+    }
+
+    /// Remove the additional Records from the Message
+    pub fn take_additionals(&mut self) -> Vec<Record> {
+        mem::replace(&mut self.additionals, vec![])
+    }
+
+    /// [RFC 6891, EDNS(0) Extensions, April 2013](https://tools.ietf.org/html/rfc6891#section-6.1.1)
+    ///
+    /// ```text
+    /// 6.1.1.  Basic Elements
+    ///
+    ///  An OPT pseudo-RR (sometimes called a meta-RR) MAY be added to the
+    ///  additional data section of a request.
+    ///
+    ///  The OPT RR has RR type 41.
+    ///
+    ///  If an OPT record is present in a received request, compliant
+    ///  responders MUST include an OPT record in their respective responses.
+    ///
+    ///  An OPT record does not carry any DNS data.  It is used only to
+    ///  contain control information pertaining to the question-and-answer
+    ///  sequence of a specific transaction.  OPT RRs MUST NOT be cached,
+    ///  forwarded, or stored in or loaded from master files.
+    ///
+    ///  The OPT RR MAY be placed anywhere within the additional data section.
+    ///  When an OPT RR is included within any DNS message, it MUST be the
+    ///  only OPT RR in that message.  If a query message with more than one
+    ///  OPT RR is received, a FORMERR (RCODE=1) MUST be returned.  The
+    ///  placement flexibility for the OPT RR does not override the need for
+    ///  the TSIG or SIG(0) RRs to be the last in the additional section
+    ///  whenever they are present.
+    /// ```
+    /// # Return value
+    ///
+    /// Returns the EDNS record if it was found in the additional section.
+    pub fn edns(&self) -> Option<&Edns> {
+        self.edns.as_ref()
+    }
+
+    /// If edns is_none, this will create a new default Edns.
+    pub fn edns_mut(&mut self) -> &mut Edns {
+        if self.edns.is_none() {
+            self.edns = Some(Edns::new());
+        }
+
+        self.edns.as_mut().unwrap()
+    }
+
+    /// # Return value
+    ///
+    /// the max payload value as it's defined in the EDNS section.
+    pub fn max_payload(&self) -> u16 {
+        let max_size = self.edns.as_ref().map_or(512, Edns::max_payload);
+        if max_size < 512 {
+            512
+        } else {
+            max_size
+        }
+    }
+
+    /// # Return value
+    ///
+    /// the version as defined in the EDNS record
+    pub fn version(&self) -> u8 {
+        self.edns.as_ref().map_or(0, Edns::version)
+    }
+
+    /// [RFC 2535, Domain Name System Security Extensions, March 1999](https://tools.ietf.org/html/rfc2535#section-4)
+    ///
+    /// ```text
+    /// A DNS request may be optionally signed by including one or more SIGs
+    ///  at the end of the query. Such SIGs are identified by having a "type
+    ///  covered" field of zero. They sign the preceding DNS request message
+    ///  including DNS header but not including the IP header or any request
+    ///  SIGs at the end and before the request RR counts have been adjusted
+    ///  for the inclusions of any request SIG(s).
+    /// ```
+    ///
+    /// # Return value
+    ///
+    /// The sig0, i.e. signed record, for verifying the sending and package integrity
+    pub fn sig0(&self) -> &[Record] {
+        &self.sig0
+    }
+
+    // TODO: only necessary in tests, should it be removed?
+    /// this is necessary to match the counts in the header from the record sections
+    ///  this happens implicitly on write_to, so no need to call before write_to
+    #[cfg(test)]
+    pub fn update_counts(&mut self) -> &mut Self {
+        self.header = update_header_counts(
+            &self.header,
+            false,
+            HeaderCounts {
+                query_count: self.queries.len(),
+                answer_count: self.answers.len(),
+                nameserver_count: self.name_servers.len(),
+                additional_count: self.additionals.len(),
+            },
+        );
+        self
+    }
+
+    /// Attempts to read the specified number of `Query`s
+    pub fn read_queries(decoder: &mut BinDecoder, count: usize) -> ProtoResult<Vec<Query>> {
+        let mut queries = Vec::with_capacity(count);
+        for _ in 0..count {
+            queries.push(Query::read(decoder)?);
+        }
+        Ok(queries)
+    }
+
+    /// Attempts to read the specified number of records
+    ///
+    /// # Returns
+    ///
+    /// This returns a tuple of first standard Records, then a possibly associated Edns, and then finally any optionally associated SIG0 records.
+    #[cfg_attr(not(feature = "dnssec"), allow(unused_mut))]
+    pub fn read_records(
+        decoder: &mut BinDecoder,
+        count: usize,
+        is_additional: bool,
+    ) -> ProtoResult<(Vec<Record>, Option<Edns>, Vec<Record>)> {
+        let mut records: Vec<Record> = Vec::with_capacity(count);
+        let mut edns: Option<Edns> = None;
+        let mut sig0s: Vec<Record> = Vec::with_capacity(if is_additional { 1 } else { 0 });
+
+        // sig0 must be last, once this is set, disable.
+        let mut saw_sig0 = false;
+        for _ in 0..count {
+            let record = Record::read(decoder)?;
+
+            if !is_additional {
+                if saw_sig0 {
+                    return Err("sig0 must be final resource record".into());
+                } // SIG0 must be last
+                records.push(record)
+            } else {
+                match record.rr_type() {
+                    #[cfg(feature = "dnssec")]
+                    RecordType::DNSSEC(DNSSECRecordType::SIG) => {
+                        saw_sig0 = true;
+                        sig0s.push(record);
+                    }
+                    RecordType::OPT => {
+                        if saw_sig0 {
+                            return Err("sig0 must be final resource record".into());
+                        } // SIG0 must be last
+                        if edns.is_some() {
+                            return Err("more than one edns record present".into());
+                        }
+                        edns = Some((&record).into());
+                    }
+                    _ => {
+                        if saw_sig0 {
+                            return Err("sig0 must be final resource record".into());
+                        } // SIG0 must be last
+                        records.push(record);
+                    }
+                }
+            }
+        }
+
+        Ok((records, edns, sig0s))
+    }
+
+    /// Decodes a message from the buffer.
+    pub fn from_vec(buffer: &[u8]) -> ProtoResult<Message> {
+        let mut decoder = BinDecoder::new(buffer);
+        Message::read(&mut decoder)
+    }
+
+    /// Encodes the Message into a buffer
+    pub fn to_vec(&self) -> Result<Vec<u8>, ProtoError> {
+        // TODO: this feels like the right place to verify the max packet size of the message,
+        //  will need to update the header for truncation and the lengths if we send less than the
+        //  full response. This needs to conform with the EDNS settings of the server...
+        let mut buffer = Vec::with_capacity(512);
+        {
+            let mut encoder = BinEncoder::new(&mut buffer);
+            self.emit(&mut encoder)?;
+        }
+
+        Ok(buffer)
+    }
+
+    /// Finalize the message prior to sending.
+    ///
+    /// Subsequent to calling this, the Message should not change.
+    pub fn finalize<MF: MessageFinalizer>(
+        &mut self,
+        finalizer: &MF,
+        inception_time: u32,
+    ) -> ProtoResult<()> {
+        debug!("finalizing message: {:?}", self);
+        let finals: Vec<Record> = finalizer.finalize_message(self, inception_time)?;
+
+        // append all records to message
+        for fin in finals {
+            match fin.rr_type() {
+                // SIG0's are special, and come at the very end of the message
+                #[cfg(feature = "dnssec")]
+                RecordType::DNSSEC(DNSSECRecordType::SIG) => self.add_sig0(fin),
+                _ => self.add_additional(fin),
+            };
+        }
+
+        Ok(())
+    }
+}
+
+impl Deref for Message {
+    type Target = Header;
+
+    fn deref(&self) -> &Self::Target {
+        &self.header
+    }
+}
+/// A trait for performing final amendments to a Message before it is sent.
+///
+/// An example of this is a SIG0 signer, which needs the final form of the message,
+///  but then needs to attach additional data to the body of the message.
+pub trait MessageFinalizer: Send + Sync + 'static {
+    /// The message taken in should be processed and then return [`Record`]s which should be
+    ///  appended to the additional section of the message.
+    ///
+    /// # Arguments
+    ///
+    /// * `message` - message to process
+    /// * `current_time` - the current time as specified by the system, it's not recommended to read the current time as that makes testing complicated.
+    ///
+    /// # Return
+    ///
+    /// A vector to append to the additionals section of the message, sorted in the order as they should appear in the message.
+    fn finalize_message(&self, message: &Message, current_time: u32) -> ProtoResult<Vec<Record>>;
+}
+
+/// A MessageFinalizer which does nothing
+///
+/// *WARNING* This should only be used in None context, it will panic in all cases where finalize is called.
+pub struct NoopMessageFinalizer;
+
+impl NoopMessageFinalizer {
+    /// Always returns None
+    pub fn new() -> Option<Arc<Self>> {
+        None
+    }
+}
+
+impl MessageFinalizer for NoopMessageFinalizer {
+    fn finalize_message(&self, _: &Message, _: u32) -> ProtoResult<Vec<Record>> {
+        panic!("Misused NoopMessageFinalizer, None should be used instead")
+    }
+}
+
+/// Returns the count written and a boolean if it was truncated
+pub fn count_was_truncated(result: ProtoResult<usize>) -> ProtoResult<(usize, bool)> {
+    result.map(|count| (count, false)).or_else(|e| {
+        if let ProtoErrorKind::NotAllRecordsWritten { count } = e.kind() {
+            return Ok((*count, true));
+        }
+
+        Err(e)
+    })
+}
+
+/// A trait that defines types which can be emitted as a set, with the associated count returned.
+pub trait EmitAndCount {
+    /// Emit self to the encoder and return the count of items
+    fn emit(&mut self, encoder: &mut BinEncoder) -> ProtoResult<usize>;
+}
+
+impl<'e, I: Iterator<Item = &'e E>, E: 'e + BinEncodable> EmitAndCount for I {
+    fn emit(&mut self, encoder: &mut BinEncoder) -> ProtoResult<usize> {
+        encoder.emit_all(self)
+    }
+}
+
+/// Emits the different sections of a message properly
+#[allow(clippy::too_many_arguments)]
+pub fn emit_message_parts<Q, A, N, D>(
+    header: &Header,
+    queries: &mut Q,
+    answers: &mut A,
+    name_servers: &mut N,
+    additionals: &mut D,
+    edns: Option<&Edns>,
+    sig0: &[Record],
+    encoder: &mut BinEncoder,
+) -> ProtoResult<()>
+where
+    Q: EmitAndCount,
+    A: EmitAndCount,
+    N: EmitAndCount,
+    D: EmitAndCount,
+{
+    let include_sig0: bool = encoder.mode() != EncodeMode::Signing;
+    let place = encoder.place::<Header>()?;
+
+    let query_count = queries.emit(encoder)?;
+    // TODO: need to do something on max records
+    //  return offset of last emitted record.
+    let answer_count = count_was_truncated(answers.emit(encoder))?;
+    let nameserver_count = count_was_truncated(name_servers.emit(encoder))?;
+    let mut additional_count = count_was_truncated(additionals.emit(encoder))?;
+
+    if let Some(edns) = edns {
+        // need to commit the error code
+        let count = count_was_truncated(encoder.emit_all(iter::once(&Record::from(edns))))?;
+        additional_count.0 += count.0;
+        additional_count.1 |= count.1;
+    }
+
+    // this is a little hacky, but if we are Verifying a signature, i.e. the original Message
+    //  then the SIG0 records should not be encoded and the edns record (if it exists) is already
+    //  part of the additionals section.
+    if include_sig0 {
+        let count = count_was_truncated(encoder.emit_all(sig0.iter()))?;
+        additional_count.0 += count.0;
+        additional_count.1 |= count.1;
+    }
+
+    let counts = HeaderCounts {
+        query_count,
+        answer_count: answer_count.0,
+        nameserver_count: nameserver_count.0,
+        additional_count: additional_count.0,
+    };
+    let was_truncated = answer_count.1 || nameserver_count.1 || additional_count.1;
+
+    place.replace(encoder, update_header_counts(header, was_truncated, counts))?;
+    Ok(())
+}
+
+impl BinEncodable for Message {
+    fn emit(&self, encoder: &mut BinEncoder) -> ProtoResult<()> {
+        emit_message_parts(
+            &self.header,
+            &mut self.queries.iter(),
+            &mut self.answers.iter(),
+            &mut self.name_servers.iter(),
+            &mut self.additionals.iter(),
+            self.edns.as_ref(),
+            &self.sig0,
+            encoder,
+        )
+    }
+}
+
+impl<'r> BinDecodable<'r> for Message {
+    fn read(decoder: &mut BinDecoder<'r>) -> ProtoResult<Self> {
+        let header = Header::read(decoder)?;
+
+        // TODO: return just header, and in the case of the rest of message getting an error.
+        //  this could improve error detection while decoding.
+
+        // get the questions
+        let count = header.query_count() as usize;
+        let mut queries = Vec::with_capacity(count);
+        for _ in 0..count {
+            queries.push(Query::read(decoder)?);
+        }
+
+        // get all counts before header moves
+        let answer_count = header.answer_count() as usize;
+        let name_server_count = header.name_server_count() as usize;
+        let additional_count = header.additional_count() as usize;
+
+        let (answers, _, _) = Self::read_records(decoder, answer_count, false)?;
+        let (name_servers, _, _) = Self::read_records(decoder, name_server_count, false)?;
+        let (additionals, edns, sig0) = Self::read_records(decoder, additional_count, true)?;
+
+        Ok(Message {
+            header,
+            queries,
+            answers,
+            name_servers,
+            additionals,
+            sig0,
+            edns,
+        })
+    }
+}
+
+#[test]
+fn test_emit_and_read_header() {
+    let mut message = Message::new();
+    message
+        .set_id(10)
+        .set_message_type(MessageType::Response)
+        .set_op_code(OpCode::Update)
+        .set_authoritative(true)
+        .set_truncated(false)
+        .set_recursion_desired(true)
+        .set_recursion_available(true)
+        .set_response_code(ResponseCode::ServFail);
+
+    test_emit_and_read(message);
+}
+
+#[test]
+fn test_emit_and_read_query() {
+    let mut message = Message::new();
+    message
+        .set_id(10)
+        .set_message_type(MessageType::Response)
+        .set_op_code(OpCode::Update)
+        .set_authoritative(true)
+        .set_truncated(true)
+        .set_recursion_desired(true)
+        .set_recursion_available(true)
+        .set_response_code(ResponseCode::ServFail)
+        .add_query(Query::new())
+        .update_counts(); // we're not testing the query parsing, just message
+
+    test_emit_and_read(message);
+}
+
+#[test]
+fn test_emit_and_read_records() {
+    let mut message = Message::new();
+    message
+        .set_id(10)
+        .set_message_type(MessageType::Response)
+        .set_op_code(OpCode::Update)
+        .set_authoritative(true)
+        .set_truncated(true)
+        .set_recursion_desired(true)
+        .set_recursion_available(true)
+        .set_authentic_data(true)
+        .set_checking_disabled(true)
+        .set_response_code(ResponseCode::ServFail);
+
+    message.add_answer(Record::new());
+    message.add_name_server(Record::new());
+    message.add_additional(Record::new());
+    message.update_counts(); // needed for the comparison...
+
+    test_emit_and_read(message);
+}
+
+#[cfg(test)]
+fn test_emit_and_read(message: Message) {
+    let mut byte_vec: Vec<u8> = Vec::with_capacity(512);
+    {
+        let mut encoder = BinEncoder::new(&mut byte_vec);
+        message.emit(&mut encoder).unwrap();
+    }
+
+    let mut decoder = BinDecoder::new(&byte_vec);
+    let got = Message::read(&mut decoder).unwrap();
+
+    assert_eq!(got, message);
+}
+
+#[test]
+#[rustfmt::skip]
+fn test_legit_message() {
+    let buf: Vec<u8> = vec![
+  0x10,0x00,0x81,0x80, // id = 4096, response, op=query, recursion_desired, recursion_available, no_error
+  0x00,0x01,0x00,0x01, // 1 query, 1 answer,
+  0x00,0x00,0x00,0x00, // 0 namesservers, 0 additional record
+
+  0x03,b'w',b'w',b'w', // query --- www.example.com
+  0x07,b'e',b'x',b'a', //
+  b'm',b'p',b'l',b'e', //
+  0x03,b'c',b'o',b'm', //
+  0x00,                // 0 = endname
+  0x00,0x01,0x00,0x01, // ReordType = A, Class = IN
+
+  0xC0,0x0C,           // name pointer to www.example.com
+  0x00,0x01,0x00,0x01, // RecordType = A, Class = IN
+  0x00,0x00,0x00,0x02, // TTL = 2 seconds
+  0x00,0x04,           // record length = 4 (ipv4 address)
+  0x5D,0xB8,0xD8,0x22, // address = 93.184.216.34
+  ];
+
+    let mut decoder = BinDecoder::new(&buf);
+    let message = Message::read(&mut decoder).unwrap();
+
+    assert_eq!(message.id(), 4096);
+
+    let mut buf: Vec<u8> = Vec::with_capacity(512);
+    {
+        let mut encoder = BinEncoder::new(&mut buf);
+        message.emit(&mut encoder).unwrap();
+    }
+
+    let mut decoder = BinDecoder::new(&buf);
+    let message = Message::read(&mut decoder).unwrap();
+
+    assert_eq!(message.id(), 4096);
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/op/mod.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/op/mod.rs
new file mode 100644
index 0000000..064efca
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/op/mod.rs
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! Operations to send with a `Client` or server, e.g. `Query`, `Message`, or `UpdateMessage` can
+//! be used together to either query or update resource records sets.
+
+mod edns;
+pub mod header;
+pub mod message;
+pub mod op_code;
+pub mod query;
+pub mod response_code;
+
+pub use self::edns::Edns;
+pub use self::header::Header;
+pub use self::header::MessageType;
+pub use self::message::{Message, MessageFinalizer, NoopMessageFinalizer};
+pub use self::op_code::OpCode;
+pub use self::query::Query;
+pub use self::response_code::ResponseCode;
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/op/op_code.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/op/op_code.rs
new file mode 100644
index 0000000..6d538ef
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/op/op_code.rs
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! Operation code for queries, updates, and responses
+
+use std::convert::From;
+
+use crate::error::*;
+
+/// Operation code for queries, updates, and responses
+///
+/// [RFC 1035, DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION, November 1987](https://tools.ietf.org/html/rfc1035)
+///
+/// ```text
+/// OPCODE          A four bit field that specifies kind of query in this
+///                 message.  This value is set by the originator of a query
+///                 and copied into the response.  The values are:
+///
+///                 0               a standard query (QUERY)
+///
+///                 1               an inverse query (IQUERY)
+///
+///                 2               a server status request (STATUS)
+///
+///                 3-15            reserved for future use
+/// ```
+#[derive(Debug, PartialEq, PartialOrd, Copy, Clone)]
+#[allow(dead_code)]
+pub enum OpCode {
+    /// Query request [RFC 1035](https://tools.ietf.org/html/rfc1035)
+    Query,
+
+    /// Status message [RFC 1035](https://tools.ietf.org/html/rfc1035)
+    Status,
+
+    /// Notify of change [RFC 1996](https://tools.ietf.org/html/rfc1996)
+    Notify,
+
+    /// Update message [RFC 2136](https://tools.ietf.org/html/rfc2136)
+    Update,
+}
+
+/// Convert from `OpCode` to `u8`
+///
+/// ```
+/// use std::convert::From;
+/// use trust_dns_proto::op::op_code::OpCode;
+///
+/// let var: u8 = From::from(OpCode::Query);
+/// assert_eq!(0, var);
+///
+/// let var: u8 = OpCode::Query.into();
+/// assert_eq!(0, var);
+/// ```
+impl From<OpCode> for u8 {
+    fn from(rt: OpCode) -> Self {
+        match rt {
+            OpCode::Query => 0,
+            // 1	IQuery (Inverse Query, OBSOLETE)	[RFC3425]
+            OpCode::Status => 2,
+            // 3	Unassigned
+            OpCode::Notify => 4,
+            OpCode::Update => 5,
+            // 6-15	Unassigned
+        }
+    }
+}
+
+/// Convert from `u8` to `OpCode`
+///
+/// ```
+/// use std::convert::From;
+/// use trust_dns_proto::op::op_code::OpCode;
+///
+/// let var: OpCode = OpCode::from_u8(0).unwrap();
+/// assert_eq!(OpCode::Query, var);
+/// ```
+impl OpCode {
+    /// Decodes the binary value of the OpCode
+    pub fn from_u8(value: u8) -> ProtoResult<Self> {
+        match value {
+            0 => Ok(OpCode::Query),
+            2 => Ok(OpCode::Status),
+            4 => Ok(OpCode::Notify),
+            5 => Ok(OpCode::Update),
+            _ => Err(format!("unknown OpCode: {}", value).into()),
+        }
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/op/query.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/op/query.rs
new file mode 100644
index 0000000..76baad2
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/op/query.rs
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! Query struct for looking up resource records
+
+use std::fmt;
+use std::fmt::{Display, Formatter};
+
+use crate::error::*;
+use crate::rr::dns_class::DNSClass;
+use crate::rr::domain::Name;
+use crate::rr::record_type::RecordType;
+use crate::serialize::binary::*;
+
+/// Query struct for looking up resource records, basically a resource record without RDATA.
+///
+/// [RFC 1035, DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION, November 1987](https://tools.ietf.org/html/rfc1035)
+///
+/// ```text
+/// 4.1.2. Question section format
+///
+/// The question section is used to carry the "question" in most queries,
+/// i.e., the parameters that define what is being asked.  The section
+/// contains QDCOUNT (usually 1) entries, each of the following format:
+///
+///                                     1  1  1  1  1  1
+///       0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///     |                                               |
+///     /                     QNAME / ZNAME             /
+///     /                                               /
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///     |                     QTYPE / ZTYPE             |
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///     |                     QCLASS / ZCLASS           |
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///
+/// ```
+#[derive(Clone, Debug, Eq, Hash, PartialEq)]
+pub struct Query {
+    name: Name,
+    query_type: RecordType,
+    query_class: DNSClass,
+}
+
+impl Default for Query {
+    /// Return a default query with an empty name and A, IN for the query_type and query_class
+    fn default() -> Self {
+        Query {
+            name: Name::new(),
+            query_type: RecordType::A,
+            query_class: DNSClass::IN,
+        }
+    }
+}
+
+impl Query {
+    /// Return a default query with an empty name and A, IN for the query_type and query_class
+    pub fn new() -> Self {
+        Default::default()
+    }
+
+    /// Create a new query from name and type, class defaults to IN
+    pub fn query(name: Name, query_type: RecordType) -> Self {
+        Query {
+            name,
+            query_type,
+            query_class: DNSClass::IN,
+        }
+    }
+
+    /// replaces name with the new name
+    pub fn set_name(&mut self, name: Name) -> &mut Self {
+        self.name = name;
+        self
+    }
+
+    /// Specify the RecordType being queried
+    pub fn set_query_type(&mut self, query_type: RecordType) -> &mut Self {
+        self.query_type = query_type;
+        self
+    }
+
+    /// Specify÷ the DNS class of the Query, almost always IN
+    pub fn set_query_class(&mut self, query_class: DNSClass) -> &mut Self {
+        self.query_class = query_class;
+        self
+    }
+
+    /// ```text
+    /// QNAME           a domain name represented as a sequence of labels, where
+    ///                 each label consists of a length octet followed by that
+    ///                 number of octets.  The domain name terminates with the
+    ///                 zero length octet for the null label of the root.  Note
+    ///                 that this field may be an odd number of octets; no
+    ///                 padding is used.
+    /// ```
+    pub fn name(&self) -> &Name {
+        &self.name
+    }
+
+    /// ```text
+    /// QTYPE           a two octet code which specifies the type of the query.
+    ///                 The values for this field include all codes valid for a
+    ///                 TYPE field, together with some more general codes which
+    ///                 can match more than one type of RR.
+    /// ```
+    pub fn query_type(&self) -> RecordType {
+        self.query_type
+    }
+
+    /// ```text
+    /// QCLASS          a two octet code that specifies the class of the query.
+    ///                 For example, the QCLASS field is IN for the Internet.
+    /// ```
+    pub fn query_class(&self) -> DNSClass {
+        self.query_class
+    }
+}
+
+impl BinEncodable for Query {
+    fn emit(&self, encoder: &mut BinEncoder) -> ProtoResult<()> {
+        self.name.emit(encoder)?;
+        self.query_type.emit(encoder)?;
+        self.query_class.emit(encoder)?;
+
+        Ok(())
+    }
+}
+
+impl<'r> BinDecodable<'r> for Query {
+    fn read(decoder: &mut BinDecoder<'r>) -> ProtoResult<Self> {
+        let name = Name::read(decoder)?;
+        let query_type = RecordType::read(decoder)?;
+        let query_class = DNSClass::read(decoder)?;
+
+        Ok(Query {
+            name,
+            query_type,
+            query_class,
+        })
+    }
+}
+
+impl Display for Query {
+    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
+        write!(
+            f,
+            "name: {} type: {} class: {}",
+            self.name, self.query_type, self.query_class
+        )
+    }
+}
+
+#[test]
+fn test_read_and_emit() {
+    let expect = Query {
+        name: Name::from_ascii("WWW.example.com").unwrap(),
+        query_type: RecordType::AAAA,
+        query_class: DNSClass::IN,
+    };
+
+    let mut byte_vec: Vec<u8> = Vec::with_capacity(512);
+    {
+        let mut encoder = BinEncoder::new(&mut byte_vec);
+        expect.emit(&mut encoder).unwrap();
+    }
+
+    let mut decoder = BinDecoder::new(&byte_vec);
+    let got = Query::read(&mut decoder).unwrap();
+    assert_eq!(got, expect);
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/op/response_code.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/op/response_code.rs
new file mode 100644
index 0000000..dfedf35
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/op/response_code.rs
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+// there is not much to format in this file, and we don't want rustfmt to mess up the comments
+
+//! All defined response codes in DNS
+
+use std::fmt;
+use std::fmt::{Display, Formatter};
+
+/// The status code of the response to a query.
+///
+/// [RFC 1035, DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION, November 1987](https://tools.ietf.org/html/rfc1035)
+///
+/// ```text
+/// RCODE           Response code - this 4 bit field is set as part of
+///                 responses.  The values have the following
+///                 interpretation:
+///
+///                 0               No error condition
+///
+///                 1               Format error - The name server was
+///                                 unable to interpret the query.
+///
+///                 2               Server failure - The name server was
+///                                 unable to process this query due to a
+///                                 problem with the name server.
+///
+///                 3               Name Error - Meaningful only for
+///                                 responses from an authoritative name
+///                                 server, this code signifies that the
+///                                 domain name referenced in the query does
+///                                 not exist.
+///
+///                 4               Not Implemented - The name server does
+///                                 not support the requested kind of query.
+///
+///                 5               Refused - The name server refuses to
+///                                 perform the specified operation for
+///                                 policy reasons.  For example, a name
+///                                 server may not wish to provide the
+///                                 information to the particular requester,
+///                                 or a name server may not wish to perform
+///                                 a particular operation (e.g., zone
+///                                 transfer) for particular data.
+///
+///                 6-15            Reserved for future use.
+///  ```
+#[derive(Debug, Eq, PartialEq, PartialOrd, Copy, Clone)]
+#[allow(dead_code)]
+pub enum ResponseCode {
+    /// No Error [RFC 1035](https://tools.ietf.org/html/rfc1035)
+    NoError,
+
+    /// Format Error [RFC 1035](https://tools.ietf.org/html/rfc1035)
+    FormErr,
+
+    /// Server Failure [RFC 1035](https://tools.ietf.org/html/rfc1035)
+    ServFail,
+
+    /// Non-Existent Domain [RFC 1035](https://tools.ietf.org/html/rfc1035)
+    NXDomain,
+
+    /// Not Implemented [RFC 1035](https://tools.ietf.org/html/rfc1035)
+    NotImp,
+
+    /// Query Refused [RFC 1035](https://tools.ietf.org/html/rfc1035)
+    Refused,
+
+    /// Name Exists when it should not [RFC 2136](https://tools.ietf.org/html/rfc2136)
+    YXDomain,
+
+    /// RR Set Exists when it should not [RFC 2136](https://tools.ietf.org/html/rfc2136)
+    YXRRSet,
+
+    /// RR Set that should exist does not [RFC 2136](https://tools.ietf.org/html/rfc2136)
+    NXRRSet,
+
+    /// Server Not Authoritative for zone [RFC 2136](https://tools.ietf.org/html/rfc2136)
+    /// or Not Authorized [RFC 2845](https://tools.ietf.org/html/rfc2845)
+    NotAuth,
+
+    /// Name not contained in zone [RFC 2136](https://tools.ietf.org/html/rfc2136)
+    NotZone,
+
+    /// Bad OPT Version [RFC 6891](https://tools.ietf.org/html/rfc6891#section-9)
+    BADVERS,
+
+    /// TSIG Signature Failure [RFC 2845](https://tools.ietf.org/html/rfc2845)
+    BADSIG,
+
+    /// Key not recognized [RFC 2845](https://tools.ietf.org/html/rfc2845)
+    BADKEY,
+
+    /// Signature out of time window [RFC 2845](https://tools.ietf.org/html/rfc2845)
+    BADTIME,
+
+    /// Bad TKEY Mode [RFC 2930](https://tools.ietf.org/html/rfc2930#section-2.6)
+    BADMODE,
+
+    /// Duplicate key name [RFC 2930](https://tools.ietf.org/html/rfc2930#section-2.6)
+    BADNAME,
+
+    /// Algorithm not supported [RFC 2930](https://tools.ietf.org/html/rfc2930#section-2.6)
+    BADALG,
+
+    /// Bad Truncation [RFC 4635](https://tools.ietf.org/html/rfc4635#section-4)
+    BADTRUNC,
+
+    /// Bad/missing server cookie [draft-ietf-dnsop-cookies](https://tools.ietf.org/html/draft-ietf-dnsop-cookies-10)
+    BADCOOKIE,
+    // 24-3840      Unassigned
+    // 3841-4095    Reserved for Private Use                        [RFC6895]
+    // 4096-65534   Unassigned
+    // 65535        Reserved, can be allocated by Standards Action  [RFC6895]
+    /// An unknown or unregisterd response code was received.
+    Unknown(u16),
+}
+
+impl ResponseCode {
+    /// returns the lower 4 bits of the response code (for the original header portion of the code)
+    pub fn low(self) -> u8 {
+        (u16::from(self) & 0x000F) as u8
+    }
+
+    /// returns the high 12 bits for the edns portion of the response code
+    pub fn high(self) -> u16 {
+        (u16::from(self) & 0x0FF0) >> 4
+    }
+
+    /// Combines the EDNS high and low from the Header to produce the Extended ResponseCode
+    pub fn from(high: u8, low: u8) -> ResponseCode {
+        ((u16::from(high) << 4) | ((u16::from(low)) & 0x000F)).into()
+    }
+
+    /// Transforms the response code into the human message
+    pub fn to_str(self) -> &'static str {
+        match self {
+            ResponseCode::NoError => "No Error",
+            ResponseCode::FormErr => "Form Error", // 1     FormErr       Format Error                        [RFC1035]
+            ResponseCode::ServFail => "Server Failure", // 2     ServFail      Server Failure                      [RFC1035]
+            ResponseCode::NXDomain => "Non-Existent Domain", // 3     NXDomain      Non-Existent Domain                 [RFC1035]
+            ResponseCode::NotImp => "Not Implemented", // 4     NotImp        Not Implemented                     [RFC1035]
+            ResponseCode::Refused => "Query Refused", // 5     Refused       Query Refused                       [RFC1035]
+            ResponseCode::YXDomain => "Name should not exist", // 6     YXDomain      Name Exists when it should not      [RFC2136][RFC6672]
+            ResponseCode::YXRRSet => "RR Set should not exist", // 7     YXRRSet       RR Set Exists when it should not    [RFC2136]
+            ResponseCode::NXRRSet => "RR Set does not exist", // 8     NXRRSet       RR Set that should exist does not   [RFC2136]
+            ResponseCode::NotAuth => "Not authorized", // 9     NotAuth       Server Not Authoritative for zone   [RFC2136]
+            ResponseCode::NotZone => "Name not in zone", // 10    NotZone       Name not contained in zone          [RFC2136]
+            ResponseCode::BADVERS => "Bad option verions", // 16    BADVERS       Bad OPT Version                     [RFC6891]
+            ResponseCode::BADSIG => "TSIG Failure", // 16    BADSIG        TSIG Signature Failure              [RFC2845]
+            ResponseCode::BADKEY => "Key not recognized", // 17    BADKEY        Key not recognized                  [RFC2845]
+            ResponseCode::BADTIME => "Signature out of time window", // 18    BADTIME       Signature out of time window        [RFC2845]
+            ResponseCode::BADMODE => "Bad TKEY mode", // 19    BADMODE       Bad TKEY Mode                       [RFC2930]
+            ResponseCode::BADNAME => "Duplicate key name", // 20    BADNAME       Duplicate key name                  [RFC2930]
+            ResponseCode::BADALG => "Algorithm not supported", // 21    BADALG        Algorithm not supported             [RFC2930]
+            ResponseCode::BADTRUNC => "Bad truncation", // 22    BADTRUNC      Bad Truncation                      [RFC4635]
+            ResponseCode::BADCOOKIE => "Bad server cookie", // 23    BADCOOKIE (TEMPORARY - registered 2015-07-26, expires 2016-07-26)    Bad/missing server cookie    [draft-ietf-dnsop-cookies]
+            ResponseCode::Unknown(_) => "Unknown response code",
+        }
+    }
+}
+
+impl Display for ResponseCode {
+    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
+        f.write_str(self.to_str())
+    }
+}
+
+/// Convert from `ResponseCode` to `u16`
+///
+/// ```
+/// use std::convert::From;
+/// use trust_dns_proto::op::response_code::ResponseCode;
+///
+/// let var: ResponseCode = From::from(0);
+/// assert_eq!(ResponseCode::NoError, var);
+///
+/// let var: ResponseCode = 0.into();
+/// assert_eq!(ResponseCode::NoError, var);
+/// ```
+impl From<ResponseCode> for u16 {
+    fn from(rt: ResponseCode) -> Self {
+        match rt {
+            ResponseCode::NoError => 0, // 0   NoError    No Error                              [RFC1035]
+            ResponseCode::FormErr => 1, // 1   FormErr    Format Error                          [RFC1035]
+            ResponseCode::ServFail => 2, // 2   ServFail   Server Failure                        [RFC1035]
+            ResponseCode::NXDomain => 3, // 3   NXDomain   Non-Existent Domain                   [RFC1035]
+            ResponseCode::NotImp => 4, // 4   NotImp     Not Implemented                       [RFC1035]
+            ResponseCode::Refused => 5, // 5   Refused    Query Refused                         [RFC1035]
+            ResponseCode::YXDomain => 6, // 6   YXDomain   Name Exists when it should not        [RFC2136][RFC6672]
+            ResponseCode::YXRRSet => 7, // 7   YXRRSet    RR Set Exists when it should not      [RFC2136]
+            ResponseCode::NXRRSet => 8, // 8   NXRRSet    RR Set that should exist does not     [RFC2136]
+            ResponseCode::NotAuth => 9, // 9   NotAuth    Server Not Authoritative for zone     [RFC2136]
+            ResponseCode::NotZone => 10, // 10  NotZone    Name not contained in zone            [RFC2136]
+            //
+            // 11-15    Unassigned
+            //
+            // 16  BADVERS  Bad OPT Version         [RFC6891]
+            // 16  BADSIG   TSIG Signature Failure  [RFC2845]
+            ResponseCode::BADVERS | ResponseCode::BADSIG => 16,
+            ResponseCode::BADKEY => 17, // 17  BADKEY    Key not recognized                     [RFC2845]
+            ResponseCode::BADTIME => 18, // 18  BADTIME   Signature out of time window           [RFC2845]
+            ResponseCode::BADMODE => 19, // 19  BADMODE   Bad TKEY Mode                          [RFC2930]
+            ResponseCode::BADNAME => 20, // 20  BADNAME   Duplicate key name                     [RFC2930]
+            ResponseCode::BADALG => 21, // 21  BADALG    Algorithm not supported                [RFC2930]
+            ResponseCode::BADTRUNC => 22, // 22  BADTRUNC  Bad Truncation                         [RFC4635]
+            // 23  BADCOOKIE (TEMPORARY - registered 2015-07-26, expires 2016-07-26)    Bad/missing server cookie    [draft-ietf-dnsop-cookies]
+            ResponseCode::BADCOOKIE => 23,
+            ResponseCode::Unknown(code) => code,
+        }
+    }
+}
+
+/// Convert from `u16` to `ResponseCode`
+///
+/// ```
+/// use std::convert::From;
+/// use trust_dns_proto::op::response_code::ResponseCode;
+///
+/// let var: u16 = From::from(ResponseCode::NoError);
+/// assert_eq!(0, var);
+///
+/// let var: u16 = ResponseCode::NoError.into();
+/// assert_eq!(0, var);
+/// ```
+impl From<u16> for ResponseCode {
+    #[allow(clippy::unimplemented)]
+    fn from(value: u16) -> Self {
+        match value {
+            0 => ResponseCode::NoError, // 0    NoError    No Error                             [RFC1035]
+            1 => ResponseCode::FormErr, // 1    FormErr    Format Error                         [RFC1035]
+            2 => ResponseCode::ServFail, // 2    ServFail   Server Failure                       [RFC1035]
+            3 => ResponseCode::NXDomain, // 3    NXDomain   Non-Existent Domain                  [RFC1035]
+            4 => ResponseCode::NotImp, // 4    NotImp     Not Implemented                      [RFC1035]
+            5 => ResponseCode::Refused, // 5    Refused    Query Refused                        [RFC1035]
+            6 => ResponseCode::YXDomain, // 6    YXDomain   Name Exists when it should not       [RFC2136][RFC6672]
+            7 => ResponseCode::YXRRSet, // 7    YXRRSet    RR Set Exists when it should not     [RFC2136]
+            8 => ResponseCode::NXRRSet, // 8    NXRRSet    RR Set that should exist does not    [RFC2136]
+            9 => ResponseCode::NotAuth, // 9    NotAuth    Server Not Authoritative for zone    [RFC2136]
+            10 => ResponseCode::NotZone, // 10   NotZone    Name not contained in zone           [RFC2136]
+            // this looks to be backwards compat for 4 bit ResponseCodes.
+            // 16    BADVERS    Bad OPT Version    [RFC6891]
+            // 16 => ResponseCode::BADVERS,
+            16 => ResponseCode::BADSIG, // 16    BADSIG    TSIG Signature Failure               [RFC2845]
+            17 => ResponseCode::BADKEY, // 17    BADKEY    Key not recognized                   [RFC2845]
+            18 => ResponseCode::BADTIME, // 18    BADTIME   Signature out of time window         [RFC2845]
+            19 => ResponseCode::BADMODE, // 19    BADMODE   Bad TKEY Mode                        [RFC2930]
+            20 => ResponseCode::BADNAME, // 20    BADNAME   Duplicate key name                   [RFC2930]
+            21 => ResponseCode::BADALG, // 21    BADALG    Algorithm not supported              [RFC2930]
+            22 => ResponseCode::BADTRUNC, // 22    BADTRUNC  Bad Truncation                       [RFC4635]
+            23 => ResponseCode::BADCOOKIE, // 23    BADCOOKIE (TEMPORARY - registered 2015-07-26, expires 2016-07-26)    Bad/missing server cookie    [draft-ietf-dnsop-cookies]
+            code => ResponseCode::Unknown(code),
+        }
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dns_class.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dns_class.rs
new file mode 100644
index 0000000..1c689d1
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dns_class.rs
@@ -0,0 +1,187 @@
+// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! class of DNS operations, in general always IN for internet
+
+use std::cmp::Ordering;
+use std::convert::From;
+use std::fmt;
+use std::fmt::{Display, Formatter};
+use std::str::FromStr;
+
+use crate::error::*;
+use crate::serialize::binary::*;
+
+/// The DNS Record class
+#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
+#[allow(dead_code)]
+pub enum DNSClass {
+    /// Internet
+    IN,
+    /// Chaos
+    CH,
+    /// Hesiod
+    HS,
+    /// QCLASS NONE
+    NONE,
+    /// QCLASS * (ANY)
+    ANY,
+    /// Special class for OPT Version, it was overloaded for EDNS - RFC 6891
+    /// From the RFC: `Values lower than 512 MUST be treated as equal to 512`
+    OPT(u16),
+}
+
+impl FromStr for DNSClass {
+    type Err = ProtoError;
+
+    /// Convert from `&str` to `DNSClass`
+    ///
+    /// ```
+    /// use std::str::FromStr;
+    /// use trust_dns_proto::rr::dns_class::DNSClass;
+    ///
+    /// let var: DNSClass = DNSClass::from_str("IN").unwrap();
+    /// assert_eq!(DNSClass::IN, var);
+    /// ```
+    fn from_str(str: &str) -> ProtoResult<Self> {
+        match str {
+            "IN" => Ok(DNSClass::IN),
+            "CH" => Ok(DNSClass::CH),
+            "HS" => Ok(DNSClass::HS),
+            "NONE" => Ok(DNSClass::NONE),
+            "ANY" | "*" => Ok(DNSClass::ANY),
+            _ => Err(ProtoErrorKind::UnknownDnsClassStr(str.to_string()).into()),
+        }
+    }
+}
+
+impl DNSClass {
+    /// Convert from `u16` to `DNSClass`
+    ///
+    /// ```
+    /// use trust_dns_proto::rr::dns_class::DNSClass;
+    ///
+    /// let var = DNSClass::from_u16(1).unwrap();
+    /// assert_eq!(DNSClass::IN, var);
+    /// ```
+    pub fn from_u16(value: u16) -> ProtoResult<Self> {
+        match value {
+            1 => Ok(DNSClass::IN),
+            3 => Ok(DNSClass::CH),
+            4 => Ok(DNSClass::HS),
+            254 => Ok(DNSClass::NONE),
+            255 => Ok(DNSClass::ANY),
+            _ => Err(ProtoErrorKind::UnknownDnsClassValue(value).into()),
+        }
+    }
+
+    /// Return the OPT version from value
+    pub fn for_opt(value: u16) -> Self {
+        // From RFC 6891: `Values lower than 512 MUST be treated as equal to 512`
+        let value = value.max(512);
+        DNSClass::OPT(value)
+    }
+}
+
+impl BinEncodable for DNSClass {
+    fn emit(&self, encoder: &mut BinEncoder) -> ProtoResult<()> {
+        encoder.emit_u16((*self).into())
+    }
+}
+
+impl<'r> BinDecodable<'r> for DNSClass {
+    fn read(decoder: &mut BinDecoder) -> ProtoResult<Self> {
+        Self::from_u16(
+            decoder.read_u16()?.unverified(/*DNSClass is verified as safe in processing this*/),
+        )
+    }
+}
+
+// TODO make these a macro or annotation
+
+/// Convert from `DNSClass` to `&str`
+///
+/// ```
+/// use trust_dns_proto::rr::dns_class::DNSClass;
+///
+/// let var: &'static str = DNSClass::IN.into();
+/// assert_eq!("IN", var);
+/// ```
+impl From<DNSClass> for &'static str {
+    fn from(rt: DNSClass) -> &'static str {
+        match rt {
+            DNSClass::IN => "IN",
+            DNSClass::CH => "CH",
+            DNSClass::HS => "HS",
+            DNSClass::NONE => "NONE",
+            DNSClass::ANY => "ANY",
+            DNSClass::OPT(_) => "OPT",
+        }
+    }
+}
+
+/// Convert from `DNSClass` to `u16`
+///
+/// ```
+/// use trust_dns_proto::rr::dns_class::DNSClass;
+///
+/// let var: u16 = DNSClass::IN.into();
+/// assert_eq!(1, var);
+/// ```
+impl From<DNSClass> for u16 {
+    fn from(rt: DNSClass) -> Self {
+        match rt {
+            DNSClass::IN => 1,
+            DNSClass::CH => 3,
+            DNSClass::HS => 4,
+            DNSClass::NONE => 254,
+            DNSClass::ANY => 255,
+            // see https://tools.ietf.org/html/rfc6891#section-6.1.2
+            DNSClass::OPT(max_payload_len) => max_payload_len.max(512),
+        }
+    }
+}
+
+impl PartialOrd<DNSClass> for DNSClass {
+    fn partial_cmp(&self, other: &DNSClass) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl Ord for DNSClass {
+    fn cmp(&self, other: &Self) -> Ordering {
+        u16::from(*self).cmp(&u16::from(*other))
+    }
+}
+
+impl Display for DNSClass {
+    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
+        f.write_str(Into::<&str>::into(*self))
+    }
+}
+
+#[test]
+fn test_order() {
+    let ordered = vec![
+        DNSClass::IN,
+        DNSClass::CH,
+        DNSClass::HS,
+        DNSClass::NONE,
+        DNSClass::ANY,
+    ];
+    let mut unordered = vec![
+        DNSClass::NONE,
+        DNSClass::HS,
+        DNSClass::CH,
+        DNSClass::IN,
+        DNSClass::ANY,
+    ];
+
+    unordered.sort();
+
+    assert_eq!(unordered, ordered);
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/algorithm.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/algorithm.rs
new file mode 100644
index 0000000..0100a98
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/algorithm.rs
@@ -0,0 +1,247 @@
+// Copyright 2015-2019 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+use std::fmt;
+use std::fmt::{Display, Formatter};
+
+use crate::error::*;
+use crate::serialize::binary::*;
+
+/// DNSSec signing and validation algorithms.
+///
+/// For [reference](http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml)
+///  the iana documents have all the officially registered algorithms.
+///
+/// [RFC 6944](https://tools.ietf.org/html/rfc6944), DNSSEC DNSKEY Algorithm Status, April 2013
+///
+/// ```text
+///
+/// 2.2.  Algorithm Implementation Status Assignment Rationale
+///
+/// RSASHA1 has an implementation status of Must Implement, consistent
+/// with [RFC4034].  RSAMD5 has an implementation status of Must Not
+/// Implement because of known weaknesses in MD5.
+///
+/// The status of RSASHA1-NSEC3-SHA1 is set to Recommended to Implement
+/// as many deployments use NSEC3.  The status of RSA/SHA-256 and RSA/
+/// SHA-512 are also set to Recommended to Implement as major deployments
+/// (such as the root zone) use these algorithms [ROOTDPS].  It is
+/// believed that RSA/SHA-256 or RSA/SHA-512 algorithms will replace
+/// older algorithms (e.g., RSA/SHA-1) that have a perceived weakness.
+///
+/// Likewise, ECDSA with the two identified curves (ECDSAP256SHA256 and
+/// ECDSAP384SHA384) is an algorithm that may see widespread use due to
+/// the perceived similar level of security offered with smaller key size
+/// compared to the key sizes of algorithms such as RSA.  Therefore,
+/// ECDSAP256SHA256 and ECDSAP384SHA384 are Recommended to Implement.
+///
+/// All other algorithms used in DNSSEC specified without an
+/// implementation status are currently set to Optional.
+///
+/// 2.3.  DNSSEC Implementation Status Table
+///
+/// The DNSSEC algorithm implementation status table is listed below.
+/// Only the algorithms already specified for use with DNSSEC at the time
+/// of writing are listed.
+///
+///  +------------+------------+-------------------+-------------------+
+///  |    Must    |  Must Not  |    Recommended    |      Optional     |
+///  |  Implement | Implement  |   to Implement    |                   |
+///  +------------+------------+-------------------+-------------------+
+///  |            |            |                   |                   |
+///  |   RSASHA1  |   RSAMD5   |   RSASHA256       |   Any             |
+///  |            |            |   RSASHA1-NSEC3   |   registered      |
+///  |            |            |    -SHA1          |   algorithm       |
+///  |            |            |   RSASHA512       |   not listed in   |
+///  |            |            |   ECDSAP256SHA256 |   this table      |
+///  |            |            |   ECDSAP384SHA384 |                   |
+///  +------------+------------+-------------------+-------------------+
+///
+///    This table does not list the Reserved values in the IANA registry
+///    table or the values for INDIRECT (252), PRIVATE (253), and PRIVATEOID
+///    (254).  These values may relate to more than one algorithm and are
+///    therefore up to the implementer's discretion.  As noted, any
+///    algorithm not listed in the table is Optional.  As of this writing,
+///    the Optional algorithms are DSASHA1, DH, DSA-NSEC3-SHA1, and GOST-
+///    ECC, but in general, anything not explicitly listed is Optional.
+///
+/// 2.4.  Specifying New Algorithms and Updating the Status of Existing
+///       Entries
+///
+///    [RFC6014] establishes a parallel procedure for adding a registry
+///    entry for a new algorithm other than a standards track document.
+///    Because any algorithm not listed in the foregoing table is Optional,
+///    algorithms entered into the registry using the [RFC6014] procedure
+///    are automatically Optional.
+///
+///    It has turned out to be useful for implementations to refer to a
+///    single document that specifies the implementation status of every
+///    algorithm.  Accordingly, when a new algorithm is to be registered
+///    with a status other than Optional, this document shall be made
+///    obsolete by a new document that adds the new algorithm to the table
+///    in Section 2.3.  Similarly, if the status of any algorithm in the
+///    table in Section 2.3 changes, a new document shall make this document
+///    obsolete; that document shall include a replacement of the table in
+///    Section 2.3.  This way, the goal of having one authoritative document
+///    to specify all the status values is achieved.
+///
+///    This document cannot be updated, only made obsolete and replaced by a
+///    successor document.
+/// ```
+#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
+pub enum Algorithm {
+    /// DO NOT USE, SHA1 is a compromised hashing function, it is here for backward compatibility
+    RSASHA1,
+    /// DO NOT USE, SHA1 is a compromised hashing function, it is here for backward compatibility
+    RSASHA1NSEC3SHA1,
+    /// RSA public key with SHA256 hash
+    RSASHA256,
+    /// RSA public key with SHA512 hash
+    RSASHA512,
+    /// [rfc6605](https://tools.ietf.org/html/rfc6605)
+    ECDSAP256SHA256,
+    /// [rfc6605](https://tools.ietf.org/html/rfc6605)
+    ECDSAP384SHA384,
+    /// [draft-ietf-curdle-dnskey-eddsa-03](https://tools.ietf.org/html/draft-ietf-curdle-dnskey-eddsa-03)
+    ED25519,
+    /// An unknown algorithm identifier
+    Unknown(u8),
+}
+
+impl Algorithm {
+    /// http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml
+    pub fn from_u8(value: u8) -> Self {
+        match value {
+            5 => Algorithm::RSASHA1,
+            7 => Algorithm::RSASHA1NSEC3SHA1,
+            8 => Algorithm::RSASHA256,
+            10 => Algorithm::RSASHA512,
+            13 => Algorithm::ECDSAP256SHA256,
+            14 => Algorithm::ECDSAP384SHA384,
+            15 => Algorithm::ED25519,
+            _ => Algorithm::Unknown(value),
+        }
+    }
+
+    /// length in bytes that the hash portion of this function will produce
+    pub fn hash_len(self) -> Option<usize> {
+        match self {
+            Algorithm::RSASHA1 | Algorithm::RSASHA1NSEC3SHA1 => Some(20), // 160 bits
+            Algorithm::RSASHA256 | Algorithm::ECDSAP256SHA256 | Algorithm::ED25519 => Some(32), // 256 bits
+            Algorithm::ECDSAP384SHA384 => Some(48),
+            Algorithm::RSASHA512 => Some(64), // 512 bites
+            Algorithm::Unknown(_) => None,
+        }
+    }
+
+    /// Convert to string form
+    #[deprecated(note = "use as_str instead")]
+    pub fn to_str(self) -> &'static str {
+        self.as_str()
+    }
+
+    /// Convert to string form
+    pub fn as_str(self) -> &'static str {
+        match self {
+            Algorithm::RSASHA1 => "RSASHA1",
+            Algorithm::RSASHA256 => "RSASHA256",
+            Algorithm::RSASHA1NSEC3SHA1 => "RSASHA1-NSEC3-SHA1",
+            Algorithm::RSASHA512 => "RSASHA512",
+            Algorithm::ECDSAP256SHA256 => "ECDSAP256SHA256",
+            Algorithm::ECDSAP384SHA384 => "ECDSAP384SHA384",
+            Algorithm::ED25519 => "ED25519",
+            Algorithm::Unknown(_) => "Unknown",
+        }
+    }
+}
+
+impl BinEncodable for Algorithm {
+    fn emit(&self, encoder: &mut BinEncoder) -> ProtoResult<()> {
+        encoder.emit(u8::from(*self))
+    }
+}
+
+impl<'r> BinDecodable<'r> for Algorithm {
+    // http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml
+    fn read(decoder: &mut BinDecoder<'r>) -> ProtoResult<Algorithm> {
+        let algorithm_id =
+            decoder.read_u8()?.unverified(/*Algorithm is verified as safe in processing this*/);
+        Ok(Algorithm::from_u8(algorithm_id))
+    }
+}
+
+impl From<Algorithm> for &'static str {
+    fn from(a: Algorithm) -> &'static str {
+        a.as_str()
+    }
+}
+
+impl From<Algorithm> for u8 {
+    fn from(a: Algorithm) -> u8 {
+        match a {
+            Algorithm::RSASHA1 => 5,
+            Algorithm::RSASHA1NSEC3SHA1 => 7,
+            Algorithm::RSASHA256 => 8,
+            Algorithm::RSASHA512 => 10,
+            Algorithm::ECDSAP256SHA256 => 13,
+            Algorithm::ECDSAP384SHA384 => 14,
+            Algorithm::ED25519 => 15,
+            Algorithm::Unknown(v) => v,
+        }
+    }
+}
+
+impl Display for Algorithm {
+    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
+        f.write_str(self.as_str())
+    }
+}
+
+#[test]
+fn test_into() {
+    for algorithm in &[
+        Algorithm::RSASHA1,
+        Algorithm::RSASHA256,
+        Algorithm::RSASHA1NSEC3SHA1,
+        Algorithm::RSASHA512,
+        Algorithm::ECDSAP256SHA256,
+        Algorithm::ECDSAP384SHA384,
+        Algorithm::ED25519,
+    ] {
+        assert_eq!(*algorithm, Algorithm::from_u8(Into::<u8>::into(*algorithm)))
+    }
+}
+
+#[test]
+fn test_order() {
+    let mut algorithms = [
+        Algorithm::RSASHA1,
+        Algorithm::RSASHA256,
+        Algorithm::RSASHA1NSEC3SHA1,
+        Algorithm::RSASHA512,
+        Algorithm::ECDSAP256SHA256,
+        Algorithm::ECDSAP384SHA384,
+        Algorithm::ED25519,
+    ];
+
+    algorithms.sort();
+
+    for (got, expect) in algorithms.iter().zip(
+        [
+            Algorithm::RSASHA1,
+            Algorithm::RSASHA1NSEC3SHA1,
+            Algorithm::RSASHA256,
+            Algorithm::RSASHA512,
+            Algorithm::ECDSAP256SHA256,
+            Algorithm::ECDSAP384SHA384,
+            Algorithm::ED25519,
+        ]
+        .iter(),
+    ) {
+        assert_eq!(got, expect);
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/digest_type.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/digest_type.rs
new file mode 100644
index 0000000..40c3ed9
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/digest_type.rs
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+#[cfg(feature = "openssl")]
+use openssl::hash;
+
+#[cfg(feature = "ring")]
+use ring::digest;
+
+use crate::error::*;
+use crate::rr::dnssec::Algorithm;
+
+#[cfg(any(feature = "ring", feature = "openssl"))]
+use super::Digest;
+
+/// This is the digest format for the
+///
+///```text
+/// 0	Reserved	-	[RFC3658]
+/// 1	SHA-1	MANDATORY	[RFC3658]
+/// 2	SHA-256	MANDATORY	[RFC4509]
+/// 3	GOST R 34.11-94	OPTIONAL	[RFC5933]
+/// 4	SHA-384	OPTIONAL	[RFC6605]
+/// 5 ED25519 [RFC draft-ietf-curdle-dnskey-eddsa-03]
+/// 5-255	Unassigned	-
+/// ```
+#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
+pub enum DigestType {
+    /// [RFC3658]
+    SHA1,
+    /// [RFC4509]
+    SHA256, // [RFC4509]
+    // GOSTR34_11_94, // [RFC5933]
+    /// [RFC6605]
+    SHA384,
+    /// Undefined
+    SHA512,
+    /// This is a passthrough digest as ED25519 is self-packaged
+    ED25519,
+}
+
+impl DigestType {
+    /// TODO: add an Unknown DigestType and make this infallible
+    /// http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml
+    pub fn from_u8(value: u8) -> ProtoResult<Self> {
+        match value {
+            1 => Ok(DigestType::SHA1),
+            2 => Ok(DigestType::SHA256),
+            //  3  => Ok(DigestType::GOSTR34_11_94),
+            4 => Ok(DigestType::SHA384),
+            5 => Ok(DigestType::ED25519),
+            _ => Err(ProtoErrorKind::UnknownAlgorithmTypeValue(value).into()),
+        }
+    }
+
+    /// The OpenSSL counterpart for the digest
+    #[cfg(feature = "openssl")]
+    pub fn to_openssl_digest(self) -> ProtoResult<hash::MessageDigest> {
+        match self {
+            DigestType::SHA1 => Ok(hash::MessageDigest::sha1()),
+            DigestType::SHA256 => Ok(hash::MessageDigest::sha256()),
+            DigestType::SHA384 => Ok(hash::MessageDigest::sha384()),
+            DigestType::SHA512 => Ok(hash::MessageDigest::sha512()),
+            _ => Err(format!("digest not supported by openssl: {:?}", self).into()),
+        }
+    }
+
+    /// The *ring* counterpart for the digest
+    #[cfg(feature = "ring")]
+    pub fn to_ring_digest_alg(self) -> ProtoResult<&'static digest::Algorithm> {
+        match self {
+            DigestType::SHA1 => Ok(&digest::SHA1_FOR_LEGACY_USE_ONLY),
+            DigestType::SHA256 => Ok(&digest::SHA256),
+            DigestType::SHA384 => Ok(&digest::SHA384),
+            DigestType::SHA512 => Ok(&digest::SHA512),
+            _ => Err(format!("digest not supported by ring: {:?}", self).into()),
+        }
+    }
+
+    /// Hash the data
+    #[cfg(all(not(feature = "ring"), feature = "openssl"))]
+    pub fn hash(self, data: &[u8]) -> ProtoResult<Digest> {
+        hash::hash(self.to_openssl_digest()?, data).map_err(Into::into)
+    }
+
+    /// Hash the data
+    #[cfg(feature = "ring")]
+    pub fn hash(self, data: &[u8]) -> ProtoResult<Digest> {
+        let alg = self.to_ring_digest_alg()?;
+        Ok(digest::digest(alg, data))
+    }
+
+    /// This will always error, enable openssl feature at compile time
+    #[cfg(not(any(feature = "openssl", feature = "ring")))]
+    pub fn hash(self, _: &[u8]) -> ProtoResult<Vec<u8>> {
+        Err("The openssl and ring features are both disabled".into())
+    }
+
+    /// Digest all the data.
+    #[cfg(all(not(feature = "ring"), feature = "openssl"))]
+    pub fn digest_all(self, data: &[&[u8]]) -> ProtoResult<Digest> {
+        use std::io::Write;
+
+        let digest_type = self.to_openssl_digest()?;
+        hash::Hasher::new(digest_type)
+            .map_err(Into::into)
+            .and_then(|mut hasher| {
+                for d in data {
+                    hasher.write_all(d)?;
+                }
+                hasher.finish().map_err(Into::into)
+            })
+    }
+
+    /// Digest all the data.
+    #[cfg(feature = "ring")]
+    pub fn digest_all(self, data: &[&[u8]]) -> ProtoResult<Digest> {
+        let alg = self.to_ring_digest_alg()?;
+        let mut ctx = digest::Context::new(alg);
+        for d in data {
+            ctx.update(d);
+        }
+        Ok(ctx.finish())
+    }
+}
+
+impl From<Algorithm> for DigestType {
+    fn from(a: Algorithm) -> DigestType {
+        match a {
+            Algorithm::RSASHA1 | Algorithm::RSASHA1NSEC3SHA1 => DigestType::SHA1,
+            Algorithm::RSASHA256 | Algorithm::ECDSAP256SHA256 => DigestType::SHA256,
+            Algorithm::RSASHA512 => DigestType::SHA512,
+            Algorithm::ECDSAP384SHA384 => DigestType::SHA384,
+            Algorithm::ED25519 => DigestType::ED25519,
+
+            Algorithm::Unknown(_) => DigestType::SHA512,
+        }
+    }
+}
+
+impl From<DigestType> for u8 {
+    fn from(a: DigestType) -> u8 {
+        match a {
+            DigestType::SHA1 => 1,
+            DigestType::SHA256 => 2,
+            // DigestType::GOSTR34_11_94 => 3,
+            DigestType::SHA384 => 4,
+            DigestType::ED25519 => 5,
+            DigestType::SHA512 => 255,
+        }
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/ec_public_key.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/ec_public_key.rs
new file mode 100644
index 0000000..af872d6
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/ec_public_key.rs
@@ -0,0 +1,46 @@
+// Copyright 2017 Brian Smith <brian@briansmith.org>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+use super::Algorithm;
+use crate::error::*;
+
+pub struct ECPublicKey {
+    buf: [u8; MAX_LEN],
+    len: usize,
+}
+
+// The length of the longest supported EC public key (P-384).
+const MAX_LEN: usize = 1 + (2 * 48);
+
+impl ECPublicKey {
+    // DNSSEC encodes uncompressed EC public keys without the standard 0x04
+    // prefix that indicates they are uncompressed, but crypto libraries
+    // require that prefix.
+    pub fn from_unprefixed(without_prefix: &[u8], algorithm: Algorithm) -> ProtoResult<Self> {
+        let field_len = match algorithm {
+            Algorithm::ECDSAP256SHA256 => 32,
+            Algorithm::ECDSAP384SHA384 => 48,
+            _ => return Err("only ECDSAP256SHA256 and ECDSAP384SHA384 are supported by Ec".into()),
+        };
+        let len = 1 + (2 * field_len);
+        if len - 1 != without_prefix.len() {
+            return Err("EC public key is the wrong length".into());
+        }
+        let mut buf = [0x04u8; MAX_LEN];
+        buf[1..len].copy_from_slice(without_prefix);
+        Ok(ECPublicKey { buf, len })
+    }
+
+    pub fn prefixed_bytes(&self) -> &[u8] {
+        &self.buf[..self.len]
+    }
+
+    #[cfg(feature = "ring")]
+    pub fn unprefixed_bytes(&self) -> &[u8] {
+        &self.buf[1..self.len]
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/mod.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/mod.rs
new file mode 100644
index 0000000..ba0b484
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/mod.rs
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! dns security extension related modules
+
+mod algorithm;
+mod digest_type;
+#[cfg(any(feature = "openssl", feature = "ring"))]
+mod ec_public_key;
+mod nsec3;
+pub mod public_key;
+pub mod rdata;
+#[cfg(any(feature = "openssl", feature = "ring"))]
+mod rsa_public_key;
+mod supported_algorithm;
+pub mod tbs;
+mod trust_anchor;
+mod verifier;
+
+pub use self::algorithm::Algorithm;
+pub use self::digest_type::DigestType;
+pub use self::nsec3::Nsec3HashAlgorithm;
+pub use self::public_key::PublicKey;
+pub use self::public_key::PublicKeyBuf;
+pub use self::public_key::PublicKeyEnum;
+pub use self::supported_algorithm::SupportedAlgorithms;
+pub use self::tbs::TBS;
+pub use self::trust_anchor::TrustAnchor;
+pub use self::verifier::Verifier;
+
+#[cfg(all(not(feature = "ring"), feature = "openssl"))]
+pub use openssl::hash::DigestBytes as Digest;
+
+#[cfg(feature = "ring")]
+pub use ring::digest::Digest;
+
+/// This is an empty type, enable Ring or OpenSSL for this feature
+#[cfg(not(any(feature = "openssl", feature = "ring")))]
+pub struct Digest;
+
+#[cfg(not(any(feature = "openssl", feature = "ring")))]
+#[allow(clippy::should_implement_trait)]
+impl Digest {
+    /// This is an empty type, enable Ring or OpenSSL for this feature
+    pub fn as_ref(&self) -> &Self {
+        self
+    }
+
+    /// This is an empty type, enable Ring or OpenSSL for this feature
+    pub fn to_owned(&self) -> Vec<u8> {
+        vec![]
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/nsec3.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/nsec3.rs
new file mode 100644
index 0000000..53b71f9
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/nsec3.rs
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ * Copyright (C) 2017 Google LLC.
+ *
+ * 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.
+ */
+
+#[cfg(any(feature = "openssl", feature = "ring"))]
+use super::{Digest, DigestType};
+use crate::error::*;
+#[cfg(any(feature = "openssl", feature = "ring"))]
+use crate::rr::Name;
+#[cfg(any(feature = "openssl", feature = "ring"))]
+use crate::serialize::binary::{BinEncodable, BinEncoder};
+
+/// ```text
+/// RFC 5155                         NSEC3                        March 2008
+///
+/// 11.  IANA Considerations
+///
+///    Although the NSEC3 and NSEC3PARAM RR formats include a hash algorithm
+///    parameter, this document does not define a particular mechanism for
+///    safely transitioning from one NSEC3 hash algorithm to another.  When
+///    specifying a new hash algorithm for use with NSEC3, a transition
+///    mechanism MUST also be defined.
+///
+///    This document updates the IANA registry "DOMAIN NAME SYSTEM
+///    PARAMETERS" (http://www.iana.org/assignments/dns-parameters) in sub-
+///    registry "TYPES", by defining two new types.  Section 3 defines the
+///    NSEC3 RR type 50.  Section 4 defines the NSEC3PARAM RR type 51.
+///
+///    This document updates the IANA registry "DNS SECURITY ALGORITHM
+///    NUMBERS -- per [RFC4035]"
+///    (http://www.iana.org/assignments/dns-sec-alg-numbers).  Section 2
+///    defines the aliases DSA-NSEC3-SHA1 (6) and RSASHA1-NSEC3-SHA1 (7) for
+///    respectively existing registrations DSA and RSASHA1 in combination
+///    with NSEC3 hash algorithm SHA1.
+///
+///    Since these algorithm numbers are aliases for existing DNSKEY
+///    algorithm numbers, the flags that exist for the original algorithm
+///    are valid for the alias algorithm.
+///
+///    This document creates a new IANA registry for NSEC3 flags.  This
+///    registry is named "DNSSEC NSEC3 Flags".  The initial contents of this
+///    registry are:
+///
+///      0   1   2   3   4   5   6   7
+///    +---+---+---+---+---+---+---+---+
+///    |   |   |   |   |   |   |   |Opt|
+///    |   |   |   |   |   |   |   |Out|
+///    +---+---+---+---+---+---+---+---+
+///
+///       bit 7 is the Opt-Out flag.
+///
+///       bits 0 - 6 are available for assignment.
+///
+///    Assignment of additional NSEC3 Flags in this registry requires IETF
+///    Standards Action [RFC2434].
+///
+///    This document creates a new IANA registry for NSEC3PARAM flags.  This
+///    registry is named "DNSSEC NSEC3PARAM Flags".  The initial contents of
+///    this registry are:
+///
+///      0   1   2   3   4   5   6   7
+///    +---+---+---+---+---+---+---+---+
+///    |   |   |   |   |   |   |   | 0 |
+///    +---+---+---+---+---+---+---+---+
+///
+///       bit 7 is reserved and must be 0.
+///
+///       bits 0 - 6 are available for assignment.
+///
+///    Assignment of additional NSEC3PARAM Flags in this registry requires
+///    IETF Standards Action [RFC2434].
+///
+///    Finally, this document creates a new IANA registry for NSEC3 hash
+///    algorithms.  This registry is named "DNSSEC NSEC3 Hash Algorithms".
+///    The initial contents of this registry are:
+///
+///       0 is Reserved.
+///
+///       1 is SHA-1.
+///
+///       2-255 Available for assignment.
+///
+///    Assignment of additional NSEC3 hash algorithms in this registry
+///    requires IETF Standards Action [RFC2434].
+/// ```
+#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
+pub enum Nsec3HashAlgorithm {
+    /// Hash for the Nsec3 records
+    SHA1,
+}
+
+impl Nsec3HashAlgorithm {
+    /// http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml
+    pub fn from_u8(value: u8) -> ProtoResult<Self> {
+        match value {
+            1 => Ok(Nsec3HashAlgorithm::SHA1),
+            // TODO: where/when is SHA2?
+            _ => Err(ProtoErrorKind::UnknownAlgorithmTypeValue(value).into()),
+        }
+    }
+
+    /// ```text
+    /// Laurie, et al.              Standards Track                    [Page 14]
+    ///
+    /// RFC 5155                         NSEC3                        March 2008
+    ///
+    /// Define H(x) to be the hash of x using the Hash Algorithm selected by
+    ///    the NSEC3 RR, k to be the number of Iterations, and || to indicate
+    ///    concatenation.  Then define:
+    ///
+    ///       IH(salt, x, 0) = H(x || salt), and
+    ///
+    ///       IH(salt, x, k) = H(IH(salt, x, k-1) || salt), if k > 0
+    ///
+    ///    Then the calculated hash of an owner name is
+    ///
+    ///       IH(salt, owner name, iterations),
+    ///
+    ///    where the owner name is in the canonical form, defined as:
+    ///
+    ///    The wire format of the owner name where:
+    ///
+    ///    1.  The owner name is fully expanded (no DNS name compression) and
+    ///        fully qualified;
+    ///
+    ///    2.  All uppercase US-ASCII letters are replaced by the corresponding
+    ///        lowercase US-ASCII letters;
+    ///
+    ///    3.  If the owner name is a wildcard name, the owner name is in its
+    ///        original unexpanded form, including the "*" label (no wildcard
+    ///        substitution);
+    /// ```
+    #[cfg(any(feature = "openssl", feature = "ring"))]
+    pub fn hash(self, salt: &[u8], name: &Name, iterations: u16) -> ProtoResult<Digest> {
+        match self {
+            // if there ever is more than just SHA1 support, this should be a genericized method
+            Nsec3HashAlgorithm::SHA1 => {
+                let mut buf: Vec<u8> = Vec::new();
+                {
+                    let mut encoder: BinEncoder = BinEncoder::new(&mut buf);
+                    encoder.set_canonical_names(true);
+                    name.emit(&mut encoder).expect("could not encode Name");
+                }
+
+                Self::sha1_recursive_hash(salt, buf, iterations)
+            }
+        }
+    }
+
+    /// until there is another supported algorithm, just hardcoded to this.
+    #[cfg(any(feature = "openssl", feature = "ring"))]
+    fn sha1_recursive_hash(salt: &[u8], bytes: Vec<u8>, iterations: u16) -> ProtoResult<Digest> {
+        let digested: Digest;
+        let to_digest = if iterations > 0 {
+            digested = Self::sha1_recursive_hash(salt, bytes, iterations - 1)?;
+            digested.as_ref()
+        } else {
+            &bytes
+        };
+        DigestType::SHA1.digest_all(&[to_digest, salt])
+    }
+}
+
+impl From<Nsec3HashAlgorithm> for u8 {
+    fn from(a: Nsec3HashAlgorithm) -> u8 {
+        match a {
+            Nsec3HashAlgorithm::SHA1 => 1,
+        }
+    }
+}
+
+#[test]
+#[cfg(any(feature = "openssl", feature = "ring"))]
+fn test_hash() {
+    use std::str::FromStr;
+
+    let name = Name::from_str("www.example.com").unwrap();
+    let salt: Vec<u8> = vec![1, 2, 3, 4];
+
+    assert_eq!(
+        Nsec3HashAlgorithm::SHA1
+            .hash(&salt, &name, 0)
+            .unwrap()
+            .as_ref()
+            .len(),
+        20
+    );
+    assert_eq!(
+        Nsec3HashAlgorithm::SHA1
+            .hash(&salt, &name, 1)
+            .unwrap()
+            .as_ref()
+            .len(),
+        20
+    );
+    assert_eq!(
+        Nsec3HashAlgorithm::SHA1
+            .hash(&salt, &name, 3)
+            .unwrap()
+            .as_ref()
+            .len(),
+        20
+    );
+}
+
+#[test]
+#[cfg(any(feature = "openssl", feature = "ring"))]
+fn test_known_hashes() {
+    // H(example)       = 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom
+    assert_eq!(
+        hash_with_base32("example"),
+        "0p9mhaveqvm6t7vbl5lop2u3t2rp3tom"
+    );
+
+    // H(a.example)     = 35mthgpgcu1qg68fab165klnsnk3dpvl
+    assert_eq!(
+        hash_with_base32("a.example"),
+        "35mthgpgcu1qg68fab165klnsnk3dpvl"
+    );
+
+    // H(ai.example)    = gjeqe526plbf1g8mklp59enfd789njgi
+    assert_eq!(
+        hash_with_base32("ai.example"),
+        "gjeqe526plbf1g8mklp59enfd789njgi"
+    );
+
+    // H(ns1.example)   = 2t7b4g4vsa5smi47k61mv5bv1a22bojr
+    assert_eq!(
+        hash_with_base32("ns1.example"),
+        "2t7b4g4vsa5smi47k61mv5bv1a22bojr"
+    );
+
+    // H(ns2.example)   = q04jkcevqvmu85r014c7dkba38o0ji5r
+    assert_eq!(
+        hash_with_base32("ns2.example"),
+        "q04jkcevqvmu85r014c7dkba38o0ji5r"
+    );
+
+    // H(w.example)     = k8udemvp1j2f7eg6jebps17vp3n8i58h
+    assert_eq!(
+        hash_with_base32("w.example"),
+        "k8udemvp1j2f7eg6jebps17vp3n8i58h"
+    );
+
+    // H(*.w.example)   = r53bq7cc2uvmubfu5ocmm6pers9tk9en
+    assert_eq!(
+        hash_with_base32("*.w.example"),
+        "r53bq7cc2uvmubfu5ocmm6pers9tk9en"
+    );
+
+    // H(x.w.example)   = b4um86eghhds6nea196smvmlo4ors995
+    assert_eq!(
+        hash_with_base32("x.w.example"),
+        "b4um86eghhds6nea196smvmlo4ors995"
+    );
+
+    // H(y.w.example)   = ji6neoaepv8b5o6k4ev33abha8ht9fgc
+    assert_eq!(
+        hash_with_base32("y.w.example"),
+        "ji6neoaepv8b5o6k4ev33abha8ht9fgc"
+    );
+
+    // H(x.y.w.example) = 2vptu5timamqttgl4luu9kg21e0aor3s
+    assert_eq!(
+        hash_with_base32("x.y.w.example"),
+        "2vptu5timamqttgl4luu9kg21e0aor3s"
+    );
+
+    // H(xx.example)    = t644ebqk9bibcna874givr6joj62mlhv
+    assert_eq!(
+        hash_with_base32("xx.example"),
+        "t644ebqk9bibcna874givr6joj62mlhv"
+    );
+}
+
+#[cfg(test)]
+#[cfg(any(feature = "openssl", feature = "ring"))]
+fn hash_with_base32(name: &str) -> String {
+    use data_encoding::BASE32_DNSSEC;
+
+    // NSEC3PARAM 1 0 12 aabbccdd
+    let known_name = Name::parse(name, Some(&Name::new())).unwrap();
+    let known_salt = [0xAAu8, 0xBBu8, 0xCCu8, 0xDDu8];
+    let hash = Nsec3HashAlgorithm::SHA1
+        .hash(&known_salt, &known_name, 12)
+        .unwrap();
+    BASE32_DNSSEC.encode(hash.as_ref())
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/public_key.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/public_key.rs
new file mode 100644
index 0000000..bea0470
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/public_key.rs
@@ -0,0 +1,533 @@
+// Copyright 2015-2016 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! Public Key implementations for supported key types
+#[cfg(not(any(feature = "openssl", feature = "ring")))]
+use std::marker::PhantomData;
+
+#[cfg(all(not(feature = "ring"), feature = "openssl"))]
+use openssl::bn::BigNum;
+#[cfg(all(not(feature = "ring"), feature = "openssl"))]
+use openssl::bn::BigNumContext;
+#[cfg(all(not(feature = "ring"), feature = "openssl"))]
+use openssl::ec::{EcGroup, EcKey, EcPoint};
+#[cfg(all(not(feature = "ring"), feature = "openssl"))]
+use openssl::nid::Nid;
+#[cfg(all(not(feature = "ring"), feature = "openssl"))]
+use openssl::pkey::{PKey, Public};
+#[cfg(all(not(feature = "ring"), feature = "openssl"))]
+use openssl::rsa::Rsa as OpenSslRsa;
+#[cfg(all(not(feature = "ring"), feature = "openssl"))]
+use openssl::sign::Verifier;
+#[cfg(feature = "ring")]
+use ring::signature::{self, ED25519_PUBLIC_KEY_LEN};
+
+use crate::error::*;
+use crate::rr::dnssec::Algorithm;
+#[cfg(all(not(feature = "ring"), feature = "openssl"))]
+use crate::rr::dnssec::DigestType;
+
+#[cfg(any(feature = "openssl", feature = "ring"))]
+use crate::rr::dnssec::ec_public_key::ECPublicKey;
+#[cfg(any(feature = "openssl", feature = "ring"))]
+use crate::rr::dnssec::rsa_public_key::RSAPublicKey;
+
+/// PublicKeys implement the ability to ideally be zero copy abstractions over public keys for verifying signed content.
+///
+/// In DNS the KEY and DNSKEY types are generally the RData types which store public key material.
+pub trait PublicKey {
+    /// Returns the public bytes of the public key, in DNS format
+    fn public_bytes(&self) -> &[u8];
+
+    /// Verifies the hash matches the signature with the current `key`.
+    ///
+    /// # Arguments
+    ///
+    /// * `message` - the message to be validated, see `hash_rrset`
+    /// * `signature` - the signature to use to verify the hash, extracted from an `RData::RRSIG`
+    ///                 for example.
+    ///
+    /// # Return value
+    ///
+    /// True if and only if the signature is valid for the hash. This will always return
+    /// false if the `key`.
+    #[allow(unused)]
+    fn verify(&self, algorithm: Algorithm, message: &[u8], signature: &[u8]) -> ProtoResult<()>;
+}
+
+#[cfg(all(not(feature = "ring"), feature = "openssl"))]
+fn verify_with_pkey(
+    pkey: &PKey<Public>,
+    algorithm: Algorithm,
+    message: &[u8],
+    signature: &[u8],
+) -> ProtoResult<()> {
+    let digest_type = DigestType::from(algorithm).to_openssl_digest()?;
+    let mut verifier = Verifier::new(digest_type, &pkey).unwrap();
+    verifier.update(message)?;
+    verifier
+        .verify(signature)
+        .map_err(Into::into)
+        .and_then(|b| {
+            if b {
+                Ok(())
+            } else {
+                Err("could not verify".into())
+            }
+        })
+}
+
+/// Elyptic Curve public key type
+#[cfg(all(not(feature = "ring"), feature = "openssl"))]
+pub struct Ec<'k> {
+    raw: &'k [u8],
+    pkey: PKey<Public>,
+}
+
+#[cfg(all(not(feature = "ring"), feature = "openssl"))]
+impl<'k> Ec<'k> {
+    /// ```text
+    /// RFC 6605                    ECDSA for DNSSEC                  April 2012
+    ///
+    ///   4.  DNSKEY and RRSIG Resource Records for ECDSA
+    ///
+    ///   ECDSA public keys consist of a single value, called "Q" in FIPS
+    ///   186-3.  In DNSSEC keys, Q is a simple bit string that represents the
+    ///   uncompressed form of a curve point, "x | y".
+    ///
+    ///   The ECDSA signature is the combination of two non-negative integers,
+    ///   called "r" and "s" in FIPS 186-3.  The two integers, each of which is
+    ///   formatted as a simple octet string, are combined into a single longer
+    ///   octet string for DNSSEC as the concatenation "r | s".  (Conversion of
+    ///   the integers to bit strings is described in Section C.2 of FIPS
+    ///   186-3.)  For P-256, each integer MUST be encoded as 32 octets; for
+    ///   P-384, each integer MUST be encoded as 48 octets.
+    ///
+    ///   The algorithm numbers associated with the DNSKEY and RRSIG resource
+    ///   records are fully defined in the IANA Considerations section.  They
+    ///   are:
+    ///
+    ///   o  DNSKEY and RRSIG RRs signifying ECDSA with the P-256 curve and
+    ///      SHA-256 use the algorithm number 13.
+    ///
+    ///   o  DNSKEY and RRSIG RRs signifying ECDSA with the P-384 curve and
+    ///      SHA-384 use the algorithm number 14.
+    ///
+    ///   Conformant implementations that create records to be put into the DNS
+    ///   MUST implement signing and verification for both of the above
+    ///   algorithms.  Conformant DNSSEC verifiers MUST implement verification
+    ///   for both of the above algorithms.
+    /// ```
+    pub fn from_public_bytes(public_key: &'k [u8], algorithm: Algorithm) -> ProtoResult<Self> {
+        let curve = match algorithm {
+            Algorithm::ECDSAP256SHA256 => Nid::X9_62_PRIME256V1,
+            Algorithm::ECDSAP384SHA384 => Nid::SECP384R1,
+            _ => return Err("only ECDSAP256SHA256 and ECDSAP384SHA384 are supported by Ec".into()),
+        };
+        // Key needs to be converted to OpenSSL format
+        let k = ECPublicKey::from_unprefixed(public_key, algorithm)?;
+        EcGroup::from_curve_name(curve)
+            .and_then(|group| BigNumContext::new().map(|ctx| (group, ctx)))
+            // FYI: BigNum slices treat all slices as BigEndian, i.e NetworkByteOrder
+            .and_then(|(group, mut ctx)| {
+                EcPoint::from_bytes(&group, k.prefixed_bytes(), &mut ctx)
+                    .map(|point| (group, point))
+            })
+            .and_then(|(group, point)| EcKey::from_public_key(&group, &point))
+            .and_then(PKey::from_ec_key)
+            .map_err(Into::into)
+            .map(|pkey| Ec {
+                raw: public_key,
+                pkey,
+            })
+    }
+}
+
+#[cfg(all(not(feature = "ring"), feature = "openssl"))]
+fn asn1_emit_integer(output: &mut Vec<u8>, int: &[u8]) {
+    assert!(!int.is_empty());
+    output.push(0x02); // INTEGER
+    if int[0] > 0x7f {
+        output.push((int.len() + 1) as u8);
+        output.push(0x00); // MSB must be zero
+        output.extend(int);
+        return;
+    }
+    // Trim leading zeros
+    let mut pos = 0;
+    while pos < int.len() {
+        if int[pos] == 0 {
+            if pos == int.len() - 1 {
+                break;
+            }
+            pos += 1;
+            continue;
+        }
+        if int[pos] > 0x7f {
+            // We need to leave one 0x00 to make MSB zero
+            pos -= 1;
+        }
+        break;
+    }
+    let int_output = &int[pos..];
+    output.push(int_output.len() as u8);
+    output.extend(int_output);
+}
+/// Convert raw DNSSEC ECDSA signature to ASN.1 DER format
+#[cfg(all(not(feature = "ring"), feature = "openssl"))]
+pub fn dnssec_ecdsa_signature_to_der(signature: &[u8]) -> ProtoResult<Vec<u8>> {
+    if signature.is_empty() || signature.len() & 1 != 0 || signature.len() > 127 {
+        return Err("invalid signature length".into());
+    }
+    let part_len = signature.len() / 2;
+    // ASN.1 SEQUENCE: 0x30 [LENGTH]
+    let mut signature_asn1 = vec![0x30, 0x00];
+    asn1_emit_integer(&mut signature_asn1, &signature[..part_len]);
+    asn1_emit_integer(&mut signature_asn1, &signature[part_len..]);
+    signature_asn1[1] = (signature_asn1.len() - 2) as u8;
+    Ok(signature_asn1)
+}
+#[cfg(all(not(feature = "ring"), feature = "openssl"))]
+impl<'k> PublicKey for Ec<'k> {
+    fn public_bytes(&self) -> &[u8] {
+        self.raw
+    }
+
+    fn verify(&self, algorithm: Algorithm, message: &[u8], signature: &[u8]) -> ProtoResult<()> {
+        let signature_asn1 = dnssec_ecdsa_signature_to_der(signature)?;
+        verify_with_pkey(&self.pkey, algorithm, message, &signature_asn1)
+    }
+}
+
+/// Elyptic Curve public key type
+#[cfg(feature = "ring")]
+type Ec = ECPublicKey;
+
+#[cfg(feature = "ring")]
+impl Ec {
+    /// ```text
+    /// RFC 6605                    ECDSA for DNSSEC                  April 2012
+    ///
+    ///   4.  DNSKEY and RRSIG Resource Records for ECDSA
+    ///
+    ///   ECDSA public keys consist of a single value, called "Q" in FIPS
+    ///   186-3.  In DNSSEC keys, Q is a simple bit string that represents the
+    ///   uncompressed form of a curve point, "x | y".
+    ///
+    ///   The ECDSA signature is the combination of two non-negative integers,
+    ///   called "r" and "s" in FIPS 186-3.  The two integers, each of which is
+    ///   formatted as a simple octet string, are combined into a single longer
+    ///   octet string for DNSSEC as the concatenation "r | s".  (Conversion of
+    ///   the integers to bit strings is described in Section C.2 of FIPS
+    ///   186-3.)  For P-256, each integer MUST be encoded as 32 octets; for
+    ///   P-384, each integer MUST be encoded as 48 octets.
+    ///
+    ///   The algorithm numbers associated with the DNSKEY and RRSIG resource
+    ///   records are fully defined in the IANA Considerations section.  They
+    ///   are:
+    ///
+    ///   o  DNSKEY and RRSIG RRs signifying ECDSA with the P-256 curve and
+    ///      SHA-256 use the algorithm number 13.
+    ///
+    ///   o  DNSKEY and RRSIG RRs signifying ECDSA with the P-384 curve and
+    ///      SHA-384 use the algorithm number 14.
+    ///
+    ///   Conformant implementations that create records to be put into the DNS
+    ///   MUST implement signing and verification for both of the above
+    ///   algorithms.  Conformant DNSSEC verifiers MUST implement verification
+    ///   for both of the above algorithms.
+    /// ```
+    pub fn from_public_bytes(public_key: &[u8], algorithm: Algorithm) -> ProtoResult<Self> {
+        ECPublicKey::from_unprefixed(public_key, algorithm)
+    }
+}
+
+#[cfg(feature = "ring")]
+impl PublicKey for Ec {
+    fn public_bytes(&self) -> &[u8] {
+        self.unprefixed_bytes()
+    }
+
+    fn verify(&self, algorithm: Algorithm, message: &[u8], signature: &[u8]) -> ProtoResult<()> {
+        // TODO: assert_eq!(algorithm, self.algorithm); once *ring* allows this.
+        let alg = match algorithm {
+            Algorithm::ECDSAP256SHA256 => &signature::ECDSA_P256_SHA256_FIXED,
+            Algorithm::ECDSAP384SHA384 => &signature::ECDSA_P384_SHA384_FIXED,
+            _ => return Err("only ECDSAP256SHA256 and ECDSAP384SHA384 are supported by Ec".into()),
+        };
+        let public_key = signature::UnparsedPublicKey::new(alg, self.prefixed_bytes());
+        public_key.verify(message, signature).map_err(Into::into)
+    }
+}
+
+/// Ed25519 Public key
+#[cfg(feature = "ring")]
+pub struct Ed25519<'k> {
+    raw: &'k [u8],
+}
+
+#[cfg(feature = "ring")]
+impl<'k> Ed25519<'k> {
+    /// ```text
+    ///  Internet-Draft              EdDSA for DNSSEC               December 2016
+    ///
+    ///  An Ed25519 public key consists of a 32-octet value, which is encoded
+    ///  into the Public Key field of a DNSKEY resource record as a simple bit
+    ///  string.  The generation of a public key is defined in Section 5.1.5
+    ///  in [RFC 8032]. Breaking tradition, the keys are encoded in little-
+    ///  endian byte order.
+    /// ```
+    pub fn from_public_bytes(public_key: &'k [u8]) -> ProtoResult<Self> {
+        if public_key.len() != ED25519_PUBLIC_KEY_LEN {
+            return Err(format!(
+                "expected {} byte public_key: {}",
+                ED25519_PUBLIC_KEY_LEN,
+                public_key.len()
+            )
+            .into());
+        }
+
+        Ok(Ed25519 { raw: public_key })
+    }
+}
+
+#[cfg(feature = "ring")]
+impl<'k> PublicKey for Ed25519<'k> {
+    // TODO: just store reference to public key bytes in ctor...
+    fn public_bytes(&self) -> &[u8] {
+        self.raw
+    }
+
+    fn verify(&self, _: Algorithm, message: &[u8], signature: &[u8]) -> ProtoResult<()> {
+        let public_key = signature::UnparsedPublicKey::new(&signature::ED25519, self.raw);
+        public_key.verify(message, signature).map_err(Into::into)
+    }
+}
+
+/// Rsa public key
+#[cfg(any(feature = "openssl", feature = "ring"))]
+pub struct Rsa<'k> {
+    raw: &'k [u8],
+
+    #[cfg(all(not(feature = "ring"), feature = "openssl"))]
+    pkey: PKey<Public>,
+
+    #[cfg(feature = "ring")]
+    pkey: RSAPublicKey<'k>,
+}
+
+#[cfg(any(feature = "openssl", feature = "ring"))]
+impl<'k> Rsa<'k> {
+    /// ```text
+    /// RFC 3110              RSA SIGs and KEYs in the DNS              May 2001
+    ///
+    ///       2. RSA Public KEY Resource Records
+    ///
+    ///  RSA public keys are stored in the DNS as KEY RRs using algorithm
+    ///  number 5 [RFC2535].  The structure of the algorithm specific portion
+    ///  of the RDATA part of such RRs is as shown below.
+    ///
+    ///        Field             Size
+    ///        -----             ----
+    ///        exponent length   1 or 3 octets (see text)
+    ///        exponent          as specified by length field
+    ///        modulus           remaining space
+    ///
+    ///  For interoperability, the exponent and modulus are each limited to
+    ///  4096 bits in length.  The public key exponent is a variable length
+    ///  unsigned integer.  Its length in octets is represented as one octet
+    ///  if it is in the range of 1 to 255 and by a zero octet followed by a
+    ///  two octet unsigned length if it is longer than 255 bytes.  The public
+    ///  key modulus field is a multiprecision unsigned integer.  The length
+    ///  of the modulus can be determined from the RDLENGTH and the preceding
+    ///  RDATA fields including the exponent.  Leading zero octets are
+    ///  prohibited in the exponent and modulus.
+    ///
+    ///  Note: KEY RRs for use with RSA/SHA1 DNS signatures MUST use this
+    ///  algorithm number (rather than the algorithm number specified in the
+    ///  obsoleted RFC 2537).
+    ///
+    ///  Note: This changes the algorithm number for RSA KEY RRs to be the
+    ///  same as the new algorithm number for RSA/SHA1 SIGs.
+    /// ```
+    pub fn from_public_bytes(raw: &'k [u8]) -> ProtoResult<Self> {
+        let parsed = RSAPublicKey::try_from(raw)?;
+        let pkey = into_pkey(parsed)?;
+        Ok(Rsa { raw, pkey })
+    }
+}
+
+#[cfg(all(not(feature = "ring"), feature = "openssl"))]
+fn into_pkey(parsed: RSAPublicKey) -> ProtoResult<PKey<Public>> {
+    // FYI: BigNum slices treat all slices as BigEndian, i.e NetworkByteOrder
+    let e = BigNum::from_slice(parsed.e())?;
+    let n = BigNum::from_slice(parsed.n())?;
+
+    OpenSslRsa::from_public_components(n, e)
+        .and_then(PKey::from_rsa)
+        .map_err(Into::into)
+}
+
+#[cfg(feature = "ring")]
+fn into_pkey<'k>(parsed: RSAPublicKey<'k>) -> ProtoResult<RSAPublicKey<'k>> {
+    Ok(parsed)
+}
+
+#[cfg(any(feature = "openssl", feature = "ring"))]
+impl<'k> PublicKey for Rsa<'k> {
+    fn public_bytes(&self) -> &[u8] {
+        self.raw
+    }
+
+    #[cfg(all(not(feature = "ring"), feature = "openssl"))]
+    fn verify(&self, algorithm: Algorithm, message: &[u8], signature: &[u8]) -> ProtoResult<()> {
+        verify_with_pkey(&self.pkey, algorithm, message, signature)
+    }
+
+    #[cfg(feature = "ring")]
+    fn verify(&self, algorithm: Algorithm, message: &[u8], signature: &[u8]) -> ProtoResult<()> {
+        let alg = match algorithm {
+            Algorithm::RSASHA256 => &signature::RSA_PKCS1_2048_8192_SHA256,
+            Algorithm::RSASHA512 => &signature::RSA_PKCS1_2048_8192_SHA512,
+            Algorithm::RSASHA1 => &signature::RSA_PKCS1_2048_8192_SHA1_FOR_LEGACY_USE_ONLY,
+            Algorithm::RSASHA1NSEC3SHA1 => {
+                return Err("*ring* doesn't support RSASHA1NSEC3SHA1 yet".into())
+            }
+            _ => unreachable!("non-RSA algorithm passed to RSA verify()"),
+        };
+        let public_key = signature::RsaPublicKeyComponents {
+            n: self.pkey.n(),
+            e: self.pkey.e(),
+        };
+        public_key
+            .verify(alg, message, signature)
+            .map_err(Into::into)
+    }
+}
+
+/// Variants of all know public keys
+pub enum PublicKeyEnum<'k> {
+    /// RSA keypair, supported by OpenSSL
+    #[cfg(any(feature = "openssl", feature = "ring"))]
+    Rsa(Rsa<'k>),
+    /// Elliptic curve keypair
+    #[cfg(all(not(feature = "ring"), feature = "openssl"))]
+    Ec(Ec<'k>),
+    /// Elliptic curve keypair
+    #[cfg(feature = "ring")]
+    Ec(Ec),
+    /// Ed25519 public key for the Algorithm::ED25519
+    #[cfg(feature = "ring")]
+    Ed25519(Ed25519<'k>),
+    /// PhatomData for compiler when ring and or openssl not defined, do not use...
+    #[cfg(not(any(feature = "ring", feature = "openssl")))]
+    Phantom(&'k PhantomData<()>),
+}
+
+impl<'k> PublicKeyEnum<'k> {
+    /// Converts the bytes into a PulbicKey of the specified algorithm
+    #[allow(unused_variables)]
+    pub fn from_public_bytes(public_key: &'k [u8], algorithm: Algorithm) -> ProtoResult<Self> {
+        match algorithm {
+            #[cfg(any(feature = "openssl", feature = "ring"))]
+            Algorithm::ECDSAP256SHA256 | Algorithm::ECDSAP384SHA384 => Ok(PublicKeyEnum::Ec(
+                Ec::from_public_bytes(public_key, algorithm)?,
+            )),
+            #[cfg(feature = "ring")]
+            Algorithm::ED25519 => Ok(PublicKeyEnum::Ed25519(Ed25519::from_public_bytes(
+                public_key,
+            )?)),
+            #[cfg(any(feature = "openssl", feature = "ring"))]
+            Algorithm::RSASHA1
+            | Algorithm::RSASHA1NSEC3SHA1
+            | Algorithm::RSASHA256
+            | Algorithm::RSASHA512 => Ok(PublicKeyEnum::Rsa(Rsa::from_public_bytes(public_key)?)),
+            _ => Err("public key algorithm not supported".into()),
+        }
+    }
+}
+
+impl<'k> PublicKey for PublicKeyEnum<'k> {
+    fn public_bytes(&self) -> &[u8] {
+        match *self {
+            #[cfg(any(feature = "openssl", feature = "ring"))]
+            PublicKeyEnum::Ec(ref ec) => ec.public_bytes(),
+            #[cfg(feature = "ring")]
+            PublicKeyEnum::Ed25519(ref ed) => ed.public_bytes(),
+            #[cfg(any(feature = "openssl", feature = "ring"))]
+            PublicKeyEnum::Rsa(ref rsa) => rsa.public_bytes(),
+            #[cfg(not(any(feature = "ring", feature = "openssl")))]
+            _ => panic!("no public keys registered, enable ring or openssl features"),
+        }
+    }
+
+    #[allow(unused_variables)]
+    fn verify(&self, algorithm: Algorithm, message: &[u8], signature: &[u8]) -> ProtoResult<()> {
+        match *self {
+            #[cfg(any(feature = "openssl", feature = "ring"))]
+            PublicKeyEnum::Ec(ref ec) => ec.verify(algorithm, message, signature),
+            #[cfg(feature = "ring")]
+            PublicKeyEnum::Ed25519(ref ed) => ed.verify(algorithm, message, signature),
+            #[cfg(any(feature = "openssl", feature = "ring"))]
+            PublicKeyEnum::Rsa(ref rsa) => rsa.verify(algorithm, message, signature),
+            #[cfg(not(any(feature = "ring", feature = "openssl")))]
+            _ => panic!("no public keys registered, enable ring or openssl features"),
+        }
+    }
+}
+
+/// An owned variant of PublicKey
+pub struct PublicKeyBuf {
+    key_buf: Vec<u8>,
+}
+
+impl PublicKeyBuf {
+    /// Constructs a new PublicKey from the specified bytes, these should be in DNSKEY form.
+    pub fn new(key_buf: Vec<u8>) -> Self {
+        PublicKeyBuf { key_buf }
+    }
+}
+
+impl PublicKey for PublicKeyBuf {
+    fn public_bytes(&self) -> &[u8] {
+        &self.key_buf
+    }
+
+    fn verify(&self, algorithm: Algorithm, message: &[u8], signature: &[u8]) -> ProtoResult<()> {
+        let public_key = PublicKeyEnum::from_public_bytes(&self.key_buf, algorithm)?;
+
+        public_key.verify(algorithm, message, signature)
+    }
+}
+
+#[cfg(all(not(feature = "ring"), feature = "openssl"))]
+#[cfg(test)]
+mod tests {
+    #[cfg(feature = "openssl")]
+    #[test]
+    fn test_asn1_emit_integer() {
+        fn test_case(source: &[u8], expected_data: &[u8]) {
+            use crate::rr::dnssec::public_key::asn1_emit_integer;
+
+            let mut output = Vec::<u8>::new();
+            asn1_emit_integer(&mut output, source);
+            assert_eq!(output[0], 0x02);
+            assert_eq!(output[1], expected_data.len() as u8);
+            assert_eq!(&output[2..], expected_data);
+        }
+        test_case(&[0x00], &[0x00]);
+        test_case(&[0x00, 0x00], &[0x00]);
+        test_case(&[0x7f], &[0x7f]);
+        test_case(&[0x80], &[0x00, 0x80]);
+        test_case(&[0x00, 0x80], &[0x00, 0x80]);
+        test_case(&[0x00, 0x00, 0x80], &[0x00, 0x80]);
+        test_case(&[0x7f, 0x00, 0x80], &[0x7f, 0x00, 0x80]);
+        test_case(&[0x00, 0x7f, 0x00, 0x80], &[0x7f, 0x00, 0x80]);
+        test_case(&[0x80, 0x00, 0x80], &[0x00, 0x80, 0x00, 0x80]);
+        test_case(&[0xff, 0x00, 0x80], &[0x00, 0xff, 0x00, 0x80]);
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/rdata/dnskey.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/rdata/dnskey.rs
new file mode 100644
index 0000000..8ab4593
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/rdata/dnskey.rs
@@ -0,0 +1,448 @@
+/*
+ * Copyright (C) 2016 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! public key record data for signing zone records
+
+use crate::error::*;
+use crate::rr::dnssec::{Algorithm, Digest, DigestType};
+use crate::rr::record_data::RData;
+use crate::rr::Name;
+use crate::serialize::binary::{
+    BinDecodable, BinDecoder, BinEncodable, BinEncoder, Restrict, RestrictedMath,
+};
+
+/// [RFC 4034](https://tools.ietf.org/html/rfc4034#section-2), DNSSEC Resource Records, March 2005
+///
+/// ```text
+/// 2.  The DNSKEY Resource Record
+///
+///    DNSSEC uses public key cryptography to sign and authenticate DNS
+///    resource record sets (RRsets).  The public keys are stored in DNSKEY
+///    resource records and are used in the DNSSEC authentication process
+///    described in [RFC4035]: A zone signs its authoritative RRsets by
+///    using a private key and stores the corresponding public key in a
+///    DNSKEY RR.  A resolver can then use the public key to validate
+///    signatures covering the RRsets in the zone, and thus to authenticate
+///    them.
+///
+///    The DNSKEY RR is not intended as a record for storing arbitrary
+///    public keys and MUST NOT be used to store certificates or public keys
+///    that do not directly relate to the DNS infrastructure.
+///
+///    The Type value for the DNSKEY RR type is 48.
+///
+///    The DNSKEY RR is class independent.
+///
+///    The DNSKEY RR has no special TTL requirements.
+///
+/// 2.1.  DNSKEY RDATA Wire Format
+///
+///    The RDATA for a DNSKEY RR consists of a 2 octet Flags Field, a 1
+///    octet Protocol Field, a 1 octet Algorithm Field, and the Public Key
+///    Field.
+///
+///                         1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+///     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+///    |              Flags            |    Protocol   |   Algorithm   |
+///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+///    /                                                               /
+///    /                            Public Key                         /
+///    /                                                               /
+///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+///
+/// 2.1.5.  Notes on DNSKEY RDATA Design
+///
+///    Although the Protocol Field always has value 3, it is retained for
+///    backward compatibility with early versions of the KEY record.
+///
+/// ```
+#[derive(Debug, PartialEq, Eq, Hash, Clone)]
+pub struct DNSKEY {
+    zone_key: bool,
+    secure_entry_point: bool,
+    revoke: bool,
+    algorithm: Algorithm,
+    public_key: Vec<u8>,
+}
+
+impl DNSKEY {
+    /// Construct a new DNSKey RData
+    ///
+    /// # Arguments
+    ///
+    /// * `zone_key` - this key is used to sign Zone resource records
+    /// * `secure_entry_point` - this key is used to sign DNSKeys that sign the Zone records
+    /// * `revoke` - this key has been revoked
+    /// * `algorithm` - specifies the algorithm which this Key uses to sign records
+    /// * `public_key` - the public key material, in native endian, the emitter will perform any necessary conversion
+    ///
+    /// # Return
+    ///
+    /// A new DNSKEY RData for use in a Resource Record
+    pub fn new(
+        zone_key: bool,
+        secure_entry_point: bool,
+        revoke: bool,
+        algorithm: Algorithm,
+        public_key: Vec<u8>,
+    ) -> DNSKEY {
+        DNSKEY {
+            zone_key,
+            secure_entry_point,
+            revoke,
+            algorithm,
+            public_key,
+        }
+    }
+
+    /// [RFC 4034, DNSSEC Resource Records, March 2005](https://tools.ietf.org/html/rfc4034#section-2.1.1)
+    ///
+    /// ```text
+    /// 2.1.1.  The Flags Field
+    ///
+    ///    Bit 7 of the Flags field is the Zone Key flag.  If bit 7 has value 1,
+    ///    then the DNSKEY record holds a DNS zone key, and the DNSKEY RR's
+    ///    owner name MUST be the name of a zone.  If bit 7 has value 0, then
+    ///    the DNSKEY record holds some other type of DNS public key and MUST
+    ///    NOT be used to verify RRSIGs that cover RRsets.
+    ///
+    ///
+    ///    Bits 0-6 and 8-14 are reserved: these bits MUST have value 0 upon
+    ///    creation of the DNSKEY RR and MUST be ignored upon receipt.
+    /// ```
+    pub fn zone_key(&self) -> bool {
+        self.zone_key
+    }
+
+    /// [RFC 4034, DNSSEC Resource Records, March 2005](https://tools.ietf.org/html/rfc4034#section-2.1.1)
+    ///
+    /// ```text
+    /// 2.1.1.  The Flags Field
+    ///
+    ///    Bit 15 of the Flags field is the Secure Entry Point flag, described
+    ///    in [RFC3757].  If bit 15 has value 1, then the DNSKEY record holds a
+    ///    key intended for use as a secure entry point.  This flag is only
+    ///    intended to be a hint to zone signing or debugging software as to the
+    ///    intended use of this DNSKEY record; validators MUST NOT alter their
+    ///    behavior during the signature validation process in any way based on
+    ///    the setting of this bit.  This also means that a DNSKEY RR with the
+    ///    SEP bit set would also need the Zone Key flag set in order to be able
+    ///    to generate signatures legally.  A DNSKEY RR with the SEP set and the
+    ///    Zone Key flag not set MUST NOT be used to verify RRSIGs that cover
+    ///    RRsets.
+    /// ```
+    pub fn secure_entry_point(&self) -> bool {
+        self.secure_entry_point
+    }
+
+    /// [RFC 5011, Trust Anchor Update, September 2007](https://tools.ietf.org/html/rfc5011#section-3)
+    ///
+    /// ```text
+    /// RFC 5011                  Trust Anchor Update             September 2007
+    ///
+    /// 7.  IANA Considerations
+    ///
+    ///   The IANA has assigned a bit in the DNSKEY flags field (see Section 7
+    ///   of [RFC4034]) for the REVOKE bit (8).
+    /// ```
+    pub fn revoke(&self) -> bool {
+        self.revoke
+    }
+
+    /// [RFC 4034, DNSSEC Resource Records, March 2005](https://tools.ietf.org/html/rfc4034#section-2.1.3)
+    ///
+    /// ```text
+    /// 2.1.3.  The Algorithm Field
+    ///
+    ///    The Algorithm field identifies the public key's cryptographic
+    ///    algorithm and determines the format of the Public Key field.  A list
+    ///    of DNSSEC algorithm types can be found in Appendix A.1
+    /// ```
+    pub fn algorithm(&self) -> Algorithm {
+        self.algorithm
+    }
+
+    /// [RFC 4034, DNSSEC Resource Records, March 2005](https://tools.ietf.org/html/rfc4034#section-2.1.4)
+    ///
+    /// ```text
+    /// 2.1.4.  The Public Key Field
+    ///
+    ///    The Public Key Field holds the public key material.  The format
+    ///    depends on the algorithm of the key being stored and is described in
+    ///    separate documents.
+    /// ```
+    pub fn public_key(&self) -> &[u8] {
+        &self.public_key
+    }
+
+    /// Creates a message digest for this DNSKEY record.
+    ///
+    /// ```text
+    /// 5.1.4.  The Digest Field
+    ///
+    ///    The DS record refers to a DNSKEY RR by including a digest of that
+    ///    DNSKEY RR.
+    ///
+    ///    The digest is calculated by concatenating the canonical form of the
+    ///    fully qualified owner name of the DNSKEY RR with the DNSKEY RDATA,
+    ///    and then applying the digest algorithm.
+    ///
+    ///      digest = digest_algorithm( DNSKEY owner name | DNSKEY RDATA);
+    ///
+    ///       "|" denotes concatenation
+    ///
+    ///      DNSKEY RDATA = Flags | Protocol | Algorithm | Public Key.
+    ///
+    ///    The size of the digest may vary depending on the digest algorithm and
+    ///    DNSKEY RR size.  As of the time of this writing, the only defined
+    ///    digest algorithm is SHA-1, which produces a 20 octet digest.
+    /// ```
+    ///
+    /// # Arguments
+    ///
+    /// * `name` - the label of of the DNSKEY record.
+    /// * `digest_type` - the `DigestType` with which to create the message digest.
+    #[cfg(any(feature = "openssl", feature = "ring"))]
+    pub fn to_digest(&self, name: &Name, digest_type: DigestType) -> ProtoResult<Digest> {
+        let mut buf: Vec<u8> = Vec::new();
+        {
+            let mut encoder: BinEncoder = BinEncoder::new(&mut buf);
+            encoder.set_canonical_names(true);
+            if let Err(e) = name
+                .emit(&mut encoder)
+                .and_then(|_| emit(&mut encoder, self))
+            {
+                log::warn!("error serializing dnskey: {}", e);
+                return Err(format!("error serializing dnskey: {}", e).into());
+            }
+        }
+
+        digest_type.hash(&buf)
+    }
+
+    /// This will always return an error unless the Ring or OpenSSL features are enabled
+    #[cfg(not(any(feature = "openssl", feature = "ring")))]
+    pub fn to_digest(&self, _: &Name, _: DigestType) -> ProtoResult<Digest> {
+        Err("Ring or OpenSSL must be enabled for this feature".into())
+    }
+
+    /// The key tag is calculated as a hash to more quickly lookup a DNSKEY.
+    ///
+    /// [RFC 1035](https://tools.ietf.org/html/rfc1035), DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION, November 1987
+    ///
+    /// ```text
+    /// RFC 2535                DNS Security Extensions               March 1999
+    ///
+    /// 4.1.6 Key Tag Field
+    ///
+    ///  The "key Tag" is a two octet quantity that is used to efficiently
+    ///  select between multiple keys which may be applicable and thus check
+    ///  that a public key about to be used for the computationally expensive
+    ///  effort to check the signature is possibly valid.  For algorithm 1
+    ///  (MD5/RSA) as defined in [RFC 2537], it is the next to the bottom two
+    ///  octets of the public key modulus needed to decode the signature
+    ///  field.  That is to say, the most significant 16 of the least
+    ///  significant 24 bits of the modulus in network (big endian) order. For
+    ///  all other algorithms, including private algorithms, it is calculated
+    ///  as a simple checksum of the KEY RR as described in Appendix C.
+    ///
+    /// Appendix C: Key Tag Calculation
+    ///
+    ///  The key tag field in the SIG RR is just a means of more efficiently
+    ///  selecting the correct KEY RR to use when there is more than one KEY
+    ///  RR candidate available, for example, in verifying a signature.  It is
+    ///  possible for more than one candidate key to have the same tag, in
+    ///  which case each must be tried until one works or all fail.  The
+    ///  following reference implementation of how to calculate the Key Tag,
+    ///  for all algorithms other than algorithm 1, is in ANSI C.  It is coded
+    ///  for clarity, not efficiency.  (See section 4.1.6 for how to determine
+    ///  the Key Tag of an algorithm 1 key.)
+    ///
+    ///  /* assumes int is at least 16 bits
+    ///     first byte of the key tag is the most significant byte of return
+    ///     value
+    ///     second byte of the key tag is the least significant byte of
+    ///     return value
+    ///     */
+    ///
+    ///  int keytag (
+    ///
+    ///          unsigned char key[],  /* the RDATA part of the KEY RR */
+    ///          unsigned int keysize, /* the RDLENGTH */
+    ///          )
+    ///  {
+    ///  long int    ac;    /* assumed to be 32 bits or larger */
+    ///
+    ///  for ( ac = 0, i = 0; i < keysize; ++i )
+    ///      ac += (i&1) ? key[i] : key[i]<<8;
+    ///  ac += (ac>>16) & 0xFFFF;
+    ///  return ac & 0xFFFF;
+    ///  }
+    /// ```
+    pub fn calculate_key_tag(&self) -> ProtoResult<u16> {
+        // TODO:
+        let mut bytes: Vec<u8> = Vec::with_capacity(512);
+        {
+            let mut e = BinEncoder::new(&mut bytes);
+            self::emit(&mut e, self)?;
+        }
+        Ok(Self::calculate_key_tag_internal(&bytes))
+    }
+
+    /// Internal checksum function (used for non-RSAMD5 hashes only,
+    /// however, RSAMD5 is considered deprecated and not implemented in
+    /// trust-dns, anyways).
+    pub fn calculate_key_tag_internal(bytes: &[u8]) -> u16 {
+        let mut ac: u32 = 0;
+        for (i, k) in bytes.iter().enumerate() {
+            ac += u32::from(*k) << if i & 0x01 != 0 { 0 } else { 8 };
+        }
+        ac += ac >> 16;
+        (ac & 0xFFFF) as u16
+    }
+}
+
+impl From<DNSKEY> for RData {
+    fn from(key: DNSKEY) -> RData {
+        RData::DNSSEC(super::DNSSECRData::DNSKEY(key))
+    }
+}
+
+/// Read the RData from the given Decoder
+pub fn read(decoder: &mut BinDecoder, rdata_length: Restrict<u16>) -> ProtoResult<DNSKEY> {
+    let flags: u16 = decoder.read_u16()?.unverified(/*used as a bitfield, this is safe*/);
+
+    //    Bits 0-6 and 8-14 are reserved: these bits MUST have value 0 upon
+    //    creation of the DNSKEY RR and MUST be ignored upon receipt.
+    let zone_key: bool = flags & 0b0000_0001_0000_0000 == 0b0000_0001_0000_0000;
+    let secure_entry_point: bool = flags & 0b0000_0000_0000_0001 == 0b0000_0000_0000_0001;
+    let revoke: bool = flags & 0b0000_0000_1000_0000 == 0b0000_0000_1000_0000;
+    let _protocol: u8 = decoder
+        .read_u8()?
+        .verify_unwrap(|protocol| {
+            // RFC 4034                DNSSEC Resource Records               March 2005
+            //
+            // 2.1.2.  The Protocol Field
+            //
+            //    The Protocol Field MUST have value 3, and the DNSKEY RR MUST be
+            //    treated as invalid during signature verification if it is found to be
+            //    some value other than 3.
+            //
+            // protocol is defined to only be '3' right now
+
+            *protocol == 3
+        })
+        .map_err(|protocol| ProtoError::from(ProtoErrorKind::DnsKeyProtocolNot3(protocol)))?;
+
+    let algorithm: Algorithm = Algorithm::read(decoder)?;
+
+    // the public key is the left-over bytes minus 4 for the first fields
+    //   this sub is safe, as the first 4 fields must have been in the rdata, otherwise there would have been
+    //   an earlier return.
+    let key_len = rdata_length
+        .map(|u| u as usize)
+        .checked_sub(4)
+        .map_err(|_| ProtoError::from("invalid rdata length in DNSKEY"))?
+        .unverified(/*used only as length safely*/);
+    let public_key: Vec<u8> =
+        decoder.read_vec(key_len)?.unverified(/*the byte array will fail in usage if invalid*/);
+
+    Ok(DNSKEY::new(
+        zone_key,
+        secure_entry_point,
+        revoke,
+        algorithm,
+        public_key,
+    ))
+}
+
+/// Write the RData from the given Decoder
+pub fn emit(encoder: &mut BinEncoder, rdata: &DNSKEY) -> ProtoResult<()> {
+    let mut flags: u16 = 0;
+    if rdata.zone_key() {
+        flags |= 0b0000_0001_0000_0000
+    }
+    if rdata.secure_entry_point() {
+        flags |= 0b0000_0000_0000_0001
+    }
+    if rdata.revoke() {
+        flags |= 0b0000_0000_1000_0000
+    }
+    encoder.emit_u16(flags)?;
+    encoder.emit(3)?; // always 3 for now
+    rdata.algorithm().emit(encoder)?;
+    encoder.emit_vec(rdata.public_key())?;
+
+    Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+    #![allow(clippy::dbg_macro, clippy::print_stdout)]
+
+    use super::*;
+
+    #[test]
+    #[cfg(any(feature = "openssl", feature = "ring"))]
+    pub fn test() {
+        let rdata = DNSKEY::new(
+            true,
+            true,
+            false,
+            Algorithm::RSASHA256,
+            vec![0, 1, 2, 3, 4, 5, 6, 7],
+        );
+
+        let mut bytes = Vec::new();
+        let mut encoder: BinEncoder = BinEncoder::new(&mut bytes);
+        assert!(emit(&mut encoder, &rdata).is_ok());
+        let bytes = encoder.into_bytes();
+
+        println!("bytes: {:?}", bytes);
+
+        let mut decoder: BinDecoder = BinDecoder::new(bytes);
+        let read_rdata = read(&mut decoder, Restrict::new(bytes.len() as u16));
+        let read_rdata = read_rdata.expect("error decoding");
+
+        assert_eq!(rdata, read_rdata);
+        assert!(rdata
+            .to_digest(
+                &Name::parse("www.example.com.", None).unwrap(),
+                DigestType::SHA256
+            )
+            .is_ok());
+    }
+
+    #[test]
+    fn test_calculate_key_tag_checksum() {
+        let test_text = "The quick brown fox jumps over the lazy dog";
+        let test_vectors = vec![
+            (vec![], 0),
+            (vec![0, 0, 0, 0], 0),
+            (vec![0xff, 0xff, 0xff, 0xff], 0xffff),
+            (vec![1, 0, 0, 0], 0x0100),
+            (vec![0, 1, 0, 0], 0x0001),
+            (vec![0, 0, 1, 0], 0x0100),
+            (test_text.as_bytes().to_vec(), 0x8d5b),
+        ];
+
+        for &(ref input_data, exp_result) in test_vectors.iter() {
+            let result = DNSKEY::calculate_key_tag_internal(&input_data);
+            assert_eq!(result, exp_result);
+        }
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/rdata/ds.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/rdata/ds.rs
new file mode 100644
index 0000000..54dc8ce
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/rdata/ds.rs
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2016 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! pointer record from parent zone to child zone for dnskey proof
+
+use crate::error::*;
+use crate::rr::dnssec::{Algorithm, DigestType};
+use crate::serialize::binary::*;
+
+use crate::rr::dnssec::rdata::DNSKEY;
+use crate::rr::Name;
+
+/// [RFC 4034, DNSSEC Resource Records, March 2005](https://tools.ietf.org/html/rfc4034#section-5)
+///
+/// ```text
+/// 5.1.  DS RDATA Wire Format
+///
+///    The RDATA for a DS RR consists of a 2 octet Key Tag field, a 1 octet
+///    Algorithm field, a 1 octet Digest Type field, and a Digest field.
+///
+///                         1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+///     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+///    |           Key Tag             |  Algorithm    |  Digest Type  |
+///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+///    /                                                               /
+///    /                            Digest                             /
+///    /                                                               /
+///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+///
+/// 5.2.  Processing of DS RRs When Validating Responses
+///
+///    The DS RR links the authentication chain across zone boundaries, so
+///    the DS RR requires extra care in processing.  The DNSKEY RR referred
+///    to in the DS RR MUST be a DNSSEC zone key.  The DNSKEY RR Flags MUST
+///    have Flags bit 7 set.  If the DNSKEY flags do not indicate a DNSSEC
+///    zone key, the DS RR (and the DNSKEY RR it references) MUST NOT be
+///    used in the validation process.
+///
+/// 5.3.  The DS RR Presentation Format
+///
+///    The presentation format of the RDATA portion is as follows:
+///
+///    The Key Tag field MUST be represented as an unsigned decimal integer.
+///
+///    The Algorithm field MUST be represented either as an unsigned decimal
+///    integer or as an algorithm mnemonic specified in Appendix A.1.
+///
+///    The Digest Type field MUST be represented as an unsigned decimal
+///    integer.
+///
+///    The Digest MUST be represented as a sequence of case-insensitive
+///    hexadecimal digits.  Whitespace is allowed within the hexadecimal
+///    text.
+/// ```
+#[derive(Debug, PartialEq, Eq, Hash, Clone)]
+pub struct DS {
+    key_tag: u16,
+    algorithm: Algorithm,
+    digest_type: DigestType,
+    digest: Vec<u8>,
+}
+
+impl DS {
+    /// Constructs a new DS RData
+    ///
+    /// # Arguments
+    ///
+    /// * `key_tag` - the key_tag associated to the DNSKEY
+    /// * `algorithm` - algorithm as specified in the DNSKEY
+    /// * `digest_type` - hash algorithm used to validate the DNSKEY
+    /// * `digest` - hash of the DNSKEY
+    ///
+    /// # Returns
+    ///
+    /// the DS RDATA for use in a Resource Record
+    pub fn new(key_tag: u16, algorithm: Algorithm, digest_type: DigestType, digest: Vec<u8>) -> DS {
+        DS {
+            key_tag,
+            algorithm,
+            digest_type,
+            digest,
+        }
+    }
+
+    /// [RFC 4034, DNSSEC Resource Records, March 2005](https://tools.ietf.org/html/rfc4034#section-5.1.1)
+    ///
+    /// ```text
+    /// 5.1.1.  The Key Tag Field
+    ///
+    ///    The Key Tag field lists the key tag of the DNSKEY RR referred to by
+    ///    the DS record, in network byte order.
+    ///
+    ///    The Key Tag used by the DS RR is identical to the Key Tag used by
+    ///    RRSIG RRs.  Appendix B describes how to compute a Key Tag.
+    /// ```
+    pub fn key_tag(&self) -> u16 {
+        self.key_tag
+    }
+
+    /// [RFC 4034, DNSSEC Resource Records, March 2005](https://tools.ietf.org/html/rfc4034#section-5.1.1)
+    ///
+    /// ```text
+    /// 5.1.2.  The Algorithm Field
+    ///
+    ///    The Algorithm field lists the algorithm number of the DNSKEY RR
+    ///    referred to by the DS record.
+    ///
+    ///    The algorithm number used by the DS RR is identical to the algorithm
+    ///    number used by RRSIG and DNSKEY RRs.  Appendix A.1 lists the
+    ///    algorithm number types.
+    /// ```
+    pub fn algorithm(&self) -> Algorithm {
+        self.algorithm
+    }
+
+    /// [RFC 4034, DNSSEC Resource Records, March 2005](https://tools.ietf.org/html/rfc4034#section-5.1.1)
+    ///
+    /// ```text
+    /// 5.1.3.  The Digest Type Field
+    ///
+    ///    The DS RR refers to a DNSKEY RR by including a digest of that DNSKEY
+    ///    RR.  The Digest Type field identifies the algorithm used to construct
+    ///    the digest.  Appendix A.2 lists the possible digest algorithm types.
+    /// ```
+    pub fn digest_type(&self) -> DigestType {
+        self.digest_type
+    }
+
+    /// [RFC 4034, DNSSEC Resource Records, March 2005](https://tools.ietf.org/html/rfc4034#section-5.1.1)
+    ///
+    /// ```text
+    /// 5.1.4.  The Digest Field
+    ///
+    ///    The DS record refers to a DNSKEY RR by including a digest of that
+    ///    DNSKEY RR.
+    ///
+    ///    The digest is calculated by concatenating the canonical form of the
+    ///    fully qualified owner name of the DNSKEY RR with the DNSKEY RDATA,
+    ///    and then applying the digest algorithm.
+    ///
+    ///      digest = digest_algorithm( DNSKEY owner name | DNSKEY RDATA);
+    ///
+    ///       "|" denotes concatenation
+    ///
+    ///      DNSKEY RDATA = Flags | Protocol | Algorithm | Public Key.
+    ///
+    ///    The size of the digest may vary depending on the digest algorithm and
+    ///    DNSKEY RR size.  As of the time of this writing, the only defined
+    ///    digest algorithm is SHA-1, which produces a 20 octet digest.
+    /// ```
+    pub fn digest(&self) -> &[u8] {
+        &self.digest
+    }
+
+    /// Validates that a given DNSKEY is covered by the DS record.
+    ///
+    /// # Return
+    ///
+    /// true if and only if the DNSKEY is covered by the DS record.
+    #[cfg(any(feature = "openssl", feature = "ring"))]
+    pub fn covers(&self, name: &Name, key: &DNSKEY) -> ProtoResult<bool> {
+        key.to_digest(name, self.digest_type())
+            .map(|hash| hash.as_ref() == self.digest())
+    }
+
+    /// This will always return an error unless the Ring or OpenSSL features are enabled
+    #[cfg(not(any(feature = "openssl", feature = "ring")))]
+    pub fn covers(&self, _: &Name, _: &DNSKEY) -> ProtoResult<bool> {
+        Err("Ring or OpenSSL must be enabled for this feature".into())
+    }
+}
+
+/// Read the RData from the given Decoder
+pub fn read(decoder: &mut BinDecoder, rdata_length: Restrict<u16>) -> ProtoResult<DS> {
+    let start_idx = decoder.index();
+
+    let key_tag: u16 = decoder.read_u16()?.unverified(/*key_tag is valid as any u16*/);
+    let algorithm: Algorithm = Algorithm::read(decoder)?;
+    let digest_type: DigestType =
+        DigestType::from_u8(decoder.read_u8()?.unverified(/*DigestType is verified as safe*/))?;
+
+    let bytes_read = decoder.index() - start_idx;
+    let left: usize = rdata_length
+        .map(|u| u as usize)
+        .checked_sub(bytes_read)
+        .map_err(|_| ProtoError::from("invalid rdata length in DS"))?
+        .unverified(/*used only as length safely*/);
+    let digest =
+        decoder.read_vec(left)?.unverified(/*the byte array will fail in usage if invalid*/);
+
+    Ok(DS::new(key_tag, algorithm, digest_type, digest))
+}
+
+/// Write the RData from the given Decoder
+pub fn emit(encoder: &mut BinEncoder, rdata: &DS) -> ProtoResult<()> {
+    encoder.emit_u16(rdata.key_tag())?;
+    rdata.algorithm().emit(encoder)?; // always 3 for now
+    encoder.emit(rdata.digest_type().into())?;
+    encoder.emit_vec(rdata.digest())?;
+
+    Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+    #![allow(clippy::dbg_macro, clippy::print_stdout)]
+
+    use super::*;
+
+    #[test]
+    pub fn test() {
+        let rdata = DS::new(
+            0xF00F,
+            Algorithm::RSASHA256,
+            DigestType::SHA256,
+            vec![5, 6, 7, 8],
+        );
+
+        let mut bytes = Vec::new();
+        let mut encoder: BinEncoder = BinEncoder::new(&mut bytes);
+        assert!(emit(&mut encoder, &rdata).is_ok());
+        let bytes = encoder.into_bytes();
+
+        println!("bytes: {:?}", bytes);
+
+        let mut decoder: BinDecoder = BinDecoder::new(bytes);
+        let restrict = Restrict::new(bytes.len() as u16);
+        let read_rdata = read(&mut decoder, restrict).expect("Decoding error");
+        assert_eq!(rdata, read_rdata);
+    }
+
+    #[test]
+    #[cfg(any(feature = "openssl", feature = "ring"))]
+    pub fn test_covers() {
+        use crate::rr::dnssec::rdata::DNSKEY;
+
+        let name = Name::parse("www.example.com.", None).unwrap();
+
+        let dnskey_rdata = DNSKEY::new(true, true, false, Algorithm::RSASHA256, vec![1, 2, 3, 4]);
+        let ds_rdata = DS::new(
+            0,
+            Algorithm::RSASHA256,
+            DigestType::SHA256,
+            dnskey_rdata
+                .to_digest(&name, DigestType::SHA256)
+                .unwrap()
+                .as_ref()
+                .to_owned(),
+        );
+
+        assert!(ds_rdata.covers(&name, &dnskey_rdata).unwrap());
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/rdata/key.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/rdata/key.rs
new file mode 100644
index 0000000..96d22fb1
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/rdata/key.rs
@@ -0,0 +1,870 @@
+/*
+ * Copyright (C) 2016 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! public key record data for signing zone records
+
+use crate::error::*;
+use crate::rr::dnssec::Algorithm;
+use crate::rr::record_data::RData;
+use crate::serialize::binary::*;
+
+/// [RFC 2535](https://tools.ietf.org/html/rfc2535#section-3), Domain Name System Security Extensions, March 1999
+///
+/// ```text
+/// 3. The KEY Resource Record
+///
+///    The KEY resource record (RR) is used to store a public key that is
+///    associated with a Domain Name System (DNS) name.  This can be the
+///    public key of a zone, a user, or a host or other end entity. Security
+///    aware DNS implementations MUST be designed to handle at least two
+///    simultaneously valid keys of the same type associated with the same
+///    name.
+///
+///    The type number for the KEY RR is 25.
+///
+///    A KEY RR is, like any other RR, authenticated by a SIG RR.  KEY RRs
+///    must be signed by a zone level key.
+///
+/// 3.1 KEY RDATA format
+///
+///    The RDATA for a KEY RR consists of flags, a protocol octet, the
+///    algorithm number octet, and the public key itself.  The format is as
+///    follows:
+///
+///                         1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+///     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+///    |             flags             |    protocol   |   algorithm   |
+///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+///    |                                                               /
+///    /                          public key                           /
+///    /                                                               /
+///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
+///
+///    The KEY RR is not intended for storage of certificates and a separate
+///    certificate RR has been developed for that purpose, defined in [RFC
+///    2538].
+///
+///    The meaning of the KEY RR owner name, flags, and protocol octet are
+///    described in Sections 3.1.1 through 3.1.5 below.  The flags and
+///    algorithm must be examined before any data following the algorithm
+///    octet as they control the existence and format of any following data.
+///    The algorithm and public key fields are described in Section 3.2.
+///    The format of the public key is algorithm dependent.
+///
+///    KEY RRs do not specify their validity period but their authenticating
+///    SIG RR(s) do as described in Section 4 below.
+///
+/// 3.1.1 Object Types, DNS Names, and Keys
+///
+///    The public key in a KEY RR is for the object named in the owner name.
+///
+///    A DNS name may refer to three different categories of things.  For
+///    example, foo.host.example could be (1) a zone, (2) a host or other
+///    end entity , or (3) the mapping into a DNS name of the user or
+///    account foo@host.example.  Thus, there are flag bits, as described
+///    below, in the KEY RR to indicate with which of these roles the owner
+///    name and public key are associated.  Note that an appropriate zone
+///    KEY RR MUST occur at the apex node of a secure zone and zone KEY RRs
+///    occur only at delegation points.
+///
+/// 3.1.2 The KEY RR Flag Field
+///
+///    In the "flags" field:
+///
+///      0   1   2   3   4   5   6   7   8   9   0   1   2   3   4   5
+///    +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+///    |  A/C  | Z | XT| Z | Z | NAMTYP| Z | Z | Z | Z |      SIG      |
+///    +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+///
+///    Bit 0 and 1 are the key "type" bits whose values have the following
+///    meanings:
+///
+///            10: Use of the key is prohibited for authentication.
+///            01: Use of the key is prohibited for confidentiality.
+///            00: Use of the key for authentication and/or confidentiality
+///                is permitted. Note that DNS security makes use of keys
+///                for authentication only. Confidentiality use flagging is
+///                provided for use of keys in other protocols.
+///                Implementations not intended to support key distribution
+///                for confidentiality MAY require that the confidentiality
+///                use prohibited bit be on for keys they serve.
+///            11: If both bits are one, the "no key" value, there is no key
+///                information and the RR stops after the algorithm octet.
+///                By the use of this "no key" value, a signed KEY RR can
+///                authenticatably assert that, for example, a zone is not
+///                secured.  See section 3.4 below.
+///
+///    Bits 2 is reserved and must be zero.
+///
+///    Bits 3 is reserved as a flag extension bit.  If it is a one, a second
+///           16 bit flag field is added after the algorithm octet and
+///           before the key data.  This bit MUST NOT be set unless one or
+///           more such additional bits have been defined and are non-zero.
+///
+///    Bits 4-5 are reserved and must be zero.
+///
+///    Bits 6 and 7 form a field that encodes the name type. Field values
+///    have the following meanings:
+///
+///            00: indicates that this is a key associated with a "user" or
+///                "account" at an end entity, usually a host.  The coding
+///                of the owner name is that used for the responsible
+///                individual mailbox in the SOA and RP RRs: The owner name
+///                is the user name as the name of a node under the entity
+///                name.  For example, "j_random_user" on
+///                host.subdomain.example could have a public key associated
+///                through a KEY RR with name
+///                j_random_user.host.subdomain.example.  It could be used
+///                in a security protocol where authentication of a user was
+///                desired.  This key might be useful in IP or other
+///                security for a user level service such a telnet, ftp,
+///                rlogin, etc.
+///            01: indicates that this is a zone key for the zone whose name
+///                is the KEY RR owner name.  This is the public key used
+///                for the primary DNS security feature of data origin
+///                authentication.  Zone KEY RRs occur only at delegation
+///                points.
+///            10: indicates that this is a key associated with the non-zone
+///                "entity" whose name is the RR owner name.  This will
+///                commonly be a host but could, in some parts of the DNS
+///                tree, be some other type of entity such as a telephone
+///                number [RFC 1530] or numeric IP address.  This is the
+///                public key used in connection with DNS request and
+///                transaction authentication services.  It could also be
+///                used in an IP-security protocol where authentication at
+///                the host, rather than user, level was desired, such as
+///                routing, NTP, etc.
+///            11: reserved.
+///
+///    Bits 8-11 are reserved and must be zero.
+///
+///    Bits 12-15 are the "signatory" field.  If non-zero, they indicate
+///               that the key can validly sign things as specified in DNS
+///               dynamic update [RFC 2137].  Note that zone keys (see bits
+///               6 and 7 above) always have authority to sign any RRs in
+///               the zone regardless of the value of the signatory field.
+/// ```
+#[allow(deprecated)]
+#[derive(Debug, PartialEq, Eq, Hash, Clone)]
+pub struct KEY {
+    key_trust: KeyTrust,
+    key_usage: KeyUsage,
+    signatory: UpdateScope,
+    protocol: Protocol,
+    algorithm: Algorithm,
+    public_key: Vec<u8>,
+}
+
+/// Specifies in what contexts this key may be trusted for use
+#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
+pub enum KeyTrust {
+    /// Use of the key is prohibited for authentication
+    NotAuth,
+    /// Use of the key is prohibited for confidentiality
+    NotPrivate,
+    /// Use of the key for authentication and/or confidentiality is permitted
+    AuthOrPrivate,
+    /// If both bits are one, the "no key" value, (revocation?)
+    DoNotTrust,
+}
+
+impl Default for KeyTrust {
+    fn default() -> Self {
+        KeyTrust::AuthOrPrivate
+    }
+}
+
+impl From<u16> for KeyTrust {
+    fn from(flags: u16) -> Self {
+        // we only care about the first two bits, zero out the rest
+        match flags & 0b1100_0000_0000_0000 {
+            // 10: Use of the key is prohibited for authentication.
+            0b1000_0000_0000_0000 => KeyTrust::NotAuth,
+            // 01: Use of the key is prohibited for confidentiality.
+            0b0100_0000_0000_0000 => KeyTrust::NotPrivate,
+            // 00: Use of the key for authentication and/or confidentiality
+            0b0000_0000_0000_0000 => KeyTrust::AuthOrPrivate,
+            // 11: If both bits are one, the "no key" value, there is no key
+            0b1100_0000_0000_0000 => KeyTrust::DoNotTrust,
+            _ => panic!("All other bit fields should have been cleared"),
+        }
+    }
+}
+
+impl From<KeyTrust> for u16 {
+    fn from(key_trust: KeyTrust) -> Self {
+        match key_trust {
+            // 10: Use of the key is prohibited for authentication.
+            KeyTrust::NotAuth => 0b1000_0000_0000_0000,
+            // 01: Use of the key is prohibited for confidentiality.
+            KeyTrust::NotPrivate => 0b0100_0000_0000_0000,
+            // 00: Use of the key for authentication and/or confidentiality
+            KeyTrust::AuthOrPrivate => 0b0000_0000_0000_0000,
+            // 11: If both bits are one, the "no key" value, there is no key
+            KeyTrust::DoNotTrust => 0b1100_0000_0000_0000,
+        }
+    }
+}
+
+#[test]
+fn test_key_trust() {
+    assert_eq!(
+        KeyTrust::NotAuth,
+        KeyTrust::from(u16::from(KeyTrust::NotAuth))
+    );
+    assert_eq!(
+        KeyTrust::NotPrivate,
+        KeyTrust::from(u16::from(KeyTrust::NotPrivate))
+    );
+    assert_eq!(
+        KeyTrust::AuthOrPrivate,
+        KeyTrust::from(u16::from(KeyTrust::AuthOrPrivate))
+    );
+    assert_eq!(
+        KeyTrust::DoNotTrust,
+        KeyTrust::from(u16::from(KeyTrust::DoNotTrust))
+    );
+}
+
+/// Declares what this key is for
+#[allow(deprecated)]
+#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
+pub enum KeyUsage {
+    /// key associated with a "user" or "account" at an end entity, usually a host
+    Host,
+    /// zone key for the zone whose name is the KEY RR owner name
+    #[deprecated = "For Zone signing DNSKEY should be used"]
+    Zone,
+    /// associated with the non-zone "entity" whose name is the RR owner name
+    Entity,
+    /// Reserved
+    Reserved,
+}
+
+impl Default for KeyUsage {
+    fn default() -> Self {
+        KeyUsage::Entity
+    }
+}
+
+impl From<u16> for KeyUsage {
+    #[allow(deprecated)]
+    fn from(flags: u16) -> Self {
+        // we only care about the 6&7 two bits, zero out the rest
+        match flags & 0b0000_0011_0000_0000 {
+            // 00: indicates that this is a key associated with a "user" or
+            0b0000_0000_0000_0000 => KeyUsage::Host,
+            // 01: indicates that this is a zone key for the zone whose name
+            0b0000_0001_0000_0000 => KeyUsage::Zone,
+            // 10: indicates that this is a key associated with the non-zone
+            0b0000_0010_0000_0000 => KeyUsage::Entity,
+            // 11: reserved.
+            0b0000_0011_0000_0000 => KeyUsage::Reserved,
+            _ => panic!("All other bit fields should have been cleared"),
+        }
+    }
+}
+
+impl From<KeyUsage> for u16 {
+    #[allow(deprecated)]
+    fn from(key_usage: KeyUsage) -> Self {
+        match key_usage {
+            // 00: indicates that this is a key associated with a "user" or
+            KeyUsage::Host => 0b0000_0000_0000_0000,
+            // 01: indicates that this is a zone key for the zone whose name
+            KeyUsage::Zone => 0b0000_0001_0000_0000,
+            // 10: indicates that this is a key associated with the non-zone
+            KeyUsage::Entity => 0b0000_0010_0000_0000,
+            // 11: reserved.
+            KeyUsage::Reserved => 0b0000_0011_0000_0000,
+        }
+    }
+}
+
+#[test]
+#[allow(deprecated)]
+fn test_key_usage() {
+    assert_eq!(KeyUsage::Host, KeyUsage::from(u16::from(KeyUsage::Host)));
+    assert_eq!(KeyUsage::Zone, KeyUsage::from(u16::from(KeyUsage::Zone)));
+    assert_eq!(
+        KeyUsage::Entity,
+        KeyUsage::from(u16::from(KeyUsage::Entity))
+    );
+    assert_eq!(
+        KeyUsage::Reserved,
+        KeyUsage::from(u16::from(KeyUsage::Reserved))
+    );
+}
+
+/// [RFC 2137](https://tools.ietf.org/html/rfc2137#section-3.1), Secure Domain Name System Dynamic Update, April 1997
+///
+/// ```text
+/// 3.1.1 Update Key Name Scope
+///
+///    The owner name of any update authorizing KEY RR must (1) be the same
+///    as the owner name of any RRs being added or deleted or (2) a wildcard
+///    name including within its extended scope (see section 3.3) the name
+///    of any RRs being added or deleted and those RRs must be in the same
+///    zone.
+///
+/// 3.1.2 Update Key Class Scope
+///
+///    The class of any update authorizing KEY RR must be the same as the
+///    class of any RR's being added or deleted.
+///
+/// 3.1.3 Update Key Signatory Field
+///
+///    The four bit "signatory field" (see RFC 2065) of any update
+///    authorizing KEY RR must be non-zero.  The bits have the meanings
+///    described below for non-zone keys (see section 3.2 for zone type
+///    keys).
+///
+///            UPDATE KEY RR SIGNATORY FIELD BITS
+///
+///          0           1           2           3
+///    +-----------+-----------+-----------+-----------+
+///    |   zone    |  strong   |  unique   |  general  |
+///    +-----------+-----------+-----------+-----------+
+///
+///    Bit 0, zone control - If nonzero, this key is authorized to attach,
+///         detach, and move zones by creating and deleting NS, glue A, and
+///         zone KEY RR(s).  If zero, the key can not authorize any update
+///         that would effect such RRs.  This bit is meaningful for both
+///         type A and type B dynamic secure zones.
+///
+///         NOTE:  do not confuse the "zone" signatory field bit with the
+///         "zone" key type bit.
+///
+///    Bit 1, strong update - If nonzero, this key is authorized to add and
+///         delete RRs even if there are other RRs with the same owner name
+///         and class that are authenticated by a SIG signed with a
+///         different dynamic update KEY. If zero, the key can only
+///         authorize updates where any existing RRs of the same owner and
+///         class are authenticated by a SIG using the same key.  This bit
+///         is meaningful only for type A dynamic zones and is ignored in
+///         type B dynamic zones.
+///
+///         Keeping this bit zero on multiple KEY RRs with the same or
+///         nested wild card owner names permits multiple entities to exist
+///         that can create and delete names but can not effect RRs with
+///         different owner names from any they created.  In effect, this
+///         creates two levels of dynamic update key, strong and weak, where
+///         weak keys are limited in interfering with each other but a
+///         strong key can interfere with any weak keys or other strong
+///         keys.
+///
+///    Bit 2, unique name update - If nonzero, this key is authorized to add
+///         and update RRs for only a single owner name.  If there already
+///         exist RRs with one or more names signed by this key, they may be
+///         updated but no new name created until the number of existing
+///         names is reduced to zero.  This bit is meaningful only for mode
+///         A dynamic zones and is ignored in mode B dynamic zones. This bit
+///         is meaningful only if the owner name is a wildcard.  (Any
+///         dynamic update KEY with a non-wildcard name is, in effect, a
+///         unique name update key.)
+///
+///         This bit can be used to restrict a KEY from flooding a zone with
+///         new names.  In conjunction with a local administratively imposed
+///         limit on the number of dynamic RRs with a particular name, it
+///         can completely restrict a KEY from flooding a zone with RRs.
+///
+///    Bit 3, general update - The general update signatory field bit has no
+///         special meaning.  If the other three bits are all zero, it must
+///         be one so that the field is non-zero to designate that the key
+///         is an update key.  The meaning of all values of the signatory
+///         field with the general bit and one or more other signatory field
+///         bits on is reserved.
+///
+///    All the signatory bit update authorizations described above only
+///    apply if the update is within the name and class scope as per
+///    sections 3.1.1 and 3.1.2.
+/// ```
+///
+/// [RFC 3007](https://tools.ietf.org/html/rfc3007#section-1.5), Secure Dynamic Update, November 2000
+///
+/// ```text
+///    [RFC2535, section 3.1.2] defines the signatory field of a key as the
+///    final 4 bits of the flags field, but does not define its value.  This
+///    proposal leaves this field undefined.  Updating [RFC2535], this field
+///    SHOULD be set to 0 in KEY records, and MUST be ignored.
+///
+/// ```
+#[deprecated = "Deprecated by RFC3007"]
+#[allow(deprecated)]
+#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
+pub struct UpdateScope {
+    /// this key is authorized to attach,
+    ///   detach, and move zones by creating and deleting NS, glue A, and
+    ///   zone KEY RR(s)
+    pub zone: bool,
+    /// this key is authorized to add and
+    ///   delete RRs even if there are other RRs with the same owner name
+    ///   and class that are authenticated by a SIG signed with a
+    ///   different dynamic update KEY
+    pub strong: bool,
+    /// this key is authorized to add and update RRs for only a single owner name
+    pub unique: bool,
+    /// The general update signatory field bit has no special meaning, (true if the others are false)
+    pub general: bool,
+}
+
+#[allow(deprecated)]
+impl Default for UpdateScope {
+    fn default() -> Self {
+        UpdateScope {
+            zone: false,
+            strong: false,
+            unique: false,
+            general: false,
+        }
+    }
+}
+
+#[allow(deprecated)]
+impl From<u16> for UpdateScope {
+    fn from(flags: u16) -> Self {
+        // we only care about the final four bits, zero out the rest
+        UpdateScope {
+            //    Bit 0, zone control - If nonzero, this key is authorized to attach,
+            zone: flags & 0b0000_0000_0000_1000 != 0,
+            //    Bit 1, strong update - If nonzero, this key is authorized to add and
+            strong: flags & 0b0000_0000_0000_0100 != 0,
+            //    Bit 2, unique name update - If nonzero, this key is authorized to add
+            unique: flags & 0b0000_0000_0000_0010 != 0,
+            //    Bit 3, general update - The general update signatory field bit has no
+            general: flags & 0b0000_0000_0000_0001 != 0,
+        }
+    }
+}
+
+#[allow(deprecated)]
+impl From<UpdateScope> for u16 {
+    fn from(update_scope: UpdateScope) -> Self {
+        let mut flags = 0_u16;
+
+        if update_scope.zone {
+            flags |= 0b0000_0000_0000_1000;
+        }
+
+        if update_scope.strong {
+            flags |= 0b0000_0000_0000_0100;
+        }
+
+        if update_scope.unique {
+            flags |= 0b0000_0000_0000_0010;
+        }
+
+        if update_scope.general {
+            flags |= 0b0000_0000_0000_0001;
+        }
+
+        flags
+    }
+}
+
+#[test]
+#[allow(deprecated)]
+fn test_update_scope() {
+    assert_eq!(
+        UpdateScope::default(),
+        UpdateScope::from(u16::from(UpdateScope::default()))
+    );
+
+    let update_scope = UpdateScope {
+        zone: true,
+        strong: true,
+        unique: true,
+        general: true,
+    };
+    assert_eq!(update_scope, UpdateScope::from(u16::from(update_scope)));
+
+    let update_scope = UpdateScope {
+        zone: true,
+        strong: false,
+        unique: true,
+        general: false,
+    };
+    assert_eq!(update_scope, UpdateScope::from(u16::from(update_scope)));
+
+    let update_scope = UpdateScope {
+        zone: false,
+        strong: true,
+        unique: false,
+        general: true,
+    };
+    assert_eq!(update_scope, UpdateScope::from(u16::from(update_scope)));
+
+    let update_scope = UpdateScope {
+        zone: false,
+        strong: true,
+        unique: true,
+        general: false,
+    };
+    assert_eq!(update_scope, UpdateScope::from(u16::from(update_scope)));
+
+    let update_scope = UpdateScope {
+        zone: true,
+        strong: false,
+        unique: false,
+        general: true,
+    };
+    assert_eq!(update_scope, UpdateScope::from(u16::from(update_scope)));
+}
+
+/// [RFC 2535](https://tools.ietf.org/html/rfc2535#section-3.1.3), Domain Name System Security Extensions, March 1999
+///
+/// ```text
+/// 3.1.3 The Protocol Octet
+///
+///    It is anticipated that keys stored in DNS will be used in conjunction
+///    with a variety of Internet protocols.  It is intended that the
+///    protocol octet and possibly some of the currently unused (must be
+///    zero) bits in the KEY RR flags as specified in the future will be
+///    used to indicate a key's validity for different protocols.
+///
+///    The following values of the Protocol Octet are reserved as indicated:
+///
+///         VALUE   Protocol
+///
+///           0      -reserved
+///           1     TLS
+///           2     email
+///           3     dnssec
+///           4     IPSEC
+///          5-254   - available for assignment by IANA
+///          255     All
+///
+///    In more detail:
+///         1 is reserved for use in connection with TLS.
+///         2 is reserved for use in connection with email.
+///         3 is used for DNS security.  The protocol field SHOULD be set to
+///           this value for zone keys and other keys used in DNS security.
+///           Implementations that can determine that a key is a DNS
+///           security key by the fact that flags label it a zone key or the
+///           signatory flag field is non-zero are NOT REQUIRED to check the
+///           protocol field.
+///         4 is reserved to refer to the Oakley/IPSEC [RFC 2401] protocol
+///           and indicates that this key is valid for use in conjunction
+///           with that security standard.  This key could be used in
+///           connection with secured communication on behalf of an end
+///           entity or user whose name is the owner name of the KEY RR if
+///           the entity or user flag bits are set.  The presence of a KEY
+///           resource with this protocol value is an assertion that the
+///           host speaks Oakley/IPSEC.
+///         255 indicates that the key can be used in connection with any
+///           protocol for which KEY RR protocol octet values have been
+///           defined.  The use of this value is discouraged and the use of
+///           different keys for different protocols is encouraged.
+/// ```
+///
+/// [RFC3445](https://tools.ietf.org/html/rfc3445#section-4), Limiting the KEY Resource Record (RR), December 2002
+///
+/// ```text
+/// All Protocol Octet values except DNSSEC (3) are eliminated
+/// ```
+#[allow(deprecated)]
+#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
+pub enum Protocol {
+    /// Not in use
+    #[deprecated = "Deprecated by RFC3445"]
+    Reserved,
+    /// Reserved for use with TLS
+    #[deprecated = "Deprecated by RFC3445"]
+    TLS,
+    /// Reserved for use with email
+    #[deprecated = "Deprecated by RFC3445"]
+    Email,
+    /// Reserved for use with DNSSec (Trust-DNS only supports DNSKEY with DNSSec)
+    DNSSec,
+    /// Reserved to refer to the Oakley/IPSEC
+    #[deprecated = "Deprecated by RFC3445"]
+    IPSec,
+    /// Undefined
+    #[deprecated = "Deprecated by RFC3445"]
+    Other(u8),
+    /// the key can be used in connection with any protocol
+    #[deprecated = "Deprecated by RFC3445"]
+    All,
+}
+
+impl Default for Protocol {
+    fn default() -> Self {
+        Protocol::DNSSec
+    }
+}
+
+impl From<u8> for Protocol {
+    #[allow(deprecated)]
+    fn from(field: u8) -> Self {
+        match field {
+            0 => Protocol::Reserved,
+            1 => Protocol::TLS,
+            2 => Protocol::Email,
+            3 => Protocol::DNSSec,
+            4 => Protocol::IPSec,
+            255 => Protocol::All,
+            _ => Protocol::Other(field),
+        }
+    }
+}
+
+impl From<Protocol> for u8 {
+    #[allow(deprecated)]
+    fn from(protocol: Protocol) -> Self {
+        match protocol {
+            Protocol::Reserved => 0,
+            Protocol::TLS => 1,
+            Protocol::Email => 2,
+            Protocol::DNSSec => 3,
+            Protocol::IPSec => 4,
+            Protocol::All => 255,
+            Protocol::Other(field) => field,
+        }
+    }
+}
+
+impl KEY {
+    /// Construct a new KEY RData
+    ///
+    /// # Arguments
+    ///
+    /// * `key_trust` - declare the security level of this key
+    /// * `key_usage` - what type of thing is this key associated to
+    /// * `revoke` - this key has been revoked
+    /// * `algorithm` - specifies the algorithm which this Key uses to sign records
+    /// * `public_key` - the public key material, in native endian, the emitter will perform any necessary conversion
+    ///
+    /// # Return
+    ///
+    /// A new KEY RData for use in a Resource Record
+    #[allow(deprecated)]
+    pub fn new(
+        key_trust: KeyTrust,
+        key_usage: KeyUsage,
+        signatory: UpdateScope,
+        protocol: Protocol,
+        algorithm: Algorithm,
+        public_key: Vec<u8>,
+    ) -> KEY {
+        KEY {
+            key_trust,
+            key_usage,
+            signatory,
+            protocol,
+            algorithm,
+            public_key,
+        }
+    }
+
+    /// Returns the trust level of the key
+    pub fn key_trust(&self) -> KeyTrust {
+        self.key_trust
+    }
+
+    /// Returns the entity type using this key
+    pub fn key_usage(&self) -> KeyUsage {
+        self.key_usage
+    }
+
+    /// Returns the signatory information of the KEY
+    #[allow(deprecated)]
+    pub fn signatory(&self) -> UpdateScope {
+        self.signatory
+    }
+
+    /// Returns true if the key_trust is DoNotTrust
+    pub fn revoke(&self) -> bool {
+        self.key_trust == KeyTrust::DoNotTrust
+    }
+
+    /// Returns the protocol which this key can be used with
+    pub fn protocol(&self) -> Protocol {
+        self.protocol
+    }
+
+    /// [RFC 4034, DNSSEC Resource Records, March 2005](https://tools.ietf.org/html/rfc4034#section-2.1.3)
+    ///
+    /// ```text
+    /// 2.1.3.  The Algorithm Field
+    ///
+    ///    The Algorithm field identifies the public key's cryptographic
+    ///    algorithm and determines the format of the Public Key field.  A list
+    ///    of DNSSEC algorithm types can be found in Appendix A.1
+    /// ```
+    pub fn algorithm(&self) -> Algorithm {
+        self.algorithm
+    }
+
+    /// [RFC 4034, DNSSEC Resource Records, March 2005](https://tools.ietf.org/html/rfc4034#section-2.1.4)
+    ///
+    /// ```text
+    /// 2.1.4.  The Public Key Field
+    ///
+    ///    The Public Key Field holds the public key material.  The format
+    ///    depends on the algorithm of the key being stored and is described in
+    ///    separate documents.
+    /// ```
+    pub fn public_key(&self) -> &[u8] {
+        &self.public_key
+    }
+
+    // /// Creates a message digest for this KEY record.
+    // ///
+    // /// ```text
+    // /// 5.1.4.  The Digest Field
+    // ///
+    // ///    The DS record refers to a KEY RR by including a digest of that
+    // ///    KEY RR.
+    // ///
+    // ///    The digest is calculated by concatenating the canonical form of the
+    // ///    fully qualified owner name of the KEY RR with the KEY RDATA,
+    // ///    and then applying the digest algorithm.
+    // ///
+    // ///      digest = digest_algorithm( KEY owner name | KEY RDATA);
+    // ///
+    // ///       "|" denotes concatenation
+    // ///
+    // ///      KEY RDATA = Flags | Protocol | Algorithm | Public Key.
+    // ///
+    // ///    The size of the digest may vary depending on the digest algorithm and
+    // ///    KEY RR size.  As of the time of this writing, the only defined
+    // ///    digest algorithm is SHA-1, which produces a 20 octet digest.
+    // /// ```
+    // ///
+    // /// # Arguments
+    // ///
+    // /// * `name` - the label of of the KEY record.
+    // /// * `digest_type` - the `DigestType` with which to create the message digest.
+    // pub fn to_digest(&self, name: &Name, digest_type: DigestType) -> ProtoResult<Vec<u8>> {
+    //     let mut buf: Vec<u8> = Vec::new();
+    //     {
+    //         let mut encoder: BinEncoder = BinEncoder::new(&mut buf);
+    //         encoder.set_canonical_names(true);
+    //         if let Err(e) = name.emit(&mut encoder)
+    //                .and_then(|_| emit(&mut encoder, self)) {
+    //             warn!("error serializing KEY: {}", e);
+    //             return Err(format!("error serializing KEY: {}", e).into());
+    //         }
+    //     }
+
+    //     digest_type.hash(&buf).map_err(|e| e.into())
+    // }
+}
+
+impl From<KEY> for RData {
+    fn from(key: KEY) -> RData {
+        RData::DNSSEC(super::DNSSECRData::KEY(key))
+    }
+}
+
+/// Read the RData from the given Decoder
+#[allow(deprecated)]
+pub fn read(decoder: &mut BinDecoder, rdata_length: Restrict<u16>) -> ProtoResult<KEY> {
+    //      0   1   2   3   4   5   6   7   8   9   0   1   2   3   4   5
+    //    +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+    //    |  A/C  | Z | XT| Z | Z | NAMTYP| Z | Z | Z | Z |      SIG      |
+    //    +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+    let flags: u16 = decoder
+        .read_u16()?
+        .verify_unwrap(|flags| {
+            //    Bits 2 is reserved and must be zero.
+            //    Bits 4-5 are reserved and must be zero.
+            //    Bits 8-11 are reserved and must be zero.
+            flags & 0b0010_1100_1111_0000 == 0
+        })
+        .map_err(|_| ProtoError::from("flag 2, 4-5, and 8-11 are reserved, must be zero"))?;
+
+    let key_trust = KeyTrust::from(flags);
+    let extended_flags: bool = flags & 0b0001_0000_0000_0000 != 0;
+    let key_usage = KeyUsage::from(flags);
+    let signatory = UpdateScope::from(flags);
+
+    if extended_flags {
+        // TODO: add an optional field to return the raw u16?
+        return Err("extended flags currently not supported".into());
+    }
+
+    // TODO: protocol my be infallible
+    let protocol = Protocol::from(decoder.read_u8()?.unverified(/*Protocol is verified as safe*/));
+
+    let algorithm: Algorithm = Algorithm::read(decoder)?;
+
+    // the public key is the left-over bytes minus 4 for the first fields
+    // TODO: decode the key here?
+    let key_len = rdata_length
+        .map(|u| u as usize)
+        .checked_sub(4)
+        .map_err(|_| ProtoError::from("invalid rdata length in KEY"))?
+        .unverified(/*used only as length safely*/);
+    let public_key: Vec<u8> =
+        decoder.read_vec(key_len)?.unverified(/*the byte array will fail in usage if invalid*/);
+
+    Ok(KEY::new(
+        key_trust, key_usage, signatory, protocol, algorithm, public_key,
+    ))
+}
+
+/// Write the RData from the given Decoder
+pub fn emit(encoder: &mut BinEncoder, rdata: &KEY) -> ProtoResult<()> {
+    let mut flags: u16 = 0;
+    flags |= u16::from(rdata.key_trust);
+    flags |= u16::from(rdata.key_usage);
+    flags |= u16::from(rdata.signatory);
+
+    encoder.emit_u16(flags)?;
+    encoder.emit(u8::from(rdata.protocol))?;
+    rdata.algorithm().emit(encoder)?;
+    encoder.emit_vec(rdata.public_key())?;
+
+    Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+    #![allow(clippy::dbg_macro, clippy::print_stdout)]
+
+    use super::*;
+
+    #[test]
+    pub fn test() {
+        let rdata = KEY::new(
+            Default::default(),
+            Default::default(),
+            Default::default(),
+            Default::default(),
+            Algorithm::RSASHA256,
+            vec![0, 1, 2, 3, 4, 5, 6, 7],
+        );
+
+        let mut bytes = Vec::new();
+        let mut encoder: BinEncoder = BinEncoder::new(&mut bytes);
+        assert!(emit(&mut encoder, &rdata).is_ok());
+        let bytes = encoder.into_bytes();
+
+        println!("bytes: {:?}", bytes);
+
+        let mut decoder: BinDecoder = BinDecoder::new(bytes);
+        let restrict = Restrict::new(bytes.len() as u16);
+        let read_rdata = read(&mut decoder, restrict).expect("Decoding error");
+        assert_eq!(rdata, read_rdata);
+        // #[cfg(any(feature = "openssl", feature = "ring"))]
+        // assert!(rdata
+        //             .to_digest(&Name::parse("www.example.com.", None).unwrap(),
+        //                        DigestType::SHA256)
+        //             .is_ok());
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/rdata/mod.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/rdata/mod.rs
new file mode 100644
index 0000000..21f732c
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/rdata/mod.rs
@@ -0,0 +1,568 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! All record data structures and related serialization methods
+
+// TODO: these should each be it's own struct, it would make parsing and decoding a little cleaner
+//  and also a little more ergonomic when accessing.
+// each of these module's has the parser for that rdata embedded, to keep the file sizes down...
+pub mod dnskey;
+pub mod ds;
+pub mod key;
+pub mod nsec;
+pub mod nsec3;
+pub mod nsec3param;
+pub mod sig;
+
+use std::str::FromStr;
+
+use enum_as_inner::EnumAsInner;
+use log::debug;
+
+use crate::error::*;
+use crate::rr::rdata::null;
+use crate::rr::rdata::NULL;
+use crate::serialize::binary::*;
+
+pub use self::dnskey::DNSKEY;
+pub use self::ds::DS;
+pub use self::key::KEY;
+pub use self::nsec::NSEC;
+pub use self::nsec3::NSEC3;
+pub use self::nsec3param::NSEC3PARAM;
+pub use self::sig::SIG;
+
+/// The type of the resource record, for DNSSEC-specific records.
+#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
+pub enum DNSSECRecordType {
+    //  CDS,        //	59	RFC 7344	Child DS
+    //  CDNSKEY,    //	60	RFC 7344	Child DNSKEY
+    //  DLV,        //	32769	RFC 4431	DNSSEC Lookaside Validation record
+    /// RFC 4034	DNS Key record: RSASHA256 and RSASHA512, RFC5702
+    DNSKEY,
+    /// RFC 4034	Delegation signer: RSASHA256 and RSASHA512, RFC5702
+    DS,
+    /// RFC 2535[3] and RFC 2930[4]	Key record
+    KEY,
+    /// RFC 4034	Next-Secure record
+    NSEC,
+    /// RFC 5155	NSEC record version 3
+    NSEC3,
+    /// RFC 5155	NSEC3 parameters
+    NSEC3PARAM,
+    /// RFC 4034	DNSSEC signature: RSASHA256 and RSASHA512, RFC5702
+    RRSIG,
+    /// RFC 2535 (2931)	Signature, to support 2137 Update.
+    ///
+    /// This isn't really a DNSSEC record type, but it is here because, at least
+    /// for now, we enable/disable SIG(0) in exactly the same circumstances that
+    /// we enable/disable DNSSEC. This may change in the future.
+    SIG,
+    /// Unknown or not yet supported DNSSec record type
+    Unknown(u16),
+}
+
+impl FromStr for DNSSECRecordType {
+    type Err = ProtoError;
+
+    fn from_str(str: &str) -> ProtoResult<Self> {
+        match str {
+            "DNSKEY" => Ok(DNSSECRecordType::DNSKEY),
+            "DS" => Ok(DNSSECRecordType::DS),
+            "KEY" => Ok(DNSSECRecordType::KEY),
+            "NSEC" => Ok(DNSSECRecordType::NSEC),
+            "NSEC3" => Ok(DNSSECRecordType::NSEC3),
+            "NSEC3PARAM" => Ok(DNSSECRecordType::NSEC3PARAM),
+            "RRSIG" => Ok(DNSSECRecordType::RRSIG),
+            "SIG" => Ok(DNSSECRecordType::SIG),
+            _ => Err(ProtoErrorKind::UnknownRecordTypeStr(str.to_string()).into()),
+        }
+    }
+}
+
+impl From<u16> for DNSSECRecordType {
+    fn from(value: u16) -> Self {
+        match value {
+            48 => DNSSECRecordType::DNSKEY,
+            43 => DNSSECRecordType::DS,
+            25 => DNSSECRecordType::KEY,
+            47 => DNSSECRecordType::NSEC,
+            50 => DNSSECRecordType::NSEC3,
+            51 => DNSSECRecordType::NSEC3PARAM,
+            46 => DNSSECRecordType::RRSIG,
+            24 => DNSSECRecordType::SIG,
+            _ => DNSSECRecordType::Unknown(value),
+        }
+    }
+}
+
+impl From<DNSSECRecordType> for &'static str {
+    fn from(rt: DNSSECRecordType) -> &'static str {
+        match rt {
+            DNSSECRecordType::DNSKEY => "DNSKEY",
+            DNSSECRecordType::DS => "DS",
+            DNSSECRecordType::KEY => "KEY",
+            DNSSECRecordType::NSEC => "NSEC",
+            DNSSECRecordType::NSEC3 => "NSEC3",
+            DNSSECRecordType::NSEC3PARAM => "NSEC3PARAM",
+            DNSSECRecordType::RRSIG => "RRSIG",
+            DNSSECRecordType::SIG => "SIG",
+            DNSSECRecordType::Unknown(..) => "DnsSecUnknown",
+        }
+    }
+}
+
+impl From<DNSSECRecordType> for u16 {
+    fn from(rt: DNSSECRecordType) -> Self {
+        match rt {
+            DNSSECRecordType::KEY => 25,
+            DNSSECRecordType::DNSKEY => 48,
+            DNSSECRecordType::DS => 43,
+            DNSSECRecordType::NSEC => 47,
+            DNSSECRecordType::NSEC3 => 50,
+            DNSSECRecordType::NSEC3PARAM => 51,
+            DNSSECRecordType::RRSIG => 46,
+            DNSSECRecordType::SIG => 24,
+            DNSSECRecordType::Unknown(value) => value,
+        }
+    }
+}
+
+/// Record data enum variants for DNSSEC-specific records.
+#[derive(Debug, EnumAsInner, PartialEq, Clone, Eq)]
+pub enum DNSSECRData {
+    /// ```text
+    /// RFC 4034                DNSSEC Resource Records               March 2005
+    ///
+    /// 2.1.  DNSKEY RDATA Wire Format
+    ///
+    ///    The RDATA for a DNSKEY RR consists of a 2 octet Flags Field, a 1
+    ///    octet Protocol Field, a 1 octet Algorithm Field, and the Public Key
+    ///    Field.
+    ///
+    ///                         1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+    ///     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+    ///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    ///    |              Flags            |    Protocol   |   Algorithm   |
+    ///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    ///    /                                                               /
+    ///    /                            Public Key                         /
+    ///    /                                                               /
+    ///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    ///
+    /// 2.1.1.  The Flags Field
+    ///
+    ///    Bit 7 of the Flags field is the Zone Key flag.  If bit 7 has value 1,
+    ///    then the DNSKEY record holds a DNS zone key, and the DNSKEY RR's
+    ///    owner name MUST be the name of a zone.  If bit 7 has value 0, then
+    ///    the DNSKEY record holds some other type of DNS public key and MUST
+    ///    NOT be used to verify RRSIGs that cover RRsets.
+    ///
+    ///    Bit 15 of the Flags field is the Secure Entry Point flag, described
+    ///    in [RFC3757].  If bit 15 has value 1, then the DNSKEY record holds a
+    ///    key intended for use as a secure entry point.  This flag is only
+    ///    intended to be a hint to zone signing or debugging software as to the
+    ///    intended use of this DNSKEY record; validators MUST NOT alter their
+    ///    behavior during the signature validation process in any way based on
+    ///    the setting of this bit.  This also means that a DNSKEY RR with the
+    ///    SEP bit set would also need the Zone Key flag set in order to be able
+    ///    to generate signatures legally.  A DNSKEY RR with the SEP set and the
+    ///    Zone Key flag not set MUST NOT be used to verify RRSIGs that cover
+    ///    RRsets.
+    ///
+    ///    Bits 0-6 and 8-14 are reserved: these bits MUST have value 0 upon
+    ///    creation of the DNSKEY RR and MUST be ignored upon receipt.
+    ///
+    /// RFC 5011                  Trust Anchor Update             September 2007
+    ///
+    /// 7.  IANA Considerations
+    ///
+    ///   The IANA has assigned a bit in the DNSKEY flags field (see Section 7
+    ///   of [RFC4034]) for the REVOKE bit (8).
+    /// ```
+    DNSKEY(DNSKEY),
+
+    /// ```text
+    /// 5.1.  DS RDATA Wire Format
+    ///
+    /// The RDATA for a DS RR consists of a 2 octet Key Tag field, a 1 octet
+    ///           Algorithm field, a 1 octet Digest Type field, and a Digest field.
+    ///
+    ///                          1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+    ///      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+    ///     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    ///     |           Key Tag             |  Algorithm    |  Digest Type  |
+    ///     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    ///     /                                                               /
+    ///     /                            Digest                             /
+    ///     /                                                               /
+    ///     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    ///
+    /// 5.1.1.  The Key Tag Field
+    ///
+    ///    The Key Tag field lists the key tag of the DNSKEY RR referred to by
+    ///    the DS record, in network byte order.
+    ///
+    ///    The Key Tag used by the DS RR is identical to the Key Tag used by
+    ///    RRSIG RRs.  Appendix B describes how to compute a Key Tag.
+    ///
+    /// 5.1.2.  The Algorithm Field
+    ///
+    ///    The Algorithm field lists the algorithm number of the DNSKEY RR
+    ///    referred to by the DS record.
+    ///
+    ///    The algorithm number used by the DS RR is identical to the algorithm
+    ///    number used by RRSIG and DNSKEY RRs.  Appendix A.1 lists the
+    ///    algorithm number types.
+    ///
+    /// 5.1.3.  The Digest Type Field
+    ///
+    ///    The DS RR refers to a DNSKEY RR by including a digest of that DNSKEY
+    ///    RR.  The Digest Type field identifies the algorithm used to construct
+    ///    the digest.  Appendix A.2 lists the possible digest algorithm types.
+    ///
+    /// 5.1.4.  The Digest Field
+    ///
+    ///    The DS record refers to a DNSKEY RR by including a digest of that
+    ///    DNSKEY RR.
+    ///
+    ///    The digest is calculated by concatenating the canonical form of the
+    ///    fully qualified owner name of the DNSKEY RR with the DNSKEY RDATA,
+    ///    and then applying the digest algorithm.
+    ///
+    ///      digest = digest_algorithm( DNSKEY owner name | DNSKEY RDATA);
+    ///
+    ///       "|" denotes concatenation
+    ///
+    ///      DNSKEY RDATA = Flags | Protocol | Algorithm | Public Key.
+    ///
+    ///    The size of the digest may vary depending on the digest algorithm and
+    ///    DNSKEY RR size.  As of the time of this writing, the only defined
+    ///    digest algorithm is SHA-1, which produces a 20 octet digest.
+    /// ```
+    DS(DS),
+
+    /// ```text
+    /// RFC 2535                DNS Security Extensions               March 1999
+    ///
+    /// 3.1 KEY RDATA format
+    ///
+    ///  The RDATA for a KEY RR consists of flags, a protocol octet, the
+    ///  algorithm number octet, and the public key itself.  The format is as
+    ///  follows:
+    ///
+    ///                       1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+    ///   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+    ///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    ///  |             flags             |    protocol   |   algorithm   |
+    ///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    ///  |                                                               /
+    ///  /                          public key                           /
+    ///  /                                                               /
+    ///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
+    ///
+    ///  The KEY RR is not intended for storage of certificates and a separate
+    ///  certificate RR has been developed for that purpose, defined in [RFC
+    ///  2538].
+    ///
+    ///  The meaning of the KEY RR owner name, flags, and protocol octet are
+    ///  described in Sections 3.1.1 through 3.1.5 below.  The flags and
+    ///  algorithm must be examined before any data following the algorithm
+    ///  octet as they control the existence and format of any following data.
+    ///  The algorithm and public key fields are described in Section 3.2.
+    ///  The format of the public key is algorithm dependent.
+    ///
+    ///  KEY RRs do not specify their validity period but their authenticating
+    ///  SIG RR(s) do as described in Section 4 below.
+    /// ```
+    KEY(KEY),
+
+    /// ```text
+    /// RFC 4034                DNSSEC Resource Records               March 2005
+    ///
+    /// 4.1.  NSEC RDATA Wire Format
+    ///
+    ///  The RDATA of the NSEC RR is as shown below:
+    ///
+    ///                       1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+    ///   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+    ///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    ///  /                      Next Domain Name                         /
+    ///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    ///  /                       Type Bit Maps                           /
+    ///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    /// ```
+    NSEC(NSEC),
+
+    /// ```text
+    /// RFC 5155                         NSEC3                        March 2008
+    ///
+    /// 3.2.  NSEC3 RDATA Wire Format
+    ///
+    ///  The RDATA of the NSEC3 RR is as shown below:
+    ///
+    ///                       1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+    ///   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+    ///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    ///  |   Hash Alg.   |     Flags     |          Iterations           |
+    ///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    ///  |  Salt Length  |                     Salt                      /
+    ///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    ///  |  Hash Length  |             Next Hashed Owner Name            /
+    ///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    ///  /                         Type Bit Maps                         /
+    ///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    ///
+    ///  Hash Algorithm is a single octet.
+    ///
+    ///  Flags field is a single octet, the Opt-Out flag is the least
+    ///  significant bit, as shown below:
+    ///
+    ///   0 1 2 3 4 5 6 7
+    ///  +-+-+-+-+-+-+-+-+
+    ///  |             |O|
+    ///  +-+-+-+-+-+-+-+-+
+    ///
+    ///  Iterations is represented as a 16-bit unsigned integer, with the most
+    ///  significant bit first.
+    ///
+    ///  Salt Length is represented as an unsigned octet.  Salt Length
+    ///  represents the length of the Salt field in octets.  If the value is
+    ///  zero, the following Salt field is omitted.
+    ///
+    ///  Salt, if present, is encoded as a sequence of binary octets.  The
+    ///  length of this field is determined by the preceding Salt Length
+    ///  field.
+    ///
+    ///  Hash Length is represented as an unsigned octet.  Hash Length
+    ///  represents the length of the Next Hashed Owner Name field in octets.
+    ///
+    ///  The next hashed owner name is not base32 encoded, unlike the owner
+    ///  name of the NSEC3 RR.  It is the unmodified binary hash value.  It
+    ///  does not include the name of the containing zone.  The length of this
+    ///  field is determined by the preceding Hash Length field.
+    ///
+    /// 3.2.1.  Type Bit Maps Encoding
+    ///
+    ///  The encoding of the Type Bit Maps field is the same as that used by
+    ///  the NSEC RR, described in [RFC4034].  It is explained and clarified
+    ///  here for clarity.
+    ///
+    ///  The RR type space is split into 256 window blocks, each representing
+    ///  the low-order 8 bits of the 16-bit RR type space.  Each block that
+    ///  has at least one active RR type is encoded using a single octet
+    ///  window number (from 0 to 255), a single octet bitmap length (from 1
+    ///  to 32) indicating the number of octets used for the bitmap of the
+    ///  window block, and up to 32 octets (256 bits) of bitmap.
+    ///
+    ///  Blocks are present in the NSEC3 RR RDATA in increasing numerical
+    ///  order.
+    ///
+    ///     Type Bit Maps Field = ( Window Block # | Bitmap Length | Bitmap )+
+    ///
+    ///     where "|" denotes concatenation.
+    ///
+    ///  Each bitmap encodes the low-order 8 bits of RR types within the
+    ///  window block, in network bit order.  The first bit is bit 0.  For
+    ///  window block 0, bit 1 corresponds to RR type 1 (A), bit 2 corresponds
+    ///  to RR type 2 (NS), and so forth.  For window block 1, bit 1
+    ///  corresponds to RR type 257, bit 2 to RR type 258.  If a bit is set to
+    ///  1, it indicates that an RRSet of that type is present for the
+    ///  original owner name of the NSEC3 RR.  If a bit is set to 0, it
+    ///  indicates that no RRSet of that type is present for the original
+    ///  owner name of the NSEC3 RR.
+    ///
+    ///  Since bit 0 in window block 0 refers to the non-existing RR type 0,
+    ///  it MUST be set to 0.  After verification, the validator MUST ignore
+    ///  the value of bit 0 in window block 0.
+    ///
+    ///  Bits representing Meta-TYPEs or QTYPEs as specified in Section 3.1 of
+    ///  [RFC2929] or within the range reserved for assignment only to QTYPEs
+    ///  and Meta-TYPEs MUST be set to 0, since they do not appear in zone
+    ///  data.  If encountered, they must be ignored upon reading.
+    ///
+    ///  Blocks with no types present MUST NOT be included.  Trailing zero
+    ///  octets in the bitmap MUST be omitted.  The length of the bitmap of
+    ///  each block is determined by the type code with the largest numerical
+    ///  value, within that block, among the set of RR types present at the
+    ///  original owner name of the NSEC3 RR.  Trailing octets not specified
+    ///  MUST be interpreted as zero octets.
+    /// ```
+    NSEC3(NSEC3),
+
+    /// ```text
+    /// RFC 5155                         NSEC3                        March 2008
+    ///
+    /// 4.2.  NSEC3PARAM RDATA Wire Format
+    ///
+    ///  The RDATA of the NSEC3PARAM RR is as shown below:
+    ///
+    ///                       1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+    ///   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+    ///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    ///  |   Hash Alg.   |     Flags     |          Iterations           |
+    ///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    ///  |  Salt Length  |                     Salt                      /
+    ///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    ///
+    ///  Hash Algorithm is a single octet.
+    ///
+    ///  Flags field is a single octet.
+    ///
+    ///  Iterations is represented as a 16-bit unsigned integer, with the most
+    ///  significant bit first.
+    ///
+    ///  Salt Length is represented as an unsigned octet.  Salt Length
+    ///  represents the length of the following Salt field in octets.  If the
+    ///  value is zero, the Salt field is omitted.
+    ///
+    ///  Salt, if present, is encoded as a sequence of binary octets.  The
+    ///  length of this field is determined by the preceding Salt Length
+    ///  field.
+    /// ```
+    NSEC3PARAM(NSEC3PARAM),
+
+    /// ```text
+    /// RFC 2535 & 2931   DNS Security Extensions               March 1999
+    /// RFC 4034          DNSSEC Resource Records               March 2005
+    ///
+    /// 3.1.  RRSIG RDATA Wire Format
+    ///
+    ///    The RDATA for an RRSIG RR consists of a 2 octet Type Covered field, a
+    ///    1 octet Algorithm field, a 1 octet Labels field, a 4 octet Original
+    ///    TTL field, a 4 octet Signature Expiration field, a 4 octet Signature
+    ///    Inception field, a 2 octet Key tag, the Signer's Name field, and the
+    ///    Signature field.
+    ///
+    ///                         1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+    ///     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+    ///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    ///    |        Type Covered           |  Algorithm    |     Labels    |
+    ///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    ///    |                         Original TTL                          |
+    ///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    ///    |                      Signature Expiration                     |
+    ///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    ///    |                      Signature Inception                      |
+    ///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    ///    |            Key Tag            |                               /
+    ///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+         Signer's Name         /
+    ///    /                                                               /
+    ///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    ///    /                                                               /
+    ///    /                            Signature                          /
+    ///    /                                                               /
+    ///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    /// ```
+    SIG(SIG),
+
+    /// Unknown or unsupported DNSSec record data
+    Unknown {
+        /// RecordType code
+        code: u16,
+        /// RData associated to the record
+        rdata: NULL,
+    },
+}
+
+impl DNSSECRData {
+    pub(crate) fn read(
+        decoder: &mut BinDecoder,
+        record_type: DNSSECRecordType,
+        rdata_length: Restrict<u16>,
+    ) -> ProtoResult<Self> {
+        match record_type {
+            DNSSECRecordType::DNSKEY => {
+                debug!("reading DNSKEY");
+                dnskey::read(decoder, rdata_length).map(DNSSECRData::DNSKEY)
+            }
+            DNSSECRecordType::DS => {
+                debug!("reading DS");
+                ds::read(decoder, rdata_length).map(DNSSECRData::DS)
+            }
+            DNSSECRecordType::KEY => {
+                debug!("reading KEY");
+                key::read(decoder, rdata_length).map(DNSSECRData::KEY)
+            }
+            DNSSECRecordType::NSEC => {
+                debug!("reading NSEC");
+                nsec::read(decoder, rdata_length).map(DNSSECRData::NSEC)
+            }
+            DNSSECRecordType::NSEC3 => {
+                debug!("reading NSEC3");
+                nsec3::read(decoder, rdata_length).map(DNSSECRData::NSEC3)
+            }
+            DNSSECRecordType::NSEC3PARAM => {
+                debug!("reading NSEC3PARAM");
+                nsec3param::read(decoder).map(DNSSECRData::NSEC3PARAM)
+            }
+            DNSSECRecordType::RRSIG => {
+                debug!("reading RRSIG");
+                sig::read(decoder, rdata_length).map(DNSSECRData::SIG)
+            }
+            DNSSECRecordType::SIG => {
+                debug!("reading SIG");
+                sig::read(decoder, rdata_length).map(DNSSECRData::SIG)
+            }
+            DNSSECRecordType::Unknown(code) => {
+                debug!("reading unknown dnssec: {}", code);
+                null::read(decoder, rdata_length).map(|rdata| DNSSECRData::Unknown { code, rdata })
+            }
+        }
+    }
+
+    pub(crate) fn emit(&self, encoder: &mut BinEncoder) -> ProtoResult<()> {
+        match *self {
+            DNSSECRData::DS(ref ds) => {
+                encoder.with_canonical_names(|encoder| ds::emit(encoder, ds))
+            }
+            DNSSECRData::KEY(ref key) => {
+                encoder.with_canonical_names(|encoder| key::emit(encoder, key))
+            }
+            DNSSECRData::DNSKEY(ref dnskey) => {
+                encoder.with_canonical_names(|encoder| dnskey::emit(encoder, dnskey))
+            }
+            DNSSECRData::NSEC(ref nsec) => {
+                encoder.with_canonical_names(|encoder| nsec::emit(encoder, nsec))
+            }
+            DNSSECRData::NSEC3(ref nsec3) => {
+                encoder.with_canonical_names(|encoder| nsec3::emit(encoder, nsec3))
+            }
+            DNSSECRData::NSEC3PARAM(ref nsec3param) => {
+                encoder.with_canonical_names(|encoder| nsec3param::emit(encoder, nsec3param))
+            }
+            DNSSECRData::SIG(ref sig) => {
+                encoder.with_canonical_names(|encoder| sig::emit(encoder, sig))
+            }
+            DNSSECRData::Unknown { ref rdata, .. } => {
+                encoder.with_canonical_names(|encoder| null::emit(encoder, rdata))
+            }
+        }
+    }
+
+    pub(crate) fn to_record_type(&self) -> DNSSECRecordType {
+        match *self {
+            DNSSECRData::DS(..) => DNSSECRecordType::DS,
+            DNSSECRData::KEY(..) => DNSSECRecordType::KEY,
+            DNSSECRData::DNSKEY(..) => DNSSECRecordType::DNSKEY,
+            DNSSECRData::NSEC(..) => DNSSECRecordType::NSEC,
+            DNSSECRData::NSEC3(..) => DNSSECRecordType::NSEC3,
+            DNSSECRData::NSEC3PARAM(..) => DNSSECRecordType::NSEC3PARAM,
+            DNSSECRData::SIG(..) => DNSSECRecordType::SIG,
+            DNSSECRData::Unknown { code, .. } => DNSSECRecordType::Unknown(code),
+        }
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/rdata/nsec.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/rdata/nsec.rs
new file mode 100644
index 0000000..873b73e
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/rdata/nsec.rs
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! negative cache proof for non-existence
+
+use super::nsec3;
+use crate::error::*;
+use crate::rr::dnssec::rdata::DNSSECRecordType;
+use crate::rr::{Name, RecordType};
+use crate::serialize::binary::*;
+
+/// [RFC 4034, DNSSEC Resource Records, March 2005](https://tools.ietf.org/html/rfc4034#section-4)
+///
+/// ```text
+/// 4.1.  NSEC RDATA Wire Format
+///
+///    The RDATA of the NSEC RR is as shown below:
+///
+///                         1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+///     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+///    /                      Next Domain Name                         /
+///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+///    /                       Type Bit Maps                           /
+///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+///
+/// 4.1.3.  Inclusion of Wildcard Names in NSEC RDATA
+///
+///    If a wildcard owner name appears in a zone, the wildcard label ("*")
+///    is treated as a literal symbol and is treated the same as any other
+///    owner name for the purposes of generating NSEC RRs.  Wildcard owner
+///    names appear in the Next Domain Name field without any wildcard
+///    expansion.  [RFC4035] describes the impact of wildcards on
+///    authenticated denial of existence.
+/// ```
+#[derive(Debug, PartialEq, Eq, Hash, Clone)]
+pub struct NSEC {
+    next_domain_name: Name,
+    type_bit_maps: Vec<RecordType>,
+}
+
+impl NSEC {
+    /// Constructs a new NSEC RData, warning this won't guarantee that the NSEC covers itself
+    ///  which it should at it's own name.
+    ///
+    /// # Arguments
+    ///
+    /// * `next_domain_name` - the name labels of the next ordered name in the zone
+    /// * `type_bit_maps` - a bit map of the types that exist at this name
+    ///
+    /// # Returns
+    ///
+    /// An NSEC RData for use in a Resource Record
+    pub fn new(next_domain_name: Name, type_bit_maps: Vec<RecordType>) -> NSEC {
+        NSEC {
+            next_domain_name,
+            type_bit_maps,
+        }
+    }
+
+    /// Constructs a new NSEC RData, this will add the NSEC itself as covered, generally
+    ///   correct for NSEC records generated at their own name
+    ///
+    /// # Arguments
+    ///
+    /// * `next_domain_name` - the name labels of the next ordered name in the zone
+    /// * `type_bit_maps` - a bit map of the types that exist at this name
+    ///
+    /// # Returns
+    ///
+    /// An NSEC RData for use in a Resource Record
+    pub fn new_cover_self(next_domain_name: Name, mut type_bit_maps: Vec<RecordType>) -> NSEC {
+        type_bit_maps.push(RecordType::DNSSEC(DNSSECRecordType::NSEC));
+
+        Self::new(next_domain_name, type_bit_maps)
+    }
+
+    /// [RFC 4034, DNSSEC Resource Records, March 2005](https://tools.ietf.org/html/rfc4034#section-4.1.1)
+    ///
+    /// ```text
+    /// 4.1.1.  The Next Domain Name Field
+    ///
+    ///    The Next Domain field contains the next owner name (in the canonical
+    ///    ordering of the zone) that has authoritative data or contains a
+    ///    delegation point NS RRset; see Section 6.1 for an explanation of
+    ///    canonical ordering.  The value of the Next Domain Name field in the
+    ///    last NSEC record in the zone is the name of the zone apex (the owner
+    ///    name of the zone's SOA RR).  This indicates that the owner name of
+    ///    the NSEC RR is the last name in the canonical ordering of the zone.
+    ///
+    ///    A sender MUST NOT use DNS name compression on the Next Domain Name
+    ///    field when transmitting an NSEC RR.
+    ///
+    ///    Owner names of RRsets for which the given zone is not authoritative
+    ///    (such as glue records) MUST NOT be listed in the Next Domain Name
+    ///    unless at least one authoritative RRset exists at the same owner
+    ///    name.
+    /// ```
+    pub fn next_domain_name(&self) -> &Name {
+        &self.next_domain_name
+    }
+
+    /// [RFC 4034, DNSSEC Resource Records, March 2005](https://tools.ietf.org/html/rfc4034#section-4.1.2)
+    ///
+    /// ```text
+    /// 4.1.2.  The Type Bit Maps Field
+    ///
+    ///    The Type Bit Maps field identifies the RRset types that exist at the
+    ///    NSEC RR's owner name.
+    ///
+    ///    A zone MUST NOT include an NSEC RR for any domain name that only
+    ///    holds glue records.
+    /// ```
+    pub fn type_bit_maps(&self) -> &[RecordType] {
+        &self.type_bit_maps
+    }
+}
+
+/// Read the RData from the given Decoder
+pub fn read(decoder: &mut BinDecoder, rdata_length: Restrict<u16>) -> ProtoResult<NSEC> {
+    let start_idx = decoder.index();
+
+    let next_domain_name = Name::read(decoder)?;
+
+    let bit_map_len = rdata_length
+        .map(|u| u as usize)
+        .checked_sub(decoder.index() - start_idx)
+        .map_err(|_| ProtoError::from("invalid rdata length in NSEC"))?;
+    let record_types = nsec3::decode_type_bit_maps(decoder, bit_map_len)?;
+
+    Ok(NSEC::new(next_domain_name, record_types))
+}
+
+/// [RFC 6840](https://tools.ietf.org/html/rfc6840#section-6)
+///
+/// ```text
+/// 5.1.  Errors in Canonical Form Type Code List
+///
+///   When canonicalizing DNS names (for both ordering and signing), DNS
+///   names in the RDATA section of NSEC resource records are not converted
+///   to lowercase.  DNS names in the RDATA section of RRSIG resource
+///   records are converted to lowercase.
+/// ```
+pub fn emit(encoder: &mut BinEncoder, rdata: &NSEC) -> ProtoResult<()> {
+    encoder.with_canonical_names(|encoder| {
+        rdata.next_domain_name().emit(encoder)?;
+        nsec3::encode_bit_maps(encoder, rdata.type_bit_maps())
+    })
+}
+
+#[cfg(test)]
+mod tests {
+    #![allow(clippy::dbg_macro, clippy::print_stdout)]
+
+    use super::*;
+
+    #[test]
+    pub fn test() {
+        use crate::rr::dnssec::rdata::DNSSECRecordType;
+        use crate::rr::RecordType;
+        use std::str::FromStr;
+
+        let rdata = NSEC::new(
+            Name::from_str("www.example.com").unwrap(),
+            vec![
+                RecordType::A,
+                RecordType::AAAA,
+                RecordType::DNSSEC(DNSSECRecordType::DS),
+                RecordType::DNSSEC(DNSSECRecordType::RRSIG),
+            ],
+        );
+
+        let mut bytes = Vec::new();
+        let mut encoder: BinEncoder = BinEncoder::new(&mut bytes);
+        assert!(emit(&mut encoder, &rdata).is_ok());
+        let bytes = encoder.into_bytes();
+
+        println!("bytes: {:?}", bytes);
+
+        let mut decoder: BinDecoder = BinDecoder::new(bytes);
+        let restrict = Restrict::new(bytes.len() as u16);
+        let read_rdata = read(&mut decoder, restrict).expect("Decoding error");
+        assert_eq!(rdata, read_rdata);
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/rdata/nsec3.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/rdata/nsec3.rs
new file mode 100644
index 0000000..ce25861
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/rdata/nsec3.rs
@@ -0,0 +1,576 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! hashed negative cache proof for non-existence
+
+use std::collections::BTreeMap;
+
+use crate::error::*;
+use crate::rr::dnssec::Nsec3HashAlgorithm;
+use crate::rr::RecordType;
+use crate::serialize::binary::*;
+
+/// [RFC 5155, NSEC3, March 2008](https://tools.ietf.org/html/rfc5155#section-3)
+///
+/// ```text
+/// 3.  The NSEC3 Resource Record
+///
+///    The NSEC3 Resource Record (RR) provides authenticated denial of
+///    existence for DNS Resource Record Sets.
+///
+///    The NSEC3 RR lists RR types present at the original owner name of the
+///    NSEC3 RR.  It includes the next hashed owner name in the hash order
+///    of the zone.  The complete set of NSEC3 RRs in a zone indicates which
+///    RRSets exist for the original owner name of the RR and form a chain
+///    of hashed owner names in the zone.  This information is used to
+///    provide authenticated denial of existence for DNS data.  To provide
+///    protection against zone enumeration, the owner names used in the
+///    NSEC3 RR are cryptographic hashes of the original owner name
+///    prepended as a single label to the name of the zone.  The NSEC3 RR
+///    indicates which hash function is used to construct the hash, which
+///    salt is used, and how many iterations of the hash function are
+///    performed over the original owner name.  The hashing technique is
+///    described fully in Section 5.
+///
+///    Hashed owner names of unsigned delegations may be excluded from the
+///    chain.  An NSEC3 RR whose span covers the hash of an owner name or
+///    "next closer" name of an unsigned delegation is referred to as an
+///    Opt-Out NSEC3 RR and is indicated by the presence of a flag.
+///
+///    The owner name for the NSEC3 RR is the base32 encoding of the hashed
+///    owner name prepended as a single label to the name of the zone.
+///
+///    The type value for the NSEC3 RR is 50.
+///
+///    The NSEC3 RR RDATA format is class independent and is described
+///    below.
+///
+///    The class MUST be the same as the class of the original owner name.
+///
+///    The NSEC3 RR SHOULD have the same TTL value as the SOA minimum TTL
+///    field.  This is in the spirit of negative caching [RFC2308].
+///
+/// 3.2.  NSEC3 RDATA Wire Format
+///
+///  The RDATA of the NSEC3 RR is as shown below:
+///
+///                       1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+///   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+///  |   Hash Alg.   |     Flags     |          Iterations           |
+///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+///  |  Salt Length  |                     Salt                      /
+///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+///  |  Hash Length  |             Next Hashed Owner Name            /
+///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+///  /                         Type Bit Maps                         /
+///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+///
+///  Hash Algorithm is a single octet.
+///
+///  Flags field is a single octet, the Opt-Out flag is the least
+///  significant bit, as shown below:
+///
+///   0 1 2 3 4 5 6 7
+///  +-+-+-+-+-+-+-+-+
+///  |             |O|
+///  +-+-+-+-+-+-+-+-+
+///
+///  Iterations is represented as a 16-bit unsigned integer, with the most
+///  significant bit first.
+///
+///  Salt Length is represented as an unsigned octet.  Salt Length
+///  represents the length of the Salt field in octets.  If the value is
+///  zero, the following Salt field is omitted.
+///
+///  Salt, if present, is encoded as a sequence of binary octets.  The
+///  length of this field is determined by the preceding Salt Length
+///  field.
+///
+///  Hash Length is represented as an unsigned octet.  Hash Length
+///  represents the length of the Next Hashed Owner Name field in octets.
+///
+///  The next hashed owner name is not base32 encoded, unlike the owner
+///  name of the NSEC3 RR.  It is the unmodified binary hash value.  It
+///  does not include the name of the containing zone.  The length of this
+///  field is determined by the preceding Hash Length field.
+/// ```
+#[derive(Debug, PartialEq, Eq, Hash, Clone)]
+pub struct NSEC3 {
+    hash_algorithm: Nsec3HashAlgorithm,
+    opt_out: bool,
+    iterations: u16,
+    salt: Vec<u8>,
+    next_hashed_owner_name: Vec<u8>,
+    type_bit_maps: Vec<RecordType>,
+}
+
+impl NSEC3 {
+    /// Constructs a new NSEC3 record
+    pub fn new(
+        hash_algorithm: Nsec3HashAlgorithm,
+        opt_out: bool,
+        iterations: u16,
+        salt: Vec<u8>,
+        next_hashed_owner_name: Vec<u8>,
+        type_bit_maps: Vec<RecordType>,
+    ) -> NSEC3 {
+        NSEC3 {
+            hash_algorithm,
+            opt_out,
+            iterations,
+            salt,
+            next_hashed_owner_name,
+            type_bit_maps,
+        }
+    }
+
+    /// [RFC 5155, NSEC3, March 2008](https://tools.ietf.org/html/rfc5155#section-3.1.1)
+    ///
+    /// ```text
+    /// 3.1.1.  Hash Algorithm
+    ///
+    ///    The Hash Algorithm field identifies the cryptographic hash algorithm
+    ///    used to construct the hash-value.
+    ///
+    ///    The values for this field are defined in the NSEC3 hash algorithm
+    ///    registry defined in Section 11.
+    /// ```
+    pub fn hash_algorithm(&self) -> Nsec3HashAlgorithm {
+        self.hash_algorithm
+    }
+
+    /// [RFC 5155, NSEC3, March 2008](https://tools.ietf.org/html/rfc5155#section-3.1.2)
+    ///
+    /// ```text
+    /// 3.1.2.  Flags
+    ///
+    ///    The Flags field contains 8 one-bit flags that can be used to indicate
+    ///    different processing.  All undefined flags must be zero.  The only
+    ///    flag defined by this specification is the Opt-Out flag.
+    ///
+    /// 3.1.2.1.  Opt-Out Flag
+    ///
+    ///    If the Opt-Out flag is set, the NSEC3 record covers zero or more
+    ///    unsigned delegations.
+    ///
+    ///    If the Opt-Out flag is clear, the NSEC3 record covers zero unsigned
+    ///    delegations.
+    ///
+    ///    The Opt-Out Flag indicates whether this NSEC3 RR may cover unsigned
+    ///    delegations.  It is the least significant bit in the Flags field.
+    ///    See Section 6 for details about the use of this flag.
+    /// ```
+    pub fn opt_out(&self) -> bool {
+        self.opt_out
+    }
+
+    /// [RFC 5155, NSEC3, March 2008](https://tools.ietf.org/html/rfc5155#section-3.1.3)
+    ///
+    /// ```text
+    /// 3.1.3.  Iterations
+    ///
+    ///    The Iterations field defines the number of additional times the hash
+    ///    function has been performed.  More iterations result in greater
+    ///    resiliency of the hash value against dictionary attacks, but at a
+    ///    higher computational cost for both the server and resolver.  See
+    ///    Section 5 for details of the use of this field, and Section 10.3 for
+    ///    limitations on the value.
+    /// ```
+    pub fn iterations(&self) -> u16 {
+        self.iterations
+    }
+
+    /// [RFC 5155, NSEC3, March 2008](https://tools.ietf.org/html/rfc5155#section-3.1.5)
+    ///
+    /// ```text
+    /// 3.1.5.  Salt
+    ///
+    ///    The Salt field is appended to the original owner name before hashing
+    ///    in order to defend against pre-calculated dictionary attacks.  See
+    ///    Section 5 for details on how the salt is used.
+    /// ```
+    pub fn salt(&self) -> &[u8] {
+        &self.salt
+    }
+
+    /// [RFC 5155, NSEC3, March 2008](https://tools.ietf.org/html/rfc5155#section-3.1.7)
+    ///
+    /// ```text
+    /// 3.1.7.  Next Hashed Owner Name
+    ///
+    ///  The Next Hashed Owner Name field contains the next hashed owner name
+    ///  in hash order.  This value is in binary format.  Given the ordered
+    ///  set of all hashed owner names, the Next Hashed Owner Name field
+    ///  contains the hash of an owner name that immediately follows the owner
+    ///  name of the given NSEC3 RR.  The value of the Next Hashed Owner Name
+    ///  field in the last NSEC3 RR in the zone is the same as the hashed
+    ///  owner name of the first NSEC3 RR in the zone in hash order.  Note
+    ///  that, unlike the owner name of the NSEC3 RR, the value of this field
+    ///  does not contain the appended zone name.
+    /// ```
+    pub fn next_hashed_owner_name(&self) -> &[u8] {
+        &self.next_hashed_owner_name
+    }
+
+    /// [RFC 5155, NSEC3, March 2008](https://tools.ietf.org/html/rfc5155#section-3.1.8)
+    ///
+    /// ```text
+    /// 3.1.8.  Type Bit Maps
+    ///
+    ///  The Type Bit Maps field identifies the RRSet types that exist at the
+    ///  original owner name of the NSEC3 RR.
+    /// ```
+    pub fn type_bit_maps(&self) -> &[RecordType] {
+        &self.type_bit_maps
+    }
+}
+
+/// Read the RData from the given Decoder
+pub fn read(decoder: &mut BinDecoder, rdata_length: Restrict<u16>) -> ProtoResult<NSEC3> {
+    let start_idx = decoder.index();
+
+    let hash_algorithm =
+        Nsec3HashAlgorithm::from_u8(decoder.read_u8()?.unverified(/*Algorithm verified as safe*/))?;
+    let flags: u8 = decoder
+        .read_u8()?
+        .verify_unwrap(|flags| flags & 0b1111_1110 == 0)
+        .map_err(|flags| ProtoError::from(ProtoErrorKind::UnrecognizedNsec3Flags(flags)))?;
+
+    let opt_out: bool = flags & 0b0000_0001 == 0b0000_0001;
+    let iterations: u16 = decoder.read_u16()?.unverified(/*valid as any u16*/);
+
+    // read the salt
+    let salt_len = decoder.read_u8()?.map(|u| u as usize);
+    let salt_len_max = rdata_length
+        .map(|u| u as usize)
+        .checked_sub(decoder.index() - start_idx)
+        .map_err(|_| "invalid rdata for salt_len_max")?;
+    let salt_len = salt_len
+        .verify_unwrap(|salt_len| {
+            *salt_len <= salt_len_max.unverified(/*safe in comparison usage*/)
+        })
+        .map_err(|_| ProtoError::from("salt_len exceeds buffer length"))?;
+    let salt: Vec<u8> =
+        decoder.read_vec(salt_len)?.unverified(/*salt is any valid array of bytes*/);
+
+    // read the hashed_owner_name
+    let hash_len = decoder.read_u8()?.map(|u| u as usize);
+    let hash_len_max = rdata_length
+        .map(|u| u as usize)
+        .checked_sub(decoder.index() - start_idx)
+        .map_err(|_| "invalid rdata for hash_len_max")?;
+    let hash_len = hash_len
+        .verify_unwrap(|hash_len| {
+            *hash_len <= hash_len_max.unverified(/*safe in comparison usage*/)
+        })
+        .map_err(|_| ProtoError::from("hash_len exceeds buffer length"))?;
+    let next_hashed_owner_name: Vec<u8> =
+        decoder.read_vec(hash_len)?.unverified(/*will fail in usage if invalid*/);
+
+    // read the bitmap
+    let bit_map_len = rdata_length
+        .map(|u| u as usize)
+        .checked_sub(decoder.index() - start_idx)
+        .map_err(|_| "invalid rdata length in NSEC3")?;
+    let record_types = decode_type_bit_maps(decoder, bit_map_len)?;
+
+    Ok(NSEC3::new(
+        hash_algorithm,
+        opt_out,
+        iterations,
+        salt,
+        next_hashed_owner_name,
+        record_types,
+    ))
+}
+
+/// Decodes the array of RecordTypes covered by this NSEC record
+///
+/// # Arguments
+///
+/// * `decoder` - decoder to read from
+/// * `bit_map_len` - the number bytes in the bit map
+///
+/// # Returns
+///
+/// The Array of covered types
+pub(crate) fn decode_type_bit_maps(
+    decoder: &mut BinDecoder,
+    bit_map_len: Restrict<usize>,
+) -> ProtoResult<Vec<RecordType>> {
+    // 3.2.1.  Type Bit Maps Encoding
+    //
+    //  The encoding of the Type Bit Maps field is the same as that used by
+    //  the NSEC RR, described in [RFC4034].  It is explained and clarified
+    //  here for clarity.
+    //
+    //  The RR type space is split into 256 window blocks, each representing
+    //  the low-order 8 bits of the 16-bit RR type space.  Each block that
+    //  has at least one active RR type is encoded using a single octet
+    //  window number (from 0 to 255), a single octet bitmap length (from 1
+    //  to 32) indicating the number of octets used for the bitmap of the
+    //  window block, and up to 32 octets (256 bits) of bitmap.
+    //
+    //  Blocks are present in the NSEC3 RR RDATA in increasing numerical
+    //  order.
+    //
+    //     Type Bit Maps Field = ( Window Block # | Bitmap Length | Bitmap )+
+    //
+    //     where "|" denotes concatenation.
+    //
+    //  Each bitmap encodes the low-order 8 bits of RR types within the
+    //  window block, in network bit order.  The first bit is bit 0.  For
+    //  window block 0, bit 1 corresponds to RR type 1 (A), bit 2 corresponds
+    //  to RR type 2 (NS), and so forth.  For window block 1, bit 1
+    //  corresponds to RR type 257, bit 2 to RR type 258.  If a bit is set to
+    //  1, it indicates that an RRSet of that type is present for the
+    //  original owner name of the NSEC3 RR.  If a bit is set to 0, it
+    //  indicates that no RRSet of that type is present for the original
+    //  owner name of the NSEC3 RR.
+    //
+    //  Since bit 0 in window block 0 refers to the non-existing RR type 0,
+    //  it MUST be set to 0.  After verification, the validator MUST ignore
+    //  the value of bit 0 in window block 0.
+    //
+    //  Bits representing Meta-TYPEs or QTYPEs as specified in Section 3.1 of
+    //  [RFC2929] or within the range reserved for assignment only to QTYPEs
+    //  and Meta-TYPEs MUST be set to 0, since they do not appear in zone
+    //  data.  If encountered, they must be ignored upon reading.
+    //
+    //  Blocks with no types present MUST NOT be included.  Trailing zero
+    //  octets in the bitmap MUST be omitted.  The length of the bitmap of
+    //  each block is determined by the type code with the largest numerical
+    //  value, within that block, among the set of RR types present at the
+    //  original owner name of the NSEC3 RR.  Trailing octets not specified
+    //  MUST be interpreted as zero octets.
+    let mut record_types: Vec<RecordType> = Vec::new();
+    let mut state: BitMapReadState = BitMapReadState::Window;
+
+    // loop through all the bytes in the bitmap
+    for _ in 0..bit_map_len.unverified(/*bounded over any length of u16*/) {
+        let current_byte = decoder.read_u8()?;
+
+        state = match state {
+            BitMapReadState::Window => BitMapReadState::Len {
+                window: current_byte.unverified(/*window is any valid u8,*/),
+            },
+            BitMapReadState::Len { window } => BitMapReadState::RecordType {
+                window,
+                len: current_byte,
+                left: current_byte,
+            },
+            BitMapReadState::RecordType { window, len, left } => {
+                // window is the Window Block # from above
+                // len is the Bitmap Length
+                // current_byte is the Bitmap
+                let mut bit_map = current_byte.unverified(/*validated and restricted in usage in following usage*/);
+
+                // for all the bits in the current_byte
+                for i in 0..8 {
+                    // if the current_bytes most significant bit is set
+                    if bit_map & 0b1000_0000 == 0b1000_0000 {
+                        // len - left is the block in the bitmap, times 8 for the bits, + the bit in the current_byte
+                        let low_byte: u8 = len
+                            .checked_sub(left.unverified(/*will fail as param in this call if invalid*/))
+                            .checked_mul(8)
+                            .checked_add(i)
+                            .map_err(|_| "block len or left out of bounds in NSEC(3)")?
+                            .unverified(/*any u8 is valid at this point*/);
+                        let rr_type: u16 = (u16::from(window) << 8) | u16::from(low_byte);
+                        record_types.push(RecordType::from(rr_type));
+                    }
+                    // shift left and look at the next bit
+                    bit_map <<= 1;
+                }
+
+                // move to the next section of the bit_map
+                let left = left
+                    .checked_sub(1)
+                    .map_err(|_| ProtoError::from("block left out of bounds in NSEC(3)"))?;
+                if left.unverified(/*comparison is safe*/) == 0 {
+                    // we've exhausted this Window, move to the next
+                    BitMapReadState::Window
+                } else {
+                    // continue reading this Window
+                    BitMapReadState::RecordType { window, len, left }
+                }
+            }
+        };
+    }
+
+    Ok(record_types)
+}
+
+enum BitMapReadState {
+    Window,
+    Len {
+        window: u8,
+    },
+    RecordType {
+        window: u8,
+        len: Restrict<u8>,
+        left: Restrict<u8>,
+    },
+}
+
+/// Write the RData from the given Decoder
+pub fn emit(encoder: &mut BinEncoder, rdata: &NSEC3) -> ProtoResult<()> {
+    encoder.emit(rdata.hash_algorithm().into())?;
+    let mut flags: u8 = 0;
+    if rdata.opt_out() {
+        flags |= 0b0000_0001
+    };
+    encoder.emit(flags)?;
+    encoder.emit_u16(rdata.iterations())?;
+    encoder.emit(rdata.salt().len() as u8)?;
+    encoder.emit_vec(rdata.salt())?;
+    encoder.emit(rdata.next_hashed_owner_name().len() as u8)?;
+    encoder.emit_vec(rdata.next_hashed_owner_name())?;
+    encode_bit_maps(encoder, rdata.type_bit_maps())?;
+
+    Ok(())
+}
+
+/// Encode the bit map
+///
+/// # Arguments
+///
+/// * `encoder` - the encoder to write to
+/// * `type_bit_maps` - types to encode into the bitmap
+pub(crate) fn encode_bit_maps(
+    encoder: &mut BinEncoder,
+    type_bit_maps: &[RecordType],
+) -> ProtoResult<()> {
+    let mut hash: BTreeMap<u8, Vec<u8>> = BTreeMap::new();
+    let mut type_bit_maps = type_bit_maps.to_vec();
+    type_bit_maps.sort();
+
+    // collect the bitmaps
+    for rr_type in type_bit_maps {
+        let code: u16 = (rr_type).into();
+        let window: u8 = (code >> 8) as u8;
+        let low: u8 = (code & 0x00FF) as u8;
+
+        let bit_map: &mut Vec<u8> = hash.entry(window).or_insert_with(Vec::new);
+        // len + left is the block in the bitmap, divided by 8 for the bits, + the bit in the current_byte
+        let index: u8 = low / 8;
+        let bit: u8 = 0b1000_0000 >> (low % 8);
+
+        // adding necessary space to the vector
+        if bit_map.len() < (index as usize + 1) {
+            bit_map.resize(index as usize + 1, 0_u8);
+        }
+
+        bit_map[index as usize] |= bit;
+    }
+
+    // output bitmaps
+    for (window, bitmap) in hash {
+        encoder.emit(window)?;
+        // the hashset should never be larger that 255 based on above logic.
+        encoder.emit(bitmap.len() as u8)?;
+        for bits in bitmap {
+            encoder.emit(bits)?;
+        }
+    }
+
+    Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+    #![allow(clippy::dbg_macro, clippy::print_stdout)]
+
+    use super::*;
+
+    #[test]
+    pub fn test() {
+        use crate::rr::dnssec::rdata::DNSSECRecordType;
+
+        let rdata = NSEC3::new(
+            Nsec3HashAlgorithm::SHA1,
+            true,
+            2,
+            vec![1, 2, 3, 4, 5],
+            vec![6, 7, 8, 9, 0],
+            vec![
+                RecordType::A,
+                RecordType::AAAA,
+                RecordType::DNSSEC(DNSSECRecordType::DS),
+                RecordType::DNSSEC(DNSSECRecordType::RRSIG),
+            ],
+        );
+
+        let mut bytes = Vec::new();
+        let mut encoder: BinEncoder = BinEncoder::new(&mut bytes);
+        assert!(emit(&mut encoder, &rdata).is_ok());
+        let bytes = encoder.into_bytes();
+
+        println!("bytes: {:?}", bytes);
+
+        let mut decoder: BinDecoder = BinDecoder::new(bytes);
+        let restrict = Restrict::new(bytes.len() as u16);
+        let read_rdata = read(&mut decoder, restrict).expect("Decoding error");
+        assert_eq!(rdata, read_rdata);
+    }
+
+    #[test]
+    pub fn test_dups() {
+        use crate::rr::dnssec::rdata::DNSSECRecordType;
+
+        let rdata_with_dups = NSEC3::new(
+            Nsec3HashAlgorithm::SHA1,
+            true,
+            2,
+            vec![1, 2, 3, 4, 5],
+            vec![6, 7, 8, 9, 0],
+            vec![
+                RecordType::A,
+                RecordType::AAAA,
+                RecordType::DNSSEC(DNSSECRecordType::DS),
+                RecordType::AAAA,
+                RecordType::DNSSEC(DNSSECRecordType::RRSIG),
+            ],
+        );
+
+        let rdata_wo = NSEC3::new(
+            Nsec3HashAlgorithm::SHA1,
+            true,
+            2,
+            vec![1, 2, 3, 4, 5],
+            vec![6, 7, 8, 9, 0],
+            vec![
+                RecordType::A,
+                RecordType::AAAA,
+                RecordType::DNSSEC(DNSSECRecordType::DS),
+                RecordType::DNSSEC(DNSSECRecordType::RRSIG),
+            ],
+        );
+
+        let mut bytes = Vec::new();
+        let mut encoder: BinEncoder = BinEncoder::new(&mut bytes);
+        assert!(emit(&mut encoder, &rdata_with_dups).is_ok());
+        let bytes = encoder.into_bytes();
+
+        println!("bytes: {:?}", bytes);
+
+        let mut decoder: BinDecoder = BinDecoder::new(bytes);
+        let restrict = Restrict::new(bytes.len() as u16);
+        let read_rdata = read(&mut decoder, restrict).expect("Decoding error");
+        assert_eq!(rdata_wo, read_rdata);
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/rdata/nsec3param.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/rdata/nsec3param.rs
new file mode 100644
index 0000000..e504c61
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/rdata/nsec3param.rs
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! parameters used for the nsec3 hash method
+
+use crate::error::*;
+use crate::rr::dnssec::Nsec3HashAlgorithm;
+use crate::serialize::binary::*;
+
+/// [RFC 5155, NSEC3, March 2008](https://tools.ietf.org/html/rfc5155#section-4)
+///
+/// ```text
+/// 4.  The NSEC3PARAM Resource Record
+///
+///    The NSEC3PARAM RR contains the NSEC3 parameters (hash algorithm,
+///    flags, iterations, and salt) needed by authoritative servers to
+///    calculate hashed owner names.  The presence of an NSEC3PARAM RR at a
+///    zone apex indicates that the specified parameters may be used by
+///    authoritative servers to choose an appropriate set of NSEC3 RRs for
+///    negative responses.  The NSEC3PARAM RR is not used by validators or
+///    resolvers.
+///
+///    If an NSEC3PARAM RR is present at the apex of a zone with a Flags
+///    field value of zero, then there MUST be an NSEC3 RR using the same
+///    hash algorithm, iterations, and salt parameters present at every
+///    hashed owner name in the zone.  That is, the zone MUST contain a
+///    complete set of NSEC3 RRs with the same hash algorithm, iterations,
+///    and salt parameters.
+///
+///    The owner name for the NSEC3PARAM RR is the name of the zone apex.
+///
+///    The type value for the NSEC3PARAM RR is 51.
+///
+///    The NSEC3PARAM RR RDATA format is class independent and is described
+///    below.
+///
+///    The class MUST be the same as the NSEC3 RRs to which this RR refers.
+///
+/// 4.2.  NSEC3PARAM RDATA Wire Format
+///
+///  The RDATA of the NSEC3PARAM RR is as shown below:
+///
+///                       1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+///   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+///  |   Hash Alg.   |     Flags     |          Iterations           |
+///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+///  |  Salt Length  |                     Salt                      /
+///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+///
+///  Hash Algorithm is a single octet.
+///
+///  Flags field is a single octet.
+///
+///  Iterations is represented as a 16-bit unsigned integer, with the most
+///  significant bit first.
+///
+///  Salt Length is represented as an unsigned octet.  Salt Length
+///  represents the length of the following Salt field in octets.  If the
+///  value is zero, the Salt field is omitted.
+///
+///  Salt, if present, is encoded as a sequence of binary octets.  The
+///  length of this field is determined by the preceding Salt Length
+///  field.
+/// ```
+#[derive(Debug, PartialEq, Eq, Hash, Clone)]
+pub struct NSEC3PARAM {
+    hash_algorithm: Nsec3HashAlgorithm,
+    opt_out: bool,
+    iterations: u16,
+    salt: Vec<u8>,
+}
+
+impl NSEC3PARAM {
+    /// Constructs a new NSEC3PARAM RData for use in a Resource Record
+    pub fn new(
+        hash_algorithm: Nsec3HashAlgorithm,
+        opt_out: bool,
+        iterations: u16,
+        salt: Vec<u8>,
+    ) -> NSEC3PARAM {
+        NSEC3PARAM {
+            hash_algorithm,
+            opt_out,
+            iterations,
+            salt,
+        }
+    }
+
+    /// [RFC 5155, NSEC3, March 2008](https://tools.ietf.org/html/rfc5155#section-4.1.1)
+    ///
+    /// ```text
+    /// 4.1.1.  Hash Algorithm
+    ///
+    ///    The Hash Algorithm field identifies the cryptographic hash algorithm
+    ///    used to construct the hash-value.
+    ///
+    ///    The acceptable values are the same as the corresponding field in the
+    ///    NSEC3 RR.
+    /// ```
+    pub fn hash_algorithm(&self) -> Nsec3HashAlgorithm {
+        self.hash_algorithm
+    }
+
+    /// [RFC 5155, NSEC3, March 2008](https://tools.ietf.org/html/rfc5155#section-4.1.2)
+    ///
+    /// ```text
+    /// 4.1.2.  Flag Fields
+    ///
+    ///    The Opt-Out flag is not used and is set to zero.
+    ///
+    ///    All other flags are reserved for future use, and must be zero.
+    ///
+    ///    NSEC3PARAM RRs with a Flags field value other than zero MUST be
+    ///    ignored.
+    /// ```
+    pub fn opt_out(&self) -> bool {
+        self.opt_out
+    }
+
+    /// [RFC 5155, NSEC3, March 2008](https://tools.ietf.org/html/rfc5155#section-4.1.3)
+    ///
+    /// ```text
+    /// 4.1.3.  Iterations
+    ///
+    ///    The Iterations field defines the number of additional times the hash
+    ///    is performed.
+    ///
+    ///    Its acceptable values are the same as the corresponding field in the
+    ///    NSEC3 RR.
+    /// ```
+    pub fn iterations(&self) -> u16 {
+        self.iterations
+    }
+
+    /// [RFC 5155, NSEC3, March 2008](https://tools.ietf.org/html/rfc5155#section-4.1.5)
+    ///
+    /// ```text
+    /// 4.1.5.  Salt
+    ///
+    ///    The Salt field is appended to the original owner name before hashing.
+    /// ```
+    pub fn salt(&self) -> &[u8] {
+        &self.salt
+    }
+}
+
+/// Read the RData from the given Decoder
+pub fn read(decoder: &mut BinDecoder) -> ProtoResult<NSEC3PARAM> {
+    let hash_algorithm =
+        Nsec3HashAlgorithm::from_u8(decoder.read_u8()?.unverified(/*Algorithm verified as safe*/))?;
+    let flags: u8 = decoder
+        .read_u8()?
+        .verify_unwrap(|flags| flags & 0b1111_1110 == 0)
+        .map_err(|flags| ProtoError::from(ProtoErrorKind::UnrecognizedNsec3Flags(flags)))?;
+
+    let opt_out: bool = flags & 0b0000_0001 == 0b0000_0001;
+    let iterations: u16 = decoder.read_u16()?.unverified(/*valid as any u16*/);
+    let salt_len: usize = decoder
+        .read_u8()?
+        .map(|u| u as usize)
+        .verify_unwrap(|salt_len| *salt_len <= decoder.len())
+        .map_err(|_| ProtoError::from("salt_len exceeds buffer length"))?;
+    let salt: Vec<u8> = decoder.read_vec(salt_len)?.unverified(/*valid as any array of u8*/);
+
+    Ok(NSEC3PARAM::new(hash_algorithm, opt_out, iterations, salt))
+}
+
+/// Write the RData from the given Decoder
+pub fn emit(encoder: &mut BinEncoder, rdata: &NSEC3PARAM) -> ProtoResult<()> {
+    encoder.emit(rdata.hash_algorithm().into())?;
+    let mut flags: u8 = 0;
+    if rdata.opt_out() {
+        flags |= 0b0000_0001
+    };
+    encoder.emit(flags)?;
+    encoder.emit_u16(rdata.iterations())?;
+    encoder.emit(rdata.salt().len() as u8)?;
+    encoder.emit_vec(rdata.salt())?;
+
+    Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+    #![allow(clippy::dbg_macro, clippy::print_stdout)]
+
+    use super::*;
+
+    #[test]
+    pub fn test() {
+        let rdata = NSEC3PARAM::new(Nsec3HashAlgorithm::SHA1, true, 2, vec![1, 2, 3, 4, 5]);
+
+        let mut bytes = Vec::new();
+        let mut encoder: BinEncoder = BinEncoder::new(&mut bytes);
+        assert!(emit(&mut encoder, &rdata).is_ok());
+        let bytes = encoder.into_bytes();
+
+        println!("bytes: {:?}", bytes);
+
+        let mut decoder: BinDecoder = BinDecoder::new(bytes);
+        let read_rdata = read(&mut decoder).expect("Decoding error");
+        assert_eq!(rdata, read_rdata);
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/rdata/sig.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/rdata/sig.rs
new file mode 100644
index 0000000..2e907f3
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/rdata/sig.rs
@@ -0,0 +1,585 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! signature record for signing queries, updates, and responses
+
+use crate::error::*;
+use crate::rr::dnssec::Algorithm;
+use crate::rr::{Name, RecordType};
+use crate::serialize::binary::*;
+
+/// [RFC 2535, Domain Name System Security Extensions, March 1999](https://tools.ietf.org/html/rfc2535#section-4)
+///
+/// NOTE: RFC 2535 was obsoleted with 4034+, with the exception of the
+///  usage for UPDATE, which is what this implementation is for.
+///
+/// ```text
+/// 4.1 SIG RDATA Format
+///
+///  The RDATA portion of a SIG RR is as shown below.  The integrity of
+///  the RDATA information is protected by the signature field.
+///
+///  1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+///  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+/// |        type covered           |  algorithm    |     labels    |
+/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+/// |                         original TTL                          |
+/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+/// |                      signature expiration                     |
+/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+/// |                      signature inception                      |
+/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+/// |            key  tag           |                               |
+/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+         signer's name         +
+/// |                                                               /
+/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-/
+/// /                                                               /
+/// /                            signature                          /
+/// /                                                               /
+/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+///
+/// ```
+/// [RFC 2931](https://tools.ietf.org/html/rfc2931), DNS Request and Transaction Signatures, September 2000
+///
+/// NOTE: 2931 updates SIG0 to clarify certain particulars...
+///
+/// ```text
+/// RFC 2931                       DNS SIG(0)                 September 2000
+///
+/// 3. The SIG(0) Resource Record
+///
+///    The structure of and type number of SIG resource records (RRs) is
+///    given in [RFC 2535] Section 4.1.  However all of Section 4.1.8.1 and
+///    the parts of Sections 4.2 and 4.3 related to SIG(0) should be
+///    considered replaced by the material below.  Any conflict between [RFC
+///    2535] and this document concerning SIG(0) RRs should be resolved in
+///    favor of this document.
+///
+///    For all transaction SIG(0)s, the signer field MUST be a name of the
+///    originating host and there MUST be a KEY RR at that name with the
+///    public key corresponding to the private key used to calculate the
+///    signature.  (The host domain name used may be the inverse IP address
+///    mapping name for an IP address of the host if the relevant KEY is
+///    stored there.)
+///
+///    For all SIG(0) RRs, the owner name, class, TTL, and original TTL, are
+///    meaningless.  The TTL fields SHOULD be zero and the CLASS field
+///    SHOULD be ANY.  To conserve space, the owner name SHOULD be root (a
+///    single zero octet).  When SIG(0) authentication on a response is
+///    desired, that SIG RR MUST be considered the highest priority of any
+///    additional information for inclusion in the response. If the SIG(0)
+///    RR cannot be added without causing the message to be truncated, the
+///    server MUST alter the response so that a SIG(0) can be included.
+///    This response consists of only the question and a SIG(0) record, and
+///    has the TC bit set and RCODE 0 (NOERROR).  The client should at this
+///    point retry the request using TCP.
+///
+/// 3.1 Calculating Request and Transaction SIGs
+///
+///    A DNS request may be optionally signed by including one SIG(0)s at
+///    the end of the query additional information section.  Such a SIG is
+///    identified by having a "type covered" field of zero. It signs the
+///    preceding DNS request message including DNS header but not including
+///    the UDP/IP header and before the request RR counts have been adjusted
+///    for the inclusions of the request SIG(0).
+///
+///    It is calculated by using a "data" (see [RFC 2535], Section 4.1.8) of
+///    (1) the SIG's RDATA section entirely omitting (not just zeroing) the
+///    signature subfield itself, (2) the DNS query messages, including DNS
+///    header, but not the UDP/IP header and before the reply RR counts have
+///    been adjusted for the inclusion of the SIG(0).  That is
+///
+///       data = RDATA | request - SIG(0)
+///
+///    where "|" is concatenation and RDATA is the RDATA of the SIG(0) being
+///    calculated less the signature itself.
+///
+///    Similarly, a SIG(0) can be used to secure a response and the request
+///    that produced it.  Such transaction signatures are calculated by
+///    using a "data" of (1) the SIG's RDATA section omitting the signature
+///    itself, (2) the entire DNS query message that produced this response,
+///    including the query's DNS header but not its UDP/IP header, and (3)
+///    the entire DNS response message, including DNS header but not the
+///    UDP/IP header and before the response RR counts have been adjusted
+///    for the inclusion of the SIG(0).
+///
+///    That is
+///
+///       data = RDATA | full query | response - SIG(0)
+///
+///    where "|" is concatenation and RDATA is the RDATA of the SIG(0) being
+///    calculated less the signature itself.
+///
+///    Verification of a response SIG(0) (which is signed by the server host
+///    key, not the zone key) by the requesting resolver shows that the
+///    query and response were not tampered with in transit, that the
+///    response corresponds to the intended query, and that the response
+///    comes from the queried server.
+///
+///    In the case of a DNS message via TCP, a SIG(0) on the first data
+///    packet is calculated with "data" as above and for each subsequent
+///    packet, it is calculated as follows:
+///
+///       data = RDATA | DNS payload - SIG(0) | previous packet
+///
+///    where "|" is concatenations, RDATA is as above, and previous packet
+///    is the previous DNS payload including DNS header and the SIG(0) but
+///    not the TCP/IP header.  Support of SIG(0) for TCP is OPTIONAL.  As an
+///    alternative, TSIG may be used after, if necessary, setting up a key
+///    with TKEY [RFC 2930].
+///
+///    Except where needed to authenticate an update, TKEY, or similar
+///    privileged request, servers are not required to check a request
+///    SIG(0).
+///
+///    Note: requests and responses can either have a single TSIG or one
+///    SIG(0) but not both a TSIG and a SIG(0).
+///
+/// 3.2 Processing Responses and SIG(0) RRs
+///
+///    If a SIG RR is at the end of the additional information section of a
+///    response and has a type covered of zero, it is a transaction
+///    signature covering the response and the query that produced the
+///    response.  For TKEY responses, it MUST be checked and the message
+///    rejected if the checks fail unless otherwise specified for the TKEY
+///    mode in use.  For all other responses, it MAY be checked and the
+///    message rejected if the checks fail.
+///
+///    If a response's SIG(0) check succeed, such a transaction
+///    authentication SIG does NOT directly authenticate the validity any
+///    data-RRs in the message.  However, it authenticates that they were
+///    sent by the queried server and have not been diddled.  (Only a proper
+///    SIG(0) RR signed by the zone or a key tracing its authority to the
+///    zone or to static resolver configuration can directly authenticate
+///
+///    data-RRs, depending on resolver policy.) If a resolver or server does
+///    not implement transaction and/or request SIGs, it MUST ignore them
+///    without error where they are optional and treat them as failing where
+///    they are required.
+///
+/// 3.3 SIG(0) Lifetime and Expiration
+///
+///    The inception and expiration times in SIG(0)s are for the purpose of
+///    resisting replay attacks.  They should be set to form a time bracket
+///    such that messages outside that bracket can be ignored.  In IP
+///    networks, this time bracket should not normally extend further than 5
+///    minutes into the past and 5 minutes into the future.
+/// ```
+#[derive(Debug, PartialEq, Eq, Hash, Clone)]
+pub struct SIG {
+    type_covered: RecordType,
+    algorithm: Algorithm,
+    num_labels: u8,
+    original_ttl: u32,
+    sig_expiration: u32,
+    sig_inception: u32,
+    key_tag: u16,
+    signer_name: Name,
+    sig: Vec<u8>,
+}
+
+impl SIG {
+    /// Creates a new SIG record data, used for both RRSIG and SIG(0) records.
+    ///
+    /// # Arguments
+    ///
+    /// * `type_covered` - The `RecordType` which this signature covers, should be NULL for SIG(0).
+    /// * `algorithm` - The `Algorithm` used to generate the `signature`.
+    /// * `num_labels` - The number of labels in the name, should be less 1 for *.name labels,
+    ///                  see `Name::num_labels()`.
+    /// * `original_ttl` - The TTL for the RRSet stored in the zone, should be 0 for SIG(0).
+    /// * `sig_expiration` - Timestamp at which this signature is no longer valid, very important to
+    ///                      keep this low, < +5 minutes to limit replay attacks.
+    /// * `sig_inception` - Timestamp when this signature was generated.
+    /// * `key_tag` - See the key_tag generation in `rr::dnssec::Signer::key_tag()`.
+    /// * `signer_name` - Domain name of the server which was used to generate the signature.
+    /// * `sig` - signature stored in this record.
+    ///
+    /// # Return value
+    ///
+    /// The new SIG record data.
+    #[allow(clippy::too_many_arguments)]
+    pub fn new(
+        type_covered: RecordType,
+        algorithm: Algorithm,
+        num_labels: u8,
+        original_ttl: u32,
+        sig_expiration: u32,
+        sig_inception: u32,
+        key_tag: u16,
+        signer_name: Name,
+        sig: Vec<u8>,
+    ) -> SIG {
+        SIG {
+            type_covered,
+            algorithm,
+            num_labels,
+            original_ttl,
+            sig_expiration,
+            sig_inception,
+            key_tag,
+            signer_name,
+            sig,
+        }
+    }
+
+    /// Add actual signature value to existing SIG record data.
+    ///
+    /// # Arguments
+    ///
+    /// * `signature` - signature to be stored in this record.
+    ///
+    /// # Return value
+    ///
+    /// The new SIG record data.
+    pub fn set_sig(self, signature: Vec<u8>) -> Self {
+        SIG {
+            type_covered: self.type_covered,
+            algorithm: self.algorithm,
+            num_labels: self.num_labels,
+            original_ttl: self.original_ttl,
+            sig_expiration: self.sig_expiration,
+            sig_inception: self.sig_inception,
+            key_tag: self.key_tag,
+            signer_name: self.signer_name,
+            sig: signature,
+        }
+    }
+
+    /// [RFC 2535, Domain Name System Security Extensions, March 1999](https://tools.ietf.org/html/rfc2535#section-4.1.1)
+    ///
+    /// ```text
+    /// 4.1.1 Type Covered Field
+    ///
+    ///  The "type covered" is the type of the other RRs covered by this SIG.
+    /// ```
+    pub fn type_covered(&self) -> RecordType {
+        self.type_covered
+    }
+
+    /// [RFC 2535, Domain Name System Security Extensions, March 1999](https://tools.ietf.org/html/rfc2535#section-4.1.2)
+    ///
+    /// ```text
+    /// 4.1.2 Algorithm Number Field
+    ///
+    ///  This octet is as described in section 3.2.
+    /// ```
+    pub fn algorithm(&self) -> Algorithm {
+        self.algorithm
+    }
+
+    /// [RFC 2535, Domain Name System Security Extensions, March 1999](https://tools.ietf.org/html/rfc2535#section-4.1.3)
+    ///
+    /// ```text
+    /// 4.1.3 Labels Field
+    ///
+    ///  The "labels" octet is an unsigned count of how many labels there are
+    ///  in the original SIG RR owner name not counting the null label for
+    ///  root and not counting any initial "*" for a wildcard.  If a secured
+    ///  retrieval is the result of wild card substitution, it is necessary
+    ///  for the resolver to use the original form of the name in verifying
+    ///  the digital signature.  This field makes it easy to determine the
+    ///  original form.
+    ///
+    ///  If, on retrieval, the RR appears to have a longer name than indicated
+    ///  by "labels", the resolver can tell it is the result of wildcard
+    ///  substitution.  If the RR owner name appears to be shorter than the
+    ///  labels count, the SIG RR must be considered corrupt and ignored.  The
+    ///  maximum number of labels allowed in the current DNS is 127 but the
+    ///  entire octet is reserved and would be required should DNS names ever
+    ///  be expanded to 255 labels.  The following table gives some examples.
+    ///  The value of "labels" is at the top, the retrieved owner name on the
+    ///  left, and the table entry is the name to use in signature
+    ///  verification except that "bad" means the RR is corrupt.
+    ///
+    ///  labels= |  0  |   1  |    2   |      3   |      4   |
+    ///  --------+-----+------+--------+----------+----------+
+    ///         .|   . | bad  |  bad   |    bad   |    bad   |
+    ///        d.|  *. |   d. |  bad   |    bad   |    bad   |
+    ///      c.d.|  *. | *.d. |   c.d. |    bad   |    bad   |
+    ///    b.c.d.|  *. | *.d. | *.c.d. |   b.c.d. |    bad   |
+    ///  a.b.c.d.|  *. | *.d. | *.c.d. | *.b.c.d. | a.b.c.d. |
+    /// ```
+    pub fn num_labels(&self) -> u8 {
+        self.num_labels
+    }
+
+    /// [RFC 2535, Domain Name System Security Extensions, March 1999](https://tools.ietf.org/html/rfc2535#section-4.1.4)
+    ///
+    /// ```text
+    /// 4.1.4 Original TTL Field
+    ///
+    ///  The "original TTL" field is included in the RDATA portion to avoid
+    ///  (1) authentication problems that caching servers would otherwise
+    ///  cause by decrementing the real TTL field and (2) security problems
+    ///  that unscrupulous servers could otherwise cause by manipulating the
+    ///  real TTL field.  This original TTL is protected by the signature
+    ///  while the current TTL field is not.
+    ///
+    ///  NOTE:  The "original TTL" must be restored into the covered RRs when
+    ///  the signature is verified (see Section 8).  This generally implies
+    ///  that all RRs for a particular type, name, and class, that is, all the
+    ///  RRs in any particular RRset, must have the same TTL to start with.
+    /// ```
+    pub fn original_ttl(&self) -> u32 {
+        self.original_ttl
+    }
+
+    /// [RFC 2535, Domain Name System Security Extensions, March 1999](https://tools.ietf.org/html/rfc2535#section-4.1.5)
+    ///
+    /// ```text
+    /// 4.1.5 Signature Expiration and Inception Fields
+    ///
+    ///  The SIG is valid from the "signature inception" time until the
+    ///  "signature expiration" time.  Both are unsigned numbers of seconds
+    ///  since the start of 1 January 1970, GMT, ignoring leap seconds.  (See
+    ///  also Section 4.4.)  Ring arithmetic is used as for DNS SOA serial
+    ///  numbers [RFC 1982] which means that these times can never be more
+    ///  than about 68 years in the past or the future.  This means that these
+    ///  times are ambiguous modulo ~136.09 years.  However there is no
+    ///  security flaw because keys are required to be changed to new random
+    ///  keys by [RFC 2541] at least every five years.  This means that the
+    ///  probability that the same key is in use N*136.09 years later should
+    ///  be the same as the probability that a random guess will work.
+    ///
+    ///  A SIG RR may have an expiration time numerically less than the
+    ///  inception time if the expiration time is near the 32 bit wrap around
+    ///  point and/or the signature is long lived.
+    ///
+    ///  (To prevent misordering of network requests to update a zone
+    ///  dynamically, monotonically increasing "signature inception" times may
+    ///  be necessary.)
+    ///
+    ///  A secure zone must be considered changed for SOA serial number
+    ///  purposes not only when its data is updated but also when new SIG RRs
+    ///  are inserted (ie, the zone or any part of it is re-signed).
+    /// ```
+    pub fn sig_expiration(&self) -> u32 {
+        self.sig_expiration
+    }
+
+    /// see `get_sig_expiration`
+    pub fn sig_inception(&self) -> u32 {
+        self.sig_inception
+    }
+
+    /// [RFC 2535, Domain Name System Security Extensions, March 1999](https://tools.ietf.org/html/rfc2535#section-4.1.6)
+    ///
+    /// ```text
+    /// 4.1.6 Key Tag Field
+    ///
+    ///  The "key Tag" is a two octet quantity that is used to efficiently
+    ///  select between multiple keys which may be applicable and thus check
+    ///  that a public key about to be used for the computationally expensive
+    ///  effort to check the signature is possibly valid.  For algorithm 1
+    ///  (MD5/RSA) as defined in [RFC 2537], it is the next to the bottom two
+    ///  octets of the public key modulus needed to decode the signature
+    ///  field.  That is to say, the most significant 16 of the least
+    ///  significant 24 bits of the modulus in network (big endian) order. For
+    ///  all other algorithms, including private algorithms, it is calculated
+    ///  as a simple checksum of the KEY RR as described in Appendix C.
+    /// ```
+    pub fn key_tag(&self) -> u16 {
+        self.key_tag
+    }
+
+    /// [RFC 2535, Domain Name System Security Extensions, March 1999](https://tools.ietf.org/html/rfc2535#section-4.1.7)
+    ///
+    /// ```text
+    /// 4.1.7 Signer's Name Field
+    ///
+    ///  The "signer's name" field is the domain name of the signer generating
+    ///  the SIG RR.  This is the owner name of the public KEY RR that can be
+    ///  used to verify the signature.  It is frequently the zone which
+    ///  contained the RRset being authenticated.  Which signers should be
+    ///  authorized to sign what is a significant resolver policy question as
+    ///  discussed in Section 6. The signer's name may be compressed with
+    ///  standard DNS name compression when being transmitted over the
+    ///  network.
+    /// ```
+    pub fn signer_name(&self) -> &Name {
+        &self.signer_name
+    }
+
+    /// [RFC 2535, Domain Name System Security Extensions, March 1999](https://tools.ietf.org/html/rfc2535#section-4.1.8)
+    ///
+    /// ```text
+    /// 4.1.8 Signature Field
+    ///
+    ///  The actual signature portion of the SIG RR binds the other RDATA
+    ///  fields to the RRset of the "type covered" RRs with that owner name
+    ///  and class.  This covered RRset is thereby authenticated.  To
+    ///  accomplish this, a data sequence is constructed as follows:
+    ///
+    ///  data = RDATA | RR(s)...
+    ///
+    ///  where "|" is concatenation,
+    ///
+    ///  RDATA is the wire format of all the RDATA fields in the SIG RR itself
+    ///  (including the canonical form of the signer's name) before but not
+    ///  including the signature, and
+    ///
+    ///  RR(s) is the RRset of the RR(s) of the type covered with the same
+    ///  owner name and class as the SIG RR in canonical form and order as
+    ///  defined in Section 8.
+    ///
+    ///  How this data sequence is processed into the signature is algorithm
+    ///  dependent.  These algorithm dependent formats and procedures are
+    ///  described in separate documents (Section 3.2).
+    ///
+    ///  SIGs SHOULD NOT be included in a zone for any "meta-type" such as
+    ///  ANY, AXFR, etc. (but see section 5.6.2 with regard to IXFR).
+    /// ```
+    pub fn sig(&self) -> &[u8] {
+        &self.sig
+    }
+}
+
+/// Read the RData from the given Decoder
+pub fn read(decoder: &mut BinDecoder, rdata_length: Restrict<u16>) -> ProtoResult<SIG> {
+    let start_idx = decoder.index();
+
+    // TODO should we verify here? or elsewhere...
+    let type_covered = RecordType::read(decoder)?;
+    let algorithm = Algorithm::read(decoder)?;
+    let num_labels = decoder.read_u8()?.unverified(/*technically valid as any u8*/);
+    let original_ttl = decoder.read_u32()?.unverified(/*valid as any u32*/);
+    let sig_expiration =
+        decoder.read_u32()?.unverified(/*valid as any u32, in practice should be in the future*/);
+    let sig_inception = decoder.read_u32()?.unverified(/*valid as any u32, in practice should be before expiration*/);
+    let key_tag = decoder.read_u16()?.unverified(/*valid as any u16*/);
+    let signer_name = Name::read(decoder)?;
+
+    // read the signature, this will vary buy key size
+    let sig_len = rdata_length
+        .map(|u| u as usize)
+        .checked_sub(decoder.index() - start_idx)
+        .map_err(|_| ProtoError::from("invalid rdata length in SIG"))?
+        .unverified(/*used only as length safely*/);
+    let sig = decoder
+        .read_vec(sig_len)?
+        .unverified(/*will fail in usage if invalid*/);
+
+    Ok(SIG::new(
+        type_covered,
+        algorithm,
+        num_labels,
+        original_ttl,
+        sig_expiration,
+        sig_inception,
+        key_tag,
+        signer_name,
+        sig,
+    ))
+}
+
+/// [RFC 4034](https://tools.ietf.org/html/rfc4034#section-6), DNSSEC Resource Records, March 2005
+///
+/// This is accurate for all currently known name records.
+///
+/// ```text
+/// 6.2.  Canonical RR Form
+///
+///    For the purposes of DNS security, the canonical form of an RR is the
+///    wire format of the RR where:
+///
+///    ...
+///
+///    3.  if the type of the RR is NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR,
+///        HINFO, MINFO, MX, HINFO, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX,
+///        SRV, DNAME, A6, RRSIG, or (rfc6840 removes NSEC), all uppercase
+///        US-ASCII letters in the DNS names contained within the RDATA are replaced
+///        by the corresponding lowercase US-ASCII letters;
+/// ```
+pub fn emit(encoder: &mut BinEncoder, sig: &SIG) -> ProtoResult<()> {
+    let is_canonical_names = encoder.is_canonical_names();
+
+    sig.type_covered().emit(encoder)?;
+    sig.algorithm().emit(encoder)?;
+    encoder.emit(sig.num_labels())?;
+    encoder.emit_u32(sig.original_ttl())?;
+    encoder.emit_u32(sig.sig_expiration())?;
+    encoder.emit_u32(sig.sig_inception())?;
+    encoder.emit_u16(sig.key_tag())?;
+    sig.signer_name()
+        .emit_with_lowercase(encoder, is_canonical_names)?;
+    encoder.emit_vec(sig.sig())?;
+    Ok(())
+}
+
+/// specifically for outputting the RData for an RRSIG, with signer_name in canonical form
+#[allow(clippy::too_many_arguments)]
+pub fn emit_pre_sig(
+    encoder: &mut BinEncoder,
+    type_covered: RecordType,
+    algorithm: Algorithm,
+    num_labels: u8,
+    original_ttl: u32,
+    sig_expiration: u32,
+    sig_inception: u32,
+    key_tag: u16,
+    signer_name: &Name,
+) -> ProtoResult<()> {
+    type_covered.emit(encoder)?;
+    algorithm.emit(encoder)?;
+    encoder.emit(num_labels)?;
+    encoder.emit_u32(original_ttl)?;
+    encoder.emit_u32(sig_expiration)?;
+    encoder.emit_u32(sig_inception)?;
+    encoder.emit_u16(key_tag)?;
+    signer_name.emit_as_canonical(encoder, true)?;
+    Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+    #![allow(clippy::dbg_macro, clippy::print_stdout)]
+
+    use super::*;
+
+    #[test]
+    fn test() {
+        use std::str::FromStr;
+
+        let rdata = SIG::new(
+            RecordType::NULL,
+            Algorithm::RSASHA256,
+            0,
+            0,
+            2,
+            1,
+            5,
+            Name::from_str("www.example.com").unwrap(),
+            vec![
+                0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+                23, 24, 25, 26, 27, 28, 29, 29, 31,
+            ], // 32 bytes for SHA256
+        );
+
+        let mut bytes = Vec::new();
+        let mut encoder: BinEncoder = BinEncoder::new(&mut bytes);
+        assert!(emit(&mut encoder, &rdata).is_ok());
+        let bytes = encoder.into_bytes();
+
+        println!("bytes: {:?}", bytes);
+
+        let mut decoder: BinDecoder = BinDecoder::new(bytes);
+        let restrict = Restrict::new(bytes.len() as u16);
+        let read_rdata = read(&mut decoder, restrict).expect("Decoding error");
+        assert_eq!(rdata, read_rdata);
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/roots/19036.rsa b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/roots/19036.rsa
new file mode 100644
index 0000000..9364102
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/roots/19036.rsa
Binary files differ
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/roots/20326.rsa b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/roots/20326.rsa
new file mode 100644
index 0000000..352389e
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/roots/20326.rsa
Binary files differ
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/roots/README.md b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/roots/README.md
new file mode 100644
index 0000000..3122235
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/roots/README.md
@@ -0,0 +1,22 @@
+# Generating Roots
+
+The process for getting the current key-signing-key, ksk, roots is by means of a tool in `utils`. The tool can be run via `cargo run --bin get-root-ksks`, it will output data that looks like this:
+
+```console
+$ cargo run --bin get-root-ksks
+   Compiling trust-dns-util v0.3.0-alpha.1 (file:///Users/benjaminfry/Development/rust/trust-dns/util)
+    Finished dev [unoptimized + debuginfo] target(s) in 6.48s
+     Running `/Users/benjaminfry/Development/rust/trust-dns/target/debug/get-root-ksks`
+found: tag: 20326 info: DNSKEY { zone_key: true, secure_entry_point: true, revoke: false, algorithm: RSASHA256, public_key: [3, 1, 0, 1, 172, 255, 180, 9, 188, 201, 57, 248, 49, 247,161, 229, 236, 136, 247, 165, 146, 85, 236, 83, 4, 11, 228, 50, 2, 115, 144, 164, 206, 137, 109, 111, 144, 134, 243, 197, 225, 119, 251, 254, 17, 129, 99, 170, 236, 122, 241, 70, 44,71, 148, 89, 68, 196, 226, 192, 38, 190, 94, 152, 187, 205, 237, 37, 151, 130, 114, 225, 227, 224, 121, 197, 9, 77, 87, 63, 14, 131, 201, 47, 2, 179, 45, 53, 19, 177, 85, 11, 130, 105, 41, 200, 13, 208, 249, 44, 172, 150, 109, 23, 118, 159, 213, 134, 123, 100, 124, 63, 56, 2, 154, 189, 196, 129, 82, 235, 143, 32, 113, 89, 236, 197, 210, 50, 199, 193, 83, 124, 121, 244, 183, 172, 40, 255, 17, 104, 47, 33, 104, 27, 246, 214, 171, 165, 85, 3, 43, 246, 249, 240, 54, 190, 178, 170, 165, 179, 119, 141, 110, 235, 251, 166, 191, 158, 161, 145, 190, 74, 176, 202, 234, 117, 158, 47, 119, 58, 31, 144, 41, 199, 62, 203, 141, 87, 53, 185, 50, 29, 176, 133, 241, 184, 226, 216, 3, 143, 226, 148, 25, 146, 84, 140, 238, 13, 103, 221, 69, 71, 225, 29, 214, 58, 249, 201, 252, 28, 84, 102, 251, 104, 76, 240, 9, 215, 25, 124, 44, 247, 158, 121, 42, 181, 1, 230, 168, 161, 202, 81, 154, 242, 203, 155, 95, 99, 103, 233, 76, 13, 71, 80, 36, 81, 53, 123, 225, 181] }
+found: tag: 19036 info: DNSKEY { zone_key: true, secure_entry_point: true, revoke: false, algorithm: RSASHA256, public_key: [3, 1, 0, 1, 168, 0, 32, 169, 85, 102, 186, 66, 232, 134, 187, 128, 76, 218, 132, 228, 126, 245, 109, 189, 122, 236, 97, 38, 21, 85, 44, 236, 144, 109, 33, 22, 208, 239, 32, 112, 40, 197, 21, 84, 20, 77, 254, 175, 231, 199, 203, 143, 0, 93, 209, 130, 52, 19, 58, 192, 113, 10, 129, 24, 44, 225, 253, 20, 173, 34, 131, 188, 131, 67, 95, 157, 242, 246, 49, 50, 81, 147, 26, 23, 109, 240, 218, 81, 229, 79, 66, 230, 4, 134, 13,251, 53, 149, 128, 37, 15, 85, 156, 197, 67, 196, 255, 213, 28, 190, 61, 232, 207, 208, 103, 25, 35, 127, 159, 196, 126, 231, 41, 218, 6, 131, 95, 164, 82, 232, 37, 233, 161, 142, 188, 46, 203, 207, 86, 52, 116, 101, 44, 51, 207, 86, 169, 3, 59, 205, 245, 217, 115, 18, 23, 151, 236, 128, 137, 4, 27, 110, 3, 161, 183, 45, 10, 115, 91, 152, 78, 3, 104, 115, 9, 51, 35, 36, 242, 124, 45, 186, 133, 233, 219, 21, 232, 58, 1, 67, 56, 46, 151, 75, 6, 33, 193, 142, 98, 94, 206, 201, 7, 87, 125, 158, 123, 173, 233, 82, 65, 168, 30, 187, 232, 169, 1, 212, 211, 39, 110, 64, 177, 20, 192, 162, 230, 252, 56, 209, 156, 46, 106, 171, 2, 100, 75, 40, 19, 245, 117, 252, 33, 96, 30, 13, 238, 73, 205, 158, 233, 106, 67, 16, 62, 82, 77, 98, 135, 61] }
+```
+
+The tags, represent key_tags, as generated when signing with keys and storing in RRSIG records. The current known key_tags are 20326 and 19036. The keys will be output to `/tmp/{key_tag}.{type}`, eg `/tmp/20326.rsa`. See [https://www.icann.org/dns-resolvers-checking-current-trust-anchors](Checking the Current Trust Anchors in DNS Validating Resolvers) for additional help.
+
+Once generated, copy the key to `proto/src/rr/dnssec/roots/` and then add to `proto/src/rr/dnssec/trust_anchor.rs`.
+
+## FAQ
+
+### Can't this be better?
+
+Yes. We should get the signatures for these keys and verify them before adding them.
\ No newline at end of file
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/rsa_public_key.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/rsa_public_key.rs
new file mode 100644
index 0000000..87582ec
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/rsa_public_key.rs
@@ -0,0 +1,42 @@
+// Copyright 2017 Brian Smith <brian@briansmith.org>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+use crate::error::*;
+
+pub struct RSAPublicKey<'a> {
+    n: &'a [u8],
+    e: &'a [u8],
+}
+
+impl<'a> RSAPublicKey<'a> {
+    pub fn try_from(encoded: &'a [u8]) -> ProtoResult<RSAPublicKey<'a>> {
+        let (e_len_len, e_len) = match encoded.get(0) {
+            Some(&0) if encoded.len() >= 3 => {
+                (3, (usize::from(encoded[1]) << 8) | usize::from(encoded[2]))
+            }
+            Some(e_len) if *e_len != 0 => (1, usize::from(*e_len)),
+            _ => {
+                return Err("bad public key".into());
+            }
+        };
+
+        if encoded.len() < e_len_len + e_len {
+            return Err("bad public key".into());
+        };
+
+        let (e, n) = encoded[e_len_len..].split_at(e_len);
+
+        Ok(Self { n, e })
+    }
+
+    pub fn n(&self) -> &[u8] {
+        self.n
+    }
+    pub fn e(&self) -> &[u8] {
+        self.e
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/supported_algorithm.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/supported_algorithm.rs
new file mode 100644
index 0000000..c562371
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/supported_algorithm.rs
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! bitmap for expressing the set of supported algorithms in edns.
+
+use std::convert::From;
+use std::fmt;
+use std::fmt::{Display, Formatter};
+
+use log::warn;
+
+use crate::error::*;
+use crate::rr::dnssec::Algorithm;
+use crate::serialize::binary::{BinEncodable, BinEncoder};
+
+/// Used to specify the set of SupportedAlgorithms between a client and server
+#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash)]
+pub struct SupportedAlgorithms {
+    // right now the number of Algorithms supported are fewer than 16..
+    bit_map: u8,
+}
+
+impl SupportedAlgorithms {
+    /// Return a new set of Supported algorithms
+    pub fn new() -> Self {
+        SupportedAlgorithms { bit_map: 0 }
+    }
+
+    /// Specify the entire set is supported
+    pub fn all() -> Self {
+        SupportedAlgorithms {
+            bit_map: 0b0111_1111,
+        }
+    }
+
+    /// Based on the set of Algorithms, return the supported set
+    pub fn from_vec(algorithms: &[Algorithm]) -> Self {
+        let mut supported = SupportedAlgorithms::new();
+
+        for a in algorithms {
+            supported.set(*a);
+        }
+
+        supported
+    }
+
+    fn pos(algorithm: Algorithm) -> Option<u8> {
+        // not using the values from the RFC's to keep the bit_map space condensed
+        let bit_pos: Option<u8> = match algorithm {
+            Algorithm::RSASHA1 => Some(0),
+            Algorithm::RSASHA256 => Some(1),
+            Algorithm::RSASHA1NSEC3SHA1 => Some(2),
+            Algorithm::RSASHA512 => Some(3),
+            Algorithm::ECDSAP256SHA256 => Some(4),
+            Algorithm::ECDSAP384SHA384 => Some(5),
+            Algorithm::ED25519 => Some(6),
+            Algorithm::Unknown(_) => None,
+        };
+
+        bit_pos.map(|b| 1u8 << b)
+    }
+
+    fn from_pos(pos: u8) -> Option<Algorithm> {
+        // TODO: should build a code generator or possibly a macro for deriving these inversions
+        match pos {
+            0 => Some(Algorithm::RSASHA1),
+            1 => Some(Algorithm::RSASHA256),
+            2 => Some(Algorithm::RSASHA1NSEC3SHA1),
+            3 => Some(Algorithm::RSASHA512),
+            4 => Some(Algorithm::ECDSAP256SHA256),
+            5 => Some(Algorithm::ECDSAP384SHA384),
+            6 => Some(Algorithm::ED25519),
+            _ => None,
+        }
+    }
+
+    /// Set the specified algorithm as supported
+    pub fn set(&mut self, algorithm: Algorithm) {
+        if let Some(bit_pos) = Self::pos(algorithm) {
+            self.bit_map |= bit_pos;
+        }
+    }
+
+    /// Returns true if the algorithm is supported
+    pub fn has(self, algorithm: Algorithm) -> bool {
+        if let Some(bit_pos) = Self::pos(algorithm) {
+            (bit_pos & self.bit_map) == bit_pos
+        } else {
+            false
+        }
+    }
+
+    /// Return an Iterator over the supported set.
+    pub fn iter(&self) -> SupportedAlgorithmsIter {
+        SupportedAlgorithmsIter::new(self)
+    }
+
+    /// Return the count of supported algorithms
+    pub fn len(self) -> u16 {
+        // this is pretty much guaranteed to be less that u16::max_value()
+        self.iter().count() as u16
+    }
+
+    /// Return true if no SupportedAlgorithms are set, this implies the option is not supported
+    pub fn is_empty(self) -> bool {
+        self.bit_map == 0
+    }
+}
+
+impl Default for SupportedAlgorithms {
+    fn default() -> SupportedAlgorithms {
+        SupportedAlgorithms::new()
+    }
+}
+
+impl Display for SupportedAlgorithms {
+    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
+        for a in self.iter() {
+            a.fmt(f)?;
+            f.write_str(", ")?;
+        }
+
+        Ok(())
+    }
+}
+
+impl<'a> From<&'a [u8]> for SupportedAlgorithms {
+    fn from(values: &'a [u8]) -> Self {
+        let mut supported = SupportedAlgorithms::new();
+
+        for a in values.iter().map(|i| Algorithm::from_u8(*i)) {
+            match a {
+                Algorithm::Unknown(v) => warn!("unrecognized algorithm: {}", v),
+                a => supported.set(a),
+            }
+        }
+
+        supported
+    }
+}
+
+impl<'a> From<&'a SupportedAlgorithms> for Vec<u8> {
+    fn from(value: &'a SupportedAlgorithms) -> Vec<u8> {
+        let mut bytes: Vec<u8> = Vec::with_capacity(8); // today this is less than 8
+
+        for a in value.iter() {
+            bytes.push(a.into());
+        }
+
+        bytes.shrink_to_fit();
+        bytes
+    }
+}
+
+impl From<Algorithm> for SupportedAlgorithms {
+    fn from(algorithm: Algorithm) -> Self {
+        SupportedAlgorithms::from_vec(&[algorithm])
+    }
+}
+
+pub struct SupportedAlgorithmsIter<'a> {
+    algorithms: &'a SupportedAlgorithms,
+    current: usize,
+}
+
+impl<'a> SupportedAlgorithmsIter<'a> {
+    pub fn new(algorithms: &'a SupportedAlgorithms) -> Self {
+        SupportedAlgorithmsIter {
+            algorithms,
+            current: 0,
+        }
+    }
+}
+
+impl<'a> Iterator for SupportedAlgorithmsIter<'a> {
+    type Item = Algorithm;
+    fn next(&mut self) -> Option<Self::Item> {
+        // some quick bounds checking
+        if self.current > u8::max_value() as usize {
+            return None;
+        }
+
+        while let Some(algorithm) = SupportedAlgorithms::from_pos(self.current as u8) {
+            self.current += 1;
+            if self.algorithms.has(algorithm) {
+                return Some(algorithm);
+            }
+        }
+
+        None
+    }
+}
+
+impl BinEncodable for SupportedAlgorithms {
+    fn emit(&self, encoder: &mut BinEncoder) -> ProtoResult<()> {
+        for a in self.iter() {
+            encoder.emit_u8(a.into())?;
+        }
+        Ok(())
+    }
+}
+
+#[test]
+fn test_has() {
+    let mut supported = SupportedAlgorithms::new();
+
+    supported.set(Algorithm::RSASHA1);
+
+    assert!(supported.has(Algorithm::RSASHA1));
+    assert!(!supported.has(Algorithm::RSASHA1NSEC3SHA1));
+
+    let mut supported = SupportedAlgorithms::new();
+
+    supported.set(Algorithm::RSASHA256);
+    assert!(!supported.has(Algorithm::RSASHA1));
+    assert!(!supported.has(Algorithm::RSASHA1NSEC3SHA1));
+    assert!(supported.has(Algorithm::RSASHA256));
+}
+
+#[test]
+fn test_iterator() {
+    let supported = SupportedAlgorithms::all();
+    assert_eq!(supported.iter().count(), 7);
+
+    // it just so happens that the iterator has a fixed order...
+    let supported = SupportedAlgorithms::all();
+    let mut iter = supported.iter();
+    assert_eq!(iter.next(), Some(Algorithm::RSASHA1));
+    assert_eq!(iter.next(), Some(Algorithm::RSASHA256));
+    assert_eq!(iter.next(), Some(Algorithm::RSASHA1NSEC3SHA1));
+    assert_eq!(iter.next(), Some(Algorithm::RSASHA512));
+    assert_eq!(iter.next(), Some(Algorithm::ECDSAP256SHA256));
+    assert_eq!(iter.next(), Some(Algorithm::ECDSAP384SHA384));
+    assert_eq!(iter.next(), Some(Algorithm::ED25519));
+
+    let mut supported = SupportedAlgorithms::new();
+    supported.set(Algorithm::RSASHA256);
+    supported.set(Algorithm::RSASHA512);
+
+    let mut iter = supported.iter();
+    assert_eq!(iter.next(), Some(Algorithm::RSASHA256));
+    assert_eq!(iter.next(), Some(Algorithm::RSASHA512));
+}
+
+#[test]
+fn test_vec() {
+    let supported = SupportedAlgorithms::all();
+    let array: Vec<u8> = (&supported).into();
+    let decoded: SupportedAlgorithms = (&array as &[_]).into();
+
+    assert_eq!(supported, decoded);
+
+    let mut supported = SupportedAlgorithms::new();
+    supported.set(Algorithm::RSASHA256);
+    supported.set(Algorithm::ECDSAP256SHA256);
+    supported.set(Algorithm::ECDSAP384SHA384);
+    supported.set(Algorithm::ED25519);
+    let array: Vec<u8> = (&supported).into();
+    let decoded: SupportedAlgorithms = (&array as &[_]).into();
+
+    assert_eq!(supported, decoded);
+    assert!(!supported.has(Algorithm::RSASHA1));
+    assert!(!supported.has(Algorithm::RSASHA1NSEC3SHA1));
+    assert!(supported.has(Algorithm::RSASHA256));
+    assert!(supported.has(Algorithm::ECDSAP256SHA256));
+    assert!(supported.has(Algorithm::ECDSAP384SHA384));
+    assert!(supported.has(Algorithm::ED25519));
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/tbs.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/tbs.rs
new file mode 100644
index 0000000..1d765e2
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/tbs.rs
@@ -0,0 +1,292 @@
+//! hash functions for DNSSec operations
+
+use super::rdata::{sig, DNSSECRData, SIG};
+use crate::error::*;
+use crate::rr::dnssec::Algorithm;
+use crate::rr::{DNSClass, Name, RData, Record, RecordType};
+use crate::serialize::binary::{BinEncodable, BinEncoder, EncodeMode};
+
+/// Data To Be Signed.
+pub struct TBS(Vec<u8>);
+
+impl<'a> From<&'a [u8]> for TBS {
+    fn from(slice: &'a [u8]) -> Self {
+        TBS(slice.to_owned())
+    }
+}
+
+impl AsRef<[u8]> for TBS {
+    fn as_ref(&self) -> &[u8] {
+        self.0.as_ref()
+    }
+}
+
+/// Returns the to-be-signed serialization of the given message.
+pub fn message_tbs<M: BinEncodable>(message: &M, pre_sig0: &SIG) -> ProtoResult<TBS> {
+    // TODO: should perform the serialization and sign block by block to reduce the max memory
+    //  usage, though at 4k max, this is probably unnecessary... For AXFR and large zones, it's
+    //  more important
+    let mut buf: Vec<u8> = Vec::with_capacity(512);
+    let mut buf2: Vec<u8> = Vec::with_capacity(512);
+
+    {
+        let mut encoder: BinEncoder = BinEncoder::with_mode(&mut buf, EncodeMode::Normal);
+        assert!(sig::emit_pre_sig(
+            &mut encoder,
+            pre_sig0.type_covered(),
+            pre_sig0.algorithm(),
+            pre_sig0.num_labels(),
+            pre_sig0.original_ttl(),
+            pre_sig0.sig_expiration(),
+            pre_sig0.sig_inception(),
+            pre_sig0.key_tag(),
+            pre_sig0.signer_name(),
+        )
+        .is_ok());
+        // need a separate encoder here, as the encoding references absolute positions
+        // inside the buffer. If the buffer already contains the sig0 RDATA, offsets
+        // are wrong and the signature won't match.
+        let mut encoder2: BinEncoder = BinEncoder::with_mode(&mut buf2, EncodeMode::Signing);
+        message.emit(&mut encoder2).unwrap(); // coding error if this panics (i think?)
+    }
+
+    buf.append(&mut buf2);
+
+    Ok(TBS(buf))
+}
+
+/// Returns the to-be-signed serialization of the given record set.
+///
+/// # Arguments
+///
+/// * `name` - RRset record name
+/// * `dns_class` - DNSClass, i.e. IN, of the records
+/// * `num_labels` - number of labels in the name, needed to deal with `*.example.com`
+/// * `type_covered` - RecordType of the RRSet being hashed
+/// * `algorithm` - The Algorithm type used for the hashing
+/// * `original_ttl` - Original TTL is the TTL as specified in the SOA zones RRSet associated record
+/// * `sig_expiration` - the epoch seconds of when this hashed signature will expire
+/// * `key_inception` - the epoch seconds of when this hashed signature will be valid
+/// * `signer_name` - label of the etity responsible for signing this hash
+/// * `records` - RRSet to hash
+///
+/// # Returns
+///
+/// the binary hash of the specified RRSet and associated information
+#[allow(clippy::too_many_arguments)]
+pub fn rrset_tbs(
+    name: &Name,
+    dns_class: DNSClass,
+    num_labels: u8,
+    type_covered: RecordType,
+    algorithm: Algorithm,
+    original_ttl: u32,
+    sig_expiration: u32,
+    sig_inception: u32,
+    key_tag: u16,
+    signer_name: &Name,
+    records: &[Record],
+) -> ProtoResult<TBS> {
+    // TODO: change this to a BTreeSet so that it's preordered, no sort necessary
+    let mut rrset: Vec<&Record> = Vec::new();
+
+    // collect only the records for this rrset
+    for record in records {
+        if dns_class == record.dns_class()
+            && type_covered == record.rr_type()
+            && name == record.name()
+        {
+            rrset.push(record);
+        }
+    }
+
+    // put records in canonical order
+    rrset.sort();
+
+    let name: Name = if let Some(name) = determine_name(name, num_labels) {
+        name
+    } else {
+        return Err(format!("could not determine name from {}", name).into());
+    };
+
+    // TODO: rather than buffering here, use the Signer/Verifier? might mean fewer allocations...
+    let mut buf: Vec<u8> = Vec::new();
+
+    {
+        let mut encoder: BinEncoder = BinEncoder::new(&mut buf);
+        encoder.set_canonical_names(true);
+
+        //          signed_data = RRSIG_RDATA | RR(1) | RR(2)...  where
+        //
+        //             "|" denotes concatenation
+        //
+        //             RRSIG_RDATA is the wire format of the RRSIG RDATA fields
+        //                with the Signature field excluded and the Signer's Name
+        //                in canonical form.
+        assert!(sig::emit_pre_sig(
+            &mut encoder,
+            type_covered,
+            algorithm,
+            name.num_labels(),
+            original_ttl,
+            sig_expiration,
+            sig_inception,
+            key_tag,
+            signer_name,
+        )
+        .is_ok());
+
+        // construct the rrset signing data
+        for record in rrset {
+            //             RR(i) = name | type | class | OrigTTL | RDATA length | RDATA
+            //
+            //                name is calculated according to the function in the RFC 4035
+            assert!(name
+                .to_lowercase()
+                .emit_as_canonical(&mut encoder, true)
+                .is_ok());
+            //
+            //                type is the RRset type and all RRs in the class
+            assert!(type_covered.emit(&mut encoder).is_ok());
+            //
+            //                class is the RRset's class
+            assert!(dns_class.emit(&mut encoder).is_ok());
+            //
+            //                OrigTTL is the value from the RRSIG Original TTL field
+            assert!(encoder.emit_u32(original_ttl).is_ok());
+            //
+            //                RDATA length
+            // TODO: add support to the encoder to set a marker to go back and write the length
+            let mut rdata_buf = Vec::new();
+            {
+                let mut rdata_encoder = BinEncoder::new(&mut rdata_buf);
+                rdata_encoder.set_canonical_names(true);
+                assert!(record.rdata().emit(&mut rdata_encoder).is_ok());
+            }
+            assert!(encoder.emit_u16(rdata_buf.len() as u16).is_ok());
+            //
+            //                All names in the RDATA field are in canonical form (set above)
+            assert!(encoder.emit_vec(&rdata_buf).is_ok());
+        }
+    }
+
+    Ok(TBS(buf))
+}
+
+/// Returns the to-be-signed serialization of the given record set using the information
+/// provided from the RRSIG record.
+///
+/// # Arguments
+///
+/// * `rrsig` - SIG or RRSIG record, which was produced from the RRSet
+/// * `records` - RRSet records to sign with the information in the `rrsig`
+///
+/// # Return
+///
+/// binary hash of the RRSet with the information from the RRSIG record
+pub fn rrset_tbs_with_rrsig(rrsig: &Record, records: &[Record]) -> ProtoResult<TBS> {
+    if let RData::DNSSEC(DNSSECRData::SIG(ref sig)) = *rrsig.rdata() {
+        rrset_tbs_with_sig(rrsig.name(), rrsig.dns_class(), sig, records)
+    } else {
+        Err(format!("could not determine name from {}", rrsig.name()).into())
+    }
+}
+
+/// Returns the to-be-signed serialization of the given record set using the information
+/// provided from the SIG record.
+///
+/// # Arguments
+///
+/// * `name` - labels of the record to sign
+/// * `dns_class` - DNSClass of the RRSet, i.e. IN
+/// * `sig` - SIG or RRSIG record, which was produced from the RRSet
+/// * `records` - RRSet records to sign with the information in the `rrsig`
+///
+/// # Return
+///
+/// binary hash of the RRSet with the information from the RRSIG record
+pub fn rrset_tbs_with_sig(
+    name: &Name,
+    dns_class: DNSClass,
+    sig: &SIG,
+    records: &[Record],
+) -> ProtoResult<TBS> {
+    rrset_tbs(
+        name,
+        dns_class,
+        sig.num_labels(),
+        sig.type_covered(),
+        sig.algorithm(),
+        sig.original_ttl(),
+        sig.sig_expiration(),
+        sig.sig_inception(),
+        sig.key_tag(),
+        sig.signer_name(),
+        records,
+    )
+}
+
+/// [RFC 4035](https://tools.ietf.org/html/rfc4035), DNSSEC Protocol Modifications, March 2005
+///
+/// ```text
+///
+/// 5.3.2.  Reconstructing the Signed Data
+///             ...
+///             To calculate the name:
+///                let rrsig_labels = the value of the RRSIG Labels field
+///
+///                let fqdn = RRset's fully qualified domain name in
+///                                canonical form
+///
+///                let fqdn_labels = Label count of the fqdn above.
+///
+///                if rrsig_labels = fqdn_labels,
+///                    name = fqdn
+///
+///                if rrsig_labels < fqdn_labels,
+///                   name = "*." | the rightmost rrsig_label labels of the
+///                                 fqdn
+///
+///                if rrsig_labels > fqdn_labels
+///                   the RRSIG RR did not pass the necessary validation
+///                   checks and MUST NOT be used to authenticate this
+///                   RRset.
+///
+///    The canonical forms for names and RRsets are defined in [RFC4034].
+/// ```
+pub fn determine_name(name: &Name, num_labels: u8) -> Option<Name> {
+    //             To calculate the name:
+    //                let rrsig_labels = the value of the RRSIG Labels field
+    //
+    //                let fqdn = RRset's fully qualified domain name in
+    //                                canonical form
+    //
+    //                let fqdn_labels = Label count of the fqdn above.
+    let fqdn_labels = name.num_labels();
+    //                if rrsig_labels = fqdn_labels,
+    //                    name = fqdn
+
+    if fqdn_labels == num_labels {
+        return Some(name.clone());
+    }
+    //                if rrsig_labels < fqdn_labels,
+    //                   name = "*." | the rightmost rrsig_label labels of the
+    //                                 fqdn
+    if num_labels < fqdn_labels {
+        let mut star_name: Name = Name::from_labels(vec![b"*" as &[u8]]).unwrap();
+        let rightmost = name.trim_to(num_labels as usize);
+        if !rightmost.is_root() {
+            star_name = star_name.append_name(&rightmost);
+            return Some(star_name);
+        }
+        return Some(star_name);
+    }
+    //
+    //                if rrsig_labels > fqdn_labels
+    //                   the RRSIG RR did not pass the necessary validation
+    //                   checks and MUST NOT be used to authenticate this
+    //                   RRset.
+
+    // TODO: this should be an error
+    None
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/trust_anchor.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/trust_anchor.rs
new file mode 100644
index 0000000..70bd007
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/trust_anchor.rs
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! Allows for the root trust_anchor to either be added to or replaced for dns_sec validation.
+
+use std::default::Default;
+
+use crate::rr::dnssec::PublicKey;
+
+const ROOT_ANCHOR_ORIG: &[u8] = include_bytes!("roots/19036.rsa");
+const ROOT_ANCHOR_2018: &[u8] = include_bytes!("roots/20326.rsa");
+
+/// The root set of trust anchors for validating DNSSec, anything in this set will be trusted
+pub struct TrustAnchor {
+    // TODO: these should also store some information, or more specifically, metadata from the signed
+    //  public certificate.
+    pkeys: Vec<Vec<u8>>,
+}
+
+impl Default for TrustAnchor {
+    fn default() -> TrustAnchor {
+        TrustAnchor {
+            pkeys: vec![ROOT_ANCHOR_ORIG.to_owned(), ROOT_ANCHOR_2018.to_owned()],
+        }
+    }
+}
+
+impl TrustAnchor {
+    /// Creates a new empty trust anchor set
+    pub fn new() -> TrustAnchor {
+        TrustAnchor { pkeys: vec![] }
+    }
+
+    /// determines if the key is in the trust anchor set with the raw dnskey bytes
+    ///
+    /// # Arguments
+    ///
+    /// * `other_key` - The raw dnskey in bytes
+    pub fn contains_dnskey_bytes(&self, other_key: &[u8]) -> bool {
+        self.pkeys.iter().any(|k| other_key == k.as_slice())
+    }
+
+    /// determines if the key is in the trust anchor set
+    pub fn contains<P: PublicKey>(&self, other_key: &P) -> bool {
+        self.contains_dnskey_bytes(other_key.public_bytes())
+    }
+
+    /// inserts the trust_anchor to the trusted chain
+    pub fn insert_trust_anchor<P: PublicKey>(&mut self, public_key: &P) {
+        if !self.contains(public_key) {
+            self.pkeys.push(public_key.public_bytes().to_vec())
+        }
+    }
+
+    /// get the trust anchor at the specified index
+    pub fn get(&self, idx: usize) -> &[u8] {
+        &self.pkeys[idx]
+    }
+}
+
+#[test]
+fn test_kjqmt7v() {
+    let trust = TrustAnchor::default();
+    assert_eq!(trust.get(0), ROOT_ANCHOR_ORIG);
+    assert!(trust.contains_dnskey_bytes(ROOT_ANCHOR_ORIG));
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/verifier.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/verifier.rs
new file mode 100644
index 0000000..c3a50c8
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/dnssec/verifier.rs
@@ -0,0 +1,91 @@
+//! Verifier is a structure for performing many of the signing processes of the DNSSec specification
+
+use crate::error::*;
+use crate::rr::dnssec::rdata::{DNSKEY, KEY, SIG};
+use crate::rr::dnssec::Algorithm;
+use crate::rr::dnssec::{tbs, PublicKey, PublicKeyEnum};
+use crate::rr::{DNSClass, Name, Record};
+use crate::serialize::binary::BinEncodable;
+
+/// Types which are able to verify DNS based signatures
+pub trait Verifier {
+    /// Return the algorithm which this Verifier covers
+    fn algorithm(&self) -> Algorithm;
+
+    /// Return the public key associated with this verifier
+    fn key<'k>(&'k self) -> ProtoResult<PublicKeyEnum<'k>>;
+
+    /// Verifies the hash matches the signature with the current `key`.
+    ///
+    /// # Arguments
+    ///
+    /// * `hash` - the hash to be validated, see `rrset_tbs`
+    /// * `signature` - the signature to use to verify the hash, extracted from an `RData::RRSIG`
+    ///                 for example.
+    ///
+    /// # Return value
+    ///
+    /// True if and only if the signature is valid for the hash.
+    /// false if the `key`.
+    fn verify(&self, hash: &[u8], signature: &[u8]) -> ProtoResult<()> {
+        self.key()?.verify(self.algorithm(), hash, signature)
+    }
+
+    /// Verifies a message with the against the given signature, i.e. SIG0
+    ///
+    /// # Arguments
+    ///
+    /// * `message` - the message to verify
+    /// * `signature` - the signature to use for validation
+    ///
+    /// # Return value
+    ///
+    /// `true` if the message could be validated against the signature, `false` otherwise
+    fn verify_message<M: BinEncodable>(
+        &self,
+        message: &M,
+        signature: &[u8],
+        sig0: &SIG,
+    ) -> ProtoResult<()> {
+        tbs::message_tbs(message, sig0).and_then(|tbs| self.verify(tbs.as_ref(), signature))
+    }
+
+    /// Verifies an RRSig with the associated key, e.g. DNSKEY
+    ///
+    /// # Arguments
+    ///
+    /// * `name` - name associated with the rrsig being validated
+    /// * `dns_class` - DNSClass of the records, generally IN
+    /// * `sig` - signature record being validated
+    /// * `records` - Records covered by SIG
+    fn verify_rrsig(
+        &self,
+        name: &Name,
+        dns_class: DNSClass,
+        sig: &SIG,
+        records: &[Record],
+    ) -> ProtoResult<()> {
+        let rrset_tbs = tbs::rrset_tbs_with_sig(name, dns_class, sig, records)?;
+        self.verify(rrset_tbs.as_ref(), sig.sig())
+    }
+}
+
+impl Verifier for DNSKEY {
+    fn algorithm(&self) -> Algorithm {
+        self.algorithm()
+    }
+
+    fn key<'k>(&'k self) -> ProtoResult<PublicKeyEnum<'k>> {
+        PublicKeyEnum::from_public_bytes(self.public_key(), self.algorithm())
+    }
+}
+
+impl Verifier for KEY {
+    fn algorithm(&self) -> Algorithm {
+        self.algorithm()
+    }
+
+    fn key<'k>(&'k self) -> ProtoResult<PublicKeyEnum<'k>> {
+        PublicKeyEnum::from_public_bytes(self.public_key(), self.algorithm())
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/domain/label.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/domain/label.rs
new file mode 100644
index 0000000..b359159
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/domain/label.rs
@@ -0,0 +1,503 @@
+// Copyright 2015-2018 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! Labels are used as the internal components of a Name.
+//!
+//! A label is stored internally as ascii, where all unicode characters are converted to punycode internally.
+
+#[allow(clippy::useless_attribute)]
+#[allow(unused)]
+#[allow(deprecated)]
+use std::ascii::AsciiExt;
+use std::borrow::Borrow;
+use std::cmp::{Ordering, PartialEq};
+use std::fmt::{self, Debug, Display, Formatter, Write};
+use std::hash::{Hash, Hasher};
+use std::sync::Arc as Rc;
+
+use idna;
+use log::debug;
+
+use crate::error::*;
+
+const WILDCARD: &[u8] = b"*";
+const IDNA_PREFIX: &[u8] = b"xn--";
+
+/// Labels are always stored as ASCII, unicode characters must be encoded with punycode
+#[derive(Clone, Eq)]
+pub struct Label(Rc<[u8]>);
+
+impl Label {
+    /// These must only be ASCII, with unicode encoded to PunyCode, or other such transformation.
+    ///
+    /// This uses the bytes as raw ascii values, with nothing escaped on the wire.
+    /// Generally users should use `from_str` or `from_ascii`
+    pub fn from_raw_bytes(bytes: &[u8]) -> ProtoResult<Self> {
+        if bytes.len() > 63 {
+            return Err(format!("Label exceeds maximum length 63: {}", bytes.len()).into());
+        };
+        Ok(Label(Rc::from(bytes)))
+    }
+
+    /// Translates this string into IDNA safe name, encoding to punycode as necessary.
+    pub fn from_utf8(s: &str) -> ProtoResult<Self> {
+        if s.as_bytes() == WILDCARD {
+            return Ok(Label::wildcard());
+        }
+
+        // special case for SRV type records
+        if s.starts_with('_') {
+            return Self::from_ascii(s);
+        }
+
+        match idna::Config::default()
+            .use_std3_ascii_rules(true)
+            .transitional_processing(true)
+            .verify_dns_length(true)
+            .to_ascii(s)
+        {
+            Ok(puny) => Self::from_ascii(&puny),
+            e => Err(format!("Label contains invalid characters: {:?}", e).into()),
+        }
+    }
+
+    /// Takes the ascii string and returns a new label.
+    ///
+    /// This will return an Error if the label is not an ascii string
+    pub fn from_ascii(s: &str) -> ProtoResult<Self> {
+        if s.as_bytes() == WILDCARD {
+            return Ok(Label::wildcard());
+        }
+
+        if !s.is_empty()
+            && s.is_ascii()
+            && s.chars().take(1).all(|c| is_safe_ascii(c, true, false))
+            && s.chars().skip(1).all(|c| is_safe_ascii(c, false, false))
+        {
+            Label::from_raw_bytes(s.as_bytes())
+        } else {
+            Err(format!("Malformed label: {}", s).into())
+        }
+    }
+
+    /// Returns a new Label of the Wildcard, i.e. "*"
+    pub fn wildcard() -> Self {
+        Label(Rc::from(WILDCARD.to_vec()))
+    }
+
+    /// Converts this label to lowercase
+    pub fn to_lowercase(&self) -> Self {
+        // TODO: replace case conversion when (ascii_ctype #39658) stabilizes
+        if let Some((idx, _)) = self
+            .0
+            .iter()
+            .enumerate()
+            .find(|&(_, c)| *c != c.to_ascii_lowercase())
+        {
+            let mut lower_label: Vec<u8> = self.0.to_vec();
+            lower_label[idx..].make_ascii_lowercase();
+            Label(Rc::from(lower_label))
+        } else {
+            self.clone()
+        }
+    }
+
+    /// Returns true if this label is the wildcard, '*', label
+    pub fn is_wildcard(&self) -> bool {
+        self.as_bytes() == WILDCARD
+    }
+
+    /// Returns the lenght in bytes of this label
+    pub fn len(&self) -> usize {
+        self.0.len()
+    }
+
+    /// True if the label contains no characters
+    pub fn is_empty(&self) -> bool {
+        self.0.is_empty()
+    }
+
+    /// Returns the raw bytes of the label, this is good for writing to the wire.
+    ///
+    /// See [`Display`] for presentation version (unescaped from punycode, etc)
+    pub fn as_bytes(&self) -> &[u8] {
+        &self.0
+    }
+
+    /// Performs the equivalence operation disregarding case
+    pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
+        self.0.eq_ignore_ascii_case(&other.0)
+    }
+
+    /// compares with the other label, ignoring case
+    pub fn cmp_with_f<F: LabelCmp>(&self, other: &Self) -> Ordering {
+        let s = self.0.iter();
+        let o = other.0.iter();
+
+        for (s, o) in s.zip(o) {
+            match F::cmp_u8(*s, *o) {
+                Ordering::Equal => continue,
+                not_eq => return not_eq,
+            }
+        }
+
+        self.0.len().cmp(&other.0.len())
+    }
+
+    /// Performs the conversion to utf8 from IDNA as necessary, see `fmt` for more details
+    pub fn to_utf8(&self) -> String {
+        format!("{}", self)
+    }
+
+    /// Converts this label to safe ascii, escaping characters as necessary
+    ///
+    /// If this is an IDNA, punycode, label, then the xn-- prefix will be maintained as ascii
+    pub fn to_ascii(&self) -> String {
+        let mut ascii = String::with_capacity(self.as_bytes().len());
+
+        self.write_ascii(&mut ascii)
+            .expect("should never fail to write a new string");
+        ascii
+    }
+
+    /// Writes this label to safe ascii, escaping characters as necessary
+    pub fn write_ascii<W: Write>(&self, f: &mut W) -> Result<(), fmt::Error> {
+        // We can't guarantee that the same input will always translate to the same output
+        fn escape_non_ascii<W: Write>(
+            byte: u8,
+            f: &mut W,
+            is_first: bool,
+        ) -> Result<(), fmt::Error> {
+            let to_triple_escape = |ch: u8| format!("\\{:03o}", ch);
+            let to_single_escape = |ch: char| format!("\\{}", ch);
+
+            match char::from(byte) {
+                c if is_safe_ascii(c, is_first, true) => f.write_char(c)?,
+                // it's not a control and is printable as well as inside the standard ascii range
+                c if byte > b'\x20' && byte < b'\x7f' => f.write_str(&to_single_escape(c))?,
+                _ => f.write_str(&to_triple_escape(byte))?,
+            }
+
+            Ok(())
+        }
+
+        // traditional ascii case...
+        let mut chars = self.as_bytes().iter();
+        if let Some(ch) = chars.next() {
+            escape_non_ascii(*ch, f, true)?;
+        }
+
+        for ch in chars {
+            escape_non_ascii(*ch, f, false)?;
+        }
+
+        Ok(())
+    }
+}
+
+impl AsRef<[u8]> for Label {
+    fn as_ref(&self) -> &[u8] {
+        &self.0
+    }
+}
+
+impl Borrow<[u8]> for Label {
+    fn borrow(&self) -> &[u8] {
+        &self.0
+    }
+}
+
+fn is_safe_ascii(c: char, is_first: bool, for_encoding: bool) -> bool {
+    match c {
+        c if !c.is_ascii() => false,
+        c if c.is_alphanumeric() => true,
+        '-' if !is_first => true,     // dash is allowed
+        '_' => true,                  // SRV like labels
+        '*' if is_first => true,      // wildcard
+        '.' if !for_encoding => true, // needed to allow dots, for things like email addresses
+        _ => false,
+    }
+}
+
+impl Display for Label {
+    /// outputs characters in a safe string manner.
+    ///
+    /// if the string is punycode, i.e. starts with `xn--`, otherwise it translates to a safe ascii string
+    ///   escaping characters as necessary.
+    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
+        if self.as_bytes().starts_with(IDNA_PREFIX) {
+            // this should never be outside the ascii codes...
+            let label = String::from_utf8_lossy(self.borrow());
+            let (label, e) = idna::Config::default()
+                .use_std3_ascii_rules(false)
+                .transitional_processing(false)
+                .verify_dns_length(false)
+                .to_unicode(&label);
+
+            if e.is_ok() {
+                return f.write_str(&label);
+            } else {
+                debug!(
+                    "xn-- prefixed string did not translate via IDNA properly: {:?}",
+                    e
+                )
+            }
+        }
+
+        // it wasn't known to be utf8
+        self.write_ascii(f)
+    }
+}
+
+impl Debug for Label {
+    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
+        let label = String::from_utf8_lossy(self.borrow());
+        f.write_str(&label)
+    }
+}
+
+impl PartialEq<Label> for Label {
+    fn eq(&self, other: &Self) -> bool {
+        self.eq_ignore_ascii_case(other)
+    }
+}
+
+impl PartialOrd<Label> for Label {
+    fn partial_cmp(&self, other: &Label) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl Ord for Label {
+    fn cmp(&self, other: &Self) -> Ordering {
+        self.cmp_with_f::<CaseInsensitive>(other)
+    }
+}
+
+impl Hash for Label {
+    fn hash<H>(&self, state: &mut H)
+    where
+        H: Hasher,
+    {
+        for b in self.borrow() as &[u8] {
+            state.write_u8(b.to_ascii_lowercase());
+        }
+    }
+}
+
+/// Label comparison trait for case sensitive or insensitive comparisons
+pub trait LabelCmp {
+    /// this should mimic the cmp method from [`PartialOrd`]
+    fn cmp_u8(l: u8, r: u8) -> Ordering;
+}
+
+/// For case sensitive comparisons
+pub(super) struct CaseSensitive;
+
+impl LabelCmp for CaseSensitive {
+    fn cmp_u8(l: u8, r: u8) -> Ordering {
+        l.cmp(&r)
+    }
+}
+
+/// For case insensitive comparisons
+pub(super) struct CaseInsensitive;
+
+impl LabelCmp for CaseInsensitive {
+    fn cmp_u8(l: u8, r: u8) -> Ordering {
+        l.to_ascii_lowercase().cmp(&r.to_ascii_lowercase())
+    }
+}
+
+/// Conversion into a Label
+pub trait IntoLabel: Sized {
+    /// Convert this into Label
+    fn into_label(self: Self) -> ProtoResult<Label>;
+}
+
+impl<'a> IntoLabel for &'a Label {
+    fn into_label(self: Self) -> ProtoResult<Label> {
+        Ok(self.clone())
+    }
+}
+
+impl IntoLabel for Label {
+    fn into_label(self: Self) -> ProtoResult<Label> {
+        Ok(self)
+    }
+}
+
+impl<'a> IntoLabel for &'a str {
+    fn into_label(self: Self) -> ProtoResult<Label> {
+        Label::from_utf8(self)
+    }
+}
+
+impl IntoLabel for String {
+    fn into_label(self: Self) -> ProtoResult<Label> {
+        Label::from_utf8(&self)
+    }
+}
+
+impl<'a> IntoLabel for &'a [u8] {
+    fn into_label(self: Self) -> ProtoResult<Label> {
+        Label::from_raw_bytes(self)
+    }
+}
+
+impl IntoLabel for Vec<u8> {
+    fn into_label(self: Self) -> ProtoResult<Label> {
+        Label::from_raw_bytes(&self)
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    #![allow(clippy::dbg_macro, clippy::print_stdout)]
+
+    use super::*;
+
+    #[test]
+    fn test_encoding() {
+        assert_eq!(
+            Label::from_utf8("abc").unwrap(),
+            Label::from_raw_bytes(b"abc").unwrap()
+        );
+        // case insensitive, this works...
+        assert_eq!(
+            Label::from_utf8("ABC").unwrap(),
+            Label::from_raw_bytes(b"ABC").unwrap()
+        );
+        assert_eq!(
+            Label::from_utf8("🦀").unwrap(),
+            Label::from_raw_bytes(b"xn--zs9h").unwrap()
+        );
+        assert_eq!(
+            Label::from_utf8("rust-🦀-icon").unwrap(),
+            Label::from_raw_bytes(b"xn--rust--icon-9447i").unwrap()
+        );
+        assert_eq!(
+            Label::from_ascii("ben.fry").unwrap(),
+            Label::from_raw_bytes(b"ben.fry").unwrap()
+        );
+        assert_eq!(Label::from_utf8("🦀").unwrap().to_utf8(), "🦀");
+        assert_eq!(Label::from_utf8("🦀").unwrap().to_ascii(), "xn--zs9h");
+    }
+
+    #[test]
+    fn test_decoding() {
+        assert_eq!(Label::from_raw_bytes(b"abc").unwrap().to_string(), "abc");
+        assert_eq!(
+            Label::from_raw_bytes(b"xn--zs9h").unwrap().to_string(),
+            "🦀"
+        );
+        assert_eq!(
+            Label::from_raw_bytes(b"xn--rust--icon-9447i")
+                .unwrap()
+                .to_string(),
+            "rust-🦀-icon"
+        );
+    }
+
+    #[test]
+    fn test_to_lowercase() {
+        assert_ne!(Label::from_ascii("ABC").unwrap().to_string(), "abc");
+        assert_ne!(Label::from_ascii("abcDEF").unwrap().to_string(), "abcdef");
+        assert_eq!(
+            Label::from_ascii("ABC").unwrap().to_lowercase().to_string(),
+            "abc"
+        );
+        assert_eq!(
+            Label::from_ascii("abcDEF")
+                .unwrap()
+                .to_lowercase()
+                .to_string(),
+            "abcdef"
+        );
+    }
+
+    #[test]
+    fn test_to_cmp_f() {
+        assert_eq!(
+            Label::from_ascii("ABC")
+                .unwrap()
+                .cmp_with_f::<CaseInsensitive>(&Label::from_ascii("abc").unwrap()),
+            Ordering::Equal
+        );
+        assert_eq!(
+            Label::from_ascii("abcDEF")
+                .unwrap()
+                .cmp_with_f::<CaseInsensitive>(&Label::from_ascii("abcdef").unwrap()),
+            Ordering::Equal
+        );
+        assert_eq!(
+            Label::from_ascii("ABC")
+                .unwrap()
+                .cmp_with_f::<CaseSensitive>(&Label::from_ascii("abc").unwrap()),
+            Ordering::Less
+        );
+        assert_eq!(
+            Label::from_ascii("abcDEF")
+                .unwrap()
+                .cmp_with_f::<CaseSensitive>(&Label::from_ascii("abcdef").unwrap()),
+            Ordering::Less
+        );
+    }
+
+    #[test]
+    fn test_partial_cmp() {
+        let comparisons: Vec<(Label, Label)> = vec![
+            (
+                Label::from_raw_bytes(b"yljkjljk").unwrap(),
+                Label::from_raw_bytes(b"Z").unwrap(),
+            ),
+            (
+                Label::from_raw_bytes(b"Z").unwrap(),
+                Label::from_raw_bytes(b"zABC").unwrap(),
+            ),
+            (
+                Label::from_raw_bytes(&[1]).unwrap(),
+                Label::from_raw_bytes(b"*").unwrap(),
+            ),
+            (
+                Label::from_raw_bytes(b"*").unwrap(),
+                Label::from_raw_bytes(&[200]).unwrap(),
+            ),
+        ];
+
+        for (left, right) in comparisons {
+            println!("left: {}, right: {}", left, right);
+            assert_eq!(left.cmp(&right), Ordering::Less);
+        }
+    }
+
+    #[test]
+    fn test_is_wildcard() {
+        assert!(Label::from_raw_bytes(b"*").unwrap().is_wildcard());
+        assert!(Label::from_ascii("*").unwrap().is_wildcard());
+        assert!(Label::from_utf8("*").unwrap().is_wildcard());
+        assert!(!Label::from_raw_bytes(b"abc").unwrap().is_wildcard());
+    }
+
+    #[test]
+    fn test_ascii_escape() {
+        assert_eq!(
+            Label::from_raw_bytes(&[0o200]).unwrap().to_string(),
+            "\\200"
+        );
+        assert_eq!(
+            Label::from_raw_bytes(&[0o001]).unwrap().to_string(),
+            "\\001"
+        );
+        assert_eq!(Label::from_ascii(".").unwrap().to_ascii(), "\\.");
+        assert_eq!(
+            Label::from_ascii("ben.fry").unwrap().to_string(),
+            "ben\\.fry"
+        );
+        assert_eq!(Label::from_raw_bytes(&[0o200]).unwrap().to_ascii(), "\\200");
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/domain/mod.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/domain/mod.rs
new file mode 100644
index 0000000..80b4e98
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/domain/mod.rs
@@ -0,0 +1,17 @@
+// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! Domain name associated types, such as Name and Label.
+
+mod label;
+mod name;
+mod try_parse_ip;
+pub mod usage;
+
+pub use self::label::{IntoLabel, Label};
+pub use self::name::{IntoName, Name};
+pub use self::try_parse_ip::TryParseIp;
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/domain/name.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/domain/name.rs
new file mode 100644
index 0000000..b1bc9c0
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/domain/name.rs
@@ -0,0 +1,1647 @@
+// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! domain name, aka labels, implementation
+
+use std::borrow::Borrow;
+use std::char;
+use std::cmp::{Ordering, PartialEq};
+use std::fmt::{self, Write};
+use std::hash::{Hash, Hasher};
+use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+use std::ops::Index;
+use std::slice::Iter;
+use std::str::FromStr;
+
+use crate::error::*;
+use crate::rr::domain::label::{CaseInsensitive, CaseSensitive, IntoLabel, Label, LabelCmp};
+use crate::rr::domain::usage::LOCALHOST as LOCALHOST_usage;
+use crate::serialize::binary::*;
+#[cfg(feature = "serde-config")]
+use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
+
+/// Them should be through references. As a workaround the Strings are all Rc as well as the array
+#[derive(Clone, Default, Debug, Eq)]
+pub struct Name {
+    is_fqdn: bool,
+    labels: Vec<Label>,
+}
+
+impl Name {
+    /// Create a new domain::Name, i.e. label
+    pub fn new() -> Self {
+        Default::default()
+    }
+
+    /// Returns the root label, i.e. no labels, can probably make this better in the future.
+    pub fn root() -> Self {
+        let mut this = Self::new();
+        this.is_fqdn = true;
+        this
+    }
+
+    /// Returns true if there are no labels, i.e. it's empty.
+    ///
+    /// In DNS the root is represented by `.`
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use trust_dns_proto::rr::domain::Name;
+    ///
+    /// let root = Name::root();
+    /// assert_eq!(&root.to_string(), ".");
+    /// ```
+    pub fn is_root(&self) -> bool {
+        self.labels.is_empty() && self.is_fqdn()
+    }
+
+    /// Returns true if the name is a fully qualified domain name.
+    ///
+    /// If this is true, it has effects like only querying for this single name, as opposed to building
+    ///  up a search list in resolvers.
+    ///
+    /// *warning: this interface is unstable and may change in the future*
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::str::FromStr;
+    /// use trust_dns_proto::rr::domain::Name;
+    ///
+    /// let name = Name::from_str("www").unwrap();
+    /// assert!(!name.is_fqdn());
+    ///
+    /// let name = Name::from_str("www.example.com").unwrap();
+    /// assert!(!name.is_fqdn());
+    ///
+    /// let name = Name::from_str("www.example.com.").unwrap();
+    /// assert!(name.is_fqdn());
+    /// ```
+    pub fn is_fqdn(&self) -> bool {
+        self.is_fqdn
+    }
+
+    /// Specifies this name is a fully qualified domain name
+    ///
+    /// *warning: this interface is unstable and may change in the future*
+    pub fn set_fqdn(&mut self, val: bool) {
+        self.is_fqdn = val
+    }
+
+    /// Returns an iterator over the labels
+    pub fn iter(&self) -> LabelIter {
+        LabelIter(self.labels.iter())
+    }
+
+    /// Appends the label to the end of this name
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// use std::str::FromStr;
+    /// use trust_dns_proto::rr::domain::Name;
+    ///
+    /// let name = Name::from_str("www.example").unwrap();
+    /// let name = name.append_label("com").unwrap();
+    /// assert_eq!(name, Name::from_str("www.example.com").unwrap());
+    /// ```
+    pub fn append_label<L: IntoLabel>(mut self, label: L) -> ProtoResult<Self> {
+        self.labels.push(label.into_label()?);
+        if self.labels.len() > 255 {
+            return Err("labels exceed maximum length of 255".into());
+        };
+        Ok(self)
+    }
+
+    /// Creates a new Name from the specified labels
+    ///
+    /// # Arguments
+    ///
+    /// * `labels` - vector of items which will be stored as Strings.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// use std::str::FromStr;
+    /// use trust_dns_proto::rr::domain::Name;
+    ///
+    /// // From strings, uses utf8 conversion
+    /// let from_labels = Name::from_labels(vec!["www", "example", "com"]).unwrap();
+    /// assert_eq!(from_labels, Name::from_str("www.example.com").unwrap());
+    ///
+    /// // Force a set of bytes into labels (this is none-standard and potentially dangerous)
+    /// let from_labels = Name::from_labels(vec!["bad chars".as_bytes(), "example".as_bytes(), "com".as_bytes()]).unwrap();
+    /// assert_eq!(from_labels[0].as_bytes(), "bad chars".as_bytes());
+    ///
+    /// let root = Name::from_labels(Vec::<&str>::new()).unwrap();
+    /// assert!(root.is_root());
+    /// ```
+    pub fn from_labels<I, L>(labels: I) -> ProtoResult<Self>
+    where
+        I: IntoIterator<Item = L>,
+        L: IntoLabel,
+    {
+        let (labels, errors): (Vec<_>, Vec<_>) = labels
+            .into_iter()
+            .map(IntoLabel::into_label)
+            .partition(Result::is_ok);
+        let labels: Vec<_> = labels.into_iter().map(Result::unwrap).collect();
+        let errors: Vec<_> = errors.into_iter().map(Result::unwrap_err).collect();
+
+        if labels.len() > 255 {
+            return Err("labels exceed maximum length of 255".into());
+        };
+        if !errors.is_empty() {
+            return Err(format!("error converting some labels: {:?}", errors).into());
+        };
+
+        Ok(Name {
+            is_fqdn: true,
+            labels,
+        })
+    }
+
+    /// Appends `other` to `self`, returning a new `Name`
+    ///
+    /// Carries forward `is_fqdn` from `other`.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// use std::str::FromStr;
+    /// use trust_dns_proto::rr::domain::Name;
+    ///
+    /// let local = Name::from_str("www").unwrap();
+    /// let domain = Name::from_str("example.com").unwrap();
+    /// assert!(!domain.is_fqdn());
+    ///
+    /// let name = local.clone().append_name(&domain);
+    /// assert_eq!(name, Name::from_str("www.example.com").unwrap());
+    /// assert!(!name.is_fqdn());
+    ///
+    /// // see also `Name::append_domain`
+    /// let domain = Name::from_str("example.com.").unwrap();
+    /// assert!(domain.is_fqdn());
+    /// let name = local.append_name(&domain);
+    /// assert_eq!(name, Name::from_str("www.example.com.").unwrap());
+    /// assert!(name.is_fqdn());
+    /// ```
+    pub fn append_name(mut self, other: &Self) -> Self {
+        self.labels.reserve_exact(other.labels.len());
+        for label in &other.labels {
+            self.labels.push(label.clone());
+        }
+
+        self.is_fqdn = other.is_fqdn;
+        self
+    }
+
+    /// Appends the `domain` to `self`, making the new `Name` an FQDN
+    ///
+    /// This is an alias for `append_name` with the added effect of marking the new `Name` as
+    /// a fully-qualified-domain-name.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// use std::str::FromStr;
+    /// use trust_dns_proto::rr::domain::Name;
+    ///
+    /// let local = Name::from_str("www").unwrap();
+    /// let domain = Name::from_str("example.com").unwrap();
+    /// let name = local.append_domain(&domain);
+    /// assert_eq!(name, Name::from_str("www.example.com").unwrap());
+    /// assert!(name.is_fqdn())
+    /// ```
+    pub fn append_domain(self, domain: &Self) -> Self {
+        let mut this = self.append_name(domain);
+        this.set_fqdn(true);
+        this
+    }
+
+    /// Creates a new Name with all labels lowercased
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::cmp::Ordering;
+    /// use std::str::FromStr;
+    ///
+    /// use trust_dns_proto::rr::domain::{Label, Name};
+    ///
+    /// let example_com = Name::from_ascii("Example.Com").unwrap();
+    /// assert_eq!(example_com.cmp_case(&Name::from_str("example.com").unwrap()), Ordering::Less);
+    /// assert!(example_com.to_lowercase().eq_case(&Name::from_str("example.com").unwrap()));
+    /// ```
+    pub fn to_lowercase(&self) -> Self {
+        let mut new_labels: Vec<Label> = Vec::with_capacity(self.labels.len());
+        for label in &self.labels {
+            new_labels.push(label.to_lowercase())
+        }
+
+        Name {
+            is_fqdn: self.is_fqdn,
+            labels: new_labels,
+        }
+    }
+
+    /// Trims off the first part of the name, to help with searching for the domain piece
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::str::FromStr;
+    /// use trust_dns_proto::rr::domain::Name;
+    ///
+    /// let example_com = Name::from_str("example.com.").unwrap();
+    /// assert_eq!(example_com.base_name(), Name::from_str("com.").unwrap());
+    /// assert_eq!(Name::from_str("com.").unwrap().base_name(), Name::root());
+    /// assert_eq!(Name::root().base_name(), Name::root());
+    /// ```
+    pub fn base_name(&self) -> Name {
+        let length = self.labels.len();
+        if length > 0 {
+            return self.trim_to(length - 1);
+        }
+        self.clone()
+    }
+
+    /// Trims to the number of labels specified
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::str::FromStr;
+    /// use trust_dns_proto::rr::domain::Name;
+    ///
+    /// let example_com = Name::from_str("example.com.").unwrap();
+    /// assert_eq!(example_com.trim_to(2), Name::from_str("example.com.").unwrap());
+    /// assert_eq!(example_com.trim_to(1), Name::from_str("com.").unwrap());
+    /// assert_eq!(example_com.trim_to(0), Name::root());
+    /// assert_eq!(example_com.trim_to(3), Name::from_str("example.com.").unwrap());
+    /// ```
+    pub fn trim_to(&self, num_labels: usize) -> Name {
+        if self.labels.len() >= num_labels {
+            let trim = self.labels.len() - num_labels;
+            Name {
+                is_fqdn: self.is_fqdn,
+                labels: self.labels[trim..].to_vec(),
+            }
+        } else {
+            self.clone()
+        }
+    }
+
+    /// same as `zone_of` allows for case sensitive call
+    pub fn zone_of_case(&self, name: &Self) -> bool {
+        let self_len = self.labels.len();
+        let name_len = name.labels.len();
+        if self_len == 0 {
+            return true;
+        }
+        if name_len == 0 {
+            // self_len != 0
+            return false;
+        }
+        if self_len > name_len {
+            return false;
+        }
+
+        let self_iter = self.iter().rev();
+        let name_iter = name.iter().rev();
+
+        let zip_iter = self_iter.zip(name_iter);
+
+        for (self_label, name_label) in zip_iter {
+            if self_label != name_label {
+                return false;
+            }
+        }
+
+        true
+    }
+
+    /// returns true if the name components of self are all present at the end of name
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// use std::str::FromStr;
+    /// use trust_dns_proto::rr::domain::Name;
+    ///
+    /// let name = Name::from_str("www.example.com").unwrap();
+    /// let name = Name::from_str("www.example.com").unwrap();
+    /// let zone = Name::from_str("example.com").unwrap();
+    /// let another = Name::from_str("example.net").unwrap();
+    /// assert!(zone.zone_of(&name));
+    /// assert!(!name.zone_of(&zone));
+    /// assert!(!another.zone_of(&name));
+    /// ```
+    pub fn zone_of(&self, name: &Self) -> bool {
+        let self_lower = self.to_lowercase();
+        let name_lower = name.to_lowercase();
+
+        self_lower.zone_of_case(&name_lower)
+    }
+
+    /// Returns the number of labels in the name, discounting `*`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::str::FromStr;
+    /// use trust_dns_proto::rr::domain::Name;
+    ///
+    /// let root = Name::root();
+    /// assert_eq!(root.num_labels(), 0);
+    ///
+    /// let example_com = Name::from_str("example.com").unwrap();
+    /// assert_eq!(example_com.num_labels(), 2);
+    ///
+    /// let star_example_com = Name::from_str("*.example.com.").unwrap();
+    /// assert_eq!(star_example_com.num_labels(), 2);
+    /// ```
+    pub fn num_labels(&self) -> u8 {
+        // it is illegal to have more than 256 labels.
+
+        let num = self.labels.len() as u8;
+
+        self.labels
+            .first()
+            .map(|l| if l.is_wildcard() { num - 1 } else { num })
+            .unwrap_or(num)
+    }
+
+    /// returns the length in bytes of the labels. '.' counts as 1
+    ///
+    /// This can be used as an estimate, when serializing labels, they will often be compressed
+    /// and/or escaped causing the exact length to be different.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::str::FromStr;
+    /// use trust_dns_proto::rr::domain::Name;
+    ///
+    /// assert_eq!(Name::from_str("www.example.com.").unwrap().len(), 16);
+    /// assert_eq!(Name::from_str(".").unwrap().len(), 1);
+    /// assert_eq!(Name::root().len(), 1);
+    /// ```
+    pub fn len(&self) -> usize {
+        let dots = if !self.labels.is_empty() {
+            self.labels.len()
+        } else {
+            1
+        };
+        self.labels.iter().fold(dots, |acc, item| acc + item.len())
+    }
+
+    /// Returns whether the length of the labels, in bytes is 0. In practice, since '.' counts as
+    /// 1, this is never the case so the method returns false.
+    pub fn is_empty(&self) -> bool {
+        false
+    }
+
+    /// attempts to parse a name such as `"example.com."` or `"subdomain.example.com."`
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// use std::str::FromStr;
+    /// use trust_dns_proto::rr::domain::Name;
+    ///
+    /// let name = Name::from_str("example.com.").unwrap();
+    /// assert_eq!(name.base_name(), Name::from_str("com.").unwrap());
+    /// assert_eq!(name[0].to_string(), "example");
+    /// ```
+    pub fn parse(local: &str, origin: Option<&Self>) -> ProtoResult<Self> {
+        Self::from_encoded_str::<LabelEncUtf8>(local, origin)
+    }
+
+    /// Will convert the string to a name only allowing ascii as valid input
+    ///
+    /// This method will also preserve the case of the name where that's desirable
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use trust_dns_proto::rr::Name;
+    ///
+    /// let bytes_name = Name::from_labels(vec!["WWW".as_bytes(), "example".as_bytes(), "COM".as_bytes()]).unwrap();
+    /// let ascii_name = Name::from_ascii("WWW.example.COM.").unwrap();
+    /// let lower_name = Name::from_ascii("www.example.com.").unwrap();
+    ///
+    /// assert!(bytes_name.eq_case(&ascii_name));
+    /// assert!(!lower_name.eq_case(&ascii_name));
+    ///
+    /// // escaped values
+    /// let bytes_name = Name::from_labels(vec!["email.name".as_bytes(), "example".as_bytes(), "com".as_bytes()]).unwrap();
+    /// let name = Name::from_ascii("email\\.name.example.com.").unwrap();
+    ///
+    /// assert_eq!(bytes_name, name);
+    ///
+    /// let bytes_name = Name::from_labels(vec!["bad.char".as_bytes(), "example".as_bytes(), "com".as_bytes()]).unwrap();
+    /// let name = Name::from_ascii("bad\\056char.example.com.").unwrap();
+    ///
+    /// assert_eq!(bytes_name, name);
+    /// ```
+    pub fn from_ascii<S: AsRef<str>>(name: S) -> ProtoResult<Self> {
+        Self::from_encoded_str::<LabelEncAscii>(name.as_ref(), None)
+    }
+
+    // TODO: currently reserved to be private to the crate, due to confusion of IDNA vs. utf8 in https://tools.ietf.org/html/rfc6762#appendix-F
+    /// Will convert the string to a name using IDNA, punycode, to encode the UTF8 as necessary
+    ///
+    /// When making names IDNA compatible, there is a side-effect of lowercasing the name.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::str::FromStr;
+    /// use trust_dns_proto::rr::Name;
+    ///
+    /// let bytes_name = Name::from_labels(vec!["WWW".as_bytes(), "example".as_bytes(), "COM".as_bytes()]).unwrap();
+    ///
+    /// // from_str calls through to from_utf8
+    /// let utf8_name = Name::from_str("WWW.example.COM.").unwrap();
+    /// let lower_name = Name::from_str("www.example.com.").unwrap();
+    ///
+    /// assert!(!bytes_name.eq_case(&utf8_name));
+    /// assert!(lower_name.eq_case(&utf8_name));
+    /// ```
+    pub fn from_utf8<S: AsRef<str>>(name: S) -> ProtoResult<Self> {
+        Self::from_encoded_str::<LabelEncUtf8>(name.as_ref(), None)
+    }
+
+    /// First attempts to decode via `from_utf8`, if that fails IDNA checks, than falls back to
+    /// ascii decoding.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::str::FromStr;
+    /// use trust_dns_proto::rr::Name;
+    ///
+    /// // Ok, underscore in the beginning of a name
+    /// assert!(Name::from_utf8("_allows.example.com.").is_ok());
+    ///
+    /// // Error, underscore in the end
+    /// assert!(Name::from_utf8("dis_allowed.example.com.").is_err());
+    ///
+    /// // Ok, relaxed mode
+    /// assert!(Name::from_str_relaxed("allow_in_.example.com.").is_ok());
+    /// ```
+    pub fn from_str_relaxed<S: AsRef<str>>(name: S) -> ProtoResult<Self> {
+        let name = name.as_ref();
+        Self::from_utf8(name).or_else(|_| Self::from_ascii(name))
+    }
+
+    fn from_encoded_str<E: LabelEnc>(local: &str, origin: Option<&Self>) -> ProtoResult<Self> {
+        let mut name = Name::new();
+        let mut label = String::new();
+
+        let mut state = ParseState::Label;
+
+        // short circuit root parse
+        if local == "." {
+            name.set_fqdn(true);
+            return Ok(name);
+        }
+
+        // TODO: it would be nice to relocate this to Label, but that is hard because the label boundary can only be detected after processing escapes...
+        // evaluate all characters
+        for ch in local.chars() {
+            match state {
+                ParseState::Label => match ch {
+                    '.' => {
+                        name.labels.push(E::to_label(&label)?);
+                        label.clear();
+                    }
+                    '\\' => state = ParseState::Escape1,
+                    ch if !ch.is_control() && !ch.is_whitespace() => label.push(ch),
+                    _ => return Err(format!("unrecognized char: {}", ch).into()),
+                },
+                ParseState::Escape1 => {
+                    if ch.is_numeric() {
+                        state =
+                            ParseState::Escape2(ch.to_digit(8).ok_or_else(|| {
+                                ProtoError::from(format!("illegal char: {}", ch))
+                            })?);
+                    } else {
+                        // it's a single escaped char
+                        label.push(ch);
+                        state = ParseState::Label;
+                    }
+                }
+                ParseState::Escape2(i) => {
+                    if ch.is_numeric() {
+                        state = ParseState::Escape3(
+                            i,
+                            ch.to_digit(8)
+                                .ok_or_else(|| ProtoError::from(format!("illegal char: {}", ch)))?,
+                        );
+                    } else {
+                        return Err(ProtoError::from(format!("unrecognized char: {}", ch)));
+                    }
+                }
+                ParseState::Escape3(i, ii) => {
+                    if ch.is_numeric() {
+                        // octal conversion
+                        let val: u32 = (i * 8 * 8)
+                            + (ii * 8)
+                            + ch.to_digit(8)
+                                .ok_or_else(|| ProtoError::from(format!("illegal char: {}", ch)))?;
+                        let new: char = char::from_u32(val)
+                            .ok_or_else(|| ProtoError::from(format!("illegal char: {}", ch)))?;
+                        label.push(new);
+                        state = ParseState::Label;
+                    } else {
+                        return Err(format!("unrecognized char: {}", ch).into());
+                    }
+                }
+            }
+        }
+
+        if !label.is_empty() {
+            name.labels.push(E::to_label(&label)?);
+        }
+
+        if local.ends_with('.') {
+            name.set_fqdn(true);
+        } else if let Some(other) = origin {
+            return Ok(name.append_domain(other));
+        }
+
+        Ok(name)
+    }
+
+    /// Emits the canonical version of the name to the encoder.
+    ///
+    /// In canonical form, there will be no pointers written to the encoder (i.e. no compression).
+    pub fn emit_as_canonical(&self, encoder: &mut BinEncoder, canonical: bool) -> ProtoResult<()> {
+        let buf_len = encoder.len(); // lazily assert the size is less than 255...
+                                     // lookup the label in the BinEncoder
+                                     // if it exists, write the Pointer
+        let labels: &[Label] = &self.labels;
+
+        // start index of each label
+        let mut labels_written: Vec<usize> = Vec::with_capacity(labels.len());
+
+        if canonical {
+            for label in labels {
+                encoder.emit_character_data(label)?;
+            }
+        } else {
+            // we're going to write out each label, tracking the indexes of the start to each label
+            //   then we'll look to see if we can remove them and recapture the capacity in the buffer...
+            for label in labels {
+                if label.len() > 63 {
+                    return Err(ProtoErrorKind::LabelBytesTooLong(label.len()).into());
+                }
+
+                labels_written.push(encoder.offset());
+                encoder.emit_character_data(label)?;
+            }
+
+            // we've written all the labels to the buf, the current offset is the end
+            let last_index = encoder.offset();
+
+            // now search for other labels already stored matching from the beginning label, strip then to the end
+            //   if it's not found, then store this as a new label
+            for label_idx in &labels_written {
+                let label_ptr: Option<u16> = encoder.get_label_pointer(*label_idx, last_index);
+
+                // before we write the label, let's look for the current set of labels.
+                if let Some(loc) = label_ptr {
+                    // reset back to the beginning of this label, and then write the pointer...
+                    encoder.set_offset(*label_idx);
+                    encoder.trim();
+
+                    // write out the pointer marker
+                    //  or'd with the location which shouldn't be larger than this 2^14 or 16k
+                    encoder.emit_u16(0xC000u16 | (loc & 0x3FFFu16))?;
+
+                    // we found a pointer don't write more, break
+                    return Ok(());
+                } else {
+                    // no existing label exists, store this new one.
+                    encoder.store_label_pointer(*label_idx, last_index);
+                }
+            }
+        }
+
+        // if we're getting here, then we didn't write out a pointer and are ending the name
+        // the end of the list of names
+        encoder.emit(0)?;
+
+        // the entire name needs to be less than 256.
+        let length = encoder.len() - buf_len;
+        if length > 255 {
+            return Err(ProtoErrorKind::DomainNameTooLong(length).into());
+        }
+
+        Ok(())
+    }
+
+    /// Writes the labels, as lower case, to the encoder
+    ///
+    /// # Arguments
+    ///
+    /// * `encoder` - encoder for writing this name
+    /// * `lowercase` - if true the name will be lowercased, otherwise it will not be changed when writing
+    pub fn emit_with_lowercase(
+        &self,
+        encoder: &mut BinEncoder,
+        lowercase: bool,
+    ) -> ProtoResult<()> {
+        let is_canonical_names = encoder.is_canonical_names();
+        if lowercase {
+            self.to_lowercase()
+                .emit_as_canonical(encoder, is_canonical_names)
+        } else {
+            self.emit_as_canonical(encoder, is_canonical_names)
+        }
+    }
+
+    /// compares with the other label, ignoring case
+    fn cmp_with_f<F: LabelCmp>(&self, other: &Self) -> Ordering {
+        if self.labels.is_empty() && other.labels.is_empty() {
+            return Ordering::Equal;
+        }
+
+        // we reverse the iters so that we are comparing from the root/domain to the local...
+        let self_labels = self.labels.iter().rev();
+        let other_labels = other.labels.iter().rev();
+
+        for (l, r) in self_labels.zip(other_labels) {
+            match l.cmp_with_f::<F>(r) {
+                Ordering::Equal => continue,
+                not_eq => return not_eq,
+            }
+        }
+
+        self.labels.len().cmp(&other.labels.len())
+    }
+
+    /// Case sensitive comparison
+    pub fn cmp_case(&self, other: &Self) -> Ordering {
+        self.cmp_with_f::<CaseSensitive>(other)
+    }
+
+    /// Compares the Names, in a case sensitive manner
+    pub fn eq_case(&self, other: &Self) -> bool {
+        self.cmp_with_f::<CaseSensitive>(other) == Ordering::Equal
+    }
+
+    /// Converts this name into an ascii safe string.
+    ///
+    /// If the name is an IDNA name, then the name labels will be returned with the `xn--` prefix.
+    ///  see `to_utf8` or the `Display` impl for methods which convert labels to utf8.
+    pub fn to_ascii(&self) -> String {
+        let mut s = String::with_capacity(self.len());
+        self.write_labels::<String, LabelEncAscii>(&mut s)
+            .expect("string conversion of name should not fail");
+        s
+    }
+
+    /// Converts the Name labels to the utf8 String form.
+    ///
+    /// This converts the name to an unescaped format, that could be used with parse. If, the name is
+    ///  is followed by the final `.`, e.g. as in `www.example.com.`, which represents a fully
+    ///  qualified Name.
+    pub fn to_utf8(&self) -> String {
+        format!("{}", self)
+    }
+
+    fn write_labels<W: Write, E: LabelEnc>(&self, f: &mut W) -> Result<(), fmt::Error> {
+        let mut iter = self.labels.iter();
+        if let Some(label) = iter.next() {
+            E::write_label(f, label)?;
+        }
+
+        for label in iter {
+            write!(f, ".")?;
+            E::write_label(f, label)?;
+        }
+
+        // if it was the root name
+        if self.is_root() || self.is_fqdn() {
+            write!(f, ".")?;
+        }
+        Ok(())
+    }
+
+    /// Returns true if the `Name` is either localhost or in the localhost zone.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use std::str::FromStr;
+    /// use trust_dns_proto::rr::Name;
+    ///
+    /// let name = Name::from_str("localhost").unwrap();
+    /// assert!(name.is_localhost());
+    ///
+    /// let name = Name::from_str("localhost.").unwrap();
+    /// assert!(name.is_localhost());
+    ///
+    /// let name = Name::from_str("my.localhost.").unwrap();
+    /// assert!(name.is_localhost());
+    /// ```
+    pub fn is_localhost(&self) -> bool {
+        LOCALHOST_usage.zone_of(self)
+    }
+
+    /// True if the first label of this name is the wildcard, i.e. '*'
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use std::str::FromStr;
+    /// use trust_dns_proto::rr::Name;
+    ///
+    /// let name = Name::from_str("www.example.com").unwrap();
+    /// assert!(!name.is_wildcard());
+    ///
+    /// let name = Name::from_str("*.example.com").unwrap();
+    /// assert!(name.is_wildcard());
+    ///
+    /// let name = Name::root();
+    /// assert!(!name.is_wildcard());
+    /// ```
+    pub fn is_wildcard(&self) -> bool {
+        self.labels.first().map_or(false, Label::is_wildcard)
+    }
+
+    /// Converts a name to a wildcard, by replacing the first label with `*`
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use std::str::FromStr;
+    /// use trust_dns_proto::rr::Name;
+    ///
+    /// let name = Name::from_str("www.example.com").unwrap().into_wildcard();
+    /// assert_eq!(name, Name::from_str("*.example.com.").unwrap());
+    ///
+    /// // does nothing if the root
+    /// let name = Name::root().into_wildcard();
+    /// assert_eq!(name, Name::root());
+    /// ```
+    pub fn into_wildcard(mut self) -> Self {
+        let wildcard = Label::wildcard();
+        if let Some(first) = self.labels.first_mut() {
+            *first = wildcard;
+        }
+
+        self
+    }
+}
+
+trait LabelEnc {
+    fn to_label(name: &str) -> ProtoResult<Label>;
+    fn write_label<W: Write>(f: &mut W, label: &Label) -> Result<(), fmt::Error>;
+}
+
+struct LabelEncAscii;
+impl LabelEnc for LabelEncAscii {
+    fn to_label(name: &str) -> ProtoResult<Label> {
+        Label::from_ascii(name)
+    }
+
+    fn write_label<W: Write>(f: &mut W, label: &Label) -> Result<(), fmt::Error> {
+        label.write_ascii(f)
+    }
+}
+
+struct LabelEncUtf8;
+impl LabelEnc for LabelEncUtf8 {
+    fn to_label(name: &str) -> ProtoResult<Label> {
+        Label::from_utf8(name)
+    }
+
+    fn write_label<W: Write>(f: &mut W, label: &Label) -> Result<(), fmt::Error> {
+        write!(f, "{}", label)
+    }
+}
+
+/// An iterator over labels in a name
+pub struct LabelIter<'a>(Iter<'a, Label>);
+
+impl<'a> Iterator for LabelIter<'a> {
+    type Item = &'a [u8];
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.0.next().map(Borrow::borrow)
+    }
+}
+
+impl<'a> ExactSizeIterator for LabelIter<'a> {}
+impl<'a> DoubleEndedIterator for LabelIter<'a> {
+    fn next_back(&mut self) -> Option<Self::Item> {
+        self.0.next_back().map(Borrow::borrow)
+    }
+}
+
+impl<'a> IntoIterator for &'a Name {
+    type Item = &'a [u8];
+    type IntoIter = LabelIter<'a>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        self.iter()
+    }
+}
+
+impl From<IpAddr> for Name {
+    fn from(addr: IpAddr) -> Name {
+        match addr {
+            IpAddr::V4(ip) => ip.into(),
+            IpAddr::V6(ip) => ip.into(),
+        }
+    }
+}
+
+impl From<Ipv4Addr> for Name {
+    fn from(addr: Ipv4Addr) -> Name {
+        let octets = addr.octets();
+
+        let mut labels =
+            octets
+                .iter()
+                .rev()
+                .fold(Vec::<Label>::with_capacity(6), |mut labels, o| {
+                    let label: Label = format!("{}", o)
+                        .as_bytes()
+                        .into_label()
+                        .expect("IP octet to label should never fail");
+                    labels.push(label);
+                    labels
+                });
+
+        labels.push(
+            b"in-addr"
+                .into_label()
+                .expect("simple name should never fail"),
+        );
+        labels.push(b"arpa".into_label().expect("simple name should never fail"));
+
+        Self::from_labels(labels).expect("a translation of Ipv4Addr should never fail")
+    }
+}
+
+impl From<Ipv6Addr> for Name {
+    fn from(addr: Ipv6Addr) -> Name {
+        let segments = addr.segments();
+
+        let mut labels =
+            segments
+                .iter()
+                .rev()
+                .fold(Vec::<Label>::with_capacity(34), |mut labels, o| {
+                    labels.push(
+                        format!("{:x}", (*o & 0x000F) as u8)
+                            .as_bytes()
+                            .into_label()
+                            .expect("IP octet to label should never fail"),
+                    );
+                    labels.push(
+                        format!("{:x}", (*o >> 4 & 0x000F) as u8)
+                            .as_bytes()
+                            .into_label()
+                            .expect("IP octet to label should never fail"),
+                    );
+                    labels.push(
+                        format!("{:x}", (*o >> 8 & 0x000F) as u8)
+                            .as_bytes()
+                            .into_label()
+                            .expect("IP octet to label should never fail"),
+                    );
+                    labels.push(
+                        format!("{:x}", (*o >> 12 & 0x000F) as u8)
+                            .as_bytes()
+                            .into_label()
+                            .expect("IP octet to label should never fail"),
+                    );
+                    labels
+                });
+
+        labels.push(b"ip6".into_label().expect("simple name should never fail"));
+        labels.push(b"arpa".into_label().expect("simple name should never fail"));
+
+        Self::from_labels(labels).expect("a translation of Ipv6Addr should never fail")
+    }
+}
+
+impl PartialEq<Name> for Name {
+    fn eq(&self, other: &Self) -> bool {
+        self.cmp_with_f::<CaseInsensitive>(other) == Ordering::Equal
+    }
+}
+
+impl Hash for Name {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.is_fqdn.hash(state);
+
+        // this needs to be CaseInsensitive like PartialEq
+        for l in self.labels.iter().map(Label::to_lowercase) {
+            l.hash(state);
+        }
+    }
+}
+
+enum ParseState {
+    Label,
+    Escape1,
+    Escape2(u32),
+    Escape3(u32, u32),
+}
+
+impl BinEncodable for Name {
+    fn emit(&self, encoder: &mut BinEncoder) -> ProtoResult<()> {
+        let is_canonical_names = encoder.is_canonical_names();
+        self.emit_as_canonical(encoder, is_canonical_names)
+    }
+}
+
+impl<'r> BinDecodable<'r> for Name {
+    /// parses the chain of labels
+    ///  this has a max of 255 octets, with each label being less than 63.
+    ///  all names will be stored lowercase internally.
+    /// This will consume the portions of the `Vec` which it is reading...
+    fn read(decoder: &mut BinDecoder<'r>) -> ProtoResult<Name> {
+        read_inner(decoder, None)
+    }
+}
+
+fn read_inner<'r>(decoder: &mut BinDecoder<'r>, max_idx: Option<usize>) -> ProtoResult<Name> {
+    let mut state: LabelParseState = LabelParseState::LabelLengthOrPointer;
+    let mut labels: Vec<Label> = Vec::with_capacity(3); // most labels will be around three, e.g. www.example.com
+    let name_start = decoder.index();
+    let mut run_len = 0_usize;
+
+    // assume all chars are utf-8. We're doing byte-by-byte operations, no endianess issues...
+    // reserved: (1000 0000 aka 0800) && (0100 0000 aka 0400)
+    // pointer: (slice == 1100 0000 aka C0) & C0 == true, then 03FF & slice = offset
+    // label: 03FF & slice = length; slice.next(length) = label
+    // root: 0000
+    loop {
+        // this protects against overlapping labels
+        if let Some(max_idx) = max_idx {
+            if decoder.index() >= max_idx {
+                return Err(ProtoErrorKind::LabelOverlapsWithOther {
+                    label: name_start,
+                    other: max_idx,
+                }
+                .into());
+            }
+        }
+
+        // enforce max length of name
+        let cur_len = run_len + labels.len();
+        if cur_len > 255 {
+            return Err(ProtoErrorKind::DomainNameTooLong(cur_len).into());
+        }
+
+        state = match state {
+            LabelParseState::LabelLengthOrPointer => {
+                // determine what the next label is
+                match decoder
+                    .peek()
+                    .map(Restrict::unverified /*verified in this usage*/)
+                {
+                    Some(0) | None => LabelParseState::Root,
+                    Some(byte) if byte & 0b1100_0000 == 0b1100_0000 => LabelParseState::Pointer,
+                    Some(byte) if byte & 0b1100_0000 == 0b0000_0000 => LabelParseState::Label,
+                    Some(byte) => return Err(ProtoErrorKind::UnrecognizedLabelCode(byte).into()),
+                }
+            }
+            // labels must have a maximum length of 63
+            LabelParseState::Label => {
+                let label = decoder
+                    .read_character_data_max(Some(63))?
+                    .verify_unwrap(|l| l.len() <= 63)
+                    .map_err(|_| ProtoError::from("label exceeds maximum length of 63"))?;
+
+                run_len += label.len();
+                labels.push(label.into_label()?);
+
+                // reset to collect more data
+                LabelParseState::LabelLengthOrPointer
+            }
+            //         4.1.4. Message compression
+            //
+            // In order to reduce the size of messages, the domain system utilizes a
+            // compression scheme which eliminates the repetition of domain names in a
+            // message.  In this scheme, an entire domain name or a list of labels at
+            // the end of a domain name is replaced with a pointer to a prior occurrence
+            // of the same name.
+            //
+            // The pointer takes the form of a two octet sequence:
+            //
+            //     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+            //     | 1  1|                OFFSET                   |
+            //     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+            //
+            // The first two bits are ones.  This allows a pointer to be distinguished
+            // from a label, since the label must begin with two zero bits because
+            // labels are restricted to 63 octets or less.  (The 10 and 01 combinations
+            // are reserved for future use.)  The OFFSET field specifies an offset from
+            // the start of the message (i.e., the first octet of the ID field in the
+            // domain header).  A zero offset specifies the first byte of the ID field,
+            // etc.
+            LabelParseState::Pointer => {
+                let pointer_location = decoder.index();
+                let location = decoder
+                    .read_u16()?
+                    .map(|u| {
+                        // get rid of the two high order bits, they are markers for length or pointers
+                        u & 0x3FFF
+                    })
+                    .verify_unwrap(|ptr| {
+                        // all labels must appear "prior" to this Name
+                        (*ptr as usize) < name_start
+                    })
+                    .map_err(|e| {
+                        ProtoError::from(ProtoErrorKind::PointerNotPriorToLabel {
+                            idx: pointer_location,
+                            ptr: e,
+                        })
+                    })?;
+
+                let mut pointer = decoder.clone(location);
+                let pointed = read_inner(&mut pointer, Some(name_start))?;
+
+                for l in &*pointed.labels {
+                    if !l.is_empty() {
+                        run_len += l.len();
+                    }
+                    labels.push(l.clone());
+                }
+
+                // Pointers always finish the name, break like Root.
+                break;
+            }
+            LabelParseState::Root => {
+                // need to pop() the 0 off the stack...
+                decoder.pop()?;
+                break;
+            }
+        }
+    }
+
+    run_len += if labels.is_empty() { 1 } else { labels.len() };
+    let name = Name {
+        is_fqdn: true,
+        labels,
+    };
+
+    debug_assert_eq!(run_len, name.len());
+
+    Ok(name)
+}
+
+impl fmt::Display for Name {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.write_labels::<fmt::Formatter, LabelEncUtf8>(f)
+    }
+}
+
+impl Index<usize> for Name {
+    type Output = Label;
+
+    fn index(&self, _index: usize) -> &Label {
+        &self.labels[_index]
+    }
+}
+
+impl PartialOrd<Name> for Name {
+    fn partial_cmp(&self, other: &Name) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl Ord for Name {
+    /// Case insensitive comparison, see [`Name::cmp_case`] for case sensitive comparisons
+    ///
+    /// RFC 4034                DNSSEC Resource Records               March 2005
+    ///
+    /// ```text
+    /// 6.1.  Canonical DNS Name Order
+    ///
+    ///  For the purposes of DNS security, owner names are ordered by treating
+    ///  individual labels as unsigned left-justified octet strings.  The
+    ///  absence of a octet sorts before a zero value octet, and uppercase
+    ///  US-ASCII letters are treated as if they were lowercase US-ASCII
+    ///  letters.
+    ///
+    ///  To compute the canonical ordering of a set of DNS names, start by
+    ///  sorting the names according to their most significant (rightmost)
+    ///  labels.  For names in which the most significant label is identical,
+    ///  continue sorting according to their next most significant label, and
+    ///  so forth.
+    ///
+    ///  For example, the following names are sorted in canonical DNS name
+    ///  order.  The most significant label is "example".  At this level,
+    ///  "example" sorts first, followed by names ending in "a.example", then
+    ///  by names ending "z.example".  The names within each level are sorted
+    ///  in the same way.
+    ///
+    ///            example
+    ///            a.example
+    ///            yljkjljk.a.example
+    ///            Z.a.example
+    ///            zABC.a.EXAMPLE
+    ///            z.example
+    ///            \001.z.example
+    ///            *.z.example
+    ///            \200.z.example
+    /// ```
+    fn cmp(&self, other: &Self) -> Ordering {
+        self.cmp_with_f::<CaseInsensitive>(other)
+    }
+}
+
+/// This is the list of states for the label parsing state machine
+enum LabelParseState {
+    LabelLengthOrPointer, // basically the start of the FSM
+    Label,                // storing length of the label, must be < 63
+    Pointer,              // location of pointer in slice,
+    Root,                 // root is the end of the labels list, aka null
+}
+
+impl FromStr for Name {
+    type Err = ProtoError;
+
+    /// Uses the Name::from_utf8 conversion on this string, see [`from_ascii`] for ascii only, or for preserving case
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        Name::from_str_relaxed(s)
+    }
+}
+
+/// Conversion into a Name
+pub trait IntoName: Sized {
+    /// Convert this into Name
+    fn into_name(self) -> ProtoResult<Name>;
+}
+
+impl<'a> IntoName for &'a str {
+    /// Performs a utf8, IDNA or punycode, translation of the `str` into `Name`
+    fn into_name(self) -> ProtoResult<Name> {
+        Name::from_utf8(self)
+    }
+}
+
+impl IntoName for String {
+    /// Performs a utf8, IDNA or punycode, translation of the `String` into `Name`
+    fn into_name(self) -> ProtoResult<Name> {
+        Name::from_utf8(self)
+    }
+}
+
+impl<T> IntoName for T
+where
+    T: Into<Name>,
+{
+    fn into_name(self) -> ProtoResult<Name> {
+        Ok(self.into())
+    }
+}
+
+#[cfg(feature = "serde-config")]
+impl Serialize for Name {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: Serializer,
+    {
+        serializer.serialize_str(&self.to_string())
+    }
+}
+
+#[cfg(feature = "serde-config")]
+impl<'de> Deserialize<'de> for Name {
+    fn deserialize<D>(deserializer: D) -> Result<Name, D::Error>
+    where
+        D: Deserializer<'de>,
+    {
+        let s = String::deserialize(deserializer)?;
+        FromStr::from_str(&s).map_err(de::Error::custom)
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    #![allow(clippy::dbg_macro, clippy::print_stdout)]
+
+    use std::cmp::Ordering;
+    use std::str::FromStr;
+
+    use super::*;
+
+    use crate::serialize::binary::bin_tests::{test_emit_data_set, test_read_data_set};
+    #[allow(clippy::useless_attribute)]
+    #[allow(unused)]
+    use crate::serialize::binary::*;
+
+    fn get_data() -> Vec<(Name, Vec<u8>)> {
+        vec![
+            (Name::new(), vec![0]),                           // base case, only the root
+            (Name::from_str("a").unwrap(), vec![1, b'a', 0]), // a single 'a' label
+            (
+                Name::from_str("a.bc").unwrap(),
+                vec![1, b'a', 2, b'b', b'c', 0],
+            ), // two labels, 'a.bc'
+            (
+                Name::from_str("a.♥").unwrap(),
+                vec![1, b'a', 7, b'x', b'n', b'-', b'-', b'g', b'6', b'h', 0],
+            ), // two labels utf8, 'a.♥'
+        ]
+    }
+
+    #[test]
+    fn test_num_labels() {
+        assert_eq!(Name::from_str("*").unwrap().num_labels(), 0);
+        assert_eq!(Name::from_str("a").unwrap().num_labels(), 1);
+        assert_eq!(Name::from_str("*.b").unwrap().num_labels(), 1);
+        assert_eq!(Name::from_str("a.b").unwrap().num_labels(), 2);
+        assert_eq!(Name::from_str("*.b.c").unwrap().num_labels(), 2);
+        assert_eq!(Name::from_str("a.b.c").unwrap().num_labels(), 3);
+    }
+
+    #[test]
+    fn test_read() {
+        test_read_data_set(get_data(), |ref mut d| Name::read(d));
+    }
+
+    #[test]
+    fn test_write_to() {
+        test_emit_data_set(get_data(), |e, n| n.emit(e));
+    }
+
+    #[test]
+    fn test_pointer() {
+        let mut bytes: Vec<u8> = Vec::with_capacity(512);
+
+        let first = Name::from_str("ra.rb.rc").unwrap();
+        let second = Name::from_str("rb.rc").unwrap();
+        let third = Name::from_str("rc").unwrap();
+        let fourth = Name::from_str("z.ra.rb.rc").unwrap();
+
+        {
+            let mut e = BinEncoder::new(&mut bytes);
+
+            first.emit(&mut e).unwrap();
+            assert_eq!(e.len(), 10); // should be 7 u8s...
+
+            second.emit(&mut e).unwrap();
+            // if this wrote the entire thing, then it would be +5... but a pointer should be +2
+            assert_eq!(e.len(), 12);
+
+            third.emit(&mut e).unwrap();
+            assert_eq!(e.len(), 14);
+
+            fourth.emit(&mut e).unwrap();
+            assert_eq!(e.len(), 18);
+        }
+
+        // now read them back
+        let mut d = BinDecoder::new(&bytes);
+
+        let r_test = Name::read(&mut d).unwrap();
+        assert_eq!(first, r_test);
+
+        let r_test = Name::read(&mut d).unwrap();
+        assert_eq!(second, r_test);
+
+        let r_test = Name::read(&mut d).unwrap();
+        assert_eq!(third, r_test);
+
+        let r_test = Name::read(&mut d).unwrap();
+        assert_eq!(fourth, r_test);
+    }
+
+    #[test]
+    fn test_recursive_pointer() {
+        // points to an invalid beginning label marker
+        let bytes = vec![0xC0, 0x01];
+        let mut d = BinDecoder::new(&bytes);
+
+        assert!(Name::read(&mut d).is_err());
+
+        // formerly a stack overflow, recursing back on itself
+        let bytes = vec![0xC0, 0x00];
+        let mut d = BinDecoder::new(&bytes);
+
+        assert!(Name::read(&mut d).is_err());
+
+        // formerly a stack overflow, recursing back on itself
+        let bytes = vec![0x01, 0x41, 0xC0, 0x00];
+        let mut d = BinDecoder::new(&bytes);
+
+        assert!(Name::read(&mut d).is_err());
+
+        // formerly a stack overflow, recursing by going past the end, then back to the beginning.
+        //   this is disallowed based on the rule that all labels must be "prior" to the current label.
+        let bytes = vec![0xC0, 0x02, 0xC0, 0x00];
+        let mut d = BinDecoder::new(&bytes);
+
+        assert!(Name::read(&mut d).is_err());
+    }
+
+    #[test]
+    fn test_bin_overlap_enforced() {
+        let mut bytes = Vec::with_capacity(512);
+        let n = 31;
+        for _ in 0..=5 {
+            for _ in 0..=n {
+                bytes.push(n);
+            }
+        }
+        bytes.push(n + 1);
+        for b in 0..n {
+            bytes.push(1 + n + b);
+        }
+        bytes.extend_from_slice(&[1, 0]);
+        for b in 0..n {
+            bytes.extend_from_slice(&[0xC0, b]);
+        }
+        let mut d = BinDecoder::new(&bytes);
+        d.read_slice(n as usize).unwrap();
+        assert!(Name::read(&mut d).is_err());
+    }
+
+    #[test]
+    fn test_bin_max_octets() {
+        let mut bytes = Vec::with_capacity(512);
+        for _ in 0..256 {
+            bytes.extend_from_slice(&[1, b'a']);
+        }
+        bytes.push(0);
+
+        let mut d = BinDecoder::new(&bytes);
+        assert!(Name::read(&mut d).is_err());
+    }
+
+    #[test]
+    fn test_base_name() {
+        let zone = Name::from_str("example.com.").unwrap();
+
+        assert_eq!(zone.base_name(), Name::from_str("com").unwrap());
+        assert!(zone.base_name().base_name().is_root());
+        assert!(zone.base_name().base_name().base_name().is_root());
+    }
+
+    #[test]
+    fn test_zone_of() {
+        let zone = Name::from_str("example.com").unwrap();
+        let www = Name::from_str("www.example.com").unwrap();
+        let none = Name::from_str("none.com").unwrap();
+        let root = Name::root();
+
+        assert!(zone.zone_of(&zone));
+        assert!(zone.zone_of(&www));
+        assert!(!zone.zone_of(&none));
+        assert!(root.zone_of(&zone));
+        assert!(!zone.zone_of(&root));
+    }
+
+    #[test]
+    fn test_zone_of_case() {
+        let zone = Name::from_ascii("examplE.cOm").unwrap();
+        let www = Name::from_str("www.example.com").unwrap();
+        let none = Name::from_str("none.com").unwrap();
+
+        assert!(zone.zone_of(&zone));
+        assert!(zone.zone_of(&www));
+        assert!(!zone.zone_of(&none))
+    }
+
+    #[test]
+    fn test_partial_cmp_eq() {
+        let root = Some(Name::from_labels(Vec::<&str>::new()).unwrap());
+        let comparisons: Vec<(Name, Name)> = vec![
+            (root.clone().unwrap(), root.clone().unwrap()),
+            (
+                Name::parse("example.", root.as_ref()).unwrap(),
+                Name::parse("example", root.as_ref()).unwrap(),
+            ),
+        ];
+
+        for (left, right) in comparisons {
+            println!("left: {}, right: {}", left, right);
+            assert_eq!(left.partial_cmp(&right), Some(Ordering::Equal));
+        }
+    }
+
+    #[test]
+    fn test_partial_cmp() {
+        let comparisons: Vec<(Name, Name)> = vec![
+            (
+                Name::from_str("example.").unwrap(),
+                Name::from_str("a.example.").unwrap(),
+            ),
+            (
+                Name::from_str("a.example.").unwrap(),
+                Name::from_str("yljkjljk.a.example.").unwrap(),
+            ),
+            (
+                Name::from_str("yljkjljk.a.example.").unwrap(),
+                Name::from_ascii("Z.a.example.").unwrap(),
+            ),
+            (
+                Name::from_ascii("Z.a.example.").unwrap(),
+                Name::from_ascii("zABC.a.EXAMPLE").unwrap(),
+            ),
+            (
+                Name::from_ascii("zABC.a.EXAMPLE.").unwrap(),
+                Name::from_str("z.example.").unwrap(),
+            ),
+            (
+                Name::from_str("z.example.").unwrap(),
+                Name::from_labels(vec![&[1u8] as &[u8], b"z", b"example"]).unwrap(),
+            ),
+            (
+                Name::from_labels(vec![&[1u8] as &[u8], b"z", b"example"]).unwrap(),
+                Name::from_str("*.z.example.").unwrap(),
+            ),
+            (
+                Name::from_str("*.z.example.").unwrap(),
+                Name::from_labels(vec![&[200u8] as &[u8], b"z", b"example"]).unwrap(),
+            ),
+        ];
+
+        for (left, right) in comparisons {
+            println!("left: {}, right: {}", left, right);
+            assert_eq!(left.cmp(&right), Ordering::Less);
+        }
+    }
+
+    #[test]
+    fn test_cmp_ignore_case() {
+        let comparisons: Vec<(Name, Name)> = vec![
+            (
+                Name::from_ascii("ExAmPle.").unwrap(),
+                Name::from_ascii("example.").unwrap(),
+            ),
+            (
+                Name::from_ascii("A.example.").unwrap(),
+                Name::from_ascii("a.example.").unwrap(),
+            ),
+        ];
+
+        for (left, right) in comparisons {
+            println!("left: {}, right: {}", left, right);
+            assert_eq!(left, right);
+        }
+    }
+
+    #[test]
+    fn test_from_ipv4() {
+        let ip = IpAddr::V4(Ipv4Addr::new(26, 3, 0, 103));
+        let name = Name::from_str("103.0.3.26.in-addr.arpa").unwrap();
+
+        assert_eq!(Into::<Name>::into(ip), name);
+    }
+
+    #[test]
+    fn test_from_ipv6() {
+        let ip = IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0x1));
+        let name = Name::from_str(
+            "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa",
+        )
+        .unwrap();
+
+        assert_eq!(Into::<Name>::into(ip), name);
+    }
+
+    #[test]
+    fn test_from_str() {
+        assert_eq!(
+            Name::from_str("www.example.com.").unwrap(),
+            Name::from_labels(vec![b"www" as &[u8], b"example", b"com"]).unwrap()
+        );
+        assert_eq!(
+            Name::from_str(".").unwrap(),
+            Name::from_labels(Vec::<&str>::new()).unwrap()
+        );
+    }
+
+    #[test]
+    fn test_fqdn() {
+        assert!(Name::root().is_fqdn());
+        assert!(Name::from_str(".").unwrap().is_fqdn());
+        assert!(Name::from_str("www.example.com.").unwrap().is_fqdn());
+        assert!(Name::from_labels(vec![b"www" as &[u8], b"example", b"com"])
+            .unwrap()
+            .is_fqdn());
+
+        assert!(!Name::new().is_fqdn());
+        assert!(!Name::from_str("www.example.com").unwrap().is_fqdn());
+        assert!(!Name::from_str("www.example").unwrap().is_fqdn());
+        assert!(!Name::from_str("www").unwrap().is_fqdn());
+    }
+
+    #[test]
+    fn test_to_string() {
+        assert_eq!(
+            Name::from_str("www.example.com.").unwrap().to_string(),
+            "www.example.com."
+        );
+        assert_eq!(
+            Name::from_str("www.example.com").unwrap().to_string(),
+            "www.example.com"
+        );
+    }
+
+    #[test]
+    fn test_from_ascii() {
+        let bytes_name = Name::from_labels(vec![b"WWW" as &[u8], b"example", b"COM"]).unwrap();
+        let ascii_name = Name::from_ascii("WWW.example.COM.").unwrap();
+        let lower_name = Name::from_ascii("www.example.com.").unwrap();
+
+        assert!(bytes_name.eq_case(&ascii_name));
+        assert!(!lower_name.eq_case(&ascii_name));
+    }
+
+    #[test]
+    fn test_from_utf8() {
+        let bytes_name = Name::from_labels(vec![b"WWW" as &[u8], b"example", b"COM"]).unwrap();
+        let utf8_name = Name::from_utf8("WWW.example.COM.").unwrap();
+        let lower_name = Name::from_utf8("www.example.com.").unwrap();
+
+        assert!(!bytes_name.eq_case(&utf8_name));
+        assert!(lower_name.eq_case(&utf8_name));
+    }
+
+    #[test]
+    fn test_into_name() {
+        let name = Name::from_utf8("www.example.com").unwrap();
+        assert_eq!(Name::from_utf8("www.example.com").unwrap(), name);
+        assert_eq!(
+            Name::from_utf8("www.example.com").unwrap(),
+            Name::from_utf8("www.example.com")
+                .unwrap()
+                .into_name()
+                .unwrap()
+        );
+        assert_eq!(
+            Name::from_utf8("www.example.com").unwrap(),
+            "www.example.com".into_name().unwrap()
+        );
+        assert_eq!(
+            Name::from_utf8("www.example.com").unwrap(),
+            "www.example.com".to_string().into_name().unwrap()
+        );
+    }
+
+    #[test]
+    fn test_encoding() {
+        assert_eq!(
+            Name::from_ascii("WWW.example.COM.").unwrap().to_ascii(),
+            "WWW.example.COM."
+        );
+        assert_eq!(
+            Name::from_utf8("WWW.example.COM.").unwrap().to_ascii(),
+            "www.example.com."
+        );
+        assert_eq!(
+            Name::from_ascii("WWW.example.COM.").unwrap().to_utf8(),
+            "WWW.example.COM."
+        );
+    }
+
+    #[test]
+    fn test_excessive_encoding_len() {
+        use crate::error::ProtoErrorKind;
+
+        // u16 max value is where issues start being tickled...
+        let mut buf = Vec::with_capacity(u16::max_value() as usize);
+        let mut encoder = BinEncoder::new(&mut buf);
+
+        let mut result = Ok(());
+        for i in 0..10000 {
+            let name = Name::from_ascii(format!("name{}.example.com.", i)).unwrap();
+            result = name.emit(&mut encoder);
+            if let Err(..) = result {
+                break;
+            }
+        }
+
+        assert!(result.is_err());
+        match *result.unwrap_err().kind() {
+            ProtoErrorKind::MaxBufferSizeExceeded(_) => (),
+            _ => panic!(),
+        }
+    }
+
+    #[test]
+    fn test_underscore() {
+        Name::from_str("_begin.example.com").expect("failed at beginning");
+        Name::from_str_relaxed("mid_dle.example.com").expect("failed in the middle");
+        Name::from_str_relaxed("end_.example.com").expect("failed at the end");
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/domain/try_parse_ip.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/domain/try_parse_ip.rs
new file mode 100644
index 0000000..523ef00
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/domain/try_parse_ip.rs
@@ -0,0 +1,73 @@
+// Copyright 2015-2018 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+use std::net::IpAddr;
+use std::str::FromStr;
+
+use crate::rr::{Name, RData};
+
+/// Types of this trait will can be attempted for conversion to an IP address
+pub trait TryParseIp {
+    /// Attempts to parse self into an RData::A or RData::AAAA, None is returned if not possible
+    fn try_parse_ip(&self) -> Option<RData>;
+}
+
+impl TryParseIp for str {
+    fn try_parse_ip(&self) -> Option<RData> {
+        match IpAddr::from_str(self) {
+            Ok(IpAddr::V4(ip4)) => Some(RData::A(ip4)),
+            Ok(IpAddr::V6(ip6)) => Some(RData::AAAA(ip6)),
+            Err(_) => None,
+        }
+    }
+}
+
+// impl<'a> TryParseIp for &'a str {
+//     fn try_parse_ip(&self) -> Option<RData> {
+//         TryParseIp::try_parse_ip(*self)
+//     }
+// }
+
+impl TryParseIp for String {
+    fn try_parse_ip(&self) -> Option<RData> {
+        let this = self as &str;
+        this.try_parse_ip()
+    }
+}
+
+impl TryParseIp for Name {
+    /// Always returns none for Name, it assumes something that is already a name, wants to be a name
+    fn try_parse_ip(&self) -> Option<RData> {
+        None
+    }
+}
+
+impl<'a, T> TryParseIp for &'a T
+where
+    T: TryParseIp + ?Sized,
+{
+    fn try_parse_ip(&self) -> Option<RData> {
+        TryParseIp::try_parse_ip(*self)
+    }
+}
+
+#[test]
+fn test_try_parse_ip() {
+    use std::net::{Ipv4Addr, Ipv6Addr};
+
+    assert_eq!(
+        "127.0.0.1".try_parse_ip().expect("failed"),
+        RData::A(Ipv4Addr::new(127, 0, 0, 1))
+    );
+
+    assert_eq!(
+        "::1".try_parse_ip().expect("failed"),
+        RData::AAAA(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1))
+    );
+
+    assert!("example.com".try_parse_ip().is_none());
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/domain/usage.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/domain/usage.rs
new file mode 100644
index 0000000..8a2e294
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/domain/usage.rs
@@ -0,0 +1,565 @@
+// Copyright 2015-2018 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! Reserved zone names.
+//!
+//! see [Special-Use Domain Names](https://tools.ietf.org/html/rfc6761), RFC 6761 February, 2013
+
+use std::ops::Deref;
+
+use lazy_static::lazy_static;
+
+use crate::rr::domain::Name;
+
+lazy_static! {
+    /// Default Name usage, everything is normal...
+    pub static ref DEFAULT: ZoneUsage = ZoneUsage::default();
+}
+
+lazy_static! {
+    static ref ARPA: Name = Name::from_ascii("arpa.").unwrap();
+    /// zone for ipv4 reverse addresses
+    pub static ref IN_ADDR_ARPA: Name = Name::from_ascii("in-addr").unwrap().append_domain(&*ARPA);
+    /// zone for ipv6 reverse addresses
+    pub static ref IP6_ARPA: Name = Name::from_ascii("ip6").unwrap().append_domain(&*ARPA);
+}
+
+lazy_static! {
+    /// localhost.
+    ///
+    /// [Special-Use Domain Names](https://tools.ietf.org/html/rfc6761), RFC 6761 February, 2013
+    ///
+    /// ```text
+    /// 6.3.  Domain Name Reservation Considerations for "localhost."
+    ///
+    ///    The domain "localhost." and any names falling within ".localhost."
+    ///    are special in the following ways:
+    /// ```
+
+    /// localhost. usage
+    pub static ref LOCALHOST: ZoneUsage = ZoneUsage::localhost(Name::from_ascii("localhost.").unwrap());
+
+    /// 127.in-addr.arpa. usage; 127/8 is reserved for loopback
+    pub static ref IN_ADDR_ARPA_127: ZoneUsage = ZoneUsage::localhost(Name::from_ascii("127").unwrap().append_domain(&*IN_ADDR_ARPA));
+
+    /// 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. usage; 1/128 is the only address in ipv6 loopback
+    pub static ref IP6_ARPA_1: ZoneUsage = ZoneUsage::localhost(Name::from_ascii("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0").unwrap().append_domain(&*IP6_ARPA));
+}
+
+lazy_static! {
+    /// .local.
+    ///
+    /// [Multicast DNS](https://tools.ietf.org/html/rfc6762), RFC 6762  February 2013
+    ///
+    /// ```text
+    /// This document specifies that the DNS top-level domain ".local." is a
+    ///   special domain with special semantics, namely that any fully
+    ///   qualified name ending in ".local." is link-local, and names within
+    ///   this domain are meaningful only on the link where they originate.
+    ///   This is analogous to IPv4 addresses in the 169.254/16 prefix or IPv6
+    ///   addresses in the FE80::/10 prefix, which are link-local and
+    ///   meaningful only on the link where they originate.
+    /// ```
+
+    /// localhost. usage
+    pub static ref LOCAL: ZoneUsage = ZoneUsage::local(Name::from_ascii("local.").unwrap());
+
+    // RFC 6762                      Multicast DNS                February 2013
+
+    // Any DNS query for a name ending with "254.169.in-addr.arpa." MUST
+    //  be sent to the mDNS IPv4 link-local multicast address 224.0.0.251
+    //  or the mDNS IPv6 multicast address FF02::FB.  Since names under
+    //  this domain correspond to IPv4 link-local addresses, it is logical
+    //  that the local link is the best place to find information
+    //  pertaining to those names.
+    //
+    //  Likewise, any DNS query for a name within the reverse mapping
+    //  domains for IPv6 link-local addresses ("8.e.f.ip6.arpa.",
+    //  "9.e.f.ip6.arpa.", "a.e.f.ip6.arpa.", and "b.e.f.ip6.arpa.") MUST
+    //  be sent to the mDNS IPv6 link-local multicast address FF02::FB or
+    //  the mDNS IPv4 link-local multicast address 224.0.0.251.
+
+    /// 254.169.in-addr.arpa. usage link-local, i.e. mDNS
+    pub static ref IN_ADDR_ARPA_169_254: ZoneUsage = ZoneUsage::local(Name::from_ascii("254.169").unwrap().append_domain(&*IN_ADDR_ARPA));
+
+    /// 254.169.in-addr.arpa. usage link-local, i.e. mDNS
+    pub static ref IP6_ARPA_FE_8: ZoneUsage = ZoneUsage::local(Name::from_ascii("8.e.f").unwrap().append_domain(&*IP6_ARPA));
+    /// 254.169.in-addr.arpa. usage link-local, i.e. mDNS
+    pub static ref IP6_ARPA_FE_9: ZoneUsage = ZoneUsage::local(Name::from_ascii("9.e.f").unwrap().append_domain(&*IP6_ARPA));
+    /// 254.169.in-addr.arpa. usage link-local, i.e. mDNS
+    pub static ref IP6_ARPA_FE_B: ZoneUsage = ZoneUsage::local(Name::from_ascii("b.e.f").unwrap().append_domain(&*IP6_ARPA));
+}
+
+lazy_static! {
+    /// invalid.
+    ///
+    /// [Special-Use Domain Names](https://tools.ietf.org/html/rfc6761), RFC 6761 February, 2013
+    ///
+    /// ```text
+    /// 6.4.  Domain Name Reservation Considerations for "invalid."
+    ///
+    ///    The domain "invalid." and any names falling within ".invalid." are
+    ///    special in the ways listed below.  In the text below, the term
+    ///    "invalid" is used in quotes to signify such names, as opposed to
+    ///    names that may be invalid for other reasons (e.g., being too long).
+    /// ```
+
+    /// invalid. name usage
+    pub static ref INVALID: ZoneUsage = ZoneUsage::invalid(Name::from_ascii("invalid.").unwrap());
+}
+
+/// Users:
+///
+///   Are human users expected to recognize these names as special and
+///   use them differently?  In what way?
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub enum UserUsage {
+    /// Users are free to use these names as they would any other
+    /// reverse-mapping names.  However, since there is no central
+    /// authority responsible for use of private addresses, users SHOULD
+    /// be aware that these names are likely to yield different results
+    /// on different networks.
+    Normal,
+
+    /// Users are free to use localhost names as they would any other
+    /// domain names.  Users may assume that IPv4 and IPv6 address
+    /// queries for localhost names will always resolve to the respective
+    /// IP loopback address.
+    Loopback,
+
+    /// Multi-cast link-local usage
+    LinkLocal,
+
+    /// Users are free to use "invalid" names as they would any other
+    /// domain names.  Users MAY assume that queries for "invalid" names
+    /// will always return NXDOMAIN responses.
+    NxDomain,
+}
+
+/// Application Software:
+///
+///   Are writers of application software expected to make their
+///   software recognize these names as special and treat them
+///   differently?  In what way?  (For example, if a human user enters
+///   such a name, should the application software reject it with an
+///   error message?)
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub enum AppUsage {
+    /// Application software SHOULD NOT recognize these names as special,
+    /// and SHOULD use these names as they would other reverse-mapping
+    /// names.
+    ///
+    /// Application software SHOULD NOT recognize test names as special,
+    /// and SHOULD use test names as they would other domain names.
+    ///
+    /// Application software SHOULD NOT recognize example names as
+    /// special and SHOULD use example names as they would other domain
+    /// names.
+    Normal,
+
+    /// Application software MAY recognize localhost names as special, or
+    /// MAY pass them to name resolution APIs as they would for other
+    /// domain names.
+    Loopback,
+
+    /// Link local, generally for mDNS
+    LinkLocal,
+
+    /// Application software MAY recognize "invalid" names as special or
+    /// MAY pass them to name resolution APIs as they would for other
+    /// domain names.
+    NxDomain,
+}
+
+/// Name Resolution APIs and Libraries:
+///
+///   Are writers of name resolution APIs and libraries expected to
+///   make their software recognize these names as special and treat
+///   them differently?  If so, how?
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub enum ResolverUsage {
+    /// Name resolution APIs and libraries SHOULD NOT recognize these
+    /// names as special and SHOULD NOT treat them differently.  Name
+    /// resolution APIs SHOULD send queries for these names to their
+    /// configured caching DNS server(s).
+    ///
+    /// Name resolution APIs and libraries SHOULD NOT recognize test
+    /// names as special and SHOULD NOT treat them differently.  Name
+    /// resolution APIs SHOULD send queries for test names to their
+    /// configured caching DNS server(s).
+    ///
+    /// Name resolution APIs and libraries SHOULD NOT recognize example
+    /// names as special and SHOULD NOT treat them differently.  Name
+    /// resolution APIs SHOULD send queries for example names to their
+    /// configured caching DNS server(s).
+    Normal,
+
+    /// Name resolution APIs and libraries SHOULD recognize localhost
+    /// names as special and SHOULD always return the IP loopback address
+    /// for address queries and negative responses for all other query
+    /// types.  Name resolution APIs SHOULD NOT send queries for
+    /// localhost names to their configured caching DNS server(s).
+    Loopback,
+
+    /// Link local, generally for mDNS
+    ///
+    /// Any DNS query for a name ending with ".local." MUST be sent to the
+    /// mDNS IPv4 link-local multicast address 224.0.0.251 (or its IPv6
+    /// equivalent FF02::FB).  The design rationale for using a fixed
+    /// multicast address instead of selecting from a range of multicast
+    /// addresses using a hash function is discussed in Appendix B.
+    /// Implementers MAY choose to look up such names concurrently via other
+    /// mechanisms (e.g., Unicast DNS) and coalesce the results in some
+    /// fashion.  Implementers choosing to do this should be aware of the
+    /// potential for user confusion when a given name can produce different
+    /// results depending on external network conditions (such as, but not
+    /// limited to, which name lookup mechanism responds faster).
+    LinkLocal,
+
+    /// Name resolution APIs and libraries SHOULD recognize "invalid"
+    /// names as special and SHOULD always return immediate negative
+    /// responses.  Name resolution APIs SHOULD NOT send queries for
+    /// "invalid" names to their configured caching DNS server(s).
+    NxDomain,
+}
+
+/// Caching DNS Servers:
+///
+///   Are developers of caching domain name servers expected to make
+///   their implementations recognize these names as special and treat
+///   them differently?  If so, how?
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub enum CacheUsage {
+    /// Caching DNS servers SHOULD recognize these names as special and
+    /// SHOULD NOT, by default, attempt to look up NS records for them,
+    /// or otherwise query authoritative DNS servers in an attempt to
+    /// resolve these names.  Instead, caching DNS servers SHOULD, by
+    /// default, generate immediate (positive or negative) responses for
+    /// all such queries.  This is to avoid unnecessary load on the root
+    /// name servers and other name servers.  Caching DNS servers SHOULD
+    /// offer a configuration option (disabled by default) to enable
+    /// upstream resolution of such names, for use in private networks
+    /// where private-address reverse-mapping names are known to be
+    /// handled by an authoritative DNS server in said private network.
+    NonRecursive,
+
+    /// Caching DNS servers SHOULD recognize "invalid" names as special
+    /// and SHOULD NOT attempt to look up NS records for them, or
+    /// otherwise query authoritative DNS servers in an attempt to
+    /// resolve "invalid" names.  Instead, caching DNS servers SHOULD
+    /// generate immediate NXDOMAIN responses for all such queries.  This
+    /// is to avoid unnecessary load on the root name servers and other
+    /// name servers.
+    NxDomain,
+
+    /// Caching DNS servers SHOULD recognize localhost names as special
+    /// and SHOULD NOT attempt to look up NS records for them, or
+    /// otherwise query authoritative DNS servers in an attempt to
+    /// resolve localhost names.  Instead, caching DNS servers SHOULD,
+    /// for all such address queries, generate an immediate positive
+    /// response giving the IP loopback address, and for all other query
+    /// types, generate an immediate negative response.  This is to avoid
+    /// unnecessary load on the root name servers and other name servers.
+    Loopback,
+
+    /// Caching DNS servers SHOULD NOT recognize example names as special
+    /// and SHOULD resolve them normally.
+    Normal,
+}
+
+/// Authoritative DNS Servers:
+///
+///   Are developers of authoritative domain name servers expected to
+///   make their implementations recognize these names as special and
+///   treat them differently?  If so, how?
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub enum AuthUsage {
+    /// Authoritative DNS servers SHOULD recognize these names as special
+    /// and SHOULD, by default, generate immediate negative responses for
+    /// all such queries, unless explicitly configured by the
+    /// administrator to give positive answers for private-address
+    /// reverse-mapping names.
+    Local,
+
+    /// Authoritative DNS servers SHOULD recognize these names as special
+    /// and SHOULD, by default, generate immediate negative responses for
+    /// all such queries, unless explicitly configured by the
+    /// administrator to give positive answers for private-address
+    /// reverse-mapping names.
+    NxDomain,
+
+    /// Authoritative DNS servers SHOULD recognize localhost names as
+    /// special and handle them as described above for caching DNS
+    /// servers.
+    Loopback,
+
+    /// Authoritative DNS servers SHOULD NOT recognize example names as
+    /// special.
+    Normal,
+}
+
+/// DNS Server Operators:
+///
+///   Does this reserved Special-Use Domain Name have any potential
+///   impact on DNS server operators?  If they try to configure their
+///   authoritative DNS server as authoritative for this reserved name,
+///   will compliant name server software reject it as invalid?  Do DNS
+///   server operators need to know about that and understand why?
+///   Even if the name server software doesn't prevent them from using
+///   this reserved name, are there other ways that it may not work as
+///  expected, of which the DNS server operator should be aware?
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub enum OpUsage {
+    /// DNS server operators SHOULD, if they are using private addresses,
+    /// configure their authoritative DNS servers to act as authoritative
+    /// for these names.
+    ///
+    /// DNS server operators SHOULD, if they are using test names,
+    /// configure their authoritative DNS servers to act as authoritative
+    /// for test names.
+    Normal,
+
+    /// DNS server operators SHOULD be aware that the effective RDATA for
+    /// localhost names is defined by protocol specification and cannot
+    /// be modified by local configuration.
+    Loopback,
+
+    /// DNS server operators SHOULD be aware that the effective RDATA for
+    /// "invalid" names is defined by protocol specification to be
+    /// nonexistent and cannot be modified by local configuration.
+    NxDomain,
+}
+
+/// DNS Registries/Registrars:
+///
+///   How should DNS Registries/Registrars treat requests to register
+///   this reserved domain name?  Should such requests be denied?
+///   Should such requests be allowed, but only to a specially-
+///   designated entity?  (For example, the name "www.example.org" is
+///   reserved for documentation examples and is not available for
+///   registration; however, the name is in fact registered; and there
+///   is even a web site at that name, which states circularly that the
+///   name is reserved for use in documentation and cannot be
+///   registered!)
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub enum RegistryUsage {
+    /// Stanard checks apply
+    Normal,
+
+    /// DNS Registries/Registrars MUST NOT grant requests to register
+    /// test names in the normal way to any person or entity.  Test names
+    /// are reserved for use in private networks and fall outside the set
+    /// of names available for allocation by registries/registrars.
+    /// Attempting to allocate a test name as if it were a normal DNS
+    /// domain name will probably not work as desired, for reasons 4, 5,
+    /// and 6 above.
+    ///
+    /// DNS Registries/Registrars MUST NOT grant requests to register
+    /// localhost names in the normal way to any person or entity.
+    /// Localhost names are defined by protocol specification and fall
+    /// outside the set of names available for allocation by registries/
+    /// registrars.  Attempting to allocate a localhost name as if it
+    /// were a normal DNS domain name will probably not work as desired,
+    /// for reasons 2, 3, 4, and 5 above.
+    ///
+    /// DNS Registries/Registrars MUST NOT grant requests to register
+    /// "invalid" names in the normal way to any person or entity.  These
+    /// "invalid" names are defined by protocol specification to be
+    /// nonexistent, and they fall outside the set of names available for
+    /// allocation by registries/registrars.  Attempting to allocate a
+    /// "invalid" name as if it were a normal DNS domain name will
+    /// probably not work as desired, for reasons 2, 3, 4, and 5 above.
+    ///
+    /// DNS Registries/Registrars MUST NOT grant requests to register
+    /// example names in the normal way to any person or entity.  All
+    /// example names are registered in perpetuity to IANA:
+    Reserved,
+}
+
+/// ZoneUsage represents information about how a name falling in a given zone should be treated
+pub struct ZoneUsage {
+    name: Name,
+    user: UserUsage,
+    app: AppUsage,
+    resolver: ResolverUsage,
+    cache: CacheUsage,
+    auth: AuthUsage,
+    op: OpUsage,
+    registry: RegistryUsage,
+}
+
+impl ZoneUsage {
+    /// Constructs a new ZoneUsage with the associated values
+    #[allow(clippy::too_many_arguments)]
+    pub fn new(
+        name: Name,
+        user: UserUsage,
+        app: AppUsage,
+        resolver: ResolverUsage,
+        cache: CacheUsage,
+        auth: AuthUsage,
+        op: OpUsage,
+        registry: RegistryUsage,
+    ) -> Self {
+        ZoneUsage {
+            name,
+            user,
+            app,
+            resolver,
+            cache,
+            auth,
+            op,
+            registry,
+        }
+    }
+
+    /// Constructs a new Default, with all no restrictions
+    pub fn default() -> Self {
+        Self::new(
+            Name::root(),
+            UserUsage::Normal,
+            AppUsage::Normal,
+            ResolverUsage::Normal,
+            CacheUsage::Normal,
+            AuthUsage::Normal,
+            OpUsage::Normal,
+            RegistryUsage::Normal,
+        )
+    }
+
+    /// Restrictions for reverse zones
+    pub fn reverse(name: Name) -> Self {
+        Self::new(
+            name,
+            UserUsage::Normal,
+            AppUsage::Normal,
+            ResolverUsage::Normal,
+            CacheUsage::NonRecursive,
+            AuthUsage::Local,
+            OpUsage::Normal,
+            RegistryUsage::Reserved,
+        )
+    }
+
+    /// Restrictions for the .test. zone
+    pub fn test(name: Name) -> Self {
+        Self::new(
+            name,
+            UserUsage::Normal,
+            AppUsage::Normal,
+            ResolverUsage::Normal,
+            CacheUsage::NonRecursive,
+            AuthUsage::Local,
+            OpUsage::Normal,
+            RegistryUsage::Reserved,
+        )
+    }
+
+    /// Restrictions for the .localhost. zone
+    pub fn localhost(name: Name) -> Self {
+        Self::new(
+            name,
+            UserUsage::Loopback,
+            AppUsage::Loopback,
+            ResolverUsage::Loopback,
+            CacheUsage::Loopback,
+            AuthUsage::Loopback,
+            OpUsage::Loopback,
+            RegistryUsage::Reserved,
+        )
+    }
+
+    /// Restrictions for the .local. zone
+    pub fn local(name: Name) -> Self {
+        Self::new(
+            name,
+            UserUsage::LinkLocal,
+            AppUsage::LinkLocal,
+            ResolverUsage::LinkLocal,
+            CacheUsage::Normal,
+            AuthUsage::Local,
+            OpUsage::Normal,
+            RegistryUsage::Reserved,
+        )
+    }
+
+    /// Restrictions for the .invalid. zone
+    pub fn invalid(name: Name) -> Self {
+        Self::new(
+            name,
+            UserUsage::NxDomain,
+            AppUsage::NxDomain,
+            ResolverUsage::NxDomain,
+            CacheUsage::NxDomain,
+            AuthUsage::NxDomain,
+            OpUsage::NxDomain,
+            RegistryUsage::Reserved,
+        )
+    }
+
+    /// Restrictions for the .example. zone
+    pub fn example(name: Name) -> Self {
+        Self::new(
+            name,
+            UserUsage::Normal,
+            AppUsage::Normal,
+            ResolverUsage::Normal,
+            CacheUsage::Normal,
+            AuthUsage::Normal,
+            OpUsage::Normal,
+            RegistryUsage::Reserved,
+        )
+    }
+
+    /// A reference to this zone name
+    pub fn name(&self) -> &Name {
+        &self.name
+    }
+
+    /// Returns the UserUsage of this zone
+    pub fn user(&self) -> UserUsage {
+        self.user
+    }
+
+    /// Returns the AppUsage of this zone
+    pub fn app(&self) -> AppUsage {
+        self.app
+    }
+
+    /// Returns the ResolverUsage of this zone
+    pub fn resolver(&self) -> ResolverUsage {
+        self.resolver
+    }
+
+    /// Returns the CacheUsage of this zone
+    pub fn cache(&self) -> CacheUsage {
+        self.cache
+    }
+
+    /// Returns the AuthUsage of this zone
+    pub fn auth(&self) -> AuthUsage {
+        self.auth
+    }
+
+    /// Returns the OpUsage of this zone
+    pub fn op(&self) -> OpUsage {
+        self.op
+    }
+
+    /// Returns the RegistryUsage of this zone
+    pub fn registry(&self) -> RegistryUsage {
+        self.registry
+    }
+}
+
+impl Deref for ZoneUsage {
+    type Target = Name;
+
+    fn deref(&self) -> &Self::Target {
+        &self.name
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/mod.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/mod.rs
new file mode 100644
index 0000000..dc012d8
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/mod.rs
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! Resource record related components, e.g. `Name` aka label, `Record`, `RData`, ...
+
+pub mod dns_class;
+// TODO: rename to sec
+#[cfg(feature = "dnssec")]
+pub mod dnssec;
+pub mod domain;
+pub mod rdata;
+pub mod record_data;
+pub mod record_type;
+pub mod resource;
+mod rr_set;
+
+pub use self::dns_class::DNSClass;
+pub use self::domain::{IntoName, Name, TryParseIp};
+pub use self::record_data::RData;
+pub use self::record_type::RecordType;
+pub use self::resource::Record;
+#[allow(deprecated)]
+pub use self::rr_set::IntoRecordSet;
+pub use self::rr_set::RecordSet;
+pub use self::rr_set::RrsetRecords;
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/a.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/a.rs
new file mode 100644
index 0000000..c76a51b
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/a.rs
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! IPv4 address record data
+//!
+//! [RFC 1035, DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION, November 1987](https://tools.ietf.org/html/rfc1035)
+//!
+//! ```text
+//! 3.4. Internet specific RRs
+//!
+//! 3.4.1. A RDATA format
+//!
+//!     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+//!     |                    ADDRESS                    |
+//!     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+//!
+//! where:
+//!
+//! ADDRESS         A 32 bit Internet address.
+//!
+//! Hosts that have multiple Internet addresses will have multiple A
+//! records.
+//!
+//! A records cause no additional section processing.  The RDATA section of
+//! an A line in a master file is an Internet address expressed as four
+//! decimal numbers separated by dots without any embedded spaces (e.g.,
+//! "10.2.0.52" or "192.0.5.6").
+//! ```
+
+use std::net::Ipv4Addr;
+
+use crate::error::*;
+use crate::serialize::binary::*;
+
+/// Read the RData from the given Decoder
+pub fn read(decoder: &mut BinDecoder) -> ProtoResult<Ipv4Addr> {
+    Ok(Ipv4Addr::new(
+        decoder.pop()?.unverified(/*valid as any u8*/),
+        decoder.pop()?.unverified(/*valid as any u8*/),
+        decoder.pop()?.unverified(/*valid as any u8*/),
+        decoder.pop()?.unverified(/*valid as any u8*/),
+    ))
+}
+
+/// Write the RData from the given Decoder
+pub fn emit(encoder: &mut BinEncoder, address: Ipv4Addr) -> ProtoResult<()> {
+    let segments = address.octets();
+
+    encoder.emit(segments[0])?;
+    encoder.emit(segments[1])?;
+    encoder.emit(segments[2])?;
+    encoder.emit(segments[3])?;
+    Ok(())
+}
+
+#[cfg(test)]
+mod mytests {
+    use std::net::Ipv4Addr;
+    use std::str::FromStr;
+
+    use super::*;
+    use crate::serialize::binary::bin_tests::{test_emit_data_set, test_read_data_set};
+
+    fn get_data() -> Vec<(Ipv4Addr, Vec<u8>)> {
+        vec![
+            (Ipv4Addr::from_str("0.0.0.0").unwrap(), vec![0, 0, 0, 0]), // base case
+            (Ipv4Addr::from_str("1.0.0.0").unwrap(), vec![1, 0, 0, 0]),
+            (Ipv4Addr::from_str("0.1.0.0").unwrap(), vec![0, 1, 0, 0]),
+            (Ipv4Addr::from_str("0.0.1.0").unwrap(), vec![0, 0, 1, 0]),
+            (Ipv4Addr::from_str("0.0.0.1").unwrap(), vec![0, 0, 0, 1]),
+            (Ipv4Addr::from_str("127.0.0.1").unwrap(), vec![127, 0, 0, 1]),
+            (
+                Ipv4Addr::from_str("192.168.64.32").unwrap(),
+                vec![192, 168, 64, 32],
+            ),
+        ]
+    }
+
+    #[test]
+    fn test_parse() {
+        test_read_data_set(get_data(), |ref mut d| read(d));
+    }
+
+    #[test]
+    fn test_write_to() {
+        test_emit_data_set(get_data(), |ref mut e, d| emit(e, d));
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/aaaa.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/aaaa.rs
new file mode 100644
index 0000000..c021de7
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/aaaa.rs
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! IPv6 address record data
+//!
+//! [RFC 3596, DNS Extensions to Support IPv6, October 2003](https://tools.ietf.org/html/rfc3596)
+//!
+//! ```text
+//! 2.1 AAAA record type
+//!
+//!   The AAAA resource record type is a record specific to the Internet
+//!   class that stores a single IPv6 address.
+//!
+//!   The IANA assigned value of the type is 28 (decimal).
+//!
+//! 2.2 AAAA data format
+//!
+//!   A 128 bit IPv6 address is encoded in the data portion of an AAAA
+//!   resource record in network byte order (high-order byte first).
+//! ```
+
+use std::net::Ipv6Addr;
+
+use crate::error::*;
+use crate::serialize::binary::*;
+
+/// Read the RData from the given Decoder
+#[allow(clippy::many_single_char_names)]
+pub fn read(decoder: &mut BinDecoder) -> ProtoResult<Ipv6Addr> {
+    let a: u16 = decoder.read_u16()?.unverified(/*valid as any u16*/);
+    let b: u16 = decoder.read_u16()?.unverified(/*valid as any u16*/);
+    let c: u16 = decoder.read_u16()?.unverified(/*valid as any u16*/);
+    let d: u16 = decoder.read_u16()?.unverified(/*valid as any u16*/);
+    let e: u16 = decoder.read_u16()?.unverified(/*valid as any u16*/);
+    let f: u16 = decoder.read_u16()?.unverified(/*valid as any u16*/);
+    let g: u16 = decoder.read_u16()?.unverified(/*valid as any u16*/);
+    let h: u16 = decoder.read_u16()?.unverified(/*valid as any u16*/);
+
+    Ok(Ipv6Addr::new(a, b, c, d, e, f, g, h))
+}
+
+/// Write the RData from the given Decoder
+pub fn emit(encoder: &mut BinEncoder, address: &Ipv6Addr) -> ProtoResult<()> {
+    let segments = address.segments();
+
+    encoder.emit_u16(segments[0])?;
+    encoder.emit_u16(segments[1])?;
+    encoder.emit_u16(segments[2])?;
+    encoder.emit_u16(segments[3])?;
+    encoder.emit_u16(segments[4])?;
+    encoder.emit_u16(segments[5])?;
+    encoder.emit_u16(segments[6])?;
+    encoder.emit_u16(segments[7])?;
+    Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+    use std::net::Ipv6Addr;
+    use std::str::FromStr;
+
+    use super::*;
+    use crate::serialize::binary::bin_tests::{test_emit_data_set, test_read_data_set};
+
+    fn get_data() -> Vec<(Ipv6Addr, Vec<u8>)> {
+        vec![
+            (
+                Ipv6Addr::from_str("::").unwrap(),
+                vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+            ), // base case
+            (
+                Ipv6Addr::from_str("1::").unwrap(),
+                vec![0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+            ),
+            (
+                Ipv6Addr::from_str("0:1::").unwrap(),
+                vec![0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+            ),
+            (
+                Ipv6Addr::from_str("0:0:1::").unwrap(),
+                vec![0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+            ),
+            (
+                Ipv6Addr::from_str("0:0:0:1::").unwrap(),
+                vec![0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
+            ),
+            (
+                Ipv6Addr::from_str("::1:0:0:0").unwrap(),
+                vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
+            ),
+            (
+                Ipv6Addr::from_str("::1:0:0").unwrap(),
+                vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
+            ),
+            (
+                Ipv6Addr::from_str("::1:0").unwrap(),
+                vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
+            ),
+            (
+                Ipv6Addr::from_str("::1").unwrap(),
+                vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
+            ),
+            (
+                Ipv6Addr::from_str("::127.0.0.1").unwrap(),
+                vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 0, 0, 1],
+            ),
+            (
+                Ipv6Addr::from_str("FF00::192.168.64.32").unwrap(),
+                vec![255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 168, 64, 32],
+            ),
+        ]
+    }
+
+    #[test]
+    fn test_read() {
+        test_read_data_set(get_data(), |ref mut d| read(d));
+    }
+
+    #[test]
+    fn test_emit() {
+        test_emit_data_set(get_data(), |e, d| emit(e, &d));
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/caa.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/caa.rs
new file mode 100644
index 0000000..49e7083
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/caa.rs
@@ -0,0 +1,1074 @@
+// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! allows a DNS domain name holder to specify one or more Certification
+//! Authorities (CAs) authorized to issue certificates for that domain.
+//!
+//! [RFC 6844, DNS Certification Authority Authorization, January 2013](https://tools.ietf.org/html/rfc6844)
+//!
+//! ```text
+//! The Certification Authority Authorization (CAA) DNS Resource Record
+//! allows a DNS domain name holder to specify one or more Certification
+//! Authorities (CAs) authorized to issue certificates for that domain.
+//! CAA Resource Records allow a public Certification Authority to
+//! implement additional controls to reduce the risk of unintended
+//! certificate mis-issue.  This document defines the syntax of the CAA
+//! record and rules for processing CAA records by certificate issuers.
+//! ```
+
+use std::str;
+
+use crate::error::*;
+use crate::rr::domain::Name;
+use crate::serialize::binary::*;
+use url::Url;
+
+/// The CAA RR Type
+///
+/// [RFC 6844, DNS Certification Authority Authorization, January 2013](https://tools.ietf.org/html/rfc6844#section-3)
+///
+/// ```text
+/// 3.  The CAA RR Type
+///
+/// A CAA RR consists of a flags byte and a tag-value pair referred to as
+/// a property.  Multiple properties MAY be associated with the same
+/// domain name by publishing multiple CAA RRs at that domain name.  The
+/// following flag is defined:
+///
+/// Issuer Critical:  If set to '1', indicates that the corresponding
+///    property tag MUST be understood if the semantics of the CAA record
+///    are to be correctly interpreted by an issuer.
+///
+///    Issuers MUST NOT issue certificates for a domain if the relevant
+///    CAA Resource Record set contains unknown property tags that have
+///    the Critical bit set.
+///
+/// The following property tags are defined:
+///
+/// issue <Issuer Domain Name> [; <name>=<value> ]* :  The issue property
+///    entry authorizes the holder of the domain name <Issuer Domain
+///    Name> or a party acting under the explicit authority of the holder
+///    of that domain name to issue certificates for the domain in which
+///    the property is published.
+///
+/// issuewild <Issuer Domain Name> [; <name>=<value> ]* :  The issuewild
+///    property entry authorizes the holder of the domain name <Issuer
+///    Domain Name> or a party acting under the explicit authority of the
+///    holder of that domain name to issue wildcard certificates for the
+///    domain in which the property is published.
+///
+/// iodef <URL> :  Specifies a URL to which an issuer MAY report
+///    certificate issue requests that are inconsistent with the issuer's
+///    Certification Practices or Certificate Policy, or that a
+///    Certificate Evaluator may use to report observation of a possible
+///    policy violation.  The Incident Object Description Exchange Format
+///    (IODEF) format is used [RFC5070].
+///
+/// The following example is a DNS zone file (see [RFC1035]) that informs
+/// CAs that certificates are not to be issued except by the holder of
+/// the domain name 'ca.example.net' or an authorized agent thereof.
+/// This policy applies to all subordinate domains under example.com.
+///
+/// $ORIGIN example.com
+/// .       CAA 0 issue "ca.example.net"
+///
+/// If the domain name holder specifies one or more iodef properties, a
+/// certificate issuer MAY report invalid certificate requests to that
+/// address.  In the following example, the domain name holder specifies
+/// that reports may be made by means of email with the IODEF data as an
+/// attachment, a Web service [RFC6546], or both:
+///
+/// $ORIGIN example.com
+/// .       CAA 0 issue "ca.example.net"
+/// .       CAA 0 iodef "mailto:security@example.com"
+/// .       CAA 0 iodef "http://iodef.example.com/"
+///
+/// A certificate issuer MAY specify additional parameters that allow
+/// customers to specify additional parameters governing certificate
+/// issuance.  This might be the Certificate Policy under which the
+/// certificate is to be issued, the authentication process to be used
+/// might be specified, or an account number specified by the CA to
+/// enable these parameters to be retrieved.
+///
+/// For example, the CA 'ca.example.net' has requested its customer
+/// 'example.com' to specify the CA's account number '230123' in each of
+/// the customer's CAA records.
+///
+/// $ORIGIN example.com
+/// .       CAA 0 issue "ca.example.net; account=230123"
+///
+/// The syntax of additional parameters is a sequence of name-value pairs
+/// as defined in Section 5.2.  The semantics of such parameters is left
+/// to site policy and is outside the scope of this document.
+///
+/// The critical flag is intended to permit future versions CAA to
+/// introduce new semantics that MUST be understood for correct
+/// processing of the record, preventing conforming CAs that do not
+/// recognize the new semantics from issuing certificates for the
+/// indicated domains.
+///
+/// In the following example, the property 'tbs' is flagged as critical.
+/// Neither the example.net CA nor any other issuer is authorized to
+/// issue under either policy unless the processing rules for the 'tbs'
+/// property tag are understood.
+///
+/// $ORIGIN example.com
+/// .       CAA 0 issue "ca.example.net; policy=ev"
+/// .       CAA 128 tbs "Unknown"
+///
+/// Note that the above restrictions only apply at certificate issue.
+/// Since the validity of an end entity certificate is typically a year
+/// or more, it is quite possible that the CAA records published at a
+/// domain will change between the time a certificate was issued and
+/// validation by a relying party.
+/// ```
+#[derive(Debug, PartialEq, Eq, Hash, Clone)]
+pub struct CAA {
+    #[doc(hidden)]
+    pub issuer_critical: bool,
+    #[doc(hidden)]
+    pub tag: Property,
+    #[doc(hidden)]
+    pub value: Value,
+}
+
+impl CAA {
+    fn issue(
+        issuer_critical: bool,
+        tag: Property,
+        name: Option<Name>,
+        options: Vec<KeyValue>,
+    ) -> Self {
+        assert!(tag.is_issue() || tag.is_issuewild());
+
+        CAA {
+            issuer_critical,
+            tag,
+            value: Value::Issuer(name, options),
+        }
+    }
+
+    /// Creates a new CAA issue record data, the tag is `issue`
+    ///
+    /// # Arguments
+    ///
+    /// * `issuer_critical` - indicates that the corresponding property tag MUST be understood if the semantics of the CAA record are to be correctly interpreted by an issuer
+    /// * `name` - authorized to issue certificates for the associated record label
+    /// * `options` - additional options for the issuer, e.g. 'account', etc.
+    pub fn new_issue(issuer_critical: bool, name: Option<Name>, options: Vec<KeyValue>) -> Self {
+        Self::issue(issuer_critical, Property::Issue, name, options)
+    }
+
+    /// Creates a new CAA issue record data, the tag is `issuewild`
+    ///
+    /// # Arguments
+    ///
+    /// * `issuer_critical` - indicates that the corresponding property tag MUST be understood if the semantics of the CAA record are to be correctly interpreted by an issuer
+    /// * `name` - authorized to issue certificates for the associated record label
+    /// * `options` - additional options for the issuer, e.g. 'account', etc.
+    pub fn new_issuewild(
+        issuer_critical: bool,
+        name: Option<Name>,
+        options: Vec<KeyValue>,
+    ) -> Self {
+        Self::issue(issuer_critical, Property::IssueWild, name, options)
+    }
+
+    /// Creates a new CAA issue record data, the tag is `iodef`
+    ///
+    /// # Arguments
+    ///
+    /// * `issuer_critical` - indicates that the corresponding property tag MUST be understood if the semantics of the CAA record are to be correctly interpreted by an issuer
+    /// * `url` - Url where issuer errors should be reported
+    ///
+    /// # Panics
+    ///
+    /// If `value` is not `Value::Issuer`
+    pub fn new_iodef(issuer_critical: bool, url: Url) -> Self {
+        CAA {
+            issuer_critical,
+            tag: Property::Iodef,
+            value: Value::Url(url),
+        }
+    }
+
+    /// Indicates that the corresponding property tag MUST be understood if the semantics of the CAA record are to be correctly interpreted by an issuer
+    pub fn issuer_critical(&self) -> bool {
+        self.issuer_critical
+    }
+
+    /// The property tag, see struct documentation
+    pub fn tag(&self) -> &Property {
+        &self.tag
+    }
+
+    /// a potentially associated value with the property tag, see struct documentation
+    pub fn value(&self) -> &Value {
+        &self.value
+    }
+}
+
+/// Specifies in what contexts this key may be trusted for use
+#[derive(Debug, PartialEq, Eq, Hash, Clone)]
+pub enum Property {
+    /// The issue property
+    ///    entry authorizes the holder of the domain name <Issuer Domain
+    ///    Name> or a party acting under the explicit authority of the holder
+    ///    of that domain name to issue certificates for the domain in which
+    ///    the property is published.
+    Issue,
+    /// The issuewild
+    ///    property entry authorizes the holder of the domain name <Issuer
+    ///    Domain Name> or a party acting under the explicit authority of the
+    ///    holder of that domain name to issue wildcard certificates for the
+    ///    domain in which the property is published.
+    IssueWild,
+    /// Specifies a URL to which an issuer MAY report
+    ///    certificate issue requests that are inconsistent with the issuer's
+    ///    Certification Practices or Certificate Policy, or that a
+    ///    Certificate Evaluator may use to report observation of a possible
+    ///    policy violation. The Incident Object Description Exchange Format
+    ///    (IODEF) format is used [RFC5070].
+    Iodef,
+    /// Unknown format to Trust-DNS
+    Unknown(String),
+}
+
+impl Property {
+    fn as_str(&self) -> &str {
+        match *self {
+            Property::Issue => "issue",
+            Property::IssueWild => "issuewild",
+            Property::Iodef => "iodef",
+            Property::Unknown(ref property) => property,
+        }
+    }
+
+    /// true if the property is `issue`
+    pub fn is_issue(&self) -> bool {
+        if let Property::Issue = *self {
+            true
+        } else {
+            false
+        }
+    }
+
+    /// true if the property is `issueworld`
+    pub fn is_issuewild(&self) -> bool {
+        if let Property::IssueWild = *self {
+            true
+        } else {
+            false
+        }
+    }
+
+    /// true if the property is `iodef`
+    pub fn is_iodef(&self) -> bool {
+        if let Property::Iodef = *self {
+            true
+        } else {
+            false
+        }
+    }
+
+    /// true if the property is not known to Trust-DNS
+    pub fn is_unknown(&self) -> bool {
+        if let Property::Unknown(_) = *self {
+            true
+        } else {
+            false
+        }
+    }
+}
+
+impl From<String> for Property {
+    fn from(tag: String) -> Property {
+        // RFC6488 section 5.1 states that "Matching of tag values is case
+        // insensitive."
+        let lower = tag.to_ascii_lowercase();
+        match &lower as &str {
+            "issue" => return Property::Issue,
+            "issuewild" => return Property::IssueWild,
+            "iodef" => return Property::Iodef,
+            &_ => (),
+        }
+
+        Property::Unknown(tag)
+    }
+}
+
+/// Potential values.
+///
+/// These are based off the Tag field:
+///
+/// `Issue` and `IssueWild` => `Issuer`,
+/// `Iodef` => `Url`,
+/// `Unknown` => `Unknown`,
+#[derive(Debug, PartialEq, Eq, Hash, Clone)]
+pub enum Value {
+    /// Issuer authorized to issue certs for this zone, and any associated parameters
+    Issuer(Option<Name>, Vec<KeyValue>),
+    /// Url to which to send CA errors
+    Url(Url),
+    /// Unrecognized tag and value by Trust-DNS
+    Unknown(Vec<u8>),
+}
+
+impl Value {
+    /// true if this is an `Issuer`
+    pub fn is_issuer(&self) -> bool {
+        if let Value::Issuer(..) = *self {
+            true
+        } else {
+            false
+        }
+    }
+
+    /// true if this is a `Url`
+    pub fn is_url(&self) -> bool {
+        if let Value::Url(..) = *self {
+            true
+        } else {
+            false
+        }
+    }
+
+    /// true if this is an `Unknown`
+    pub fn is_unknown(&self) -> bool {
+        if let Value::Unknown(..) = *self {
+            true
+        } else {
+            false
+        }
+    }
+}
+
+fn read_value(
+    tag: &Property,
+    decoder: &mut BinDecoder,
+    value_len: Restrict<u16>,
+) -> ProtoResult<Value> {
+    let value_len = value_len.map(|u| u as usize).unverified(/*used purely as length safely*/);
+    match *tag {
+        Property::Issue | Property::IssueWild => {
+            let slice = decoder.read_slice(value_len)?.unverified(/*read_issuer verified as safe*/);
+            let value = read_issuer(slice)?;
+            Ok(Value::Issuer(value.0, value.1))
+        }
+        Property::Iodef => {
+            let url = decoder.read_slice(value_len)?.unverified(/*read_iodef verified as safe*/);
+            let url = read_iodef(url)?;
+            Ok(Value::Url(url))
+        }
+        Property::Unknown(_) => Ok(Value::Unknown(
+            decoder.read_vec(value_len)?.unverified(/*unknown will fail in usage*/),
+        )),
+    }
+}
+
+fn emit_value(encoder: &mut BinEncoder, value: &Value) -> ProtoResult<()> {
+    match *value {
+        Value::Issuer(ref name, ref key_values) => {
+            // output the name
+            if let Some(ref name) = *name {
+                let name = name.to_string();
+                encoder.emit_vec(name.as_bytes())?;
+            }
+
+            // if there was no name, then we just output ';'
+            if name.is_none() && key_values.is_empty() {
+                return encoder.emit(b';');
+            }
+
+            for key_value in key_values {
+                encoder.emit(b';')?;
+                encoder.emit(b' ')?;
+                encoder.emit_vec(key_value.key.as_bytes())?;
+                encoder.emit(b'=')?;
+                encoder.emit_vec(key_value.value.as_bytes())?;
+            }
+
+            Ok(())
+        }
+        Value::Url(ref url) => {
+            let url = url.as_str();
+            let bytes = url.as_bytes();
+            encoder.emit_vec(bytes)
+        }
+        Value::Unknown(ref data) => encoder.emit_vec(data),
+    }
+}
+
+enum ParseNameKeyPairState {
+    BeforeKey(Vec<KeyValue>),
+    Key {
+        first_char: bool,
+        key: String,
+        key_values: Vec<KeyValue>,
+    },
+    Value {
+        key: String,
+        value: String,
+        key_values: Vec<KeyValue>,
+    },
+}
+
+/// Reads the issuer field according to the spec
+///
+/// [RFC 6844, DNS Certification Authority Authorization, January 2013](https://tools.ietf.org/html/rfc6844#section-5.2)
+///
+/// ```text
+/// 5.2.  CAA issue Property
+///
+///    The issue property tag is used to request that certificate issuers
+///    perform CAA issue restriction processing for the domain and to grant
+///    authorization to specific certificate issuers.
+///
+///    The CAA issue property value has the following sub-syntax (specified
+///    in ABNF as per [RFC5234]).
+///
+///    issuevalue  = space [domain] space [";" *(space parameter) space]
+///
+///    domain = label *("." label)
+///    label = (ALPHA / DIGIT) *( *("-") (ALPHA / DIGIT))
+///
+///    space = *(SP / HTAB)
+///
+///    parameter =  tag "=" value
+///
+///    tag = 1*(ALPHA / DIGIT)
+///
+///    value = *VCHAR
+///
+///    For consistency with other aspects of DNS administration, domain name
+///    values are specified in letter-digit-hyphen Label (LDH-Label) form.
+///
+///    A CAA record with an issue parameter tag that does not specify a
+///    domain name is a request that certificate issuers perform CAA issue
+///    restriction processing for the corresponding domain without granting
+///    authorization to any certificate issuer.
+///
+///    This form of issue restriction would be appropriate to specify that
+///    no certificates are to be issued for the domain in question.
+///
+///    For example, the following CAA record set requests that no
+///    certificates be issued for the domain 'nocerts.example.com' by any
+///    certificate issuer.
+///
+///    nocerts.example.com       CAA 0 issue ";"
+///
+///    A CAA record with an issue parameter tag that specifies a domain name
+///    is a request that certificate issuers perform CAA issue restriction
+///    processing for the corresponding domain and grants authorization to
+///    the certificate issuer specified by the domain name.
+///
+///    For example, the following CAA record set requests that no
+///    certificates be issued for the domain 'certs.example.com' by any
+///    certificate issuer other than the example.net certificate issuer.
+///
+///    certs.example.com       CAA 0 issue "example.net"
+///
+///    CAA authorizations are additive; thus, the result of specifying both
+///    the empty issuer and a specified issuer is the same as specifying
+///    just the specified issuer alone.
+///
+///    An issuer MAY choose to specify issuer-parameters that further
+///    constrain the issue of certificates by that issuer, for example,
+///    specifying that certificates are to be subject to specific validation
+///    polices, billed to certain accounts, or issued under specific trust
+///    anchors.
+///
+///    The semantics of issuer-parameters are determined by the issuer
+///    alone.
+/// ```
+///
+/// Updated parsing rules:
+///
+/// [RFC 6844bis, CAA Resource Record, May 2018](https://tools.ietf.org/html/draft-ietf-lamps-rfc6844bis-00)
+/// [RFC 6844, CAA Record Extensions, May 2018](https://tools.ietf.org/html/draft-ietf-acme-caa-04)
+///
+/// This explicitly allows `-` in key names, diverging from the original RFC. To support this, key names will
+/// allow `-` as non-starting characters. Additionally, this significantly relaxes the characters allowed in the value
+/// to allow URL like characters (it does not validate URL syntax).
+pub fn read_issuer(bytes: &[u8]) -> ProtoResult<(Option<Name>, Vec<KeyValue>)> {
+    let mut byte_iter = bytes.iter();
+
+    // we want to reuse the name parsing rules
+    let name: Option<Name> = {
+        let take_name = byte_iter.by_ref().take_while(|ch| char::from(**ch) != ';');
+        let name_str = take_name.cloned().collect::<Vec<u8>>();
+
+        if !name_str.is_empty() {
+            let name_str = str::from_utf8(&name_str)?;
+            Some(Name::parse(name_str, None)?)
+        } else {
+            None
+        }
+    };
+
+    // initial state is looking for a key ';' is valid...
+    let mut state = ParseNameKeyPairState::BeforeKey(vec![]);
+
+    // run the state machine through all remaining data, collecting all key/value pairs.
+    for ch in byte_iter {
+        match state {
+            // Name was already successfully parsed, otherwise we couldn't get here.
+            ParseNameKeyPairState::BeforeKey(key_values) => {
+                match char::from(*ch) {
+                    // gobble ';', ' ', and tab
+                    ';' | ' ' | '\u{0009}' => state = ParseNameKeyPairState::BeforeKey(key_values),
+                    ch if ch.is_alphanumeric() && ch != '=' => {
+                        // We found the beginning of a new Key
+                        let mut key = String::new();
+                        key.push(ch);
+
+                        state = ParseNameKeyPairState::Key {
+                            first_char: true,
+                            key,
+                            key_values,
+                        }
+                    }
+                    ch => return Err(format!("bad character in CAA issuer key: {}", ch).into()),
+                }
+            }
+            ParseNameKeyPairState::Key {
+                first_char,
+                mut key,
+                key_values,
+            } => {
+                match char::from(*ch) {
+                    // transition to value
+                    '=' => {
+                        let value = String::new();
+                        state = ParseNameKeyPairState::Value {
+                            key,
+                            value,
+                            key_values,
+                        }
+                    }
+                    // push onto the existing key
+                    ch if (ch.is_alphanumeric() || (!first_char && ch == '-'))
+                        && ch != '='
+                        && ch != ';' =>
+                    {
+                        key.push(ch);
+                        state = ParseNameKeyPairState::Key {
+                            first_char: false,
+                            key,
+                            key_values,
+                        }
+                    }
+                    ch => return Err(format!("bad character in CAA issuer key: {}", ch).into()),
+                }
+            }
+            ParseNameKeyPairState::Value {
+                key,
+                mut value,
+                mut key_values,
+            } => {
+                match char::from(*ch) {
+                    // transition back to find another pair
+                    ';' => {
+                        key_values.push(KeyValue { key, value });
+                        state = ParseNameKeyPairState::BeforeKey(key_values);
+                    }
+                    // push onto the existing key
+                    ch if !ch.is_control() && !ch.is_whitespace() => {
+                        value.push(ch);
+
+                        state = ParseNameKeyPairState::Value {
+                            key,
+                            value,
+                            key_values,
+                        }
+                    }
+                    ch => return Err(format!("bad character in CAA issuer value: '{}'", ch).into()),
+                }
+            }
+        }
+    }
+
+    // valid final states are BeforeKey, where there was a final ';' but nothing followed it.
+    //                        Value, where we collected the final chars of the value, but no more data
+    let key_values = match state {
+        ParseNameKeyPairState::BeforeKey(key_values) => key_values,
+        ParseNameKeyPairState::Value {
+            key,
+            value,
+            mut key_values,
+        } => {
+            key_values.push(KeyValue { key, value });
+            key_values
+        }
+        ParseNameKeyPairState::Key { key, .. } => {
+            return Err(format!("key missing value: {}", key).into());
+        }
+    };
+
+    Ok((name, key_values))
+}
+
+/// Incident Object Description Exchange Format
+///
+/// [RFC 6844, DNS Certification Authority Authorization, January 2013](https://tools.ietf.org/html/rfc6844#section-5.4)
+///
+/// ```text
+/// 5.4.  CAA iodef Property
+///
+///    The iodef property specifies a means of reporting certificate issue
+///    requests or cases of certificate issue for the corresponding domain
+///    that violate the security policy of the issuer or the domain name
+///    holder.
+///
+///    The Incident Object Description Exchange Format (IODEF) [RFC5070] is
+///    used to present the incident report in machine-readable form.
+///
+///    The iodef property takes a URL as its parameter.  The URL scheme type
+///    determines the method used for reporting:
+///
+///    mailto:  The IODEF incident report is reported as a MIME email
+///       attachment to an SMTP email that is submitted to the mail address
+///       specified.  The mail message sent SHOULD contain a brief text
+///       message to alert the recipient to the nature of the attachment.
+///
+///    http or https:  The IODEF report is submitted as a Web service
+///       request to the HTTP address specified using the protocol specified
+///       in [RFC6546].
+/// ```
+pub fn read_iodef(url: &[u8]) -> ProtoResult<Url> {
+    let url = str::from_utf8(url)?;
+    let url = Url::parse(url)?;
+    Ok(url)
+}
+
+/// Issuer key and value pairs.
+///
+/// See [RFC 6844, DNS Certification Authority Authorization, January 2013](https://tools.ietf.org/html/rfc6844#section-5.2)
+/// for more explanation.
+#[derive(Debug, PartialEq, Eq, Hash, Clone)]
+pub struct KeyValue {
+    key: String,
+    value: String,
+}
+
+impl KeyValue {
+    /// Construct a new KeyValue pair
+    pub fn new<K: Into<String>, V: Into<String>>(key: K, value: V) -> Self {
+        KeyValue {
+            key: key.into(),
+            value: value.into(),
+        }
+    }
+
+    /// Gets a reference to the key of the pair.
+    pub fn key(&self) -> &str {
+        &self.key
+    }
+
+    /// Gets a reference to the value of the pair.
+    pub fn value(&self) -> &str {
+        &self.value
+    }
+}
+
+/// Read the binary CAA format
+///
+/// [RFC 6844, DNS Certification Authority Authorization, January 2013](https://tools.ietf.org/html/rfc6844#section-5.1)
+///
+/// ```text
+/// 5.1.  Syntax
+///
+///   A CAA RR contains a single property entry consisting of a tag-value
+///   pair.  Each tag represents a property of the CAA record.  The value
+///   of a CAA property is that specified in the corresponding value field.
+///
+///   A domain name MAY have multiple CAA RRs associated with it and a
+///   given property MAY be specified more than once.
+///
+///   The CAA data field contains one property entry.  A property entry
+///   consists of the following data fields:
+///
+///   +0-1-2-3-4-5-6-7-|0-1-2-3-4-5-6-7-|
+///   | Flags          | Tag Length = n |
+///   +----------------+----------------+...+---------------+
+///   | Tag char 0     | Tag char 1     |...| Tag char n-1  |
+///   +----------------+----------------+...+---------------+
+///   +----------------+----------------+.....+----------------+
+///   | Value byte 0   | Value byte 1   |.....| Value byte m-1 |
+///   +----------------+----------------+.....+----------------+
+///
+///   Where n is the length specified in the Tag length field and m is the
+///   remaining octets in the Value field (m = d - n - 2) where d is the
+///   length of the RDATA section.
+///
+///   The data fields are defined as follows:
+///
+///   Flags:  One octet containing the following fields:
+///
+///      Bit 0, Issuer Critical Flag:  If the value is set to '1', the
+///         critical flag is asserted and the property MUST be understood
+///         if the CAA record is to be correctly processed by a certificate
+///         issuer.
+///
+///         A Certification Authority MUST NOT issue certificates for any
+///         Domain that contains a CAA critical property for an unknown or
+///         unsupported property tag that for which the issuer critical
+///         flag is set.
+///
+///      Note that according to the conventions set out in [RFC1035], bit 0
+///      is the Most Significant Bit and bit 7 is the Least Significant
+///      Bit. Thus, the Flags value 1 means that bit 7 is set while a value
+///      of 128 means that bit 0 is set according to this convention.
+///
+///      All other bit positions are reserved for future use.
+///
+///      To ensure compatibility with future extensions to CAA, DNS records
+///      compliant with this version of the CAA specification MUST clear
+///      (set to "0") all reserved flags bits.  Applications that interpret
+///      CAA records MUST ignore the value of all reserved flag bits.
+///
+///   Tag Length:  A single octet containing an unsigned integer specifying
+///      the tag length in octets.  The tag length MUST be at least 1 and
+///      SHOULD be no more than 15.
+///
+///   Tag:  The property identifier, a sequence of US-ASCII characters.
+///
+///      Tag values MAY contain US-ASCII characters 'a' through 'z', 'A'
+///      through 'Z', and the numbers 0 through 9.  Tag values SHOULD NOT
+///      contain any other characters.  Matching of tag values is case
+///      insensitive.
+///
+///      Tag values submitted for registration by IANA MUST NOT contain any
+///      characters other than the (lowercase) US-ASCII characters 'a'
+///      through 'z' and the numbers 0 through 9.
+///
+///   Value:  A sequence of octets representing the property value.
+///      Property values are encoded as binary values and MAY employ sub-
+///      formats.
+///
+///      The length of the value field is specified implicitly as the
+///      remaining length of the enclosing Resource Record data field.
+/// ```
+pub fn read(decoder: &mut BinDecoder, rdata_length: Restrict<u16>) -> ProtoResult<CAA> {
+    // the spec declares that other flags should be ignored for future compatibility...
+    let issuer_critical: bool =
+        decoder.read_u8()?.unverified(/*used as bitfield*/) & 0b1000_0000 != 0;
+
+    let tag_len = decoder.read_u8()?;
+    let value_len: Restrict<u16> = rdata_length
+        .checked_sub(u16::from(tag_len.unverified(/*safe usage here*/)))
+        .checked_sub(2)
+        .map_err(|_| ProtoError::from("CAA tag character(s) out of bounds"))?;
+
+    let tag = read_tag(decoder, tag_len)?;
+    let tag = Property::from(tag);
+    let value = read_value(&tag, decoder, value_len)?;
+
+    Ok(CAA {
+        issuer_critical,
+        tag,
+        value,
+    })
+}
+
+// TODO: change this to return &str
+fn read_tag(decoder: &mut BinDecoder, len: Restrict<u8>) -> ProtoResult<String> {
+    let len = len
+        .map(|len| len as usize)
+        .verify_unwrap(|len| *len > 0 && *len <= 15)
+        .map_err(|_| ProtoError::from("CAA tag length out of bounds, 1-15"))?;
+    let mut tag = String::with_capacity(len);
+
+    for _ in 0..len {
+        let ch = decoder
+            .pop()?
+            .map(char::from)
+            .verify_unwrap(|ch| match ch {
+                'a'..='z' | 'A'..='Z' | '0'..='9' => true,
+                _ => false,
+            })
+            .map_err(|_| ProtoError::from("CAA tag character(s) out of bounds"))?;
+
+        tag.push(ch);
+    }
+
+    Ok(tag)
+}
+
+/// writes out the tag in binary form to the buffer, returning the number of bytes written
+fn emit_tag(buf: &mut [u8], tag: &Property) -> ProtoResult<u8> {
+    let property = tag.as_str();
+    let property = property.as_bytes();
+
+    let len = property.len();
+    if len > ::std::u8::MAX as usize {
+        return Err(format!("CAA property too long: {}", len).into());
+    }
+    if buf.len() < len {
+        return Err(format!(
+            "insufficient capacity in CAA buffer: {} for tag: {}",
+            buf.len(),
+            len
+        )
+        .into());
+    }
+
+    // copy into the buffer
+    let buf = &mut buf[0..len];
+    buf.copy_from_slice(property);
+
+    Ok(len as u8)
+}
+
+/// Write the RData from the given Decoder
+pub fn emit(encoder: &mut BinEncoder, caa: &CAA) -> ProtoResult<()> {
+    let mut flags = 0_u8;
+
+    if caa.issuer_critical {
+        flags |= 0b1000_0000;
+    }
+
+    encoder.emit(flags)?;
+    // TODO: it might be interesting to use the new place semantics here to output all the data, then place the length back to the beginning...
+    let mut tag_buf = [0_u8; ::std::u8::MAX as usize];
+    let len = emit_tag(&mut tag_buf, &caa.tag)?;
+
+    // now write to the encoder
+    encoder.emit(len)?;
+    encoder.emit_vec(&tag_buf[0..len as usize])?;
+    emit_value(encoder, &caa.value)?;
+
+    Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+    #![allow(clippy::dbg_macro, clippy::print_stdout)]
+
+    use super::*;
+    use std::str;
+
+    #[test]
+    fn test_read_tag() {
+        let ok_under15 = b"abcxyzABCXYZ019";
+        let mut decoder = BinDecoder::new(ok_under15);
+
+        let read = read_tag(&mut decoder, Restrict::new(ok_under15.len() as u8))
+            .expect("failed to read tag");
+
+        assert_eq!(str::from_utf8(ok_under15).unwrap(), read);
+    }
+
+    #[test]
+    fn test_bad_tag() {
+        let bad_under15 = b"-";
+        let mut decoder = BinDecoder::new(bad_under15);
+
+        assert!(read_tag(&mut decoder, Restrict::new(bad_under15.len() as u8)).is_err());
+    }
+
+    #[test]
+    fn test_too_short_tag() {
+        let too_short = b"";
+        let mut decoder = BinDecoder::new(too_short);
+
+        assert!(read_tag(&mut decoder, Restrict::new(too_short.len() as u8)).is_err());
+    }
+
+    #[test]
+    fn test_too_long_tag() {
+        let too_long = b"0123456789abcdef";
+        let mut decoder = BinDecoder::new(too_long);
+
+        assert!(read_tag(&mut decoder, Restrict::new(too_long.len() as u8)).is_err());
+    }
+
+    #[test]
+    fn test_from_str_property() {
+        assert_eq!(Property::from("Issue".to_string()), Property::Issue);
+        assert_eq!(Property::from("issueWild".to_string()), Property::IssueWild);
+        assert_eq!(Property::from("iodef".to_string()), Property::Iodef);
+        assert_eq!(
+            Property::from("unknown".to_string()),
+            Property::Unknown("unknown".to_string())
+        );
+    }
+
+    #[test]
+    fn test_read_issuer() {
+        // (Option<Name>, Vec<KeyValue>)
+        assert_eq!(
+            read_issuer(b"ca.example.net; account=230123").unwrap(),
+            (
+                Some(Name::parse("ca.example.net", None).unwrap()),
+                vec![KeyValue {
+                    key: "account".to_string(),
+                    value: "230123".to_string(),
+                }],
+            )
+        );
+
+        assert_eq!(
+            read_issuer(b"ca.example.net").unwrap(),
+            (Some(Name::parse("ca.example.net", None,).unwrap(),), vec![],)
+        );
+        assert_eq!(
+            read_issuer(b"ca.example.net; policy=ev").unwrap(),
+            (
+                Some(Name::parse("ca.example.net", None).unwrap(),),
+                vec![KeyValue {
+                    key: "policy".to_string(),
+                    value: "ev".to_string(),
+                }],
+            )
+        );
+        assert_eq!(
+            read_issuer(b"ca.example.net; account=230123; policy=ev").unwrap(),
+            (
+                Some(Name::parse("ca.example.net", None).unwrap(),),
+                vec![
+                    KeyValue {
+                        key: "account".to_string(),
+                        value: "230123".to_string(),
+                    },
+                    KeyValue {
+                        key: "policy".to_string(),
+                        value: "ev".to_string(),
+                    },
+                ],
+            )
+        );
+        assert_eq!(
+            read_issuer(b"example.net; account-uri=https://example.net/account/1234; validation-methods=dns-01").unwrap(),
+            (
+                Some(Name::parse("example.net", None).unwrap(),),
+                vec![
+                    KeyValue {
+                        key: "account-uri".to_string(),
+                        value: "https://example.net/account/1234".to_string(),
+                    },
+                    KeyValue {
+                        key: "validation-methods".to_string(),
+                        value: "dns-01".to_string(),
+                    },
+                ],
+            )
+        );
+        assert_eq!(read_issuer(b";").unwrap(), (None, vec![]));
+    }
+
+    #[test]
+    fn test_read_iodef() {
+        assert_eq!(
+            read_iodef(b"mailto:security@example.com").unwrap(),
+            Url::parse("mailto:security@example.com").unwrap()
+        );
+        assert_eq!(
+            read_iodef(b"http://iodef.example.com/").unwrap(),
+            Url::parse("http://iodef.example.com/").unwrap()
+        );
+    }
+
+    fn test_encode_decode(rdata: CAA) {
+        let mut bytes = Vec::new();
+        let mut encoder: BinEncoder = BinEncoder::new(&mut bytes);
+        emit(&mut encoder, &rdata).expect("failed to emit caa");
+        let bytes = encoder.into_bytes();
+
+        println!("bytes: {:?}", bytes);
+
+        let mut decoder: BinDecoder = BinDecoder::new(bytes);
+        let read_rdata =
+            read(&mut decoder, Restrict::new(bytes.len() as u16)).expect("failed to read back");
+        assert_eq!(rdata, read_rdata);
+    }
+
+    #[test]
+    fn test_encode_decode_issue() {
+        test_encode_decode(CAA::new_issue(true, None, vec![]));
+        test_encode_decode(CAA::new_issue(
+            true,
+            Some(Name::parse("example.com", None).unwrap()),
+            vec![],
+        ));
+        test_encode_decode(CAA::new_issue(
+            true,
+            Some(Name::parse("example.com", None).unwrap()),
+            vec![KeyValue::new("key", "value")],
+        ));
+        // technically the this parser supports this case, though it's not clear it's something the spec allows for
+        test_encode_decode(CAA::new_issue(
+            true,
+            None,
+            vec![KeyValue::new("key", "value")],
+        ));
+        // test fqdn
+        test_encode_decode(CAA::new_issue(
+            true,
+            Some(Name::parse("example.com.", None).unwrap()),
+            vec![],
+        ));
+    }
+
+    #[test]
+    fn test_encode_decode_issuewild() {
+        test_encode_decode(CAA::new_issuewild(false, None, vec![]));
+        // other variants handled in test_encode_decode_issue
+    }
+
+    #[test]
+    fn test_encode_decode_iodef() {
+        test_encode_decode(CAA::new_iodef(
+            true,
+            Url::parse("http://www.example.com").unwrap(),
+        ));
+        test_encode_decode(CAA::new_iodef(
+            false,
+            Url::parse("mailto:root@example.com").unwrap(),
+        ));
+    }
+
+    fn test_encode(rdata: CAA, encoded: &[u8]) {
+        let mut bytes = Vec::new();
+        let mut encoder: BinEncoder = BinEncoder::new(&mut bytes);
+        emit(&mut encoder, &rdata).expect("failed to emit caa");
+        let bytes = encoder.into_bytes();
+        assert_eq!(&bytes as &[u8], encoded);
+    }
+
+    #[test]
+    fn test_encode_non_fqdn() {
+        let name_bytes: &[u8] = b"issueexample.com";
+        let header: &[u8] = &[128, 5];
+        let encoded: Vec<u8> = header.iter().chain(name_bytes.iter()).cloned().collect();
+
+        test_encode(
+            CAA::new_issue(
+                true,
+                Some(Name::parse("example.com", None).unwrap()),
+                vec![],
+            ),
+            &encoded,
+        );
+    }
+
+    #[test]
+    fn test_encode_fqdn() {
+        let name_bytes: &[u8] = b"issueexample.com.";
+        let header: [u8; 2] = [128, 5];
+        let encoded: Vec<u8> = header.iter().chain(name_bytes.iter()).cloned().collect();
+
+        test_encode(
+            CAA::new_issue(
+                true,
+                Some(Name::parse("example.com.", None).unwrap()),
+                vec![],
+            ),
+            &encoded,
+        );
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/mod.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/mod.rs
new file mode 100644
index 0000000..f463cdb
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/mod.rs
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2015-2019 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! All record data structures and related serialization methods
+
+// TODO: these should each be it's own struct, it would make parsing and decoding a little cleaner
+//  and also a little more ergonomic when accessing.
+// each of these module's has the parser for that rdata embedded, to keep the file sizes down...
+pub mod a;
+pub mod aaaa;
+pub mod caa;
+pub mod mx;
+pub mod name;
+pub mod naptr;
+pub mod null;
+pub mod openpgpkey;
+pub mod opt;
+pub mod soa;
+pub mod srv;
+pub mod sshfp;
+pub mod tlsa;
+pub mod txt;
+
+pub use self::caa::CAA;
+pub use self::mx::MX;
+pub use self::naptr::NAPTR;
+pub use self::null::NULL;
+pub use self::openpgpkey::OPENPGPKEY;
+pub use self::opt::OPT;
+pub use self::soa::SOA;
+pub use self::srv::SRV;
+pub use self::sshfp::SSHFP;
+pub use self::tlsa::TLSA;
+pub use self::txt::TXT;
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/mx.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/mx.rs
new file mode 100644
index 0000000..3d52b7c
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/mx.rs
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! mail exchange, email, record
+
+use crate::error::*;
+use crate::rr::domain::Name;
+use crate::serialize::binary::*;
+
+/// [RFC 1035, DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION, November 1987](https://tools.ietf.org/html/rfc1035)
+///
+/// ```text
+/// 3.3.9. MX RDATA format
+///
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///     |                  PREFERENCE                   |
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///     /                   EXCHANGE                    /
+///     /                                               /
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///
+/// MX records cause type A additional section processing for the host
+/// specified by EXCHANGE.  The use of MX RRs is explained in detail in
+/// [RFC-974].
+///
+/// ```
+#[derive(Debug, PartialEq, Eq, Hash, Clone)]
+pub struct MX {
+    preference: u16,
+    exchange: Name,
+}
+
+impl MX {
+    /// Constructs a new MX RData
+    ///
+    /// # Arguments
+    ///
+    /// * `preference` - weight of this MX record as opposed to others, lower values have the higher preference
+    /// * `exchange` - Name labels for the mail server
+    ///
+    /// # Returns
+    ///
+    /// A new MX RData for use in a Resource Record
+    pub fn new(preference: u16, exchange: Name) -> MX {
+        MX {
+            preference,
+            exchange,
+        }
+    }
+
+    /// [RFC 1035, DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION, November 1987](https://tools.ietf.org/html/rfc1035)
+    ///
+    /// ```text
+    /// PREFERENCE      A 16 bit integer which specifies the preference given to
+    ///                 this RR among others at the same owner.  Lower values
+    ///                 are preferred.
+    /// ```
+    pub fn preference(&self) -> u16 {
+        self.preference
+    }
+
+    /// [RFC 1035, DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION, November 1987](https://tools.ietf.org/html/rfc1035)
+    ///
+    /// ```text
+    /// EXCHANGE        A <domain-name> which specifies a host willing to act as
+    ///                 a mail exchange for the owner name.
+    /// ```
+    pub fn exchange(&self) -> &Name {
+        &self.exchange
+    }
+}
+
+/// Read the RData from the given Decoder
+pub fn read(decoder: &mut BinDecoder) -> ProtoResult<MX> {
+    Ok(MX::new(
+        decoder.read_u16()?.unverified(/*any u16 is valid*/),
+        Name::read(decoder)?,
+    ))
+}
+
+/// [RFC 4034](https://tools.ietf.org/html/rfc4034#section-6), DNSSEC Resource Records, March 2005
+///
+/// ```text
+/// 6.2.  Canonical RR Form
+///
+///    For the purposes of DNS security, the canonical form of an RR is the
+///    wire format of the RR where:
+///
+///    ...
+///
+///    3.  if the type of the RR is NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR,
+///        HINFO, MINFO, MX, HINFO, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX,
+///        SRV, DNAME, A6, RRSIG, or NSEC (rfc6840 removes NSEC), all uppercase
+///        US-ASCII letters in the DNS names contained within the RDATA are replaced
+///        by the corresponding lowercase US-ASCII letters;
+/// ```
+pub fn emit(encoder: &mut BinEncoder, mx: &MX) -> ProtoResult<()> {
+    let is_canonical_names = encoder.is_canonical_names();
+    encoder.emit_u16(mx.preference())?;
+    mx.exchange()
+        .emit_with_lowercase(encoder, is_canonical_names)?;
+    Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+    #![allow(clippy::dbg_macro, clippy::print_stdout)]
+
+    use super::*;
+
+    #[test]
+    pub fn test() {
+        use std::str::FromStr;
+
+        let rdata = MX::new(16, Name::from_str("mail.example.com").unwrap());
+
+        let mut bytes = Vec::new();
+        let mut encoder: BinEncoder = BinEncoder::new(&mut bytes);
+        assert!(emit(&mut encoder, &rdata).is_ok());
+        let bytes = encoder.into_bytes();
+
+        println!("bytes: {:?}", bytes);
+
+        let mut decoder: BinDecoder = BinDecoder::new(bytes);
+        let read_rdata = read(&mut decoder).expect("Decoding error");
+        assert_eq!(rdata, read_rdata);
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/name.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/name.rs
new file mode 100644
index 0000000..3e49908
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/name.rs
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! Record type for all cname like records.
+//!
+//! A generic struct for all {*}NAME pointer RData records, CNAME, NS, and PTR. Here is the text for
+//! CNAME from RFC 1035, Domain Implementation and Specification, November 1987:
+//!
+//! [RFC 1035, DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION, November 1987](https://tools.ietf.org/html/rfc1035)
+//!
+//! ```text
+//! 3.3.1. CNAME RDATA format
+//!
+//!     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+//!     /                     CNAME                     /
+//!     /                                               /
+//!     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+//!
+//! where:
+//!
+//! CNAME           A <domain-name> which specifies the canonical or primary
+//!                 name for the owner.  The owner name is an alias.
+//!
+//! CNAME RRs cause no additional section processing, but name servers may
+//! choose to restart the query at the canonical name in certain cases.  See
+//! the description of name server logic in [RFC-1034] for details.
+//! ```
+
+use crate::error::*;
+use crate::rr::domain::Name;
+use crate::serialize::binary::*;
+
+/// Read the RData from the given Decoder
+pub fn read(decoder: &mut BinDecoder) -> ProtoResult<Name> {
+    Name::read(decoder)
+}
+
+/// [RFC 4034](https://tools.ietf.org/html/rfc4034#section-6), DNSSEC Resource Records, March 2005
+///
+/// This is accurate for all currently known name records.
+///
+/// ```text
+/// 6.2.  Canonical RR Form
+///
+///    For the purposes of DNS security, the canonical form of an RR is the
+///    wire format of the RR where:
+///
+///    ...
+///
+///    3.  if the type of the RR is NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR,
+///        HINFO, MINFO, MX, HINFO, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX,
+///        SRV, DNAME, A6, RRSIG, or (rfc6840 removes NSEC), all uppercase
+///        US-ASCII letters in the DNS names contained within the RDATA are replaced
+///        by the corresponding lowercase US-ASCII letters;
+/// ```
+pub fn emit(encoder: &mut BinEncoder, name_data: &Name) -> ProtoResult<()> {
+    let is_canonical_names = encoder.is_canonical_names();
+    name_data.emit_with_lowercase(encoder, is_canonical_names)?;
+    Ok(())
+}
+
+#[test]
+pub fn test() {
+    #![allow(clippy::dbg_macro, clippy::print_stdout)]
+
+    let rdata = Name::from_ascii("WWW.example.com.").unwrap();
+
+    let mut bytes = Vec::new();
+    let mut encoder: BinEncoder = BinEncoder::new(&mut bytes);
+    assert!(emit(&mut encoder, &rdata).is_ok());
+    let bytes = encoder.into_bytes();
+
+    println!("bytes: {:?}", bytes);
+
+    let mut decoder: BinDecoder = BinDecoder::new(bytes);
+    let read_rdata = read(&mut decoder).expect("Decoding error");
+    assert_eq!(rdata, read_rdata);
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/naptr.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/naptr.rs
new file mode 100644
index 0000000..2dbfd07
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/naptr.rs
@@ -0,0 +1,290 @@
+// Copyright 2015-2019 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! Dynamic Delegation Discovery System
+
+use crate::error::*;
+use crate::rr::domain::Name;
+use crate::serialize::binary::*;
+
+/// [RFC 3403 DDDS DNS Database, October 2002](https://tools.ietf.org/html/rfc3403#section-4)
+///
+/// ```text
+/// 4.1 Packet Format
+///
+///   The packet format of the NAPTR RR is given below.  The DNS type code
+///   for NAPTR is 35.
+///
+///      The packet format for the NAPTR record is as follows
+///                                       1  1  1  1  1  1
+///         0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
+///       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///       |                     ORDER                     |
+///       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///       |                   PREFERENCE                  |
+///       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///       /                     FLAGS                     /
+///       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///       /                   SERVICES                    /
+///       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///       /                    REGEXP                     /
+///       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///       /                  REPLACEMENT                  /
+///       /                                               /
+///       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///
+///   <character-string> and <domain-name> as used here are defined in RFC
+///   1035 [7].
+/// ```
+#[derive(Debug, PartialEq, Eq, Hash, Clone)]
+pub struct NAPTR {
+    order: u16,
+    preference: u16,
+    flags: Box<[u8]>,
+    services: Box<[u8]>,
+    regexp: Box<[u8]>,
+    replacement: Name,
+}
+
+impl NAPTR {
+    /// Constructs a new NAPTR record
+    ///
+    /// # Arguments
+    ///
+    /// * `order` - the order in which the NAPTR records MUST be processed in order to accurately represent the ordered list of Rules.
+    /// * `preference` - this field is equivalent to the Priority value in the DDDS Algorithm.
+    /// * `flags` - flags to control aspects of the rewriting and interpretation of the fields in the record.  Flags are single characters from the set A-Z and 0-9.
+    /// * `services` - the Service Parameters applicable to this this delegation path.
+    /// * `regexp` - substitution expression that is applied to the original string held by the client in order to construct the next domain name to lookup.
+    /// * `replacement` - the next domain-name to query for depending on the potential values found in the flags field.
+    pub fn new(
+        order: u16,
+        preference: u16,
+        flags: Box<[u8]>,
+        services: Box<[u8]>,
+        regexp: Box<[u8]>,
+        replacement: Name,
+    ) -> Self {
+        Self {
+            order,
+            preference,
+            flags,
+            services,
+            regexp,
+            replacement,
+        }
+    }
+
+    /// ```text
+    ///   ORDER
+    ///      A 16-bit unsigned integer specifying the order in which the NAPTR
+    ///      records MUST be processed in order to accurately represent the
+    ///      ordered list of Rules.  The ordering is from lowest to highest.
+    ///      If two records have the same order value then they are considered
+    ///      to be the same rule and should be selected based on the
+    ///      combination of the Preference values and Services offered.
+    /// ```
+    pub fn order(&self) -> u16 {
+        self.order
+    }
+
+    /// ```text
+    ///   PREFERENCE
+    ///      Although it is called "preference" in deference to DNS
+    ///      terminology, this field is equivalent to the Priority value in the
+    ///      DDDS Algorithm.  It is a 16-bit unsigned integer that specifies
+    ///      the order in which NAPTR records with equal Order values SHOULD be
+    ///      processed, low numbers being processed before high numbers.  This
+    ///      is similar to the preference field in an MX record, and is used so
+    ///      domain administrators can direct clients towards more capable
+    ///      hosts or lighter weight protocols.  A client MAY look at records
+    ///      with higher preference values if it has a good reason to do so
+    ///      such as not supporting some protocol or service very well.
+    ///
+    ///      The important difference between Order and Preference is that once
+    ///      a match is found the client MUST NOT consider records with a
+    ///      different Order but they MAY process records with the same Order
+    ///      but different Preferences.  The only exception to this is noted in
+    ///      the second important Note in the DDDS algorithm specification
+    ///      concerning allowing clients to use more complex Service
+    ///      determination between steps 3 and 4 in the algorithm.  Preference
+    ///      is used to give communicate a higher quality of service to rules
+    ///      that are considered the same from an authority standpoint but not
+    ///      from a simple load balancing standpoint.
+    ///
+    ///      It is important to note that DNS contains several load balancing
+    ///      mechanisms and if load balancing among otherwise equal services
+    ///      should be needed then methods such as SRV records or multiple A
+    ///      records should be utilized to accomplish load balancing.
+    /// ```
+    pub fn preference(&self) -> u16 {
+        self.preference
+    }
+
+    /// ```text
+    ///   FLAGS
+    ///      A <character-string> containing flags to control aspects of the
+    ///      rewriting and interpretation of the fields in the record.  Flags
+    ///      are single characters from the set A-Z and 0-9.  The case of the
+    ///      alphabetic characters is not significant.  The field can be empty.
+    ///
+    ///      It is up to the Application specifying how it is using this
+    ///      Database to define the Flags in this field.  It must define which
+    ///      ones are terminal and which ones are not.
+    /// ```
+    pub fn flags(&self) -> &[u8] {
+        &self.flags
+    }
+
+    /// ```text
+    ///   SERVICES
+    ///      A <character-string> that specifies the Service Parameters
+    ///      applicable to this this delegation path.  It is up to the
+    ///      Application Specification to specify the values found in this
+    ///      field.
+    /// ```
+    pub fn services(&self) -> &[u8] {
+        &self.services
+    }
+
+    /// ```text
+    ///   REGEXP
+    ///      A <character-string> containing a substitution expression that is
+    ///      applied to the original string held by the client in order to
+    ///      construct the next domain name to lookup.  See the DDDS Algorithm
+    ///      specification for the syntax of this field.
+    ///
+    ///      As stated in the DDDS algorithm, The regular expressions MUST NOT
+    ///      be used in a cumulative fashion, that is, they should only be
+    ///      applied to the original string held by the client, never to the
+    ///      domain name p  roduced by a previous NAPTR rewrite.  The latter is
+    ///      tempting in some applications but experience has shown such use to
+    ///      be extremely fault sensitive, very error prone, and extremely
+    ///      difficult to debug.
+    /// ```
+    pub fn regexp(&self) -> &[u8] {
+        &self.regexp
+    }
+
+    /// ```text
+    ///   REPLACEMENT
+    ///      A <domain-name> which is the next domain-name to query for
+    ///      depending on the potential values found in the flags field.  This
+    ///      field is used when the regular expression is a simple replacement
+    ///      operation.  Any value in this field MUST be a fully qualified
+    ///      domain-name.  Name compression is not to be used for this field.
+    ///
+    ///      This field and the REGEXP field together make up the Substitution
+    ///      Expression in the DDDS Algorithm.  It is simply a historical
+    ///      optimization specifically for DNS compression that this field
+    ///      exists.  The fields are also mutually exclusive.  If a record is
+    ///      returned that has values for both fields then it is considered to
+    ///      be in error and SHOULD be either ignored or an error returned.
+    /// ```
+    pub fn replacement(&self) -> &Name {
+        &self.replacement
+    }
+}
+
+/// verifies that the flags are valid
+pub fn verify_flags(flags: &[u8]) -> bool {
+    flags.iter().all(|c| match c {
+        b'0'..=b'9' => true,
+        b'a'..=b'z' => true,
+        b'A'..=b'Z' => true,
+        _ => false,
+    })
+}
+
+/// Read the RData from the given Decoder
+pub fn read(decoder: &mut BinDecoder) -> ProtoResult<NAPTR> {
+    Ok(NAPTR::new(
+        decoder.read_u16()?.unverified(/*any u16 is valid*/),
+        decoder.read_u16()?.unverified(/*any u16 is valid*/),
+        // must be 0-9a-z
+        decoder
+            .read_character_data()?
+            .verify_unwrap(|s| verify_flags(s))
+            .map_err(|_e| ProtoError::from("flags are not within range [a-zA-Z0-9]"))?
+            .to_vec()
+            .into_boxed_slice(),
+        decoder.read_character_data()?.unverified(/*any chardata*/).to_vec().into_boxed_slice(),
+        decoder.read_character_data()?.unverified(/*any chardata*/).to_vec().into_boxed_slice(),
+        Name::read(decoder)?,
+    ))
+}
+
+/// Declares the method for emitting this type
+pub fn emit(encoder: &mut BinEncoder, naptr: &NAPTR) -> ProtoResult<()> {
+    naptr.order.emit(encoder)?;
+    naptr.preference.emit(encoder)?;
+    encoder.emit_character_data(&naptr.flags)?;
+    encoder.emit_character_data(&naptr.services)?;
+    encoder.emit_character_data(&naptr.regexp)?;
+
+    encoder.with_canonical_names(|encoder| naptr.replacement.emit(encoder))?;
+    Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+    #![allow(clippy::dbg_macro, clippy::print_stdout)]
+
+    use super::*;
+    #[test]
+    pub fn test() {
+        use std::str::FromStr;
+
+        let rdata = NAPTR::new(
+            8,
+            16,
+            b"aa11AA".to_vec().into_boxed_slice(),
+            b"services".to_vec().into_boxed_slice(),
+            b"regexpr".to_vec().into_boxed_slice(),
+            Name::from_str("naptr.example.com").unwrap(),
+        );
+
+        let mut bytes = Vec::new();
+        let mut encoder: BinEncoder = BinEncoder::new(&mut bytes);
+        assert!(emit(&mut encoder, &rdata).is_ok());
+        let bytes = encoder.into_bytes();
+
+        println!("bytes: {:?}", bytes);
+
+        let mut decoder: BinDecoder = BinDecoder::new(bytes);
+        let read_rdata = read(&mut decoder).expect("Decoding error");
+        assert_eq!(rdata, read_rdata);
+    }
+
+    #[test]
+    pub fn test_bad_data() {
+        use std::str::FromStr;
+
+        let rdata = NAPTR::new(
+            8,
+            16,
+            b"aa11AA-".to_vec().into_boxed_slice(),
+            b"services".to_vec().into_boxed_slice(),
+            b"regexpr".to_vec().into_boxed_slice(),
+            Name::from_str("naptr.example.com").unwrap(),
+        );
+
+        let mut bytes = Vec::new();
+        let mut encoder: BinEncoder = BinEncoder::new(&mut bytes);
+        assert!(emit(&mut encoder, &rdata).is_ok());
+        let bytes = encoder.into_bytes();
+
+        println!("bytes: {:?}", bytes);
+
+        let mut decoder: BinDecoder = BinDecoder::new(bytes);
+        let read_rdata = read(&mut decoder);
+        assert!(
+            read_rdata.is_err(),
+            "should have failed decoding with bad flag data"
+        );
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/null.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/null.rs
new file mode 100644
index 0000000..34d8dab
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/null.rs
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! null record type, generally not used except as an internal tool for representing null data
+
+use crate::error::*;
+use crate::serialize::binary::*;
+
+/// [RFC 1035, DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION, November 1987](https://tools.ietf.org/html/rfc1035)
+///
+/// ```text
+/// 3.3.10. NULL RDATA format (EXPERIMENTAL)
+///
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///     /                  <anything>                   /
+///     /                                               /
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///
+/// Anything at all may be in the RDATA field so long as it is 65535 octets
+/// or less.
+///
+/// NULL records cause no additional section processing.  NULL RRs are not
+/// allowed in master files.  NULLs are used as placeholders in some
+/// experimental extensions of the DNS.
+/// ```
+#[derive(Default, Debug, PartialEq, Eq, Hash, Clone)]
+pub struct NULL {
+    anything: Option<Vec<u8>>,
+}
+
+impl NULL {
+    /// Construct a new NULL RData
+    pub fn new() -> NULL {
+        Default::default()
+    }
+
+    /// Constructs a new NULL RData with the associated data
+    pub fn with(anything: Vec<u8>) -> NULL {
+        NULL {
+            anything: Some(anything),
+        }
+    }
+
+    /// Returns the buffer stored in the NULL
+    pub fn anything(&self) -> Option<&[u8]> {
+        self.anything.as_ref().map(|bytes| &bytes[..])
+    }
+}
+
+/// Read the RData from the given Decoder
+pub fn read(decoder: &mut BinDecoder, rdata_length: Restrict<u16>) -> ProtoResult<NULL> {
+    let rdata_length = rdata_length.map(|u| u as usize).unverified(/*any u16 is valid*/);
+    if rdata_length > 0 {
+        let anything = decoder.read_vec(rdata_length)?.unverified(/*any byte array is good*/);
+        Ok(NULL::with(anything))
+    } else {
+        Ok(NULL::new())
+    }
+}
+
+/// Write the RData from the given Decoder
+pub fn emit(encoder: &mut BinEncoder, nil: &NULL) -> ProtoResult<()> {
+    if let Some(anything) = nil.anything() {
+        for b in anything.iter() {
+            encoder.emit(*b)?;
+        }
+    }
+
+    Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+    #![allow(clippy::dbg_macro, clippy::print_stdout)]
+
+    use super::*;
+
+    #[test]
+    pub fn test() {
+        let rdata = NULL::with(vec![0, 1, 2, 3, 4, 5, 6, 7]);
+
+        let mut bytes = Vec::new();
+        let mut encoder: BinEncoder = BinEncoder::new(&mut bytes);
+        assert!(emit(&mut encoder, &rdata).is_ok());
+        let bytes = encoder.into_bytes();
+
+        println!("bytes: {:?}", bytes);
+
+        let mut decoder: BinDecoder = BinDecoder::new(bytes);
+        let restrict = Restrict::new(bytes.len() as u16);
+        let read_rdata = read(&mut decoder, restrict).expect("Decoding error");
+        assert_eq!(rdata, read_rdata);
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/openpgpkey.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/openpgpkey.rs
new file mode 100644
index 0000000..c22b635
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/openpgpkey.rs
@@ -0,0 +1,56 @@
+// Copyright 2019 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! OPENPGPKEY records for OpenPGP public keys
+
+use crate::error::*;
+use crate::serialize::binary::*;
+
+/// [RFC 7929](https://tools.ietf.org/html/rfc7929#section-2.1)
+///
+/// ```text
+/// The RDATA portion of an OPENPGPKEY resource record contains a single
+/// value consisting of a Transferable Public Key formatted as specified
+/// in [RFC4880].
+/// ```
+#[derive(Debug, PartialEq, Eq, Hash, Clone)]
+pub struct OPENPGPKEY {
+    public_key: Vec<u8>,
+}
+
+impl OPENPGPKEY {
+    /// Creates a new OPENPGPKEY record data.
+    ///
+    /// # Arguments
+    ///
+    /// * `public_key` - an OpenPGP Transferable Public Key. This will NOT
+    ///    be checked.
+    pub fn new(public_key: Vec<u8>) -> Self {
+        OPENPGPKEY { public_key }
+    }
+
+    /// The public key. This should be an OpenPGP Transferable Public Key,
+    /// but this is not guaranteed.
+    pub fn public_key(&self) -> &[u8] {
+        &self.public_key
+    }
+}
+
+/// Read the RData from the given decoder.
+pub fn read(decoder: &mut BinDecoder, rdata_length: Restrict<u16>) -> ProtoResult<OPENPGPKEY> {
+    let rdata_length = rdata_length.map(usize::from).unverified();
+    let public_key =
+        decoder.read_vec(rdata_length)?.unverified(/*we do not enforce a specific format*/);
+    Ok(OPENPGPKEY::new(public_key))
+}
+
+/// Write the RData using the given encoder
+pub fn emit(encoder: &mut BinEncoder, openpgpkey: &OPENPGPKEY) -> ProtoResult<()> {
+    encoder.emit_vec(openpgpkey.public_key())
+}
+
+// TODO test
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/opt.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/opt.rs
new file mode 100644
index 0000000..93ec54b
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/opt.rs
@@ -0,0 +1,503 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! option record for passing protocol options between the client and server
+
+use std::collections::HashMap;
+
+use log::warn;
+
+use crate::error::*;
+use crate::serialize::binary::*;
+
+#[cfg(feature = "dnssec")]
+use crate::rr::dnssec::SupportedAlgorithms;
+
+/// The OPT record type is used for ExtendedDNS records.
+///
+/// These allow for additional information to be associated with the DNS request that otherwise
+/// would require changes to the DNS protocol.
+///
+/// [RFC 6891, EDNS(0) Extensions, April 2013](https://tools.ietf.org/html/rfc6891#section-6)
+///
+/// ```text
+/// 6.1.  OPT Record Definition
+///
+/// 6.1.1.  Basic Elements
+///
+///    An OPT pseudo-RR (sometimes called a meta-RR) MAY be added to the
+///    additional data section of a request.
+///
+///    The OPT RR has RR type 41.
+///
+///    If an OPT record is present in a received request, compliant
+///    responders MUST include an OPT record in their respective responses.
+///
+///    An OPT record does not carry any DNS data.  It is used only to
+///    contain control information pertaining to the question-and-answer
+///    sequence of a specific transaction.  OPT RRs MUST NOT be cached,
+///    forwarded, or stored in or loaded from master files.
+///
+///    The OPT RR MAY be placed anywhere within the additional data section.
+///    When an OPT RR is included within any DNS message, it MUST be the
+///    only OPT RR in that message.  If a query message with more than one
+///    OPT RR is received, a FORMERR (RCODE=1) MUST be returned.  The
+///    placement flexibility for the OPT RR does not override the need for
+///    the TSIG or SIG(0) RRs to be the last in the additional section
+///    whenever they are present.
+///
+/// 6.1.2.  Wire Format
+///
+///    An OPT RR has a fixed part and a variable set of options expressed as
+///    {attribute, value} pairs.  The fixed part holds some DNS metadata,
+///    and also a small collection of basic extension elements that we
+///    expect to be so popular that it would be a waste of wire space to
+///    encode them as {attribute, value} pairs.
+///
+///    The fixed part of an OPT RR is structured as follows:
+///
+///        +------------+--------------+------------------------------+
+///        | Field Name | Field Type   | Description                  |
+///        +------------+--------------+------------------------------+
+///        | NAME       | domain name  | MUST be 0 (root domain)      |
+///        | TYPE       | u_int16_t    | OPT (41)                     |
+///        | CLASS      | u_int16_t    | requestor's UDP payload size |
+///        | TTL        | u_int32_t    | extended RCODE and flags     |
+///        | RDLEN      | u_int16_t    | length of all RDATA          |
+///        | RDATA      | octet stream | {attribute,value} pairs      |
+///        +------------+--------------+------------------------------+
+///
+///                                OPT RR Format
+///
+///    The variable part of an OPT RR may contain zero or more options in
+///    the RDATA.  Each option MUST be treated as a bit field.  Each option
+///    is encoded as:
+///
+///                   +0 (MSB)                            +1 (LSB)
+///        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+///     0: |                          OPTION-CODE                          |
+///        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+///     2: |                         OPTION-LENGTH                         |
+///        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+///     4: |                                                               |
+///        /                          OPTION-DATA                          /
+///        /                                                               /
+///        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+///
+///    OPTION-CODE
+///       Assigned by the Expert Review process as defined by the DNSEXT
+///       working group and the IESG.
+///
+///    OPTION-LENGTH
+///       Size (in octets) of OPTION-DATA.
+///
+///    OPTION-DATA
+///       Varies per OPTION-CODE.  MUST be treated as a bit field.
+///
+///    The order of appearance of option tuples is not defined.  If one
+///    option modifies the behaviour of another or multiple options are
+///    related to one another in some way, they have the same effect
+///    regardless of ordering in the RDATA wire encoding.
+///
+///    Any OPTION-CODE values not understood by a responder or requestor
+///    MUST be ignored.  Specifications of such options might wish to
+///    include some kind of signaled acknowledgement.  For example, an
+///    option specification might say that if a responder sees and supports
+///    option XYZ, it MUST include option XYZ in its response.
+///
+/// 6.1.3.  OPT Record TTL Field Use
+///
+///    The extended RCODE and flags, which OPT stores in the RR Time to Live
+///    (TTL) field, are structured as follows:
+///
+///                   +0 (MSB)                            +1 (LSB)
+///        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+///     0: |         EXTENDED-RCODE        |            VERSION            |
+///        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+///     2: | DO|                           Z                               |
+///        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+///
+///    EXTENDED-RCODE
+///       Forms the upper 8 bits of extended 12-bit RCODE (together with the
+///       4 bits defined in [RFC1035].  Note that EXTENDED-RCODE value 0
+///       indicates that an unextended RCODE is in use (values 0 through
+///       15).
+///
+///    VERSION
+///       Indicates the implementation level of the setter.  Full
+///       conformance with this specification is indicated by version '0'.
+///       Requestors are encouraged to set this to the lowest implemented
+///       level capable of expressing a transaction, to minimise the
+///       responder and network load of discovering the greatest common
+///       implementation level between requestor and responder.  A
+///       requestor's version numbering strategy MAY ideally be a run-time
+///       configuration option.
+///       If a responder does not implement the VERSION level of the
+///       request, then it MUST respond with RCODE=BADVERS.  All responses
+///       MUST be limited in format to the VERSION level of the request, but
+///       the VERSION of each response SHOULD be the highest implementation
+///       level of the responder.  In this way, a requestor will learn the
+///       implementation level of a responder as a side effect of every
+///       response, including error responses and including RCODE=BADVERS.
+///
+/// 6.1.4.  Flags
+///
+///    DO
+///       DNSSEC OK bit as defined by [RFC3225].
+///
+///    Z
+///       Set to zero by senders and ignored by receivers, unless modified
+///       in a subsequent specification.
+/// ```
+#[derive(Default, Debug, PartialEq, Eq, Clone)]
+pub struct OPT {
+    options: HashMap<EdnsCode, EdnsOption>,
+}
+
+impl OPT {
+    /// Creates a new OPT record data.
+    ///
+    /// # Arguments
+    ///
+    /// * `options` - A map of the codes and record types
+    ///
+    /// # Return value
+    ///
+    /// The newly created OPT data
+    pub fn new(options: HashMap<EdnsCode, EdnsOption>) -> OPT {
+        OPT { options }
+    }
+
+    /// The entire map of options
+    pub fn options(&self) -> &HashMap<EdnsCode, EdnsOption> {
+        &self.options
+    }
+
+    /// Get a single option based on the code
+    pub fn get(&self, code: EdnsCode) -> Option<&EdnsOption> {
+        self.options.get(&code)
+    }
+
+    /// Insert a new option, the key is derived from the `EdnsOption`
+    pub fn insert(&mut self, option: EdnsOption) {
+        self.options.insert((&option).into(), option);
+    }
+}
+
+/// Read the RData from the given Decoder
+pub fn read(decoder: &mut BinDecoder, rdata_length: Restrict<u16>) -> ProtoResult<OPT> {
+    let mut state: OptReadState = OptReadState::ReadCode;
+    let mut options: HashMap<EdnsCode, EdnsOption> = HashMap::new();
+    let start_idx = decoder.index();
+
+    // There is no unsafe direct use of the rdata length after this point
+    let rdata_length =
+        rdata_length.map(|u| u as usize).unverified(/*rdata length usage is bounded*/);
+    while rdata_length > decoder.index() - start_idx {
+        match state {
+            OptReadState::ReadCode => {
+                state = OptReadState::Code {
+                    code: EdnsCode::from(
+                        decoder.read_u16()?.unverified(/*EdnsCode is verified as safe*/),
+                    ),
+                };
+            }
+            OptReadState::Code { code } => {
+                let length = decoder
+                    .read_u16()?
+                    .map(|u| u as usize)
+                    .verify_unwrap(|u| *u <= rdata_length)
+                    .map_err(|_| ProtoError::from("OPT value length exceeds rdata length"))?;
+                state = OptReadState::Data {
+                    code,
+                    length,
+                    // TODO: this can be replaced with decoder.read_vec(), right?
+                    //  the current version allows for malformed opt to be skipped...
+                    collected: Vec::<u8>::with_capacity(length),
+                };
+            }
+            OptReadState::Data {
+                code,
+                length,
+                mut collected,
+            } => {
+                // TODO: can this be replaced by read_slice()?
+                collected.push(decoder.pop()?.unverified(/*byte array is safe*/));
+                if length == collected.len() {
+                    options.insert(code, (code, &collected as &[u8]).into());
+                    state = OptReadState::ReadCode;
+                } else {
+                    state = OptReadState::Data {
+                        code,
+                        length,
+                        collected,
+                    };
+                }
+            }
+        }
+    }
+
+    if state != OptReadState::ReadCode {
+        // there was some problem parsing the data for the options, ignoring them
+        // TODO: should we ignore all of the EDNS data in this case?
+        warn!("incomplete or poorly formatted EDNS options: {:?}", state);
+        options.clear();
+    }
+
+    // the record data is stored as unstructured data, the expectation is that this will be processed after initial parsing.
+    Ok(OPT::new(options))
+}
+
+/// Write the RData from the given Decoder
+pub fn emit(encoder: &mut BinEncoder, opt: &OPT) -> ProtoResult<()> {
+    for (edns_code, edns_option) in opt.options().iter() {
+        encoder.emit_u16(u16::from(*edns_code))?;
+        encoder.emit_u16(edns_option.len())?;
+        edns_option.emit(encoder)?
+    }
+    Ok(())
+}
+
+#[derive(Debug, PartialEq, Eq)]
+enum OptReadState {
+    ReadCode,
+    Code {
+        code: EdnsCode,
+    }, // expect LSB for the opt code, store the high byte
+    Data {
+        code: EdnsCode,
+        length: usize,
+        collected: Vec<u8>,
+    }, // expect the data for the option
+}
+
+/// The code of the EDNS data option
+#[derive(Hash, Debug, Copy, Clone, PartialEq, Eq)]
+pub enum EdnsCode {
+    /// [RFC 6891, Reserved](https://tools.ietf.org/html/rfc6891)
+    Zero,
+
+    /// [LLQ On-hold](http://files.dns-sd.org/draft-sekar-dns-llq.txt)
+    LLQ,
+
+    /// [UL On-hold](http://files.dns-sd.org/draft-sekar-dns-ul.txt)
+    UL,
+
+    /// [RFC 5001, NSID](https://tools.ietf.org/html/rfc5001)
+    NSID,
+    // 4 Reserved [draft-cheshire-edns0-owner-option] -EXPIRED-
+    /// [RFC 6975, DNSSEC Algorithm Understood](https://tools.ietf.org/html/rfc6975)
+    DAU,
+
+    /// [RFC 6975, DS Hash Understood](https://tools.ietf.org/html/rfc6975)
+    DHU,
+
+    /// [RFC 6975, NSEC3 Hash Understood](https://tools.ietf.org/html/rfc6975)
+    N3U,
+
+    /// [edns-client-subnet, Optional](https://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02)
+    Subnet,
+
+    /// [RFC 7314, EDNS EXPIRE, Optional](https://tools.ietf.org/html/rfc7314)
+    Expire,
+
+    /// [draft-ietf-dnsop-cookies](https://tools.ietf.org/html/draft-ietf-dnsop-cookies-07)
+    Cookie,
+
+    /// [draft-ietf-dnsop-edns-tcp-keepalive, Optional](https://tools.ietf.org/html/draft-ietf-dnsop-edns-tcp-keepalive-04)
+    Keepalive,
+
+    /// [draft-mayrhofer-edns0-padding, Optional](https://tools.ietf.org/html/draft-mayrhofer-edns0-padding-01)
+    Padding,
+
+    /// [draft-ietf-dnsop-edns-chain-query](https://tools.ietf.org/html/draft-ietf-dnsop-edns-chain-query-07)
+    Chain,
+
+    /// Unknown, used to deal with unknown or unsupported codes
+    Unknown(u16),
+}
+
+// TODO: implement a macro to perform these inversions
+impl From<u16> for EdnsCode {
+    fn from(value: u16) -> EdnsCode {
+        match value {
+            0 => EdnsCode::Zero,
+            1 => EdnsCode::LLQ,
+            2 => EdnsCode::UL,
+            3 => EdnsCode::NSID,
+            // 4 Reserved [draft-cheshire-edns0-owner-option] -EXPIRED-
+            5 => EdnsCode::DAU,
+            6 => EdnsCode::DHU,
+            7 => EdnsCode::N3U,
+            8 => EdnsCode::Subnet,
+            9 => EdnsCode::Expire,
+            10 => EdnsCode::Cookie,
+            11 => EdnsCode::Keepalive,
+            12 => EdnsCode::Padding,
+            13 => EdnsCode::Chain,
+            _ => EdnsCode::Unknown(value),
+        }
+    }
+}
+
+impl From<EdnsCode> for u16 {
+    fn from(value: EdnsCode) -> u16 {
+        match value {
+            EdnsCode::Zero => 0,
+            EdnsCode::LLQ => 1,
+            EdnsCode::UL => 2,
+            EdnsCode::NSID => 3,
+            // 4 Reserved [draft-cheshire-edns0-owner-option] -EXPIRED-
+            EdnsCode::DAU => 5,
+            EdnsCode::DHU => 6,
+            EdnsCode::N3U => 7,
+            EdnsCode::Subnet => 8,
+            EdnsCode::Expire => 9,
+            EdnsCode::Cookie => 10,
+            EdnsCode::Keepalive => 11,
+            EdnsCode::Padding => 12,
+            EdnsCode::Chain => 13,
+            EdnsCode::Unknown(value) => value,
+        }
+    }
+}
+
+/// options used to pass information about capabilities between client and server
+///
+/// `note: Not all EdnsOptions are supported at this time.`
+///
+/// http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-13
+#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Hash)]
+pub enum EdnsOption {
+    /// [RFC 6975, DNSSEC Algorithm Understood](https://tools.ietf.org/html/rfc6975)
+    #[cfg(feature = "dnssec")]
+    DAU(SupportedAlgorithms),
+
+    /// [RFC 6975, DS Hash Understood](https://tools.ietf.org/html/rfc6975)
+    #[cfg(feature = "dnssec")]
+    DHU(SupportedAlgorithms),
+
+    /// [RFC 6975, NSEC3 Hash Understood](https://tools.ietf.org/html/rfc6975)
+    #[cfg(feature = "dnssec")]
+    N3U(SupportedAlgorithms),
+
+    /// Unknown, used to deal with unknown or unsupported codes
+    Unknown(u16, Vec<u8>),
+}
+
+impl EdnsOption {
+    /// Returns the length in bytes of the EdnsOption
+    pub fn len(&self) -> u16 {
+        match *self {
+            #[cfg(feature = "dnssec")]
+            EdnsOption::DAU(ref algorithms)
+            | EdnsOption::DHU(ref algorithms)
+            | EdnsOption::N3U(ref algorithms) => algorithms.len(),
+            EdnsOption::Unknown(_, ref data) => data.len() as u16, // TODO: should we verify?
+        }
+    }
+
+    /// Returns `true` if the length in bytes of the EdnsOption is 0
+    pub fn is_empty(&self) -> bool {
+        match *self {
+            #[cfg(feature = "dnssec")]
+            EdnsOption::DAU(ref algorithms)
+            | EdnsOption::DHU(ref algorithms)
+            | EdnsOption::N3U(ref algorithms) => algorithms.is_empty(),
+            EdnsOption::Unknown(_, ref data) => data.is_empty(),
+        }
+    }
+}
+
+impl BinEncodable for EdnsOption {
+    fn emit(&self, encoder: &mut BinEncoder) -> ProtoResult<()> {
+        match *self {
+            #[cfg(feature = "dnssec")]
+            EdnsOption::DAU(ref algorithms)
+            | EdnsOption::DHU(ref algorithms)
+            | EdnsOption::N3U(ref algorithms) => algorithms.emit(encoder),
+            EdnsOption::Unknown(_, ref data) => encoder.emit_vec(data), // gah, clone needed or make a crazy api.
+        }
+    }
+}
+
+/// only the supported extensions are listed right now.
+impl<'a> From<(EdnsCode, &'a [u8])> for EdnsOption {
+    fn from(value: (EdnsCode, &'a [u8])) -> EdnsOption {
+        match value.0 {
+            #[cfg(feature = "dnssec")]
+            EdnsCode::DAU => EdnsOption::DAU(value.1.into()),
+            #[cfg(feature = "dnssec")]
+            EdnsCode::DHU => EdnsOption::DHU(value.1.into()),
+            #[cfg(feature = "dnssec")]
+            EdnsCode::N3U => EdnsOption::N3U(value.1.into()),
+            _ => EdnsOption::Unknown(value.0.into(), value.1.to_vec()),
+        }
+    }
+}
+
+impl<'a> From<&'a EdnsOption> for Vec<u8> {
+    fn from(value: &'a EdnsOption) -> Vec<u8> {
+        match *value {
+            #[cfg(feature = "dnssec")]
+            EdnsOption::DAU(ref algorithms)
+            | EdnsOption::DHU(ref algorithms)
+            | EdnsOption::N3U(ref algorithms) => algorithms.into(),
+            EdnsOption::Unknown(_, ref data) => data.clone(), // gah, clone needed or make a crazy api.
+        }
+    }
+}
+
+impl<'a> From<&'a EdnsOption> for EdnsCode {
+    fn from(value: &'a EdnsOption) -> EdnsCode {
+        match *value {
+            #[cfg(feature = "dnssec")]
+            EdnsOption::DAU(..) => EdnsCode::DAU,
+            #[cfg(feature = "dnssec")]
+            EdnsOption::DHU(..) => EdnsCode::DHU,
+            #[cfg(feature = "dnssec")]
+            EdnsOption::N3U(..) => EdnsCode::N3U,
+            EdnsOption::Unknown(code, _) => code.into(),
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    #![allow(clippy::dbg_macro, clippy::print_stdout)]
+
+    #[cfg(feature = "dnssec")]
+    use super::*;
+
+    #[test]
+    #[cfg(feature = "dnssec")]
+    pub fn test() {
+        let mut rdata = OPT::default();
+        rdata.insert(EdnsOption::DAU(SupportedAlgorithms::all()));
+
+        let mut bytes = Vec::new();
+        let mut encoder: BinEncoder = BinEncoder::new(&mut bytes);
+        assert!(emit(&mut encoder, &rdata).is_ok());
+        let bytes = encoder.into_bytes();
+
+        println!("bytes: {:?}", bytes);
+
+        let mut decoder: BinDecoder = BinDecoder::new(bytes);
+        let restrict = Restrict::new(bytes.len() as u16);
+        let read_rdata = read(&mut decoder, restrict).expect("Decoding error");
+        assert_eq!(rdata, read_rdata);
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/soa.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/soa.rs
new file mode 100644
index 0000000..fabb4c6
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/soa.rs
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! start of authority record defining ownership and defaults for the zone
+
+use crate::error::*;
+use crate::rr::domain::Name;
+use crate::serialize::binary::*;
+
+/// [RFC 1035, DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION, November 1987](https://tools.ietf.org/html/rfc1035)
+///
+/// ```text
+/// 3.3.13. SOA RDATA format
+///
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///     /                     MNAME                     /
+///     /                                               /
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///     /                     RNAME                     /
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///     |                    SERIAL                     |
+///     |                                               |
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///     |                    REFRESH                    |
+///     |                                               |
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///     |                     RETRY                     |
+///     |                                               |
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///     |                    EXPIRE                     |
+///     |                                               |
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///     |                    MINIMUM                    |
+///     |                                               |
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///
+/// where:
+///
+/// SOA records cause no additional section processing.
+///
+/// All times are in units of seconds.
+///
+/// Most of these fields are pertinent only for name server maintenance
+/// operations.  However, MINIMUM is used in all query operations that
+/// retrieve RRs from a zone.  Whenever a RR is sent in a response to a
+/// query, the TTL field is set to the maximum of the TTL field from the RR
+/// and the MINIMUM field in the appropriate SOA.  Thus MINIMUM is a lower
+/// bound on the TTL field for all RRs in a zone.  Note that this use of
+/// MINIMUM should occur when the RRs are copied into the response and not
+/// when the zone is loaded from a master file or via a zone transfer.  The
+/// reason for this provison is to allow future dynamic update facilities to
+/// change the SOA RR with known semantics.
+/// ```
+#[derive(Debug, PartialEq, Eq, Hash, Clone)]
+pub struct SOA {
+    mname: Name,
+    rname: Name,
+    serial: u32,
+    refresh: i32,
+    retry: i32,
+    expire: i32,
+    minimum: u32,
+}
+
+impl SOA {
+    /// Creates a new SOA record data.
+    ///
+    /// # Arguments
+    ///
+    /// * `mname` - the name of the master, primary, authority for this zone.
+    /// * `rname` - the name of the responsible party for this zone, e.g. an email address.
+    /// * `serial` - the serial number of the zone, used for caching purposes.
+    /// * `refresh` - the amount of time to wait before a zone is resynched.
+    /// * `retry` - the minimum period to wait if there is a failure during refresh.
+    /// * `expire` - the time until this master is no longer authoritative for the zone.
+    /// * `minimum` - no zone records should have time-to-live values less than this minimum.
+    ///
+    /// # Return value
+    ///
+    /// The newly created SOA record data.
+    pub fn new(
+        mname: Name,
+        rname: Name,
+        serial: u32,
+        refresh: i32,
+        retry: i32,
+        expire: i32,
+        minimum: u32,
+    ) -> Self {
+        SOA {
+            mname,
+            rname,
+            serial,
+            refresh,
+            retry,
+            expire,
+            minimum,
+        }
+    }
+
+    /// Increments the serial number by one
+    pub fn increment_serial(&mut self) {
+        self.serial += 1; // TODO: what to do on overflow?
+    }
+
+    /// ```text
+    /// MNAME           The <domain-name> of the name server that was the
+    ///                 original or primary source of data for this zone.
+    /// ```
+    ///
+    /// # Return value
+    ///
+    /// The `domain-name` of the name server that was the original or primary source of data for
+    /// this zone, i.e. the master name server.
+    pub fn mname(&self) -> &Name {
+        &self.mname
+    }
+
+    /// ```text
+    /// RNAME           A <domain-name> which specifies the mailbox of the
+    ///                 person responsible for this zone.
+    /// ```
+    ///
+    /// # Return value
+    ///
+    /// A `domain-name` which specifies the mailbox of the person responsible for this zone, i.e.
+    /// the responsible name.
+    pub fn rname(&self) -> &Name {
+        &self.rname
+    }
+
+    /// ```text
+    /// SERIAL          The unsigned 32 bit version number of the original copy
+    ///                 of the zone.  Zone transfers preserve this value.  This
+    ///                 value wraps and should be compared using sequence space
+    ///                 arithmetic.
+    /// ```
+    ///
+    /// # Return value
+    ///
+    /// The unsigned 32 bit version number of the original copy of the zone. Zone transfers
+    /// preserve this value. This value wraps and should be compared using sequence space arithmetic.
+    pub fn serial(&self) -> u32 {
+        self.serial
+    }
+
+    /// ```text
+    /// REFRESH         A 32 bit time interval before the zone should be
+    ///                 refreshed.
+    /// ```
+    ///
+    /// # Return value
+    ///
+    /// A 32 bit time interval before the zone should be refreshed, in seconds.
+    pub fn refresh(&self) -> i32 {
+        self.refresh
+    }
+
+    /// ```text
+    /// RETRY           A 32 bit time interval that should elapse before a
+    ///                 failed refresh should be retried.
+    /// ```
+    ///
+    /// # Return value
+    ///
+    /// A 32 bit time interval that should elapse before a failed refresh should be retried,
+    /// in seconds.
+    pub fn retry(&self) -> i32 {
+        self.retry
+    }
+
+    /// ```text
+    /// EXPIRE          A 32 bit time value that specifies the upper limit on
+    ///                 the time interval that can elapse before the zone is no
+    ///                 longer authoritative.
+    /// ```
+    ///
+    /// # Return value
+    ///
+    /// A 32 bit time value that specifies the upper limit on the time interval that can elapse
+    /// before the zone is no longer authoritative, in seconds
+    pub fn expire(&self) -> i32 {
+        self.expire
+    }
+
+    /// ```text
+    /// MINIMUM         The unsigned 32 bit minimum TTL field that should be
+    ///                 exported with any RR from this zone.
+    /// ```
+    ///
+    /// # Return value
+    ///
+    /// The unsigned 32 bit minimum TTL field that should be exported with any RR from this zone.
+    pub fn minimum(&self) -> u32 {
+        self.minimum
+    }
+}
+
+/// Read the RData from the given Decoder
+pub fn read(decoder: &mut BinDecoder) -> ProtoResult<SOA> {
+    Ok(SOA {
+        mname: Name::read(decoder)?,
+        rname: Name::read(decoder)?,
+        serial: decoder.read_u32()?.unverified(/*any u32 is valid*/),
+        refresh: decoder.read_i32()?.unverified(/*any i32 is valid*/),
+        retry: decoder.read_i32()?.unverified(/*any i32 is valid*/),
+        expire: decoder.read_i32()?.unverified(/*any i32 is valid*/),
+        minimum: decoder.read_u32()?.unverified(/*any u32 is valid*/),
+    })
+}
+
+/// [RFC 4034](https://tools.ietf.org/html/rfc4034#section-6), DNSSEC Resource Records, March 2005
+///
+/// This is accurate for all currently known name records.
+///
+/// ```text
+/// 6.2.  Canonical RR Form
+///
+///    For the purposes of DNS security, the canonical form of an RR is the
+///    wire format of the RR where:
+///
+///    ...
+///
+///    3.  if the type of the RR is NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR,
+///        HINFO, MINFO, MX, HINFO, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX,
+///        SRV, DNAME, A6, RRSIG, or (rfc6840 removes NSEC), all uppercase
+///        US-ASCII letters in the DNS names contained within the RDATA are replaced
+///        by the corresponding lowercase US-ASCII letters;
+/// ```
+pub fn emit(encoder: &mut BinEncoder, soa: &SOA) -> ProtoResult<()> {
+    let is_canonical_names = encoder.is_canonical_names();
+
+    soa.mname.emit_with_lowercase(encoder, is_canonical_names)?;
+    soa.rname.emit_with_lowercase(encoder, is_canonical_names)?;
+    encoder.emit_u32(soa.serial)?;
+    encoder.emit_i32(soa.refresh)?;
+    encoder.emit_i32(soa.retry)?;
+    encoder.emit_i32(soa.expire)?;
+    encoder.emit_u32(soa.minimum)?;
+    Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+    #![allow(clippy::dbg_macro, clippy::print_stdout)]
+
+    use super::*;
+
+    #[test]
+    fn test() {
+        use std::str::FromStr;
+
+        let rdata = SOA::new(
+            Name::from_str("m.example.com").unwrap(),
+            Name::from_str("r.example.com").unwrap(),
+            1,
+            2,
+            3,
+            4,
+            5,
+        );
+
+        let mut bytes = Vec::new();
+        let mut encoder: BinEncoder = BinEncoder::new(&mut bytes);
+        assert!(emit(&mut encoder, &rdata).is_ok());
+        let bytes = encoder.into_bytes();
+
+        println!("bytes: {:?}", bytes);
+
+        let mut decoder: BinDecoder = BinDecoder::new(bytes);
+        let read_rdata = read(&mut decoder).expect("Decoding error");
+        assert_eq!(rdata, read_rdata);
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/srv.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/srv.rs
new file mode 100644
index 0000000..cd12c14
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/srv.rs
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! service records for identify port mapping for specific services on a host
+
+use crate::error::*;
+use crate::rr::domain::Name;
+use crate::serialize::binary::*;
+
+/// [RFC 2782, DNS SRV RR, February 2000](https://tools.ietf.org/html/rfc2782)
+///
+/// ```text
+/// Introductory example
+///
+///  If a SRV-cognizant LDAP client wants to discover a LDAP server that
+///  supports TCP protocol and provides LDAP service for the domain
+///  example.com., it does a lookup of
+///
+/// _ldap._tcp.example.com
+///
+///  as described in [ARM].  The example zone file near the end of this
+///  memo contains answering RRs for an SRV query.
+///
+///  Note: LDAP is chosen as an example for illustrative purposes only,
+///  and the LDAP examples used in this document should not be considered
+///  a definitive statement on the recommended way for LDAP to use SRV
+///  records. As described in the earlier applicability section, consult
+///  the appropriate LDAP documents for the recommended procedures.
+///
+/// The format of the SRV RR
+///
+///  Here is the format of the SRV RR, whose DNS type code is 33:
+///
+/// _Service._Proto.Name TTL Class SRV Priority Weight Port Target
+///
+/// (There is an example near the end of this document.)
+///
+///  Service
+/// The symbolic name of the desired service, as defined in Assigned
+/// Numbers [STD 2] or locally.  An underscore (_) is prepended to
+/// the service identifier to avoid collisions with DNS labels that
+/// occur in nature.
+///
+/// Some widely used services, notably POP, don't have a single
+/// universal name.  If Assigned Numbers names the service
+/// indicated, that name is the only name which is legal for SRV
+/// lookups.  The Service is case insensitive.
+///
+///  Proto
+/// The symbolic name of the desired protocol, with an underscore
+/// (_) prepended to prevent collisions with DNS labels that occur
+/// in nature.  _TCP and _UDP are at present the most useful values
+/// for this field, though any name defined by Assigned Numbers or
+/// locally may be used (as for Service).  The Proto is case
+/// insensitive.
+///
+///  Name
+/// The domain this RR refers to.  The SRV RR is unique in that the
+/// name one searches for is not this name; the example near the end
+/// shows this clearly.
+///
+///  TTL
+/// Standard DNS meaning [RFC 1035].
+///
+///  Class
+/// Standard DNS meaning [RFC 1035].   SRV records occur in the IN
+/// Class.
+///
+/// ```
+#[derive(Debug, PartialEq, Eq, Hash, Clone)]
+pub struct SRV {
+    priority: u16,
+    weight: u16,
+    port: u16,
+    target: Name,
+}
+
+impl SRV {
+    /// Creates a new SRV record data.
+    ///
+    /// # Arguments
+    ///
+    /// * `priority` - lower values have a higher priority and clients will attempt to use these
+    ///                first.
+    /// * `weight` - for servers with the same priority, higher weights will be chosen more often.
+    /// * `port` - the socket port number on which the service is listening.
+    /// * `target` - like CNAME, this is the target domain name to which the service is associated.
+    ///
+    /// # Return value
+    ///
+    /// The newly constructed SRV record data.
+    pub fn new(priority: u16, weight: u16, port: u16, target: Name) -> SRV {
+        SRV {
+            priority,
+            weight,
+            port,
+            target,
+        }
+    }
+
+    /// ```text
+    ///  Priority
+    /// The priority of this target host.  A client MUST attempt to
+    /// contact the target host with the lowest-numbered priority it can
+    /// reach; target hosts with the same priority SHOULD be tried in an
+    /// order defined by the weight field.  The range is 0-65535.  This
+    /// is a 16 bit unsigned integer in network byte order.
+    /// ```
+    pub fn priority(&self) -> u16 {
+        self.priority
+    }
+
+    /// ```text
+    ///  Weight
+    /// A server selection mechanism.  The weight field specifies a
+    /// relative weight for entries with the same priority. Larger
+    /// weights SHOULD be given a proportionately higher probability of
+    /// being selected. The range of this number is 0-65535.  This is a
+    /// 16 bit unsigned integer in network byte order.  Domain
+    /// administrators SHOULD use Weight 0 when there isn't any server
+    /// selection to do, to make the RR easier to read for humans (less
+    /// noisy).  In the presence of records containing weights greater
+    /// than 0, records with weight 0 should have a very small chance of
+    /// being selected.
+    ///
+    /// In the absence of a protocol whose specification calls for the
+    /// use of other weighting information, a client arranges the SRV
+    /// RRs of the same Priority in the order in which target hosts,
+    /// specified by the SRV RRs, will be contacted. The following
+    /// algorithm SHOULD be used to order the SRV RRs of the same
+    /// priority:
+    ///
+    /// To select a target to be contacted next, arrange all SRV RRs
+    /// (that have not been ordered yet) in any order, except that all
+    /// those with weight 0 are placed at the beginning of the list.
+    ///
+    /// Compute the sum of the weights of those RRs, and with each RR
+    /// associate the running sum in the selected order. Then choose a
+    /// uniform random number between 0 and the sum computed
+    /// (inclusive), and select the RR whose running sum value is the
+    /// first in the selected order which is greater than or equal to
+    /// the random number selected. The target host specified in the
+    /// selected SRV RR is the next one to be contacted by the client.
+    /// Remove this SRV RR from the set of the unordered SRV RRs and
+    /// apply the described algorithm to the unordered SRV RRs to select
+    /// the next target host.  Continue the ordering process until there
+    /// are no unordered SRV RRs.  This process is repeated for each
+    /// Priority.
+    /// ```
+    pub fn weight(&self) -> u16 {
+        self.weight
+    }
+
+    /// ```text
+    ///  Port
+    /// The port on this target host of this service.  The range is 0-
+    /// 65535.  This is a 16 bit unsigned integer in network byte order.
+    /// This is often as specified in Assigned Numbers but need not be.
+    ///
+    /// ```
+    pub fn port(&self) -> u16 {
+        self.port
+    }
+
+    /// ```text
+    ///  Target
+    /// The domain name of the target host.  There MUST be one or more
+    /// address records for this name, the name MUST NOT be an alias (in
+    /// the sense of RFC 1034 or RFC 2181).  Implementors are urged, but
+    /// not required, to return the address record(s) in the Additional
+    /// Data section.  Unless and until permitted by future standards
+    /// action, name compression is not to be used for this field.
+    ///
+    /// A Target of "." means that the service is decidedly not
+    /// available at this domain.
+    /// ```
+    pub fn target(&self) -> &Name {
+        &self.target
+    }
+}
+
+/// Read the RData from the given Decoder
+pub fn read(decoder: &mut BinDecoder) -> ProtoResult<SRV> {
+    // SRV { priority: u16, weight: u16, port: u16, target: Name, },
+    Ok(SRV::new(
+        decoder.read_u16()?.unverified(/*any u16 is valid*/),
+        decoder.read_u16()?.unverified(/*any u16 is valid*/),
+        decoder.read_u16()?.unverified(/*any u16 is valid*/),
+        Name::read(decoder)?,
+    ))
+}
+
+/// [RFC 4034](https://tools.ietf.org/html/rfc4034#section-6), DNSSEC Resource Records, March 2005
+///
+/// This is accurate for all currently known name records.
+///
+/// ```text
+/// 6.2.  Canonical RR Form
+///
+///    For the purposes of DNS security, the canonical form of an RR is the
+///    wire format of the RR where:
+///
+///    ...
+///
+///    3.  if the type of the RR is NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR,
+///        HINFO, MINFO, MX, HINFO, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX,
+///        SRV, DNAME, A6, RRSIG, or (rfc6840 removes NSEC), all uppercase
+///        US-ASCII letters in the DNS names contained within the RDATA are replaced
+///        by the corresponding lowercase US-ASCII letters;
+/// ```
+pub fn emit(encoder: &mut BinEncoder, srv: &SRV) -> ProtoResult<()> {
+    let is_canonical_names = encoder.is_canonical_names();
+
+    encoder.emit_u16(srv.priority())?;
+    encoder.emit_u16(srv.weight())?;
+    encoder.emit_u16(srv.port())?;
+    srv.target()
+        .emit_with_lowercase(encoder, is_canonical_names)?;
+    Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+    #![allow(clippy::dbg_macro, clippy::print_stdout)]
+
+    use super::*;
+
+    #[test]
+    fn test() {
+        use std::str::FromStr;
+
+        let rdata = SRV::new(1, 2, 3, Name::from_str("_dns._tcp.example.com").unwrap());
+
+        let mut bytes = Vec::new();
+        let mut encoder: BinEncoder = BinEncoder::new(&mut bytes);
+        assert!(emit(&mut encoder, &rdata).is_ok());
+        let bytes = encoder.into_bytes();
+
+        println!("bytes: {:?}", bytes);
+
+        let mut decoder: BinDecoder = BinDecoder::new(bytes);
+
+        let read_rdata = read(&mut decoder).expect("Decoding error");
+        assert_eq!(rdata, read_rdata);
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/sshfp.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/sshfp.rs
new file mode 100644
index 0000000..944b5a9
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/sshfp.rs
@@ -0,0 +1,309 @@
+// Copyright 2019 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! SSHFP records for SSH public key fingerprints
+
+use crate::error::*;
+use crate::serialize::binary::*;
+
+/// [RFC 4255](https://tools.ietf.org/html/rfc4255#section-3.1)
+///
+/// ```text
+/// 3.1.  The SSHFP RDATA Format
+///
+///    The RDATA for a SSHFP RR consists of an algorithm number, fingerprint
+///    type and the fingerprint of the public host key.
+///
+///        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+///        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+///        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+///        |   algorithm   |    fp type    |                               /
+///        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               /
+///        /                                                               /
+///        /                          fingerprint                          /
+///        /                                                               /
+///        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+///
+/// 3.1.3.  Fingerprint
+///
+///    The fingerprint is calculated over the public key blob as described
+///    in [7].
+///
+///    The message-digest algorithm is presumed to produce an opaque octet
+///    string output, which is placed as-is in the RDATA fingerprint field.
+/// ```
+#[derive(Debug, PartialEq, Eq, Hash, Clone)]
+pub struct SSHFP {
+    algorithm: Algorithm,
+    fingerprint_type: FingerprintType,
+    fingerprint: Vec<u8>,
+}
+
+impl SSHFP {
+    /// Creates a new SSHFP record data.
+    ///
+    /// # Arguments
+    ///
+    /// * `algorithm` - the SSH public key algorithm.
+    /// * `fingerprint_type` - the fingerprint type to use.
+    /// * `fingerprint` - the fingerprint of the public key.
+    pub fn new(
+        algorithm: Algorithm,
+        fingerprint_type: FingerprintType,
+        fingerprint: Vec<u8>,
+    ) -> Self {
+        SSHFP {
+            algorithm,
+            fingerprint_type,
+            fingerprint,
+        }
+    }
+
+    /// The SSH public key algorithm.
+    pub fn algorithm(&self) -> Algorithm {
+        self.algorithm
+    }
+
+    /// The fingerprint type to use.
+    pub fn fingerprint_type(&self) -> FingerprintType {
+        self.fingerprint_type
+    }
+
+    /// The fingerprint of the public key.
+    pub fn fingerprint(&self) -> &[u8] {
+        &self.fingerprint
+    }
+}
+
+/// ```text
+/// 3.1.1.  Algorithm Number Specification
+///
+///    This algorithm number octet describes the algorithm of the public
+///    key.  The following values are assigned:
+///
+///           Value    Algorithm name
+///           -----    --------------
+///           0        reserved
+///           1        RSA
+///           2        DSS
+///
+///    Reserving other types requires IETF consensus [4].
+/// ```text
+///
+/// The algorithm values have been updated in
+/// [RFC 6594](https://tools.ietf.org/html/rfc6594) and
+/// [RFC 7479](https://tools.ietf.org/html/rfc7479).
+#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
+pub enum Algorithm {
+    /// Reserved value
+    Reserved,
+
+    /// RSA
+    RSA,
+
+    /// DSS/DSA
+    DSA,
+
+    /// ECDSA
+    ECDSA,
+
+    /// Ed25519
+    Ed25519,
+
+    /// Unassigned value
+    Unassigned(u8),
+}
+
+impl From<u8> for Algorithm {
+    fn from(alg: u8) -> Self {
+        match alg {
+            0 => Algorithm::Reserved,
+            1 => Algorithm::RSA,
+            2 => Algorithm::DSA,
+            3 => Algorithm::ECDSA,
+            4 => Algorithm::Ed25519, // TODO more (XMSS)
+            _ => Algorithm::Unassigned(alg),
+        }
+    }
+}
+
+impl From<Algorithm> for u8 {
+    fn from(algorithm: Algorithm) -> u8 {
+        match algorithm {
+            Algorithm::Reserved => 0,
+            Algorithm::RSA => 1,
+            Algorithm::DSA => 2,
+            Algorithm::ECDSA => 3,
+            Algorithm::Ed25519 => 4,
+            Algorithm::Unassigned(alg) => alg,
+        }
+    }
+}
+
+/// ```text
+/// 3.1.2.  Fingerprint Type Specification
+///
+///    The fingerprint type octet describes the message-digest algorithm
+///    used to calculate the fingerprint of the public key.  The following
+///    values are assigned:
+///
+///           Value    Fingerprint type
+///           -----    ----------------
+///           0        reserved
+///           1        SHA-1
+///
+///    Reserving other types requires IETF consensus [4].
+///
+///    For interoperability reasons, as few fingerprint types as possible
+///    should be reserved.  The only reason to reserve additional types is
+///    to increase security.
+/// ```
+///
+/// The fingerprint type values have been updated in
+/// [RFC 6594](https://tools.ietf.org/html/rfc6594).
+#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
+pub enum FingerprintType {
+    /// Reserved value
+    Reserved,
+
+    /// SHA-1
+    SHA1,
+
+    /// SHA-256
+    SHA256,
+
+    /// Unassigned value
+    Unassigned(u8),
+}
+
+impl From<u8> for FingerprintType {
+    fn from(ft: u8) -> Self {
+        match ft {
+            0 => FingerprintType::Reserved,
+            1 => FingerprintType::SHA1,
+            2 => FingerprintType::SHA256,
+            _ => FingerprintType::Unassigned(ft),
+        }
+    }
+}
+
+impl From<FingerprintType> for u8 {
+    fn from(fingerprint_type: FingerprintType) -> u8 {
+        match fingerprint_type {
+            FingerprintType::Reserved => 0,
+            FingerprintType::SHA1 => 1,
+            FingerprintType::SHA256 => 2,
+            FingerprintType::Unassigned(ft) => ft,
+        }
+    }
+}
+
+/// Read the RData from the given decoder.
+pub fn read(decoder: &mut BinDecoder, rdata_length: Restrict<u16>) -> ProtoResult<SSHFP> {
+    let algorithm = decoder.read_u8()?.unverified().into();
+    let fingerprint_type = decoder.read_u8()?.unverified().into();
+    let fingerprint_len = rdata_length
+        .map(|l| l as usize)
+        .checked_sub(2)
+        .map_err(|_| ProtoError::from("invalid rdata length in SSHFP"))?
+        .unverified();
+    let fingerprint = decoder.read_vec(fingerprint_len)?.unverified();
+    Ok(SSHFP::new(algorithm, fingerprint_type, fingerprint))
+}
+
+/// Write the RData using the given encoder.
+pub fn emit(encoder: &mut BinEncoder, sshfp: &SSHFP) -> ProtoResult<()> {
+    encoder.emit_u8(sshfp.algorithm().into())?;
+    encoder.emit_u8(sshfp.fingerprint_type().into())?;
+    encoder.emit_vec(sshfp.fingerprint())
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn read_algorithm() {
+        assert_eq!(Algorithm::Reserved, 0.into());
+        assert_eq!(Algorithm::RSA, 1.into());
+        assert_eq!(Algorithm::DSA, 2.into());
+        assert_eq!(Algorithm::ECDSA, 3.into());
+        assert_eq!(Algorithm::Ed25519, 4.into());
+        assert_eq!(Algorithm::Unassigned(17), 17.into());
+        assert_eq!(Algorithm::Unassigned(42), 42.into());
+
+        assert_eq!(0u8, Algorithm::Reserved.into());
+        assert_eq!(1u8, Algorithm::RSA.into());
+        assert_eq!(2u8, Algorithm::DSA.into());
+        assert_eq!(3u8, Algorithm::ECDSA.into());
+        assert_eq!(4u8, Algorithm::Ed25519.into());
+        assert_eq!(17u8, Algorithm::Unassigned(17).into());
+        assert_eq!(42u8, Algorithm::Unassigned(42).into());
+    }
+
+    #[test]
+    fn read_fingerprint_type() {
+        assert_eq!(FingerprintType::Reserved, 0.into());
+        assert_eq!(FingerprintType::SHA1, 1.into());
+        assert_eq!(FingerprintType::SHA256, 2.into());
+        assert_eq!(FingerprintType::Unassigned(12), 12.into());
+        assert_eq!(FingerprintType::Unassigned(89), 89.into());
+
+        assert_eq!(0u8, FingerprintType::Reserved.into());
+        assert_eq!(1u8, FingerprintType::SHA1.into());
+        assert_eq!(2u8, FingerprintType::SHA256.into());
+        assert_eq!(12u8, FingerprintType::Unassigned(12).into());
+        assert_eq!(89u8, FingerprintType::Unassigned(89).into());
+    }
+
+    fn test_encode_decode(rdata: SSHFP, result: &[u8]) {
+        let mut bytes = Vec::new();
+        let mut encoder = BinEncoder::new(&mut bytes);
+        emit(&mut encoder, &rdata).expect("failed to emit SSHFP");
+        let bytes = encoder.into_bytes();
+        assert_eq!(bytes, &result);
+
+        let mut decoder = BinDecoder::new(result);
+        let read_rdata =
+            read(&mut decoder, Restrict::new(result.len() as u16)).expect("failed to read SSHFP");
+        assert_eq!(read_rdata, rdata)
+    }
+
+    #[test]
+    fn test_encode_decode_sshfp() {
+        test_encode_decode(
+            SSHFP::new(Algorithm::RSA, FingerprintType::SHA256, vec![]),
+            &[1, 2],
+        );
+        test_encode_decode(
+            SSHFP::new(
+                Algorithm::ECDSA,
+                FingerprintType::SHA1,
+                vec![115, 115, 104, 102, 112],
+            ),
+            &[3, 1, 115, 115, 104, 102, 112],
+        );
+        test_encode_decode(
+            SSHFP::new(
+                Algorithm::Reserved,
+                FingerprintType::Reserved,
+                b"ssh fingerprint".to_vec(),
+            ),
+            &[
+                0, 0, 115, 115, 104, 32, 102, 105, 110, 103, 101, 114, 112, 114, 105, 110, 116,
+            ],
+        );
+        test_encode_decode(
+            SSHFP::new(
+                Algorithm::Unassigned(255),
+                FingerprintType::Unassigned(13),
+                vec![100, 110, 115, 115, 101, 99, 32, 100, 97, 110, 101],
+            ),
+            &[255, 13, 100, 110, 115, 115, 101, 99, 32, 100, 97, 110, 101],
+        );
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/tlsa.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/tlsa.rs
new file mode 100644
index 0000000..1730290
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/tlsa.rs
@@ -0,0 +1,471 @@
+// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! TLSA records for storing TLS certificate validation information
+
+use crate::error::*;
+use crate::serialize::binary::*;
+
+/// [RFC 6698, DNS-Based Authentication for TLS](https://tools.ietf.org/html/rfc6698#section-2.1)
+///
+/// ```text
+/// 2.1.  TLSA RDATA Wire Format
+///
+///    The RDATA for a TLSA RR consists of a one-octet certificate usage
+///    field, a one-octet selector field, a one-octet matching type field,
+///    and the certificate association data field.
+///
+///                         1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+///     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+///    |  Cert. Usage  |   Selector    | Matching Type |               /
+///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+               /
+///    /                                                               /
+///    /                 Certificate Association Data                  /
+///    /                                                               /
+///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+/// ```
+#[derive(Debug, PartialEq, Eq, Hash, Clone)]
+pub struct TLSA {
+    cert_usage: CertUsage,
+    selector: Selector,
+    matching: Matching,
+    cert_data: Vec<u8>,
+}
+
+/// [RFC 6698, DNS-Based Authentication for TLS](https://tools.ietf.org/html/rfc6698#section-2.1.1)
+///
+/// ```text
+/// 2.1.1.  The Certificate Usage Field
+///
+///    A one-octet value, called "certificate usage", specifies the provided
+///    association that will be used to match the certificate presented in
+///    the TLS handshake.  This value is defined in a new IANA registry (see
+///    Section 7.2) in order to make it easier to add additional certificate
+///    usages in the future.  The certificate usages defined in this
+///    document are:
+///
+///       0 -- CA
+///
+///       1 -- Service
+///
+///       2 -- TrustAnchor
+///
+///       3 -- DomainIssued
+///
+///    The certificate usages defined in this document explicitly only apply
+///    to PKIX-formatted certificates in DER encoding [X.690].  If TLS
+///    allows other formats later, or if extensions to this RRtype are made
+///    that accept other formats for certificates, those certificates will
+///    need their own certificate usage values.
+/// ```
+#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
+pub enum CertUsage {
+    /// ```text
+    ///       0 -- Certificate usage 0 is used to specify a CA certificate, or
+    ///       the public key of such a certificate, that MUST be found in any of
+    ///       the PKIX certification paths for the end entity certificate given
+    ///       by the server in TLS.  This certificate usage is sometimes
+    ///       referred to as "CA constraint" because it limits which CA can be
+    ///       used to issue certificates for a given service on a host.  The
+    ///       presented certificate MUST pass PKIX certification path
+    ///       validation, and a CA certificate that matches the TLSA record MUST
+    ///       be included as part of a valid certification path.  Because this
+    ///       certificate usage allows both trust anchors and CA certificates,
+    ///       the certificate might or might not have the basicConstraints
+    ///       extension present.
+    /// ```
+    CA,
+
+    /// ```text
+    ///       1 -- Certificate usage 1 is used to specify an end entity
+    ///       certificate, or the public key of such a certificate, that MUST be
+    ///       matched with the end entity certificate given by the server in
+    ///       TLS.  This certificate usage is sometimes referred to as "service
+    ///       certificate constraint" because it limits which end entity
+    ///       certificate can be used by a given service on a host.  The target
+    ///       certificate MUST pass PKIX certification path validation and MUST
+    ///       match the TLSA record.
+    /// ```
+    Service,
+
+    /// ```text
+    ///       2 -- Certificate usage 2 is used to specify a certificate, or the
+    ///       public key of such a certificate, that MUST be used as the trust
+    ///       anchor when validating the end entity certificate given by the
+    ///       server in TLS.  This certificate usage is sometimes referred to as
+    ///       "trust anchor assertion" and allows a domain name administrator to
+    ///       specify a new trust anchor -- for example, if the domain issues
+    ///       its own certificates under its own CA that is not expected to be
+    ///       in the end users' collection of trust anchors.  The target
+    ///       certificate MUST pass PKIX certification path validation, with any
+    ///       certificate matching the TLSA record considered to be a trust
+    ///       anchor for this certification path validation.
+    /// ```
+    TrustAnchor,
+
+    /// ```text
+    ///       3 -- Certificate usage 3 is used to specify a certificate, or the
+    ///       public key of such a certificate, that MUST match the end entity
+    ///       certificate given by the server in TLS.  This certificate usage is
+    ///       sometimes referred to as "domain-issued certificate" because it
+    ///       allows for a domain name administrator to issue certificates for a
+    ///       domain without involving a third-party CA.  The target certificate
+    ///       MUST match the TLSA record.  The difference between certificate
+    ///       usage 1 and certificate usage 3 is that certificate usage 1
+    ///       requires that the certificate pass PKIX validation, but PKIX
+    ///       validation is not tested for certificate usage 3.
+    /// ```
+    DomainIssued,
+
+    /// Unassigned at the time of this implementation
+    Unassigned(u8),
+
+    /// Private usage
+    Private,
+}
+
+impl From<u8> for CertUsage {
+    fn from(usage: u8) -> Self {
+        match usage {
+            0 => CertUsage::CA,
+            1 => CertUsage::Service,
+            2 => CertUsage::TrustAnchor,
+            3 => CertUsage::DomainIssued,
+            4..=254 => CertUsage::Unassigned(usage),
+            255 => CertUsage::Private,
+        }
+    }
+}
+
+impl From<CertUsage> for u8 {
+    fn from(usage: CertUsage) -> u8 {
+        match usage {
+            CertUsage::CA => 0,
+            CertUsage::Service => 1,
+            CertUsage::TrustAnchor => 2,
+            CertUsage::DomainIssued => 3,
+            CertUsage::Unassigned(usage) => usage,
+            CertUsage::Private => 255,
+        }
+    }
+}
+
+/// [RFC 6698, DNS-Based Authentication for TLS](https://tools.ietf.org/html/rfc6698#section-2.1.1)
+///
+/// ```text
+/// 2.1.2.  The Selector Field
+///
+///    A one-octet value, called "selector", specifies which part of the TLS
+///    certificate presented by the server will be matched against the
+///    association data.  This value is defined in a new IANA registry (see
+///    Section 7.3).  The selectors defined in this document are:
+///
+///       0 -- Full
+///
+///       1 -- Spki
+///
+///    (Note that the use of "selector" in this document is completely
+///    unrelated to the use of "selector" in DomainKeys Identified Mail
+///    (DKIM) [RFC6376].)
+/// ```
+#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
+pub enum Selector {
+    /// Full certificate: the Certificate binary structure as defined in [RFC5280]
+    Full,
+
+    /// SubjectPublicKeyInfo: DER-encoded binary structure as defined in [RFC5280]
+    Spki,
+
+    /// Unassigned at the time of this writing
+    Unassigned(u8),
+
+    /// Private usage
+    Private,
+}
+
+impl From<u8> for Selector {
+    fn from(selector: u8) -> Self {
+        match selector {
+            0 => Selector::Full,
+            1 => Selector::Spki,
+            2..=254 => Selector::Unassigned(selector),
+            255 => Selector::Private,
+        }
+    }
+}
+
+impl From<Selector> for u8 {
+    fn from(selector: Selector) -> u8 {
+        match selector {
+            Selector::Full => 0,
+            Selector::Spki => 1,
+            Selector::Unassigned(selector) => selector,
+            Selector::Private => 255,
+        }
+    }
+}
+
+/// [RFC 6698, DNS-Based Authentication for TLS](https://tools.ietf.org/html/rfc6698#section-2.1.3)
+///
+/// ```text
+/// 2.1.3.  The Matching Type Field
+///
+///    A one-octet value, called "matching type", specifies how the
+///    certificate association is presented.  This value is defined in a new
+///    IANA registry (see Section 7.4).  The types defined in this document
+///    are:
+///
+///       0 -- Raw
+///
+///       1 -- Sha256
+///
+///       2 -- Sha512
+///
+///    If the TLSA record's matching type is a hash, having the record use
+///    the same hash algorithm that was used in the signature in the
+///    certificate (if possible) will assist clients that support a small
+///    number of hash algorithms.
+/// ```
+#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
+pub enum Matching {
+    /// Exact match on selected content
+    Raw,
+
+    /// SHA-256 hash of selected content [RFC6234]
+    Sha256,
+
+    /// SHA-512 hash of selected content [RFC6234]
+    Sha512,
+
+    /// Unassigned at the time of this writing
+    Unassigned(u8),
+
+    /// Private usage
+    Private,
+}
+
+impl From<u8> for Matching {
+    fn from(matching: u8) -> Self {
+        match matching {
+            0 => Matching::Raw,
+            1 => Matching::Sha256,
+            2 => Matching::Sha512,
+            3..=254 => Matching::Unassigned(matching),
+            255 => Matching::Private,
+        }
+    }
+}
+
+impl From<Matching> for u8 {
+    fn from(matching: Matching) -> u8 {
+        match matching {
+            Matching::Raw => 0,
+            Matching::Sha256 => 1,
+            Matching::Sha512 => 2,
+            Matching::Unassigned(matching) => matching,
+            Matching::Private => 255,
+        }
+    }
+}
+
+impl TLSA {
+    /// Constructs a new TLSA
+    ///
+    /// [RFC 6698, DNS-Based Authentication for TLS](https://tools.ietf.org/html/rfc6698#section-2)
+    ///
+    /// ```text
+    /// 2.  The TLSA Resource Record
+    ///
+    ///    The TLSA DNS resource record (RR) is used to associate a TLS server
+    ///    certificate or public key with the domain name where the record is
+    ///    found, thus forming a "TLSA certificate association".  The semantics
+    ///    of how the TLSA RR is interpreted are given later in this document.
+    ///
+    ///    The type value for the TLSA RR type is defined in Section 7.1.
+    ///
+    ///    The TLSA RR is class independent.
+    ///
+    ///    The TLSA RR has no special Time to Live (TTL) requirements.
+    /// ```
+    pub fn new(
+        cert_usage: CertUsage,
+        selector: Selector,
+        matching: Matching,
+        cert_data: Vec<u8>,
+    ) -> Self {
+        TLSA {
+            cert_usage,
+            selector,
+            matching,
+            cert_data,
+        }
+    }
+
+    /// Specifies the provided association that will be used to match the certificate presented in the TLS handshake
+    pub fn cert_usage(&self) -> CertUsage {
+        self.cert_usage
+    }
+
+    /// Specifies which part of the TLS certificate presented by the server will be matched against the association data
+    pub fn selector(&self) -> Selector {
+        self.selector
+    }
+
+    /// Specifies how the certificate association is presented
+    pub fn matching(&self) -> Matching {
+        self.matching
+    }
+
+    /// Binary data for validating the cert, see other members to understand format
+    pub fn cert_data(&self) -> &[u8] {
+        &self.cert_data
+    }
+}
+
+/// Read the RData from the given Decoder
+///
+/// ```text
+///                         1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+///     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+///    |  Cert. Usage  |   Selector    | Matching Type |               /
+///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+               /
+///    /                                                               /
+///    /                 Certificate Association Data                  /
+///    /                                                               /
+///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+/// ```
+pub fn read(decoder: &mut BinDecoder, rdata_length: Restrict<u16>) -> ProtoResult<TLSA> {
+    let cert_usage = decoder.read_u8()?.unverified(/*CertUsage is verified*/).into();
+    let selector = decoder.read_u8()?.unverified(/*Selector is verified*/).into();
+    let matching = decoder.read_u8()?.unverified(/*Matching is verified*/).into();
+
+    // the remaining data is for the cert
+    let cert_len = rdata_length
+        .map(|u| u as usize)
+        .checked_sub(3)
+        .map_err(|_| ProtoError::from("invalid rdata length in TLSA"))?
+        .unverified(/*used purely as length safely*/);
+    let cert_data = decoder.read_vec(cert_len)?.unverified(/*will fail in usage if invalid*/);
+
+    Ok(TLSA {
+        cert_usage,
+        selector,
+        matching,
+        cert_data,
+    })
+}
+
+/// Write the RData from the given Decoder
+pub fn emit(encoder: &mut BinEncoder, tlsa: &TLSA) -> ProtoResult<()> {
+    encoder.emit_u8(tlsa.cert_usage.into())?;
+    encoder.emit_u8(tlsa.selector.into())?;
+    encoder.emit_u8(tlsa.matching.into())?;
+    encoder.emit_vec(&tlsa.cert_data)?;
+    Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+    #![allow(clippy::dbg_macro, clippy::print_stdout)]
+
+    use super::*;
+
+    #[test]
+    fn read_cert_usage() {
+        assert_eq!(CertUsage::CA, CertUsage::from(0));
+        assert_eq!(CertUsage::Service, CertUsage::from(1));
+        assert_eq!(CertUsage::TrustAnchor, CertUsage::from(2));
+        assert_eq!(CertUsage::DomainIssued, CertUsage::from(3));
+        assert_eq!(CertUsage::Unassigned(4), CertUsage::from(4));
+        assert_eq!(CertUsage::Unassigned(254), CertUsage::from(254));
+        assert_eq!(CertUsage::Private, CertUsage::from(255));
+
+        assert_eq!(u8::from(CertUsage::CA), 0);
+        assert_eq!(u8::from(CertUsage::Service), 1);
+        assert_eq!(u8::from(CertUsage::TrustAnchor), 2);
+        assert_eq!(u8::from(CertUsage::DomainIssued), 3);
+        assert_eq!(u8::from(CertUsage::Unassigned(4)), 4);
+        assert_eq!(u8::from(CertUsage::Unassigned(254)), 254);
+        assert_eq!(u8::from(CertUsage::Private), 255);
+    }
+
+    #[test]
+    fn read_selector() {
+        assert_eq!(Selector::Full, Selector::from(0));
+        assert_eq!(Selector::Spki, Selector::from(1));
+        assert_eq!(Selector::Unassigned(2), Selector::from(2));
+        assert_eq!(Selector::Unassigned(254), Selector::from(254));
+        assert_eq!(Selector::Private, Selector::from(255));
+
+        assert_eq!(u8::from(Selector::Full), 0);
+        assert_eq!(u8::from(Selector::Spki), 1);
+        assert_eq!(u8::from(Selector::Unassigned(2)), 2);
+        assert_eq!(u8::from(Selector::Unassigned(254)), 254);
+        assert_eq!(u8::from(Selector::Private), 255);
+    }
+
+    #[test]
+    fn read_matching() {
+        assert_eq!(Matching::Raw, Matching::from(0));
+        assert_eq!(Matching::Sha256, Matching::from(1));
+        assert_eq!(Matching::Sha512, Matching::from(2));
+        assert_eq!(Matching::Unassigned(3), Matching::from(3));
+        assert_eq!(Matching::Unassigned(254), Matching::from(254));
+        assert_eq!(Matching::Private, Matching::from(255));
+
+        assert_eq!(u8::from(Matching::Raw), 0);
+        assert_eq!(u8::from(Matching::Sha256), 1);
+        assert_eq!(u8::from(Matching::Sha512), 2);
+        assert_eq!(u8::from(Matching::Unassigned(3)), 3);
+        assert_eq!(u8::from(Matching::Unassigned(254)), 254);
+        assert_eq!(u8::from(Matching::Private), 255);
+    }
+
+    fn test_encode_decode(rdata: TLSA) {
+        let mut bytes = Vec::new();
+        let mut encoder: BinEncoder = BinEncoder::new(&mut bytes);
+        emit(&mut encoder, &rdata).expect("failed to emit tlsa");
+        let bytes = encoder.into_bytes();
+
+        println!("bytes: {:?}", bytes);
+
+        let mut decoder: BinDecoder = BinDecoder::new(bytes);
+        let read_rdata =
+            read(&mut decoder, Restrict::new(bytes.len() as u16)).expect("failed to read back");
+        assert_eq!(rdata, read_rdata);
+    }
+
+    #[test]
+    fn test_encode_decode_tlsa() {
+        test_encode_decode(TLSA::new(
+            CertUsage::Service,
+            Selector::Spki,
+            Matching::Sha256,
+            vec![1, 2, 3, 4, 5, 6, 7, 8],
+        ));
+        test_encode_decode(TLSA::new(
+            CertUsage::CA,
+            Selector::Full,
+            Matching::Raw,
+            vec![1, 2, 3, 4, 5, 6, 7, 8],
+        ));
+        test_encode_decode(TLSA::new(
+            CertUsage::DomainIssued,
+            Selector::Full,
+            Matching::Sha512,
+            vec![1, 2, 3, 4, 5, 6, 7, 8],
+        ));
+        test_encode_decode(TLSA::new(
+            CertUsage::Unassigned(40),
+            Selector::Unassigned(39),
+            Matching::Unassigned(6),
+            vec![1, 2, 3, 4, 5, 6, 7, 8],
+        ));
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/txt.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/txt.rs
new file mode 100644
index 0000000..116bcae
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rdata/txt.rs
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! text records for storing arbitrary data
+
+use std::slice::Iter;
+
+use crate::error::*;
+use crate::serialize::binary::*;
+
+/// [RFC 1035, DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION, November 1987](https://tools.ietf.org/html/rfc1035)
+///
+/// ```text
+/// 3.3.14. TXT RDATA format
+///
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///     /                   TXT-DATA                    /
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///
+///
+/// TXT RRs are used to hold descriptive text.  The semantics of the text
+/// depends on the domain where it is found.
+/// ```
+#[derive(Debug, PartialEq, Eq, Hash, Clone)]
+pub struct TXT {
+    txt_data: Box<[Box<[u8]>]>,
+}
+
+impl TXT {
+    /// Creates a new TXT record data.
+    ///
+    /// # Arguments
+    ///
+    /// * `txt_data` - the set of strings which make up the txt_data.
+    ///
+    /// # Return value
+    ///
+    /// The new TXT record data.
+    pub fn new(txt_data: Vec<String>) -> TXT {
+        TXT {
+            txt_data: txt_data
+                .into_iter()
+                .map(|s| s.as_bytes().to_vec().into_boxed_slice())
+                .collect::<Vec<_>>()
+                .into_boxed_slice(),
+        }
+    }
+
+    /// ```text
+    /// TXT-DATA        One or more <character-string>s.
+    /// ```
+    pub fn txt_data(&self) -> &[Box<[u8]>] {
+        &self.txt_data
+    }
+
+    /// Returns an iterator over the arrays in the txt data
+    pub fn iter(&self) -> Iter<Box<[u8]>> {
+        self.txt_data.iter()
+    }
+}
+
+/// Read the RData from the given Decoder
+pub fn read(decoder: &mut BinDecoder, rdata_length: Restrict<u16>) -> ProtoResult<TXT> {
+    let data_len = decoder.len();
+    let mut strings = Vec::with_capacity(1);
+
+    // no unsafe usage of rdata length after this point
+    let rdata_length =
+        rdata_length.map(|u| u as usize).unverified(/*used as a higher bound, safely*/);
+    while data_len - decoder.len() < rdata_length {
+        let string =
+            decoder.read_character_data()?.unverified(/*any data should be validate in TXT usage*/);
+        strings.push(string.to_vec().into_boxed_slice());
+    }
+    Ok(TXT {
+        txt_data: strings.into_boxed_slice(),
+    })
+}
+
+/// Write the RData from the given Decoder
+pub fn emit(encoder: &mut BinEncoder, txt: &TXT) -> ProtoResult<()> {
+    for s in txt.txt_data() {
+        encoder.emit_character_data(s)?;
+    }
+
+    Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+    #![allow(clippy::dbg_macro, clippy::print_stdout)]
+
+    use super::*;
+
+    #[test]
+    fn test() {
+        let rdata = TXT::new(vec!["Test me some".to_string(), "more please".to_string()]);
+
+        let mut bytes = Vec::new();
+        let mut encoder: BinEncoder = BinEncoder::new(&mut bytes);
+        assert!(emit(&mut encoder, &rdata).is_ok());
+        let bytes = encoder.into_bytes();
+
+        println!("bytes: {:?}", bytes);
+
+        let mut decoder: BinDecoder = BinDecoder::new(bytes);
+        let restrict = Restrict::new(bytes.len() as u16);
+        let read_rdata = read(&mut decoder, restrict).expect("Decoding error");
+        assert_eq!(rdata, read_rdata);
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/record_data.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/record_data.rs
new file mode 100644
index 0000000..5b34c17
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/record_data.rs
@@ -0,0 +1,1110 @@
+/*
+ * Copyright (C) 2015-2019 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! record data enum variants
+
+use std::cmp::Ordering;
+#[cfg(test)]
+use std::convert::From;
+use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+
+use enum_as_inner::EnumAsInner;
+use log::{debug, warn};
+
+use super::domain::Name;
+use super::rdata;
+use super::rdata::{CAA, MX, NAPTR, NULL, OPENPGPKEY, OPT, SOA, SRV, SSHFP, TLSA, TXT};
+use super::record_type::RecordType;
+use crate::error::*;
+use crate::serialize::binary::*;
+
+#[cfg(feature = "dnssec")]
+use super::dnssec::rdata::DNSSECRData;
+
+/// Record data enum variants
+///
+/// [RFC 1035](https://tools.ietf.org/html/rfc1035), DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION, November 1987
+///
+/// ```text
+/// 3.3. Standard RRs
+///
+/// The following RR definitions are expected to occur, at least
+/// potentially, in all classes.  In particular, NS, SOA, CNAME, and PTR
+/// will be used in all classes, and have the same format in all classes.
+/// Because their RDATA format is known, all domain names in the RDATA
+/// section of these RRs may be compressed.
+///
+/// <domain-name> is a domain name represented as a series of labels, and
+/// terminated by a label with zero length.  <character-string> is a single
+/// length octet followed by that number of characters.  <character-string>
+/// is treated as binary information, and can be up to 256 characters in
+/// length (including the length octet).
+/// ```
+#[derive(Debug, EnumAsInner, PartialEq, Clone, Eq)]
+pub enum RData {
+    /// ```text
+    /// -- RFC 1035 -- Domain Implementation and Specification    November 1987
+    ///
+    /// 3.4. Internet specific RRs
+    ///
+    /// 3.4.1. A RDATA format
+    ///
+    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    ///     |                    ADDRESS                    |
+    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    ///
+    /// where:
+    ///
+    /// ADDRESS         A 32 bit Internet address.
+    ///
+    /// Hosts that have multiple Internet addresses will have multiple A
+    /// records.
+    ///
+    /// A records cause no additional section processing.  The RDATA section of
+    /// an A line in a master file is an Internet address expressed as four
+    /// decimal numbers separated by dots without any embedded spaces (e.g.,
+    /// "10.2.0.52" or "192.0.5.6").
+    /// ```
+    A(Ipv4Addr),
+
+    /// ```text
+    /// -- RFC 1886 -- IPv6 DNS Extensions              December 1995
+    ///
+    /// 2.2 AAAA data format
+    ///
+    ///    A 128 bit IPv6 address is encoded in the data portion of an AAAA
+    ///    resource record in network byte order (high-order byte first).
+    /// ```
+    AAAA(Ipv6Addr),
+
+    /// ```text
+    /// 2.  The ANAME resource record
+    ///
+    ///   This document defines the "ANAME" DNS resource record type, with RR
+    ///   TYPE value [TBD].
+    ///
+    /// 2.1.  Presentation and wire format
+    ///
+    ///   The ANAME presentation format is identical to that of CNAME
+    ///   [RFC1033]:
+    ///
+    ///       owner ttl class ANAME target
+    /// ```
+    ANAME(Name),
+
+    /// ```text
+    /// -- RFC 6844          Certification Authority Authorization     January 2013
+    ///
+    /// 5.1.  Syntax
+    ///
+    /// A CAA RR contains a single property entry consisting of a tag-value
+    /// pair.  Each tag represents a property of the CAA record.  The value
+    /// of a CAA property is that specified in the corresponding value field.
+    ///
+    /// A domain name MAY have multiple CAA RRs associated with it and a
+    /// given property MAY be specified more than once.
+    ///
+    /// The CAA data field contains one property entry.  A property entry
+    /// consists of the following data fields:
+    ///
+    /// +0-1-2-3-4-5-6-7-|0-1-2-3-4-5-6-7-|
+    /// | Flags          | Tag Length = n |
+    /// +----------------+----------------+...+---------------+
+    /// | Tag char 0     | Tag char 1     |...| Tag char n-1  |
+    /// +----------------+----------------+...+---------------+
+    /// +----------------+----------------+.....+----------------+
+    /// | Value byte 0   | Value byte 1   |.....| Value byte m-1 |
+    /// +----------------+----------------+.....+----------------+
+
+    /// Where n is the length specified in the Tag length field and m is the
+    /// remaining octets in the Value field (m = d - n - 2) where d is the
+    /// length of the RDATA section.
+    /// ```
+    CAA(CAA),
+
+    /// ```text
+    ///   3.3. Standard RRs
+    ///
+    /// The following RR definitions are expected to occur, at least
+    /// potentially, in all classes.  In particular, NS, SOA, CNAME, and PTR
+    /// will be used in all classes, and have the same format in all classes.
+    /// Because their RDATA format is known, all domain names in the RDATA
+    /// section of these RRs may be compressed.
+    ///
+    /// <domain-name> is a domain name represented as a series of labels, and
+    /// terminated by a label with zero length.  <character-string> is a single
+    /// length octet followed by that number of characters.  <character-string>
+    /// is treated as binary information, and can be up to 256 characters in
+    /// length (including the length octet).
+    ///
+    /// 3.3.1. CNAME RDATA format
+    ///
+    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    ///     /                     CNAME                     /
+    ///     /                                               /
+    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    ///
+    /// where:
+    ///
+    /// CNAME           A <domain-name> which specifies the canonical or primary
+    ///                 name for the owner.  The owner name is an alias.
+    ///
+    /// CNAME RRs cause no additional section processing, but name servers may
+    /// choose to restart the query at the canonical name in certain cases.  See
+    /// the description of name server logic in [RFC-1034] for details.
+    /// ```
+    CNAME(Name),
+
+    /// ```text
+    /// 3.3.9. MX RDATA format
+    ///
+    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    ///     |                  PREFERENCE                   |
+    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    ///     /                   EXCHANGE                    /
+    ///     /                                               /
+    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    ///
+    /// where:
+    ///
+    /// PREFERENCE      A 16 bit integer which specifies the preference given to
+    ///                 this RR among others at the same owner.  Lower values
+    ///                 are preferred.
+    ///
+    /// EXCHANGE        A <domain-name> which specifies a host willing to act as
+    ///                 a mail exchange for the owner name.
+    ///
+    /// MX records cause type A additional section processing for the host
+    /// specified by EXCHANGE.  The use of MX RRs is explained in detail in
+    /// [RFC-974].
+    /// ```
+    MX(MX),
+
+    /// [RFC 3403 DDDS DNS Database, October 2002](https://tools.ietf.org/html/rfc3403#section-4)
+    ///
+    /// ```text
+    /// 4.1 Packet Format
+    ///
+    ///   The packet format of the NAPTR RR is given below.  The DNS type code
+    ///   for NAPTR is 35.
+    ///
+    ///      The packet format for the NAPTR record is as follows
+    ///                                       1  1  1  1  1  1
+    ///         0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
+    ///       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    ///       |                     ORDER                     |
+    ///       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    ///       |                   PREFERENCE                  |
+    ///       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    ///       /                     FLAGS                     /
+    ///       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    ///       /                   SERVICES                    /
+    ///       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    ///       /                    REGEXP                     /
+    ///       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    ///       /                  REPLACEMENT                  /
+    ///       /                                               /
+    ///       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    ///
+    ///   <character-string> and <domain-name> as used here are defined in RFC
+    ///   1035 [7].
+    ///
+    ///   ORDER
+    ///      A 16-bit unsigned integer specifying the order in which the NAPTR
+    ///      records MUST be processed in order to accurately represent the
+    ///      ordered list of Rules.  The ordering is from lowest to highest.
+    ///      If two records have the same order value then they are considered
+    ///      to be the same rule and should be selected based on the
+    ///      combination of the Preference values and Services offered.
+    ///
+    ///   PREFERENCE
+    ///      Although it is called "preference" in deference to DNS
+    ///      terminology, this field is equivalent to the Priority value in the
+    ///      DDDS Algorithm.  It is a 16-bit unsigned integer that specifies
+    ///      the order in which NAPTR records with equal Order values SHOULD be
+    ///      processed, low numbers being processed before high numbers.  This
+    ///      is similar to the preference field in an MX record, and is used so
+    ///      domain administrators can direct clients towards more capable
+    ///      hosts or lighter weight protocols.  A client MAY look at records
+    ///      with higher preference values if it has a good reason to do so
+    ///      such as not supporting some protocol or service very well.
+    ///
+    ///      The important difference between Order and Preference is that once
+    ///      a match is found the client MUST NOT consider records with a
+    ///      different Order but they MAY process records with the same Order
+    ///      but different Preferences.  The only exception to this is noted in
+    ///      the second important Note in the DDDS algorithm specification
+    ///      concerning allowing clients to use more complex Service
+    ///      determination between steps 3 and 4 in the algorithm.  Preference
+    ///      is used to give communicate a higher quality of service to rules
+    ///      that are considered the same from an authority standpoint but not
+    ///      from a simple load balancing standpoint.
+    ///
+    ///      It is important to note that DNS contains several load balancing
+    ///      mechanisms and if load balancing among otherwise equal services
+    ///      should be needed then methods such as SRV records or multiple A
+    ///      records should be utilized to accomplish load balancing.
+    ///
+    ///   FLAGS
+    ///      A <character-string> containing flags to control aspects of the
+    ///      rewriting and interpretation of the fields in the record.  Flags
+    ///      are single characters from the set A-Z and 0-9.  The case of the
+    ///      alphabetic characters is not significant.  The field can be empty.
+    ///
+    ///      It is up to the Application specifying how it is using this
+    ///      Database to define the Flags in this field.  It must define which
+    ///      ones are terminal and which ones are not.
+    ///
+    ///   SERVICES
+    ///      A <character-string> that specifies the Service Parameters
+    ///      applicable to this this delegation path.  It is up to the
+    ///      Application Specification to specify the values found in this
+    ///      field.
+    ///
+    ///   REGEXP
+    ///      A <character-string> containing a substitution expression that is
+    ///      applied to the original string held by the client in order to
+    ///      construct the next domain name to lookup.  See the DDDS Algorithm
+    ///      specification for the syntax of this field.
+    ///
+    ///      As stated in the DDDS algorithm, The regular expressions MUST NOT
+    ///      be used in a cumulative fashion, that is, they should only be
+    ///      applied to the original string held by the client, never to the
+    ///      domain name produced by a previous NAPTR rewrite.  The latter is
+    ///      tempting in some applications but experience has shown such use to
+    ///      be extremely fault sensitive, very error prone, and extremely
+    ///      difficult to debug.
+    ///
+    ///   REPLACEMENT
+    ///      A <domain-name> which is the next domain-name to query for
+    ///      depending on the potential values found in the flags field.  This
+    ///      field is used when the regular expression is a simple replacement
+    ///      operation.  Any value in this field MUST be a fully qualified
+    ///      domain-name.  Name compression is not to be used for this field.
+    ///
+    ///      This field and the REGEXP field together make up the Substitution
+    ///      Expression in the DDDS Algorithm.  It is simply a historical
+    ///      optimization specifically for DNS compression that this field
+    ///      exists.  The fields are also mutually exclusive.  If a record is
+    ///      returned that has values for both fields then it is considered to
+    ///      be in error and SHOULD be either ignored or an error returned.
+    /// ```
+    NAPTR(NAPTR),
+
+    /// ```text
+    /// 3.3.10. NULL RDATA format (EXPERIMENTAL)
+    ///
+    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    ///     /                  <anything>                   /
+    ///     /                                               /
+    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    ///
+    /// Anything at all may be in the RDATA field so long as it is 65535 octets
+    /// or less.
+    ///
+    /// NULL records cause no additional section processing.  NULL RRs are not
+    /// allowed in master files.  NULLs are used as placeholders in some
+    /// experimental extensions of the DNS.
+    /// ```
+    NULL(NULL),
+
+    /// ```text
+    /// 3.3.11. NS RDATA format
+    ///
+    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    ///     /                   NSDNAME                     /
+    ///     /                                               /
+    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    ///
+    /// where:
+    ///
+    /// NSDNAME         A <domain-name> which specifies a host which should be
+    ///                 authoritative for the specified class and domain.
+    ///
+    /// NS records cause both the usual additional section processing to locate
+    /// a type A record, and, when used in a referral, a special search of the
+    /// zone in which they reside for glue information.
+    ///
+    /// The NS RR states that the named host should be expected to have a zone
+    /// starting at owner name of the specified class.  Note that the class may
+    /// not indicate the protocol family which should be used to communicate
+    /// with the host, although it is typically a strong hint.  For example,
+    /// hosts which are name servers for either Internet (IN) or Hesiod (HS)
+    /// class information are normally queried using IN class protocols.
+    /// ```
+    NS(Name),
+
+    /// [RFC 7929](https://tools.ietf.org/html/rfc7929#section-2.1)
+    ///
+    /// ```text
+    /// The RDATA portion of an OPENPGPKEY resource record contains a single
+    /// value consisting of a Transferable Public Key formatted as specified
+    /// in [RFC4880].
+    /// ```
+    OPENPGPKEY(OPENPGPKEY),
+
+    /// ```text
+    /// RFC 6891                   EDNS(0) Extensions                 April 2013
+    /// 6.1.2.  Wire Format
+    ///
+    ///        +------------+--------------+------------------------------+
+    ///        | Field Name | Field Type   | Description                  |
+    ///        +------------+--------------+------------------------------+
+    ///        | NAME       | domain name  | MUST be 0 (root domain)      |
+    ///        | TYPE       | u_int16_t    | OPT (41)                     |
+    ///        | CLASS      | u_int16_t    | requestor's UDP payload size |
+    ///        | TTL        | u_int32_t    | extended RCODE and flags     |
+    ///        | RDLEN      | u_int16_t    | length of all RDATA          |
+    ///        | RDATA      | octet stream | {attribute,value} pairs      |
+    ///        +------------+--------------+------------------------------+
+    ///
+    /// The variable part of an OPT RR may contain zero or more options in
+    ///    the RDATA.  Each option MUST be treated as a bit field.  Each option
+    ///    is encoded as:
+    ///
+    ///                   +0 (MSB)                            +1 (LSB)
+    ///        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+    ///     0: |                          OPTION-CODE                          |
+    ///        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+    ///     2: |                         OPTION-LENGTH                         |
+    ///        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+    ///     4: |                                                               |
+    ///        /                          OPTION-DATA                          /
+    ///        /                                                               /
+    ///        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+    /// ```
+    OPT(OPT),
+
+    /// ```text
+    /// 3.3.12. PTR RDATA format
+    ///
+    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    ///     /                   PTRDNAME                    /
+    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    ///
+    /// where:
+    ///
+    /// PTRDNAME        A <domain-name> which points to some location in the
+    ///                 domain name space.
+    ///
+    /// PTR records cause no additional section processing.  These RRs are used
+    /// in special domains to point to some other location in the domain space.
+    /// These records are simple data, and don't imply any special processing
+    /// similar to that performed by CNAME, which identifies aliases.  See the
+    /// description of the IN-ADDR.ARPA domain for an example.
+    /// ```
+    PTR(Name),
+
+    /// ```text
+    /// 3.3.13. SOA RDATA format
+    ///
+    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    ///     /                     MNAME                     /
+    ///     /                                               /
+    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    ///     /                     RNAME                     /
+    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    ///     |                    SERIAL                     |
+    ///     |                                               |
+    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    ///     |                    REFRESH                    |
+    ///     |                                               |
+    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    ///     |                     RETRY                     |
+    ///     |                                               |
+    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    ///     |                    EXPIRE                     |
+    ///     |                                               |
+    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    ///     |                    MINIMUM                    |
+    ///     |                                               |
+    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    ///
+    /// where:
+    ///
+    /// MNAME           The <domain-name> of the name server that was the
+    ///                 original or primary source of data for this zone.
+    ///
+    /// RNAME           A <domain-name> which specifies the mailbox of the
+    ///                 person responsible for this zone.
+    ///
+    /// SERIAL          The unsigned 32 bit version number of the original copy
+    ///                 of the zone.  Zone transfers preserve this value.  This
+    ///                 value wraps and should be compared using sequence space
+    ///                 arithmetic.
+    ///
+    /// REFRESH         A 32 bit time interval before the zone should be
+    ///                 refreshed.
+    ///
+    /// RETRY           A 32 bit time interval that should elapse before a
+    ///                 failed refresh should be retried.
+    ///
+    /// EXPIRE          A 32 bit time value that specifies the upper limit on
+    ///                 the time interval that can elapse before the zone is no
+    ///                 longer authoritative.
+    ///
+    /// MINIMUM         The unsigned 32 bit minimum TTL field that should be
+    ///                 exported with any RR from this zone.
+    ///
+    /// SOA records cause no additional section processing.
+    ///
+    /// All times are in units of seconds.
+    ///
+    /// Most of these fields are pertinent only for name server maintenance
+    /// operations.  However, MINIMUM is used in all query operations that
+    /// retrieve RRs from a zone.  Whenever a RR is sent in a response to a
+    /// query, the TTL field is set to the maximum of the TTL field from the RR
+    /// and the MINIMUM field in the appropriate SOA.  Thus MINIMUM is a lower
+    /// bound on the TTL field for all RRs in a zone.  Note that this use of
+    /// MINIMUM should occur when the RRs are copied into the response and not
+    /// when the zone is loaded from a master file or via a zone transfer.  The
+    /// reason for this provision is to allow future dynamic update facilities to
+    /// change the SOA RR with known semantics.
+    /// ```
+    SOA(SOA),
+
+    /// ```text
+    /// RFC 2782                       DNS SRV RR                  February 2000
+    ///
+    /// The format of the SRV RR
+    ///
+    ///  _Service._Proto.Name TTL Class SRV Priority Weight Port Target
+    /// ```
+    SRV(SRV),
+
+    /// [RFC 4255](https://tools.ietf.org/html/rfc4255#section-3.1)
+    ///
+    /// ```text
+    /// 3.1.  The SSHFP RDATA Format
+    ///
+    ///    The RDATA for a SSHFP RR consists of an algorithm number, fingerprint
+    ///    type and the fingerprint of the public host key.
+    ///
+    ///        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+    ///        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+    ///        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    ///        |   algorithm   |    fp type    |                               /
+    ///        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               /
+    ///        /                                                               /
+    ///        /                          fingerprint                          /
+    ///        /                                                               /
+    ///        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    ///
+    /// 3.1.1.  Algorithm Number Specification
+    ///
+    ///    This algorithm number octet describes the algorithm of the public
+    ///    key.  The following values are assigned:
+    ///
+    ///           Value    Algorithm name
+    ///           -----    --------------
+    ///           0        reserved
+    ///           1        RSA
+    ///           2        DSS
+    ///
+    ///    Reserving other types requires IETF consensus [4].
+    ///
+    /// 3.1.2.  Fingerprint Type Specification
+    ///
+    ///    The fingerprint type octet describes the message-digest algorithm
+    ///    used to calculate the fingerprint of the public key.  The following
+    ///    values are assigned:
+    ///
+    ///           Value    Fingerprint type
+    ///           -----    ----------------
+    ///           0        reserved
+    ///           1        SHA-1
+    ///
+    ///    Reserving other types requires IETF consensus [4].
+    ///
+    ///    For interoperability reasons, as few fingerprint types as possible
+    ///    should be reserved.  The only reason to reserve additional types is
+    ///    to increase security.
+    ///
+    /// 3.1.3.  Fingerprint
+    ///
+    ///    The fingerprint is calculated over the public key blob as described
+    ///    in [7].
+    ///
+    ///    The message-digest algorithm is presumed to produce an opaque octet
+    ///    string output, which is placed as-is in the RDATA fingerprint field.
+    /// ```
+    ///
+    /// The algorithm and fingerprint type values have been updated in
+    /// [RFC 6594](https://tools.ietf.org/html/rfc6594) and
+    /// [RFC 7479](https://tools.ietf.org/html/rfc7479).
+    SSHFP(SSHFP),
+
+    /// [RFC 6698, DNS-Based Authentication for TLS](https://tools.ietf.org/html/rfc6698#section-2.1)
+    ///
+    /// ```text
+    ///                         1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+    ///     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+    ///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    ///    |  Cert. Usage  |   Selector    | Matching Type |               /
+    ///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+               /
+    ///    /                                                               /
+    ///    /                 Certificate Association Data                  /
+    ///    /                                                               /
+    ///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    /// ```
+    TLSA(TLSA),
+
+    /// ```text
+    /// 3.3.14. TXT RDATA format
+    ///
+    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    ///     /                   TXT-DATA                    /
+    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    ///
+    /// where:
+    ///
+    /// TXT-DATA        One or more <character-string>s.
+    ///
+    /// TXT RRs are used to hold descriptive text.  The semantics of the text
+    /// depends on the domain where it is found.
+    /// ```
+    TXT(TXT),
+
+    /// A DNSSEC- or SIG(0)- specific record. See `DNSSECRData` for details.
+    ///
+    /// These types are in `DNSSECRData` to make them easy to disable when
+    /// crypto functionality isn't needed.
+    #[cfg(feature = "dnssec")]
+    DNSSEC(DNSSECRData),
+
+    /// Unknown RecordData is for record types not supported by Trust-DNS
+    Unknown {
+        /// RecordType code
+        code: u16,
+        /// RData associated to the record
+        rdata: NULL,
+    },
+
+    /// This corresponds to a record type of 0, unspecified
+    ZERO,
+}
+
+impl RData {
+    fn to_bytes(&self) -> Vec<u8> {
+        let mut buf: Vec<u8> = Vec::new();
+        {
+            let mut encoder: BinEncoder = BinEncoder::new(&mut buf);
+            self.emit(&mut encoder).unwrap_or_else(|_| {
+                warn!("could not encode RDATA: {:?}", self);
+            });
+        }
+        buf
+    }
+
+    /// Read the RData from the given Decoder
+    pub fn read(
+        decoder: &mut BinDecoder,
+        record_type: RecordType,
+        rdata_length: Restrict<u16>,
+    ) -> ProtoResult<Self> {
+        let start_idx = decoder.index();
+
+        let result = match record_type {
+            RecordType::A => {
+                debug!("reading A");
+                rdata::a::read(decoder).map(RData::A)
+            }
+            RecordType::AAAA => {
+                debug!("reading AAAA");
+                rdata::aaaa::read(decoder).map(RData::AAAA)
+            }
+            RecordType::ANAME => {
+                debug!("reading ANAME");
+                rdata::name::read(decoder).map(RData::ANAME)
+            }
+            rt @ RecordType::ANY | rt @ RecordType::AXFR | rt @ RecordType::IXFR => {
+                return Err(ProtoErrorKind::UnknownRecordTypeValue(rt.into()).into());
+            }
+            RecordType::CAA => {
+                debug!("reading CAA");
+                rdata::caa::read(decoder, rdata_length).map(RData::CAA)
+            }
+            RecordType::CNAME => {
+                debug!("reading CNAME");
+                rdata::name::read(decoder).map(RData::CNAME)
+            }
+            RecordType::ZERO => {
+                debug!("reading EMPTY");
+                return Ok(RData::ZERO);
+            }
+            RecordType::MX => {
+                debug!("reading MX");
+                rdata::mx::read(decoder).map(RData::MX)
+            }
+            RecordType::NAPTR => {
+                debug!("reading NAPTR");
+                rdata::naptr::read(decoder).map(RData::NAPTR)
+            }
+            RecordType::NULL => {
+                debug!("reading NULL");
+                rdata::null::read(decoder, rdata_length).map(RData::NULL)
+            }
+            RecordType::NS => {
+                debug!("reading NS");
+                rdata::name::read(decoder).map(RData::NS)
+            }
+            RecordType::OPENPGPKEY => {
+                debug!("reading OPENPGPKEY");
+                rdata::openpgpkey::read(decoder, rdata_length).map(RData::OPENPGPKEY)
+            }
+            RecordType::OPT => {
+                debug!("reading OPT");
+                rdata::opt::read(decoder, rdata_length).map(RData::OPT)
+            }
+            RecordType::PTR => {
+                debug!("reading PTR");
+                rdata::name::read(decoder).map(RData::PTR)
+            }
+            RecordType::SOA => {
+                debug!("reading SOA");
+                rdata::soa::read(decoder).map(RData::SOA)
+            }
+            RecordType::SRV => {
+                debug!("reading SRV");
+                rdata::srv::read(decoder).map(RData::SRV)
+            }
+            RecordType::SSHFP => {
+                debug!("reading SSHFP");
+                rdata::sshfp::read(decoder, rdata_length).map(RData::SSHFP)
+            }
+            RecordType::TLSA => {
+                debug!("reading TLSA");
+                rdata::tlsa::read(decoder, rdata_length).map(RData::TLSA)
+            }
+            RecordType::TXT => {
+                debug!("reading TXT");
+                rdata::txt::read(decoder, rdata_length).map(RData::TXT)
+            }
+            #[cfg(feature = "dnssec")]
+            RecordType::DNSSEC(record_type) => {
+                DNSSECRData::read(decoder, record_type, rdata_length).map(RData::DNSSEC)
+            }
+            RecordType::Unknown(code) => {
+                debug!("reading Unknown");
+                rdata::null::read(decoder, rdata_length).map(|rdata| RData::Unknown { code, rdata })
+            }
+        };
+
+        // we should have read rdata_length, but we did not
+        let read = decoder.index() - start_idx;
+        rdata_length
+            .map(|u| u as usize)
+            .verify_unwrap(|rdata_length| read == *rdata_length)
+            .map_err(|rdata_length| {
+                ProtoError::from(ProtoErrorKind::IncorrectRDataLengthRead {
+                    read,
+                    len: rdata_length,
+                })
+            })?;
+
+        result
+    }
+
+    /// [RFC 4034](https://tools.ietf.org/html/rfc4034#section-6), DNSSEC Resource Records, March 2005
+    ///
+    /// ```text
+    /// 6.2.  Canonical RR Form
+    ///
+    ///    For the purposes of DNS security, the canonical form of an RR is the
+    ///    wire format of the RR where:
+    ///
+    ///    ...
+    ///
+    ///    3.  if the type of the RR is NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR,
+    ///        HINFO, MINFO, MX, HINFO, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX,
+    ///        SRV, DNAME, A6, RRSIG, or (rfc6840 removes NSEC), all uppercase
+    ///        US-ASCII letters in the DNS names contained within the RDATA are replaced
+    ///        by the corresponding lowercase US-ASCII letters;
+    /// ```
+    ///
+    /// Canonical name form for all non-1035 records:
+    ///   [RFC 3579](https://tools.ietf.org/html/rfc3597)
+    /// ```text
+    ///  4.  Domain Name Compression
+    ///
+    ///   RRs containing compression pointers in the RDATA part cannot be
+    ///   treated transparently, as the compression pointers are only
+    ///   meaningful within the context of a DNS message.  Transparently
+    ///   copying the RDATA into a new DNS message would cause the compression
+    ///   pointers to point at the corresponding location in the new message,
+    ///   which now contains unrelated data.  This would cause the compressed
+    ///   name to be corrupted.
+    ///
+    ///   To avoid such corruption, servers MUST NOT compress domain names
+    ///   embedded in the RDATA of types that are class-specific or not well-
+    ///   known.  This requirement was stated in [RFC1123] without defining the
+    ///   term "well-known"; it is hereby specified that only the RR types
+    ///   defined in [RFC1035] are to be considered "well-known".
+    ///
+    ///   The specifications of a few existing RR types have explicitly allowed
+    ///   compression contrary to this specification: [RFC2163] specified that
+    ///   compression applies to the PX RR, and [RFC2535] allowed compression
+    ///   in SIG RRs and NXT RRs records.  Since this specification disallows
+    ///   compression in these cases, it is an update to [RFC2163] (section 4)
+    ///   and [RFC2535] (sections 4.1.7 and 5.2).
+    ///
+    ///   Receiving servers MUST decompress domain names in RRs of well-known
+    ///   type, and SHOULD also decompress RRs of type RP, AFSDB, RT, SIG, PX,
+    ///   NXT, NAPTR, and SRV (although the current specification of the SRV RR
+    ///   in [RFC2782] prohibits compression, [RFC2052] mandated it, and some
+    ///   servers following that earlier specification are still in use).
+    ///
+    ///   Future specifications for new RR types that contain domain names
+    ///   within their RDATA MUST NOT allow the use of name compression for
+    ///   those names, and SHOULD explicitly state that the embedded domain
+    ///   names MUST NOT be compressed.
+    ///
+    ///   As noted in [RFC1123], the owner name of an RR is always eligible for
+    ///   compression.
+    ///
+    ///   ...
+    ///   As a courtesy to implementors, it is hereby noted that the complete
+    ///    set of such previously published RR types that contain embedded
+    ///    domain names, and whose DNSSEC canonical form therefore involves
+    ///   downcasing according to the DNS rules for character comparisons,
+    ///   consists of the RR types NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR,
+    ///   HINFO, MINFO, MX, HINFO, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX, SRV,
+    ///   DNAME, and A6.
+    ///   ...
+    /// ```
+    pub fn emit(&self, encoder: &mut BinEncoder) -> ProtoResult<()> {
+        match *self {
+            RData::A(address) => rdata::a::emit(encoder, address),
+            RData::AAAA(ref address) => rdata::aaaa::emit(encoder, address),
+            RData::ANAME(ref name) => {
+                encoder.with_canonical_names(|encoder| rdata::name::emit(encoder, name))
+            }
+            RData::CAA(ref caa) => {
+                encoder.with_canonical_names(|encoder| rdata::caa::emit(encoder, caa))
+            }
+            // to_lowercase for rfc4034 and rfc6840
+            RData::CNAME(ref name) | RData::NS(ref name) | RData::PTR(ref name) => {
+                rdata::name::emit(encoder, name)
+            }
+            RData::ZERO => Ok(()),
+            // to_lowercase for rfc4034 and rfc6840
+            RData::MX(ref mx) => rdata::mx::emit(encoder, mx),
+            RData::NAPTR(ref naptr) => {
+                encoder.with_canonical_names(|encoder| rdata::naptr::emit(encoder, naptr))
+            }
+            RData::NULL(ref null) => rdata::null::emit(encoder, null),
+            RData::OPENPGPKEY(ref openpgpkey) => {
+                encoder.with_canonical_names(|encoder| rdata::openpgpkey::emit(encoder, openpgpkey))
+            }
+            RData::OPT(ref opt) => rdata::opt::emit(encoder, opt),
+            // to_lowercase for rfc4034 and rfc6840
+            RData::SOA(ref soa) => rdata::soa::emit(encoder, soa),
+            // to_lowercase for rfc4034 and rfc6840
+            RData::SRV(ref srv) => {
+                encoder.with_canonical_names(|encoder| rdata::srv::emit(encoder, srv))
+            }
+            RData::SSHFP(ref sshfp) => {
+                encoder.with_canonical_names(|encoder| rdata::sshfp::emit(encoder, sshfp))
+            }
+            RData::TLSA(ref tlsa) => {
+                encoder.with_canonical_names(|encoder| rdata::tlsa::emit(encoder, tlsa))
+            }
+            RData::TXT(ref txt) => rdata::txt::emit(encoder, txt),
+            #[cfg(feature = "dnssec")]
+            RData::DNSSEC(ref rdata) => encoder.with_canonical_names(|encoder| rdata.emit(encoder)),
+            RData::Unknown { ref rdata, .. } => rdata::null::emit(encoder, rdata),
+        }
+    }
+
+    /// Converts this to a Recordtype
+    pub fn to_record_type(&self) -> RecordType {
+        match *self {
+            RData::A(..) => RecordType::A,
+            RData::AAAA(..) => RecordType::AAAA,
+            RData::ANAME(..) => RecordType::ANAME,
+            RData::CAA(..) => RecordType::CAA,
+            RData::CNAME(..) => RecordType::CNAME,
+            RData::MX(..) => RecordType::MX,
+            RData::NAPTR(..) => RecordType::NAPTR,
+            RData::NS(..) => RecordType::NS,
+            RData::NULL(..) => RecordType::NULL,
+            RData::OPENPGPKEY(..) => RecordType::OPENPGPKEY,
+            RData::OPT(..) => RecordType::OPT,
+            RData::PTR(..) => RecordType::PTR,
+            RData::SOA(..) => RecordType::SOA,
+            RData::SRV(..) => RecordType::SRV,
+            RData::SSHFP(..) => RecordType::SSHFP,
+            RData::TLSA(..) => RecordType::TLSA,
+            RData::TXT(..) => RecordType::TXT,
+            #[cfg(feature = "dnssec")]
+            RData::DNSSEC(ref rdata) => RecordType::DNSSEC(DNSSECRData::to_record_type(rdata)),
+            RData::Unknown { code, .. } => RecordType::Unknown(code),
+            RData::ZERO => RecordType::ZERO,
+        }
+    }
+
+    /// If this is an A or AAAA record type, then an IpAddr will be returned
+    pub fn to_ip_addr(&self) -> Option<IpAddr> {
+        match *self {
+            RData::A(a) => Some(IpAddr::from(a)),
+            RData::AAAA(aaaa) => Some(IpAddr::from(aaaa)),
+            _ => None,
+        }
+    }
+}
+
+impl PartialOrd<RData> for RData {
+    fn partial_cmp(&self, other: &RData) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl Ord for RData {
+    // RFC 4034                DNSSEC Resource Records               March 2005
+    //
+    // 6.3.  Canonical RR Ordering within an RRset
+    //
+    //    For the purposes of DNS security, RRs with the same owner name,
+    //    class, and type are sorted by treating the RDATA portion of the
+    //    canonical form of each RR as a left-justified unsigned octet sequence
+    //    in which the absence of an octet sorts before a zero octet.
+    //
+    //    [RFC2181] specifies that an RRset is not allowed to contain duplicate
+    //    records (multiple RRs with the same owner name, class, type, and
+    //    RDATA).  Therefore, if an implementation detects duplicate RRs when
+    //    putting the RRset in canonical form, it MUST treat this as a protocol
+    //    error.  If the implementation chooses to handle this protocol error
+    //    in the spirit of the robustness principle (being liberal in what it
+    //    accepts), it MUST remove all but one of the duplicate RR(s) for the
+    //    purposes of calculating the canonical form of the RRset.
+    fn cmp(&self, other: &Self) -> Ordering {
+        // TODO: how about we just store the bytes with the decoded data?
+        //  the decoded data is useful for queries, the encoded data is needed for transfers, signing
+        //  and ordering.
+        self.to_bytes().cmp(&other.to_bytes())
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    #![allow(clippy::dbg_macro, clippy::print_stdout)]
+
+    use std::net::Ipv4Addr;
+    use std::net::Ipv6Addr;
+    use std::str::FromStr;
+
+    use super::*;
+    use crate::rr::domain::Name;
+    use crate::rr::rdata::{MX, SOA, SRV, TXT};
+    use crate::serialize::binary::bin_tests::test_emit_data_set;
+    #[allow(clippy::useless_attribute)]
+    #[allow(unused)]
+    use crate::serialize::binary::*;
+
+    fn get_data() -> Vec<(RData, Vec<u8>)> {
+        vec![
+            (
+                RData::CNAME(Name::from_str("www.example.com").unwrap()),
+                vec![
+                    3, b'w', b'w', b'w', 7, b'e', b'x', b'a', b'm', b'p', b'l', b'e', 3, b'c',
+                    b'o', b'm', 0,
+                ],
+            ),
+            (
+                RData::MX(MX::new(256, Name::from_str("n").unwrap())),
+                vec![1, 0, 1, b'n', 0],
+            ),
+            (
+                RData::NS(Name::from_str("www.example.com").unwrap()),
+                vec![
+                    3, b'w', b'w', b'w', 7, b'e', b'x', b'a', b'm', b'p', b'l', b'e', 3, b'c',
+                    b'o', b'm', 0,
+                ],
+            ),
+            (
+                RData::PTR(Name::from_str("www.example.com").unwrap()),
+                vec![
+                    3, b'w', b'w', b'w', 7, b'e', b'x', b'a', b'm', b'p', b'l', b'e', 3, b'c',
+                    b'o', b'm', 0,
+                ],
+            ),
+            (
+                RData::SOA(SOA::new(
+                    Name::from_str("www.example.com").unwrap(),
+                    Name::from_str("xxx.example.com").unwrap(),
+                    u32::max_value(),
+                    -1 as i32,
+                    -1 as i32,
+                    -1 as i32,
+                    u32::max_value(),
+                )),
+                vec![
+                    3, b'w', b'w', b'w', 7, b'e', b'x', b'a', b'm', b'p', b'l', b'e', 3, b'c',
+                    b'o', b'm', 0, 3, b'x', b'x', b'x', 0xC0, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+                    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+                    0xFF, 0xFF,
+                ],
+            ),
+            (
+                RData::TXT(TXT::new(vec![
+                    "abcdef".to_string(),
+                    "ghi".to_string(),
+                    "".to_string(),
+                    "j".to_string(),
+                ])),
+                vec![
+                    6, b'a', b'b', b'c', b'd', b'e', b'f', 3, b'g', b'h', b'i', 0, 1, b'j',
+                ],
+            ),
+            (
+                RData::A(Ipv4Addr::from_str("0.0.0.0").unwrap()),
+                vec![0, 0, 0, 0],
+            ),
+            (
+                RData::AAAA(Ipv6Addr::from_str("::").unwrap()),
+                vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+            ),
+            (
+                RData::SRV(SRV::new(
+                    1,
+                    2,
+                    3,
+                    Name::from_str("www.example.com").unwrap(),
+                )),
+                vec![
+                    0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 3, b'w', b'w', b'w', 7, b'e', b'x', b'a',
+                    b'm', b'p', b'l', b'e', 3, b'c', b'o', b'm', 0,
+                ],
+            ),
+        ]
+    }
+
+    // TODO this test kinda sucks, shows the problem with not storing the binary parts
+    #[test]
+    fn test_order() {
+        let ordered: Vec<RData> = vec![
+            RData::A(Ipv4Addr::from_str("0.0.0.0").unwrap()),
+            RData::AAAA(Ipv6Addr::from_str("::").unwrap()),
+            RData::SRV(SRV::new(
+                1,
+                2,
+                3,
+                Name::from_str("www.example.com").unwrap(),
+            )),
+            RData::MX(MX::new(256, Name::from_str("n").unwrap())),
+            RData::CNAME(Name::from_str("www.example.com").unwrap()),
+            RData::PTR(Name::from_str("www.example.com").unwrap()),
+            RData::NS(Name::from_str("www.example.com").unwrap()),
+            RData::SOA(SOA::new(
+                Name::from_str("www.example.com").unwrap(),
+                Name::from_str("xxx.example.com").unwrap(),
+                u32::max_value(),
+                -1 as i32,
+                -1 as i32,
+                -1 as i32,
+                u32::max_value(),
+            )),
+            RData::TXT(TXT::new(vec![
+                "abcdef".to_string(),
+                "ghi".to_string(),
+                "".to_string(),
+                "j".to_string(),
+            ])),
+        ];
+        let mut unordered = vec![
+            RData::CNAME(Name::from_str("www.example.com").unwrap()),
+            RData::MX(MX::new(256, Name::from_str("n").unwrap())),
+            RData::PTR(Name::from_str("www.example.com").unwrap()),
+            RData::NS(Name::from_str("www.example.com").unwrap()),
+            RData::SOA(SOA::new(
+                Name::from_str("www.example.com").unwrap(),
+                Name::from_str("xxx.example.com").unwrap(),
+                u32::max_value(),
+                -1 as i32,
+                -1 as i32,
+                -1 as i32,
+                u32::max_value(),
+            )),
+            RData::TXT(TXT::new(vec![
+                "abcdef".to_string(),
+                "ghi".to_string(),
+                "".to_string(),
+                "j".to_string(),
+            ])),
+            RData::A(Ipv4Addr::from_str("0.0.0.0").unwrap()),
+            RData::AAAA(Ipv6Addr::from_str("::").unwrap()),
+            RData::SRV(SRV::new(
+                1,
+                2,
+                3,
+                Name::from_str("www.example.com").unwrap(),
+            )),
+        ];
+
+        unordered.sort();
+        assert_eq!(ordered, unordered);
+    }
+
+    #[test]
+    fn test_read() {
+        for (test_pass, (expect, binary)) in get_data().into_iter().enumerate() {
+            println!("test {}: {:?}", test_pass, binary);
+            let length = binary.len() as u16; // pre exclusive borrow
+            let mut decoder = BinDecoder::new(&binary);
+
+            assert_eq!(
+                RData::read(
+                    &mut decoder,
+                    record_type_from_rdata(&expect),
+                    Restrict::new(length)
+                )
+                .unwrap(),
+                expect
+            );
+        }
+    }
+
+    fn record_type_from_rdata(rdata: &RData) -> crate::rr::record_type::RecordType {
+        match *rdata {
+            RData::A(..) => RecordType::A,
+            RData::AAAA(..) => RecordType::AAAA,
+            RData::ANAME(..) => RecordType::ANAME,
+            RData::CAA(..) => RecordType::CAA,
+            RData::CNAME(..) => RecordType::CNAME,
+            RData::MX(..) => RecordType::MX,
+            RData::NAPTR(..) => RecordType::NAPTR,
+            RData::NS(..) => RecordType::NS,
+            RData::NULL(..) => RecordType::NULL,
+            RData::OPENPGPKEY(..) => RecordType::OPENPGPKEY,
+            RData::OPT(..) => RecordType::OPT,
+            RData::PTR(..) => RecordType::PTR,
+            RData::SOA(..) => RecordType::SOA,
+            RData::SRV(..) => RecordType::SRV,
+            RData::SSHFP(..) => RecordType::SSHFP,
+            RData::TLSA(..) => RecordType::TLSA,
+            RData::TXT(..) => RecordType::TXT,
+            #[cfg(feature = "dnssec")]
+            RData::DNSSEC(ref rdata) => RecordType::DNSSEC(rdata.to_record_type()),
+            RData::Unknown { code, .. } => RecordType::Unknown(code),
+            RData::ZERO => RecordType::ZERO,
+        }
+    }
+
+    #[test]
+    fn test_write_to() {
+        test_emit_data_set(get_data(), |e, d| d.emit(e));
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/record_type.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/record_type.rs
new file mode 100644
index 0000000..cfd3e8c
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/record_type.rs
@@ -0,0 +1,443 @@
+/*
+ * Copyright (C) 2015-2019 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! record type definitions
+
+use std::cmp::Ordering;
+use std::convert::From;
+use std::fmt;
+use std::fmt::{Display, Formatter};
+use std::str::FromStr;
+
+use crate::error::*;
+use crate::serialize::binary::*;
+
+#[cfg(feature = "dnssec")]
+use crate::rr::dnssec::rdata::DNSSECRecordType;
+
+// TODO: adopt proper restrictions on usage: https://tools.ietf.org/html/rfc6895 section 3.1
+//  add the data TYPEs, QTYPEs, and Meta-TYPEs
+//
+
+/// The type of the resource record.
+///
+/// This specifies the type of data in the RData field of the Resource Record
+#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
+#[allow(dead_code)]
+pub enum RecordType {
+    /// RFC 1035[1] IPv4 Address record
+    A,
+    /// RFC 3596[2] IPv6 address record
+    AAAA,
+    /// ANAME draft-ietf-dnsop-aname
+    ANAME,
+    //  AFSDB,      //	18	RFC 1183	AFS database record
+    /// RFC 1035[1] All cached records, aka ANY
+    ANY,
+    //  APL,        //	42	RFC 3123	Address Prefix List
+    /// RFC 1035[1] Authoritative Zone Transfer
+    AXFR,
+    /// RFC 6844 Certification Authority Authorization
+    CAA,
+    //  CERT,       //	37	RFC 4398	Certificate record
+    /// RFC 1035[1] Canonical name record
+    CNAME,
+    //  DHCID,      //	49	RFC 4701	DHCP identifier
+    //  DNAME,      //	39	RFC 2672	Delegation Name
+    //  HIP,        //	55	RFC 5205	Host Identity Protocol
+    //  IPSECKEY,   //	45	RFC 4025	IPsec Key
+    /// RFC 1996 Incremental Zone Transfer
+    IXFR,
+    //  KX,         //	36	RFC 2230	Key eXchanger record
+    //  LOC,        //	29	RFC 1876	Location record
+    /// RFC 1035[1] Mail exchange record
+    MX,
+    /// RFC 3403 Naming Authority Pointer
+    NAPTR,
+    /// RFC 1035[1] Name server record
+    NS,
+    /// RFC 1035[1] Null server record, for testing
+    NULL,
+    /// RFC 7929	OpenPGP public key
+    OPENPGPKEY,
+    /// RFC 6891	Option
+    OPT,
+    /// RFC 1035[1] Pointer record
+    PTR,
+    //  RP,         //	17	RFC 1183	Responsible person
+    /// RFC 1035[1] and RFC 2308[9]	Start of [a zone of] authority record
+    SOA,
+    /// RFC 2782 Service locator
+    SRV,
+    /// RFC 4255 SSH Public Key Fingerprint
+    SSHFP,
+    //  TA,         //	32768	N/A	DNSSEC Trust Authorities
+    //  TKEY,       //	249	RFC 2930	Secret key record
+    /// RFC 6698 TLSA certificate association
+    TLSA,
+    //  TSIG,       //	250	RFC 2845	Transaction Signature
+    /// RFC 1035[1] Text record
+    TXT,
+
+    /// A DNSSEC- or SIG(0)- specific record type.
+    ///
+    /// These types are in `DNSSECRecordType` to make them easy to disable when
+    /// crypto functionality isn't needed.
+    #[cfg(feature = "dnssec")]
+    DNSSEC(DNSSECRecordType),
+
+    /// Unknown Record type, or unsupported
+    Unknown(u16),
+
+    /// This corresponds to a record type of 0, unspecified
+    ZERO,
+}
+
+impl RecordType {
+    /// Returns true if this is an ANY
+    #[inline]
+    pub fn is_any(self) -> bool {
+        self == RecordType::ANY
+    }
+
+    /// Returns true if this is a CNAME
+    #[inline]
+    pub fn is_cname(self) -> bool {
+        self == RecordType::CNAME
+    }
+
+    /// Returns true if this is an SRV
+    #[inline]
+    pub fn is_srv(self) -> bool {
+        self == RecordType::SRV
+    }
+
+    /// Returns true if this is an A or an AAAA record
+    #[inline]
+    pub fn is_ip_addr(self) -> bool {
+        match self {
+            RecordType::A | RecordType::AAAA => true,
+            _ => false,
+        }
+    }
+}
+
+impl FromStr for RecordType {
+    type Err = ProtoError;
+
+    /// Convert `&str` to `RecordType`
+    ///
+    /// ```
+    /// use std::str::FromStr;
+    /// use trust_dns_proto::rr::record_type::RecordType;
+    ///
+    /// let var: RecordType = RecordType::from_str("A").unwrap();
+    /// assert_eq!(RecordType::A, var);
+    /// ```
+    fn from_str(str: &str) -> ProtoResult<Self> {
+        // TODO missing stuff?
+        match str {
+            "A" => Ok(RecordType::A),
+            "AAAA" => Ok(RecordType::AAAA),
+            "ANAME" => Ok(RecordType::ANAME),
+            "CAA" => Ok(RecordType::CAA),
+            "CNAME" => Ok(RecordType::CNAME),
+            "NULL" => Ok(RecordType::NULL),
+            "MX" => Ok(RecordType::MX),
+            "NAPTR" => Ok(RecordType::NAPTR),
+            "NS" => Ok(RecordType::NS),
+            "OPENPGPKEY" => Ok(RecordType::OPENPGPKEY),
+            "PTR" => Ok(RecordType::PTR),
+            "SOA" => Ok(RecordType::SOA),
+            "SRV" => Ok(RecordType::SRV),
+            "SSHFP" => Ok(RecordType::SSHFP),
+            "TLSA" => Ok(RecordType::TLSA),
+            "TXT" => Ok(RecordType::TXT),
+            "ANY" | "*" => Ok(RecordType::ANY),
+            "AXFR" => Ok(RecordType::AXFR),
+            #[cfg(feature = "dnssec")]
+            "DNSKEY" | "DS" | "KEY" | "NSEC" | "NSEC3" | "NSEC3PARAM" | "RRSIG" | "SIG" => {
+                Ok(RecordType::DNSSEC(str.parse()?))
+            }
+            _ => Err(ProtoErrorKind::UnknownRecordTypeStr(str.to_string()).into()),
+        }
+    }
+}
+
+impl From<u16> for RecordType {
+    /// Convert from `u16` to `RecordType`
+    ///
+    /// ```
+    /// use trust_dns_proto::rr::record_type::RecordType;
+    ///
+    /// let var = RecordType::from(1);
+    /// assert_eq!(RecordType::A, var);
+    /// ```
+    fn from(value: u16) -> Self {
+        match value {
+            1 => RecordType::A,
+            28 => RecordType::AAAA,
+            // TODO: wrong value here, see https://github.com/bluejekyll/trust-dns/issues/723
+            65305 => RecordType::ANAME,
+            255 => RecordType::ANY,
+            252 => RecordType::AXFR,
+            257 => RecordType::CAA,
+            5 => RecordType::CNAME,
+            0 => RecordType::ZERO,
+            15 => RecordType::MX,
+            35 => RecordType::NAPTR,
+            2 => RecordType::NS,
+            10 => RecordType::NULL,
+            61 => RecordType::OPENPGPKEY,
+            41 => RecordType::OPT,
+            12 => RecordType::PTR,
+            6 => RecordType::SOA,
+            33 => RecordType::SRV,
+            44 => RecordType::SSHFP,
+            52 => RecordType::TLSA,
+            16 => RecordType::TXT,
+            #[cfg(feature = "dnssec")]
+            48/*DNSKEY*/ |
+            43/*DS*/ |
+            25/*KEY*/ |
+            47/*NSEC*/|
+            50/*NSEC3*/|
+            51/*NSEC3PARAM*/|
+            46/*RRSIG*/|
+            24/*SIG*/ => RecordType::DNSSEC(DNSSECRecordType::from(value)),
+            // all unknown record types
+            _ => RecordType::Unknown(value),
+        }
+    }
+}
+
+impl BinEncodable for RecordType {
+    fn emit(&self, encoder: &mut BinEncoder) -> ProtoResult<()> {
+        encoder.emit_u16((*self).into())
+    }
+}
+
+impl<'r> BinDecodable<'r> for RecordType {
+    fn read(decoder: &mut BinDecoder) -> ProtoResult<Self> {
+        decoder
+            .read_u16()
+            .map(
+                Restrict::unverified, /*RecordType is safe with any u16*/
+            )
+            .map(Self::from)
+    }
+}
+
+// TODO make these a macro...
+
+/// Convert from `RecordType` to `&str`
+///
+/// ```
+/// use std::convert::From;
+/// use trust_dns_proto::rr::record_type::RecordType;
+///
+/// let var: &'static str = From::from(RecordType::A);
+/// assert_eq!("A", var);
+///
+/// let var: &'static str = RecordType::A.into();
+/// assert_eq!("A", var);
+/// ```
+impl From<RecordType> for &'static str {
+    fn from(rt: RecordType) -> &'static str {
+        match rt {
+            RecordType::A => "A",
+            RecordType::AAAA => "AAAA",
+            RecordType::ANAME => "ANAME",
+            RecordType::ANY => "ANY",
+            RecordType::AXFR => "AXFR",
+            RecordType::CAA => "CAA",
+            RecordType::CNAME => "CNAME",
+            RecordType::ZERO => "",
+            RecordType::IXFR => "IXFR",
+            RecordType::MX => "MX",
+            RecordType::NAPTR => "NAPTR",
+            RecordType::NS => "NS",
+            RecordType::NULL => "NULL",
+            RecordType::OPENPGPKEY => "OPENPGPKEY",
+            RecordType::OPT => "OPT",
+            RecordType::PTR => "PTR",
+            RecordType::SOA => "SOA",
+            RecordType::SRV => "SRV",
+            RecordType::SSHFP => "SSHFP",
+            RecordType::TLSA => "TLSA",
+            RecordType::TXT => "TXT",
+            #[cfg(feature = "dnssec")]
+            RecordType::DNSSEC(rt) => rt.into(),
+            RecordType::Unknown(_) => "Unknown",
+        }
+    }
+}
+
+/// Convert from `RecordType` to `u16`
+///
+/// ```
+/// use std::convert::From;
+/// use trust_dns_proto::rr::record_type::RecordType;
+///
+/// let var: u16 = RecordType::A.into();
+/// assert_eq!(1, var);
+/// ```
+impl From<RecordType> for u16 {
+    fn from(rt: RecordType) -> Self {
+        match rt {
+            RecordType::A => 1,
+            RecordType::AAAA => 28,
+            // TODO: wrong value here, see https://github.com/bluejekyll/trust-dns/issues/723
+            RecordType::ANAME => 65305,
+            RecordType::ANY => 255,
+            RecordType::AXFR => 252,
+            RecordType::CAA => 257,
+            RecordType::CNAME => 5,
+            RecordType::ZERO => 0,
+            RecordType::IXFR => 251,
+            RecordType::MX => 15,
+            RecordType::NAPTR => 35,
+            RecordType::NS => 2,
+            RecordType::NULL => 10,
+            RecordType::OPENPGPKEY => 61,
+            RecordType::OPT => 41,
+            RecordType::PTR => 12,
+            RecordType::SOA => 6,
+            RecordType::SRV => 33,
+            RecordType::SSHFP => 44,
+            RecordType::TLSA => 52,
+            RecordType::TXT => 16,
+            #[cfg(feature = "dnssec")]
+            RecordType::DNSSEC(rt) => rt.into(),
+            RecordType::Unknown(code) => code,
+        }
+    }
+}
+
+/// [Canonical DNS Name Order](https://tools.ietf.org/html/rfc4034#section-6)
+impl PartialOrd<RecordType> for RecordType {
+    fn partial_cmp(&self, other: &RecordType) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+/// [Canonical DNS Name Order](https://tools.ietf.org/html/rfc4034#section-6)
+impl Ord for RecordType {
+    fn cmp(&self, other: &Self) -> Ordering {
+        u16::from(*self).cmp(&u16::from(*other))
+    }
+}
+
+impl Display for RecordType {
+    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
+        f.write_str(Into::<&str>::into(*self))
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    #![allow(clippy::dbg_macro, clippy::print_stdout)]
+
+    use super::*;
+
+    #[test]
+    fn test_order() {
+        let ordered = vec![
+            RecordType::A,
+            RecordType::NS,
+            RecordType::CNAME,
+            RecordType::SOA,
+            RecordType::NULL,
+            RecordType::PTR,
+            RecordType::MX,
+            RecordType::TXT,
+            RecordType::AAAA,
+            RecordType::SRV,
+            RecordType::AXFR,
+            RecordType::ANY,
+        ];
+
+        let mut unordered = vec![
+            RecordType::ANY,
+            RecordType::NULL,
+            RecordType::AXFR,
+            RecordType::A,
+            RecordType::NS,
+            RecordType::SOA,
+            RecordType::SRV,
+            RecordType::PTR,
+            RecordType::MX,
+            RecordType::CNAME,
+            RecordType::TXT,
+            RecordType::AAAA,
+        ];
+
+        unordered.sort();
+
+        for rtype in unordered.clone() {
+            println!("u16 for {:?}: {}", rtype, u16::from(rtype));
+        }
+
+        assert_eq!(ordered, unordered);
+    }
+
+    /// Check that all record type names parse into unique `RecordType` instances,
+    /// and can be converted back into the same name.
+    #[test]
+    fn test_record_type_parse() {
+        let record_names = &[
+            "A",
+            "AAAA",
+            "ANAME",
+            "CAA",
+            "CNAME",
+            "NULL",
+            "MX",
+            "NAPTR",
+            "NS",
+            "OPENPGPKEY",
+            "PTR",
+            "SOA",
+            "SRV",
+            "SSHFP",
+            "TLSA",
+            "TXT",
+            "ANY",
+            "AXFR",
+        ];
+
+        #[cfg(feature = "dnssec")]
+        let dnssec_record_names = &[
+            "DNSKEY",
+            "DS",
+            "KEY",
+            "NSEC",
+            "NSEC3",
+            "NSEC3PARAM",
+            "RRSIG",
+            "SIG",
+        ];
+        #[cfg(not(feature = "dnssec"))]
+        let dnssec_record_names = &[];
+
+        let mut rtypes = std::collections::HashSet::new();
+        for name in record_names.iter().chain(dnssec_record_names) {
+            let rtype: RecordType = name.parse().unwrap();
+            assert_eq!(rtype.to_string().as_str(), *name);
+            assert!(rtypes.insert(rtype));
+        }
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/resource.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/resource.rs
new file mode 100644
index 0000000..5dac6d0
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/resource.rs
@@ -0,0 +1,488 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! resource record implementation
+
+use std::cmp::Ordering;
+
+use crate::error::*;
+use crate::rr::dns_class::DNSClass;
+use crate::rr::rdata::NULL;
+#[allow(deprecated)]
+use crate::rr::IntoRecordSet;
+use crate::rr::Name;
+use crate::rr::RData;
+use crate::rr::RecordSet;
+use crate::rr::RecordType;
+use crate::serialize::binary::*;
+
+/// Resource records are storage value in DNS, into which all key/value pair data is stored.
+///
+/// [RFC 1035](https://tools.ietf.org/html/rfc1035), DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION, November 1987
+///
+/// ```text
+/// 4.1.3. Resource record format
+///
+/// The answer, authority, and additional sections all share the same
+/// format: a variable number of resource records, where the number of
+/// records is specified in the corresponding count field in the header.
+/// Each resource record has the following format:
+///                                     1  1  1  1  1  1
+///       0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///     |                                               |
+///     /                                               /
+///     /                      NAME                     /
+///     |                                               |
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///     |                      TYPE                     |
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///     |                     CLASS                     |
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///     |                      TTL                      |
+///     |                                               |
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///     |                   RDLENGTH                    |
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
+///     /                     RDATA                     /
+///     /                                               /
+///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+///
+/// ```
+#[derive(Eq, Ord, Debug, Clone)]
+pub struct Record {
+    name_labels: Name,
+    rr_type: RecordType,
+    dns_class: DNSClass,
+    ttl: u32,
+    rdata: RData,
+}
+
+impl Default for Record {
+    fn default() -> Self {
+        Record {
+            // TODO: these really should all be Optionals, I was lazy.
+            name_labels: Name::new(),
+            rr_type: RecordType::A,
+            dns_class: DNSClass::IN,
+            ttl: 0,
+            rdata: RData::NULL(NULL::new()),
+        }
+    }
+}
+
+impl Record {
+    /// Creates a default record, use the setters to build a more useful object.
+    ///
+    /// There are no optional elements in this object, defaults are an empty name, type A, class IN,
+    /// ttl of 0 and the 0.0.0.0 ip address.
+    pub fn new() -> Record {
+        Default::default()
+    }
+
+    /// Create a record with the specified initial values.
+    ///
+    /// # Arguments
+    ///
+    /// * `name` - name of the resource records
+    /// * `rr_type` - the record type
+    /// * `ttl` - time-to-live is the amount of time this record should be cached before refreshing
+    pub fn with(name: Name, rr_type: RecordType, ttl: u32) -> Record {
+        Record {
+            name_labels: name,
+            rr_type,
+            dns_class: DNSClass::IN,
+            ttl,
+            rdata: RData::NULL(NULL::new()),
+        }
+    }
+
+    /// Create a record with the specified initial values.
+    ///
+    /// # Arguments
+    ///
+    /// * `name` - name of the resource records
+    /// * `ttl` - time-to-live is the amount of time this record should be cached before refreshing
+    /// * `rdata` - record data to associate with the Record
+    pub fn from_rdata(name: Name, ttl: u32, rdata: RData) -> Record {
+        Record {
+            name_labels: name,
+            rr_type: rdata.to_record_type(),
+            dns_class: DNSClass::IN,
+            ttl,
+            rdata,
+        }
+    }
+
+    /// ```text
+    /// NAME            a domain name to which this resource record pertains.
+    /// ```
+    pub fn set_name(&mut self, name: Name) -> &mut Self {
+        self.name_labels = name;
+        self
+    }
+
+    /// ```text
+    /// TYPE            two octets containing one of the RR type codes.  This
+    ///                 field specifies the meaning of the data in the RDATA
+    ///                 field.
+    /// ```
+    // #[deprecated(note = "use `Record::set_record_type`")]
+    pub fn set_rr_type(&mut self, rr_type: RecordType) -> &mut Self {
+        self.rr_type = rr_type;
+        self
+    }
+
+    /// ```text
+    /// TYPE            two octets containing one of the RR type codes.  This
+    ///                 field specifies the meaning of the data in the RDATA
+    ///                 field.
+    /// ```
+    pub fn set_record_type(&mut self, rr_type: RecordType) -> &mut Self {
+        self.rr_type = rr_type;
+        self
+    }
+
+    /// ```text
+    /// CLASS           two octets which specify the class of the data in the
+    ///                 RDATA field.
+    /// ```
+    pub fn set_dns_class(&mut self, dns_class: DNSClass) -> &mut Self {
+        self.dns_class = dns_class;
+        self
+    }
+
+    /// ```text
+    /// TTL             a 32 bit unsigned integer that specifies the time
+    ///                 interval (in seconds) that the resource record may be
+    ///                 cached before it should be discarded.  Zero values are
+    ///                 interpreted to mean that the RR can only be used for the
+    ///                 transaction in progress, and should not be cached.
+    /// ```
+    pub fn set_ttl(&mut self, ttl: u32) -> &mut Self {
+        self.ttl = ttl;
+        self
+    }
+
+    /// ```text
+    /// RDATA           a variable length string of octets that describes the
+    ///                 resource.  The format of this information varies
+    ///                 according to the TYPE and CLASS of the resource record.
+    ///                 For example, the if the TYPE is A and the CLASS is IN,
+    ///                 the RDATA field is a 4 octet ARPA Internet address.
+    /// ```
+    pub fn set_rdata(&mut self, rdata: RData) -> &mut Self {
+        self.rdata = rdata;
+        self
+    }
+
+    /// Returns the name of the record
+    pub fn name(&self) -> &Name {
+        &self.name_labels
+    }
+
+    /// Returns the type of the RData in the record
+    // #[deprecated(note = "use `Record::record_type`")]
+    pub fn rr_type(&self) -> RecordType {
+        self.rr_type
+    }
+
+    /// Returns the type of the RecordData in the record
+    pub fn record_type(&self) -> RecordType {
+        self.rr_type
+    }
+
+    /// Returns the DNSClass of the Record, generally IN fro internet
+    pub fn dns_class(&self) -> DNSClass {
+        self.dns_class
+    }
+
+    /// Returns the time-to-live of the record, for caching purposes
+    pub fn ttl(&self) -> u32 {
+        self.ttl
+    }
+
+    /// Returns the Record Data, i.e. the record information
+    pub fn rdata(&self) -> &RData {
+        &self.rdata
+    }
+
+    /// Returns a mutable reference to the Record Data
+    pub fn rdata_mut(&mut self) -> &mut RData {
+        &mut self.rdata
+    }
+
+    /// Returns the RData consuming the Record
+    pub fn unwrap_rdata(self) -> RData {
+        self.rdata
+    }
+}
+
+#[allow(deprecated)]
+impl IntoRecordSet for Record {
+    fn into_record_set(self) -> RecordSet {
+        RecordSet::from(self)
+    }
+}
+
+impl BinEncodable for Record {
+    fn emit(&self, encoder: &mut BinEncoder) -> ProtoResult<()> {
+        self.name_labels.emit(encoder)?;
+        self.rr_type.emit(encoder)?;
+        self.dns_class.emit(encoder)?;
+
+        encoder.emit_u32(self.ttl)?;
+
+        // place the RData length
+        let place = encoder.place::<u16>()?;
+
+        // write the RData
+        self.rdata.emit(encoder)?;
+
+        // get the length written
+        let len = encoder.len_since_place(&place);
+        assert!(len <= u16::max_value() as usize);
+
+        // replace the location with the length
+        place.replace(encoder, len as u16)?;
+        Ok(())
+    }
+}
+
+impl<'r> BinDecodable<'r> for Record {
+    /// parse a resource record line example:
+    ///  WARNING: the record_bytes is 100% consumed and destroyed in this parsing process
+    fn read(decoder: &mut BinDecoder<'r>) -> ProtoResult<Record> {
+        // NAME            an owner name, i.e., the name of the node to which this
+        //                 resource record pertains.
+        let name_labels: Name = Name::read(decoder)?;
+
+        // TYPE            two octets containing one of the RR TYPE codes.
+        let record_type: RecordType = RecordType::read(decoder)?;
+
+        // CLASS           two octets containing one of the RR CLASS codes.
+        let class: DNSClass = if record_type == RecordType::OPT {
+            // verify that the OPT record is Root
+            if !name_labels.is_root() {
+                return Err(ProtoErrorKind::EdnsNameNotRoot(name_labels).into());
+            }
+
+            //  DNS Class is overloaded for OPT records in EDNS - RFC 6891
+            DNSClass::for_opt(
+                decoder.read_u16()?.unverified(/*restricted to a min of 512 in for_opt*/),
+            )
+        } else {
+            DNSClass::read(decoder)?
+        };
+
+        // TTL             a 32 bit signed integer that specifies the time interval
+        //                that the resource record may be cached before the source
+        //                of the information should again be consulted.  Zero
+        //                values are interpreted to mean that the RR can only be
+        //                used for the transaction in progress, and should not be
+        //                cached.  For example, SOA records are always distributed
+        //                with a zero TTL to prohibit caching.  Zero values can
+        //                also be used for extremely volatile data.
+        // note: u32 seems more accurate given that it can only be positive
+        let ttl: u32 = decoder.read_u32()?.unverified(/*any u32 is valid*/);
+
+        // RDLENGTH        an unsigned 16 bit integer that specifies the length in
+        //                octets of the RDATA field.
+        let rd_length: u16 = decoder
+            .read_u16()?
+            .verify_unwrap(|u| (*u as usize) <= decoder.len())
+            .map_err(|_| {
+                ProtoError::from("rdata length too large for remaining bytes, need: {} remain: {}")
+            })?;
+
+        // this is to handle updates, RFC 2136, which uses 0 to indicate certain aspects of
+        //  pre-requisites
+        let rdata: RData = if rd_length == 0 {
+            RData::NULL(NULL::new())
+        } else {
+            // RDATA           a variable length string of octets that describes the
+            //                resource.  The format of this information varies
+            //                according to the TYPE and CLASS of the resource record.
+            // Adding restrict to the rdata length because it's used for many calculations later
+            //  and must be validated before hand
+            RData::read(decoder, record_type, Restrict::new(rd_length))?
+        };
+
+        Ok(Record {
+            name_labels,
+            rr_type: record_type,
+            dns_class: class,
+            ttl,
+            rdata,
+        })
+    }
+}
+
+impl PartialEq for Record {
+    /// Equality or records, as defined by
+    ///  [RFC 2136](https://tools.ietf.org/html/rfc2136), DNS Update, April 1997
+    ///
+    /// ```text
+    ///   1.1.1. Two RRs are considered equal if their NAME, CLASS, TYPE,
+    ///   RDLENGTH and RDATA fields are equal.  Note that the time-to-live
+    ///   (TTL) field is explicitly excluded from the comparison.
+    ///
+    ///   1.1.2. The rules for comparison of character strings in names are
+    ///   specified in [RFC1035 2.3.3]. i.e. case insensitive
+    /// ```
+    fn eq(&self, other: &Self) -> bool {
+        // self == other && // the same pointer
+        self.name_labels == other.name_labels
+            && self.rr_type == other.rr_type
+            && self.dns_class == other.dns_class
+            && self.rdata == other.rdata
+    }
+}
+
+/// returns the value of the compare if the items are greater or lesser, but continues on equal
+macro_rules! compare_or_equal {
+    ($x:ident, $y:ident, $z:ident) => {
+        match $x.$z.partial_cmp(&$y.$z) {
+            o @ Some(Ordering::Less) | o @ Some(Ordering::Greater) => return o,
+            None => return None,
+            Some(Ordering::Equal) => (),
+        }
+    };
+}
+
+impl PartialOrd<Record> for Record {
+    /// Canonical ordering as defined by
+    ///  [RFC 4034](https://tools.ietf.org/html/rfc4034#section-6), DNSSEC Resource Records, March 2005
+    ///
+    /// ```text
+    /// 6.2.  Canonical RR Form
+    ///
+    ///    For the purposes of DNS security, the canonical form of an RR is the
+    ///    wire format of the RR where:
+    ///
+    ///    1.  every domain name in the RR is fully expanded (no DNS name
+    ///        compression) and fully qualified;
+    ///
+    ///    2.  all uppercase US-ASCII letters in the owner name of the RR are
+    ///        replaced by the corresponding lowercase US-ASCII letters;
+    ///
+    ///    3.  if the type of the RR is NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR,
+    ///        HINFO, MINFO, MX, HINFO, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX,
+    ///        SRV, DNAME, A6, RRSIG, or NSEC, all uppercase US-ASCII letters in
+    ///        the DNS names contained within the RDATA are replaced by the
+    ///        corresponding lowercase US-ASCII letters;
+    ///
+    ///    4.  if the owner name of the RR is a wildcard name, the owner name is
+    ///        in its original unexpanded form, including the "*" label (no
+    ///        wildcard substitution); and
+    ///
+    ///    5.  the RR's TTL is set to its original value as it appears in the
+    ///        originating authoritative zone or the Original TTL field of the
+    ///        covering RRSIG RR.
+    /// ```
+    fn partial_cmp(&self, other: &Record) -> Option<Ordering> {
+        // TODO: given that the ordering of Resource Records is dependent on it's binary form and this
+        //  method will be used during insertion sort or similar, we should probably do this
+        //  conversion once somehow and store it separately. Or should the internal storage of all
+        //  resource records be maintained in binary?
+
+        compare_or_equal!(self, other, name_labels);
+        compare_or_equal!(self, other, rr_type);
+        compare_or_equal!(self, other, dns_class);
+        compare_or_equal!(self, other, ttl);
+        compare_or_equal!(self, other, rdata);
+
+        // got here, means they are equal
+        Some(Ordering::Equal)
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    #![allow(clippy::dbg_macro, clippy::print_stdout)]
+
+    use std::cmp::Ordering;
+    use std::net::Ipv4Addr;
+    use std::str::FromStr;
+
+    use super::*;
+    use crate::rr::dns_class::DNSClass;
+    use crate::rr::record_data::RData;
+    use crate::rr::record_type::RecordType;
+    use crate::rr::Name;
+    #[allow(clippy::useless_attribute)]
+    #[allow(unused)]
+    use crate::serialize::binary::*;
+
+    #[test]
+    fn test_emit_and_read() {
+        let mut record = Record::new();
+        record
+            .set_name(Name::from_str("www.example.com").unwrap())
+            .set_rr_type(RecordType::A)
+            .set_dns_class(DNSClass::IN)
+            .set_ttl(5)
+            .set_rdata(RData::A(Ipv4Addr::new(192, 168, 0, 1)));
+
+        let mut vec_bytes: Vec<u8> = Vec::with_capacity(512);
+        {
+            let mut encoder = BinEncoder::new(&mut vec_bytes);
+            record.emit(&mut encoder).unwrap();
+        }
+
+        let mut decoder = BinDecoder::new(&vec_bytes);
+
+        let got = Record::read(&mut decoder).unwrap();
+
+        assert_eq!(got, record);
+    }
+
+    #[test]
+    fn test_order() {
+        let mut record = Record::new();
+        record
+            .set_name(Name::from_str("www.example.com").unwrap())
+            .set_rr_type(RecordType::A)
+            .set_dns_class(DNSClass::IN)
+            .set_ttl(5)
+            .set_rdata(RData::A(Ipv4Addr::new(192, 168, 0, 1)));
+
+        let mut greater_name = record.clone();
+        greater_name.set_name(Name::from_str("zzz.example.com").unwrap());
+
+        let mut greater_type = record.clone();
+        greater_type.set_rr_type(RecordType::AAAA);
+
+        let mut greater_class = record.clone();
+        greater_class.set_dns_class(DNSClass::NONE);
+
+        let mut greater_rdata = record.clone();
+        greater_rdata.set_rdata(RData::A(Ipv4Addr::new(192, 168, 0, 255)));
+
+        let compares = vec![
+            (&record, &greater_name),
+            (&record, &greater_type),
+            (&record, &greater_class),
+            (&record, &greater_rdata),
+        ];
+
+        assert_eq!(record.clone(), record.clone());
+        for (r, g) in compares {
+            println!("r, g: {:?}, {:?}", r, g);
+            assert_eq!(r.cmp(g), Ordering::Less);
+        }
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rr_set.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rr_set.rs
new file mode 100644
index 0000000..e69fe0f
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/rr/rr_set.rs
@@ -0,0 +1,936 @@
+// Copyright 2015-2019 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+use std::iter::Chain;
+use std::slice::Iter;
+use std::vec;
+
+use log::info;
+
+use crate::rr::{DNSClass, Name, RData, Record, RecordType};
+
+#[cfg(feature = "dnssec")]
+use crate::rr::dnssec::SupportedAlgorithms;
+
+/// Set of resource records associated to a name and type
+#[derive(Clone, Debug, PartialEq)]
+pub struct RecordSet {
+    name: Name,
+    record_type: RecordType,
+    dns_class: DNSClass,
+    ttl: u32,
+    records: Vec<Record>,
+    rrsigs: Vec<Record>,
+    serial: u32, // serial number at which this record was modified
+}
+
+impl RecordSet {
+    /// Creates a new Resource Record Set.
+    ///
+    /// # Arguments
+    ///
+    /// * `name` - The label for the `RecordSet`
+    /// * `record_type` - `RecordType` of this `RecordSet`, all records in the `RecordSet` must be of the
+    ///                   specified `RecordType`.
+    /// * `serial` - current serial number of the `SOA` record, this is to be used for `IXFR` and
+    ///              signing for DNSSec after updates.
+    ///
+    /// # Return value
+    ///
+    /// The newly created Resource Record Set
+    /// TODO: make all cloned params pass by value
+    pub fn new(name: &Name, record_type: RecordType, serial: u32) -> Self {
+        RecordSet {
+            name: name.clone(),
+            record_type,
+            dns_class: DNSClass::IN,
+            ttl: 0,
+            records: Vec::new(),
+            rrsigs: Vec::new(),
+            serial,
+        }
+    }
+
+    /// Creates a new Resource Record Set.
+    ///
+    /// # Arguments
+    ///
+    /// * `name` - The label for the `RecordSet`
+    /// * `record_type` - `RecordType` of this `RecordSet`, all records in the `RecordSet` must be of the
+    ///                   specified `RecordType`.
+    /// * `ttl` - time-to-live for the `RecordSet` in seconds.
+    ///
+    /// # Return value
+    ///
+    /// The newly created Resource Record Set
+    /// TODO: make all cloned params pass by value
+    pub fn with_ttl(name: Name, record_type: RecordType, ttl: u32) -> Self {
+        RecordSet {
+            name,
+            record_type,
+            dns_class: DNSClass::IN,
+            ttl,
+            records: Vec::new(),
+            rrsigs: Vec::new(),
+            serial: 0,
+        }
+    }
+
+    /// # Return value
+    ///
+    /// Label of the Resource Record Set
+    pub fn name(&self) -> &Name {
+        &self.name
+    }
+
+    /// # Return value
+    ///
+    /// `RecordType` of the Resource Record Set
+    pub fn record_type(&self) -> RecordType {
+        self.record_type
+    }
+
+    /// Sets the DNSClass to the specified value
+    ///
+    /// This will traverse every record and associate with it the specified dns_class
+    pub fn set_dns_class(&mut self, dns_class: DNSClass) {
+        self.dns_class = dns_class;
+        for r in &mut self.records {
+            r.set_dns_class(dns_class);
+        }
+    }
+
+    /// Returns the `DNSClass` of the RecordSet
+    pub fn dns_class(&self) -> DNSClass {
+        self.dns_class
+    }
+
+    /// Sets the TTL, in seconds, to the specified value
+    ///
+    /// This will traverse every record and associate with it the specified ttl
+    pub fn set_ttl(&mut self, ttl: u32) {
+        self.ttl = ttl;
+        for r in &mut self.records {
+            r.set_ttl(ttl);
+        }
+    }
+
+    /// Returns the time-to-live for the record.
+    ///
+    /// # Return value
+    ///
+    /// TTL, time-to-live, of the Resource Record Set, this is the maximum length of time that an
+    /// RecordSet should be cached.
+    pub fn ttl(&self) -> u32 {
+        self.ttl
+    }
+
+    /// Returns a Vec of all records in the set.
+    ///
+    /// # Arguments
+    ///
+    /// * `and_rrsigs` - if true, RRSIGs will be returned if they exist
+    /// * `supported_algorithms` - the RRSIGs will be filtered by the set of supported_algorithms,
+    ///                            and then only the maximal RRSIG algorithm will be returned.
+    #[cfg(feature = "dnssec")]
+    pub fn records(
+        &self,
+        and_rrsigs: bool,
+        supported_algorithms: SupportedAlgorithms,
+    ) -> RrsetRecords {
+        if and_rrsigs {
+            self.records_with_rrsigs(supported_algorithms)
+        } else {
+            self.records_without_rrsigs()
+        }
+    }
+
+    /// Returns a Vec of all records in the set, with RRSIGs, if present.
+    ///
+    /// # Arguments
+    ///
+    /// * `supported_algorithms` - the RRSIGs will be filtered by the set of supported_algorithms,
+    ///                            and then only the maximal RRSIG algorithm will be returned.
+    #[cfg(feature = "dnssec")]
+    pub fn records_with_rrsigs(&self, supported_algorithms: SupportedAlgorithms) -> RrsetRecords {
+        if self.records.is_empty() {
+            RrsetRecords::Empty
+        } else {
+            let rrsigs = RrsigsByAlgorithms {
+                rrsigs: self.rrsigs.iter(),
+                supported_algorithms,
+            };
+            RrsetRecords::RecordsAndRrsigs(RecordsAndRrsigsIter(self.records.iter().chain(rrsigs)))
+        }
+    }
+
+    /// Returns a Vec of all records in the set, without any RRSIGs.
+    pub fn records_without_rrsigs(&self) -> RrsetRecords {
+        if self.records.is_empty() {
+            RrsetRecords::Empty
+        } else {
+            RrsetRecords::RecordsOnly(self.records.iter())
+        }
+    }
+
+    /// Returns an iterator over the records in the set
+    #[deprecated(note = "see `records_without_rrsigs`")]
+    pub fn iter(&self) -> Iter<Record> {
+        self.records.iter()
+    }
+
+    /// Returns true if there are no records in this set
+    pub fn is_empty(&self) -> bool {
+        self.records.is_empty()
+    }
+
+    /// Returns the serial number at which the record was updated.
+    pub fn serial(&self) -> u32 {
+        self.serial
+    }
+
+    /// Returns a slice of all the Records signatures in the RecordSet
+    pub fn rrsigs(&self) -> &[Record] {
+        &self.rrsigs
+    }
+
+    /// Inserts a Signature for the Record set
+    ///
+    /// Many can be associated with the RecordSet. Once added, the RecordSet should not be changed
+    ///
+    /// # Arguments
+    ///
+    /// * `rrsig` - A signature which covers the RecordSet.
+    pub fn insert_rrsig(&mut self, rrsig: Record) {
+        self.rrsigs.push(rrsig)
+    }
+
+    /// Useful for clearing all signatures when the RecordSet is updated, or keys are rotated.
+    pub fn clear_rrsigs(&mut self) {
+        self.rrsigs.clear()
+    }
+
+    fn updated(&mut self, serial: u32) {
+        self.serial = serial;
+        self.rrsigs.clear(); // on updates, the rrsigs are invalid
+    }
+
+    /// creates a new Record as part of this RecordSet, adding the associated RData
+    ///
+    /// this interface may be deprecated in the future.
+    pub fn new_record(&mut self, rdata: &RData) -> &Record {
+        self.add_rdata(rdata.clone());
+
+        self.records
+            .iter()
+            .find(|r| r.rdata() == rdata)
+            .expect("insert failed")
+    }
+
+    /// creates a new Record as part of this RecordSet, adding the associated RData
+    pub fn add_rdata(&mut self, rdata: RData) -> bool {
+        debug_assert_eq!(self.record_type, rdata.to_record_type());
+
+        let mut record = Record::with(self.name.clone(), self.record_type, self.ttl);
+        record.set_rdata(rdata);
+        self.insert(record, 0)
+    }
+
+    /// Inserts a new Resource Record into the Set.
+    ///
+    /// If the record is inserted, the ttl for the most recent record will be used for the ttl of
+    /// the entire resource record set.
+    ///
+    /// This abides by the following restrictions in RFC 2136, April 1997:
+    ///
+    /// ```text
+    /// 1.1.5. The following RR types cannot be appended to an RRset.  If the
+    ///  following comparison rules are met, then an attempt to add the new RR
+    ///  will result in the replacement of the previous RR:
+    ///
+    /// SOA    compare only NAME, CLASS and TYPE -- it is not possible to
+    ///         have more than one SOA per zone, even if any of the data
+    ///         fields differ.
+    ///
+    /// CNAME  compare only NAME, CLASS, and TYPE -- it is not possible
+    ///         to have more than one CNAME RR, even if their data fields
+    ///         differ.
+    /// ```
+    ///
+    /// # Arguments
+    ///
+    /// * `record` - `Record` asserts that the `name` and `record_type` match the `RecordSet`.
+    /// * `serial` - current serial number of the `SOA` record, this is to be used for `IXFR` and
+    ///              signing for DNSSec after updates. The serial will only be updated if the
+    ///              record was added.
+    ///
+    /// # Return value
+    ///
+    /// True if the record was inserted.
+    ///
+    /// TODO: make a default add without serial number for basic usage
+    pub fn insert(&mut self, record: Record, serial: u32) -> bool {
+        assert_eq!(record.name(), &self.name);
+        assert_eq!(record.rr_type(), self.record_type);
+
+        // RFC 2136                       DNS Update                     April 1997
+        //
+        // 1.1.5. The following RR types cannot be appended to an RRset.  If the
+        //  following comparison rules are met, then an attempt to add the new RR
+        //  will result in the replacement of the previous RR:
+        match record.rr_type() {
+            // SOA    compare only NAME, CLASS and TYPE -- it is not possible to
+            //         have more than one SOA per zone, even if any of the data
+            //         fields differ.
+            RecordType::SOA => {
+                assert!(self.records.len() <= 1);
+
+                if let Some(soa_record) = self.records.iter().next() {
+                    match soa_record.rdata() {
+                        &RData::SOA(ref existing_soa) => {
+                            if let RData::SOA(ref new_soa) = *record.rdata() {
+                                if new_soa.serial() <= existing_soa.serial() {
+                                    info!(
+                                        "update ignored serial out of data: {:?} <= {:?}",
+                                        new_soa, existing_soa
+                                    );
+                                    return false;
+                                }
+                            } else {
+                                // not panicking here, b/c this is a bad record from the client or something, ignore
+                                info!("wrong rdata for SOA update: {:?}", record.rdata());
+                                return false;
+                            }
+                        }
+                        rdata => panic!("wrong rdata: {:?}", rdata), // valid panic, never should happen
+                    }
+                }
+
+                // if we got here, we're updating...
+                self.records.clear();
+            }
+            // RFC 1034/1035
+            // CNAME  compare only NAME, CLASS, and TYPE -- it is not possible
+            //         to have more than one CNAME RR, even if their data fields
+            //         differ.
+            //
+            // ANAME https://tools.ietf.org/html/draft-ietf-dnsop-aname-02
+            //    2.2.  Coexistence with other types
+            //
+            //   Only one ANAME <target> can be defined per <owner>.  An ANAME RRset
+            //   MUST NOT contain more than one resource record.
+            //
+            //   An ANAME's sibling address records are under the control of ANAME
+            //   processing (see Section 5) and are not first-class records in their
+            //   own right.  They MAY exist in zone files, but they can subsequently
+            //   be altered by ANAME processing.
+            //
+            //   ANAME records MAY freely coexist at the same owner name with other RR
+            //   types, except they MUST NOT coexist with CNAME or any other RR type
+            //   that restricts the types with which it can itself coexist.
+            //
+            //   Like other types, ANAME records can coexist with DNAME records at the
+            //   same owner name; in fact, the two can be used cooperatively to
+            //   redirect both the owner name address records (via ANAME) and
+            //   everything under it (via DNAME).
+            RecordType::CNAME | RecordType::ANAME => {
+                assert!(self.records.len() <= 1);
+                self.records.clear();
+            }
+            _ => (),
+        }
+
+        // collect any records to update based on rdata
+        let to_replace: Vec<usize> = self
+            .records
+            .iter()
+            .enumerate()
+            .filter(|&(_, rr)| rr.rdata() == record.rdata())
+            .map(|(i, _)| i)
+            .collect::<Vec<usize>>();
+
+        // if the Records are identical, ignore the update, update all that are not (ttl, etc.)
+        let mut replaced = false;
+        for i in to_replace {
+            if self.records[i] == record {
+                return false;
+            }
+
+            // TODO: this shouldn't really need a clone since there should only be one...
+            self.records.push(record.clone());
+            self.records.swap_remove(i);
+            self.ttl = record.ttl();
+            self.updated(serial);
+            replaced = true;
+        }
+
+        if !replaced {
+            self.ttl = record.ttl();
+            self.updated(serial);
+            self.records.push(record);
+            true
+        } else {
+            replaced
+        }
+    }
+
+    /// Removes the Resource Record if it exists.
+    ///
+    /// # Arguments
+    ///
+    /// * `record` - `Record` asserts that the `name` and `record_type` match the `RecordSet`. Removes
+    ///              any `record` if the record data, `RData`, match.
+    /// * `serial` - current serial number of the `SOA` record, this is to be used for `IXFR` and
+    ///              signing for DNSSec after updates. The serial will only be updated if the
+    ///              record was added.
+    ///
+    /// # Return value
+    ///
+    /// True if a record was removed.
+    pub fn remove(&mut self, record: &Record, serial: u32) -> bool {
+        assert_eq!(record.name(), &self.name);
+        assert!(record.rr_type() == self.record_type || record.rr_type() == RecordType::ANY);
+
+        match record.rr_type() {
+            // never delete the last NS record
+            RecordType::NS => {
+                if self.records.len() <= 1 {
+                    info!("ignoring delete of last NS record: {:?}", record);
+                    return false;
+                }
+            }
+            // never delete SOA
+            RecordType::SOA => {
+                info!("ignored delete of SOA");
+                return false;
+            }
+            _ => (), // move on to the delete
+        }
+
+        // remove the records, first collect all the indexes, then remove the records
+        let to_remove: Vec<usize> = self
+            .records
+            .iter()
+            .enumerate()
+            .filter(|&(_, rr)| rr.rdata() == record.rdata())
+            .map(|(i, _)| i)
+            .collect::<Vec<usize>>();
+
+        let mut removed = false;
+        for i in to_remove {
+            self.records.remove(i);
+            removed = true;
+            self.updated(serial);
+        }
+
+        removed
+    }
+}
+
+impl From<Record> for RecordSet {
+    fn from(record: Record) -> Self {
+        RecordSet {
+            name: record.name().clone(),
+            record_type: record.rr_type(),
+            dns_class: record.dns_class(),
+            ttl: record.ttl(),
+            records: vec![record],
+            rrsigs: vec![],
+            serial: 0,
+        }
+    }
+}
+
+/// Types which implement this can be converted into a RecordSet
+#[deprecated(note = "use From/Into")]
+pub trait IntoRecordSet: Sized {
+    /// Performs the conversion to a RecordSet
+    fn into_record_set(self) -> RecordSet;
+}
+
+#[allow(deprecated)]
+impl IntoRecordSet for RecordSet {
+    fn into_record_set(self) -> Self {
+        self
+    }
+}
+
+impl IntoIterator for RecordSet {
+    type Item = Record;
+    type IntoIter = Chain<vec::IntoIter<Record>, vec::IntoIter<Record>>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        self.records.into_iter().chain(self.rrsigs.into_iter())
+    }
+}
+
+/// An iterator over all the records and their signatures
+#[cfg(feature = "dnssec")]
+#[derive(Debug)]
+pub struct RecordsAndRrsigsIter<'r>(Chain<Iter<'r, Record>, RrsigsByAlgorithms<'r>>);
+
+#[cfg(feature = "dnssec")]
+impl<'r> Iterator for RecordsAndRrsigsIter<'r> {
+    type Item = &'r Record;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.0.next()
+    }
+}
+
+/// An iterator that limits the record signatures by SupportedAlgorithms
+#[cfg(feature = "dnssec")]
+#[derive(Debug)]
+pub struct RrsigsByAlgorithms<'r> {
+    rrsigs: Iter<'r, Record>,
+    supported_algorithms: SupportedAlgorithms,
+}
+
+#[cfg(feature = "dnssec")]
+impl<'r> Iterator for RrsigsByAlgorithms<'r> {
+    type Item = &'r Record;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        use crate::rr::dnssec::rdata::DNSSECRData;
+        use crate::rr::dnssec::Algorithm;
+
+        let supported_algorithms = self.supported_algorithms;
+
+        // disable rfc 6975 when no supported_algorithms specified
+        if supported_algorithms.is_empty() {
+            self.rrsigs.next()
+        } else {
+            self.rrsigs
+                .by_ref()
+                .filter(|record| {
+                    if let RData::DNSSEC(DNSSECRData::SIG(ref rrsig)) = *record.rdata() {
+                        supported_algorithms.has(rrsig.algorithm())
+                    } else {
+                        false
+                    }
+                })
+                .max_by_key(|record| {
+                    if let RData::DNSSEC(DNSSECRData::SIG(ref rrsig)) = *record.rdata() {
+                        rrsig.algorithm()
+                    } else {
+                        Algorithm::RSASHA1
+                    }
+                })
+        }
+    }
+}
+
+/// An iterator over the RecordSet data
+#[derive(Debug)]
+pub enum RrsetRecords<'r> {
+    /// There are no records in the record set
+    Empty,
+    /// The records associated with the record set
+    RecordsOnly(Iter<'r, Record>),
+    /// The records along with their signatures in the record set
+    #[cfg(feature = "dnssec")]
+    RecordsAndRrsigs(RecordsAndRrsigsIter<'r>),
+}
+
+impl<'r> RrsetRecords<'r> {
+    /// This is a best effort emptyness check
+    pub fn is_empty(&self) -> bool {
+        match *self {
+            RrsetRecords::Empty => true,
+            _ => false,
+        }
+    }
+}
+
+impl<'r> Iterator for RrsetRecords<'r> {
+    type Item = &'r Record;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        match self {
+            RrsetRecords::Empty => None,
+            RrsetRecords::RecordsOnly(i) => i.next(),
+            #[cfg(feature = "dnssec")]
+            RrsetRecords::RecordsAndRrsigs(i) => i.next(),
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use std::net::Ipv4Addr;
+    use std::str::FromStr;
+
+    use crate::rr::rdata::SOA;
+    use crate::rr::*;
+
+    #[test]
+    fn test_insert() {
+        let name = Name::from_str("www.example.com.").unwrap();
+        let record_type = RecordType::A;
+        let mut rr_set = RecordSet::new(&name, record_type, 0);
+
+        let insert = Record::new()
+            .set_name(name.clone())
+            .set_ttl(86400)
+            .set_rr_type(record_type)
+            .set_dns_class(DNSClass::IN)
+            .set_rdata(RData::A(Ipv4Addr::new(93, 184, 216, 24)))
+            .clone();
+
+        assert!(rr_set.insert(insert.clone(), 0));
+        assert_eq!(rr_set.records_without_rrsigs().count(), 1);
+        assert!(rr_set.records_without_rrsigs().any(|ref x| x == &&insert));
+
+        // dups ignored
+        assert!(!rr_set.insert(insert.clone(), 0));
+        assert_eq!(rr_set.records_without_rrsigs().count(), 1);
+        assert!(rr_set.records_without_rrsigs().any(|ref x| x == &&insert));
+
+        // add one
+        let insert1 = Record::new()
+            .set_name(name)
+            .set_ttl(86400)
+            .set_rr_type(record_type)
+            .set_dns_class(DNSClass::IN)
+            .set_rdata(RData::A(Ipv4Addr::new(93, 184, 216, 25)))
+            .clone();
+        assert!(rr_set.insert(insert1.clone(), 0));
+        assert_eq!(rr_set.records_without_rrsigs().count(), 2);
+        assert!(rr_set.records_without_rrsigs().any(|ref x| x == &&insert));
+        assert!(rr_set.records_without_rrsigs().any(|ref x| x == &&insert1));
+    }
+
+    #[test]
+    #[allow(clippy::unreadable_literal)]
+    fn test_insert_soa() {
+        let name = Name::from_str("example.com.").unwrap();
+        let record_type = RecordType::SOA;
+        let mut rr_set = RecordSet::new(&name, record_type, 0);
+
+        let insert = Record::new()
+            .set_name(name.clone())
+            .set_ttl(3600)
+            .set_rr_type(RecordType::SOA)
+            .set_dns_class(DNSClass::IN)
+            .set_rdata(RData::SOA(SOA::new(
+                Name::from_str("sns.dns.icann.org.").unwrap(),
+                Name::from_str("noc.dns.icann.org.").unwrap(),
+                2015082403,
+                7200,
+                3600,
+                1209600,
+                3600,
+            )))
+            .clone();
+        let same_serial = Record::new()
+            .set_name(name.clone())
+            .set_ttl(3600)
+            .set_rr_type(RecordType::SOA)
+            .set_dns_class(DNSClass::IN)
+            .set_rdata(RData::SOA(SOA::new(
+                Name::from_str("sns.dns.icann.net.").unwrap(),
+                Name::from_str("noc.dns.icann.net.").unwrap(),
+                2015082403,
+                7200,
+                3600,
+                1209600,
+                3600,
+            )))
+            .clone();
+        let new_serial = Record::new()
+            .set_name(name)
+            .set_ttl(3600)
+            .set_rr_type(RecordType::SOA)
+            .set_dns_class(DNSClass::IN)
+            .set_rdata(RData::SOA(SOA::new(
+                Name::from_str("sns.dns.icann.net.").unwrap(),
+                Name::from_str("noc.dns.icann.net.").unwrap(),
+                2015082404,
+                7200,
+                3600,
+                1209600,
+                3600,
+            )))
+            .clone();
+
+        assert!(rr_set.insert(insert.clone(), 0));
+        assert!(rr_set.records_without_rrsigs().any(|ref x| x == &&insert));
+        // same serial number
+        assert!(!rr_set.insert(same_serial.clone(), 0));
+        assert!(rr_set.records_without_rrsigs().any(|ref x| x == &&insert));
+        assert!(!rr_set
+            .records_without_rrsigs()
+            .any(|ref x| x == &&same_serial));
+
+        assert!(rr_set.insert(new_serial.clone(), 0));
+        assert!(!rr_set.insert(same_serial.clone(), 0));
+        assert!(!rr_set.insert(insert.clone(), 0));
+
+        assert!(rr_set
+            .records_without_rrsigs()
+            .any(|ref x| x == &&new_serial));
+        assert!(!rr_set.records_without_rrsigs().any(|ref x| x == &&insert));
+        assert!(!rr_set
+            .records_without_rrsigs()
+            .any(|ref x| x == &&same_serial));
+    }
+
+    #[test]
+    fn test_insert_cname() {
+        let name = Name::from_str("web.example.com.").unwrap();
+        let cname = Name::from_str("www.example.com.").unwrap();
+        let new_cname = Name::from_str("w2.example.com.").unwrap();
+
+        let record_type = RecordType::CNAME;
+        let mut rr_set = RecordSet::new(&name, record_type, 0);
+
+        let insert = Record::new()
+            .set_name(name.clone())
+            .set_ttl(3600)
+            .set_rr_type(RecordType::CNAME)
+            .set_dns_class(DNSClass::IN)
+            .set_rdata(RData::CNAME(cname))
+            .clone();
+        let new_record = Record::new()
+            .set_name(name)
+            .set_ttl(3600)
+            .set_rr_type(RecordType::CNAME)
+            .set_dns_class(DNSClass::IN)
+            .set_rdata(RData::CNAME(new_cname))
+            .clone();
+
+        assert!(rr_set.insert(insert.clone(), 0));
+        assert!(rr_set.records_without_rrsigs().any(|ref x| x == &&insert));
+
+        // update the record
+        assert!(rr_set.insert(new_record.clone(), 0));
+        assert!(!rr_set.records_without_rrsigs().any(|ref x| x == &&insert));
+        assert!(rr_set
+            .records_without_rrsigs()
+            .any(|ref x| x == &&new_record));
+    }
+
+    #[test]
+    fn test_remove() {
+        let name = Name::from_str("www.example.com.").unwrap();
+        let record_type = RecordType::A;
+        let mut rr_set = RecordSet::new(&name, record_type, 0);
+
+        let insert = Record::new()
+            .set_name(name.clone())
+            .set_ttl(86400)
+            .set_rr_type(record_type)
+            .set_dns_class(DNSClass::IN)
+            .set_rdata(RData::A(Ipv4Addr::new(93, 184, 216, 24)))
+            .clone();
+        let insert1 = Record::new()
+            .set_name(name)
+            .set_ttl(86400)
+            .set_rr_type(record_type)
+            .set_dns_class(DNSClass::IN)
+            .set_rdata(RData::A(Ipv4Addr::new(93, 184, 216, 25)))
+            .clone();
+
+        assert!(rr_set.insert(insert.clone(), 0));
+        assert!(rr_set.insert(insert1.clone(), 0));
+
+        assert!(rr_set.remove(&insert, 0));
+        assert!(!rr_set.remove(&insert, 0));
+        assert!(rr_set.remove(&insert1, 0));
+        assert!(!rr_set.remove(&insert1, 0));
+    }
+
+    #[test]
+    #[allow(clippy::unreadable_literal)]
+    fn test_remove_soa() {
+        let name = Name::from_str("www.example.com.").unwrap();
+        let record_type = RecordType::SOA;
+        let mut rr_set = RecordSet::new(&name, record_type, 0);
+
+        let insert = Record::new()
+            .set_name(name)
+            .set_ttl(3600)
+            .set_rr_type(RecordType::SOA)
+            .set_dns_class(DNSClass::IN)
+            .set_rdata(RData::SOA(SOA::new(
+                Name::from_str("sns.dns.icann.org.").unwrap(),
+                Name::from_str("noc.dns.icann.org.").unwrap(),
+                2015082403,
+                7200,
+                3600,
+                1209600,
+                3600,
+            )))
+            .clone();
+
+        assert!(rr_set.insert(insert.clone(), 0));
+        assert!(!rr_set.remove(&insert, 0));
+        assert!(rr_set.records_without_rrsigs().any(|ref x| x == &&insert));
+    }
+
+    #[test]
+    fn test_remove_ns() {
+        let name = Name::from_str("example.com.").unwrap();
+        let record_type = RecordType::NS;
+        let mut rr_set = RecordSet::new(&name, record_type, 0);
+
+        let ns1 = Record::new()
+            .set_name(name.clone())
+            .set_ttl(86400)
+            .set_rr_type(RecordType::NS)
+            .set_dns_class(DNSClass::IN)
+            .set_rdata(RData::NS(Name::from_str("a.iana-servers.net.").unwrap()))
+            .clone();
+        let ns2 = Record::new()
+            .set_name(name)
+            .set_ttl(86400)
+            .set_rr_type(RecordType::NS)
+            .set_dns_class(DNSClass::IN)
+            .set_rdata(RData::NS(Name::from_str("b.iana-servers.net.").unwrap()))
+            .clone();
+
+        assert!(rr_set.insert(ns1.clone(), 0));
+        assert!(rr_set.insert(ns2.clone(), 0));
+
+        // ok to remove one, but not two...
+        assert!(rr_set.remove(&ns1, 0));
+        assert!(!rr_set.remove(&ns2, 0));
+
+        // check that we can swap which ones are removed
+        assert!(rr_set.insert(ns1.clone(), 0));
+
+        assert!(rr_set.remove(&ns2, 0));
+        assert!(!rr_set.remove(&ns1, 0));
+    }
+
+    #[test]
+    #[cfg(feature = "dnssec")] // This tests RFC 6975, a DNSSEC-specific feature.
+    #[allow(clippy::block_in_if_condition_stmt)]
+    fn test_get_filter() {
+        use crate::rr::dnssec::rdata::SIG;
+        use crate::rr::dnssec::rdata::{DNSSECRData, DNSSECRecordType};
+        use crate::rr::dnssec::{Algorithm, SupportedAlgorithms};
+
+        let name = Name::root();
+        let rsasha256 = SIG::new(
+            RecordType::A,
+            Algorithm::RSASHA256,
+            0,
+            0,
+            0,
+            0,
+            0,
+            Name::root(),
+            vec![],
+        );
+        let ecp256 = SIG::new(
+            RecordType::A,
+            Algorithm::ECDSAP256SHA256,
+            0,
+            0,
+            0,
+            0,
+            0,
+            Name::root(),
+            vec![],
+        );
+        let ecp384 = SIG::new(
+            RecordType::A,
+            Algorithm::ECDSAP384SHA384,
+            0,
+            0,
+            0,
+            0,
+            0,
+            Name::root(),
+            vec![],
+        );
+        let ed25519 = SIG::new(
+            RecordType::A,
+            Algorithm::ED25519,
+            0,
+            0,
+            0,
+            0,
+            0,
+            Name::root(),
+            vec![],
+        );
+
+        let rrsig_rsa = Record::new()
+            .set_name(name.clone())
+            .set_ttl(3600)
+            .set_rr_type(RecordType::DNSSEC(DNSSECRecordType::RRSIG))
+            .set_dns_class(DNSClass::IN)
+            .set_rdata(RData::DNSSEC(DNSSECRData::SIG(rsasha256)))
+            .clone();
+        let rrsig_ecp256 = Record::new()
+            .set_name(name.clone())
+            .set_ttl(3600)
+            .set_rr_type(RecordType::DNSSEC(DNSSECRecordType::RRSIG))
+            .set_dns_class(DNSClass::IN)
+            .set_rdata(RData::DNSSEC(DNSSECRData::SIG(ecp256)))
+            .clone();
+        let rrsig_ecp384 = Record::new()
+            .set_name(name.clone())
+            .set_ttl(3600)
+            .set_rr_type(RecordType::DNSSEC(DNSSECRecordType::RRSIG))
+            .set_dns_class(DNSClass::IN)
+            .set_rdata(RData::DNSSEC(DNSSECRData::SIG(ecp384)))
+            .clone();
+        let rrsig_ed25519 = Record::new()
+            .set_name(name.clone())
+            .set_ttl(3600)
+            .set_rr_type(RecordType::DNSSEC(DNSSECRecordType::RRSIG))
+            .set_dns_class(DNSClass::IN)
+            .set_rdata(RData::DNSSEC(DNSSECRData::SIG(ed25519)))
+            .clone();
+
+        let a = Record::new()
+            .set_name(name)
+            .set_ttl(3600)
+            .set_rr_type(RecordType::A)
+            .set_dns_class(DNSClass::IN)
+            .set_rdata(RData::A(Ipv4Addr::new(93, 184, 216, 24)))
+            .clone();
+
+        let mut rrset = RecordSet::from(a);
+        rrset.insert_rrsig(rrsig_rsa);
+        rrset.insert_rrsig(rrsig_ecp256);
+        rrset.insert_rrsig(rrsig_ecp384);
+        rrset.insert_rrsig(rrsig_ed25519);
+
+        assert!(rrset
+            .records_with_rrsigs(SupportedAlgorithms::all(),)
+            .any(
+                |r| if let RData::DNSSEC(DNSSECRData::SIG(ref sig)) = *r.rdata() {
+                    sig.algorithm() == Algorithm::ED25519
+                } else {
+                    false
+                },
+            ));
+
+        let mut supported_algorithms = SupportedAlgorithms::new();
+        supported_algorithms.set(Algorithm::ECDSAP384SHA384);
+        assert!(rrset.records_with_rrsigs(supported_algorithms).any(|r| {
+            if let RData::DNSSEC(DNSSECRData::SIG(ref sig)) = *r.rdata() {
+                sig.algorithm() == Algorithm::ECDSAP384SHA384
+            } else {
+                false
+            }
+        }));
+
+        let mut supported_algorithms = SupportedAlgorithms::new();
+        supported_algorithms.set(Algorithm::ED25519);
+        assert!(rrset.records_with_rrsigs(supported_algorithms).any(|r| {
+            if let RData::DNSSEC(DNSSECRData::SIG(ref sig)) = *r.rdata() {
+                sig.algorithm() == Algorithm::ED25519
+            } else {
+                false
+            }
+        }));
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/serialize/binary/bin_tests.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/serialize/binary/bin_tests.rs
new file mode 100644
index 0000000..7c5350e
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/serialize/binary/bin_tests.rs
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+#![allow(clippy::dbg_macro, clippy::print_stdout)]
+
+use super::*;
+use crate::error::*;
+use std::fmt::Debug;
+
+fn get_character_data() -> Vec<(&'static str, Vec<u8>)> {
+    vec![
+        ("", vec![0]),                      // base case, only the root
+        ("a", vec![1, b'a']),               // a single 'a' label
+        ("bc", vec![2, b'b', b'c']),        // two labels, 'a.bc'
+        ("♥", vec![3, 0xE2, 0x99, 0xA5]), // two labels utf8, 'a.♥'
+    ]
+}
+
+#[test]
+fn read_character_data() {
+    for (string, bytes) in get_character_data() {
+        let mut decoder = BinDecoder::new(&bytes);
+        assert_eq!(
+            decoder.read_character_data().unwrap().unverified(),
+            string.as_bytes()
+        );
+    }
+}
+
+#[test]
+fn emit_character_data() {
+    test_emit_data_set(get_character_data(), |ref mut e, d| {
+        e.emit_character_data(&d)
+    });
+}
+
+fn get_u16_data() -> Vec<(u16, Vec<u8>)> {
+    vec![
+        (0, vec![0x00, 0x00]),
+        (1, vec![0x00, 0x01]),
+        (256, vec![0x01, 0x00]),
+        (u16::max_value(), vec![0xFF, 0xFF]),
+    ]
+}
+
+#[test]
+fn read_u16() {
+    test_read_data_set(get_u16_data(), |mut d| {
+        d.read_u16().map(Restrict::unverified)
+    });
+}
+
+#[test]
+fn emit_u16() {
+    test_emit_data_set(get_u16_data(), |ref mut e, d| e.emit_u16(d));
+}
+
+fn get_i32_data() -> Vec<(i32, Vec<u8>)> {
+    vec![
+        (0, vec![0x00, 0x00, 0x00, 0x00]),
+        (1, vec![0x00, 0x00, 0x00, 0x01]),
+        (256, vec![0x00, 0x00, 0x01, 0x00]),
+        (256 * 256, vec![0x00, 0x01, 0x00, 0x00]),
+        (256 * 256 * 256, vec![0x01, 0x00, 0x00, 0x00]),
+        (-1, vec![0xFF, 0xFF, 0xFF, 0xFF]),
+        (i32::min_value(), vec![0x80, 0x00, 0x00, 0x00]),
+        (i32::max_value(), vec![0x7F, 0xFF, 0xFF, 0xFF]),
+    ]
+}
+
+#[test]
+fn read_i32() {
+    test_read_data_set(get_i32_data(), |mut d| {
+        d.read_i32().map(Restrict::unverified)
+    });
+}
+
+#[test]
+fn emit_i32() {
+    test_emit_data_set(get_i32_data(), |ref mut e, d| e.emit_i32(d));
+}
+
+#[allow(clippy::unreadable_literal)]
+fn get_u32_data() -> Vec<(u32, Vec<u8>)> {
+    vec![
+        (0, vec![0x00, 0x00, 0x00, 0x00]),
+        (1, vec![0x00, 0x00, 0x00, 0x01]),
+        (256, vec![0x00, 0x00, 0x01, 0x00]),
+        (256 * 256, vec![0x00, 0x01, 0x00, 0x00]),
+        (256 * 256 * 256, vec![0x01, 0x00, 0x00, 0x00]),
+        (u32::max_value(), vec![0xFF, 0xFF, 0xFF, 0xFF]),
+        (2147483648, vec![0x80, 0x00, 0x00, 0x00]),
+        (i32::max_value() as u32, vec![0x7F, 0xFF, 0xFF, 0xFF]),
+    ]
+}
+
+#[test]
+fn read_u32() {
+    test_read_data_set(get_u32_data(), |mut d| {
+        d.read_u32().map(Restrict::unverified)
+    });
+}
+
+#[test]
+fn emit_u32() {
+    test_emit_data_set(get_u32_data(), |ref mut e, d| e.emit_u32(d));
+}
+
+pub fn test_read_data_set<E, F>(data_set: Vec<(E, Vec<u8>)>, read_func: F)
+where
+    E: PartialEq<E> + Debug,
+    F: Fn(BinDecoder) -> ProtoResult<E>,
+{
+    for (test_pass, (expect, binary)) in data_set.into_iter().enumerate() {
+        println!("test {}: {:?}", test_pass, binary);
+
+        let decoder = BinDecoder::new(&binary);
+        assert_eq!(read_func(decoder).unwrap(), expect);
+    }
+}
+
+pub fn test_emit_data_set<S, F>(data_set: Vec<(S, Vec<u8>)>, emit_func: F)
+where
+    F: Fn(&mut BinEncoder, S) -> ProtoResult<()>,
+    S: Debug,
+{
+    for (test_pass, (data, expect)) in data_set.into_iter().enumerate() {
+        println!("test {}: {:?}", test_pass, data);
+
+        let mut bytes: Vec<u8> = Vec::with_capacity(512);
+        {
+            let mut encoder = BinEncoder::new(&mut bytes);
+            emit_func(&mut encoder, data).unwrap();
+        }
+        assert_eq!(bytes, expect);
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/serialize/binary/decoder.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/serialize/binary/decoder.rs
new file mode 100644
index 0000000..6ae6373
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/serialize/binary/decoder.rs
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+use crate::error::{ProtoError, ProtoErrorKind, ProtoResult};
+use crate::serialize::binary::Restrict;
+
+/// This is non-destructive to the inner buffer, b/c for pointer types we need to perform a reverse
+///  seek to lookup names
+///
+/// A note on serialization, there was a thought to have this implement the Serde deserializer,
+///  but given that this is such a small subset of all the serialization which that performs
+///  this is a simpler implementation without the cruft, at least for serializing to/from the
+///  binary DNS protocols.
+pub struct BinDecoder<'a> {
+    buffer: &'a [u8],
+    index: usize,
+}
+
+impl<'a> BinDecoder<'a> {
+    /// Creates a new BinDecoder
+    ///
+    /// # Arguments
+    ///
+    /// * `buffer` - buffer from which all data will be read
+    pub fn new(buffer: &'a [u8]) -> Self {
+        BinDecoder { buffer, index: 0 }
+    }
+
+    /// Pop one byte from the buffer
+    pub fn pop(&mut self) -> ProtoResult<Restrict<u8>> {
+        if self.index < self.buffer.len() {
+            let byte = self.buffer[self.index];
+            self.index += 1;
+            Ok(Restrict::new(byte))
+        } else {
+            Err("unexpected end of input reached".into())
+        }
+    }
+
+    /// Returns the number of bytes in the buffer
+    ///
+    /// ```
+    /// use trust_dns_proto::serialize::binary::BinDecoder;
+    ///
+    /// let deadbeef = b"deadbeef";
+    /// let mut decoder = BinDecoder::new(deadbeef);
+    /// assert_eq!(decoder.len(), 8);
+    /// decoder.read_slice(7).unwrap();
+    /// assert_eq!(decoder.len(), 1);
+    /// ```
+    pub fn len(&self) -> usize {
+        self.buffer.len().saturating_sub(self.index)
+    }
+
+    /// Returns `true` if the buffer is empty
+    pub fn is_empty(&self) -> bool {
+        self.len() == 0
+    }
+
+    /// Peed one byte forward, without moving the current index forward
+    pub fn peek(&self) -> Option<Restrict<u8>> {
+        if self.index < self.buffer.len() {
+            Some(Restrict::new(self.buffer[self.index]))
+        } else {
+            None
+        }
+    }
+
+    /// Returns the current index in the buffer
+    pub fn index(&self) -> usize {
+        self.index
+    }
+
+    /// This is a pretty efficient clone, as the buffer is never cloned, and only the index is set
+    ///  to the value passed in
+    pub fn clone(&self, index_at: u16) -> BinDecoder<'a> {
+        BinDecoder {
+            buffer: self.buffer,
+            index: index_at as usize,
+        }
+    }
+
+    /// Reads a String from the buffer
+    ///
+    /// ```text
+    /// <character-string> is a single
+    /// length octet followed by that number of characters.  <character-string>
+    /// is treated as binary information, and can be up to 256 characters in
+    /// length (including the length octet).
+    /// ```
+    ///
+    /// # Returns
+    ///
+    /// A String version of the character data
+    pub fn read_character_data(&mut self) -> ProtoResult<Restrict<&[u8]>> {
+        self.read_character_data_max(None)
+    }
+
+    /// Reads to a maximum length of data, returns an error if this is exceeded
+    pub fn read_character_data_max(
+        &mut self,
+        max_len: Option<usize>,
+    ) -> ProtoResult<Restrict<&[u8]>> {
+        let length = self
+            .pop()?
+            .map(|u| u as usize)
+            .verify_unwrap(|length| {
+                if let Some(max_len) = max_len {
+                    *length <= max_len
+                } else {
+                    true
+                }
+            })
+            .map_err(|length| {
+                ProtoError::from(ProtoErrorKind::CharacterDataTooLong {
+                    max: max_len.unwrap_or_default(),
+                    len: length,
+                })
+            })?;
+
+        self.read_slice(length)
+    }
+
+    /// Reads a Vec out of the buffer
+    ///
+    /// # Arguments
+    ///
+    /// * `len` - number of bytes to read from the buffer
+    ///
+    /// # Returns
+    ///
+    /// The Vec of the specified length, otherwise an error
+    pub fn read_vec(&mut self, len: usize) -> ProtoResult<Restrict<Vec<u8>>> {
+        self.read_slice(len).map(|s| s.map(ToOwned::to_owned))
+    }
+
+    /// Reads a slice out of the buffer, without allocating
+    ///
+    /// # Arguments
+    ///
+    /// * `len` - number of bytes to read from the buffer
+    ///
+    /// # Returns
+    ///
+    /// The slice of the specified length, otherwise an error
+    pub fn read_slice(&mut self, len: usize) -> ProtoResult<Restrict<&'a [u8]>> {
+        let end = self
+            .index
+            .checked_add(len)
+            .ok_or_else(|| ProtoError::from("invalid length for slice"))?;
+        if end > self.buffer.len() {
+            return Err("buffer exhausted".into());
+        }
+        let slice: &'a [u8] = &self.buffer[self.index..end];
+        self.index += len;
+        Ok(Restrict::new(slice))
+    }
+
+    /// Reads a slice from a previous index to the current
+    pub fn slice_from(&self, index: usize) -> ProtoResult<&'a [u8]> {
+        if index > self.index {
+            return Err("index antecedes upper bound".into());
+        }
+
+        Ok(&self.buffer[index..self.index])
+    }
+
+    /// Reads a byte from the buffer, equivalent to `Self::pop()`
+    pub fn read_u8(&mut self) -> ProtoResult<Restrict<u8>> {
+        self.pop()
+    }
+
+    /// Reads the next 2 bytes into u16
+    ///
+    /// This performs a byte-by-byte manipulation, there
+    ///  which means endianness is implicitly handled (i.e. no network to little endian (intel), issues)
+    ///
+    /// # Return
+    ///
+    /// Return the u16 from the buffer
+    pub fn read_u16(&mut self) -> ProtoResult<Restrict<u16>> {
+        Ok(self
+            .read_slice(2)?
+            .map(|s| u16::from_be_bytes([s[0], s[1]])))
+    }
+
+    /// Reads the next four bytes into i32.
+    ///
+    /// This performs a byte-by-byte manipulation, there
+    ///  which means endianness is implicitly handled (i.e. no network to little endian (intel), issues)
+    ///
+    /// # Return
+    ///
+    /// Return the i32 from the buffer
+    pub fn read_i32(&mut self) -> ProtoResult<Restrict<i32>> {
+        Ok(self
+            .read_slice(4)?
+            .map(|s| i32::from_be_bytes([s[0], s[1], s[2], s[3]])))
+    }
+
+    /// Reads the next four bytes into u32.
+    ///
+    /// This performs a byte-by-byte manipulation, there
+    ///  which means endianness is implicitly handled (i.e. no network to little endian (intel), issues)
+    ///
+    /// # Return
+    ///
+    /// Return the u32 from the buffer
+    pub fn read_u32(&mut self) -> ProtoResult<Restrict<u32>> {
+        Ok(self
+            .read_slice(4)?
+            .map(|s| u32::from_be_bytes([s[0], s[1], s[2], s[3]])))
+    }
+}
+
+#[cfg(tests)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_read_slice() {
+        let deadbeef = b"deadbeef";
+        let mut decoder = BinDecoder::new(deadbeef);
+
+        let read = decoder.read_slice(4).expect("failed to read dead");
+        assert_eq!(read, "dead");
+
+        let read = decoder.read_slice(2).expect("failed to read be");
+        assert_eq!(read, "be");
+
+        let read = decoder.read_slice(0).expect("failed to read nothing");
+        assert_eq!(read, "");
+
+        // this should fail
+        assert!(decoder.read_slice(3).is_err());
+    }
+
+    #[test]
+    fn test_read_slice_from() {
+        let deadbeef = b"deadbeef";
+        let mut decoder = BinDecoder::new(deadbeef);
+
+        decoder.read_slice_from(4).expect("failed to read dead");
+        let read = decoder.slice_from(0).expect("failed to get slice");
+        assert_eq!(read, "dead");
+
+        decoder.read_slice(2).expect("failed to read be");
+        let read = decoder.slice_from(4).expect("failed to get slice");
+        assert_eq!(read, "be");
+
+        decoder.read_slice(0).expect("failed to read nothing");
+        let read = decoder.slice_from(4).expect("failed to get slice");
+        assert_eq!(read, "be");
+
+        // this should fail
+        assert!(decoder.slice_from(6).is_err());
+        assert!(decoder.slice_from(10).is_err());
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/serialize/binary/encoder.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/serialize/binary/encoder.rs
new file mode 100644
index 0000000..d3622f8
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/serialize/binary/encoder.rs
@@ -0,0 +1,621 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+use std::marker::PhantomData;
+
+use crate::error::{ProtoErrorKind, ProtoResult};
+
+use super::BinEncodable;
+use crate::op::Header;
+
+// this is private to make sure there is no accidental access to the inner buffer.
+mod private {
+    use crate::error::{ProtoErrorKind, ProtoResult};
+
+    /// A wrapper for a buffer that guarantees writes never exceed a defined set of bytes
+    pub struct MaximalBuf<'a> {
+        max_size: usize,
+        buffer: &'a mut Vec<u8>,
+    }
+
+    impl<'a> MaximalBuf<'a> {
+        pub fn new(max_size: u16, buffer: &'a mut Vec<u8>) -> Self {
+            MaximalBuf {
+                max_size: max_size as usize,
+                buffer,
+            }
+        }
+
+        /// Sets the maximum size to enforce
+        pub fn set_max_size(&mut self, max: u16) {
+            self.max_size = max as usize;
+        }
+
+        /// returns an error if the maximum buffer size would be exceeded with the addition number of elements
+        ///
+        /// and reserves the additional space in the buffer
+        pub fn enforced_write<F>(&mut self, additional: usize, writer: F) -> ProtoResult<()>
+        where
+            F: FnOnce(&mut Vec<u8>) -> (),
+        {
+            let expected_len = self.buffer.len() + additional;
+
+            if expected_len > self.max_size {
+                Err(ProtoErrorKind::MaxBufferSizeExceeded(self.max_size).into())
+            } else {
+                self.buffer.reserve(additional);
+                writer(self.buffer);
+
+                debug_assert_eq!(self.buffer.len(), expected_len);
+                Ok(())
+            }
+        }
+
+        /// truncates are always safe
+        pub fn truncate(&mut self, len: usize) {
+            self.buffer.truncate(len)
+        }
+
+        /// returns the length of the underlying buffer
+        pub fn len(&self) -> usize {
+            self.buffer.len()
+        }
+
+        /// Immutable reads are always safe
+        pub fn buffer(&'a self) -> &'a [u8] {
+            self.buffer as &'a [u8]
+        }
+
+        /// Returns a reference to the internal buffer
+        pub fn into_bytes(self) -> &'a Vec<u8> {
+            self.buffer
+        }
+    }
+}
+
+/// Encode DNS messages and resource record types.
+pub struct BinEncoder<'a> {
+    offset: usize,
+    buffer: private::MaximalBuf<'a>,
+    /// start and end of label pointers, smallvec here?
+    name_pointers: Vec<(usize, usize)>,
+    mode: EncodeMode,
+    canonical_names: bool,
+}
+
+impl<'a> BinEncoder<'a> {
+    /// Create a new encoder with the Vec to fill
+    pub fn new(buf: &'a mut Vec<u8>) -> Self {
+        Self::with_offset(buf, 0, EncodeMode::Normal)
+    }
+
+    /// Specify the mode for encoding
+    ///
+    /// # Arguments
+    ///
+    /// * `mode` - In Signing mode, canonical forms of all data are encoded, otherwise format matches the source form
+    pub fn with_mode(buf: &'a mut Vec<u8>, mode: EncodeMode) -> Self {
+        Self::with_offset(buf, 0, mode)
+    }
+
+    /// Begins the encoder at the given offset
+    ///
+    /// This is used for pointers. If this encoder is starting at some point further in
+    ///  the sequence of bytes, for the proper offset of the pointer, the offset accounts for that
+    ///  by using the offset to add to the pointer location being written.
+    ///
+    /// # Arguments
+    ///
+    /// * `offset` - index at which to start writing into the buffer
+    pub fn with_offset(buf: &'a mut Vec<u8>, offset: u32, mode: EncodeMode) -> Self {
+        if buf.capacity() < 512 {
+            let reserve = 512 - buf.capacity();
+            buf.reserve(reserve);
+        }
+
+        BinEncoder {
+            offset: offset as usize,
+            // TODO: add max_size to signature
+            buffer: private::MaximalBuf::new(u16::max_value(), buf),
+            name_pointers: Vec::new(),
+            mode,
+            canonical_names: false,
+        }
+    }
+
+    // TODO: move to constructor (kept for backward compatibility)
+    /// Sets the maximum size of the buffer
+    ///
+    /// DNS message lens must be smaller than u16::max_value due to hard limits in the protocol
+    ///
+    /// *this method will move to the constructor in a future release*
+    pub fn set_max_size(&mut self, max: u16) {
+        self.buffer.set_max_size(max);
+    }
+
+    /// Returns a reference to the internal buffer
+    pub fn into_bytes(self) -> &'a Vec<u8> {
+        self.buffer.into_bytes()
+    }
+
+    /// Returns the length of the buffer
+    pub fn len(&self) -> usize {
+        self.buffer.len()
+    }
+
+    /// Returns `true` if the buffer is empty
+    pub fn is_empty(&self) -> bool {
+        self.buffer.buffer().is_empty()
+    }
+
+    /// Returns the current offset into the buffer
+    pub fn offset(&self) -> usize {
+        self.offset
+    }
+
+    /// sets the current offset to the new offset
+    pub fn set_offset(&mut self, offset: usize) {
+        self.offset = offset;
+    }
+
+    /// Returns the current Encoding mode
+    pub fn mode(&self) -> EncodeMode {
+        self.mode
+    }
+
+    /// If set to true, then names will be written into the buffer in canonical form
+    pub fn set_canonical_names(&mut self, canonical_names: bool) {
+        self.canonical_names = canonical_names;
+    }
+
+    /// Returns true if then encoder is writing in canonical form
+    pub fn is_canonical_names(&self) -> bool {
+        self.canonical_names
+    }
+
+    /// Emit all names in canonical form, useful for https://tools.ietf.org/html/rfc3597
+    pub fn with_canonical_names<F: FnOnce(&mut Self) -> ProtoResult<()>>(
+        &mut self,
+        f: F,
+    ) -> ProtoResult<()> {
+        let was_canonical = self.is_canonical_names();
+        self.set_canonical_names(true);
+
+        let res = f(self);
+        self.set_canonical_names(was_canonical);
+
+        res
+    }
+
+    // TODO: deprecate this...
+    /// Reserve specified additional length in the internal buffer.
+    pub fn reserve(&mut self, _additional: usize) -> ProtoResult<()> {
+        Ok(())
+    }
+
+    /// trims to the current offset
+    pub fn trim(&mut self) {
+        let offset = self.offset;
+        self.buffer.truncate(offset);
+        self.name_pointers
+            .retain(|&(start, end)| start < offset && end <= offset);
+    }
+
+    // /// returns an error if the maximum buffer size would be exceeded with the addition number of elements
+    // ///
+    // /// and reserves the additional space in the buffer
+    // fn enforce_size(&mut self, additional: usize) -> ProtoResult<()> {
+    //     if (self.buffer.len() + additional) > self.max_size {
+    //         Err(ProtoErrorKind::MaxBufferSizeExceeded(self.max_size).into())
+    //     } else {
+    //         self.reserve(additional);
+    //         Ok(())
+    //     }
+    // }
+
+    /// borrow a slice from the encoder
+    pub fn slice_of(&self, start: usize, end: usize) -> &[u8] {
+        assert!(start < self.offset);
+        assert!(end <= self.buffer.len());
+        &self.buffer.buffer()[start..end]
+    }
+
+    /// Stores a label pointer to an already written label
+    ///
+    /// The location is the current position in the buffer
+    ///  implicitly, it is expected that the name will be written to the stream after the current index.
+    pub fn store_label_pointer(&mut self, start: usize, end: usize) {
+        assert!(start <= (u16::max_value() as usize));
+        assert!(end <= (u16::max_value() as usize));
+        assert!(start <= end);
+        if self.offset < 0x3FFF_usize {
+            self.name_pointers.push((start, end)); // the next char will be at the len() location
+        }
+    }
+
+    /// Looks up the index of an already written label
+    pub fn get_label_pointer(&self, start: usize, end: usize) -> Option<u16> {
+        let search = self.slice_of(start, end);
+
+        for &(match_start, match_end) in &self.name_pointers {
+            let matcher = self.slice_of(match_start as usize, match_end as usize);
+            if matcher == search {
+                assert!(match_start <= (u16::max_value() as usize));
+                return Some(match_start as u16);
+            }
+        }
+
+        None
+    }
+
+    /// Emit one byte into the buffer
+    pub fn emit(&mut self, b: u8) -> ProtoResult<()> {
+        if self.offset < self.buffer.len() {
+            let offset = self.offset;
+            self.buffer.enforced_write(0, |buffer| {
+                *buffer
+                    .get_mut(offset)
+                    .expect("could not get index at offset") = b
+            })?;
+        } else {
+            self.buffer.enforced_write(1, |buffer| buffer.push(b))?;
+        }
+        self.offset += 1;
+        Ok(())
+    }
+
+    /// matches description from above.
+    ///
+    /// ```
+    /// use trust_dns_proto::serialize::binary::BinEncoder;
+    ///
+    /// let mut bytes: Vec<u8> = Vec::new();
+    /// {
+    ///   let mut encoder: BinEncoder = BinEncoder::new(&mut bytes);
+    ///   encoder.emit_character_data("abc");
+    /// }
+    /// assert_eq!(bytes, vec![3,b'a',b'b',b'c']);
+    /// ```
+    pub fn emit_character_data<S: AsRef<[u8]>>(&mut self, char_data: S) -> ProtoResult<()> {
+        let char_bytes = char_data.as_ref();
+        if char_bytes.len() > 255 {
+            return Err(ProtoErrorKind::CharacterDataTooLong {
+                max: 255,
+                len: char_bytes.len(),
+            }
+            .into());
+        }
+
+        // first the length is written
+        self.emit(char_bytes.len() as u8)?;
+        self.write_slice(char_bytes)
+    }
+
+    /// Emit one byte into the buffer
+    pub fn emit_u8(&mut self, data: u8) -> ProtoResult<()> {
+        self.emit(data)
+    }
+
+    /// Writes a u16 in network byte order to the buffer
+    pub fn emit_u16(&mut self, data: u16) -> ProtoResult<()> {
+        self.write_slice(&data.to_be_bytes())
+    }
+
+    /// Writes an i32 in network byte order to the buffer
+    pub fn emit_i32(&mut self, data: i32) -> ProtoResult<()> {
+        self.write_slice(&data.to_be_bytes())
+    }
+
+    /// Writes an u32 in network byte order to the buffer
+    pub fn emit_u32(&mut self, data: u32) -> ProtoResult<()> {
+        self.write_slice(&data.to_be_bytes())
+    }
+
+    fn write_slice(&mut self, data: &[u8]) -> ProtoResult<()> {
+        // replacement case, the necessary space should have been reserved already...
+        if self.offset < self.buffer.len() {
+            let offset = self.offset;
+
+            self.buffer.enforced_write(0, |buffer| {
+                let mut offset = offset;
+                for b in data {
+                    *buffer
+                        .get_mut(offset)
+                        .expect("could not get index at offset for slice") = *b;
+                    offset += 1;
+                }
+            })?;
+
+            self.offset += data.len();
+        } else {
+            self.buffer
+                .enforced_write(data.len(), |buffer| buffer.extend_from_slice(data))?;
+            self.offset += data.len();
+        }
+
+        Ok(())
+    }
+
+    /// Writes the byte slice to the stream
+    pub fn emit_vec(&mut self, data: &[u8]) -> ProtoResult<()> {
+        self.write_slice(data)
+    }
+
+    /// Emits all the elements of an Iterator to the encoder
+    pub fn emit_all<'e, I: Iterator<Item = &'e E>, E: 'e + BinEncodable>(
+        &mut self,
+        mut iter: I,
+    ) -> ProtoResult<usize> {
+        self.emit_iter(&mut iter)
+    }
+
+    // TODO: dedup with above emit_all
+    /// Emits all the elements of an Iterator to the encoder
+    pub fn emit_all_refs<'r, 'e, I, E>(&mut self, iter: I) -> ProtoResult<usize>
+    where
+        'e: 'r,
+        I: Iterator<Item = &'r &'e E>,
+        E: 'r + 'e + BinEncodable,
+    {
+        let mut iter = iter.cloned();
+        self.emit_iter(&mut iter)
+    }
+
+    /// emits all items in the iterator, return the number emitted
+    #[allow(clippy::needless_return)]
+    pub fn emit_iter<'e, I: Iterator<Item = &'e E>, E: 'e + BinEncodable>(
+        &mut self,
+        iter: &mut I,
+    ) -> ProtoResult<usize> {
+        let mut count = 0;
+        for i in iter {
+            let rollback = self.set_rollback();
+            i.emit(self).map_err(|e| {
+                if let ProtoErrorKind::MaxBufferSizeExceeded(_) = e.kind() {
+                    rollback.rollback(self);
+                    return ProtoErrorKind::NotAllRecordsWritten { count }.into();
+                } else {
+                    return e;
+                }
+            })?;
+            count += 1;
+        }
+        Ok(count)
+    }
+
+    /// capture a location to write back to
+    pub fn place<T: EncodedSize>(&mut self) -> ProtoResult<Place<T>> {
+        let index = self.offset;
+        let len = T::size_of();
+
+        // resize the buffer
+        self.buffer
+            .enforced_write(len, |buffer| buffer.resize(index + len, 0))?;
+
+        // update the offset
+        self.offset += len;
+
+        Ok(Place {
+            start_index: index,
+            phantom: PhantomData,
+        })
+    }
+
+    /// calculates the length of data written since the place was creating
+    pub fn len_since_place<T: EncodedSize>(&self, place: &Place<T>) -> usize {
+        (self.offset - place.start_index) - place.size_of()
+    }
+
+    /// write back to a previously captured location
+    pub fn emit_at<T: EncodedSize>(&mut self, place: Place<T>, data: T) -> ProtoResult<()> {
+        // preserve current index
+        let current_index = self.offset;
+
+        // reset the current index back to place before writing
+        //   this is an assert because it's programming error for it to be wrong.
+        assert!(place.start_index < current_index);
+        self.offset = place.start_index;
+
+        // emit the data to be written at this place
+        let emit_result = data.emit(self);
+
+        // double check that the current number of bytes were written
+        //   this is an assert because it's programming error for it to be wrong.
+        assert!((self.offset - place.start_index) == place.size_of());
+
+        // reset to original location
+        self.offset = current_index;
+
+        emit_result
+    }
+
+    fn set_rollback(&self) -> Rollback {
+        Rollback {
+            rollback_index: self.offset(),
+        }
+    }
+}
+
+/// A trait to return the size of a type as it will be encoded in DNS
+///
+/// it does not necessarily equal `std::mem::size_of`, though it might, especially for primitives
+pub trait EncodedSize: BinEncodable {
+    /// Return the size in bytes of the
+    fn size_of() -> usize;
+}
+
+impl EncodedSize for u16 {
+    fn size_of() -> usize {
+        2
+    }
+}
+
+impl EncodedSize for Header {
+    fn size_of() -> usize {
+        Header::len()
+    }
+}
+
+#[derive(Debug)]
+#[must_use = "data must be written back to the place"]
+pub struct Place<T: EncodedSize> {
+    start_index: usize,
+    phantom: PhantomData<T>,
+}
+
+impl<T: EncodedSize> Place<T> {
+    pub fn replace(self, encoder: &mut BinEncoder, data: T) -> ProtoResult<()> {
+        encoder.emit_at(self, data)
+    }
+
+    pub fn size_of(&self) -> usize {
+        T::size_of()
+    }
+}
+
+/// A type representing a rollback point in a stream
+pub struct Rollback {
+    rollback_index: usize,
+}
+
+impl Rollback {
+    pub fn rollback(self, encoder: &mut BinEncoder) {
+        encoder.set_offset(self.rollback_index)
+    }
+}
+
+/// In the Verify mode there maybe some things which are encoded differently, e.g. SIG0 records
+///  should not be included in the additional count and not in the encoded data when in Verify
+#[derive(Copy, Clone, Eq, PartialEq)]
+pub enum EncodeMode {
+    /// In signing mode records are written in canonical form
+    Signing,
+    /// Write records in standard format
+    Normal,
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::op::Message;
+    use crate::serialize::binary::BinDecoder;
+
+    #[test]
+    fn test_label_compression_regression() {
+        // https://github.com/bluejekyll/trust-dns/issues/339
+        /*
+        ;; QUESTION SECTION:
+        ;bluedot.is.autonavi.com.gds.alibabadns.com. IN AAAA
+
+        ;; AUTHORITY SECTION:
+        gds.alibabadns.com.     1799    IN      SOA     gdsns1.alibabadns.com. none. 2015080610 1800 600 3600 360
+        */
+        let data: Vec<u8> = vec![
+            154, 50, 129, 128, 0, 1, 0, 0, 0, 1, 0, 1, 7, 98, 108, 117, 101, 100, 111, 116, 2, 105,
+            115, 8, 97, 117, 116, 111, 110, 97, 118, 105, 3, 99, 111, 109, 3, 103, 100, 115, 10,
+            97, 108, 105, 98, 97, 98, 97, 100, 110, 115, 3, 99, 111, 109, 0, 0, 28, 0, 1, 192, 36,
+            0, 6, 0, 1, 0, 0, 7, 7, 0, 35, 6, 103, 100, 115, 110, 115, 49, 192, 40, 4, 110, 111,
+            110, 101, 0, 120, 27, 176, 162, 0, 0, 7, 8, 0, 0, 2, 88, 0, 0, 14, 16, 0, 0, 1, 104, 0,
+            0, 41, 2, 0, 0, 0, 0, 0, 0, 0,
+        ];
+
+        let msg = Message::from_vec(&data).unwrap();
+        msg.to_bytes().unwrap();
+    }
+
+    #[test]
+    fn test_size_of() {
+        assert_eq!(u16::size_of(), 2);
+    }
+
+    #[test]
+    fn test_place() {
+        let mut buf = vec![];
+        {
+            let mut encoder = BinEncoder::new(&mut buf);
+            let place = encoder.place::<u16>().unwrap();
+            assert_eq!(place.size_of(), 2);
+            assert_eq!(encoder.len_since_place(&place), 0);
+
+            encoder.emit(42_u8).expect("failed 0");
+            assert_eq!(encoder.len_since_place(&place), 1);
+
+            encoder.emit(48_u8).expect("failed 1");
+            assert_eq!(encoder.len_since_place(&place), 2);
+
+            place
+                .replace(&mut encoder, 4_u16)
+                .expect("failed to replace");
+            drop(encoder);
+        }
+
+        assert_eq!(buf.len(), 4);
+
+        let mut decoder = BinDecoder::new(&buf);
+        let written = decoder.read_u16().expect("cound not read u16").unverified();
+
+        assert_eq!(written, 4);
+    }
+
+    #[test]
+    fn test_max_size() {
+        let mut buf = vec![];
+        let mut encoder = BinEncoder::new(&mut buf);
+
+        encoder.set_max_size(5);
+        encoder.emit(0).expect("failed to write");
+        encoder.emit(1).expect("failed to write");
+        encoder.emit(2).expect("failed to write");
+        encoder.emit(3).expect("failed to write");
+        encoder.emit(4).expect("failed to write");
+        let error = encoder.emit(5).unwrap_err();
+
+        match *error.kind() {
+            ProtoErrorKind::MaxBufferSizeExceeded(_) => (),
+            _ => panic!(),
+        }
+    }
+
+    #[test]
+    fn test_max_size_0() {
+        let mut buf = vec![];
+        let mut encoder = BinEncoder::new(&mut buf);
+
+        encoder.set_max_size(0);
+        let error = encoder.emit(0).unwrap_err();
+
+        match *error.kind() {
+            ProtoErrorKind::MaxBufferSizeExceeded(_) => (),
+            _ => panic!(),
+        }
+    }
+
+    #[test]
+    fn test_max_size_place() {
+        let mut buf = vec![];
+        let mut encoder = BinEncoder::new(&mut buf);
+
+        encoder.set_max_size(2);
+        let place = encoder.place::<u16>().expect("place failed");
+        place.replace(&mut encoder, 16).expect("placeback failed");
+
+        let error = encoder.place::<u16>().unwrap_err();
+
+        match *error.kind() {
+            ProtoErrorKind::MaxBufferSizeExceeded(_) => (),
+            _ => panic!(),
+        }
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/serialize/binary/mod.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/serialize/binary/mod.rs
new file mode 100644
index 0000000..1054f29
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/serialize/binary/mod.rs
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! Binary serialization types
+
+mod decoder;
+mod encoder;
+mod restrict;
+
+pub use self::decoder::BinDecoder;
+pub use self::encoder::BinEncoder;
+pub use self::encoder::EncodeMode;
+pub use self::restrict::{Restrict, RestrictedMath, Verified};
+
+#[cfg(test)]
+pub mod bin_tests;
+
+use crate::error::*;
+
+/// A type which can be encoded into a DNS binary format
+pub trait BinEncodable {
+    /// Write the type to the stream
+    fn emit(&self, encoder: &mut BinEncoder) -> ProtoResult<()>;
+
+    /// Returns the object in binary form
+    fn to_bytes(&self) -> ProtoResult<Vec<u8>> {
+        let mut bytes = Vec::<u8>::new();
+        {
+            let mut encoder = BinEncoder::new(&mut bytes);
+            self.emit(&mut encoder)?;
+        }
+
+        Ok(bytes)
+    }
+}
+
+/// A trait for types which are serializable to and from DNS binary formats
+pub trait BinDecodable<'r>: Sized {
+    /// Read the type from the stream
+    fn read(decoder: &mut BinDecoder<'r>) -> ProtoResult<Self>;
+
+    /// Returns the object in binary form
+    fn from_bytes(bytes: &'r [u8]) -> ProtoResult<Self> {
+        let mut decoder = BinDecoder::new(bytes);
+        Self::read(&mut decoder)
+    }
+}
+
+impl BinEncodable for u16 {
+    fn emit(&self, encoder: &mut BinEncoder) -> ProtoResult<()> {
+        encoder.emit_u16(*self)
+    }
+}
+
+impl<'r> BinDecodable<'r> for u16 {
+    fn read(decoder: &mut BinDecoder) -> ProtoResult<Self> {
+        decoder.read_u16().map(Restrict::unverified)
+    }
+}
+
+impl BinEncodable for i32 {
+    fn emit(&self, encoder: &mut BinEncoder) -> ProtoResult<()> {
+        encoder.emit_i32(*self)
+    }
+}
+
+impl<'r> BinDecodable<'r> for i32 {
+    fn read(decoder: &mut BinDecoder) -> ProtoResult<i32> {
+        decoder.read_i32().map(Restrict::unverified)
+    }
+}
+
+impl BinEncodable for u32 {
+    fn emit(&self, encoder: &mut BinEncoder) -> ProtoResult<()> {
+        encoder.emit_u32(*self)
+    }
+}
+
+impl<'r> BinDecodable<'r> for u32 {
+    fn read(decoder: &mut BinDecoder) -> ProtoResult<Self> {
+        decoder.read_u32().map(Restrict::unverified)
+    }
+}
+
+impl BinEncodable for Vec<u8> {
+    fn emit(&self, encoder: &mut BinEncoder) -> ProtoResult<()> {
+        encoder.emit_vec(self)
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/serialize/binary/restrict.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/serialize/binary/restrict.rs
new file mode 100644
index 0000000..be11fa4
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/serialize/binary/restrict.rs
@@ -0,0 +1,239 @@
+/// Untrusted types will be wrapped in this type.
+///
+/// To gain access to the data, some form of verification through one of the public methods is necessary.
+#[derive(Clone, Copy)]
+pub struct Restrict<T>(T);
+
+impl<T> Restrict<T> {
+    /// Create a new restricted type
+    #[inline]
+    pub fn new(restricted: T) -> Self {
+        Restrict(restricted)
+    }
+
+    /// It is the responsibility of this function to verify the contained type is valid.
+    ///
+    /// ```
+    /// use trust_dns_proto::serialize::binary::Restrict;
+    ///
+    /// let unrestricted = Restrict::new(0).verify(|r| *r == 0).then(|r| *r + 1).unwrap();
+    /// assert!(unrestricted == 1);
+    /// ```
+    ///
+    /// # Returns
+    ///
+    /// If `f` returns true then the value is valid and a chainable `Verified` type is returned
+    #[inline]
+    pub fn verify<'a, F: Fn(&'a T) -> bool>(&'a self, f: F) -> Verified<'a, T> {
+        if f(&self.0) {
+            Verified(VerifiedInner::Valid(&self.0))
+        } else {
+            Verified(VerifiedInner::Invalid(&self.0))
+        }
+    }
+
+    /// It is the responsibility of this function to verify the contained type is valid.
+    ///
+    /// ```
+    /// use trust_dns_proto::serialize::binary::Restrict;
+    ///
+    /// let unrestricted = Restrict::new(0).verify_unwrap(|r| *r == 0).unwrap();
+    /// assert!(unrestricted == 0);
+    /// ```
+    ///
+    /// # Returns
+    ///
+    /// If `f` returns true then the value is valid and `Ok(T)` is returned. Otherwise
+    ///  `Err(T)` is returned.
+    #[inline]
+    pub fn verify_unwrap<F: Fn(&T) -> bool>(self, f: F) -> Result<T, T> {
+        if f(&self.0) {
+            Ok(self.0)
+        } else {
+            Err(self.0)
+        }
+    }
+
+    /// Unwraps the value without verifying the data, akin to Result::unwrap and Option::unwrap, but will not panic
+    #[inline]
+    pub fn unverified(self) -> T {
+        self.0
+    }
+
+    /// Map the internal type of the restriction
+    ///
+    /// ```
+    /// use trust_dns_proto::serialize::binary::Restrict;
+    ///
+    /// let restricted = Restrict::new(0).map(|b| vec![b, 1]);
+    /// assert!(restricted.verify(|v| v == &[0, 1]).is_valid());
+    /// assert!(!restricted.verify(|v| v == &[1, 0]).is_valid());
+    /// ```
+    #[inline]
+    pub fn map<R, F: Fn(T) -> R>(self, f: F) -> Restrict<R> {
+        Restrict(f(self.0))
+    }
+}
+
+/// Verified data that can be operated on
+pub struct Verified<'a, T: 'a>(VerifiedInner<'a, T>);
+
+impl<'a, T> Verified<'a, T> {
+    /// Perform some operation on the data, and return a result.
+    #[inline]
+    pub fn then<R, F: Fn(&T) -> R>(&self, f: F) -> Result<R, &T> {
+        match self.0 {
+            VerifiedInner::Valid(t) => Ok(f(t)),
+            VerifiedInner::Invalid(t) => Err(t),
+        }
+    }
+
+    /// Is this valid
+    #[inline]
+    pub fn is_valid(&self) -> bool {
+        match self.0 {
+            VerifiedInner::Valid(_) => true,
+            VerifiedInner::Invalid(_) => false,
+        }
+    }
+}
+
+/// Verified data that can be operated on
+enum VerifiedInner<'a, T: 'a> {
+    Valid(&'a T),
+    Invalid(&'a T),
+}
+
+/// Common checked math operations for the Restrict type
+pub trait RestrictedMath {
+    /// Argument for the math operations
+    type Arg: 'static + Sized + Copy;
+    /// Return value, generally the same as Arg
+    type Value: 'static + Sized + Copy;
+
+    /// Checked addition, see `usize::checked_add`
+    fn checked_add(&self, arg: Self::Arg) -> Result<Restrict<Self::Value>, Self::Arg>;
+    /// Checked subtraction, see `usize::checked_sub`
+    fn checked_sub(&self, arg: Self::Arg) -> Result<Restrict<Self::Value>, Self::Arg>;
+    /// Checked multiplication, see `usize::checked_mul`
+    fn checked_mul(&self, arg: Self::Arg) -> Result<Restrict<Self::Value>, Self::Arg>;
+}
+
+impl RestrictedMath for Restrict<usize> {
+    type Arg = usize;
+    type Value = usize;
+
+    fn checked_add(&self, arg: Self::Arg) -> Result<Restrict<Self::Value>, Self::Arg> {
+        self.0.checked_add(arg).map(Restrict).ok_or_else(|| arg)
+    }
+    fn checked_sub(&self, arg: Self::Arg) -> Result<Restrict<Self::Value>, Self::Arg> {
+        self.0.checked_sub(arg).map(Restrict).ok_or_else(|| arg)
+    }
+    fn checked_mul(&self, arg: Self::Arg) -> Result<Restrict<Self::Value>, Self::Arg> {
+        self.0.checked_mul(arg).map(Restrict).ok_or_else(|| arg)
+    }
+}
+
+impl RestrictedMath for Restrict<u8> {
+    type Arg = u8;
+    type Value = u8;
+
+    fn checked_add(&self, arg: Self::Arg) -> Result<Restrict<Self::Value>, Self::Arg> {
+        self.0.checked_add(arg).map(Restrict).ok_or_else(|| arg)
+    }
+    fn checked_sub(&self, arg: Self::Arg) -> Result<Restrict<Self::Value>, Self::Arg> {
+        self.0.checked_sub(arg).map(Restrict).ok_or_else(|| arg)
+    }
+    fn checked_mul(&self, arg: Self::Arg) -> Result<Restrict<Self::Value>, Self::Arg> {
+        self.0.checked_mul(arg).map(Restrict).ok_or_else(|| arg)
+    }
+}
+
+impl RestrictedMath for Restrict<u16> {
+    type Arg = u16;
+    type Value = u16;
+
+    fn checked_add(&self, arg: Self::Arg) -> Result<Restrict<Self::Value>, Self::Arg> {
+        self.0.checked_add(arg).map(Restrict).ok_or_else(|| arg)
+    }
+    fn checked_sub(&self, arg: Self::Arg) -> Result<Restrict<Self::Value>, Self::Arg> {
+        self.0.checked_sub(arg).map(Restrict).ok_or_else(|| arg)
+    }
+    fn checked_mul(&self, arg: Self::Arg) -> Result<Restrict<Self::Value>, Self::Arg> {
+        self.0.checked_mul(arg).map(Restrict).ok_or_else(|| arg)
+    }
+}
+
+impl<R, A> RestrictedMath for Result<R, A>
+where
+    R: RestrictedMath,
+    A: 'static + Sized + Copy,
+{
+    type Arg = <R as RestrictedMath>::Arg;
+    type Value = <R as RestrictedMath>::Value;
+
+    fn checked_add(&self, arg: Self::Arg) -> Result<Restrict<Self::Value>, Self::Arg> {
+        match *self {
+            Ok(ref r) => r.checked_add(arg),
+            Err(_) => Err(arg),
+        }
+    }
+
+    fn checked_sub(&self, arg: Self::Arg) -> Result<Restrict<Self::Value>, Self::Arg> {
+        match *self {
+            Ok(ref r) => r.checked_sub(arg),
+            Err(_) => Err(arg),
+        }
+    }
+
+    fn checked_mul(&self, arg: Self::Arg) -> Result<Restrict<Self::Value>, Self::Arg> {
+        match *self {
+            Ok(ref r) => r.checked_mul(arg),
+            Err(_) => Err(arg),
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_checked_add() {
+        assert_eq!(
+            Restrict(1_usize).checked_add(2_usize).unwrap().unverified(),
+            3_usize
+        );
+        assert_eq!(
+            Restrict(1_u16).checked_add(2_u16).unwrap().unverified(),
+            3_u16
+        );
+        assert_eq!(Restrict(1_u8).checked_add(2_u8).unwrap().unverified(), 3_u8);
+    }
+
+    #[test]
+    fn test_checked_sub() {
+        assert_eq!(
+            Restrict(2_usize).checked_sub(1_usize).unwrap().unverified(),
+            1_usize
+        );
+        assert_eq!(
+            Restrict(2_u16).checked_sub(1_u16).unwrap().unverified(),
+            1_u16
+        );
+        assert_eq!(Restrict(2_u8).checked_sub(1_u8).unwrap().unverified(), 1_u8);
+    }
+
+    #[test]
+    fn test_checked_mul() {
+        assert_eq!(
+            Restrict(1_usize).checked_mul(2_usize).unwrap().unverified(),
+            2_usize
+        );
+        assert_eq!(
+            Restrict(1_u16).checked_mul(2_u16).unwrap().unverified(),
+            2_u16
+        );
+        assert_eq!(Restrict(1_u8).checked_mul(2_u8).unwrap().unverified(), 2_u8);
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/serialize/mod.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/serialize/mod.rs
new file mode 100644
index 0000000..3924f0e
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/serialize/mod.rs
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! Contains serialization libraries for `binary` and text, `txt`.
+
+pub mod binary;
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/tcp/mod.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/tcp/mod.rs
new file mode 100644
index 0000000..b4f6273
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/tcp/mod.rs
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! TCP protocol related components for DNS
+mod tcp_client_stream;
+mod tcp_stream;
+
+pub use self::tcp_client_stream::{TcpClientConnect, TcpClientStream};
+pub use self::tcp_stream::{Connect, TcpStream};
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/tcp/tcp_client_stream.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/tcp/tcp_client_stream.rs
new file mode 100644
index 0000000..199f798
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/tcp/tcp_client_stream.rs
@@ -0,0 +1,176 @@
+// Copyright 2015-2016 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+use std::fmt::{self, Display};
+#[cfg(feature = "tokio-runtime")]
+use std::io;
+use std::net::SocketAddr;
+use std::pin::Pin;
+use std::task::{Context, Poll};
+use std::time::Duration;
+
+#[cfg(feature = "tokio-runtime")]
+use async_trait::async_trait;
+use futures::io::{AsyncRead, AsyncWrite};
+use futures::{Future, Stream, StreamExt, TryFutureExt};
+use log::warn;
+
+use crate::error::ProtoError;
+#[cfg(feature = "tokio-runtime")]
+use crate::iocompat::AsyncIo02As03;
+use crate::tcp::{Connect, TcpStream};
+use crate::xfer::{DnsClientStream, SerialMessage};
+use crate::Time;
+use crate::{BufDnsStreamHandle, DnsStreamHandle};
+
+/// Tcp client stream
+///
+/// Use with `trust_dns_client::client::DnsMultiplexer` impls
+#[must_use = "futures do nothing unless polled"]
+pub struct TcpClientStream<S> {
+    tcp_stream: TcpStream<S>,
+}
+
+impl<S: Connect + 'static + Send> TcpClientStream<S> {
+    /// Constructs a new TcpStream for a client to the specified SocketAddr.
+    ///
+    /// Defaults to a 5 second timeout
+    ///
+    /// # Arguments
+    ///
+    /// * `name_server` - the IP and Port of the DNS server to connect to
+    #[allow(clippy::new_ret_no_self)]
+    pub fn new<TE: 'static + Time>(
+        name_server: SocketAddr,
+    ) -> (
+        TcpClientConnect<S::Transport>,
+        Box<dyn DnsStreamHandle + 'static + Send>,
+    ) {
+        Self::with_timeout::<TE>(name_server, Duration::from_secs(5))
+    }
+
+    /// Constructs a new TcpStream for a client to the specified SocketAddr.
+    ///
+    /// # Arguments
+    ///
+    /// * `name_server` - the IP and Port of the DNS server to connect to
+    /// * `timeout` - connection timeout
+    pub fn with_timeout<TE: 'static + Time>(
+        name_server: SocketAddr,
+        timeout: Duration,
+    ) -> (
+        TcpClientConnect<S::Transport>,
+        Box<dyn DnsStreamHandle + 'static + Send>,
+    ) {
+        let (stream_future, sender) = TcpStream::<S>::with_timeout::<TE>(name_server, timeout);
+
+        let new_future = Box::pin(
+            stream_future
+                .map_ok(move |tcp_stream| TcpClientStream { tcp_stream })
+                .map_err(ProtoError::from),
+        );
+
+        let sender = Box::new(BufDnsStreamHandle::new(name_server, sender));
+
+        (TcpClientConnect(new_future), sender)
+    }
+}
+
+impl<S: AsyncRead + AsyncWrite + Send> TcpClientStream<S> {
+    /// Wraps the TcpStream in TcpClientStream
+    pub fn from_stream(tcp_stream: TcpStream<S>) -> Self {
+        TcpClientStream { tcp_stream }
+    }
+}
+
+impl<S: AsyncRead + AsyncWrite + Send> Display for TcpClientStream<S> {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+        write!(formatter, "TCP({})", self.tcp_stream.peer_addr())
+    }
+}
+
+impl<S: AsyncRead + AsyncWrite + Send + Unpin> DnsClientStream for TcpClientStream<S> {
+    fn name_server_addr(&self) -> SocketAddr {
+        self.tcp_stream.peer_addr()
+    }
+}
+
+impl<S: AsyncRead + AsyncWrite + Send + Unpin> Stream for TcpClientStream<S> {
+    type Item = Result<SerialMessage, ProtoError>;
+
+    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
+        let message = try_ready_stream!(self.tcp_stream.poll_next_unpin(cx));
+
+        // this is busted if the tcp connection doesn't have a peer
+        let peer = self.tcp_stream.peer_addr();
+        if message.addr() != peer {
+            // TODO: this should be an error, right?
+            warn!("{} does not match name_server: {}", message.addr(), peer)
+        }
+
+        Poll::Ready(Some(Ok(message)))
+    }
+}
+
+// TODO: create unboxed future for the TCP Stream
+/// A future that resolves to an TcpClientStream
+pub struct TcpClientConnect<S>(
+    Pin<Box<dyn Future<Output = Result<TcpClientStream<S>, ProtoError>> + Send + 'static>>,
+);
+
+impl<S> Future for TcpClientConnect<S> {
+    type Output = Result<TcpClientStream<S>, ProtoError>;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+        self.0.as_mut().poll(cx)
+    }
+}
+
+#[cfg(feature = "tokio-runtime")]
+use tokio::net::TcpStream as TokioTcpStream;
+
+#[cfg(feature = "tokio-runtime")]
+#[async_trait]
+impl Connect for AsyncIo02As03<TokioTcpStream> {
+    type Transport = AsyncIo02As03<TokioTcpStream>;
+
+    async fn connect(addr: SocketAddr) -> io::Result<Self::Transport> {
+        TokioTcpStream::connect(&addr).await.map(AsyncIo02As03)
+    }
+}
+
+#[cfg(test)]
+#[cfg(feature = "tokio-runtime")]
+mod tests {
+    use super::AsyncIo02As03;
+    #[cfg(not(target_os = "linux"))]
+    use std::net::Ipv6Addr;
+    use std::net::{IpAddr, Ipv4Addr};
+    use tokio::net::TcpStream as TokioTcpStream;
+    use tokio::runtime::Runtime;
+
+    use crate::tests::tcp_client_stream_test;
+    use crate::TokioTime;
+    #[test]
+    fn test_tcp_stream_ipv4() {
+        let io_loop = Runtime::new().expect("failed to create tokio runtime");
+        tcp_client_stream_test::<AsyncIo02As03<TokioTcpStream>, Runtime, TokioTime>(
+            IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
+            io_loop,
+        )
+    }
+
+    #[test]
+    #[cfg(not(target_os = "linux"))] // ignored until Travis-CI fixes IPv6
+    fn test_tcp_stream_ipv6() {
+        let io_loop = Runtime::new().expect("failed to create tokio runtime");
+        tcp_client_stream_test::<AsyncIo02As03<TokioTcpStream>, Runtime, TokioTime>(
+            IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)),
+            io_loop,
+        )
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/tcp/tcp_stream.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/tcp/tcp_stream.rs
new file mode 100644
index 0000000..b5915c9
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/tcp/tcp_stream.rs
@@ -0,0 +1,473 @@
+// Copyright 2015-2016 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! This module contains all the TCP structures for demuxing TCP into streams of DNS packets.
+
+use std::io;
+use std::mem;
+use std::net::SocketAddr;
+use std::pin::Pin;
+use std::task::{Context, Poll};
+use std::time::Duration;
+
+use async_trait::async_trait;
+use futures::channel::mpsc::{unbounded, UnboundedReceiver};
+use futures::stream::{Fuse, Peekable, Stream, StreamExt};
+use futures::{self, ready, Future, FutureExt};
+use log::debug;
+
+use crate::error::*;
+use crate::xfer::{BufStreamHandle, SerialMessage};
+use crate::Time;
+
+/// Trait for TCP connection
+#[async_trait]
+pub trait Connect
+where
+    Self: Sized,
+{
+    /// TcpSteam
+    type Transport: futures::io::AsyncRead + futures::io::AsyncWrite + Send + Unpin;
+
+    /// connect to tcp
+    async fn connect(addr: SocketAddr) -> io::Result<Self::Transport>;
+}
+
+/// Current state while writing to the remote of the TCP connection
+enum WriteTcpState {
+    /// Currently writing the length of bytes to of the buffer.
+    LenBytes {
+        /// Current position in the length buffer being written
+        pos: usize,
+        /// Length of the buffer
+        length: [u8; 2],
+        /// Buffer to write after the length
+        bytes: Vec<u8>,
+    },
+    /// Currently writing the buffer to the remote
+    Bytes {
+        /// Current position in the buffer written
+        pos: usize,
+        /// Buffer to write to the remote
+        bytes: Vec<u8>,
+    },
+    /// Currently flushing the bytes to the remote
+    Flushing,
+}
+
+/// Current state of a TCP stream as it's being read.
+pub enum ReadTcpState {
+    /// Currently reading the length of the TCP packet
+    LenBytes {
+        /// Current position in the buffer
+        pos: usize,
+        /// Buffer of the length to read
+        bytes: [u8; 2],
+    },
+    /// Currently reading the bytes of the DNS packet
+    Bytes {
+        /// Current position while reading the buffer
+        pos: usize,
+        /// buffer being read into
+        bytes: Vec<u8>,
+    },
+}
+
+/// A Stream used for sending data to and from a remote DNS endpoint (client or server).
+#[must_use = "futures do nothing unless polled"]
+pub struct TcpStream<S> {
+    socket: S,
+    outbound_messages: Peekable<Fuse<UnboundedReceiver<SerialMessage>>>,
+    send_state: Option<WriteTcpState>,
+    read_state: ReadTcpState,
+    peer_addr: SocketAddr,
+}
+
+impl<S> TcpStream<S> {
+    /// Returns the address of the peer connection.
+    pub fn peer_addr(&self) -> SocketAddr {
+        self.peer_addr
+    }
+
+    fn pollable_split(
+        &mut self,
+    ) -> (
+        &mut S,
+        &mut Peekable<Fuse<UnboundedReceiver<SerialMessage>>>,
+        &mut Option<WriteTcpState>,
+        &mut ReadTcpState,
+    ) {
+        (
+            &mut self.socket,
+            &mut self.outbound_messages,
+            &mut self.send_state,
+            &mut self.read_state,
+        )
+    }
+}
+
+impl<S: Connect + 'static> TcpStream<S> {
+    /// Creates a new future of the eventually establish a IO stream connection or fail trying.
+    ///
+    /// Defaults to a 5 second timeout
+    ///
+    /// # Arguments
+    ///
+    /// * `name_server` - the IP and Port of the DNS server to connect to
+    #[allow(clippy::new_ret_no_self, clippy::type_complexity)]
+    pub fn new<E, TE>(
+        name_server: SocketAddr,
+    ) -> (
+        impl Future<Output = Result<TcpStream<S::Transport>, io::Error>> + Send,
+        BufStreamHandle,
+    )
+    where
+        E: FromProtoError,
+        TE: Time,
+    {
+        Self::with_timeout::<TE>(name_server, Duration::from_secs(5))
+    }
+
+    /// Creates a new future of the eventually establish a IO stream connection or fail trying
+    ///
+    /// # Arguments
+    ///
+    /// * `name_server` - the IP and Port of the DNS server to connect to
+    /// * `timeout` - connection timeout
+    #[allow(clippy::type_complexity)]
+    pub fn with_timeout<TE: Time>(
+        name_server: SocketAddr,
+        timeout: Duration,
+    ) -> (
+        impl Future<Output = Result<TcpStream<S::Transport>, io::Error>> + Send,
+        BufStreamHandle,
+    ) {
+        let (message_sender, outbound_messages) = unbounded();
+        let message_sender = BufStreamHandle::new(message_sender);
+        // This set of futures collapses the next tcp socket into a stream which can be used for
+        //  sending and receiving tcp packets.
+        let stream_fut = Self::connect::<TE>(name_server, timeout, outbound_messages);
+
+        (stream_fut, message_sender)
+    }
+
+    async fn connect<TE: Time>(
+        name_server: SocketAddr,
+        timeout: Duration,
+        outbound_messages: UnboundedReceiver<SerialMessage>,
+    ) -> Result<TcpStream<S::Transport>, io::Error> {
+        let tcp = S::connect(name_server);
+        TE::timeout(timeout, tcp)
+            .map(
+                move |tcp_stream: Result<Result<S::Transport, io::Error>, _>| {
+                    tcp_stream
+                        .and_then(|tcp_stream| tcp_stream)
+                        .map(|tcp_stream| {
+                            debug!("TCP connection established to: {}", name_server);
+                            TcpStream {
+                                socket: tcp_stream,
+                                outbound_messages: outbound_messages.fuse().peekable(),
+                                send_state: None,
+                                read_state: ReadTcpState::LenBytes {
+                                    pos: 0,
+                                    bytes: [0u8; 2],
+                                },
+                                peer_addr: name_server,
+                            }
+                        })
+                },
+            )
+            .await
+    }
+}
+
+impl<S: futures::io::AsyncRead + futures::io::AsyncWrite> TcpStream<S> {
+    /// Initializes a TcpStream.
+    ///
+    /// This is intended for use with a TcpListener and Incoming.
+    ///
+    /// # Arguments
+    ///
+    /// * `stream` - the established IO stream for communication
+    /// * `peer_addr` - sources address of the stream
+    pub fn from_stream(stream: S, peer_addr: SocketAddr) -> (Self, BufStreamHandle) {
+        let (message_sender, outbound_messages) = unbounded();
+        let message_sender = BufStreamHandle::new(message_sender);
+
+        let stream = Self::from_stream_with_receiver(stream, peer_addr, outbound_messages);
+
+        (stream, message_sender)
+    }
+
+    /// Wraps a stream where a sender and receiver have already been established
+    pub fn from_stream_with_receiver(
+        stream: S,
+        peer_addr: SocketAddr,
+        receiver: UnboundedReceiver<SerialMessage>,
+    ) -> Self {
+        TcpStream {
+            socket: stream,
+            outbound_messages: receiver.fuse().peekable(),
+            send_state: None,
+            read_state: ReadTcpState::LenBytes {
+                pos: 0,
+                bytes: [0u8; 2],
+            },
+            peer_addr,
+        }
+    }
+}
+
+impl<S: futures::io::AsyncRead + futures::io::AsyncWrite + Unpin> Stream for TcpStream<S> {
+    type Item = io::Result<SerialMessage>;
+
+    #[allow(clippy::cognitive_complexity)]
+    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
+        let peer = self.peer_addr;
+        let (socket, outbound_messages, send_state, read_state) = self.pollable_split();
+        let mut socket = Pin::new(socket);
+        let mut outbound_messages = Pin::new(outbound_messages);
+
+        // this will not accept incoming data while there is data to send
+        //  makes this self throttling.
+        // TODO: it might be interesting to try and split the sending and receiving futures.
+        loop {
+            // in the case we are sending, send it all?
+            if send_state.is_some() {
+                // sending...
+                match send_state {
+                    Some(WriteTcpState::LenBytes {
+                        ref mut pos,
+                        ref length,
+                        ..
+                    }) => {
+                        let wrote = ready!(socket.as_mut().poll_write(cx, &length[*pos..]))?;
+                        *pos += wrote;
+                    }
+                    Some(WriteTcpState::Bytes {
+                        ref mut pos,
+                        ref bytes,
+                    }) => {
+                        let wrote = ready!(socket.as_mut().poll_write(cx, &bytes[*pos..]))?;
+                        *pos += wrote;
+                    }
+                    Some(WriteTcpState::Flushing) => {
+                        ready!(socket.as_mut().poll_flush(cx))?;
+                    }
+                    _ => (),
+                }
+
+                // get current state
+                let current_state = send_state.take();
+
+                // switch states
+                match current_state {
+                    Some(WriteTcpState::LenBytes { pos, length, bytes }) => {
+                        if pos < length.len() {
+                            mem::replace(
+                                send_state,
+                                Some(WriteTcpState::LenBytes { pos, length, bytes }),
+                            );
+                        } else {
+                            mem::replace(send_state, Some(WriteTcpState::Bytes { pos: 0, bytes }));
+                        }
+                    }
+                    Some(WriteTcpState::Bytes { pos, bytes }) => {
+                        if pos < bytes.len() {
+                            mem::replace(send_state, Some(WriteTcpState::Bytes { pos, bytes }));
+                        } else {
+                            // At this point we successfully delivered the entire message.
+                            //  flush
+                            mem::replace(send_state, Some(WriteTcpState::Flushing));
+                        }
+                    }
+                    Some(WriteTcpState::Flushing) => {
+                        // At this point we successfully delivered the entire message.
+                        send_state.take();
+                    }
+                    None => (),
+                };
+            } else {
+                // then see if there is more to send
+                match outbound_messages.as_mut().poll_next(cx)
+                    // .map_err(|()| io::Error::new(io::ErrorKind::Other, "unknown"))?
+                {
+                    // already handled above, here to make sure the poll() pops the next message
+                    Poll::Ready(Some(message)) => {
+                        // if there is no peer, this connection should die...
+                        let (buffer, dst) = message.unwrap();
+
+                        // This is an error if the destination is not our peer (this is TCP after all)
+                        //  This will kill the connection...
+                        if peer != dst {
+                            return Poll::Ready(Some(Err(io::Error::new(
+                                io::ErrorKind::InvalidData,
+                                format!("mismatched peer: {} and dst: {}", peer, dst),
+                            ))));
+                        }
+
+                        // will return if the socket will block
+                        // the length is 16 bits
+                        let len: [u8; 2] = [
+                            (buffer.len() >> 8 & 0xFF) as u8,
+                            (buffer.len() & 0xFF) as u8,
+                        ];
+
+                        debug!("sending message len: {} to: {}", buffer.len(), dst);
+                        *send_state = Some(WriteTcpState::LenBytes {
+                            pos: 0,
+                            length: len,
+                            bytes: buffer,
+                        });
+                    }
+                    // now we get to drop through to the receives...
+                    // TODO: should we also return None if there are no more messages to send?
+                    Poll::Pending => break,
+                    Poll::Ready(None) => {
+                        debug!("no messages to send");
+                        break;
+                    }
+                }
+            }
+        }
+
+        let mut ret_buf: Option<Vec<u8>> = None;
+
+        // this will loop while there is data to read, or the data has been read, or an IO
+        //  event would block
+        while ret_buf.is_none() {
+            // Evaluates the next state. If None is the result, then no state change occurs,
+            //  if Some(_) is returned, then that will be used as the next state.
+            let new_state: Option<ReadTcpState> = match read_state {
+                ReadTcpState::LenBytes {
+                    ref mut pos,
+                    ref mut bytes,
+                } => {
+                    // debug!("reading length {}", bytes.len());
+                    let read = ready!(socket.as_mut().poll_read(cx, &mut bytes[*pos..]))?;
+                    if read == 0 {
+                        // the Stream was closed!
+                        debug!("zero bytes read, stream closed?");
+                        //try!(self.socket.shutdown(Shutdown::Both)); // TODO: add generic shutdown function
+
+                        if *pos == 0 {
+                            // Since this is the start of the next message, we have a clean end
+                            return Poll::Ready(None);
+                        } else {
+                            return Poll::Ready(Some(Err(io::Error::new(
+                                io::ErrorKind::BrokenPipe,
+                                "closed while reading length",
+                            ))));
+                        }
+                    }
+                    debug!("in ReadTcpState::LenBytes: {}", pos);
+                    *pos += read;
+
+                    if *pos < bytes.len() {
+                        debug!("remain ReadTcpState::LenBytes: {}", pos);
+                        None
+                    } else {
+                        let length =
+                            u16::from(bytes[0]) << 8 & 0xFF00 | u16::from(bytes[1]) & 0x00FF;
+                        debug!("got length: {}", length);
+                        let mut bytes = vec![0; length as usize];
+                        bytes.resize(length as usize, 0);
+
+                        debug!("move ReadTcpState::Bytes: {}", bytes.len());
+                        Some(ReadTcpState::Bytes { pos: 0, bytes })
+                    }
+                }
+                ReadTcpState::Bytes {
+                    ref mut pos,
+                    ref mut bytes,
+                } => {
+                    let read = ready!(socket.as_mut().poll_read(cx, &mut bytes[*pos..]))?;
+                    if read == 0 {
+                        // the Stream was closed!
+                        debug!("zero bytes read for message, stream closed?");
+
+                        // Since this is the start of the next message, we have a clean end
+                        // try!(self.socket.shutdown(Shutdown::Both));  // TODO: add generic shutdown function
+                        return Poll::Ready(Some(Err(io::Error::new(
+                            io::ErrorKind::BrokenPipe,
+                            "closed while reading message",
+                        ))));
+                    }
+
+                    debug!("in ReadTcpState::Bytes: {}", bytes.len());
+                    *pos += read;
+
+                    if *pos < bytes.len() {
+                        debug!("remain ReadTcpState::Bytes: {}", bytes.len());
+                        None
+                    } else {
+                        debug!("reset ReadTcpState::LenBytes: {}", 0);
+                        Some(ReadTcpState::LenBytes {
+                            pos: 0,
+                            bytes: [0u8; 2],
+                        })
+                    }
+                }
+            };
+
+            // this will move to the next state,
+            //  if it was a completed receipt of bytes, then it will move out the bytes
+            if let Some(state) = new_state {
+                if let ReadTcpState::Bytes { pos, bytes } = mem::replace(read_state, state) {
+                    debug!("returning bytes");
+                    assert_eq!(pos, bytes.len());
+                    ret_buf = Some(bytes);
+                }
+            }
+        }
+
+        // if the buffer is ready, return it, if not we're Pending
+        if let Some(buffer) = ret_buf {
+            debug!("returning buffer");
+            let src_addr = self.peer_addr;
+            Poll::Ready(Some(Ok(SerialMessage::new(buffer, src_addr))))
+        } else {
+            debug!("bottomed out");
+            // at a minimum the outbound_messages should have been polled,
+            //  which will wake this future up later...
+            Poll::Pending
+        }
+    }
+}
+
+#[cfg(test)]
+#[cfg(feature = "tokio-runtime")]
+mod tests {
+    #[cfg(not(target_os = "linux"))]
+    use std::net::Ipv6Addr;
+    use std::net::{IpAddr, Ipv4Addr};
+    use tokio::net::TcpStream as TokioTcpStream;
+    use tokio::runtime::Runtime;
+
+    use crate::iocompat::AsyncIo02As03;
+    use crate::TokioTime;
+
+    use crate::tests::tcp_stream_test;
+    #[test]
+    fn test_tcp_stream_ipv4() {
+        let io_loop = Runtime::new().expect("failed to create tokio runtime");
+        tcp_stream_test::<AsyncIo02As03<TokioTcpStream>, Runtime, TokioTime>(
+            IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
+            io_loop,
+        )
+    }
+
+    #[test]
+    #[cfg(not(target_os = "linux"))] // ignored until Travis-CI fixes IPv6
+    fn test_tcp_stream_ipv6() {
+        let io_loop = Runtime::new().expect("failed to create tokio runtime");
+        tcp_stream_test::<AsyncIo02As03<TokioTcpStream>, Runtime, TokioTime>(
+            IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)),
+            io_loop,
+        )
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/tests/mod.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/tests/mod.rs
new file mode 100644
index 0000000..7249d38
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/tests/mod.rs
@@ -0,0 +1,10 @@
+//! Tests for TCP and UDP stream and client
+
+mod tcp;
+mod udp;
+
+pub use self::tcp::tcp_client_stream_test;
+pub use self::tcp::tcp_stream_test;
+pub use self::udp::next_random_socket_test;
+pub use self::udp::udp_client_stream_test;
+pub use self::udp::udp_stream_test;
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/tests/tcp.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/tests/tcp.rs
new file mode 100644
index 0000000..a2ea4ae
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/tests/tcp.rs
@@ -0,0 +1,157 @@
+use std::io::{Read, Write};
+use std::net::{IpAddr, SocketAddr};
+use std::sync::{atomic::AtomicBool, Arc};
+
+use futures::io::{AsyncRead, AsyncWrite};
+use futures::stream::StreamExt;
+
+use crate::error::ProtoError;
+use crate::tcp::{Connect, TcpClientStream, TcpStream};
+use crate::xfer::SerialMessage;
+use crate::{Executor, Time};
+
+const TEST_BYTES: &[u8; 8] = b"DEADBEEF";
+const TEST_BYTES_LEN: usize = 8;
+const SEND_RECV_TIMES: usize = 4;
+
+fn tcp_server_setup(
+    server_name: &str,
+    server_addr: IpAddr,
+) -> (Arc<AtomicBool>, std::thread::JoinHandle<()>, SocketAddr) {
+    let succeeded = Arc::new(AtomicBool::new(false));
+    let succeeded_clone = succeeded.clone();
+    std::thread::Builder::new()
+        .name("thread_killer".to_string())
+        .spawn(move || {
+            let succeeded = succeeded_clone;
+            for _ in 0..15 {
+                std::thread::sleep(std::time::Duration::from_secs(1));
+                if succeeded.load(std::sync::atomic::Ordering::Relaxed) {
+                    return;
+                }
+            }
+
+            panic!("timeout");
+        })
+        .unwrap();
+
+    // TODO: need a timeout on listen
+    let server = std::net::TcpListener::bind(SocketAddr::new(server_addr, 0)).unwrap();
+    let server_addr = server.local_addr().unwrap();
+
+    // an in and out server
+    let server_handle = std::thread::Builder::new()
+        .name(server_name.to_string())
+        .spawn(move || {
+            let (mut socket, _) = server.accept().expect("accept failed");
+
+            socket
+                .set_read_timeout(Some(std::time::Duration::from_secs(5)))
+                .unwrap(); // should receive something within 5 seconds...
+            socket
+                .set_write_timeout(Some(std::time::Duration::from_secs(5)))
+                .unwrap(); // should receive something within 5 seconds...
+
+            for _ in 0..SEND_RECV_TIMES {
+                // wait for some bytes...
+                let mut len_bytes = [0_u8; 2];
+                socket
+                    .read_exact(&mut len_bytes)
+                    .expect("SERVER: receive failed");
+                let length =
+                    u16::from(len_bytes[0]) << 8 & 0xFF00 | u16::from(len_bytes[1]) & 0x00FF;
+                assert_eq!(length as usize, TEST_BYTES_LEN);
+
+                let mut buffer = [0_u8; TEST_BYTES_LEN];
+                socket.read_exact(&mut buffer).unwrap();
+
+                // println!("read bytes iter: {}", i);
+                assert_eq!(&buffer, TEST_BYTES);
+
+                // bounce them right back...
+                socket
+                    .write_all(&len_bytes)
+                    .expect("SERVER: send length failed");
+                socket
+                    .write_all(&buffer)
+                    .expect("SERVER: send buffer failed");
+                // println!("wrote bytes iter: {}", i);
+                std::thread::yield_now();
+            }
+        })
+        .unwrap();
+    (succeeded, server_handle, server_addr)
+}
+
+/// Test tcp_stream.
+pub fn tcp_stream_test<S: Connect + 'static, E: Executor, TE: Time>(
+    server_addr: IpAddr,
+    mut exec: E,
+) where
+    <S as Connect>::Transport: AsyncRead + AsyncWrite + Unpin,
+{
+    let (succeeded, server_handle, server_addr) =
+        tcp_server_setup("test_tcp_stream:server", server_addr);
+
+    // setup the client, which is going to run on the testing thread...
+
+    // the tests should run within 5 seconds... right?
+    // TODO: add timeout here, so that test never hangs...
+    // let timeout = Timeout::new(Duration::from_secs(5));
+    let (stream, sender) = TcpStream::<S>::new::<ProtoError, TE>(server_addr);
+
+    let mut stream = exec.block_on(stream).expect("run failed to get stream");
+
+    for _ in 0..SEND_RECV_TIMES {
+        // test once
+        sender
+            .unbounded_send(SerialMessage::new(TEST_BYTES.to_vec(), server_addr))
+            .expect("send failed");
+
+        let (buffer, stream_tmp) = exec.block_on(stream.into_future());
+        stream = stream_tmp;
+        let message = buffer
+            .expect("no buffer received")
+            .expect("error receiving buffer");
+        assert_eq!(message.bytes(), TEST_BYTES);
+    }
+
+    succeeded.store(true, std::sync::atomic::Ordering::Relaxed);
+    server_handle.join().expect("server thread failed");
+}
+
+/// Test tcp_client_stream.
+pub fn tcp_client_stream_test<S: Connect + Send + 'static, E: Executor, TE: Time + 'static>(
+    server_addr: IpAddr,
+    mut exec: E,
+) where
+    <S as Connect>::Transport: AsyncRead + AsyncWrite + Unpin,
+{
+    let (succeeded, server_handle, server_addr) =
+        tcp_server_setup("test_tcp_client_stream:server", server_addr);
+
+    // setup the client, which is going to run on the testing thread...
+
+    // the tests should run within 5 seconds... right?
+    // TODO: add timeout here, so that test never hangs...
+    // let timeout = Timeout::new(Duration::from_secs(5));
+    let (stream, mut sender) = TcpClientStream::<S>::new::<TE>(server_addr);
+
+    let mut stream = exec.block_on(stream).expect("run failed to get stream");
+
+    for _ in 0..SEND_RECV_TIMES {
+        // test once
+        sender
+            .send(SerialMessage::new(TEST_BYTES.to_vec(), server_addr))
+            .expect("send failed");
+        let (buffer, stream_tmp) = exec.block_on(stream.into_future());
+        stream = stream_tmp;
+        let buffer = buffer
+            .expect("no buffer received")
+            .expect("error receiving buffer");
+        assert_eq!(buffer.bytes(), TEST_BYTES);
+    }
+
+    succeeded.store(true, std::sync::atomic::Ordering::Relaxed);
+    server_handle.join().expect("server thread failed");
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/tests/udp.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/tests/udp.rs
new file mode 100644
index 0000000..4279e83
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/tests/udp.rs
@@ -0,0 +1,236 @@
+use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+
+use futures::stream::StreamExt;
+use log::debug;
+
+use crate::udp::{UdpClientStream, UdpSocket, UdpStream};
+use crate::{Executor, Time};
+
+/// Test next random udpsocket.
+pub fn next_random_socket_test<S: UdpSocket + Send + 'static, E: Executor>(mut exec: E) {
+    let (stream, _) =
+        UdpStream::<S>::new(SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 52));
+    drop(
+        exec.block_on(stream)
+            .expect("failed to get next socket address"),
+    );
+}
+
+/// Test udp_stream.
+pub fn udp_stream_test<S: UdpSocket + Send + 'static, E: Executor>(
+    server_addr: IpAddr,
+    mut exec: E,
+) {
+    use crate::xfer::SerialMessage;
+    use std::net::ToSocketAddrs;
+
+    let succeeded = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false));
+    let succeeded_clone = succeeded.clone();
+    std::thread::Builder::new()
+        .name("thread_killer".to_string())
+        .spawn(move || {
+            let succeeded = succeeded_clone;
+            for _ in 0..15 {
+                std::thread::sleep(std::time::Duration::from_secs(1));
+                if succeeded.load(std::sync::atomic::Ordering::Relaxed) {
+                    return;
+                }
+            }
+
+            panic!("timeout");
+        })
+        .unwrap();
+
+    let server = std::net::UdpSocket::bind(SocketAddr::new(server_addr, 0)).unwrap();
+    server
+        .set_read_timeout(Some(std::time::Duration::from_secs(5)))
+        .unwrap(); // should receive something within 5 seconds...
+    server
+        .set_write_timeout(Some(std::time::Duration::from_secs(5)))
+        .unwrap(); // should receive something within 5 seconds...
+    let server_addr = server.local_addr().unwrap();
+
+    let test_bytes: &'static [u8; 8] = b"DEADBEEF";
+    let send_recv_times = 4;
+
+    // an in and out server
+    let server_handle = std::thread::Builder::new()
+        .name("test_udp_stream_ipv4:server".to_string())
+        .spawn(move || {
+            let mut buffer = [0_u8; 512];
+
+            for _ in 0..send_recv_times {
+                // wait for some bytes...
+                let (len, addr) = server.recv_from(&mut buffer).expect("receive failed");
+
+                assert_eq!(&buffer[0..len], test_bytes);
+
+                // bounce them right back...
+                assert_eq!(
+                    server.send_to(&buffer[0..len], addr).expect("send failed"),
+                    len
+                );
+            }
+        })
+        .unwrap();
+
+    // setup the client, which is going to run on the testing thread...
+    // the tests should run within 5 seconds... right?
+    // TODO: add timeout here, so that test never hangs...
+    let client_addr = match server_addr {
+        std::net::SocketAddr::V4(_) => "127.0.0.1:0",
+        std::net::SocketAddr::V6(_) => "[::1]:0",
+    };
+
+    let socket = exec
+        .block_on(S::bind(
+            &client_addr.to_socket_addrs().unwrap().next().unwrap(),
+        ))
+        .expect("could not create socket"); // some random address...
+    let (mut stream, sender) = UdpStream::<S>::with_bound(socket);
+
+    for _ in 0..send_recv_times {
+        // test once
+        sender
+            .unbounded_send(SerialMessage::new(test_bytes.to_vec(), server_addr))
+            .unwrap();
+        let (buffer_and_addr, stream_tmp) = exec.block_on(stream.into_future());
+        stream = stream_tmp;
+        let message = buffer_and_addr
+            .expect("no buffer received")
+            .expect("error receiving buffer");
+        assert_eq!(message.bytes(), test_bytes);
+        assert_eq!(message.addr(), server_addr);
+    }
+
+    succeeded.store(true, std::sync::atomic::Ordering::Relaxed);
+    server_handle.join().expect("server thread failed");
+}
+
+/// Test udp_client_stream.
+#[allow(clippy::print_stdout)]
+pub fn udp_client_stream_test<S: UdpSocket + Send + 'static, E: Executor, TE: Time>(
+    server_addr: IpAddr,
+    mut exec: E,
+) {
+    use crate::op::{Message, Query};
+    use crate::rr::rdata::NULL;
+    use crate::rr::{Name, RData, Record, RecordType};
+    use crate::xfer::{DnsRequest, DnsRequestSender};
+    use futures::future;
+    use std::str::FromStr;
+    use std::time::Duration;
+
+    // use env_logger;
+    // env_logger::try_init().ok();
+
+    let succeeded = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false));
+    let succeeded_clone = succeeded.clone();
+    std::thread::Builder::new()
+        .name("thread_killer".to_string())
+        .spawn(move || {
+            let succeeded = succeeded_clone;
+            for _ in 0..15 {
+                std::thread::sleep(std::time::Duration::from_secs(1));
+                if succeeded.load(std::sync::atomic::Ordering::Relaxed) {
+                    return;
+                }
+            }
+
+            panic!("timeout");
+        })
+        .unwrap();
+
+    let server = std::net::UdpSocket::bind(SocketAddr::new(server_addr, 0)).unwrap();
+    server
+        .set_read_timeout(Some(std::time::Duration::from_secs(5)))
+        .unwrap(); // should receive something within 5 seconds...
+    server
+        .set_write_timeout(Some(std::time::Duration::from_secs(5)))
+        .unwrap(); // should receive something within 5 seconds...
+    let server_addr = server.local_addr().unwrap();
+
+    let mut query = Message::new();
+    let test_name = Name::from_str("dead.beef").unwrap();
+    query.add_query(Query::query(test_name.clone(), RecordType::NULL));
+    let test_bytes: &'static [u8; 8] = b"DEADBEEF";
+    let send_recv_times = 4;
+
+    let test_name_server = test_name;
+    // an in and out server
+    let server_handle = std::thread::Builder::new()
+        .name("test_udp_client_stream_ipv4:server".to_string())
+        .spawn(move || {
+            let mut buffer = [0_u8; 512];
+
+            for i in 0..send_recv_times {
+                // wait for some bytes...
+                debug!("server receiving request {}", i);
+                let (len, addr) = server.recv_from(&mut buffer).expect("receive failed");
+                debug!("server received request {} from: {}", i, addr);
+
+                let request = Message::from_vec(&buffer[0..len]).expect("failed parse of request");
+                assert_eq!(*request.queries()[0].name(), test_name_server.clone());
+                assert_eq!(request.queries()[0].query_type(), RecordType::NULL);
+
+                let mut message = Message::new();
+                message.set_id(request.id());
+                message.add_queries(request.queries().to_vec());
+                message.add_answer(Record::from_rdata(
+                    test_name_server.clone(),
+                    0,
+                    RData::NULL(NULL::with(test_bytes.to_vec())),
+                ));
+
+                // bounce them right back...
+                let bytes = message.to_vec().unwrap();
+                debug!("server sending response {} to: {}", i, addr);
+                assert_eq!(
+                    server.send_to(&bytes, addr).expect("send failed"),
+                    bytes.len()
+                );
+                debug!("server sent response {}", i);
+                std::thread::yield_now();
+            }
+        })
+        .unwrap();
+
+    // setup the client, which is going to run on the testing thread...
+
+    // the tests should run within 5 seconds... right?
+    // TODO: add timeout here, so that test never hangs...
+    // let timeout = Timeout::new(Duration::from_secs(5));
+    let stream = UdpClientStream::with_timeout(server_addr, Duration::from_millis(500));
+    let mut stream: UdpClientStream<S> = exec.block_on(stream).ok().unwrap();
+    let mut worked_once = false;
+
+    for i in 0..send_recv_times {
+        // test once
+        let response_future = exec.block_on(future::lazy(|cx| {
+            stream.send_message::<TE>(DnsRequest::new(query.clone(), Default::default()), cx)
+        }));
+        println!("client sending request {}", i);
+        let response = match exec.block_on(response_future) {
+            Ok(response) => response,
+            Err(err) => {
+                println!("failed to get message: {}", err);
+                continue;
+            }
+        };
+        println!("client got response {}", i);
+
+        let response = Message::from(response);
+        if let RData::NULL(null) = response.answers()[0].rdata() {
+            assert_eq!(null.anything().expect("no bytes in NULL"), test_bytes);
+        } else {
+            panic!("not a NULL response");
+        }
+
+        worked_once = true;
+    }
+
+    succeeded.store(true, std::sync::atomic::Ordering::Relaxed);
+    server_handle.join().expect("server thread failed");
+
+    assert!(worked_once);
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/udp/mod.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/udp/mod.rs
new file mode 100644
index 0000000..9df9e2b
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/udp/mod.rs
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
+ *
+ * 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.
+ */
+
+//! UDP protocol related components for DNS
+
+mod udp_client_stream;
+mod udp_stream;
+
+pub use self::udp_client_stream::{UdpClientConnect, UdpClientStream, UdpResponse};
+pub use self::udp_stream::{UdpSocket, UdpStream};
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/udp/udp_client_stream.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/udp/udp_client_stream.rs
new file mode 100644
index 0000000..99a65cb
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/udp/udp_client_stream.rs
@@ -0,0 +1,381 @@
+// Copyright 2015-2016 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+use std::borrow::Borrow;
+use std::fmt::{self, Display};
+use std::io;
+use std::marker::PhantomData;
+use std::net::SocketAddr;
+use std::pin::Pin;
+use std::sync::Arc;
+use std::task::{Context, Poll};
+use std::time::{Duration, SystemTime, UNIX_EPOCH};
+
+use futures::{Future, Stream};
+use log::{debug, warn};
+
+use crate::error::ProtoError;
+use crate::op::message::NoopMessageFinalizer;
+use crate::op::{MessageFinalizer, OpCode};
+use crate::udp::udp_stream::{NextRandomUdpSocket, UdpSocket};
+use crate::xfer::{DnsRequest, DnsRequestSender, DnsResponse, SerialMessage};
+use crate::Time;
+
+/// A UDP client stream of DNS binary packets
+///
+/// This stream will create a new UDP socket for every request. This is to avoid potential cache
+///   poisoning during use by UDP based attacks.
+#[must_use = "futures do nothing unless polled"]
+pub struct UdpClientStream<S, MF = NoopMessageFinalizer>
+where
+    S: Send,
+    MF: MessageFinalizer,
+{
+    name_server: SocketAddr,
+    timeout: Duration,
+    is_shutdown: bool,
+    signer: Option<Arc<MF>>,
+    marker: PhantomData<S>,
+}
+
+impl<S: Send> UdpClientStream<S, NoopMessageFinalizer> {
+    /// it is expected that the resolver wrapper will be responsible for creating and managing
+    ///  new UdpClients such that each new client would have a random port (reduce chance of cache
+    ///  poisoning)
+    ///
+    /// # Return
+    ///
+    /// a tuple of a Future Stream which will handle sending and receiving messages, and a
+    ///  handle which can be used to send messages into the stream.
+    #[allow(clippy::new_ret_no_self)]
+    pub fn new(name_server: SocketAddr) -> UdpClientConnect<S, NoopMessageFinalizer> {
+        Self::with_timeout(name_server, Duration::from_secs(5))
+    }
+
+    /// Constructs a new UdpStream for a client to the specified SocketAddr.
+    ///
+    /// # Arguments
+    ///
+    /// * `name_server` - the IP and Port of the DNS server to connect to
+    /// * `timeout` - connection timeout
+    pub fn with_timeout(
+        name_server: SocketAddr,
+        timeout: Duration,
+    ) -> UdpClientConnect<S, NoopMessageFinalizer> {
+        Self::with_timeout_and_signer(name_server, timeout, None)
+    }
+}
+
+impl<S: Send, MF: MessageFinalizer> UdpClientStream<S, MF> {
+    /// Constructs a new TcpStream for a client to the specified SocketAddr.
+    ///
+    /// # Arguments
+    ///
+    /// * `name_server` - the IP and Port of the DNS server to connect to
+    /// * `timeout` - connection timeout
+    pub fn with_timeout_and_signer(
+        name_server: SocketAddr,
+        timeout: Duration,
+        signer: Option<Arc<MF>>,
+    ) -> UdpClientConnect<S, MF> {
+        UdpClientConnect {
+            name_server: Some(name_server),
+            timeout,
+            signer,
+            marker: PhantomData::<S>,
+        }
+    }
+}
+
+impl<S: Send, MF: MessageFinalizer> Display for UdpClientStream<S, MF> {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+        write!(formatter, "UDP({})", self.name_server)
+    }
+}
+
+/// creates random query_id, each socket is unique, no need for global uniqueness
+fn random_query_id() -> u16 {
+    use rand::distributions::{Distribution, Standard};
+    let mut rand = rand::thread_rng();
+
+    Standard.sample(&mut rand)
+}
+
+impl<S: UdpSocket + Send + 'static, MF: MessageFinalizer> DnsRequestSender
+    for UdpClientStream<S, MF>
+{
+    type DnsResponseFuture = UdpResponse;
+
+    fn send_message<TE: Time>(
+        &mut self,
+        mut message: DnsRequest,
+        _cx: &mut Context,
+    ) -> Self::DnsResponseFuture {
+        if self.is_shutdown {
+            panic!("can not send messages after stream is shutdown")
+        }
+
+        // associated the ID for this request, b/c this connection is unique to socket port, the ID
+        //   does not need to be globally unique
+        message.set_id(random_query_id());
+
+        let now = match SystemTime::now()
+            .duration_since(UNIX_EPOCH)
+            .map_err(|_| ProtoError::from("Current time is before the Unix epoch."))
+        {
+            Ok(now) => now.as_secs(),
+            Err(err) => {
+                let err: ProtoError = err;
+
+                return UdpResponse::complete::<_, TE>(SingleUseUdpSocket::errored(err));
+            }
+        };
+
+        // TODO: truncates u64 to u32, error on overflow?
+        let now = now as u32;
+
+        // TODO: move this logic into Message::finalize?
+        if let OpCode::Update = message.op_code() {
+            if let Some(ref signer) = self.signer {
+                if let Err(e) = message.finalize::<MF>(signer.borrow(), now) {
+                    debug!("could not sign message: {}", e);
+                    return UdpResponse::complete::<_, TE>(SingleUseUdpSocket::errored(e));
+                }
+            }
+        }
+
+        let bytes = match message.to_vec() {
+            Ok(bytes) => bytes,
+            Err(err) => {
+                return UdpResponse::complete::<_, TE>(SingleUseUdpSocket::errored(err));
+            }
+        };
+
+        let message_id = message.id();
+        let message = SerialMessage::new(bytes, self.name_server);
+
+        UdpResponse::new::<S, TE>(message, message_id, self.timeout)
+    }
+
+    fn error_response<TE: Time>(err: ProtoError) -> Self::DnsResponseFuture {
+        UdpResponse::complete::<_, TE>(SingleUseUdpSocket::errored(err))
+    }
+
+    fn shutdown(&mut self) {
+        self.is_shutdown = true;
+    }
+
+    fn is_shutdown(&self) -> bool {
+        self.is_shutdown
+    }
+}
+
+// TODO: is this impl necessary? there's nothing being driven here...
+impl<S: Send, MF: MessageFinalizer> Stream for UdpClientStream<S, MF> {
+    type Item = Result<(), ProtoError>;
+
+    fn poll_next(self: Pin<&mut Self>, _cx: &mut Context) -> Poll<Option<Self::Item>> {
+        // Technically the Stream doesn't actually do anything.
+        if self.is_shutdown {
+            Poll::Ready(None)
+        } else {
+            Poll::Ready(Some(Ok(())))
+        }
+    }
+}
+
+/// A future that resolves to
+#[allow(clippy::type_complexity)]
+pub struct UdpResponse(
+    Pin<Box<dyn Future<Output = Result<Result<DnsResponse, ProtoError>, io::Error>> + Send>>,
+);
+
+impl UdpResponse {
+    /// creates a new future for the request
+    ///
+    /// # Arguments
+    ///
+    /// * `request` - Serialized message being sent
+    /// * `message_id` - Id of the message that was encoded in the serial message
+    fn new<S: UdpSocket + Send + Unpin + 'static, T: Time>(
+        request: SerialMessage,
+        message_id: u16,
+        timeout: Duration,
+    ) -> Self {
+        UdpResponse(T::timeout::<
+            Pin<Box<dyn Future<Output = Result<DnsResponse, ProtoError>> + Send>>,
+        >(
+            timeout,
+            Box::pin(SingleUseUdpSocket::send_serial_message::<S>(
+                request, message_id,
+            )),
+        ))
+    }
+
+    /// ad already completed future
+    fn complete<F: Future<Output = Result<DnsResponse, ProtoError>> + Send + 'static, T: Time>(
+        f: F,
+    ) -> Self {
+        // TODO: this constructure isn't really necessary
+        UdpResponse(T::timeout::<
+            Pin<Box<dyn Future<Output = Result<DnsResponse, ProtoError>> + Send>>,
+        >(Duration::from_secs(5), Box::pin(f)))
+    }
+}
+
+impl Future for UdpResponse {
+    type Output = Result<DnsResponse, ProtoError>;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+        self.0
+            .as_mut()
+            .poll(cx)
+            .map_err(ProtoError::from)
+            .map(|r| r.and_then(|r| r))
+    }
+}
+
+/// A future that resolves to an UdpClientStream
+pub struct UdpClientConnect<S, MF = NoopMessageFinalizer>
+where
+    S: Send,
+    MF: MessageFinalizer,
+{
+    name_server: Option<SocketAddr>,
+    timeout: Duration,
+    signer: Option<Arc<MF>>,
+    marker: PhantomData<S>,
+}
+
+impl<S: Send + Unpin, MF: MessageFinalizer> Future for UdpClientConnect<S, MF> {
+    type Output = Result<UdpClientStream<S, MF>, ProtoError>;
+
+    fn poll(mut self: Pin<&mut Self>, _cx: &mut Context) -> Poll<Self::Output> {
+        // TODO: this doesn't need to be a future?
+        Poll::Ready(Ok(UdpClientStream::<S, MF> {
+            name_server: self
+                .name_server
+                .take()
+                .expect("UdpClientConnect invalid state: name_server"),
+            is_shutdown: false,
+            timeout: self.timeout,
+            signer: self.signer.take(),
+            marker: PhantomData,
+        }))
+    }
+}
+
+struct SingleUseUdpSocket;
+
+impl SingleUseUdpSocket {
+    async fn send_serial_message<S: UdpSocket + Send>(
+        msg: SerialMessage,
+        msg_id: u16,
+    ) -> Result<DnsResponse, ProtoError> {
+        let name_server = msg.addr();
+        let mut socket: S = NextRandomUdpSocket::new(&name_server).await?;
+        let bytes = msg.bytes();
+        let addr = &msg.addr();
+        let len_sent: usize = socket.send_to(bytes, addr).await?;
+
+        if bytes.len() != len_sent {
+            return Err(ProtoError::from(format!(
+                "Not all bytes of message sent, {} of {}",
+                len_sent,
+                bytes.len()
+            )));
+        }
+
+        // TODO: limit the max number of attempted messages? this relies on a timeout to die...
+        loop {
+            // TODO: consider making this heap based? need to verify it matches EDNS settings
+            let mut recv_buf = [0u8; 2048];
+
+            let (len, src) = socket.recv_from(&mut recv_buf).await?;
+            let response = SerialMessage::new(recv_buf.iter().take(len).cloned().collect(), src);
+
+            // compare expected src to received packet
+            let request_target = msg.addr();
+
+            if response.addr() != request_target {
+                warn!(
+                    "ignoring response from {} because it does not match name_server: {}.",
+                    response.addr(),
+                    request_target,
+                );
+
+                // await an answer from the correct NameServer
+                continue;
+            }
+
+            // TODO: match query strings from request and response?
+
+            match response.to_message() {
+                Ok(message) => {
+                    if msg_id == message.id() {
+                        debug!("received message id: {}", message.id());
+                        return Ok(DnsResponse::from(message));
+                    } else {
+                        // on wrong id, attempted poison?
+                        warn!(
+                            "expected message id: {} got: {}, dropped",
+                            msg_id,
+                            message.id()
+                        );
+
+                        continue;
+                    }
+                }
+                Err(e) => {
+                    // on errors deserializing, continue
+                    warn!(
+                        "dropped malformed message waiting for id: {} err: {}",
+                        msg_id, e
+                    );
+
+                    continue;
+                }
+            }
+        }
+    }
+
+    // TODO: this is unnecessary
+    async fn errored(err: ProtoError) -> Result<DnsResponse, ProtoError> {
+        futures::future::err(err).await
+    }
+}
+
+#[cfg(test)]
+#[cfg(feature = "tokio-runtime")]
+mod tests {
+    #![allow(clippy::dbg_macro, clippy::print_stdout)]
+    use crate::tests::udp_client_stream_test;
+    use crate::TokioTime;
+    #[cfg(not(target_os = "linux"))]
+    use std::net::Ipv6Addr;
+    use std::net::{IpAddr, Ipv4Addr};
+    use tokio::{net::UdpSocket as TokioUdpSocket, runtime::Runtime};
+
+    #[test]
+    fn test_udp_client_stream_ipv4() {
+        let io_loop = Runtime::new().expect("failed to create tokio runtime");
+        udp_client_stream_test::<TokioUdpSocket, Runtime, TokioTime>(
+            IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
+            io_loop,
+        )
+    }
+
+    #[test]
+    #[cfg(not(target_os = "linux"))] // ignored until Travis-CI fixes IPv6
+    fn test_udp_client_stream_ipv6() {
+        let io_loop = Runtime::new().expect("failed to create tokio runtime");
+        udp_client_stream_test::<TokioUdpSocket, Runtime, TokioTime>(
+            IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)),
+            io_loop,
+        )
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/udp/udp_stream.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/udp/udp_stream.rs
new file mode 100644
index 0000000..0adcf51d
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/udp/udp_stream.rs
@@ -0,0 +1,288 @@
+// Copyright 2015-2018 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+use std::io;
+use std::marker::PhantomData;
+use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
+use std::pin::Pin;
+use std::task::{Context, Poll};
+
+use async_trait::async_trait;
+use futures::channel::mpsc::{unbounded, UnboundedReceiver};
+use futures::stream::{Fuse, Peekable, Stream, StreamExt};
+use futures::{ready, Future, FutureExt, TryFutureExt};
+use log::debug;
+use rand;
+use rand::distributions::{uniform::Uniform, Distribution};
+
+use crate::xfer::{BufStreamHandle, SerialMessage};
+
+/// Trait for UdpSocket
+#[async_trait]
+pub trait UdpSocket
+where
+    Self: Sized + Unpin,
+{
+    /// UdpSocket
+    async fn bind(addr: &SocketAddr) -> io::Result<Self>;
+    /// Receive data from the socket and returns the number of bytes read and the address from
+    /// where the data came on success.
+    async fn recv_from(&mut self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)>;
+    /// Send data to the given address.
+    async fn send_to(&mut self, buf: &[u8], target: &SocketAddr) -> io::Result<usize>;
+}
+
+/// A UDP stream of DNS binary packets
+#[must_use = "futures do nothing unless polled"]
+pub struct UdpStream<S: Send> {
+    socket: S,
+    outbound_messages: Peekable<Fuse<UnboundedReceiver<SerialMessage>>>,
+}
+
+impl<S: UdpSocket + Send + 'static> UdpStream<S> {
+    /// This method is intended for client connections, see `with_bound` for a method better for
+    ///  straight listening. It is expected that the resolver wrapper will be responsible for
+    ///  creating and managing new UdpStreams such that each new client would have a random port
+    ///  (reduce chance of cache poisoning). This will return a randomly assigned local port.
+    ///
+    /// # Arguments
+    ///
+    /// * `name_server` - socket address for the remote server (used to determine IPv4 or IPv6)
+    ///
+    /// # Return
+    ///
+    /// a tuple of a Future Stream which will handle sending and receiving messages, and a
+    ///  handle which can be used to send messages into the stream.
+    #[allow(clippy::type_complexity)]
+    pub fn new(
+        name_server: SocketAddr,
+    ) -> (
+        Box<dyn Future<Output = Result<UdpStream<S>, io::Error>> + Send + Unpin>,
+        BufStreamHandle,
+    ) {
+        let (message_sender, outbound_messages) = unbounded();
+        let message_sender = BufStreamHandle::new(message_sender);
+
+        // TODO: allow the bind address to be specified...
+        // constructs a future for getting the next randomly bound port to a UdpSocket
+        let next_socket = NextRandomUdpSocket::new(&name_server);
+
+        // This set of futures collapses the next udp socket into a stream which can be used for
+        //  sending and receiving udp packets.
+        let stream = Box::new(next_socket.map_ok(move |socket| UdpStream {
+            socket,
+            outbound_messages: outbound_messages.fuse().peekable(),
+        }));
+
+        (stream, message_sender)
+    }
+
+    /// Initialize the Stream with an already bound socket. Generally this should be only used for
+    ///  server listening sockets. See `new` for a client oriented socket. Specifically, this there
+    ///  is already a bound socket in this context, whereas `new` makes sure to randomize ports
+    ///  for additional cache poison prevention.
+    ///
+    /// # Arguments
+    ///
+    /// * `socket` - an already bound UDP socket
+    ///
+    /// # Return
+    ///
+    /// a tuple of a Future Stream which will handle sending and receiving messsages, and a
+    ///  handle which can be used to send messages into the stream.
+    pub fn with_bound(socket: S) -> (Self, BufStreamHandle) {
+        let (message_sender, outbound_messages) = unbounded();
+        let message_sender = BufStreamHandle::new(message_sender);
+
+        let stream = UdpStream {
+            socket,
+            outbound_messages: outbound_messages.fuse().peekable(),
+        };
+
+        (stream, message_sender)
+    }
+
+    #[allow(unused)]
+    pub(crate) fn from_parts(
+        socket: S,
+        outbound_messages: UnboundedReceiver<SerialMessage>,
+    ) -> Self {
+        UdpStream {
+            socket,
+            outbound_messages: outbound_messages.fuse().peekable(),
+        }
+    }
+}
+
+impl<S: Send> UdpStream<S> {
+    #[allow(clippy::type_complexity)]
+    fn pollable_split(
+        &mut self,
+    ) -> (
+        &mut S,
+        &mut Peekable<Fuse<UnboundedReceiver<SerialMessage>>>,
+    ) {
+        (&mut self.socket, &mut self.outbound_messages)
+    }
+}
+
+impl<S: UdpSocket + Send + 'static> Stream for UdpStream<S> {
+    type Item = Result<SerialMessage, io::Error>;
+
+    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
+        let (socket, outbound_messages) = self.pollable_split();
+        let mut socket = Pin::new(socket);
+        let mut outbound_messages = Pin::new(outbound_messages);
+
+        // this will not accept incoming data while there is data to send
+        //  makes this self throttling.
+        while let Poll::Ready(Some(message)) = outbound_messages.as_mut().poll_peek(cx) {
+            // first try to send
+            let addr = &message.addr();
+
+            // this wiil return if not ready,
+            //   meaning that sending will be prefered over receiving...
+
+            // TODO: shouldn't this return the error to send to the sender?
+            ready!(socket.send_to(message.bytes(), addr).poll_unpin(cx))?;
+
+            // message sent, need to pop the message
+            assert!(outbound_messages.as_mut().poll_next(cx).is_ready());
+        }
+
+        // For QoS, this will only accept one message and output that
+        // receive all inbound messages
+
+        // TODO: this should match edns settings
+        let mut buf = [0u8; 2048];
+        let (len, src) = ready!(socket.recv_from(&mut buf).poll_unpin(cx))?;
+
+        Poll::Ready(Some(Ok(SerialMessage::new(
+            buf.iter().take(len).cloned().collect(),
+            src,
+        ))))
+    }
+}
+
+#[must_use = "futures do nothing unless polled"]
+pub(crate) struct NextRandomUdpSocket<S> {
+    bind_address: IpAddr,
+    marker: PhantomData<S>,
+}
+
+impl<S: UdpSocket> NextRandomUdpSocket<S> {
+    /// Creates a future for randomly binding to a local socket address for client connections.
+    pub(crate) fn new(name_server: &SocketAddr) -> NextRandomUdpSocket<S> {
+        let zero_addr: IpAddr = match *name_server {
+            SocketAddr::V4(..) => IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)),
+            SocketAddr::V6(..) => IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)),
+        };
+
+        NextRandomUdpSocket {
+            bind_address: zero_addr,
+            marker: PhantomData,
+        }
+    }
+
+    async fn bind(zero_addr: SocketAddr) -> Result<S, io::Error> {
+        S::bind(&zero_addr).await
+    }
+}
+
+impl<S: UdpSocket> Future for NextRandomUdpSocket<S> {
+    type Output = Result<S, io::Error>;
+
+    /// polls until there is an available next random UDP port.
+    ///
+    /// if there is no port available after 10 attempts, returns NotReady
+    fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+        let rand_port_range = Uniform::new_inclusive(1025_u16, u16::max_value());
+        let mut rand = rand::thread_rng();
+
+        for attempt in 0..10 {
+            let port = rand_port_range.sample(&mut rand); // the range is [0 ... u16::max]
+            let zero_addr = SocketAddr::new(self.bind_address, port);
+
+            // TODO: allow TTL to be adjusted...
+            // TODO: this immediate poll might be wrong in some cases...
+            match Box::pin(Self::bind(zero_addr)).as_mut().poll(cx) {
+                Poll::Ready(Ok(socket)) => {
+                    debug!("created socket successfully");
+                    return Poll::Ready(Ok(socket));
+                }
+                Poll::Ready(Err(err)) => {
+                    debug!("unable to bind port, attempt: {}: {}", attempt, err)
+                }
+                Poll::Pending => debug!("unable to bind port, attempt: {}", attempt),
+            }
+        }
+
+        debug!("could not get next random port, delaying");
+
+        // TODO: because no interest is registered anywhere, we must awake.
+        cx.waker().wake_by_ref();
+
+        // returning NotReady here, perhaps the next poll there will be some more socket available.
+        Poll::Pending
+    }
+}
+
+#[cfg(feature = "tokio-runtime")]
+use tokio::net;
+
+#[cfg(feature = "tokio-runtime")]
+#[async_trait]
+impl UdpSocket for net::UdpSocket {
+    async fn bind(addr: &SocketAddr) -> io::Result<Self> {
+        net::UdpSocket::bind(addr).await
+    }
+
+    async fn recv_from(&mut self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
+        self.recv_from(buf).await
+    }
+
+    async fn send_to(&mut self, buf: &[u8], target: &SocketAddr) -> io::Result<usize> {
+        self.send_to(buf, target).await
+    }
+}
+
+#[cfg(test)]
+#[cfg(feature = "tokio-runtime")]
+mod tests {
+    #[cfg(not(target_os = "linux"))] // ignored until Travis-CI fixes IPv6
+    use std::net::Ipv6Addr;
+    use std::net::{IpAddr, Ipv4Addr};
+    use tokio::{net::UdpSocket as TokioUdpSocket, runtime::Runtime};
+
+    #[test]
+    fn test_next_random_socket() {
+        use crate::tests::next_random_socket_test;
+        let io_loop = Runtime::new().expect("failed to create tokio runtime");
+        next_random_socket_test::<TokioUdpSocket, Runtime>(io_loop)
+    }
+
+    #[test]
+    fn test_udp_stream_ipv4() {
+        use crate::tests::udp_stream_test;
+        let io_loop = Runtime::new().expect("failed to create tokio runtime");
+        udp_stream_test::<TokioUdpSocket, Runtime>(
+            IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
+            io_loop,
+        );
+    }
+
+    #[test]
+    #[cfg(not(target_os = "linux"))] // ignored until Travis-CI fixes IPv6
+    fn test_udp_stream_ipv6() {
+        use crate::tests::udp_stream_test;
+        let io_loop = Runtime::new().expect("failed to create tokio runtime");
+        udp_stream_test::<TokioUdpSocket, Runtime>(
+            IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)),
+            io_loop,
+        );
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/xfer/dns_exchange.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/xfer/dns_exchange.rs
new file mode 100644
index 0000000..eddcb82
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/xfer/dns_exchange.rs
@@ -0,0 +1,400 @@
+// Copyright 2015-2018 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! This module contains all the types for demuxing DNS oriented streams.
+
+use std::marker::PhantomData;
+use std::pin::Pin;
+use std::task::{Context, Poll};
+
+use futures::channel::mpsc::{unbounded, UnboundedReceiver};
+use futures::stream::{Peekable, Stream, StreamExt};
+use futures::{Future, FutureExt};
+use log::{debug, warn};
+
+use crate::error::*;
+use crate::xfer::dns_handle::DnsHandle;
+use crate::xfer::OneshotDnsResponseReceiver;
+use crate::xfer::{
+    BufDnsRequestStreamHandle, DnsRequest, DnsRequestSender, DnsRequestStreamHandle, DnsResponse,
+    OneshotDnsRequest,
+};
+use crate::Time;
+
+/// This is a generic Exchange implemented over multiplexed DNS connection providers.
+///
+/// The underlying `DnsRequestSender` is expected to multiplex any I/O connections. DnsExchange assumes that the underlying stream is responsible for this.
+#[must_use = "futures do nothing unless polled"]
+pub struct DnsExchange<R>
+where
+    R: Future<Output = Result<DnsResponse, ProtoError>> + 'static + Send + Unpin,
+{
+    sender: BufDnsRequestStreamHandle<R>,
+}
+
+impl<R> DnsExchange<R>
+where
+    R: Future<Output = Result<DnsResponse, ProtoError>> + 'static + Send + Unpin,
+{
+    /// Initializes a TcpStream with an existing tcp::TcpStream.
+    ///
+    /// This is intended for use with a TcpListener and Incoming.
+    ///
+    /// # Arguments
+    ///
+    /// * `stream` - the established IO stream for communication
+    pub fn from_stream<S, TE>(stream: S) -> (Self, DnsExchangeBackground<S, R, TE>)
+    where
+        S: DnsRequestSender<DnsResponseFuture = R> + 'static + Send + Unpin,
+    {
+        let (message_sender, outbound_messages) = unbounded();
+        let message_sender = DnsRequestStreamHandle::<R>::new(message_sender);
+
+        Self::from_stream_with_receiver(stream, outbound_messages, message_sender)
+    }
+
+    /// Wraps a stream where a sender and receiver have already been established
+    pub fn from_stream_with_receiver<S, TE>(
+        stream: S,
+        receiver: UnboundedReceiver<OneshotDnsRequest<R>>,
+        sender: DnsRequestStreamHandle<R>,
+    ) -> (Self, DnsExchangeBackground<S, R, TE>)
+    where
+        S: DnsRequestSender<DnsResponseFuture = R> + 'static + Send + Unpin,
+    {
+        let background = DnsExchangeBackground {
+            io_stream: stream,
+            outbound_messages: receiver.peekable(),
+            marker: PhantomData,
+        };
+
+        let sender = BufDnsRequestStreamHandle::new(sender);
+
+        (Self { sender }, background)
+    }
+
+    /// Returns a future, which itself wraps a future which is awaiting connection.
+    ///
+    /// The connect_future should be lazy.
+    pub fn connect<F, S, TE>(connect_future: F) -> DnsExchangeConnect<F, S, R, TE>
+    where
+        F: Future<Output = Result<S, ProtoError>> + 'static + Send + Unpin,
+        S: DnsRequestSender<DnsResponseFuture = R> + 'static + Send + Unpin,
+        TE: Time + Unpin,
+    {
+        let (message_sender, outbound_messages) = unbounded();
+        let message_sender = DnsRequestStreamHandle::<R>::new(message_sender);
+
+        DnsExchangeConnect::connect(connect_future, outbound_messages, message_sender)
+    }
+}
+
+impl<R> Clone for DnsExchange<R>
+where
+    R: Future<Output = Result<DnsResponse, ProtoError>> + 'static + Send + Unpin,
+{
+    fn clone(&self) -> Self {
+        Self {
+            sender: self.sender.clone(),
+        }
+    }
+}
+
+impl<Resp> DnsHandle for DnsExchange<Resp>
+where
+    Resp: Future<Output = Result<DnsResponse, ProtoError>> + 'static + Send + Unpin,
+{
+    type Response = DnsExchangeSend<Resp>;
+
+    fn send<R: Into<DnsRequest> + Unpin + Send + 'static>(&mut self, request: R) -> Self::Response {
+        DnsExchangeSend {
+            result: self.sender.send(request),
+            _sender: self.sender.clone(), // TODO: this shouldn't be necessary, currently the presence of Senders is what allows the background to track current users, it generally is dropped right after send, this makes sure that there is at least one active after send
+        }
+    }
+}
+
+/// A Future that will resolve to a Response after sending the request
+#[must_use = "futures do nothing unless polled"]
+pub struct DnsExchangeSend<R>
+where
+    R: Future<Output = Result<DnsResponse, ProtoError>> + 'static + Send + Unpin,
+{
+    result: OneshotDnsResponseReceiver<R>,
+    _sender: BufDnsRequestStreamHandle<R>,
+}
+
+impl<R> Future for DnsExchangeSend<R>
+where
+    R: Future<Output = Result<DnsResponse, ProtoError>> + 'static + Send + Unpin,
+{
+    type Output = Result<DnsResponse, ProtoError>;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+        // as long as there is no result, poll the exchange
+        self.result.poll_unpin(cx)
+    }
+}
+
+/// This background future is responsible for driving all network operations for the DNS protocol.
+///
+/// It must be spawned before any DNS messages are sent.
+#[must_use = "futures do nothing unless polled"]
+pub struct DnsExchangeBackground<S, R, TE>
+where
+    S: DnsRequestSender<DnsResponseFuture = R> + 'static + Send + Unpin,
+    R: Future<Output = Result<DnsResponse, ProtoError>> + 'static + Send + Unpin,
+{
+    io_stream: S,
+    outbound_messages: Peekable<UnboundedReceiver<OneshotDnsRequest<R>>>,
+    marker: PhantomData<TE>,
+}
+
+impl<S, R, TE> DnsExchangeBackground<S, R, TE>
+where
+    S: DnsRequestSender<DnsResponseFuture = R> + 'static + Send + Unpin,
+    R: Future<Output = Result<DnsResponse, ProtoError>> + 'static + Send + Unpin,
+{
+    fn pollable_split(
+        &mut self,
+    ) -> (
+        &mut S,
+        &mut Peekable<UnboundedReceiver<OneshotDnsRequest<R>>>,
+    ) {
+        (&mut self.io_stream, &mut self.outbound_messages)
+    }
+}
+
+impl<S, R, TE> Future for DnsExchangeBackground<S, R, TE>
+where
+    S: DnsRequestSender<DnsResponseFuture = R> + 'static + Send + Unpin,
+    R: Future<Output = Result<DnsResponse, ProtoError>> + 'static + Send + Unpin,
+    TE: Time + Unpin,
+{
+    type Output = Result<(), ProtoError>;
+
+    #[allow(clippy::unused_unit)]
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+        let (io_stream, outbound_messages) = self.pollable_split();
+        let mut io_stream = Pin::new(io_stream);
+        let mut outbound_messages = Pin::new(outbound_messages);
+
+        // this will not accept incoming data while there is data to send
+        //  makes this self throttling.
+        loop {
+            // poll the underlying stream, to drive it...
+            match io_stream.as_mut().poll_next(cx) {
+                // The stream is ready
+                Poll::Ready(Some(Ok(()))) => (),
+                Poll::Pending => {
+                    if io_stream.is_shutdown() {
+                        // the io_stream is in a shutdown state, we are only waiting for final results...
+                        return Poll::Pending;
+                    }
+
+                    // NotReady and not shutdown, see if there are more messages to send
+                    ()
+                } // underlying stream is complete.
+                Poll::Ready(None) => {
+                    debug!("io_stream is done, shutting down");
+                    // TODO: return shutdown error to anything in the stream?
+
+                    return Poll::Ready(Ok(()));
+                }
+                Poll::Ready(Some(Err(err))) => {
+                    warn!("io_stream hit an error, shutting down: {}", err);
+
+                    return Poll::Ready(Err(err));
+                }
+            }
+
+            // then see if there is more to send
+            match outbound_messages.as_mut().poll_next(cx) {
+                // already handled above, here to make sure the poll() pops the next message
+                Poll::Ready(Some(dns_request)) => {
+                    // if there is no peer, this connection should die...
+                    let (dns_request, serial_response): (DnsRequest, _) = dns_request.unwrap();
+
+                    match serial_response
+                        .send_response(io_stream.send_message::<TE>(dns_request, cx))
+                    {
+                        Ok(()) => (),
+                        Err(_) => {
+                            warn!("failed to associate send_message response to the sender");
+
+                            return Poll::Ready(Err(
+                                "failed to associate send_message response to the sender".into(),
+                            ));
+                        }
+                    }
+                }
+                // On not ready, this is our time to return...
+                Poll::Pending => return Poll::Pending,
+                Poll::Ready(None) => {
+                    // if there is nothing that can use this connection to send messages, then this is done...
+                    io_stream.shutdown();
+
+                    // now we'll await the stream to shutdown... see io_stream poll above
+                }
+            }
+
+            // else we loop to poll on the outbound_messages
+        }
+    }
+}
+
+/// A wrapper for a future DnsExchange connection.
+///
+/// DnsExchangeConnect is clonable, making it possible to share this if the connection
+///  will be shared across threads.
+///
+/// The future will return a tuple of the DnsExchange (for sending messages) and a background
+///  for running the background tasks. The background is optional as only one thread should run
+///  the background. If returned, it must be spawned before any dns requests will function.
+pub struct DnsExchangeConnect<F, S, R, TE>(DnsExchangeConnectInner<F, S, R, TE>)
+where
+    F: Future<Output = Result<S, ProtoError>> + 'static + Send + Unpin,
+    S: DnsRequestSender<DnsResponseFuture = R> + 'static,
+    R: Future<Output = Result<DnsResponse, ProtoError>> + 'static + Send + Unpin,
+    TE: Time + Unpin;
+
+impl<F, S, R, TE> DnsExchangeConnect<F, S, R, TE>
+where
+    F: Future<Output = Result<S, ProtoError>> + 'static + Send + Unpin,
+    S: DnsRequestSender<DnsResponseFuture = R> + 'static,
+    R: Future<Output = Result<DnsResponse, ProtoError>> + 'static + Send + Unpin,
+    TE: Time + Unpin,
+{
+    fn connect(
+        connect_future: F,
+        outbound_messages: UnboundedReceiver<OneshotDnsRequest<R>>,
+        sender: DnsRequestStreamHandle<R>,
+    ) -> Self {
+        DnsExchangeConnect(DnsExchangeConnectInner::Connecting {
+            connect_future,
+            outbound_messages: Some(outbound_messages),
+            sender: Some(sender),
+        })
+    }
+}
+
+#[allow(clippy::type_complexity)]
+impl<F, S, R, TE> Future for DnsExchangeConnect<F, S, R, TE>
+where
+    F: Future<Output = Result<S, ProtoError>> + 'static + Send + Unpin,
+    S: DnsRequestSender<DnsResponseFuture = R> + 'static + Send + Unpin,
+    R: Future<Output = Result<DnsResponse, ProtoError>> + 'static + Send + Unpin,
+    TE: Time + Unpin,
+{
+    type Output = Result<(DnsExchange<R>, DnsExchangeBackground<S, R, TE>), ProtoError>;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+        self.0.poll_unpin(cx)
+    }
+}
+
+enum DnsExchangeConnectInner<F, S, R, TE>
+where
+    F: Future<Output = Result<S, ProtoError>> + 'static + Send,
+    S: DnsRequestSender<DnsResponseFuture = R> + 'static + Send,
+    R: Future<Output = Result<DnsResponse, ProtoError>> + 'static + Send + Unpin,
+    TE: Time + Unpin,
+{
+    Connecting {
+        connect_future: F,
+        outbound_messages: Option<UnboundedReceiver<OneshotDnsRequest<R>>>,
+        sender: Option<DnsRequestStreamHandle<R>>,
+    },
+    Connected {
+        exchange: DnsExchange<R>,
+        background: Option<DnsExchangeBackground<S, R, TE>>,
+    },
+    FailAll {
+        error: ProtoError,
+        outbound_messages: UnboundedReceiver<OneshotDnsRequest<R>>,
+    },
+}
+
+#[allow(clippy::type_complexity)]
+impl<F, S, R, TE> Future for DnsExchangeConnectInner<F, S, R, TE>
+where
+    F: Future<Output = Result<S, ProtoError>> + 'static + Send + Unpin,
+    S: DnsRequestSender<DnsResponseFuture = R> + 'static + Send + Unpin,
+    R: Future<Output = Result<DnsResponse, ProtoError>> + 'static + Send + Unpin,
+    TE: Time + Unpin,
+{
+    type Output = Result<(DnsExchange<R>, DnsExchangeBackground<S, R, TE>), ProtoError>;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+        loop {
+            let next;
+            match *self {
+                DnsExchangeConnectInner::Connecting {
+                    ref mut connect_future,
+                    ref mut outbound_messages,
+                    ref mut sender,
+                } => {
+                    let connect_future = Pin::new(connect_future);
+                    match connect_future.poll(cx) {
+                        Poll::Ready(Ok(stream)) => {
+                            //debug!("connection established: {}", stream);
+
+                            let (exchange, background) = DnsExchange::from_stream_with_receiver(
+                                stream,
+                                outbound_messages
+                                    .take()
+                                    .expect("cannot poll after complete"),
+                                sender.take().expect("cannot poll after complete"),
+                            );
+
+                            next = DnsExchangeConnectInner::Connected {
+                                exchange,
+                                background: Some(background),
+                            };
+                        }
+                        Poll::Pending => return Poll::Pending,
+                        Poll::Ready(Err(error)) => {
+                            debug!("stream errored while connecting: {:?}", error);
+                            next = DnsExchangeConnectInner::FailAll {
+                                error,
+                                outbound_messages: outbound_messages
+                                    .take()
+                                    .expect("cannot poll after complete"),
+                            }
+                        }
+                    };
+                }
+                DnsExchangeConnectInner::Connected {
+                    ref exchange,
+                    ref mut background,
+                } => {
+                    let exchange = exchange.clone();
+                    let background = background.take().expect("cannot poll after complete");
+
+                    return Poll::Ready(Ok((exchange, background)));
+                }
+                DnsExchangeConnectInner::FailAll {
+                    ref error,
+                    ref mut outbound_messages,
+                } => {
+                    while let Some(outbound_message) = match outbound_messages.poll_next_unpin(cx) {
+                        Poll::Ready(opt) => opt,
+                        Poll::Pending => return Poll::Pending,
+                    } {
+                        let response = S::error_response::<TE>(error.clone());
+                        // ignoring errors... best effort send...
+                        outbound_message.unwrap().1.send_response(response).ok();
+                    }
+
+                    return Poll::Ready(Err(error.clone()));
+                }
+            }
+
+            *self = next;
+        }
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/xfer/dns_handle.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/xfer/dns_handle.rs
new file mode 100644
index 0000000..e350c45
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/xfer/dns_handle.rs
@@ -0,0 +1,101 @@
+// Copyright 2015-2018 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! `DnsHandle` types perform conversions of the raw DNS messages before sending the messages on the specified streams.
+use futures::channel::mpsc::UnboundedSender;
+use futures::future::Future;
+use log::debug;
+use rand;
+
+use crate::error::*;
+use crate::op::{Message, MessageType, OpCode, Query};
+use crate::xfer::{DnsRequest, DnsRequestOptions, DnsResponse, SerialMessage};
+
+// TODO: this should be configurable
+const MAX_PAYLOAD_LEN: u16 = 1500 - 40 - 8; // 1500 (general MTU) - 40 (ipv6 header) - 8 (udp header)
+
+/// The StreamHandle is the general interface for communicating with the DnsMultiplexer
+pub struct StreamHandle {
+    sender: UnboundedSender<Vec<u8>>,
+}
+
+impl StreamHandle {
+    /// Constructs a new StreamHandle for wrapping the sender
+    pub fn new(sender: UnboundedSender<Vec<u8>>) -> Self {
+        StreamHandle { sender }
+    }
+}
+
+/// Implementations of Sinks for sending DNS messages
+pub trait DnsStreamHandle: 'static + Send {
+    /// Sends a message to the Handle for delivery to the server.
+    fn send(&mut self, buffer: SerialMessage) -> Result<(), ProtoError>;
+}
+
+impl DnsStreamHandle for StreamHandle {
+    fn send(&mut self, buffer: SerialMessage) -> Result<(), ProtoError> {
+        UnboundedSender::unbounded_send(&self.sender, buffer.unwrap().0)
+            .map_err(|e| ProtoError::from(format!("mpsc::SendError {}", e)))
+    }
+}
+
+/// A trait for implementing high level functions of DNS.
+pub trait DnsHandle: 'static + Clone + Send + Sync + Unpin {
+    /// The associated response from the response future, this should resolve to the Response message
+    type Response: Future<Output = Result<DnsResponse, ProtoError>> + 'static + Send + Unpin;
+
+    /// Only returns true if and only if this DNS handle is validating DNSSec.
+    ///
+    /// If the DnsHandle impl is wrapping other clients, then the correct option is to delegate the question to the wrapped client.
+    fn is_verifying_dnssec(&self) -> bool {
+        false
+    }
+
+    /// Send a message via the channel in the client
+    ///
+    /// # Arguments
+    ///
+    /// * `request` - the fully constructed Message to send, note that most implementations of
+    ///               will most likely be required to rewrite the QueryId, do no rely on that as
+    ///               being stable.
+    fn send<R: Into<DnsRequest> + Unpin + Send + 'static>(&mut self, request: R) -> Self::Response;
+
+    /// A *classic* DNS query
+    ///
+    /// This is identical to `query`, but instead takes a `Query` object.
+    ///
+    /// # Arguments
+    ///
+    /// * `query` - the query to lookup
+    fn lookup(&mut self, query: Query, options: DnsRequestOptions) -> Self::Response {
+        debug!("querying: {} {:?}", query.name(), query.query_type());
+
+        // build the message
+        let mut message: Message = Message::new();
+
+        // TODO: This is not the final ID, it's actually set in the poll method of DNS future
+        //  should we just remove this?
+        let id: u16 = rand::random();
+
+        message.add_query(query);
+        message
+            .set_id(id)
+            .set_message_type(MessageType::Query)
+            .set_op_code(OpCode::Query)
+            .set_recursion_desired(true);
+
+        // Extended dns
+        {
+            // TODO: this should really be configurable...
+            let edns = message.edns_mut();
+            edns.set_max_payload(MAX_PAYLOAD_LEN);
+            edns.set_version(0);
+        }
+
+        self.send(DnsRequest::new(message, options))
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/xfer/dns_multiplexer.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/xfer/dns_multiplexer.rs
new file mode 100644
index 0000000..9eaad53
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/xfer/dns_multiplexer.rs
@@ -0,0 +1,527 @@
+// Copyright 2015-2018 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! `DnsMultiplexer` and associated types implement the state machines for sending DNS messages while using the underlying streams.
+
+use std::borrow::Borrow;
+use std::collections::hash_map::Entry;
+use std::collections::HashMap;
+use std::fmt::{self, Display};
+use std::marker::Unpin;
+use std::pin::Pin;
+use std::sync::Arc;
+use std::task::{Context, Poll};
+use std::time::{Duration, SystemTime, UNIX_EPOCH};
+
+use futures::channel::oneshot;
+use futures::stream::{Stream, StreamExt};
+use futures::{ready, Future, FutureExt};
+use log::{debug, warn};
+use rand;
+use rand::distributions::{Distribution, Standard};
+use smallvec::SmallVec;
+
+use crate::error::*;
+use crate::op::{Message, MessageFinalizer, OpCode};
+use crate::xfer::{
+    ignore_send, DnsClientStream, DnsRequest, DnsRequestOptions, DnsRequestSender, DnsResponse,
+    SerialMessage,
+};
+use crate::DnsStreamHandle;
+use crate::Time;
+
+const QOS_MAX_RECEIVE_MSGS: usize = 100; // max number of messages to receive from the UDP socket
+
+struct ActiveRequest {
+    // the completion is the channel for a response to the original request
+    completion: oneshot::Sender<Result<DnsResponse, ProtoError>>,
+    request_id: u16,
+    request_options: DnsRequestOptions,
+    // most requests pass a single Message response directly through to the completion
+    //  this small vec will have no allocations, unless the requests is a DNS-SD request
+    //  expecting more than one response
+    // TODO: change the completion above to a Stream, and don't hold messages...
+    responses: SmallVec<[Message; 1]>,
+    timeout: Box<dyn Future<Output = ()> + Send + Unpin>,
+}
+
+impl ActiveRequest {
+    fn new(
+        completion: oneshot::Sender<Result<DnsResponse, ProtoError>>,
+        request_id: u16,
+        request_options: DnsRequestOptions,
+        timeout: Box<dyn Future<Output = ()> + Send + Unpin>,
+    ) -> Self {
+        ActiveRequest {
+            completion,
+            request_id,
+            request_options,
+            // request,
+            responses: SmallVec::new(),
+            timeout,
+        }
+    }
+
+    /// polls the timeout and converts the error
+    fn poll_timeout(&mut self, cx: &mut Context) -> Poll<()> {
+        self.timeout.poll_unpin(cx)
+    }
+
+    /// Returns true of the other side canceled the request
+    fn is_canceled(&self) -> bool {
+        self.completion.is_canceled()
+    }
+
+    /// Adds the response to the request such that it can be later sent to the client
+    fn add_response(&mut self, message: Message) {
+        self.responses.push(message);
+    }
+
+    /// the request id of the message that was sent
+    fn request_id(&self) -> u16 {
+        self.request_id
+    }
+
+    /// the request options from the message that was sent
+    fn request_options(&self) -> &DnsRequestOptions {
+        &self.request_options
+    }
+
+    /// Sends an error
+    fn complete_with_error(self, error: ProtoError) {
+        ignore_send(self.completion.send(Err(error)));
+    }
+
+    /// sends any registered responses to the requestor
+    ///
+    /// Any error sending will be logged and ignored. This must only be called after associating a response,
+    ///   otherwise an error will always be returned.
+    fn complete(self) {
+        if self.responses.is_empty() {
+            self.complete_with_error("no responses received, should have timedout".into());
+        } else {
+            ignore_send(self.completion.send(Ok(self.responses.into())));
+        }
+    }
+}
+
+/// A DNS Client implemented over futures-rs.
+///
+/// This Client is generic and capable of wrapping UDP, TCP, and other underlying DNS protocol
+///  implementations. This should be used for underlying protocols that do not natively support
+///  multiplexed sessions.
+#[must_use = "futures do nothing unless polled"]
+pub struct DnsMultiplexer<S, MF, D = Box<dyn DnsStreamHandle>>
+where
+    D: Send + 'static,
+    S: DnsClientStream + 'static,
+    MF: MessageFinalizer,
+{
+    stream: S,
+    timeout_duration: Duration,
+    stream_handle: D,
+    active_requests: HashMap<u16, ActiveRequest>,
+    signer: Option<Arc<MF>>,
+    is_shutdown: bool,
+}
+
+impl<S, MF> DnsMultiplexer<S, MF, Box<dyn DnsStreamHandle>>
+where
+    S: DnsClientStream + Unpin + 'static,
+    MF: MessageFinalizer,
+{
+    /// Spawns a new DnsMultiplexer Stream. This uses a default timeout of 5 seconds for all requests.
+    ///
+    /// # Arguments
+    ///
+    /// * `stream` - A stream of bytes that can be used to send/receive DNS messages
+    ///              (see TcpClientStream or UdpClientStream)
+    /// * `stream_handle` - The handle for the `stream` on which bytes can be sent/received.
+    /// * `signer` - An optional signer for requests, needed for Updates with Sig0, otherwise not needed
+    #[allow(clippy::new_ret_no_self)]
+    pub fn new<F>(
+        stream: F,
+        stream_handle: Box<dyn DnsStreamHandle>,
+        signer: Option<Arc<MF>>,
+    ) -> DnsMultiplexerConnect<F, S, MF>
+    where
+        F: Future<Output = Result<S, ProtoError>> + Send + Unpin + 'static,
+    {
+        Self::with_timeout(stream, stream_handle, Duration::from_secs(5), signer)
+    }
+
+    /// Spawns a new DnsMultiplexer Stream.
+    ///
+    /// # Arguments
+    ///
+    /// * `stream` - A stream of bytes that can be used to send/receive DNS messages
+    ///              (see TcpClientStream or UdpClientStream)
+    /// * `timeout_duration` - All requests may fail due to lack of response, this is the time to
+    ///                        wait for a response before canceling the request.
+    /// * `stream_handle` - The handle for the `stream` on which bytes can be sent/received.
+    /// * `signer` - An optional signer for requests, needed for Updates with Sig0, otherwise not needed
+    pub fn with_timeout<F>(
+        stream: F,
+        stream_handle: Box<dyn DnsStreamHandle>,
+        timeout_duration: Duration,
+        signer: Option<Arc<MF>>,
+    ) -> DnsMultiplexerConnect<F, S, MF>
+    where
+        F: Future<Output = Result<S, ProtoError>> + Send + Unpin + 'static,
+    {
+        DnsMultiplexerConnect {
+            stream,
+            stream_handle: Some(stream_handle),
+            timeout_duration,
+            signer,
+        }
+    }
+
+    /// loop over active_requests and remove cancelled requests
+    ///  this should free up space if we already had 4096 active requests
+    fn drop_cancelled(&mut self, cx: &mut Context) {
+        let mut canceled = HashMap::<u16, ProtoError>::new();
+        for (&id, ref mut active_req) in &mut self.active_requests {
+            if active_req.is_canceled() {
+                canceled.insert(id, ProtoError::from("requestor canceled"));
+            }
+
+            // check for timeouts...
+            match active_req.poll_timeout(cx) {
+                Poll::Ready(()) => {
+                    debug!("request timed out: {}", id);
+                    canceled.insert(id, ProtoError::from(ProtoErrorKind::Timeout));
+                }
+                Poll::Pending => (),
+            }
+        }
+
+        // drop all the canceled requests
+        for (id, error) in canceled {
+            if let Some(active_request) = self.active_requests.remove(&id) {
+                if active_request.responses.is_empty() {
+                    // complete the request, it's failed...
+                    active_request.complete_with_error(error);
+                } else {
+                    // this is a timeout waiting for multiple responses...
+                    active_request.complete();
+                }
+            }
+        }
+    }
+
+    /// creates random query_id, validates against all active queries
+    fn next_random_query_id(&self, cx: &mut Context) -> Poll<u16> {
+        let mut rand = rand::thread_rng();
+
+        for _ in 0..100 {
+            let id: u16 = Standard.sample(&mut rand); // the range is [0 ... u16::max]
+
+            if !self.active_requests.contains_key(&id) {
+                return Poll::Ready(id);
+            }
+        }
+
+        cx.waker().wake_by_ref();
+        Poll::Pending
+    }
+
+    /// Closes all outstanding completes with a closed stream error
+    fn stream_closed_close_all(&mut self) {
+        if !self.active_requests.is_empty() {
+            warn!(
+                "stream closed before response received: {}",
+                self.stream.name_server_addr()
+            );
+        }
+
+        let error = ProtoError::from("stream closed before response received");
+
+        for (_, active_request) in self.active_requests.drain() {
+            if active_request.responses.is_empty() {
+                // complete the request, it's failed...
+                active_request.complete_with_error(error.clone());
+            } else {
+                // this is a timeout waiting for multiple responses...
+                active_request.complete();
+            }
+        }
+    }
+}
+
+/// A wrapper for a future DnsExchange connection
+#[must_use = "futures do nothing unless polled"]
+pub struct DnsMultiplexerConnect<F, S, MF>
+where
+    F: Future<Output = Result<S, ProtoError>> + Send + Unpin + 'static,
+    S: Stream<Item = Result<SerialMessage, ProtoError>> + Unpin,
+    MF: MessageFinalizer + Send + Sync + 'static,
+{
+    stream: F,
+    stream_handle: Option<Box<dyn DnsStreamHandle>>,
+    timeout_duration: Duration,
+    signer: Option<Arc<MF>>,
+}
+
+impl<F, S, MF> Future for DnsMultiplexerConnect<F, S, MF>
+where
+    F: Future<Output = Result<S, ProtoError>> + Send + Unpin + 'static,
+    S: DnsClientStream + Unpin + 'static,
+    MF: MessageFinalizer + Send + Sync + 'static,
+{
+    type Output = Result<DnsMultiplexer<S, MF, Box<dyn DnsStreamHandle>>, ProtoError>;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+        let stream: S = ready!(self.stream.poll_unpin(cx))?;
+
+        Poll::Ready(Ok(DnsMultiplexer {
+            stream,
+            timeout_duration: self.timeout_duration,
+            stream_handle: self
+                .stream_handle
+                .take()
+                .expect("must not poll after complete"),
+            active_requests: HashMap::new(),
+            signer: self.signer.clone(),
+            is_shutdown: false,
+        }))
+    }
+}
+
+impl<S, MF> Display for DnsMultiplexer<S, MF>
+where
+    S: DnsClientStream + 'static,
+    MF: MessageFinalizer + Send + Sync + 'static,
+{
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+        write!(formatter, "{}", self.stream)
+    }
+}
+
+impl<S, MF> DnsRequestSender for DnsMultiplexer<S, MF>
+where
+    S: DnsClientStream + Unpin + 'static,
+    MF: MessageFinalizer + Send + Sync + 'static,
+{
+    type DnsResponseFuture = DnsMultiplexerSerialResponse;
+
+    fn send_message<TE: Time>(
+        &mut self,
+        request: DnsRequest,
+        cx: &mut Context,
+    ) -> Self::DnsResponseFuture {
+        if self.is_shutdown {
+            panic!("can not send messages after stream is shutdown")
+        }
+
+        // TODO: handle the pending case with future::poll_fn
+        // get next query_id
+        let query_id: u16 = match self.next_random_query_id(cx) {
+            Poll::Ready(id) => id,
+            Poll::Pending => {
+                return DnsMultiplexerSerialResponseInner::Err(Some(ProtoError::from(
+                    "id space exhausted, consider filing an issue",
+                )))
+                .into()
+            }
+        };
+
+        let (mut request, request_options) = request.unwrap();
+        request.set_id(query_id);
+
+        let now = match SystemTime::now()
+            .duration_since(UNIX_EPOCH)
+            .map_err(|_| ProtoErrorKind::Message("Current time is before the Unix epoch.").into())
+        {
+            Ok(now) => now.as_secs(),
+            Err(err) => return DnsMultiplexerSerialResponseInner::Err(Some(err)).into(),
+        };
+
+        // TODO: truncates u64 to u32, error on overflow?
+        let now = now as u32;
+
+        // update messages need to be signed.
+        if let OpCode::Update = request.op_code() {
+            if let Some(ref signer) = self.signer {
+                if let Err(e) = request.finalize::<MF>(signer.borrow(), now) {
+                    debug!("could not sign message: {}", e);
+                    return DnsMultiplexerSerialResponseInner::Err(Some(e)).into();
+                }
+            }
+        }
+
+        // store a Timeout for this message before sending
+        let timeout = TE::delay_for(self.timeout_duration);
+
+        let (complete, receiver) = oneshot::channel();
+
+        // send the message
+        let active_request =
+            ActiveRequest::new(complete, request.id(), request_options, Box::new(timeout));
+
+        match request.to_vec() {
+            Ok(buffer) => {
+                debug!("sending message id: {}", active_request.request_id());
+                let serial_message = SerialMessage::new(buffer, self.stream.name_server_addr());
+
+                // add to the map -after- the client send b/c we don't want to put it in the map if
+                //  we ended up returning an error from the send.
+                match self.stream_handle.send(serial_message) {
+                    Ok(()) => self
+                        .active_requests
+                        .insert(active_request.request_id(), active_request),
+                    Err(err) => return DnsMultiplexerSerialResponseInner::Err(Some(err)).into(),
+                };
+            }
+            Err(e) => {
+                debug!(
+                    "error message id: {} error: {}",
+                    active_request.request_id(),
+                    e
+                );
+                // complete with the error, don't add to the map of active requests
+                return DnsMultiplexerSerialResponseInner::Err(Some(e)).into();
+            }
+        }
+
+        DnsMultiplexerSerialResponseInner::Completion(receiver).into()
+    }
+
+    fn error_response<TE: Time>(error: ProtoError) -> Self::DnsResponseFuture {
+        DnsMultiplexerSerialResponseInner::Err(Some(error)).into()
+    }
+
+    fn shutdown(&mut self) {
+        self.is_shutdown = true;
+    }
+
+    fn is_shutdown(&self) -> bool {
+        self.is_shutdown
+    }
+}
+
+impl<S, MF> Stream for DnsMultiplexer<S, MF>
+where
+    S: DnsClientStream + Unpin + 'static,
+    MF: MessageFinalizer + Send + Sync + 'static,
+{
+    type Item = Result<(), ProtoError>;
+
+    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
+        // Always drop the cancelled queries first
+        self.drop_cancelled(cx);
+
+        if self.is_shutdown && self.active_requests.is_empty() {
+            debug!("stream is done: {}", self);
+            return Poll::Ready(None);
+        }
+
+        // Collect all inbound requests, max 100 at a time for QoS
+        //   by having a max we will guarantee that the client can't be DOSed in this loop
+        // TODO: make the QoS configurable
+        let mut messages_received = 0;
+        for i in 0..QOS_MAX_RECEIVE_MSGS {
+            match self.stream.poll_next_unpin(cx)? {
+                Poll::Ready(Some(buffer)) => {
+                    messages_received = i;
+
+                    //   deserialize or log decode_error
+                    match buffer.to_message() {
+                        Ok(message) => match self.active_requests.entry(message.id()) {
+                            Entry::Occupied(mut request_entry) => {
+                                // first add the response to the active_requests responses
+                                let complete = {
+                                    let active_request = request_entry.get_mut();
+                                    active_request.add_response(message);
+
+                                    // determine if this is complete
+                                    !active_request.request_options().expects_multiple_responses
+                                };
+
+                                // now check if the request is complete
+                                if complete {
+                                    let active_request = request_entry.remove();
+                                    active_request.complete();
+                                }
+                            }
+                            Entry::Vacant(..) => debug!("unexpected request_id: {}", message.id()),
+                        },
+                        // TODO: return src address for diagnostics
+                        Err(e) => debug!("error decoding message: {}", e),
+                    }
+                }
+                Poll::Ready(None) => {
+                    debug!("io_stream closed by other side: {}", self.stream);
+                    self.stream_closed_close_all();
+                    return Poll::Ready(None);
+                }
+                Poll::Pending => break,
+            }
+        }
+
+        // If still active, then if the qos (for _ in 0..100 loop) limit
+        // was hit then "yield". This'll make sure that the future is
+        // woken up immediately on the next turn of the event loop.
+        if messages_received == QOS_MAX_RECEIVE_MSGS {
+            // FIXME: this was a task::current().notify(); is this right?
+            cx.waker().wake_by_ref();
+        }
+
+        // Finally, return not ready to keep the 'driver task' alive.
+        Poll::Pending
+    }
+}
+
+/// A future that resolves into a DnsResponse
+#[must_use = "futures do nothing unless polled"]
+pub struct DnsMultiplexerSerialResponse(DnsMultiplexerSerialResponseInner);
+
+impl DnsMultiplexerSerialResponse {
+    /// Returns a new future with the oneshot completion
+    pub fn completion(complete: oneshot::Receiver<ProtoResult<DnsResponse>>) -> Self {
+        DnsMultiplexerSerialResponseInner::Completion(complete).into()
+    }
+}
+
+impl Future for DnsMultiplexerSerialResponse {
+    type Output = Result<DnsResponse, ProtoError>;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+        self.0.poll_unpin(cx)
+    }
+}
+
+impl From<DnsMultiplexerSerialResponseInner> for DnsMultiplexerSerialResponse {
+    fn from(inner: DnsMultiplexerSerialResponseInner) -> Self {
+        DnsMultiplexerSerialResponse(inner)
+    }
+}
+
+enum DnsMultiplexerSerialResponseInner {
+    Completion(oneshot::Receiver<ProtoResult<DnsResponse>>),
+    Err(Option<ProtoError>),
+}
+
+impl Future for DnsMultiplexerSerialResponseInner {
+    type Output = Result<DnsResponse, ProtoError>;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+        match *self {
+            // The inner type of the completion might have been an error
+            //   we need to unwrap that, and translate to be the Future's error
+            DnsMultiplexerSerialResponseInner::Completion(ref mut complete) => {
+                complete.poll_unpin(cx).map(|r| {
+                    r.map_err(|_| ProtoError::from("the completion was canceled"))
+                        .and_then(|r| r)
+                })
+            }
+            DnsMultiplexerSerialResponseInner::Err(ref mut err) => {
+                Poll::Ready(Err(err.take().expect("cannot poll after complete")))
+            }
+        }
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/xfer/dns_request.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/xfer/dns_request.rs
new file mode 100644
index 0000000..d502cbd
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/xfer/dns_request.rs
@@ -0,0 +1,69 @@
+// Copyright 2015-2018 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! `DnsRequest` wraps a `Message` and associates a set of `DnsRequestOptions` for specifying different transfer options.
+
+use std::ops::{Deref, DerefMut};
+
+use crate::op::Message;
+
+/// A set of options for expressing options to how requests should be treated
+#[derive(Clone, Default)]
+pub struct DnsRequestOptions {
+    /// When true, the underlying DNS protocols will not return on the first response received.
+    ///
+    /// Setting this option will cause the underlying protocol to await the timeout, and then return all Responses.
+    pub expects_multiple_responses: bool,
+    // /// If set, then the request will terminate early if all types have been received
+    // pub expected_record_types: Option<SmallVec<[RecordType; 2]>>,
+    // TODO: add EDNS options here?
+}
+
+/// A DNS request object
+///
+/// This wraps a DNS Message for requests. It also has request options associated for controlling certain features of the DNS protocol handlers.
+#[derive(Clone)]
+pub struct DnsRequest {
+    message: Message,
+    options: DnsRequestOptions,
+}
+
+impl DnsRequest {
+    /// Returns a new DnsRequest object
+    pub fn new(message: Message, options: DnsRequestOptions) -> Self {
+        DnsRequest { message, options }
+    }
+
+    /// Get the set of request options associated with this request
+    pub fn options(&self) -> &DnsRequestOptions {
+        &self.options
+    }
+
+    /// Unwraps the raw message
+    pub fn unwrap(self) -> (Message, DnsRequestOptions) {
+        (self.message, self.options)
+    }
+}
+
+impl Deref for DnsRequest {
+    type Target = Message;
+    fn deref(&self) -> &Self::Target {
+        &self.message
+    }
+}
+
+impl DerefMut for DnsRequest {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.message
+    }
+}
+
+impl Into<DnsRequest> for Message {
+    fn into(self) -> DnsRequest {
+        DnsRequest::new(self, DnsRequestOptions::default())
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/xfer/dns_response.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/xfer/dns_response.rs
new file mode 100644
index 0000000..9ed8d13
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/xfer/dns_response.rs
@@ -0,0 +1,82 @@
+// Copyright 2015-2018 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! `DnsResponse` wraps a `Message` and any associated connection details
+
+use std::ops::{Deref, DerefMut};
+use std::slice::{Iter, IterMut};
+
+use smallvec::SmallVec;
+
+use crate::op::Message;
+
+// TODO: this needs to have the IP addr of the remote system...
+// TODO: see https://github.com/bluejekyll/trust-dns/issues/383 for removing vec of messages and instead returning a Stream
+/// A DNS response object
+///
+/// For Most DNS requests, only one response is expected, the exception is a multicast request.
+#[derive(Clone, Debug)]
+pub struct DnsResponse(SmallVec<[Message; 1]>);
+
+// TODO: when `impl Trait` lands in stable, remove this, and expose FlatMap over answers, et al.
+impl DnsResponse {
+    /// Get all the messages in the Response
+    pub fn messages(&self) -> Iter<Message> {
+        self.0.as_slice().iter()
+    }
+
+    /// Get all the messages in the Response
+    pub fn messages_mut(&mut self) -> IterMut<Message> {
+        self.0.as_mut_slice().iter_mut()
+    }
+
+    /// returns the number of messages in the response
+    pub fn len(&self) -> usize {
+        self.0.len()
+    }
+
+    /// returns the number of messages in the response
+    pub fn is_empty(&self) -> bool {
+        self.0.is_empty()
+    }
+}
+
+impl Deref for DnsResponse {
+    type Target = Message;
+
+    fn deref(&self) -> &Self::Target {
+        &self.0[0]
+    }
+}
+
+impl DerefMut for DnsResponse {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.0[0]
+    }
+}
+
+impl From<DnsResponse> for Message {
+    fn from(mut response: DnsResponse) -> Message {
+        response.0.remove(0)
+    }
+}
+
+impl From<Message> for DnsResponse {
+    fn from(message: Message) -> DnsResponse {
+        DnsResponse(SmallVec::from([message]))
+    }
+}
+
+impl From<SmallVec<[Message; 1]>> for DnsResponse {
+    fn from(messages: SmallVec<[Message; 1]>) -> DnsResponse {
+        debug_assert!(
+            !messages.is_empty(),
+            "There should be at least one message in any DnsResponse"
+        );
+        DnsResponse(messages)
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/xfer/dnssec_dns_handle.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/xfer/dnssec_dns_handle.rs
new file mode 100644
index 0000000..ea4a9e57
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/xfer/dnssec_dns_handle.rs
@@ -0,0 +1,878 @@
+// Copyright 2015-2016 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! The `DnssecDnsHandle` is used to validate all DNS responses for correct DNSSec signatures.
+
+use std::clone::Clone;
+use std::collections::HashSet;
+use std::pin::Pin;
+use std::sync::Arc;
+
+use futures::future;
+use futures::{Future, FutureExt, TryFutureExt};
+use log::debug;
+
+use crate::error::*;
+use crate::op::{OpCode, Query};
+use crate::rr::dnssec::rdata::{DNSSECRData, DNSSECRecordType, DNSKEY, SIG};
+#[cfg(feature = "dnssec")]
+use crate::rr::dnssec::Verifier;
+use crate::rr::dnssec::{Algorithm, SupportedAlgorithms, TrustAnchor};
+use crate::rr::rdata::opt::EdnsOption;
+use crate::rr::{DNSClass, Name, RData, Record, RecordType};
+use crate::xfer::dns_handle::DnsHandle;
+use crate::xfer::{DnsRequest, DnsRequestOptions, DnsResponse};
+
+#[derive(Debug)]
+struct Rrset {
+    pub name: Name,
+    pub record_type: RecordType,
+    pub record_class: DNSClass,
+    pub records: Vec<Record>,
+}
+
+/// Performs DNSSec validation of all DNS responses from the wrapped DnsHandle
+///
+/// This wraps a DnsHandle, changing the implementation `send()` to validate all
+///  message responses for Query operations. Update operation responses are not validated by
+///  this process.
+#[derive(Clone)]
+#[must_use = "queries can only be sent through a DnsHandle"]
+pub struct DnssecDnsHandle<H>
+where
+    H: DnsHandle + Unpin + 'static,
+{
+    handle: H,
+    trust_anchor: Arc<TrustAnchor>,
+    request_depth: usize,
+    minimum_key_len: usize,
+    minimum_algorithm: Algorithm, // used to prevent down grade attacks...
+}
+
+impl<H> DnssecDnsHandle<H>
+where
+    H: DnsHandle + Unpin + 'static,
+{
+    /// Create a new DnssecDnsHandle wrapping the specified handle.
+    ///
+    /// This uses the compiled in TrustAnchor default trusted keys.
+    ///
+    /// # Arguments
+    /// * `handle` - handle to use for all connections to a remote server.
+    pub fn new(handle: H) -> DnssecDnsHandle<H> {
+        Self::with_trust_anchor(handle, TrustAnchor::default())
+    }
+
+    /// Create a new DnssecDnsHandle wrapping the specified handle.
+    ///
+    /// This allows a custom TrustAnchor to be define.
+    ///
+    /// # Arguments
+    /// * `handle` - handle to use for all connections to a remote server.
+    /// * `trust_anchor` - custom DNSKEYs that will be trusted, can be used to pin trusted keys.
+    pub fn with_trust_anchor(handle: H, trust_anchor: TrustAnchor) -> DnssecDnsHandle<H> {
+        DnssecDnsHandle {
+            handle,
+            trust_anchor: Arc::new(trust_anchor),
+            request_depth: 0,
+            minimum_key_len: 0,
+            minimum_algorithm: Algorithm::RSASHA256,
+        }
+    }
+
+    /// An internal function used to clone the handle, but maintain some information back to the
+    ///  original handle, such as the request_depth such that infinite recursion does
+    ///  not occur.
+    fn clone_with_context(&self) -> Self {
+        DnssecDnsHandle {
+            handle: self.handle.clone(),
+            trust_anchor: Arc::clone(&self.trust_anchor),
+            request_depth: self.request_depth + 1,
+            minimum_key_len: self.minimum_key_len,
+            minimum_algorithm: self.minimum_algorithm,
+        }
+    }
+}
+
+impl<H: DnsHandle + Sync + Unpin> DnsHandle for DnssecDnsHandle<H> {
+    type Response = Pin<Box<dyn Future<Output = Result<DnsResponse, ProtoError>> + Send>>;
+
+    fn is_verifying_dnssec(&self) -> bool {
+        // This handler is always verifying...
+        true
+    }
+
+    fn send<R: Into<DnsRequest>>(&mut self, request: R) -> Self::Response {
+        let mut request = request.into();
+
+        // backstop, this might need to be configurable at some point
+        if self.request_depth > 20 {
+            return Box::pin(future::err(ProtoError::from(
+                "exceeded max validation depth",
+            )));
+        }
+
+        // dnssec only matters on queries.
+        if let OpCode::Query = request.op_code() {
+            // This will panic on no queries, that is a very odd type of request, isn't it?
+            // TODO: with mDNS there can be multiple queries
+            let query = request
+                .queries()
+                .first()
+                .cloned()
+                .expect("no queries in request");
+            let handle: DnssecDnsHandle<H> = self.clone_with_context();
+
+            // TODO: cache response of the server about understood algorithms
+            #[cfg(feature = "dnssec")]
+            {
+                let edns = request.edns_mut();
+
+                edns.set_dnssec_ok(true);
+
+                // send along the algorithms which are supported by this handle
+                let mut algorithms = SupportedAlgorithms::new();
+                #[cfg(feature = "ring")]
+                {
+                    algorithms.set(Algorithm::ED25519);
+                }
+                algorithms.set(Algorithm::ECDSAP256SHA256);
+                algorithms.set(Algorithm::ECDSAP384SHA384);
+                algorithms.set(Algorithm::RSASHA256);
+
+                let dau = EdnsOption::DAU(algorithms);
+                let dhu = EdnsOption::DHU(algorithms);
+
+                edns.set_option(dau);
+                edns.set_option(dhu);
+            }
+
+            request.set_authentic_data(true);
+            request.set_checking_disabled(false);
+            let dns_class = request
+                .queries()
+                .first()
+                .map_or(DNSClass::IN, Query::query_class);
+
+            return Box::pin(
+                self.handle
+                    .send(request)
+                    .and_then(move |message_response| {
+                        // group the record sets by name and type
+                        //  each rrset type needs to validated independently
+                        debug!("validating message_response: {}", message_response.id());
+                        verify_rrsets(handle, message_response, dns_class)
+                    })
+                    .and_then(move |verified_message| {
+                        // at this point all of the message is verified.
+                        //  This is where NSEC (and possibly NSEC3) validation occurs
+                        // As of now, only NSEC is supported.
+                        if verified_message.answers().is_empty() {
+                            // get SOA name
+                            let soa_name = if let Some(soa_name) = verified_message
+                                .name_servers()
+                                .iter()
+                                // there should only be one
+                                .find(|rr| rr.record_type() == RecordType::SOA)
+                                .map(Record::name)
+                            {
+                                soa_name
+                            } else {
+                                return future::err(ProtoError::from(
+                                    "could not validate negative response missing SOA",
+                                ));
+                            };
+
+                            let nsecs = verified_message
+                                .name_servers()
+                                .iter()
+                                .filter(|rr| is_dnssec(rr, DNSSECRecordType::NSEC))
+                                .collect::<Vec<_>>();
+
+                            if !verify_nsec(&query, soa_name, nsecs.as_slice()) {
+                                // TODO change this to remove the NSECs, like we do for the others?
+                                return future::err(ProtoError::from(
+                                    "could not validate negative response with NSEC",
+                                ));
+                            }
+                        }
+
+                        future::ok(verified_message)
+                    }),
+            );
+        }
+
+        Box::pin(self.handle.send(request))
+    }
+}
+
+/// this pulls all records returned in a Message response and returns a future which will
+///  validate all of them.
+#[allow(clippy::type_complexity)]
+async fn verify_rrsets<H: DnsHandle + Sync + Unpin>(
+    handle: DnssecDnsHandle<H>,
+    message_result: DnsResponse,
+    dns_class: DNSClass,
+) -> Result<DnsResponse, ProtoError> {
+    let mut rrset_types: HashSet<(Name, RecordType)> = HashSet::new();
+    for rrset in message_result
+        .answers()
+        .iter()
+        .chain(message_result.name_servers())
+        .filter(|rr| {
+            !is_dnssec(rr, DNSSECRecordType::RRSIG) &&
+                             // if we are at a depth greater than 1, we are only interested in proving evaluation chains
+                             //   this means that only DNSKEY and DS are interesting at that point.
+                             //   this protects against looping over things like NS records and DNSKEYs in responses.
+                             // TODO: is there a cleaner way to prevent cycles in the evaluations?
+                                          (handle.request_depth <= 1 ||
+                                           is_dnssec(rr, DNSSECRecordType::DNSKEY) ||
+                                           is_dnssec(rr, DNSSECRecordType::DS))
+        })
+        .map(|rr| (rr.name().clone(), rr.rr_type()))
+    {
+        rrset_types.insert(rrset);
+    }
+
+    // there was no data returned in that message
+    if rrset_types.is_empty() {
+        let mut message_result = message_result;
+
+        // there were no returned results, double check by dropping all the results
+        message_result.take_answers();
+        message_result.take_name_servers();
+        message_result.take_additionals();
+
+        return Err(ProtoError::from(ProtoErrorKind::Message(
+            "no results to verify",
+        )));
+    }
+
+    // collect all the rrsets to verify
+    // TODO: is there a way to get rid of this clone() safely?
+    let mut rrsets_to_verify = Vec::with_capacity(rrset_types.len());
+    for (name, record_type) in rrset_types {
+        // TODO: should we evaluate the different sections (answers and name_servers) separately?
+        let records: Vec<Record> = message_result
+            .answers()
+            .iter()
+            .chain(message_result.name_servers())
+            .chain(message_result.additionals())
+            .filter(|rr| rr.rr_type() == record_type && rr.name() == &name)
+            .cloned()
+            .collect();
+
+        let rrsigs: Vec<Record> = message_result
+            .answers()
+            .iter()
+            .chain(message_result.name_servers())
+            .chain(message_result.additionals())
+            .filter(|rr| is_dnssec(rr, DNSSECRecordType::RRSIG))
+            .filter(|rr| {
+                if let RData::DNSSEC(DNSSECRData::SIG(ref rrsig)) = *rr.rdata() {
+                    rrsig.type_covered() == record_type
+                } else {
+                    false
+                }
+            })
+            .cloned()
+            .collect();
+
+        // if there is already an active validation going on, assume the other validation will
+        //  complete properly or error if it is invalid
+        let rrset = Rrset {
+            name,
+            record_type,
+            record_class: dns_class,
+            records,
+        };
+
+        // TODO: support non-IN classes?
+        debug!(
+            "verifying: {}, record_type: {:?}, rrsigs: {}",
+            rrset.name,
+            record_type,
+            rrsigs.len()
+        );
+        rrsets_to_verify.push(verify_rrset(handle.clone_with_context(), rrset, rrsigs).boxed());
+    }
+
+    // spawn a select_all over this vec, these are the individual RRSet validators
+    verify_all_rrsets(message_result, rrsets_to_verify).await
+}
+
+fn is_dnssec(rr: &Record, dnssec_type: DNSSECRecordType) -> bool {
+    rr.rr_type() == RecordType::DNSSEC(dnssec_type)
+}
+
+async fn verify_all_rrsets<F>(
+    message_result: DnsResponse,
+    rrsets: Vec<F>,
+) -> Result<DnsResponse, ProtoError>
+where
+    F: Future<Output = Result<Rrset, ProtoError>> + Send + Unpin,
+{
+    let mut verified_rrsets: HashSet<(Name, RecordType)> = HashSet::new();
+    let mut rrsets = future::select_all(rrsets);
+    let mut last_validation_err: Option<ProtoError> = None;
+
+    // loop through all the rrset evaluations, filter all the rrsets in the Message
+    //  down to just the ones that were able to be validated
+    loop {
+        let (rrset, _, remaining) = rrsets.await;
+        match rrset {
+            Ok(rrset) => {
+                debug!(
+                    "an rrset was verified: {}, {:?}",
+                    rrset.name, rrset.record_type
+                );
+                verified_rrsets.insert((rrset.name, rrset.record_type));
+            }
+            // TODO: should we return the Message on errors? Allow the consumer to decide what to do
+            //       on a validation failure?
+            // any error, is an error for all
+            Err(e) => {
+                debug!("an rrset failed to verify: {:?}", e);
+                last_validation_err = Some(e);
+            }
+        };
+
+        if !remaining.is_empty() {
+            // continue the evaluation
+            rrsets = future::select_all(remaining);
+        } else {
+            break;
+        }
+    }
+
+    // check if any are valid, otherwise return whatever error caused it to fail
+    if verified_rrsets.is_empty() && last_validation_err.is_some() {
+        return Err(last_validation_err.expect("can not be none based on above check"));
+    }
+
+    // validated not none above...
+    let mut message_result = message_result;
+
+    // take all the rrsets from the Message, filter down each set to the validated rrsets
+    // TODO: does the section in the message matter here?
+    //       we could probably end up with record_types in any section.
+    //       track the section in the rrset evaluation?
+    let answers = message_result
+        .take_answers()
+        .into_iter()
+        .chain(message_result.take_additionals().into_iter())
+        .filter(|record| verified_rrsets.contains(&(record.name().clone(), record.rr_type())))
+        .collect::<Vec<Record>>();
+
+    let name_servers = message_result
+        .take_name_servers()
+        .into_iter()
+        .filter(|record| verified_rrsets.contains(&(record.name().clone(), record.rr_type())))
+        .collect::<Vec<Record>>();
+
+    let additionals = message_result
+        .take_additionals()
+        .into_iter()
+        .filter(|record| verified_rrsets.contains(&(record.name().clone(), record.rr_type())))
+        .collect::<Vec<Record>>();
+
+    // add the filtered records back to the message
+    message_result.insert_answers(answers);
+    message_result.insert_name_servers(name_servers);
+    message_result.insert_additionals(additionals);
+
+    // breaks out of the loop... and returns the filtered Message.
+    Ok(message_result)
+}
+
+/// Generic entrypoint to verify any RRSET against the provided signatures.
+///
+/// Generally, the RRSET will be validated by `verify_default_rrset()`. There are additional
+///  checks that happen after the RRSET is successfully validated. In the case of DNSKEYs this
+///  triggers `verify_dnskey_rrset()`. If it's an NSEC record, then the NSEC record will be
+///  validated to prove it's correctness. There is a special case for DNSKEY, where if the RRSET
+///  is unsigned, `rrsigs` is empty, then an immediate `verify_dnskey_rrset()` is triggered. In
+///  this case, it's possible the DNSKEY is a trust_anchor and is not self-signed.
+async fn verify_rrset<H>(
+    handle: DnssecDnsHandle<H>,
+    rrset: Rrset,
+    rrsigs: Vec<Record>,
+) -> Result<Rrset, ProtoError>
+where
+    H: DnsHandle + Sync + Unpin,
+{
+    // Special case for unsigned DNSKEYs, it's valid for a DNSKEY to be bare in the zone if
+    //  it's a trust_anchor, though some DNS servers choose to self-sign in this case,
+    //  for self-signed KEYS they will drop through to the standard validation logic.
+    if let RecordType::DNSSEC(DNSSECRecordType::DNSKEY) = rrset.record_type {
+        if rrsigs.is_empty() {
+            debug!("unsigned key: {}, {:?}", rrset.name, rrset.record_type);
+            // TODO: validate that this DNSKEY is stronger than the one lower in the chain,
+            //  also, set the min algorithm to this algorithm to prevent downgrade attacks.
+            return verify_dnskey_rrset(handle.clone_with_context(), rrset).await;
+        }
+    }
+
+    // standard validation path
+    let rrset = verify_default_rrset(&handle.clone_with_context(), rrset, rrsigs).await?;
+
+    // POST validation
+    match rrset.record_type {
+        RecordType::DNSSEC(DNSSECRecordType::DNSKEY) => verify_dnskey_rrset(handle, rrset).await,
+        _ => Ok(rrset),
+    }
+}
+
+/// Verifies a dnskey rrset
+///
+/// This first checks to see if the key is in the set of trust_anchors. If so then it's returned
+///  as a success. Otherwise, a query is sent to get the DS record, and the DNSKEY is validated
+///  against the DS record.
+async fn verify_dnskey_rrset<H>(
+    mut handle: DnssecDnsHandle<H>,
+    rrset: Rrset,
+) -> Result<Rrset, ProtoError>
+where
+    H: DnsHandle + Sync + Unpin,
+{
+    debug!(
+        "dnskey validation {}, record_type: {:?}",
+        rrset.name, rrset.record_type
+    );
+
+    // check the DNSKEYS against the trust_anchor, if it's approved allow it.
+    {
+        let anchored_keys = rrset
+            .records
+            .iter()
+            .enumerate()
+            .filter(|&(_, rr)| is_dnssec(rr, DNSSECRecordType::DNSKEY))
+            .filter_map(|(i, rr)| {
+                if let RData::DNSSEC(DNSSECRData::DNSKEY(ref rdata)) = *rr.rdata() {
+                    Some((i, rdata))
+                } else {
+                    None
+                }
+            })
+            .filter_map(|(i, rdata)| {
+                if handle
+                    .trust_anchor
+                    .contains_dnskey_bytes(rdata.public_key())
+                {
+                    debug!("in trust_anchor");
+                    Some(i)
+                } else {
+                    None
+                }
+            })
+            .collect::<Vec<usize>>();
+
+        if !anchored_keys.is_empty() {
+            let mut rrset = rrset;
+            preserve(&mut rrset.records, anchored_keys);
+
+            debug!(
+                "validated dnskey with trust_anchor: {}, {}",
+                rrset.name,
+                rrset.records.len()
+            );
+            return Ok(rrset);
+        }
+    }
+
+    // need to get DS records for each DNSKEY
+    let valid_dnskey = handle
+        .lookup(
+            Query::query(rrset.name.clone(), RecordType::DNSSEC(DNSSECRecordType::DS)),
+            DnsRequestOptions::default(),
+        )
+        .and_then(move |ds_message| {
+            let valid_keys = rrset
+                .records
+                .iter()
+                .enumerate()
+                .filter(|&(_, rr)| is_dnssec(rr, DNSSECRecordType::DNSKEY))
+                .filter_map(|(i, rr)| {
+                    if let RData::DNSSEC(DNSSECRData::DNSKEY(ref rdata)) = *rr.rdata() {
+                        Some((i, rdata))
+                    } else {
+                        None
+                    }
+                })
+                .filter(|&(_, key_rdata)| {
+                    ds_message
+                        .answers()
+                        .iter()
+                        .filter(|ds| is_dnssec(ds, DNSSECRecordType::DS))
+                        .filter_map(|ds| {
+                            if let RData::DNSSEC(DNSSECRData::DS(ref ds_rdata)) = *ds.rdata() {
+                                Some(ds_rdata)
+                            } else {
+                                None
+                            }
+                        })
+                        // must be covered by at least one DS record
+                        .any(|ds_rdata| ds_rdata.covers(&rrset.name, key_rdata).unwrap_or(false))
+                })
+                .map(|(i, _)| i)
+                .collect::<Vec<usize>>();
+
+            if !valid_keys.is_empty() {
+                let mut rrset = rrset;
+                preserve(&mut rrset.records, valid_keys);
+
+                debug!("validated dnskey: {}, {}", rrset.name, rrset.records.len());
+                future::ok(rrset)
+            } else {
+                future::err(ProtoError::from(ProtoErrorKind::Message(
+                    "Could not validate all DNSKEYs",
+                )))
+            }
+        });
+
+    valid_dnskey.await
+}
+
+/// Preserves the specified indexes in vec, all others will be removed
+///
+/// # Arguments
+///
+/// * `vec` - vec to mutate
+/// * `indexes` - ordered list of indexes to remove
+fn preserve<T, I>(vec: &mut Vec<T>, indexes: I)
+where
+    I: IntoIterator<Item = usize>,
+    <I as IntoIterator>::IntoIter: DoubleEndedIterator,
+{
+    // this removes all indexes that were not part of the anchored keys
+    let mut indexes_iter = indexes.into_iter().rev();
+    let mut i = indexes_iter.next();
+    for j in (0..vec.len()).rev() {
+        // check the next index to preserve
+        if i.map_or(false, |i| i > j) {
+            i = indexes_iter.next();
+        }
+        // if the key is not in the set of anchored_keys, remove it
+        if i.map_or(true, |i| i != j) {
+            vec.remove(j);
+        }
+    }
+}
+
+#[test]
+fn test_preserve() {
+    let mut vec = vec![1, 2, 3];
+    let indexes = vec![];
+    preserve(&mut vec, indexes);
+    assert_eq!(vec, vec![]);
+
+    let mut vec = vec![1, 2, 3];
+    let indexes = vec![0];
+    preserve(&mut vec, indexes);
+    assert_eq!(vec, vec![1]);
+
+    let mut vec = vec![1, 2, 3];
+    let indexes = vec![1];
+    preserve(&mut vec, indexes);
+    assert_eq!(vec, vec![2]);
+
+    let mut vec = vec![1, 2, 3];
+    let indexes = vec![2];
+    preserve(&mut vec, indexes);
+    assert_eq!(vec, vec![3]);
+
+    let mut vec = vec![1, 2, 3];
+    let indexes = vec![0, 2];
+    preserve(&mut vec, indexes);
+    assert_eq!(vec, vec![1, 3]);
+
+    let mut vec = vec![1, 2, 3];
+    let indexes = vec![0, 1, 2];
+    preserve(&mut vec, indexes);
+    assert_eq!(vec, vec![1, 2, 3]);
+}
+
+/// Verifies that a given RRSET is validly signed by any of the specified RRSIGs.
+///
+/// Invalid RRSIGs will be ignored. RRSIGs will only be validated against DNSKEYs which can
+///  be validated through a chain back to the `trust_anchor`. As long as one RRSIG is valid,
+///  then the RRSET will be valid.
+#[allow(clippy::block_in_if_condition_stmt)]
+async fn verify_default_rrset<H>(
+    handle: &DnssecDnsHandle<H>,
+    rrset: Rrset,
+    rrsigs: Vec<Record>,
+) -> Result<Rrset, ProtoError>
+where
+    H: DnsHandle + Sync + Unpin,
+{
+    // the record set is going to be shared across a bunch of futures, Arc for that.
+    let rrset = Arc::new(rrset);
+    debug!(
+        "default validation {}, record_type: {:?}",
+        rrset.name, rrset.record_type
+    );
+
+    // Special case for self-signed DNSKEYS, validate with itself...
+    if rrsigs
+        .iter()
+        .filter(|rrsig| is_dnssec(rrsig, DNSSECRecordType::RRSIG))
+        .any(|rrsig| {
+            if let RData::DNSSEC(DNSSECRData::SIG(ref sig)) = *rrsig.rdata() {
+                RecordType::DNSSEC(DNSSECRecordType::DNSKEY) == rrset.record_type
+                    && sig.signer_name() == &rrset.name
+            } else {
+                panic!("expected a SIG here");
+            }
+        })
+    {
+        // in this case it was looks like a self-signed key, first validate the signature
+        //  then return rrset. Like the standard case below, the DNSKEY is validated
+        //  after this function. This function is only responsible for validating the signature
+        //  the DNSKey validation should come after, see verify_rrset().
+        return future::ready(
+            rrsigs
+                .into_iter()
+                // this filter is technically unnecessary, can probably remove it...
+                .filter(|rrsig| is_dnssec(rrsig, DNSSECRecordType::RRSIG))
+                .map(|rrsig| {
+                    if let RData::DNSSEC(DNSSECRData::SIG(sig)) = rrsig.unwrap_rdata() {
+                        // setting up the context explicitly.
+                        sig
+                    } else {
+                        panic!("expected a SIG here");
+                    }
+                })
+                .filter_map(|sig| {
+                    let rrset = Arc::clone(&rrset);
+
+                    if rrset.records.iter().any(|r| {
+                        if let RData::DNSSEC(DNSSECRData::DNSKEY(ref dnskey)) = *r.rdata() {
+                            verify_rrset_with_dnskey(dnskey, &sig, &rrset).is_ok()
+                        } else {
+                            panic!("expected a DNSKEY here: {:?}", r.rdata());
+                        }
+                    }) {
+                        Some(())
+                    } else {
+                        None
+                    }
+                })
+                .next()
+                .ok_or_else(|| {
+                    ProtoError::from(ProtoErrorKind::Message("self-signed dnskey is invalid"))
+                }),
+        )
+        .map_ok(move |_| Arc::try_unwrap(rrset).expect("unable to unwrap Arc"))
+        .await;
+    }
+
+    // we can validate with any of the rrsigs...
+    //  i.e. the first that validates is good enough
+    //  TODO: could there be a cert downgrade attack here with a MITM stripping stronger RRSIGs?
+    //         we could check for the strongest RRSIG and only use that...
+    //         though, since the entire package isn't signed any RRSIG could have been injected,
+    //         right? meaning if there is an attack on any of the acceptable algorithms, we'd be
+    //         susceptible until that algorithm is removed as an option.
+    //        dns over TLS will mitigate this.
+    //  TODO: strip RRSIGS to accepted algorithms and make algorithms configurable.
+    let verifications = rrsigs.into_iter()
+        // this filter is technically unnecessary, can probably remove it...
+        .filter(|rrsig| is_dnssec(rrsig, DNSSECRecordType::RRSIG))
+        .map(|rrsig|
+            if let RData::DNSSEC(DNSSECRData::SIG(sig)) = rrsig.unwrap_rdata() {
+                // setting up the context explicitly.
+                sig
+            } else {
+                panic!("expected a SIG here");
+            }
+        )
+        .map(|sig| {
+            let rrset = Arc::clone(&rrset);
+            let mut handle = handle.clone_with_context();
+
+            handle
+                .lookup(
+                    Query::query(sig.signer_name().clone(), RecordType::DNSSEC(DNSSECRecordType::DNSKEY)),
+                    DnsRequestOptions::default()
+                )
+                .and_then(move |message|
+                    // DNSKEYs are validated by the inner query
+                    future::ready(message
+                        .answers()
+                        .iter()
+                        .filter(|r| is_dnssec(r, DNSSECRecordType::DNSKEY))
+                        .find(|r|
+                            if let RData::DNSSEC(DNSSECRData::DNSKEY(ref dnskey)) = *r.rdata() {
+                                verify_rrset_with_dnskey(dnskey, &sig, &rrset).is_ok()
+                            } else {
+                                panic!("expected a DNSKEY here: {:?}", r.rdata());
+                            }
+                        )
+                        .map(|_| ())
+                        .ok_or_else(|| ProtoError::from(ProtoErrorKind::Message("validation failed"))))
+                )
+        })
+        .collect::<Vec<_>>();
+
+    // if there are no available verifications, then we are in a failed state.
+    if verifications.is_empty() {
+        return Err(ProtoError::from(ProtoErrorKind::RrsigsNotPresent {
+            name: rrset.name.clone(),
+            record_type: rrset.record_type,
+        }));
+    }
+
+    // as long as any of the verifications is good, then the RRSET is valid.
+    let select = future::select_ok(verifications)
+        // getting here means at least one of the rrsigs succeeded...
+        .map_ok(move |((), rest)| {
+            drop(rest); // drop all others, should free up Arc
+            Arc::try_unwrap(rrset).expect("unable to unwrap Arc")
+        });
+
+    select.await
+}
+
+/// Verifies the given SIG of the RRSET with the DNSKEY.
+#[cfg(feature = "dnssec")]
+fn verify_rrset_with_dnskey(dnskey: &DNSKEY, sig: &SIG, rrset: &Rrset) -> ProtoResult<()> {
+    if dnskey.revoke() {
+        debug!("revoked");
+        return Err(ProtoErrorKind::Message("revoked").into());
+    } // TODO: does this need to be validated? RFC 5011
+    if !dnskey.zone_key() {
+        return Err(ProtoErrorKind::Message("is not a zone key").into());
+    }
+    if dnskey.algorithm() != sig.algorithm() {
+        return Err(ProtoErrorKind::Message("mismatched algorithm").into());
+    }
+
+    dnskey
+        .verify_rrsig(&rrset.name, rrset.record_class, sig, &rrset.records)
+        .map_err(Into::into)
+}
+
+/// Will always return an error. To enable record verification compile with the openssl feature.
+#[cfg(not(feature = "dnssec"))]
+fn verify_rrset_with_dnskey(_: &DNSKEY, _: &SIG, _: &Rrset) -> ProtoResult<()> {
+    Err(ProtoErrorKind::Message("openssl or ring feature(s) not enabled").into())
+}
+
+/// Verifies NSEC records
+///
+/// ```text
+/// RFC 4035             DNSSEC Protocol Modifications            March 2005
+///
+/// 5.4.  Authenticated Denial of Existence
+///
+///  A resolver can use authenticated NSEC RRs to prove that an RRset is
+///  not present in a signed zone.  Security-aware name servers should
+///  automatically include any necessary NSEC RRs for signed zones in
+///  their responses to security-aware resolvers.
+///
+///  Denial of existence is determined by the following rules:
+///
+///  o  If the requested RR name matches the owner name of an
+///     authenticated NSEC RR, then the NSEC RR's type bit map field lists
+///     all RR types present at that owner name, and a resolver can prove
+///     that the requested RR type does not exist by checking for the RR
+///     type in the bit map.  If the number of labels in an authenticated
+///     NSEC RR's owner name equals the Labels field of the covering RRSIG
+///     RR, then the existence of the NSEC RR proves that wildcard
+///     expansion could not have been used to match the request.
+///
+///  o  If the requested RR name would appear after an authenticated NSEC
+///     RR's owner name and before the name listed in that NSEC RR's Next
+///     Domain Name field according to the canonical DNS name order
+///     defined in [RFC4034], then no RRsets with the requested name exist
+///     in the zone.  However, it is possible that a wildcard could be
+///     used to match the requested RR owner name and type, so proving
+///     that the requested RRset does not exist also requires proving that
+///     no possible wildcard RRset exists that could have been used to
+///     generate a positive response.
+///
+///  In addition, security-aware resolvers MUST authenticate the NSEC
+///  RRsets that comprise the non-existence proof as described in Section
+///  5.3.
+///
+///  To prove the non-existence of an RRset, the resolver must be able to
+///  verify both that the queried RRset does not exist and that no
+///  relevant wildcard RRset exists.  Proving this may require more than
+///  one NSEC RRset from the zone.  If the complete set of necessary NSEC
+///  RRsets is not present in a response (perhaps due to message
+///  truncation), then a security-aware resolver MUST resend the query in
+///  order to attempt to obtain the full collection of NSEC RRs necessary
+///  to verify the non-existence of the requested RRset.  As with all DNS
+///  operations, however, the resolver MUST bound the work it puts into
+///  answering any particular query.
+///
+///  Since a validated NSEC RR proves the existence of both itself and its
+///  corresponding RRSIG RR, a validator MUST ignore the settings of the
+///  NSEC and RRSIG bits in an NSEC RR.
+/// ```
+#[allow(clippy::block_in_if_condition_stmt)]
+#[doc(hidden)]
+pub fn verify_nsec(query: &Query, soa_name: &Name, nsecs: &[&Record]) -> bool {
+    // TODO: consider converting this to Result, and giving explicit reason for the failure
+
+    // first look for a record with the same name
+    //  if they are, then the query_type should not exist in the NSEC record.
+    //  if we got an NSEC record of the same name, but it is listed in the NSEC types,
+    //    WTF? is that bad server, bad record
+    if let Some(nsec) = nsecs.iter().find(|nsec| query.name() == nsec.name()) {
+        return nsec
+            .rdata()
+            .as_dnssec()
+            .and_then(DNSSECRData::as_nsec)
+            .map_or(false, |rdata| {
+                // this should not be in the covered list
+                !rdata.type_bit_maps().contains(&query.query_type())
+            });
+    }
+
+    let verify_nsec_coverage = |name: &Name| -> bool {
+        nsecs.iter().any(|nsec| {
+            // the query name must be greater than nsec's label (or equal in the case of wildcard)
+            name >= nsec.name() && {
+                nsec.rdata()
+                    .as_dnssec()
+                    .and_then(DNSSECRData::as_nsec)
+                    .map_or(false, |rdata| {
+                        // the query name is less than the next name
+                        // or this record wraps the end, i.e. is the last record
+                        name < rdata.next_domain_name() || rdata.next_domain_name() < nsec.name()
+                    })
+            }
+        })
+    };
+
+    if !verify_nsec_coverage(query.name()) {
+        // continue to validate there is no wildcard
+        return false;
+    }
+
+    // validate ANY or *.domain record existence
+
+    // we need the wildcard proof, but make sure that it's still part of the zone.
+    let wildcard = query.name().base_name();
+    let wildcard = if soa_name.zone_of(&wildcard) {
+        wildcard
+    } else {
+        soa_name.clone()
+    };
+
+    // don't need to validate the same name again
+    if wildcard == *query.name() {
+        // this was validated by the nsec coverage over the query.name()
+        true
+    } else {
+        // this is the final check, return it's value
+        //  if there is wildcard coverage, we're good.
+        verify_nsec_coverage(&wildcard)
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/xfer/mod.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/xfer/mod.rs
new file mode 100644
index 0000000..7958648
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/xfer/mod.rs
@@ -0,0 +1,336 @@
+//! DNS high level transit implimentations.
+//!
+//! Primarily there are two types in this module of interest, the `DnsMultiplexer` type and the `DnsHandle` type. `DnsMultiplexer` can be thought of as the state machine responsible for sending and receiving DNS messages. `DnsHandle` is the type given to API users of the `trust-dns-proto` library to send messages into the `DnsMultiplexer` for delivery. Finally there is the `DnsRequest` type. This allows for customizations, through `DnsRequestOptions`, to the delivery of messages via a `DnsMultiplexer`.
+//!
+//! TODO: this module needs some serious refactoring and normalization.
+
+use std::fmt::{Debug, Display};
+use std::net::SocketAddr;
+use std::pin::Pin;
+use std::task::{Context, Poll};
+
+use futures::channel::mpsc::{TrySendError, UnboundedSender};
+use futures::channel::oneshot::{self, Receiver, Sender};
+use futures::{ready, Future, Stream};
+use log::{debug, warn};
+
+use crate::error::*;
+use crate::Time;
+
+mod dns_exchange;
+pub mod dns_handle;
+pub mod dns_multiplexer;
+pub mod dns_request;
+pub mod dns_response;
+#[cfg(feature = "dnssec")]
+pub mod dnssec_dns_handle;
+pub mod retry_dns_handle;
+mod serial_message;
+
+pub use self::dns_exchange::{
+    DnsExchange, DnsExchangeBackground, DnsExchangeConnect, DnsExchangeSend,
+};
+pub use self::dns_handle::{DnsHandle, DnsStreamHandle, StreamHandle};
+pub use self::dns_multiplexer::{
+    DnsMultiplexer, DnsMultiplexerConnect, DnsMultiplexerSerialResponse,
+};
+pub use self::dns_request::{DnsRequest, DnsRequestOptions};
+pub use self::dns_response::DnsResponse;
+#[cfg(feature = "dnssec")]
+pub use self::dnssec_dns_handle::DnssecDnsHandle;
+pub use self::retry_dns_handle::RetryDnsHandle;
+pub use self::serial_message::SerialMessage;
+
+/// Ignores the result of a send operation and logs and ignores errors
+fn ignore_send<M, E: Debug>(result: Result<M, E>) {
+    if let Err(error) = result {
+        warn!("error notifying wait, possible future leak: {:?}", error);
+    }
+}
+
+/// A non-multiplexed stream of Serialized DNS messages
+pub trait DnsClientStream:
+    Stream<Item = Result<SerialMessage, ProtoError>> + Display + Send
+{
+    /// The remote name server address
+    fn name_server_addr(&self) -> SocketAddr;
+}
+
+// TODO: change to Sink
+/// A sender to which serialized DNS Messages can be sent
+#[derive(Clone)]
+pub struct BufStreamHandle {
+    sender: UnboundedSender<SerialMessage>,
+}
+
+impl BufStreamHandle {
+    /// Constructs a new BufStreamHandle with the associated ProtoError
+    pub fn new(sender: UnboundedSender<SerialMessage>) -> Self {
+        BufStreamHandle { sender }
+    }
+
+    /// see [`futures::sync::mpsc::UnboundedSender`]
+    pub fn unbounded_send(&self, msg: SerialMessage) -> Result<(), TrySendError<SerialMessage>> {
+        self.sender.unbounded_send(msg)
+    }
+}
+
+/// A buffering stream bound to a `SocketAddr`
+pub struct BufDnsStreamHandle {
+    name_server: SocketAddr,
+    sender: BufStreamHandle,
+}
+
+impl BufDnsStreamHandle {
+    /// Constructs a new Buffered Stream Handle, used for sending data to the DNS peer.
+    ///
+    /// # Arguments
+    ///
+    /// * `name_server` - the address of the DNS server
+    /// * `sender` - the handle being used to send data to the server
+    pub fn new(name_server: SocketAddr, sender: BufStreamHandle) -> Self {
+        BufDnsStreamHandle {
+            name_server,
+            sender,
+        }
+    }
+}
+
+impl DnsStreamHandle for BufDnsStreamHandle {
+    fn send(&mut self, buffer: SerialMessage) -> Result<(), ProtoError> {
+        let name_server: SocketAddr = self.name_server;
+        let sender: &mut _ = &mut self.sender;
+        sender
+            .sender
+            .unbounded_send(SerialMessage::new(buffer.unwrap().0, name_server))
+            .map_err(|e| ProtoError::from(format!("mpsc::SendError {}", e)))
+    }
+}
+
+// TODO: expose the Sink trait for this?
+/// A sender to which serialized DNS Messages can be sent
+pub struct DnsRequestStreamHandle<F>
+where
+    F: Future<Output = Result<DnsResponse, ProtoError>> + Send,
+{
+    sender: UnboundedSender<OneshotDnsRequest<F>>,
+}
+
+impl<F> DnsRequestStreamHandle<F>
+where
+    F: Future<Output = Result<DnsResponse, ProtoError>> + Send,
+{
+    /// Constructs a new BufStreamHandle with the associated ProtoError
+    pub fn new(sender: UnboundedSender<OneshotDnsRequest<F>>) -> Self {
+        DnsRequestStreamHandle { sender }
+    }
+
+    /// see [`futures::sync::mpsc::UnboundedSender`]
+    pub fn unbounded_send(
+        &self,
+        msg: OneshotDnsRequest<F>,
+    ) -> Result<(), TrySendError<OneshotDnsRequest<F>>> {
+        self.sender.unbounded_send(msg)
+    }
+}
+
+impl<F> Clone for DnsRequestStreamHandle<F>
+where
+    F: Future<Output = Result<DnsResponse, ProtoError>> + Send,
+{
+    fn clone(&self) -> Self {
+        DnsRequestStreamHandle {
+            sender: self.sender.clone(),
+        }
+    }
+}
+
+/// Types that implement this are capable of sending a serialized DNS message on a stream
+///
+/// The underlying Stream implementation should yield `Some(())` whenever it is ready to send a message,
+///   NotReady, if it is not ready to send a message, and `Err` or `None` in the case that the stream is
+///   done, and should be shutdown.
+pub trait DnsRequestSender: Stream<Item = Result<(), ProtoError>> + Send + Unpin + 'static {
+    /// A future that resolves to a response serial message
+    type DnsResponseFuture: Future<Output = Result<DnsResponse, ProtoError>>
+        + 'static
+        + Send
+        + Unpin;
+
+    /// Send a message, and return a future of the response
+    ///
+    /// # Return
+    ///
+    /// A future which will resolve to a SerialMessage response
+    fn send_message<TE: Time>(
+        &mut self,
+        message: DnsRequest,
+        cx: &mut Context,
+    ) -> Self::DnsResponseFuture;
+
+    /// Constructs an error response
+    fn error_response<TE: Time>(error: ProtoError) -> Self::DnsResponseFuture;
+
+    /// Allows the upstream user to inform the underling stream that it should shutdown.
+    ///
+    /// After this is called, the next time `poll` is called on the stream it would be correct to return `Poll::Ready(Ok(()))`. This is not required though, if there are say outstanding requests that are not yet complete, then it would be correct to first wait for those results.
+    fn shutdown(&mut self);
+
+    /// Returns true if the stream has been shutdown with `shutdown`
+    fn is_shutdown(&self) -> bool;
+}
+
+/// Used for associating a name_server to a DnsRequestStreamHandle
+pub struct BufDnsRequestStreamHandle<F>
+where
+    F: Future<Output = Result<DnsResponse, ProtoError>> + Send,
+{
+    sender: DnsRequestStreamHandle<F>,
+}
+
+impl<F> BufDnsRequestStreamHandle<F>
+where
+    F: Future<Output = Result<DnsResponse, ProtoError>> + Send,
+{
+    /// Construct a new BufDnsRequestStreamHandle
+    pub fn new(sender: DnsRequestStreamHandle<F>) -> Self {
+        BufDnsRequestStreamHandle { sender }
+    }
+}
+
+impl<F> Clone for BufDnsRequestStreamHandle<F>
+where
+    F: Future<Output = Result<DnsResponse, ProtoError>> + Send,
+{
+    fn clone(&self) -> Self {
+        BufDnsRequestStreamHandle {
+            sender: self.sender.clone(),
+        }
+    }
+}
+
+macro_rules! try_oneshot {
+    ($expr:expr) => {{
+        use std::result::Result;
+
+        match $expr {
+            Result::Ok(val) => val,
+            Result::Err(err) => {
+                return OneshotDnsResponseReceiver::Err(Some(ProtoError::from(err)))
+            }
+        }
+    }};
+    ($expr:expr,) => {
+        $expr?
+    };
+}
+
+impl<F> DnsHandle for BufDnsRequestStreamHandle<F>
+where
+    F: Future<Output = Result<DnsResponse, ProtoError>> + Send + Unpin + 'static,
+{
+    type Response = OneshotDnsResponseReceiver<F>;
+
+    fn send<R: Into<DnsRequest>>(&mut self, request: R) -> Self::Response {
+        let request: DnsRequest = request.into();
+        debug!("enqueueing message: {:?}", request.queries());
+
+        let (request, oneshot) = OneshotDnsRequest::oneshot(request);
+        try_oneshot!(self.sender.unbounded_send(request).map_err(|_| {
+            debug!("unable to enqueue message");
+            ProtoError::from("could not send request")
+        }));
+
+        OneshotDnsResponseReceiver::Receiver(oneshot)
+    }
+}
+
+// TODO: this future should return the origin message in the response on errors
+/// A OneshotDnsRequest creates a channel for a response to message
+pub struct OneshotDnsRequest<F>
+where
+    F: Future<Output = Result<DnsResponse, ProtoError>> + Send,
+{
+    dns_request: DnsRequest,
+    sender_for_response: Sender<F>,
+}
+
+impl<F> OneshotDnsRequest<F>
+where
+    F: Future<Output = Result<DnsResponse, ProtoError>> + Send,
+{
+    fn oneshot(dns_request: DnsRequest) -> (OneshotDnsRequest<F>, oneshot::Receiver<F>) {
+        let (sender_for_response, receiver) = oneshot::channel();
+
+        (
+            OneshotDnsRequest {
+                dns_request,
+                sender_for_response,
+            },
+            receiver,
+        )
+    }
+
+    fn unwrap(self) -> (DnsRequest, OneshotDnsResponse<F>) {
+        (
+            self.dns_request,
+            OneshotDnsResponse(self.sender_for_response),
+        )
+    }
+}
+
+struct OneshotDnsResponse<F>(oneshot::Sender<F>)
+where
+    F: Future<Output = Result<DnsResponse, ProtoError>> + Send;
+
+impl<F> OneshotDnsResponse<F>
+where
+    F: Future<Output = Result<DnsResponse, ProtoError>> + Send,
+{
+    fn send_response(self, serial_response: F) -> Result<(), F> {
+        self.0.send(serial_response)
+    }
+}
+
+/// A Future that wraps a oneshot::Receiver and resolves to the final value
+pub enum OneshotDnsResponseReceiver<F>
+where
+    F: Future<Output = Result<DnsResponse, ProtoError>> + Send + Unpin,
+{
+    /// The receiver
+    Receiver(Receiver<F>),
+    /// The future once received
+    Received(F),
+    /// Error during the send operation
+    Err(Option<ProtoError>),
+}
+
+impl<F> Future for OneshotDnsResponseReceiver<F>
+where
+    F: Future<Output = Result<DnsResponse, ProtoError>> + Send + Unpin,
+{
+    type Output = <F as Future>::Output;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+        loop {
+            *self = match *self.as_mut() {
+                OneshotDnsResponseReceiver::Receiver(ref mut receiver) => {
+                    let receiver = Pin::new(receiver);
+                    let future = ready!(receiver
+                        .poll(cx)
+                        .map_err(|_| ProtoError::from("receiver was canceled")))?;
+                    OneshotDnsResponseReceiver::Received(future)
+                }
+                OneshotDnsResponseReceiver::Received(ref mut future) => {
+                    let future = Pin::new(future);
+                    return future.poll(cx);
+                }
+                OneshotDnsResponseReceiver::Err(ref mut err) => {
+                    return Poll::Ready(Err(err
+                        .take()
+                        .expect("futures should not be polled after complete")))
+                }
+            };
+        }
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/xfer/retry_dns_handle.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/xfer/retry_dns_handle.rs
new file mode 100644
index 0000000..8aadc29
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/xfer/retry_dns_handle.rs
@@ -0,0 +1,161 @@
+// Copyright 2015-2016 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! `RetryDnsHandle` allows for DnsQueries to be reattempted on failure
+
+use std::pin::Pin;
+use std::task::{Context, Poll};
+
+use futures::{Future, FutureExt};
+
+use crate::error::ProtoError;
+use crate::xfer::{DnsRequest, DnsResponse};
+use crate::DnsHandle;
+
+/// Can be used to reattempt a queries if they fail
+///
+/// *note* Current value of this is not clear, it may be removed
+#[derive(Clone)]
+#[must_use = "queries can only be sent through a ClientHandle"]
+pub struct RetryDnsHandle<H: DnsHandle + Unpin + Send> {
+    handle: H,
+    attempts: usize,
+}
+
+impl<H: DnsHandle + Unpin> RetryDnsHandle<H> {
+    /// Creates a new Client handler for reattempting requests on failures.
+    ///
+    /// # Arguments
+    ///
+    /// * `handle` - handle to the dns connection
+    /// * `attempts` - number of attempts before failing
+    pub fn new(handle: H, attempts: usize) -> Self {
+        RetryDnsHandle { handle, attempts }
+    }
+}
+
+impl<H> DnsHandle for RetryDnsHandle<H>
+where
+    H: DnsHandle + Send + Unpin + 'static,
+{
+    type Response = Pin<Box<dyn Future<Output = Result<DnsResponse, ProtoError>> + Send + Unpin>>;
+
+    fn send<R: Into<DnsRequest>>(&mut self, request: R) -> Self::Response {
+        let request = request.into();
+
+        // need to clone here so that the retry can resend if necessary...
+        //  obviously it would be nice to be lazy about this...
+        let future = self.handle.send(request.clone());
+
+        Box::pin(RetrySendFuture {
+            request,
+            handle: self.handle.clone(),
+            future,
+            remaining_attempts: self.attempts,
+        })
+    }
+}
+
+/// A future for retrying (on failure, for the remaining number of times specified)
+struct RetrySendFuture<H: DnsHandle> {
+    request: DnsRequest,
+    handle: H,
+    future: <H as DnsHandle>::Response,
+    remaining_attempts: usize,
+}
+
+impl<H: DnsHandle + Unpin> Future for RetrySendFuture<H> {
+    type Output = Result<DnsResponse, ProtoError>;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+        // loop over the future, on errors, spawn a new future
+        //  on ready and not ready return.
+        loop {
+            match self.future.poll_unpin(cx) {
+                Poll::Ready(Err(e)) => {
+                    if self.remaining_attempts == 0 {
+                        return Poll::Ready(Err(e));
+                    }
+
+                    self.remaining_attempts -= 1;
+                    // TODO: if the "sent" Message is part of the error result,
+                    //  then we can just reuse it... and no clone necessary
+                    let request = self.request.clone();
+                    self.future = self.handle.send(request);
+                }
+                poll => return poll,
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+    use crate::error::*;
+    use crate::op::*;
+    use futures::executor::block_on;
+    use futures::future::*;
+    use std::sync::{
+        atomic::{AtomicU16, Ordering},
+        Arc,
+    };
+    use DnsHandle;
+
+    #[derive(Clone)]
+    struct TestClient {
+        last_succeed: bool,
+        retries: u16,
+        attempts: Arc<AtomicU16>,
+    }
+
+    impl DnsHandle for TestClient {
+        type Response = Box<dyn Future<Output = Result<DnsResponse, ProtoError>> + Send + Unpin>;
+
+        fn send<R: Into<DnsRequest>>(&mut self, _: R) -> Self::Response {
+            let i = self.attempts.load(Ordering::SeqCst);
+
+            if (i > self.retries || self.retries - i == 0) && self.last_succeed {
+                let mut message = Message::new();
+                message.set_id(i);
+                return Box::new(ok(message.into()));
+            }
+
+            self.attempts.fetch_add(1, Ordering::SeqCst);
+            Box::new(err(ProtoError::from("last retry set to fail")))
+        }
+    }
+
+    #[test]
+    fn test_retry() {
+        let mut handle = RetryDnsHandle::new(
+            TestClient {
+                last_succeed: true,
+                retries: 1,
+                attempts: Arc::new(AtomicU16::new(0)),
+            },
+            2,
+        );
+        let test1 = Message::new();
+        let result = block_on(handle.send(test1)).expect("should have succeeded");
+        assert_eq!(result.id(), 1); // this is checking the number of iterations the TestClient ran
+    }
+
+    #[test]
+    fn test_error() {
+        let mut client = RetryDnsHandle::new(
+            TestClient {
+                last_succeed: false,
+                retries: 1,
+                attempts: Arc::new(AtomicU16::new(0)),
+            },
+            2,
+        );
+        let test1 = Message::new();
+        assert!(block_on(client.send(test1)).is_err());
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-proto/src/xfer/serial_message.rs b/third_party/rust_crates/vendor/trust-dns-proto/src/xfer/serial_message.rs
new file mode 100644
index 0000000..c34024f
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-proto/src/xfer/serial_message.rs
@@ -0,0 +1,45 @@
+// Copyright 2015-2018 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+use std::net::SocketAddr;
+
+use crate::error::ProtoResult;
+use crate::op::Message;
+
+/// A DNS message in serialized form, with either the target address or source address
+pub struct SerialMessage {
+    // TODO: change to Bytes? this would be more compatible with some underlying libraries
+    message: Vec<u8>,
+    addr: SocketAddr,
+}
+
+impl SerialMessage {
+    /// Construct a new SerialMessage and the source or destination address
+    pub fn new(message: Vec<u8>, addr: SocketAddr) -> Self {
+        SerialMessage { message, addr }
+    }
+
+    /// Get a reference to the bytes
+    pub fn bytes(&self) -> &[u8] {
+        &self.message
+    }
+
+    /// Get the source or destination address (context dependent)
+    pub fn addr(&self) -> SocketAddr {
+        self.addr
+    }
+
+    /// Unwrap the Bytes and address
+    pub fn unwrap(self) -> (Vec<u8>, SocketAddr) {
+        (self.message, self.addr)
+    }
+
+    /// Deserializes the inner data into a Message
+    pub fn to_message(&self) -> ProtoResult<Message> {
+        Message::from_vec(&self.message)
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/.cargo-checksum.json b/third_party/rust_crates/vendor/trust-dns-resolver/.cargo-checksum.json
new file mode 100644
index 0000000..ccf778e
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.lock":"990e36f2bb660e7b159f2ee0c21743c7005b9553515bcd73227fb66780454d59","Cargo.toml":"c69b9c2746bc931d416ccd5aeaf68e7e23f712a72be8a4fdd755e1f3b37ef46e","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"10d73bf26900fa6dd6f2613bb962b7bd8fa1e66618fcf0f9f899aa071a4ee200","Makefile.toml":"795e2807c1a487d38554631febf1c8e539d8de0aa390aecf7c44e7e6f8ccdef3","README.md":"0a73bbe6275ca51f22da30fd16c779eb3a7cc78798bd7e26eab59dec62757efd","examples/global_resolver.rs":"7ab547cf4a0fe8a44e1eb47d86ba15391def9310d7fa20c55a7da3611ec54561","examples/multithreaded_runtime.rs":"9f7de91e3ab09ae1d935e42571ec3b2b0f9543e95cad86877fd628ffaee4a1d6","src/async_resolver.rs":"75ba400b80dad176ba60dafdeeb386e3e8475e9428292feb31d9ce16d67abb2a","src/config.rs":"c74b75262cdd88c765fa2b38837ad2f48b414e3e745d3c98a31939aef1587e71","src/dns_lru.rs":"eacbbe75c69a864ccca331c2c3c61af8941b8da6c5758ed46626236f765b9a9a","src/dns_sd.rs":"6d18845a6092a736e29df22c9ce9041ccd7baf364a75cab70aecc6b8a2dd9ea4","src/error.rs":"e2954cfd96b615364e626de4443535ac47ad37767c5c627d87c2c3d0d8474d89","src/hosts.rs":"74d3eb647520df844815105aab3e27be4384571005980c4c18ad3e737e055ae0","src/https.rs":"82fb305bce03a3f3f93dd6bfeca06e27113f0fd658b3773feeaa2ddd38c71993","src/lib.rs":"629d3e72ea9f7692225b9538bbe54aac6beba0fde3dba889ce37297bb4cd18db","src/lookup.rs":"c35ccc5c0d0171bb0a76ca9365237b325f2b18dae8168dbca7eff72cd8d305e6","src/lookup_ip.rs":"5cf1f91faa20541dec77a3ab67282de916bfb2214c1be49b333d63665674847a","src/lookup_state.rs":"c0afa10a7faec9a4bb16351b10a37184275c534c13669f839b900810350a2d00","src/name_server/connection_provider.rs":"1a3ffa77eddef79c15751025ded52f1259571cc408aa68574d33262cf23b23a1","src/name_server/mod.rs":"8c3479eaaf817d98a04dbbc03d575af9e0a02a6473853dac94d2de35a716b343","src/name_server/name_server.rs":"ebc9b38710ca17ba2024f5e0ec910b9e5f05160f3efb39330673ecd2f25c8e09","src/name_server/name_server_pool.rs":"39113bd1f2e2edbde91ff727301a37e251ad7e6d27abd1b911c9e86ee3cf3783","src/name_server/name_server_state.rs":"255a8cc2bb2f50becb52d010dabadb75147eb4735590278b1c413be255c4b00d","src/name_server/name_server_stats.rs":"ba625618f6d0f00a2d8444c4d096d4d68a64a07bcacc3747a129d8d384657be9","src/resolver.rs":"2d3e52a9fe6be1dafb29902ccfaf6994f0d4e04b61d614b7ebcd02a7c7f8ebb1","src/system_conf/mod.rs":"e0a503a1cd86475350b880a5e83535a7ec6549a6c5bd9d878b49d607de3bcd8b","src/system_conf/unix.rs":"7e2adb00208523198ac503c2f783b247ffa002a83f8fba1a80293079fa999b01","src/system_conf/windows.rs":"a5d1635be1482f708e0729882c7240b31900c6b4f2f5b2ac4fb05958e56ff8de","src/tls/dns_over_native_tls.rs":"91415aef8b68f8b2b49ca78ef631186d8deb467e6a586ab67fd4bcb976a61872","src/tls/dns_over_openssl.rs":"457a686261a18d56f176b7ceaee55d6b538ed3f14b0696b994208ba96b0da025","src/tls/dns_over_rustls.rs":"8d504e2007eeaa6916900352c7659a1825c3f0abe36b113854ac18572a0bfa95","src/tls/mod.rs":"eccde1ca1836ea3ca694202dc080d8e1a098eb462635f82e38c42c5f3d005bce","tests/hosts":"7db3fd5310a533ec943382fd26cae8ec8d26ef969d2c03a69ef5ae59a6e2ec1d","tests/resolv.conf-linux":"6428de5b2cdfaccccece1d5b79b34a26b7c6e5e7f9751a1dbef2e4d6c8be4a71","tests/resolv.conf-macos":"5ef7c2fed4468e94d88e2b05f93ffe349a43c54d27ad66ff92cb434bec1ac376","tests/resolv.conf-simple":"198a8782d693cd733822aad06c36dbe64a03105bc89c5677e34508011967f048"},"package":"4b1d87b791540d243a84329cc922a76daf9b89680053f947873ca89078a14a77"}
\ No newline at end of file
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/Cargo.lock b/third_party/rust_crates/vendor/trust-dns-resolver/Cargo.lock
new file mode 100644
index 0000000..a289daa
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/Cargo.lock
@@ -0,0 +1,1447 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "aho-corasick"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "async-trait"
+version = "0.1.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "atty"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "autocfg"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "autocfg"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "backtrace"
+version = "0.3.42"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "backtrace-sys"
+version = "0.1.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "base64"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "base64"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "bitflags"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "bumpalo"
+version = "3.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "byteorder"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "bytes"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "c2-chacha"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "cc"
+version = "1.0.50"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "cfg-if"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "chrono"
+version = "0.4.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "core-foundation"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "data-encoding"
+version = "2.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "enum-as-inner"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "env_logger"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "fnv"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "foreign-types"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "foreign-types-shared"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "fuchsia-zircon"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "fuchsia-zircon-sys"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "futures"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-executor 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "futures-channel"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "futures-core"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "futures-executor"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "futures-io"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "futures-macro"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "futures-sink"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "futures-task"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "futures-util"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-macro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.1.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
+ "wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "h2"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "indexmap 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "heck"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "hostname"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winutil 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "http"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "humantime"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "idna"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-normalization 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "indexmap"
+version = "1.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "iovec"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "ipconfig"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "widestring 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "itoa"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "js-sys"
+version = "0.3.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "wasm-bindgen 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "kernel32-sys"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "libc"
+version = "0.2.66"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "linked-hash-map"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "log"
+version = "0.4.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "lru-cache"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "matches"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "memchr"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "mime"
+version = "0.3.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "mio"
+version = "0.6.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "miow"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "native-tls"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl 0.10.26 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.53 (registry+https://github.com/rust-lang/crates.io-index)",
+ "schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
+ "security-framework 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "net2"
+version = "0.2.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "nom"
+version = "4.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num-integer"
+version = "0.1.42"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "openssl"
+version = "0.10.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.53 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "openssl-probe"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "openssl-sys"
+version = "0.9.53"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "percent-encoding"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "pin-project-lite"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0-alpha.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "pkg-config"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "proc-macro-hack"
+version = "0.5.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "proc-macro-nested"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "quick-error"
+version = "1.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "quote"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rand"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rand_hc"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.1.56"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "regex"
+version = "1.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex-syntax 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "remove_dir_all"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "resolv-conf"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "ring"
+version = "0.16.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
+ "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "web-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "rustls"
+version = "0.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "schannel"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "sct"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "security-framework"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
+ "security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "security-framework-sys"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "serde"
+version = "1.0.104"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.104"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "slab"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "smallvec"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "socket2"
+version = "0.3.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "sourcefile"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "spin"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "syn"
+version = "1.0.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tempfile"
+version = "3.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
+ "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "termcolor"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "thiserror-impl 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "thread_local"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "time"
+version = "0.1.42"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pin-project-lite 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-openssl"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "openssl 0.10.26 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-rustls"
+version = "0.12.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-tls"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-util"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pin-project-lite 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "trust-dns-https"
+version = "0.19.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "backtrace 0.3.42 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "h2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-rustls 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "trust-dns-proto 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "trust-dns-rustls 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "typed-headers 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "webpki-roots 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "trust-dns-native-tls"
+version = "0.19.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-tls 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "trust-dns-proto 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "trust-dns-openssl"
+version = "0.19.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl 0.10.26 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-openssl 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "trust-dns-proto 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "trust-dns-proto"
+version = "0.19.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "async-trait 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "backtrace 0.3.42 (registry+https://github.com/rust-lang/crates.io-index)",
+ "data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "enum-as-inner 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl 0.10.26 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "trust-dns-resolver"
+version = "0.19.2"
+dependencies = [
+ "backtrace 0.3.42 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ipconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-openssl 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-rustls 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-tls 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "trust-dns-https 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "trust-dns-native-tls 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "trust-dns-openssl 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "trust-dns-proto 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "trust-dns-rustls 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "webpki-roots 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "trust-dns-rustls"
+version = "0.19.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-rustls 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "trust-dns-proto 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "typed-headers"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "unicode-bidi"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "unicode-normalization"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "unicode-segmentation"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "untrusted"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "url"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "vcpkg"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "version_check"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "wasi"
+version = "0.9.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.58"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "wasm-bindgen-macro 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.58"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bumpalo 3.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "wasm-bindgen-shared 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.58"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "wasm-bindgen-macro-support 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.58"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "wasm-bindgen-backend 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
+ "wasm-bindgen-shared 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.58"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "wasm-bindgen-webidl"
+version = "0.2.58"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
+ "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "wasm-bindgen-backend 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
+ "weedle 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "web-sys"
+version = "0.3.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
+ "js-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
+ "sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "wasm-bindgen 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
+ "wasm-bindgen-webidl 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "webpki"
+version = "0.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "webpki-roots"
+version = "0.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "weedle"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "widestring"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "winapi-build"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winreg"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "winutil"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "ws2_32-sys"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[metadata]
+"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d"
+"checksum anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c"
+"checksum async-trait 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "c8df72488e87761e772f14ae0c2480396810e51b2c2ade912f97f0f7e5b95e3c"
+"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
+"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
+"checksum backtrace 0.3.42 (registry+https://github.com/rust-lang/crates.io-index)" = "b4b1549d804b6c73f4817df2ba073709e96e426f12987127c48e6745568c350b"
+"checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491"
+"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
+"checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
+"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
+"checksum bumpalo 3.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5fb8038c1ddc0a5f73787b130f4cc75151e96ed33e417fde765eb5a81e3532f4"
+"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
+"checksum bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "10004c15deb332055f7a4a208190aed362cf9a7c2f6ab70a305fba50e1105f38"
+"checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb"
+"checksum cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)" = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd"
+"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
+"checksum chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "31850b4a4d6bae316f7a09e691c944c28299298837edc0a03f755618c23cbc01"
+"checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d"
+"checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b"
+"checksum data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f4f47ca1860a761136924ddd2422ba77b2ea54fe8cc75b9040804a0d9d32ad97"
+"checksum enum-as-inner 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "900a6c7fbe523f4c2884eaf26b57b81bb69b6810a01a236390a7ac021d09492e"
+"checksum env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
+"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
+"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
+"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
+"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
+"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
+"checksum futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b6f16056ecbb57525ff698bb955162d0cd03bee84e6241c27ff75c08d8ca5987"
+"checksum futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fcae98ca17d102fd8a3603727b9259fcf7fa4239b603d2142926189bc8999b86"
+"checksum futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "79564c427afefab1dfb3298535b21eda083ef7935b4f0ecbfcb121f0aec10866"
+"checksum futures-executor 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1e274736563f686a837a0568b478bdabfeaec2dca794b5649b04e2fe1627c231"
+"checksum futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e676577d229e70952ab25f3945795ba5b16d63ca794ca9d2c860e5595d20b5ff"
+"checksum futures-macro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "52e7c56c15537adb4f76d0b7a76ad131cb4d2f4f32d3b0bcabcbe1c7c5e87764"
+"checksum futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "171be33efae63c2d59e6dbba34186fe0d6394fb378069a76dfd80fdcffd43c16"
+"checksum futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0bae52d6b29cf440e298856fec3965ee6fa71b06aa7495178615953fd669e5f9"
+"checksum futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d66274fb76985d3c62c886d1da7ac4c0903a8c9f754e8fe0f35a6a6cc39e76"
+"checksum getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
+"checksum h2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9433d71e471c1736fd5a61b671fc0b148d7a2992f666c958d03cd8feb3b88d1"
+"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
+"checksum hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eff2656d88f158ce120947499e971d743c05dbcbed62e5bd2f38f1698bbc3772"
+"checksum hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e"
+"checksum http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b708cc7f06493459026f53b9a61a7a121a5d1ec6238dee58ea4941132b30156b"
+"checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
+"checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9"
+"checksum indexmap 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b54058f0a6ff80b6803da8faf8997cde53872b38f4023728f6830b06cd3c0dc"
+"checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
+"checksum ipconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa79fa216fbe60834a9c0737d7fcd30425b32d1c58854663e24d4c4b328ed83f"
+"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
+"checksum js-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)" = "7889c7c36282151f6bf465be4700359318aef36baa951462382eae49e9577cf9"
+"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
+"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
+"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83"
+"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
+"checksum lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c"
+"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
+"checksum memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3197e20c7edb283f87c071ddfc7a2cca8f8e0b888c242959846a6fce03c72223"
+"checksum mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
+"checksum mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f"
+"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
+"checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e"
+"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
+"checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6"
+"checksum num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba"
+"checksum num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
+"checksum openssl 0.10.26 (registry+https://github.com/rust-lang/crates.io-index)" = "3a3cc5799d98e1088141b8e01ff760112bbd9f19d850c124500566ca6901a585"
+"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
+"checksum openssl-sys 0.9.53 (registry+https://github.com/rust-lang/crates.io-index)" = "465d16ae7fc0e313318f7de5cecf57b2fbe7511fd213978b457e1c96ff46736f"
+"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
+"checksum pin-project-lite 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e8822eb8bb72452f038ebf6048efa02c3fe22bf83f76519c9583e47fc194a422"
+"checksum pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587"
+"checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
+"checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b"
+"checksum proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5"
+"checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e"
+"checksum proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3acb317c6ff86a4e579dfa00fc5e6cca91ecbb4e7eb2df0468805b674eb88548"
+"checksum quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
+"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
+"checksum rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
+"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853"
+"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
+"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
+"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
+"checksum regex 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b5508c1941e4e7cb19965abef075d35a9a8b5cdf0846f30b4050e9b55dc55e87"
+"checksum regex-syntax 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e734e891f5b408a29efbf8309e656876276f49ab6a6ac208600b4419bd893d90"
+"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
+"checksum resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b263b4aa1b5de9ffc0054a2386f96992058bb6870aab516f8cdeb8a667d56dcb"
+"checksum ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6747f8da1f2b1fabbee1aaa4eb8a11abf9adef0bf58a41cee45db5d59cecdfac"
+"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
+"checksum rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b25a18b1bf7387f0145e7f8324e700805aade3842dd3db2e74e4cdeb4677c09e"
+"checksum schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "87f550b06b6cba9c8b8be3ee73f391990116bf527450d2556e9b9ce263b9a021"
+"checksum sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c"
+"checksum security-framework 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8ef2429d7cefe5fd28bd1d2ed41c944547d4ff84776f5935b456da44593a16df"
+"checksum security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e31493fc37615debb8c5090a7aeb4a9730bc61e77ab10b9af59f1a202284f895"
+"checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449"
+"checksum serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64"
+"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
+"checksum smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44e59e0c9fa00817912ae6e4e6e3c4fe04455e75699d06eedc7d85917ed8e8f4"
+"checksum socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e8b74de517221a2cb01a53349cf54182acdc31a074727d3079068448c0676d85"
+"checksum sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf77cb82ba8453b42b6ae1d692e4cdc92f9a47beaf89a847c8be83f4e328ad3"
+"checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
+"checksum syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1e4ff033220a41d1a57d8125eab57bf5263783dfdcc18688b1dacc6ce9651ef8"
+"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
+"checksum termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f"
+"checksum thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6f357d1814b33bc2dc221243f8424104bfe72dbe911d5b71b3816a2dff1c977e"
+"checksum thiserror-impl 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2e25d25307eb8436894f727aba8f65d07adf02e5b35a13cebed48bd282bfef"
+"checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
+"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
+"checksum tokio 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "ffa2fdcfa937b20cb3c822a635ceecd5fc1a27a6a474527e5516aa24b8c8820a"
+"checksum tokio-openssl 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c4b08c5f4208e699ede3df2520aca2e82401b2de33f45e96696a074480be594"
+"checksum tokio-rustls 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "141afec0978abae6573065a48882c6bae44c5cc61db9b511ac4abf6a09bfd9cc"
+"checksum tokio-tls 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7bde02a3a5291395f59b06ec6945a3077602fac2b07eeeaf0dee2122f3619828"
+"checksum tokio-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "571da51182ec208780505a32528fc5512a8fe1443ab960b3f2f3ef093cd16930"
+"checksum trust-dns-https 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)" = "029eb4b3ea49de60fa5b32eb3e7d90a58e8bd6f9d658f8e2f3cf4e687f640090"
+"checksum trust-dns-native-tls 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e3ef2072974a55f1102d67143f7bab795ca58fdaabab0b64b3d539ca58dd703c"
+"checksum trust-dns-openssl 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)" = "058122869d3b9d1ca50df687a304c6cd1b7bcf01fdb9e78ad601da4f57bc8beb"
+"checksum trust-dns-proto 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)" = "da8316d3a7fa285971a602e42ec6d31639cc3744e77694d89fea42152968063b"
+"checksum trust-dns-rustls 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dcaab11da895c0aba7427ca90b630540294baa6b004ee2b51961a888bf7ebc80"
+"checksum typed-headers 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3179a61e9eccceead5f1574fd173cf2e162ac42638b9bf214c6ad0baf7efa24a"
+"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
+"checksum unicode-normalization 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b561e267b2326bb4cebfc0ef9e68355c7abe6c6f522aeac2f5bf95d56c59bdcf"
+"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
+"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
+"checksum untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60369ef7a31de49bcb3f6ca728d4ba7300d9a1658f94c727d4cab8c8d9f4aece"
+"checksum url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb"
+"checksum vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168"
+"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
+"checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
+"checksum wasm-bindgen 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "5205e9afdf42282b192e2310a5b463a6d1c1d774e30dc3c791ac37ab42d2616c"
+"checksum wasm-bindgen-backend 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "11cdb95816290b525b32587d76419facd99662a07e59d3cdb560488a819d9a45"
+"checksum wasm-bindgen-macro 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "574094772ce6921576fb6f2e3f7497b8a76273b6db092be18fc48a082de09dc3"
+"checksum wasm-bindgen-macro-support 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "e85031354f25eaebe78bb7db1c3d86140312a911a106b2e29f9cc440ce3e7668"
+"checksum wasm-bindgen-shared 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "f5e7e61fc929f4c0dddb748b102ebf9f632e2b8d739f2016542b4de2965a9601"
+"checksum wasm-bindgen-webidl 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "ef012a0d93fc0432df126a8eaf547b2dce25a8ce9212e1d3cbeef5c11157975d"
+"checksum web-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)" = "aaf97caf6aa8c2b1dac90faf0db529d9d63c93846cca4911856f78a83cebf53b"
+"checksum webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d7e664e770ac0110e2384769bcc59ed19e329d81f555916a6e072714957b81b4"
+"checksum webpki-roots 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91cd5736df7f12a964a5067a12c62fa38e1bd8080aff1f80bc29be7c80d19ab4"
+"checksum weedle 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bb43f70885151e629e2a19ce9e50bd730fd436cfd4b666894c9ce4de9141164"
+"checksum widestring 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effc0e4ff8085673ea7b9b2e3c73f6bd4d118810c9009ed8f1e16bd96c331db6"
+"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
+"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
+"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
+"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+"checksum winapi-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4ccfbf554c6ad11084fb7517daca16cfdcaccbdadba4fc336f032a8b12c2ad80"
+"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+"checksum winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9"
+"checksum winutil 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7daf138b6b14196e3830a588acf1e86966c694d3e8fb026fb105b8b5dca07e6e"
+"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/Cargo.toml b/third_party/rust_crates/vendor/trust-dns-resolver/Cargo.toml
new file mode 100644
index 0000000..85b4923
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/Cargo.toml
@@ -0,0 +1,135 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+edition = "2018"
+name = "trust-dns-resolver"
+version = "0.19.2"
+authors = ["Benjamin Fry <benjaminfry@me.com>"]
+description = "Trust-DNS is a safe and secure DNS library. This Resolver library  uses the Client library to perform all DNS queries. The Resolver is intended to be a high-level library for any DNS record resolution see Resolver and AsyncResolver for supported resolution types. The Client can be used for other queries.\n"
+homepage = "http://www.trust-dns.org/index.html"
+documentation = "https://docs.rs/trust-dns-resolver"
+readme = "README.md"
+keywords = ["DNS", "BIND", "dig", "named", "dnssec"]
+categories = ["network-programming"]
+license = "MIT/Apache-2.0"
+repository = "https://github.com/bluejekyll/trust-dns"
+
+[lib]
+name = "trust_dns_resolver"
+path = "src/lib.rs"
+[dependencies.backtrace]
+version = "0.3.40"
+
+[dependencies.cfg-if]
+version = "0.1.9"
+
+[dependencies.futures]
+version = "0.3.0"
+
+[dependencies.lazy_static]
+version = "1.0"
+
+[dependencies.log]
+version = "0.4"
+
+[dependencies.lru-cache]
+version = "0.1.2"
+
+[dependencies.resolv-conf]
+version = "0.6.0"
+features = ["system"]
+optional = true
+
+[dependencies.rustls]
+version = "0.16"
+optional = true
+
+[dependencies.serde]
+version = "1.0"
+features = ["derive"]
+optional = true
+
+[dependencies.smallvec]
+version = "1.0"
+
+[dependencies.thiserror]
+version = "1.0.9"
+
+[dependencies.tokio]
+version = "0.2.1"
+optional = true
+
+[dependencies.tokio-openssl]
+version = "0.4.0"
+optional = true
+
+[dependencies.tokio-rustls]
+version = "0.12.1"
+optional = true
+
+[dependencies.tokio-tls]
+version = "0.3.0"
+optional = true
+
+[dependencies.trust-dns-https]
+version = "0.19.2"
+optional = true
+
+[dependencies.trust-dns-native-tls]
+version = "0.19.2"
+optional = true
+
+[dependencies.trust-dns-openssl]
+version = "0.19.2"
+optional = true
+
+[dependencies.trust-dns-proto]
+version = "0.19.2"
+default-features = false
+
+[dependencies.trust-dns-rustls]
+version = "0.19.2"
+optional = true
+
+[dependencies.webpki-roots]
+version = "0.18"
+optional = true
+[dev-dependencies.env_logger]
+version = "0.7"
+
+[features]
+default = ["system-config", "tokio-runtime"]
+dns-over-https = []
+dns-over-https-rustls = ["trust-dns-https", "dns-over-rustls", "dns-over-https"]
+dns-over-native-tls = ["dns-over-tls", "tokio-tls", "trust-dns-native-tls"]
+dns-over-openssl = ["dns-over-tls", "trust-dns-openssl", "tokio-openssl"]
+dns-over-rustls = ["dns-over-tls", "rustls", "tokio-rustls", "trust-dns-rustls", "webpki-roots"]
+dns-over-tls = []
+dnssec = []
+dnssec-openssl = ["dnssec", "trust-dns-proto/dnssec-openssl"]
+dnssec-ring = ["dnssec", "trust-dns-proto/dnssec-ring"]
+mdns = ["trust-dns-proto/mdns"]
+serde-config = ["serde", "trust-dns-proto/serde-config"]
+system-config = ["ipconfig", "resolv-conf"]
+testing = []
+tokio-runtime = ["tokio/rt-core", "trust-dns-proto/tokio-runtime"]
+[target."cfg(windows)".dependencies.ipconfig]
+version = "0.2.0"
+optional = true
+[badges.codecov]
+branch = "master"
+repository = "bluejekyll/trust-dns"
+service = "github"
+
+[badges.maintenance]
+status = "actively-developed"
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/LICENSE-APACHE b/third_party/rust_crates/vendor/trust-dns-resolver/LICENSE-APACHE
new file mode 100644
index 0000000..8f71f43
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/LICENSE-APACHE
@@ -0,0 +1,202 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "{}"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright {yyyy} {name of copyright owner}
+
+   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.
+
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/LICENSE-MIT b/third_party/rust_crates/vendor/trust-dns-resolver/LICENSE-MIT
new file mode 100644
index 0000000..b497b09
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/LICENSE-MIT
@@ -0,0 +1,20 @@
+Copyright (c) 2015 The trust-dns Developers
+Copyright (c) 2017 Google LLC.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/Makefile.toml b/third_party/rust_crates/vendor/trust-dns-resolver/Makefile.toml
new file mode 100644
index 0000000..b0504e5
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/Makefile.toml
@@ -0,0 +1,27 @@
+# This is a Makefile for `cargo make`, to use it first istall cargo-make with `cargo install cargo-make`
+
+[config]
+skip_core_tasks = true
+
+[config.modify_core_tasks]
+# if true, all core tasks are set to private (default false)
+private = true
+
+## Feature profiles
+[env]
+CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = "true"
+
+# TODO: add --lib back when there is a common cli library in util
+#  probably just remove this override file at that point
+
+[tasks.example-global_resolver]
+command = "cargo"
+args = ["run", "--example=global_resolver"]
+
+[tasks.example-multithreaded_runtime]
+command = "cargo"
+args = ["run", "--example=multithreaded_runtime"]
+
+# Also test that the examples run
+[tasks.test]
+dependencies = ["example-global_resolver", "example-multithreaded_runtime"]
\ No newline at end of file
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/README.md b/third_party/rust_crates/vendor/trust-dns-resolver/README.md
new file mode 100644
index 0000000..ec5db3c
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/README.md
@@ -0,0 +1,88 @@
+# Overview
+
+Trust-DNS Resolver is a library which implements the DNS resolver using the Trust-DNS Proto library.
+
+This library contains implementations for IPv4 (A) and IPv6 (AAAA) resolution, more features are in the works. It is built on top of the [tokio](https://tokio.rs) async-io project, this allows it to be integrated into other systems using the tokio and futures libraries. The Trust-DNS [project](https://github.com/bluejekyll/trust-dns) contains other libraries for DNS: a [client library](https://crates.io/crates/trust-dns-client) for raw protocol usage, a [server library](https://crates.io/crates/trust-dns-server) for hosting zones, and variations on the TLS implementation over [rustls](https://crates.io/crates/trust-dns-rustls) and [native-tls](https://crates.io/crates/trust-dns-native-tls).
+
+## Features
+
+- Various IPv4 and IPv6 lookup strategies
+- `/etc/resolv.conf` based configuration on Unix/Posix systems
+- NameServer pools with performance based priority usage
+- Caching of query results
+- NxDomain/NoData caching (negative caching)
+- DNSSec validation
+- Generic Record Type Lookup
+- CNAME chain resolution
+- *experimental* mDNS support (enable with `mdns` feature)
+- DNS over TLS (utilizing `native-tls`, `rustls`, and `openssl`; `native-tls` or `rustls` are recommended)
+- DNS over HTTPS (currently only supports `rustls`)
+
+## Example
+
+```rust
+use std::net::*;
+use trust_dns_resolver::Resolver;
+use trust_dns_resolver::config::*;
+
+// Construct a new Resolver with default configuration options
+let mut resolver = Resolver::new(ResolverConfig::default(), ResolverOpts::default()).unwrap();
+
+// On Unix/Posix systems, this will read the /etc/resolv.conf
+// let mut resolver = Resolver::from_system_conf().unwrap();
+
+// Lookup the IP addresses associated with a name.
+let mut response = resolver.lookup_ip("www.example.com.").unwrap();
+
+// There can be many addresses associated with the name,
+//  this can return IPv4 and/or IPv6 addresses
+let address = response.next().expect("no addresses returned!");
+if address.is_ipv4() {
+    assert_eq!(address, IpAddr::V4(Ipv4Addr::new(93, 184, 216, 34)));
+} else {
+    assert_eq!(address, IpAddr::V6(Ipv6Addr::new(0x2606, 0x2800, 0x220, 0x1, 0x248, 0x1893, 0x25c8, 0x1946)));
+}
+```
+
+## DNS-over-TLS and DNS-over-HTTPS
+
+DoT and DoH are supported. This is accomplished through the use of one of `native-tls`, `openssl`, or `rustls` (only `rustls` is currently supported for DoH). The Resolver requires only requires valid DoT or DoH resolvers being registered in order to be used.
+
+To use with the `Client`, the `TlsClientConnection` or `HttpsClientConnection` should be used. Similarly, to use with the tokio `AsyncClient` the `TlsClientStream` or `HttpsClientStream` should be used. ClientAuth, mTLS, is currently not supported, there are some issues still being worked on. TLS is useful for Server authentication and connection privacy.
+
+To enable DoT one of the features `dns-over-native-tls`, `dns-over-openssl`, or `dns-over-rustls` must be enabled, `dns-over-https-rustls` is used for DoH.
+
+### Example
+
+Enable the TLS library through the dependency on `trust-dns-resolver`:
+
+```toml
+trust-dns-resolver = { version = "*", features = ["dns-over-rustls"] }
+```
+
+A default TLS configuration is available for Cloudflare's `1.1.1.1` DNS service (Quad9 as well):
+
+```rust
+// Construct a new Resolver with default configuration options
+let mut resolver = Resolver::new(ResolverConfig::cloudflare_tls(), ResolverOpts::default()).unwrap();
+
+/// see example above...
+```
+
+## DNSSec status
+
+Currently the root key is hardcoded into the system. This gives validation of
+ DNSKEY and DS records back to the root. NSEC is implemented, but not NSEC3.
+ Because caching is not yet enabled, it has been noticed that some DNS servers
+ appear to rate limit the connections, validating RRSIG records back to the root
+ can require a significant number of additional queries for those records.
+
+Zones will be automatically resigned on any record updates via dynamic DNS. To enable DNSSEC, one of the features `dnssec-openssl` or `dnssec-rustls` must be enabled.
+
+## Minimum Rust Version
+
+The current minimum rustc version for this project is `1.39`
+
+## Versioning
+
+Trust-DNS does its best job to follow semver. Trust-DNS will be promoted to 1.0 upon stabilization of the publicly exposed APIs. This does not mean that Trust-DNS will necessarily break on upgrades between 0.x updates. Whenever possible, old APIs will be deprecated with notes on what replaced those deprecations. Trust-DNS will make a best effort to never break software which depends on it due to API changes, though this can not be guaranteed. Deprecated interfaces will be maintained for at minimum one major release after that in which they were deprecated (where possible), with the exception of the upgrade to 1.0 where all deprecated interfaces will be planned to be removed.
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/examples/global_resolver.rs b/third_party/rust_crates/vendor/trust-dns-resolver/examples/global_resolver.rs
new file mode 100644
index 0000000..9137908
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/examples/global_resolver.rs
@@ -0,0 +1,162 @@
+#![recursion_limit = "128"]
+
+#[macro_use]
+extern crate lazy_static;
+extern crate futures;
+#[cfg(feature = "tokio-runtime")]
+extern crate tokio;
+extern crate trust_dns_resolver;
+
+use std::fmt::Display;
+#[cfg(feature = "tokio-runtime")]
+use std::io;
+#[cfg(feature = "tokio-runtime")]
+use std::net::SocketAddr;
+use std::task::Poll;
+
+use futures::future;
+
+#[cfg(feature = "tokio-runtime")]
+use trust_dns_resolver::TokioAsyncResolver;
+#[cfg(feature = "tokio-runtime")]
+use trust_dns_resolver::{IntoName, TryParseIp};
+
+// This is an example of registering a static global resolver into any system.
+//
+// We may want to create a GlobalResolver as part of the Resolver library
+//   in the mean time, this example has the necessary steps to do so.
+//
+// Thank you to @zonyitoo for the original example.
+// TODO: this example can probably be made much simpler with the new
+//      `AsyncResolver`.
+#[cfg(feature = "tokio-runtime")]
+lazy_static! {
+    // First we need to setup the global Resolver
+    static ref GLOBAL_DNS_RESOLVER: TokioAsyncResolver = {
+        use std::sync::{Arc, Mutex, Condvar};
+        use std::thread;
+
+        // We'll be using this condvar to get the Resolver from the thread...
+        let pair = Arc::new((Mutex::new(None::<TokioAsyncResolver>), Condvar::new()));
+        let pair2 = pair.clone();
+
+
+        // Spawn the runtime to a new thread...
+        //
+        // This thread will manage the actual resolution runtime
+        thread::spawn(move || {
+            // A runtime for this new thread
+            let mut runtime = tokio::runtime::Runtime::new().expect("failed to launch Runtime");
+
+            // our platform independent future, result, see next blocks
+            let resolver = {
+
+                // To make this independent, if targeting macOS, BSD, Linux, or Windows, we can use the system's configuration:
+                #[cfg(any(unix, windows))]
+                {
+                    // use the system resolver configuration
+                    TokioAsyncResolver::from_system_conf(runtime.handle().clone())
+                }
+
+                // For other operating systems, we can use one of the preconfigured definitions
+                #[cfg(not(any(unix, windows)))]
+                {
+                    // Directly reference the config types
+                    use trust_dns_resolver::config::{ResolverConfig, ResolverOpts};
+
+                    // Get a new resolver with the google nameservers as the upstream recursive resolvers
+                    TokioAsyncResolver::new(ResolverConfig::google(), ResolverOpts::default(), runtime.handle().clone())
+                }
+            };
+
+            let &(ref lock, ref cvar) = &*pair2;
+            let mut started = lock.lock().unwrap();
+
+            let resolver = runtime.block_on(resolver).expect("failed to create trust-dns-resolver");
+
+            *started = Some(resolver);
+            cvar.notify_one();
+            drop(started);
+
+            runtime.block_on(future::poll_fn(|_cx| Poll::<()>::Pending))
+        });
+
+        // Wait for the thread to start up.
+        let &(ref lock, ref cvar) = &*pair;
+        let mut resolver = lock.lock().unwrap();
+        while resolver.is_none() {
+            resolver = cvar.wait(resolver).unwrap();
+        }
+
+        // take the started resolver
+        let resolver = std::mem::replace(&mut *resolver, None);
+
+        // set the global resolver
+        resolver.expect("resolver should not be none")
+    };
+}
+
+/// Provide a general purpose resolution function.
+///
+/// This looks up the `host` (a `&str` or `String` is good), and combines that with the provided port
+///   this mimics the lookup functions of `std::net`.
+#[cfg(feature = "tokio-runtime")]
+pub async fn resolve<N: IntoName + Display + TryParseIp + 'static>(
+    host: N,
+    port: u16,
+) -> io::Result<Vec<SocketAddr>> {
+    // Now we use the global resolver to perform a lookup_ip.
+    let name = host.to_string();
+    let result = GLOBAL_DNS_RESOLVER.lookup_ip(host).await;
+    // map the result into what we want...
+    result
+        .map_err(move |err| {
+            // we transform the error into a standard IO error for convenience
+            io::Error::new(
+                io::ErrorKind::AddrNotAvailable,
+                format!("dns resolution error for {}: {}", name, err),
+            )
+        })
+        .map(move |lookup_ip| {
+            // we take all the IPs returned, and then send back the set of IPs
+            lookup_ip
+                .iter()
+                .map(|ip| SocketAddr::new(ip, port))
+                .collect::<Vec<_>>()
+        })
+}
+
+#[cfg(feature = "tokio-runtime")]
+fn main() {
+    use std::thread;
+
+    // Let's resolve some names, we should be able to do it across threads
+    let names = &["www.google.com", "www.reddit.com", "www.wikipedia.org"];
+
+    // spawn all the threads to do the lookups
+    let threads = names
+        .iter()
+        .map(|name| {
+            let join = thread::spawn(move || {
+                let mut runtime = tokio::runtime::Runtime::new().expect("failed to launch Runtime");
+                runtime.block_on(resolve(*name, 443))
+            });
+
+            (name, join)
+        })
+        .collect::<Vec<_>>();
+
+    // print the resolved IPs
+    for (name, join) in threads {
+        let result = join
+            .join()
+            .expect("resolution thread failed")
+            .expect("resolution failed");
+        println!("{} resolved to {:?}", name, result);
+    }
+}
+
+#[cfg(not(feature = "tokio-runtime"))]
+fn main() {
+    println!("tokio-runtime feature must be enabled")
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/examples/multithreaded_runtime.rs b/third_party/rust_crates/vendor/trust-dns-resolver/examples/multithreaded_runtime.rs
new file mode 100644
index 0000000..3bb9310
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/examples/multithreaded_runtime.rs
@@ -0,0 +1,76 @@
+#![recursion_limit = "128"]
+
+//! This example shows how to create a resolver that uses the tokio multithreaded runtime. This is how
+//! you might integrate the resolver into a more complex application.
+
+extern crate env_logger;
+extern crate futures;
+#[cfg(feature = "tokio-runtime")]
+extern crate tokio;
+extern crate trust_dns_resolver;
+
+#[cfg(feature = "tokio-runtime")]
+fn main() {
+    use tokio::runtime::Runtime;
+    use trust_dns_resolver::TokioAsyncResolver;
+
+    env_logger::init();
+
+    // Set up the standard tokio runtime (multithreaded by default).
+    let mut runtime = Runtime::new().expect("Failed to create runtime");
+
+    let resolver = {
+        // To make this independent, if targeting macOS, BSD, Linux, or Windows, we can use the system's configuration:
+        #[cfg(any(unix, windows))]
+        {
+            // use the system resolver configuration
+            TokioAsyncResolver::from_system_conf(runtime.handle().clone())
+        }
+
+        // For other operating systems, we can use one of the preconfigured definitions
+        #[cfg(not(any(unix, windows)))]
+        {
+            // Directly reference the config types
+            use trust_dns_resolver::config::{ResolverConfig, ResolverOpts};
+
+            // Get a new resolver with the google nameservers as the upstream recursive resolvers
+            AsyncResolver::new(
+                ResolverConfig::google(),
+                ResolverOpts::default(),
+                runtime.handle().clone(),
+            )
+        }
+    };
+
+    // The resolver background task needs to be created in the runtime so it can
+    // connect to the reactor.
+    let resolver = runtime
+        .block_on(resolver)
+        .expect("failed to create resolver");
+
+    // Create some futures representing name lookups.
+    let names = &["www.google.com", "www.reddit.com", "www.wikipedia.org"];
+    let mut futures = names
+        .iter()
+        .map(|name| (name, resolver.lookup_ip(*name)))
+        .collect::<Vec<_>>();
+
+    // Go through the list of resolution operations and wait for them to complete.
+    for (name, lookup) in futures.drain(..) {
+        let ips = runtime
+            .block_on(lookup)
+            .expect("Failed completing lookup future")
+            .iter()
+            .collect::<Vec<_>>();
+        println!("{} resolved to {:?}", name, ips);
+    }
+
+    // Drop the resolver, which means that the runtime will become idle.
+    drop(futures);
+    drop(resolver);
+}
+
+#[cfg(not(feature = "tokio-runtime"))]
+fn main() {
+    println!("tokio-runtime feature must be enabled")
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/src/async_resolver.rs b/third_party/rust_crates/vendor/trust-dns-resolver/src/async_resolver.rs
new file mode 100644
index 0000000..3fc4198
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/src/async_resolver.rs
@@ -0,0 +1,1307 @@
+// Copyright 2015-2019 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! Structs for creating and using a AsyncResolver
+use std::fmt;
+use std::future::Future;
+use std::net::IpAddr;
+use std::sync::Arc;
+
+use futures::{self, future, lock::Mutex};
+use proto::error::ProtoResult;
+use proto::op::Query;
+use proto::rr::domain::TryParseIp;
+use proto::rr::{IntoName, Name, Record, RecordType};
+use proto::xfer::{DnsRequestOptions, RetryDnsHandle};
+use proto::DnsHandle;
+
+use crate::config::{ResolverConfig, ResolverOpts};
+use crate::dns_lru::{self, DnsLru};
+use crate::error::*;
+use crate::lookup::{self, Lookup, LookupEither, LookupFuture};
+use crate::lookup_ip::{LookupIp, LookupIpFuture};
+use crate::lookup_state::CachingClient;
+use crate::name_server::{
+    ConnectionProvider, GenericConnection, GenericConnectionProvider, NameServerPool,
+    RuntimeProvider,
+};
+#[cfg(feature = "tokio-runtime")]
+use crate::name_server::{TokioConnection, TokioConnectionProvider};
+use crate::Hosts;
+
+/// An asynchronous resolver for DNS generic over async Runtimes.
+///
+/// Creating a `AsyncResolver` returns a new handle and a future that should
+/// be spawned on an executor to drive the background work. The lookup methods
+/// on `AsyncResolver` request lookups from the background task.
+///
+/// The futures returned by a `AsyncResolver` and the corresponding background
+/// task need not be spawned on the same executor, or be in the same thread.
+///  Additionally, one background task may have any number of handles; calling
+/// `clone()` on a handle will create a new handle linked to the same
+/// background task.
+///
+/// *NOTE* If lookup futures returned by a `AsyncResolver` and the background
+/// future are spawned on two separate `CurrentThread` executors, one thread
+/// cannot run both executors simultaneously, so the `run` or `block_on`
+/// functions will cause the thread to deadlock. If both the background work
+/// and the lookup futures are intended to be run on the same thread, they
+/// should be spawned on the same executor.
+///
+/// The background task manages the name server pool and other state used
+/// to drive lookups. When this future is spawned on an executor, it will
+/// first construct and configure the necessary client state, before checking
+/// for any incoming lookup requests, handling them, and yielding. It will
+/// continue to do so as long as there are still any [`AsyncResolver`] handle
+/// linked to it. When all of its [`AsyncResolver`]s have been dropped, the
+/// background future will finish.
+#[derive(Clone)]
+pub struct AsyncResolver<C: DnsHandle, P: ConnectionProvider<Conn = C>> {
+    config: ResolverConfig,
+    options: ResolverOpts,
+    client_cache: CachingClient<LookupEither<C, P>>,
+    hosts: Option<Arc<Hosts>>,
+}
+
+/// An AsyncResolver used with Tokio
+#[cfg(feature = "tokio-runtime")]
+pub type TokioAsyncResolver = AsyncResolver<TokioConnection, TokioConnectionProvider>;
+
+macro_rules! lookup_fn {
+    ($p:ident, $l:ty, $r:path) => {
+/// Performs a lookup for the associated type.
+///
+/// *hint* queries that end with a '.' are fully qualified names and are cheaper lookups
+///
+/// # Arguments
+///
+/// * `query` - a string which parses to a domain name, failure to parse will return an error
+pub async fn $p<N: IntoName>(&self, query: N) -> Result<$l, ResolveError> {
+    let name = match query.into_name() {
+        Ok(name) => name,
+        Err(err) => {
+            return Err(err.into());
+        }
+    };
+
+    self.inner_lookup(name, $r, DnsRequestOptions::default()).await
+}
+    };
+    ($p:ident, $l:ty, $r:path, $t:ty) => {
+/// Performs a lookup for the associated type.
+///
+/// # Arguments
+///
+/// * `query` - a type which can be converted to `Name` via `From`.
+pub async fn $p(&self, query: $t) -> Result<$l, ResolveError> {
+    let name = Name::from(query);
+    self.inner_lookup(name, $r, DnsRequestOptions::default()).await
+}
+    };
+}
+
+#[cfg(feature = "tokio-runtime")]
+impl TokioAsyncResolver {
+    /// Construct a new Tokio based `AsyncResolver` with the provided configuration.
+    ///
+    /// # Arguments
+    ///
+    /// * `config` - configuration, name_servers, etc. for the Resolver
+    /// * `options` - basic lookup options for the resolver
+    ///
+    /// # Returns
+    ///
+    /// A tuple containing the new `AsyncResolver` and a future that drives the
+    /// background task that runs resolutions for the `AsyncResolver`. See the
+    /// documentation for `AsyncResolver` for more information on how to use
+    /// the background future.
+    pub async fn tokio(
+        config: ResolverConfig,
+        options: ResolverOpts,
+    ) -> Result<Self, ResolveError> {
+        use tokio::runtime::Handle;
+        Self::new(config, options, Handle::current()).await
+    }
+
+    /// Constructs a new Tokio based Resolver with the system configuration.
+    ///
+    /// This will use `/etc/resolv.conf` on Unix OSes and the registry on Windows.
+    #[cfg(any(unix, target_os = "windows"))]
+    #[cfg(feature = "system-config")]
+    pub async fn tokio_from_system_conf() -> Result<Self, ResolveError> {
+        use tokio::runtime::Handle;
+        Self::from_system_conf(Handle::current()).await
+    }
+}
+
+impl<R: RuntimeProvider> AsyncResolver<GenericConnection, GenericConnectionProvider<R>> {
+    /// Construct a new `AsyncResolver` with the provided configuration.
+    ///
+    /// # Arguments
+    ///
+    /// * `config` - configuration, name_servers, etc. for the Resolver
+    /// * `options` - basic lookup options for the resolver
+    ///
+    /// # Returns
+    ///
+    /// A tuple containing the new `AsyncResolver` and a future that drives the
+    /// background task that runs resolutions for the `AsyncResolver`. See the
+    /// documentation for `AsyncResolver` for more information on how to use
+    /// the background future.
+    pub async fn new(
+        config: ResolverConfig,
+        options: ResolverOpts,
+        runtime: R::Handle,
+    ) -> Result<Self, ResolveError> {
+        AsyncResolver::<GenericConnection, GenericConnectionProvider<R>>::new_with_conn(
+            config,
+            options,
+            GenericConnectionProvider::<R>::new(runtime),
+        )
+        .await
+    }
+
+    /// Constructs a new Resolver with the system configuration.
+    ///
+    /// This will use `/etc/resolv.conf` on Unix OSes and the registry on Windows.
+    #[cfg(any(unix, target_os = "windows"))]
+    #[cfg(feature = "system-config")]
+    pub async fn from_system_conf(runtime: R::Handle) -> Result<Self, ResolveError> {
+        Self::from_system_conf_with_provider(GenericConnectionProvider::<R>::new(runtime)).await
+    }
+}
+
+impl<C: DnsHandle, P: ConnectionProvider<Conn = C>> AsyncResolver<C, P> {
+    /// Construct a new `AsyncResolver` with the provided configuration.
+    ///
+    /// # Arguments
+    ///
+    /// * `config` - configuration, name_servers, etc. for the Resolver
+    /// * `options` - basic lookup options for the resolver
+    ///
+    /// # Returns
+    ///
+    /// A tuple containing the new `AsyncResolver` and a future that drives the
+    /// background task that runs resolutions for the `AsyncResolver`. See the
+    /// documentation for `AsyncResolver` for more information on how to use
+    /// the background future.
+    pub async fn new_with_conn(
+        config: ResolverConfig,
+        options: ResolverOpts,
+        conn_provider: P,
+    ) -> Result<Self, ResolveError> {
+        let lru = DnsLru::new(options.cache_size, dns_lru::TtlConfig::from_opts(&options));
+        let lru = Arc::new(Mutex::new(lru));
+
+        Self::with_cache_with_provider(config, options, lru, conn_provider).await
+    }
+
+    /// Construct a new `AsyncResolver` with the associated Client and configuration.
+    ///
+    /// # Arguments
+    ///
+    /// * `config` - configuration, name_servers, etc. for the Resolver
+    /// * `options` - basic lookup options for the resolver
+    /// * `lru` - the cache to be used with the resolver
+    ///
+    /// # Returns
+    ///
+    /// A new `AsyncResolver` that should be used for resolutions, or an error.
+    pub(crate) async fn with_cache_with_provider(
+        config: ResolverConfig,
+        options: ResolverOpts,
+        lru: Arc<Mutex<DnsLru>>,
+        conn_provider: P,
+    ) -> Result<Self, ResolveError> {
+        debug!("trust-dns resolver running");
+
+        let pool = NameServerPool::from_config_with_provider(&config, &options, conn_provider);
+        let either;
+        let client = RetryDnsHandle::new(pool, options.attempts);
+        if options.validate {
+            #[cfg(feature = "dnssec")]
+            {
+                use proto::xfer::DnssecDnsHandle;
+                either = LookupEither::Secure(DnssecDnsHandle::new(client));
+            }
+
+            #[cfg(not(feature = "dnssec"))]
+            {
+                // TODO: should this just be a panic, or a pinned error?
+                warn!("validate option is only available with 'dnssec' feature");
+                either = LookupEither::Retry(client);
+            }
+        } else {
+            either = LookupEither::Retry(client);
+        }
+
+        let hosts = if options.use_hosts_file {
+            Some(Arc::new(Hosts::new()))
+        } else {
+            None
+        };
+
+        trace!("handle passed back");
+        Ok(AsyncResolver {
+            config,
+            options,
+            client_cache: CachingClient::with_cache(lru, either),
+            hosts,
+        })
+    }
+
+    /// Constructs a new Resolver with the system configuration.
+    ///
+    /// This will use `/etc/resolv.conf` on Unix OSes and the registry on Windows.
+    #[cfg(any(unix, target_os = "windows"))]
+    #[cfg(feature = "system-config")]
+    pub async fn from_system_conf_with_provider(conn_provider: P) -> Result<Self, ResolveError> {
+        let (config, options) = super::system_conf::read_system_conf()?;
+        Self::new_with_conn(config, options, conn_provider).await
+    }
+
+    /// Generic lookup for any RecordType
+    ///
+    /// *WARNING* this interface may change in the future, see if one of the specializations would be better.
+    ///
+    /// # Arguments
+    ///
+    /// * `name` - name of the record to lookup, if name is not a valid domain name, an error will be returned
+    /// * `record_type` - type of record to lookup, all RecordData responses will be filtered to this type
+    ///
+    /// # Returns
+    ///
+    //  A future for the returned Lookup RData
+    pub fn lookup<N: IntoName>(
+        &self,
+        name: N,
+        record_type: RecordType,
+        options: DnsRequestOptions,
+    ) -> impl Future<Output = Result<Lookup, ResolveError>> + Send + Unpin + 'static {
+        let name = match name.into_name() {
+            Ok(name) => name,
+            Err(err) => return future::Either::Left(future::err(err.into())),
+        };
+
+        let names = self.build_names(name);
+        future::Either::Right(LookupFuture::lookup(
+            names,
+            record_type,
+            options,
+            self.client_cache.clone(),
+        ))
+    }
+
+    fn push_name(name: Name, names: &mut Vec<Name>) {
+        if !names.contains(&name) {
+            names.push(name);
+        }
+    }
+
+    fn build_names(&self, name: Name) -> Vec<Name> {
+        // if it's fully qualified, we can short circuit the lookup logic
+        if name.is_fqdn() {
+            vec![name]
+        } else {
+            // Otherwise we have to build the search list
+            // Note: the vec is built in reverse order of precedence, for stack semantics
+            let mut names =
+                Vec::<Name>::with_capacity(1 /*FQDN*/ + 1 /*DOMAIN*/ + self.config.search().len());
+
+            // if not meeting ndots, we always do the raw name in the final lookup, or it's a localhost...
+            let raw_name_first: bool =
+                name.num_labels() as usize > self.options.ndots || name.is_localhost();
+
+            // if not meeting ndots, we always do the raw name in the final lookup
+            if !raw_name_first {
+                names.push(name.clone());
+            }
+
+            for search in self.config.search().iter().rev() {
+                let name_search = name.clone().append_domain(search);
+                Self::push_name(name_search, &mut names);
+            }
+
+            if let Some(domain) = self.config.domain() {
+                let name_search = name.clone().append_domain(domain);
+                Self::push_name(name_search, &mut names);
+            }
+
+            // this is the direct name lookup
+            if raw_name_first {
+                // adding the name as though it's an FQDN for lookup
+                names.push(name);
+            }
+
+            names
+        }
+    }
+
+    pub(crate) async fn inner_lookup<L>(
+        &self,
+        name: Name,
+        record_type: RecordType,
+        options: DnsRequestOptions,
+    ) -> Result<L, ResolveError>
+    where
+        L: From<Lookup> + Send + 'static,
+    {
+        self.lookup(name, record_type, options).await.map(L::from)
+    }
+
+    /// Performs a dual-stack DNS lookup for the IP for the given hostname.
+    ///
+    /// See the configuration and options parameters for controlling the way in which A(Ipv4) and AAAA(Ipv6) lookups will be performed. For the least expensive query a fully-qualified-domain-name, FQDN, which ends in a final `.`, e.g. `www.example.com.`, will only issue one query. Anything else will always incur the cost of querying the `ResolverConfig::domain` and `ResolverConfig::search`.
+    ///
+    /// # Arguments
+    /// * `host` - string hostname, if this is an invalid hostname, an error will be returned.
+    pub async fn lookup_ip<N: IntoName + TryParseIp>(
+        &self,
+        host: N,
+    ) -> Result<LookupIp, ResolveError> {
+        let mut finally_ip_addr: Option<Record> = None;
+        let maybe_ip = host.try_parse_ip();
+        let maybe_name: ProtoResult<Name> = host.into_name();
+
+        // if host is a ip address, return directly.
+        if let Some(ip_addr) = maybe_ip {
+            let name = maybe_name.clone().unwrap_or_default();
+            let record = Record::from_rdata(name.clone(), dns_lru::MAX_TTL, ip_addr.clone());
+
+            // if ndots are greater than 4, then we can't assume the name is an IpAddr
+            //   this accepts IPv6 as well, b/c IPv6 can take the form: 2001:db8::198.51.100.35
+            //   but `:` is not a valid DNS character, so technically this will fail parsing.
+            //   TODO: should we always do search before returning this?
+            if self.options.ndots > 4 {
+                finally_ip_addr = Some(record);
+            } else {
+                let query = Query::query(name, ip_addr.to_record_type());
+                let lookup = Lookup::new_with_max_ttl(query, Arc::new(vec![record]));
+                return Ok(lookup.into());
+            }
+        }
+
+        let name = match (maybe_name, finally_ip_addr.as_ref()) {
+            (Ok(name), _) => name,
+            (Err(_), Some(ip_addr)) => {
+                // it was a valid IP, return that...
+                let query = Query::query(ip_addr.name().clone(), ip_addr.record_type());
+                let lookup = Lookup::new_with_max_ttl(query, Arc::new(vec![ip_addr.clone()]));
+                return Ok(lookup.into());
+            }
+            (Err(err), None) => {
+                return Err(err.into());
+            }
+        };
+
+        let names = self.build_names(name);
+        let hosts = self.hosts.as_ref().cloned();
+
+        LookupIpFuture::lookup(
+            names,
+            self.options.ip_strategy,
+            self.client_cache.clone(),
+            DnsRequestOptions::default(),
+            hosts,
+            finally_ip_addr.map(Record::unwrap_rdata),
+        )
+        .await
+    }
+
+    lookup_fn!(
+        reverse_lookup,
+        lookup::ReverseLookup,
+        RecordType::PTR,
+        IpAddr
+    );
+    lookup_fn!(ipv4_lookup, lookup::Ipv4Lookup, RecordType::A);
+    lookup_fn!(ipv6_lookup, lookup::Ipv6Lookup, RecordType::AAAA);
+    lookup_fn!(mx_lookup, lookup::MxLookup, RecordType::MX);
+    lookup_fn!(ns_lookup, lookup::NsLookup, RecordType::NS);
+    lookup_fn!(soa_lookup, lookup::SoaLookup, RecordType::SOA);
+    lookup_fn!(srv_lookup, lookup::SrvLookup, RecordType::SRV);
+    lookup_fn!(txt_lookup, lookup::TxtLookup, RecordType::TXT);
+}
+
+impl<C: DnsHandle, P: ConnectionProvider<Conn = C>> fmt::Debug for AsyncResolver<C, P> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("AsyncResolver")
+            .field("request_tx", &"...")
+            .finish()
+    }
+}
+
+/// Unit tests compatible with different runtime.
+#[cfg(any(test, feature = "testing"))]
+#[allow(dead_code)]
+pub mod testing {
+    use std::{marker::Unpin, net::*, str::FromStr};
+
+    use crate::config::{LookupIpStrategy, NameServerConfig, ResolverConfig, ResolverOpts};
+    use crate::name_server::{GenericConnection, GenericConnectionProvider, RuntimeProvider};
+    use crate::AsyncResolver;
+    use proto::{rr::Name, tcp::Connect, Executor};
+
+    /// Test IP lookup from URLs.
+    pub fn lookup_test<E: Executor, R: RuntimeProvider>(
+        config: ResolverConfig,
+        mut exec: E,
+        handle: R::Handle,
+    ) where
+        <<R as RuntimeProvider>::Tcp as Connect>::Transport: Unpin,
+    {
+        let resolver = AsyncResolver::<GenericConnection, GenericConnectionProvider<R>>::new(
+            config,
+            ResolverOpts::default(),
+            handle,
+        );
+        let resolver = exec.block_on(resolver).expect("failed to create resolver");
+
+        let response = exec
+            .block_on(resolver.lookup_ip("www.example.com."))
+            .expect("failed to run lookup");
+
+        assert_eq!(response.iter().count(), 1);
+        for address in response.iter() {
+            if address.is_ipv4() {
+                assert_eq!(address, IpAddr::V4(Ipv4Addr::new(93, 184, 216, 34)));
+            } else {
+                assert_eq!(
+                    address,
+                    IpAddr::V6(Ipv6Addr::new(
+                        0x2606, 0x2800, 0x220, 0x1, 0x248, 0x1893, 0x25c8, 0x1946,
+                    ))
+                );
+            }
+        }
+    }
+
+    /// Test IP lookup from IP literals.
+    pub fn ip_lookup_test<E: Executor, R: RuntimeProvider>(mut exec: E, handle: R::Handle)
+    where
+        <<R as RuntimeProvider>::Tcp as Connect>::Transport: Unpin,
+    {
+        let resolver = AsyncResolver::<GenericConnection, GenericConnectionProvider<R>>::new(
+            ResolverConfig::default(),
+            ResolverOpts::default(),
+            handle,
+        );
+        let resolver = exec.block_on(resolver).expect("failed to create resolver");
+
+        let response = exec
+            .block_on(resolver.lookup_ip("10.1.0.2"))
+            .expect("failed to run lookup");
+
+        assert_eq!(
+            Some(IpAddr::V4(Ipv4Addr::new(10, 1, 0, 2))),
+            response.iter().next()
+        );
+
+        let response = exec
+            .block_on(resolver.lookup_ip("2606:2800:220:1:248:1893:25c8:1946"))
+            .expect("failed to run lookup");
+
+        assert_eq!(
+            Some(IpAddr::V6(Ipv6Addr::new(
+                0x2606, 0x2800, 0x220, 0x1, 0x248, 0x1893, 0x25c8, 0x1946,
+            ))),
+            response.iter().next()
+        );
+    }
+
+    /// Test IP lookup from IP literals across threads.
+    pub fn ip_lookup_across_threads_test<E: Executor + Send + 'static, R: RuntimeProvider>(
+        mut exec: E,
+        handle: R::Handle,
+    ) where
+        <<R as RuntimeProvider>::Tcp as Connect>::Transport: Unpin,
+    {
+        // Test ensuring that running the background task on a separate
+        // executor in a separate thread from the futures returned by the
+        // AsyncResolver works correctly.
+        use std::thread;
+        let resolver = AsyncResolver::<GenericConnection, GenericConnectionProvider<R>>::new(
+            ResolverConfig::default(),
+            ResolverOpts::default(),
+            handle,
+        );
+        let resolver = exec.block_on(resolver).expect("failed to create resolver");
+
+        let resolver_one = resolver.clone();
+        let resolver_two = resolver;
+
+        let test_fn = |resolver: AsyncResolver<GenericConnection, GenericConnectionProvider<R>>| {
+            let mut exec = E::new();
+
+            let response = exec
+                .block_on(resolver.lookup_ip("10.1.0.2"))
+                .expect("failed to run lookup");
+
+            assert_eq!(
+                Some(IpAddr::V4(Ipv4Addr::new(10, 1, 0, 2))),
+                response.iter().next()
+            );
+
+            let response = exec
+                .block_on(resolver.lookup_ip("2606:2800:220:1:248:1893:25c8:1946"))
+                .expect("failed to run lookup");
+
+            assert_eq!(
+                Some(IpAddr::V6(Ipv6Addr::new(
+                    0x2606, 0x2800, 0x220, 0x1, 0x248, 0x1893, 0x25c8, 0x1946,
+                ))),
+                response.iter().next()
+            );
+        };
+
+        let thread_one = thread::spawn(move || {
+            test_fn(resolver_one);
+        });
+
+        let thread_two = thread::spawn(move || {
+            test_fn(resolver_two);
+        });
+
+        thread_one.join().expect("thread_one failed");
+        thread_two.join().expect("thread_two failed");
+    }
+
+    /// Test IP lookup from URLs with DNSSec validation.
+    pub fn sec_lookup_test<E: Executor + Send + 'static, R: RuntimeProvider>(
+        mut exec: E,
+        handle: R::Handle,
+    ) where
+        <<R as RuntimeProvider>::Tcp as Connect>::Transport: Unpin,
+    {
+        let resolver = AsyncResolver::<GenericConnection, GenericConnectionProvider<R>>::new(
+            ResolverConfig::default(),
+            ResolverOpts {
+                validate: true,
+                ..ResolverOpts::default()
+            },
+            handle,
+        );
+        let resolver = exec.block_on(resolver).expect("failed to create resolver");
+
+        let response = exec
+            .block_on(resolver.lookup_ip("www.example.com."))
+            .expect("failed to run lookup");
+
+        // TODO: this test is flaky, sometimes 1 is returned, sometimes 2...
+        assert_eq!(response.iter().count(), 1);
+        for address in response.iter() {
+            if address.is_ipv4() {
+                assert_eq!(address, IpAddr::V4(Ipv4Addr::new(93, 184, 216, 34)));
+            } else {
+                assert_eq!(
+                    address,
+                    IpAddr::V6(Ipv6Addr::new(
+                        0x2606, 0x2800, 0x220, 0x1, 0x248, 0x1893, 0x25c8, 0x1946,
+                    ))
+                );
+            }
+        }
+    }
+
+    /// Test IP lookup from domains that exist but unsigned with DNSSec validation.
+    #[allow(deprecated)]
+    pub fn sec_lookup_fails_test<E: Executor + Send + 'static, R: RuntimeProvider>(
+        mut exec: E,
+        handle: R::Handle,
+    ) where
+        <<R as RuntimeProvider>::Tcp as Connect>::Transport: Unpin,
+    {
+        use crate::error::*;
+        use proto::rr::RecordType;
+        let resolver = AsyncResolver::<GenericConnection, GenericConnectionProvider<R>>::new(
+            ResolverConfig::default(),
+            ResolverOpts {
+                validate: true,
+                ip_strategy: LookupIpStrategy::Ipv4Only,
+                ..ResolverOpts::default()
+            },
+            handle,
+        );
+        let resolver = exec.block_on(resolver).expect("failed to create resolver");
+
+        // needs to be a domain that exists, but is not signed (eventually this will be)
+        let name = Name::from_str("www.trust-dns.org.").unwrap();
+        let response = exec.block_on(resolver.lookup_ip("www.trust-dns.org."));
+
+        assert!(response.is_err());
+        let error = response.unwrap_err();
+
+        use proto::error::{ProtoError, ProtoErrorKind};
+
+        let error_str = format!("{}", error);
+        let expected_str = format!(
+            "{}",
+            ProtoError::from(ProtoErrorKind::RrsigsNotPresent {
+                name,
+                record_type: RecordType::A
+            })
+        );
+        assert_eq!(error_str, expected_str);
+        if let ResolveErrorKind::Proto(_) = *error.kind() {
+        } else {
+            panic!("wrong error")
+        }
+    }
+
+    #[cfg(feature = "system-config")]
+    /// Test AsyncResolver created from system configuration with IP lookup.
+    pub fn system_lookup_test<E: Executor + Send + 'static, R: RuntimeProvider>(
+        mut exec: E,
+        handle: R::Handle,
+    ) where
+        <<R as RuntimeProvider>::Tcp as Connect>::Transport: Unpin,
+    {
+        let resolver =
+            AsyncResolver::<GenericConnection, GenericConnectionProvider<R>>::from_system_conf(
+                handle,
+            );
+        let resolver = exec.block_on(resolver).expect("failed to create resolver");
+
+        let response = exec
+            .block_on(resolver.lookup_ip("www.example.com."))
+            .expect("failed to run lookup");
+
+        assert_eq!(response.iter().count(), 2);
+        for address in response.iter() {
+            if address.is_ipv4() {
+                assert_eq!(address, IpAddr::V4(Ipv4Addr::new(93, 184, 216, 34)));
+            } else {
+                assert_eq!(
+                    address,
+                    IpAddr::V6(Ipv6Addr::new(
+                        0x2606, 0x2800, 0x220, 0x1, 0x248, 0x1893, 0x25c8, 0x1946,
+                    ))
+                );
+            }
+        }
+    }
+
+    #[cfg(feature = "system-config")]
+    /// Test AsyncResolver created from system configuration with host lookups.
+    pub fn hosts_lookup_test<E: Executor + Send + 'static, R: RuntimeProvider>(
+        mut exec: E,
+        handle: R::Handle,
+    ) where
+        <<R as RuntimeProvider>::Tcp as Connect>::Transport: Unpin,
+    {
+        let resolver =
+            AsyncResolver::<GenericConnection, GenericConnectionProvider<R>>::from_system_conf(
+                handle,
+            );
+        let resolver = exec.block_on(resolver).expect("failed to create resolver");
+
+        let response = exec
+            .block_on(resolver.lookup_ip("a.com"))
+            .expect("failed to run lookup");
+
+        assert_eq!(response.iter().count(), 1);
+        for address in response.iter() {
+            if address.is_ipv4() {
+                assert_eq!(address, IpAddr::V4(Ipv4Addr::new(10, 1, 0, 104)));
+            } else {
+                panic!("failed to run lookup");
+            }
+        }
+    }
+
+    /// Test fqdn.
+    pub fn fqdn_test<E: Executor + Send + 'static, R: RuntimeProvider>(
+        mut exec: E,
+        handle: R::Handle,
+    ) where
+        <<R as RuntimeProvider>::Tcp as Connect>::Transport: Unpin,
+    {
+        let domain = Name::from_str("incorrect.example.com.").unwrap();
+        let search = vec![
+            Name::from_str("bad.example.com.").unwrap(),
+            Name::from_str("wrong.example.com.").unwrap(),
+        ];
+        let name_servers: Vec<NameServerConfig> =
+            ResolverConfig::default().name_servers().to_owned();
+
+        let resolver = AsyncResolver::<GenericConnection, GenericConnectionProvider<R>>::new(
+            ResolverConfig::from_parts(Some(domain), search, name_servers),
+            ResolverOpts {
+                ip_strategy: LookupIpStrategy::Ipv4Only,
+                ..ResolverOpts::default()
+            },
+            handle,
+        );
+        let resolver = exec.block_on(resolver).expect("failed to create resolver");
+
+        let response = exec
+            .block_on(resolver.lookup_ip("www.example.com."))
+            .expect("failed to run lookup");
+
+        assert_eq!(response.iter().count(), 1);
+        for address in response.iter() {
+            if address.is_ipv4() {
+                assert_eq!(address, IpAddr::V4(Ipv4Addr::new(93, 184, 216, 34)));
+            } else {
+                panic!("should only be looking up IPv4");
+            }
+        }
+    }
+
+    /// Test ndots with non-fqdn.
+    pub fn ndots_test<E: Executor + Send + 'static, R: RuntimeProvider>(
+        mut exec: E,
+        handle: R::Handle,
+    ) where
+        <<R as RuntimeProvider>::Tcp as Connect>::Transport: Unpin,
+    {
+        let domain = Name::from_str("incorrect.example.com.").unwrap();
+        let search = vec![
+            Name::from_str("bad.example.com.").unwrap(),
+            Name::from_str("wrong.example.com.").unwrap(),
+        ];
+        let name_servers: Vec<NameServerConfig> =
+            ResolverConfig::default().name_servers().to_owned();
+
+        let resolver = AsyncResolver::<GenericConnection, GenericConnectionProvider<R>>::new(
+            ResolverConfig::from_parts(Some(domain), search, name_servers),
+            ResolverOpts {
+                // our name does have 2, the default should be fine, let's just narrow the test criteria a bit.
+                ndots: 2,
+                ip_strategy: LookupIpStrategy::Ipv4Only,
+                ..ResolverOpts::default()
+            },
+            handle,
+        );
+        let resolver = exec.block_on(resolver).expect("failed to create resolver");
+
+        // notice this is not a FQDN, no trailing dot.
+        let response = exec
+            .block_on(resolver.lookup_ip("www.example.com"))
+            .expect("failed to run lookup");
+
+        assert_eq!(response.iter().count(), 1);
+        for address in response.iter() {
+            if address.is_ipv4() {
+                assert_eq!(address, IpAddr::V4(Ipv4Addr::new(93, 184, 216, 34)));
+            } else {
+                panic!("should only be looking up IPv4");
+            }
+        }
+    }
+
+    /// Test large ndots with non-fqdn.
+    pub fn large_ndots_test<E: Executor + Send + 'static, R: RuntimeProvider>(
+        mut exec: E,
+        handle: R::Handle,
+    ) where
+        <<R as RuntimeProvider>::Tcp as Connect>::Transport: Unpin,
+    {
+        let domain = Name::from_str("incorrect.example.com.").unwrap();
+        let search = vec![
+            Name::from_str("bad.example.com.").unwrap(),
+            Name::from_str("wrong.example.com.").unwrap(),
+        ];
+        let name_servers: Vec<NameServerConfig> =
+            ResolverConfig::default().name_servers().to_owned();
+
+        let resolver = AsyncResolver::<GenericConnection, GenericConnectionProvider<R>>::new(
+            ResolverConfig::from_parts(Some(domain), search, name_servers),
+            ResolverOpts {
+                // matches kubernetes default
+                ndots: 5,
+                ip_strategy: LookupIpStrategy::Ipv4Only,
+                ..ResolverOpts::default()
+            },
+            handle,
+        );
+        let resolver = exec.block_on(resolver).expect("failed to create resolver");
+
+        // notice this is not a FQDN, no trailing dot.
+        let response = exec
+            .block_on(resolver.lookup_ip("www.example.com"))
+            .expect("failed to run lookup");
+
+        assert_eq!(response.iter().count(), 1);
+        for address in response.iter() {
+            if address.is_ipv4() {
+                assert_eq!(address, IpAddr::V4(Ipv4Addr::new(93, 184, 216, 34)));
+            } else {
+                panic!("should only be looking up IPv4");
+            }
+        }
+    }
+
+    /// Test domain search.
+    pub fn domain_search_test<E: Executor + Send + 'static, R: RuntimeProvider>(
+        mut exec: E,
+        handle: R::Handle,
+    ) where
+        <<R as RuntimeProvider>::Tcp as Connect>::Transport: Unpin,
+    {
+        //env_logger::try_init().ok();
+
+        // domain is good now, should be combined with the name to form www.example.com
+        let domain = Name::from_str("example.com.").unwrap();
+        let search = vec![
+            Name::from_str("bad.example.com.").unwrap(),
+            Name::from_str("wrong.example.com.").unwrap(),
+        ];
+        let name_servers: Vec<NameServerConfig> =
+            ResolverConfig::default().name_servers().to_owned();
+
+        let resolver = AsyncResolver::<GenericConnection, GenericConnectionProvider<R>>::new(
+            ResolverConfig::from_parts(Some(domain), search, name_servers),
+            ResolverOpts {
+                ip_strategy: LookupIpStrategy::Ipv4Only,
+                ..ResolverOpts::default()
+            },
+            handle,
+        );
+        let resolver = exec.block_on(resolver).expect("failed to create resolver");
+
+        // notice no dots, should not trigger ndots rule
+        let response = exec
+            .block_on(resolver.lookup_ip("www"))
+            .expect("failed to run lookup");
+
+        assert_eq!(response.iter().count(), 1);
+        for address in response.iter() {
+            if address.is_ipv4() {
+                assert_eq!(address, IpAddr::V4(Ipv4Addr::new(93, 184, 216, 34)));
+            } else {
+                panic!("should only be looking up IPv4");
+            }
+        }
+    }
+
+    /// Test search lists.
+    pub fn search_list_test<E: Executor + Send + 'static, R: RuntimeProvider>(
+        mut exec: E,
+        handle: R::Handle,
+    ) where
+        <<R as RuntimeProvider>::Tcp as Connect>::Transport: Unpin,
+    {
+        let domain = Name::from_str("incorrect.example.com.").unwrap();
+        let search = vec![
+            // let's skip one search domain to test the loop...
+            Name::from_str("bad.example.com.").unwrap(),
+            // this should combine with the search name to form www.example.com
+            Name::from_str("example.com.").unwrap(),
+        ];
+        let name_servers: Vec<NameServerConfig> =
+            ResolverConfig::default().name_servers().to_owned();
+
+        let resolver = AsyncResolver::<GenericConnection, GenericConnectionProvider<R>>::new(
+            ResolverConfig::from_parts(Some(domain), search, name_servers),
+            ResolverOpts {
+                ip_strategy: LookupIpStrategy::Ipv4Only,
+                ..ResolverOpts::default()
+            },
+            handle,
+        );
+        let resolver = exec.block_on(resolver).expect("failed to create resolver");
+
+        // notice no dots, should not trigger ndots rule
+        let response = exec
+            .block_on(resolver.lookup_ip("www"))
+            .expect("failed to run lookup");
+
+        assert_eq!(response.iter().count(), 1);
+        for address in response.iter() {
+            if address.is_ipv4() {
+                assert_eq!(address, IpAddr::V4(Ipv4Addr::new(93, 184, 216, 34)));
+            } else {
+                panic!("should only be looking up IPv4");
+            }
+        }
+    }
+
+    /// Test idna.
+    pub fn idna_test<E: Executor + Send + 'static, R: RuntimeProvider>(
+        mut exec: E,
+        handle: R::Handle,
+    ) where
+        <<R as RuntimeProvider>::Tcp as Connect>::Transport: Unpin,
+    {
+        let resolver = AsyncResolver::<GenericConnection, GenericConnectionProvider<R>>::new(
+            ResolverConfig::default(),
+            ResolverOpts::default(),
+            handle,
+        );
+        let resolver = exec.block_on(resolver).expect("failed to create resolver");
+
+        let response = exec
+            .block_on(resolver.lookup_ip("中国.icom.museum."))
+            .expect("failed to run lookup");
+
+        // we just care that the request succeeded, not about the actual content
+        //   it's not certain that the ip won't change.
+        assert!(response.iter().next().is_some());
+    }
+
+    /// Test ipv4 localhost.
+    pub fn localhost_ipv4_test<E: Executor + Send + 'static, R: RuntimeProvider>(
+        mut exec: E,
+        handle: R::Handle,
+    ) where
+        <<R as RuntimeProvider>::Tcp as Connect>::Transport: Unpin,
+    {
+        let resolver = AsyncResolver::<GenericConnection, GenericConnectionProvider<R>>::new(
+            ResolverConfig::default(),
+            ResolverOpts {
+                ip_strategy: LookupIpStrategy::Ipv4thenIpv6,
+                ..ResolverOpts::default()
+            },
+            handle,
+        );
+        let resolver = exec.block_on(resolver).expect("failed to create resolver");
+
+        let response = exec
+            .block_on(resolver.lookup_ip("localhost"))
+            .expect("failed to run lookup");
+
+        let mut iter = response.iter();
+        assert_eq!(
+            iter.next().expect("no A"),
+            IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))
+        );
+    }
+
+    /// Test ipv6 localhost.
+    pub fn localhost_ipv6_test<E: Executor + Send + 'static, R: RuntimeProvider>(
+        mut exec: E,
+        handle: R::Handle,
+    ) where
+        <<R as RuntimeProvider>::Tcp as Connect>::Transport: Unpin,
+    {
+        let resolver = AsyncResolver::<GenericConnection, GenericConnectionProvider<R>>::new(
+            ResolverConfig::default(),
+            ResolverOpts {
+                ip_strategy: LookupIpStrategy::Ipv6thenIpv4,
+                ..ResolverOpts::default()
+            },
+            handle,
+        );
+        let resolver = exec.block_on(resolver).expect("failed to create resolver");
+
+        let response = exec
+            .block_on(resolver.lookup_ip("localhost"))
+            .expect("failed to run lookup");
+
+        let mut iter = response.iter();
+        assert_eq!(
+            iter.next().expect("no AAAA"),
+            IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1,))
+        );
+    }
+
+    /// Test ipv4 search with large ndots.
+    pub fn search_ipv4_large_ndots_test<E: Executor + Send + 'static, R: RuntimeProvider>(
+        mut exec: E,
+        handle: R::Handle,
+    ) where
+        <<R as RuntimeProvider>::Tcp as Connect>::Transport: Unpin,
+    {
+        let mut config = ResolverConfig::default();
+        config.add_search(Name::from_str("example.com").unwrap());
+
+        let resolver = AsyncResolver::<GenericConnection, GenericConnectionProvider<R>>::new(
+            config,
+            ResolverOpts {
+                ip_strategy: LookupIpStrategy::Ipv4Only,
+                ndots: 5,
+                ..ResolverOpts::default()
+            },
+            handle,
+        );
+        let resolver = exec.block_on(resolver).expect("failed to create resolver");
+
+        let response = exec
+            .block_on(resolver.lookup_ip("198.51.100.35"))
+            .expect("failed to run lookup");
+
+        let mut iter = response.iter();
+        assert_eq!(
+            iter.next().expect("no rdatas"),
+            IpAddr::V4(Ipv4Addr::new(198, 51, 100, 35))
+        );
+    }
+
+    /// Test ipv6 search with large ndots.
+    pub fn search_ipv6_large_ndots_test<E: Executor + Send + 'static, R: RuntimeProvider>(
+        mut exec: E,
+        handle: R::Handle,
+    ) where
+        <<R as RuntimeProvider>::Tcp as Connect>::Transport: Unpin,
+    {
+        let mut config = ResolverConfig::default();
+        config.add_search(Name::from_str("example.com").unwrap());
+
+        let resolver = AsyncResolver::<GenericConnection, GenericConnectionProvider<R>>::new(
+            config,
+            ResolverOpts {
+                ip_strategy: LookupIpStrategy::Ipv4Only,
+                ndots: 5,
+                ..ResolverOpts::default()
+            },
+            handle,
+        );
+        let resolver = exec.block_on(resolver).expect("failed to create resolver");
+
+        let response = exec
+            .block_on(resolver.lookup_ip("2001:db8::c633:6423"))
+            .expect("failed to run lookup");
+
+        let mut iter = response.iter();
+        assert_eq!(
+            iter.next().expect("no rdatas"),
+            IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0xc633, 0x6423))
+        );
+    }
+
+    /// Test ipv6 name parse fails.
+    pub fn search_ipv6_name_parse_fails_test<E: Executor + Send + 'static, R: RuntimeProvider>(
+        mut exec: E,
+        handle: R::Handle,
+    ) where
+        <<R as RuntimeProvider>::Tcp as Connect>::Transport: Unpin,
+    {
+        let mut config = ResolverConfig::default();
+        config.add_search(Name::from_str("example.com").unwrap());
+
+        let resolver = AsyncResolver::<GenericConnection, GenericConnectionProvider<R>>::new(
+            config,
+            ResolverOpts {
+                ip_strategy: LookupIpStrategy::Ipv4Only,
+                ndots: 5,
+                ..ResolverOpts::default()
+            },
+            handle,
+        );
+        let resolver = exec.block_on(resolver).expect("failed to create resolver");
+
+        let response = exec
+            .block_on(resolver.lookup_ip("2001:db8::198.51.100.35"))
+            .expect("failed to run lookup");
+
+        let mut iter = response.iter();
+        assert_eq!(
+            iter.next().expect("no rdatas"),
+            IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0xc633, 0x6423))
+        );
+    }
+}
+#[cfg(test)]
+#[cfg(feature = "tokio-runtime")]
+mod tests {
+    extern crate env_logger;
+    extern crate tokio;
+
+    use proto::xfer::DnsRequest;
+
+    use self::tokio::runtime::Runtime;
+    use crate::config::{ResolverConfig, ResolverOpts};
+    use crate::name_server::{TokioConnection, TokioConnectionProvider, TokioRuntime};
+
+    use super::*;
+
+    fn is_send_t<T: Send>() -> bool {
+        true
+    }
+
+    fn is_sync_t<T: Sync>() -> bool {
+        true
+    }
+
+    #[test]
+    fn test_send_sync() {
+        assert!(is_send_t::<ResolverConfig>());
+        assert!(is_sync_t::<ResolverConfig>());
+        assert!(is_send_t::<ResolverOpts>());
+        assert!(is_sync_t::<ResolverOpts>());
+
+        assert!(is_send_t::<
+            AsyncResolver<TokioConnection, TokioConnectionProvider>,
+        >());
+        assert!(is_sync_t::<
+            AsyncResolver<TokioConnection, TokioConnectionProvider>,
+        >());
+
+        assert!(is_send_t::<DnsRequest>());
+        assert!(is_send_t::<LookupIpFuture<TokioConnection>>());
+        assert!(is_send_t::<LookupFuture<TokioConnection>>());
+    }
+
+    #[test]
+    fn test_lookup_google() {
+        use super::testing::lookup_test;
+        let io_loop = Runtime::new().expect("failed to create tokio runtime");
+        let handle = io_loop.handle().clone();
+        lookup_test::<Runtime, TokioRuntime>(ResolverConfig::google(), io_loop, handle)
+    }
+
+    #[test]
+    fn test_lookup_cloudflare() {
+        use super::testing::lookup_test;
+        let io_loop = Runtime::new().expect("failed to create tokio runtime");
+        let handle = io_loop.handle().clone();
+        lookup_test::<Runtime, TokioRuntime>(ResolverConfig::cloudflare(), io_loop, handle)
+    }
+
+    #[test]
+    fn test_lookup_quad9() {
+        use super::testing::lookup_test;
+        let io_loop = Runtime::new().expect("failed to create tokio runtime");
+        let handle = io_loop.handle().clone();
+        lookup_test::<Runtime, TokioRuntime>(ResolverConfig::quad9(), io_loop, handle)
+    }
+
+    #[test]
+    fn test_ip_lookup() {
+        use super::testing::ip_lookup_test;
+        let io_loop = Runtime::new().expect("failed to create tokio runtime");
+        let handle = io_loop.handle().clone();
+        ip_lookup_test::<Runtime, TokioRuntime>(io_loop, handle)
+    }
+
+    #[test]
+    fn test_ip_lookup_across_threads() {
+        use super::testing::ip_lookup_across_threads_test;
+        let io_loop = Runtime::new().expect("failed to create tokio runtime io_loop");
+        let handle = io_loop.handle().clone();
+        ip_lookup_across_threads_test::<Runtime, TokioRuntime>(io_loop, handle)
+    }
+
+    #[test]
+    #[ignore] // these appear to not work on CI
+    fn test_sec_lookup() {
+        use super::testing::sec_lookup_test;
+        let io_loop = Runtime::new().expect("failed to create tokio runtime io_loop");
+        let handle = io_loop.handle().clone();
+        sec_lookup_test::<Runtime, TokioRuntime>(io_loop, handle);
+    }
+
+    #[test]
+    #[ignore] // these appear to not work on CI
+    fn test_sec_lookup_fails() {
+        use super::testing::sec_lookup_fails_test;
+        let io_loop = Runtime::new().expect("failed to create tokio runtime io_loop");
+        let handle = io_loop.handle().clone();
+        sec_lookup_fails_test::<Runtime, TokioRuntime>(io_loop, handle);
+    }
+
+    #[test]
+    #[ignore]
+    #[cfg(any(unix, target_os = "windows"))]
+    #[cfg(feature = "system-config")]
+    fn test_system_lookup() {
+        use super::testing::system_lookup_test;
+        let io_loop = Runtime::new().expect("failed to create tokio runtime io_loop");
+        let handle = io_loop.handle().clone();
+        system_lookup_test::<Runtime, TokioRuntime>(io_loop, handle);
+    }
+
+    #[test]
+    #[ignore]
+    // these appear to not work on CI, test on macos with `10.1.0.104  a.com`
+    #[cfg(unix)]
+    fn test_hosts_lookup() {
+        use super::testing::hosts_lookup_test;
+        let io_loop = Runtime::new().expect("failed to create tokio runtime io_loop");
+        let handle = io_loop.handle().clone();
+        hosts_lookup_test::<Runtime, TokioRuntime>(io_loop, handle);
+    }
+
+    #[test]
+    fn test_fqdn() {
+        use super::testing::fqdn_test;
+        let io_loop = Runtime::new().expect("failed to create tokio runtime io_loop");
+        let handle = io_loop.handle().clone();
+        fqdn_test::<Runtime, TokioRuntime>(io_loop, handle);
+    }
+
+    #[test]
+    fn test_ndots() {
+        use super::testing::ndots_test;
+        let io_loop = Runtime::new().expect("failed to create tokio runtime io_loop");
+        let handle = io_loop.handle().clone();
+        ndots_test::<Runtime, TokioRuntime>(io_loop, handle);
+    }
+
+    #[test]
+    fn test_large_ndots() {
+        use super::testing::large_ndots_test;
+        let io_loop = Runtime::new().expect("failed to create tokio runtime io_loop");
+        let handle = io_loop.handle().clone();
+        large_ndots_test::<Runtime, TokioRuntime>(io_loop, handle);
+    }
+
+    #[test]
+    fn test_domain_search() {
+        use super::testing::domain_search_test;
+        let io_loop = Runtime::new().expect("failed to create tokio runtime io_loop");
+        let handle = io_loop.handle().clone();
+        domain_search_test::<Runtime, TokioRuntime>(io_loop, handle);
+    }
+
+    #[test]
+    fn test_search_list() {
+        use super::testing::search_list_test;
+        let io_loop = Runtime::new().expect("failed to create tokio runtime io_loop");
+        let handle = io_loop.handle().clone();
+        search_list_test::<Runtime, TokioRuntime>(io_loop, handle);
+    }
+
+    #[test]
+    fn test_idna() {
+        use super::testing::idna_test;
+        let io_loop = Runtime::new().expect("failed to create tokio runtime io_loop");
+        let handle = io_loop.handle().clone();
+        idna_test::<Runtime, TokioRuntime>(io_loop, handle);
+    }
+
+    #[test]
+    fn test_localhost_ipv4() {
+        use super::testing::localhost_ipv4_test;
+        let io_loop = Runtime::new().expect("failed to create tokio runtime io_loop");
+        let handle = io_loop.handle().clone();
+        localhost_ipv4_test::<Runtime, TokioRuntime>(io_loop, handle);
+    }
+
+    #[test]
+    fn test_localhost_ipv6() {
+        use super::testing::localhost_ipv6_test;
+        let io_loop = Runtime::new().expect("failed to create tokio runtime io_loop");
+        let handle = io_loop.handle().clone();
+        localhost_ipv6_test::<Runtime, TokioRuntime>(io_loop, handle);
+    }
+
+    #[test]
+    fn test_search_ipv4_large_ndots() {
+        use super::testing::search_ipv4_large_ndots_test;
+        let io_loop = Runtime::new().expect("failed to create tokio runtime io_loop");
+        let handle = io_loop.handle().clone();
+        search_ipv4_large_ndots_test::<Runtime, TokioRuntime>(io_loop, handle);
+    }
+
+    #[test]
+    fn test_search_ipv6_large_ndots() {
+        use super::testing::search_ipv6_large_ndots_test;
+        let io_loop = Runtime::new().expect("failed to create tokio runtime io_loop");
+        let handle = io_loop.handle().clone();
+        search_ipv6_large_ndots_test::<Runtime, TokioRuntime>(io_loop, handle);
+    }
+
+    #[test]
+    fn test_search_ipv6_name_parse_fails() {
+        use super::testing::search_ipv6_name_parse_fails_test;
+        let io_loop = Runtime::new().expect("failed to create tokio runtime io_loop");
+        let handle = io_loop.handle().clone();
+        search_ipv6_name_parse_fails_test::<Runtime, TokioRuntime>(io_loop, handle);
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/src/config.rs b/third_party/rust_crates/vendor/trust-dns-resolver/src/config.rs
new file mode 100644
index 0000000..4600422
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/src/config.rs
@@ -0,0 +1,717 @@
+// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! Configuration for a resolver
+#[cfg(feature = "dns-over-rustls")]
+use std::fmt;
+use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
+use std::ops::{Deref, DerefMut};
+use std::time::Duration;
+
+#[cfg(feature = "dns-over-rustls")]
+use std::sync::Arc;
+
+use proto::rr::Name;
+#[cfg(feature = "dns-over-rustls")]
+use rustls::ClientConfig;
+
+#[cfg(all(feature = "serde-config", feature = "dns-over-rustls"))]
+use serde::{
+    de::{Deserialize as DeserializeT, Deserializer},
+    ser::{Serialize as SerializeT, Serializer},
+};
+
+/// Configuration for the upstream nameservers to use for resolution
+#[derive(Clone, Debug, PartialEq, Eq)]
+#[cfg_attr(feature = "serde-config", derive(Serialize, Deserialize))]
+pub struct ResolverConfig {
+    // base search domain
+    domain: Option<Name>,
+    // search domains
+    search: Vec<Name>,
+    // nameservers to use for resolution.
+    name_servers: NameServerConfigGroup,
+}
+
+impl ResolverConfig {
+    /// Creates a new empty configuration
+    pub fn new() -> Self {
+        ResolverConfig {
+            // TODO: this should get the hostname and use the basename as the default
+            domain: None,
+            search: vec![],
+            name_servers: NameServerConfigGroup::new(),
+        }
+    }
+
+    /// Creates a default configuration, using `8.8.8.8`, `8.8.4.4` and `2001:4860:4860::8888`, `2001:4860:4860::8844` (thank you, Google).
+    ///
+    /// Please see Google's [privacy statement](https://developers.google.com/speed/public-dns/privacy) for important information about what they track, many ISP's track similar information in DNS. To use the system configuration see: `Resolver::from_system_conf` and `AsyncResolver::from_system_conf`
+    ///
+    /// NameServerConfigGroups can be combined to use a set of different providers, see `NameServerConfigGroup` and `ResolverConfig::from_parts`
+    pub fn google() -> Self {
+        ResolverConfig {
+            // TODO: this should get the hostname and use the basename as the default
+            domain: None,
+            search: vec![],
+            name_servers: NameServerConfigGroup::google(),
+        }
+    }
+
+    /// Creates a default configuration, using `1.1.1.1`, `1.0.0.1` and `2606:4700:4700::1111`, `2606:4700:4700::1001` (thank you, Cloudflare).
+    ///
+    /// Please see: https://www.cloudflare.com/dns/
+    ///
+    /// NameServerConfigGroups can be combined to use a set of different providers, see `NameServerConfigGroup` and `ResolverConfig::from_parts`
+    pub fn cloudflare() -> Self {
+        ResolverConfig {
+            // TODO: this should get the hostname and use the basename as the default
+            domain: None,
+            search: vec![],
+            name_servers: NameServerConfigGroup::cloudflare(),
+        }
+    }
+
+    /// Creates a configuration, using `1.1.1.1`, `1.0.0.1` and `2606:4700:4700::1111`, `2606:4700:4700::1001` (thank you, Cloudflare). This limits the registered connections to just TLS lookups
+    ///
+    /// Please see: https://www.cloudflare.com/dns/
+    ///
+    /// NameServerConfigGroups can be combined to use a set of different providers, see `NameServerConfigGroup` and `ResolverConfig::from_parts`
+    #[cfg(feature = "dns-over-tls")]
+    pub fn cloudflare_tls() -> Self {
+        ResolverConfig {
+            // TODO: this should get the hostname and use the basename as the default
+            domain: None,
+            search: vec![],
+            name_servers: NameServerConfigGroup::cloudflare_tls(),
+        }
+    }
+
+    /// Creates a configuration, using `1.1.1.1`, `1.0.0.1` and `2606:4700:4700::1111`, `2606:4700:4700::1001` (thank you, Cloudflare). This limits the registered connections to just HTTPS lookups
+    ///
+    /// Please see: https://www.cloudflare.com/dns/
+    ///
+    /// NameServerConfigGroups can be combined to use a set of different providers, see `NameServerConfigGroup` and `ResolverConfig::from_parts`
+    #[cfg(feature = "dns-over-https")]
+    pub fn cloudflare_https() -> Self {
+        ResolverConfig {
+            // TODO: this should get the hostname and use the basename as the default
+            domain: None,
+            search: vec![],
+            name_servers: NameServerConfigGroup::cloudflare_https(),
+        }
+    }
+
+    /// Creates a configuration, using `9.9.9.9` and `2620:fe::fe`, the "secure" variants of the quad9 settings (thank you, Quad9).
+    ///
+    /// Please see: https://www.quad9.net/faq/
+    ///
+    /// NameServerConfigGroups can be combined to use a set of different providers, see `NameServerConfigGroup` and `ResolverConfig::from_parts`
+    pub fn quad9() -> Self {
+        ResolverConfig {
+            // TODO: this should get the hostname and use the basename as the default
+            domain: None,
+            search: vec![],
+            name_servers: NameServerConfigGroup::quad9(),
+        }
+    }
+
+    /// Creates a configuration, using `9.9.9.9` and `2620:fe::fe`, the "secure" variants of the quad9 settings. This limits the registered connections to just TLS lookups
+    ///
+    /// Please see: https://www.quad9.net/faq/
+    ///
+    /// NameServerConfigGroups can be combined to use a set of different providers, see `NameServerConfigGroup` and `ResolverConfig::from_parts`
+    #[cfg(feature = "dns-over-tls")]
+    pub fn quad9_tls() -> Self {
+        ResolverConfig {
+            // TODO: this should get the hostname and use the basename as the default
+            domain: None,
+            search: vec![],
+            name_servers: NameServerConfigGroup::quad9_tls(),
+        }
+    }
+
+    /// Create a ResolverConfig with all parts specified
+    ///
+    /// # Arguments
+    ///
+    /// * `domain` - domain of the entity querying results. If the `Name` being looked up is not an FQDN, then this is the first part appended to attempt a lookup. `ndots` in the `ResolverOption` does take precedence over this.
+    /// * `search` - additional search domains that are attempted if the `Name` is not found in `domain`, defaults to `vec![]`
+    /// * `name_servers` - set of name servers to use for lookups, defaults are Google: `8.8.8.8`, `8.8.4.4` and `2001:4860:4860::8888`, `2001:4860:4860::8844`
+    pub fn from_parts<G: Into<NameServerConfigGroup>>(
+        domain: Option<Name>,
+        search: Vec<Name>,
+        name_servers: G,
+    ) -> Self {
+        ResolverConfig {
+            domain,
+            search,
+            name_servers: name_servers.into(),
+        }
+    }
+
+    /// Returns the local domain
+    ///
+    /// By default any names will be appended to all non-fully-qualified-domain names, and searched for after any ndots rules
+    pub fn domain(&self) -> Option<&Name> {
+        self.domain.as_ref()
+    }
+
+    /// Set the domain of the entity querying results.
+    pub fn set_domain(&mut self, domain: Name) {
+        self.domain = Some(domain.clone());
+        self.search = vec![domain];
+    }
+
+    /// Returns the search domains
+    ///
+    /// These will be queried after any local domain and then in the order of the set of search domains
+    pub fn search(&self) -> &[Name] {
+        &self.search
+    }
+
+    /// Add a search domain
+    pub fn add_search(&mut self, search: Name) {
+        self.search.push(search)
+    }
+
+    // TODO: consider allowing options per NameServer... like different timeouts?
+    /// Add the configuration for a name server
+    pub fn add_name_server(&mut self, name_server: NameServerConfig) {
+        self.name_servers.push(name_server);
+    }
+
+    /// Returns a reference to the name servers
+    pub fn name_servers(&self) -> &[NameServerConfig] {
+        &self.name_servers
+    }
+
+    /// return the associated TlsClientConfig
+    #[cfg(feature = "dns-over-rustls")]
+    pub fn client_config(&self) -> &Option<TlsClientConfig> {
+        &self.name_servers.1
+    }
+
+    /// adds the [`rustls::ClientConf`] for every configured NameServer
+    /// of the Resolver.
+    ///
+    /// ```
+    /// use std::sync::Arc;
+    ///
+    /// use rustls::{ClientConfig, ProtocolVersion, RootCertStore};
+    /// use trust_dns_resolver::config::ResolverConfig;
+    /// use webpki_roots;
+    ///
+    /// let mut root_store = RootCertStore::empty();
+    /// root_store.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
+    /// let versions = vec![ProtocolVersion::TLSv1_2];
+    ///
+    /// let mut client_config = ClientConfig::new();
+    /// client_config.root_store = root_store;
+    /// client_config.versions = versions;
+    ///
+    /// let mut resolver_config = ResolverConfig::quad9_tls();
+    /// resolver_config.set_tls_client_config(Arc::new(client_config));
+    /// ```
+    #[cfg(feature = "dns-over-rustls")]
+    pub fn set_tls_client_config(&mut self, client_config: Arc<ClientConfig>) {
+        self.name_servers = self.name_servers.clone().with_client_config(client_config);
+    }
+}
+
+impl Default for ResolverConfig {
+    /// Creates a default configuration, using `8.8.8.8`, `8.8.4.4` and `2001:4860:4860::8888`, `2001:4860:4860::8844` (thank you, Google).
+    ///
+    /// Please see Google's [privacy statement](https://developers.google.com/speed/public-dns/privacy) for important information about what they track, many ISP's track similar information in DNS. To use the system configuration see: `Resolver::from_system_conf` and `AsyncResolver::from_system_conf`
+    fn default() -> Self {
+        ResolverConfig::google()
+    }
+}
+
+/// The protocol on which a NameServer should be communicated with
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+#[cfg_attr(feature = "serde-config", derive(Serialize, Deserialize))]
+pub enum Protocol {
+    /// UDP is the traditional DNS port, this is generally the correct choice
+    Udp,
+    /// TCP can be used for large queries, but not all NameServers support it
+    Tcp,
+    /// Tls for DNS over TLS
+    #[cfg(feature = "dns-over-tls")]
+    Tls,
+    /// Https for DNS over HTTPS
+    #[cfg(feature = "dns-over-https")]
+    Https,
+    /// mDNS protocol for performing multicast lookups
+    #[cfg(feature = "mdns")]
+    Mdns,
+}
+
+impl Protocol {
+    /// Returns true if this is a datagram oriented protocol, e.g. UDP
+    pub fn is_datagram(self) -> bool {
+        match self {
+            Protocol::Udp => true,
+            Protocol::Tcp => false,
+            #[cfg(feature = "dns-over-tls")]
+            Protocol::Tls => false,
+            #[cfg(feature = "dns-over-https")]
+            Protocol::Https => false,
+            #[cfg(feature = "mdns")]
+            Protocol::Mdns => true,
+        }
+    }
+
+    /// Returns true if this is a stream oriented protocol, e.g. TCP
+    pub fn is_stream(self) -> bool {
+        !self.is_datagram()
+    }
+
+    /// Is this an encrypted protocol, i.e. TLS or HTTPS
+    pub fn is_encrypted(self) -> bool {
+        match self {
+            Protocol::Udp => false,
+            Protocol::Tcp => false,
+            #[cfg(feature = "dns-over-tls")]
+            Protocol::Tls => true,
+            #[cfg(feature = "dns-over-https")]
+            Protocol::Https => true,
+            #[cfg(feature = "mdns")]
+            Protocol::Mdns => false,
+        }
+    }
+}
+
+#[cfg(feature = "dns-over-rustls")]
+#[derive(Clone)]
+/// a compatibility wrapper around rustls
+/// ClientConfig
+pub struct TlsClientConfig(pub Arc<ClientConfig>);
+
+#[cfg(feature = "dns-over-rustls")]
+impl std::cmp::PartialEq for TlsClientConfig {
+    fn eq(&self, other: &Self) -> bool {
+        Arc::ptr_eq(&self.0, &other.0)
+    }
+}
+
+#[cfg(feature = "dns-over-rustls")]
+impl std::cmp::Eq for TlsClientConfig {}
+
+#[cfg(feature = "dns-over-rustls")]
+impl std::fmt::Debug for TlsClientConfig {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "rustls client config")
+    }
+}
+
+/// Configuration for the NameServer
+#[derive(Clone, Debug, Eq, PartialEq)]
+#[cfg_attr(feature = "serde-config", derive(Serialize, Deserialize))]
+pub struct NameServerConfig {
+    /// The address which the DNS NameServer is registered at.
+    pub socket_addr: SocketAddr,
+    /// The protocol to use when communicating with the NameServer.
+    pub protocol: Protocol,
+    /// SPKI name, only relevant for TLS connections
+    pub tls_dns_name: Option<String>,
+    #[cfg(feature = "dns-over-rustls")]
+    #[cfg_attr(feature = "serde-config", serde(skip))]
+    /// optional configuration for the tls client
+    pub tls_config: Option<TlsClientConfig>,
+}
+
+/// A set of name_servers to associate with a [`ResolverConfig`].
+#[derive(Clone, Debug, Eq, PartialEq)]
+#[cfg_attr(
+    all(feature = "serde-config", not(feature = "dns-over-rustls")),
+    derive(Serialize, Deserialize)
+)]
+pub struct NameServerConfigGroup(
+    Vec<NameServerConfig>,
+    #[cfg(feature = "dns-over-rustls")] Option<TlsClientConfig>,
+);
+
+#[cfg(all(feature = "serde-config", feature = "dns-over-rustls"))]
+impl SerializeT for NameServerConfigGroup {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: Serializer,
+    {
+        self.0.serialize(serializer)
+    }
+}
+
+#[cfg(all(feature = "serde-config", feature = "dns-over-rustls"))]
+impl<'de> DeserializeT<'de> for NameServerConfigGroup {
+    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+    where
+        D: Deserializer<'de>,
+    {
+        Vec::deserialize(deserializer).map(|nameservers| Self(nameservers, None))
+    }
+}
+
+impl NameServerConfigGroup {
+    /// Creates a new `NameServerConfigGroup` with a default size of 2
+    pub fn new() -> Self {
+        // this might be a nice opportunity for SmallVec
+        //   most name_server configs will be 2.
+        Self::with_capacity(2)
+    }
+
+    /// Creates a new `NameServiceConfigGroup` with the specified capacity
+    pub fn with_capacity(capacity: usize) -> Self {
+        NameServerConfigGroup(
+            Vec::with_capacity(capacity),
+            #[cfg(feature = "dns-over-rustls")]
+            None,
+        )
+    }
+
+    /// Configure a NameServer address and port
+    ///
+    /// This will create UDP and TCP connections, using the same port.
+    pub fn from_ips_clear(ips: &[IpAddr], port: u16) -> Self {
+        let mut name_servers = Self::with_capacity(ips.len());
+
+        for ip in ips {
+            let udp = NameServerConfig {
+                socket_addr: SocketAddr::new(*ip, port),
+                protocol: Protocol::Udp,
+                tls_dns_name: None,
+                #[cfg(feature = "dns-over-rustls")]
+                tls_config: None,
+            };
+            let tcp = NameServerConfig {
+                socket_addr: SocketAddr::new(*ip, port),
+                protocol: Protocol::Tcp,
+                tls_dns_name: None,
+                #[cfg(feature = "dns-over-rustls")]
+                tls_config: None,
+            };
+
+            name_servers.push(udp);
+            name_servers.push(tcp);
+        }
+
+        name_servers
+    }
+
+    #[cfg(any(feature = "dns-over-tls", feature = "dns-over-https"))]
+    fn from_ips_encrypted(
+        ips: &[IpAddr],
+        port: u16,
+        tls_dns_name: String,
+        protocol: Protocol,
+    ) -> Self {
+        assert!(protocol.is_encrypted());
+
+        let mut name_servers = Self::with_capacity(ips.len());
+
+        for ip in ips {
+            let config = NameServerConfig {
+                socket_addr: SocketAddr::new(*ip, port),
+                protocol,
+                tls_dns_name: Some(tls_dns_name.clone()),
+                #[cfg(feature = "dns-over-rustls")]
+                tls_config: None,
+            };
+
+            name_servers.push(config);
+        }
+
+        name_servers
+    }
+
+    /// Configure a NameServer address and port for DNS-over-TLS
+    ///
+    /// This will create a TLS connections.
+    #[cfg(feature = "dns-over-tls")]
+    pub fn from_ips_tls(ips: &[IpAddr], port: u16, tls_dns_name: String) -> Self {
+        Self::from_ips_encrypted(ips, port, tls_dns_name, Protocol::Tls)
+    }
+
+    /// Configure a NameServer address and port for DNS-over-HTTPS
+    ///
+    /// This will create a HTTPS connections.
+    #[cfg(feature = "dns-over-https")]
+    pub fn from_ips_https(ips: &[IpAddr], port: u16, tls_dns_name: String) -> Self {
+        Self::from_ips_encrypted(ips, port, tls_dns_name, Protocol::Https)
+    }
+
+    /// Creates a default configuration, using `8.8.8.8`, `8.8.4.4` and `2001:4860:4860::8888`, `2001:4860:4860::8844` (thank you, Google).
+    ///
+    /// Please see Google's [privacy statement](https://developers.google.com/speed/public-dns/privacy) for important information about what they track, many ISP's track similar information in DNS. To use the system configuration see: `Resolver::from_system_conf` and `AsyncResolver::from_system_conf`
+    pub fn google() -> Self {
+        Self::from_ips_clear(
+            &[
+                IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8)),
+                IpAddr::V4(Ipv4Addr::new(8, 8, 4, 4)),
+                IpAddr::V6(Ipv6Addr::new(0x2001, 0x4860, 0x4860, 0, 0, 0, 0, 0x8888)),
+                IpAddr::V6(Ipv6Addr::new(0x2001, 0x4860, 0x4860, 0, 0, 0, 0, 0x8844)),
+            ],
+            53,
+        )
+    }
+
+    /// Creates a default configuration, using `1.1.1.1`, `1.0.0.1` and `2606:4700:4700::1111`, `2606:4700:4700::1001` (thank you, Cloudflare).
+    ///
+    /// Please see: https://www.cloudflare.com/dns/
+    pub fn cloudflare() -> Self {
+        Self::from_ips_clear(
+            &[
+                IpAddr::V4(Ipv4Addr::new(1, 1, 1, 1)),
+                IpAddr::V4(Ipv4Addr::new(1, 0, 0, 1)),
+                IpAddr::V6(Ipv6Addr::new(0x2606, 0x4700, 0x4700, 0, 0, 0, 0, 0x1111)),
+                IpAddr::V6(Ipv6Addr::new(0x2606, 0x4700, 0x4700, 0, 0, 0, 0, 0x1001)),
+            ],
+            53,
+        )
+    }
+
+    /// Creates a configuration, using `1.1.1.1`, `1.0.0.1` and `2606:4700:4700::1111`, `2606:4700:4700::1001` (thank you, Cloudflare). This limits the registered connections to just TLS lookups
+    ///
+    /// Please see: https://www.cloudflare.com/dns/
+    #[cfg(feature = "dns-over-tls")]
+    pub fn cloudflare_tls() -> Self {
+        Self::from_ips_tls(
+            &[
+                IpAddr::V4(Ipv4Addr::new(1, 1, 1, 1)),
+                IpAddr::V4(Ipv4Addr::new(1, 0, 0, 1)),
+                IpAddr::V6(Ipv6Addr::new(0x2606, 0x4700, 0x4700, 0, 0, 0, 0, 0x1111)),
+                IpAddr::V6(Ipv6Addr::new(0x2606, 0x4700, 0x4700, 0, 0, 0, 0, 0x1001)),
+            ],
+            853,
+            "cloudflare-dns.com".to_string(),
+        )
+    }
+
+    /// Creates a configuration, using `1.1.1.1`, `1.0.0.1` and `2606:4700:4700::1111`, `2606:4700:4700::1001` (thank you, Cloudflare). This limits the registered connections to just TLS lookups
+    ///
+    /// Please see: https://www.cloudflare.com/dns/
+    #[cfg(feature = "dns-over-https")]
+    pub fn cloudflare_https() -> Self {
+        Self::from_ips_https(
+            &[
+                IpAddr::V4(Ipv4Addr::new(1, 1, 1, 1)),
+                IpAddr::V4(Ipv4Addr::new(1, 0, 0, 1)),
+                IpAddr::V6(Ipv6Addr::new(0x2606, 0x4700, 0x4700, 0, 0, 0, 0, 0x1111)),
+                IpAddr::V6(Ipv6Addr::new(0x2606, 0x4700, 0x4700, 0, 0, 0, 0, 0x1001)),
+            ],
+            443,
+            "cloudflare-dns.com".to_string(),
+        )
+    }
+
+    /// Creates a configuration, using `9.9.9.9` and `2620:fe::fe`, the "secure" variants of the quad9 settings (thank you, Quad9).
+    ///
+    /// Please see: https://www.quad9.net/faq/
+    pub fn quad9() -> Self {
+        Self::from_ips_clear(
+            &[
+                IpAddr::V4(Ipv4Addr::new(9, 9, 9, 9)),
+                IpAddr::V6(Ipv6Addr::new(0x2620, 0x00fe, 0, 0, 0, 0, 0, 0x00fe)),
+            ],
+            53,
+        )
+    }
+
+    /// Creates a configuration, using `9.9.9.9` and `2620:fe::fe`, the "secure" variants of the quad9 settings. This limits the registered connections to just TLS lookups
+    ///
+    /// Please see: https://www.quad9.net/faq/
+    #[cfg(feature = "dns-over-tls")]
+    pub fn quad9_tls() -> Self {
+        Self::from_ips_tls(
+            &[
+                IpAddr::V4(Ipv4Addr::new(9, 9, 9, 9)),
+                IpAddr::V6(Ipv6Addr::new(0x2620, 0x00fe, 0, 0, 0, 0, 0, 0x00fe)),
+            ],
+            853,
+            "dns.quad9.net".to_string(),
+        )
+    }
+
+    /// Merges this set of [`NameServerConfig`]s with the other
+    ///
+    /// ```
+    /// use std::net::{SocketAddr, Ipv4Addr};
+    /// use trust_dns_resolver::config::NameServerConfigGroup;
+    ///
+    /// let mut group = NameServerConfigGroup::google();
+    /// group.merge(NameServerConfigGroup::cloudflare());
+    /// group.merge(NameServerConfigGroup::quad9());
+    ///
+    /// assert!(group.iter().any(|c| c.socket_addr == SocketAddr::new(Ipv4Addr::new(8, 8, 8, 8).into(), 53)));
+    /// assert!(group.iter().any(|c| c.socket_addr == SocketAddr::new(Ipv4Addr::new(1, 1, 1, 1).into(), 53)));
+    /// assert!(group.iter().any(|c| c.socket_addr == SocketAddr::new(Ipv4Addr::new(9, 9, 9, 9).into(), 53)));
+    /// ```
+    pub fn merge(&mut self, mut other: Self) {
+        #[cfg(not(feature = "dns-over-rustls"))]
+        {
+            self.append(&mut other);
+        }
+        #[cfg(feature = "dns-over-rustls")]
+        {
+            self.0.append(&mut other);
+        }
+    }
+
+    #[cfg(feature = "dns-over-rustls")]
+    /// add a [`rustls::ClientConfig`]
+    pub fn with_client_config(self, client_config: Arc<ClientConfig>) -> Self {
+        Self(self.0, Some(TlsClientConfig(client_config)))
+    }
+}
+
+impl Default for NameServerConfigGroup {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+impl Deref for NameServerConfigGroup {
+    type Target = Vec<NameServerConfig>;
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+impl DerefMut for NameServerConfigGroup {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.0
+    }
+}
+
+impl From<Vec<NameServerConfig>> for NameServerConfigGroup {
+    fn from(configs: Vec<NameServerConfig>) -> Self {
+        #[cfg(not(feature = "dns-over-rustls"))]
+        {
+            NameServerConfigGroup(configs)
+        }
+        #[cfg(feature = "dns-over-rustls")]
+        {
+            NameServerConfigGroup(configs, None)
+        }
+    }
+}
+
+/// The lookup ip strategy
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[cfg_attr(feature = "serde-config", derive(Serialize, Deserialize))]
+pub enum LookupIpStrategy {
+    /// Only query for A (Ipv4) records
+    Ipv4Only,
+    /// Only query for AAAA (Ipv6) records
+    Ipv6Only,
+    /// Query for A and AAAA in parallel
+    Ipv4AndIpv6,
+    /// Query for Ipv6 if that fails, query for Ipv4
+    Ipv6thenIpv4,
+    /// Query for Ipv4 if that fails, query for Ipv6 (default)
+    Ipv4thenIpv6,
+}
+
+impl Default for LookupIpStrategy {
+    /// Returns [`LookupIpStrategy::Ipv4AndIpv6`] as the default.
+    fn default() -> Self {
+        LookupIpStrategy::Ipv4thenIpv6
+    }
+}
+
+/// Configuration for the Resolver
+#[derive(Debug, Clone, Copy, Eq, PartialEq)]
+#[cfg_attr(
+    feature = "serde-config",
+    derive(Serialize, Deserialize),
+    serde(default)
+)]
+#[allow(dead_code)] // TODO: remove after all params are supported
+pub struct ResolverOpts {
+    /// Sets the number of dots that must appear (unless it's a final dot representing the root)
+    ///  that must appear before a query is assumed to include the TLD. The default is one, which
+    ///  means that `www` would never be assumed to be a TLD, and would always be appended to either
+    ///  the search
+    pub ndots: usize,
+    /// Specify the timeout for a request. Defaults to 5 seconds
+    pub timeout: Duration,
+    /// Number of attempts before giving up. Defaults to 2
+    pub attempts: usize,
+    /// Rotate through the resource records in the response (if there is more than one for a given name)
+    pub(crate) rotate: bool,
+    /// Validate the names in the response, not implemented don't really see the point unless you need to support
+    ///  badly configured DNS
+    pub(crate) check_names: bool,
+    /// Enable edns, for larger records
+    pub(crate) edns0: bool,
+    /// Use DNSSec to validate the request
+    pub validate: bool,
+    /// The ip_strategy for the Resolver to use when lookup Ipv4 or Ipv6 addresses
+    pub ip_strategy: LookupIpStrategy,
+    /// Cache size is in number of records (some records can be large)
+    pub cache_size: usize,
+    /// Check /ect/hosts file before dns requery (only works for unix like OS)
+    pub use_hosts_file: bool,
+    /// Optional minimum TTL for positive responses.
+    ///
+    /// If this is set, any positive responses with a TTL lower than this value will have a TTL of
+    /// `positive_min_ttl` instead. Otherwise, this will default to 0 seconds.
+    pub positive_min_ttl: Option<Duration>,
+    /// Optional minimum TTL for negative (`NXDOMAIN`) responses.
+    ///
+    /// If this is set, any positive responses with a TTL lower than this value will have a TTL of
+    /// `negative_min_ttl` instead. Otherwise, this will default to 0 seconds.
+    pub negative_min_ttl: Option<Duration>,
+    /// Optional maximum TTL for positive responses.
+    ///
+    /// If this is set, any positive responses with a TTL higher than this value will have a TTL of
+    /// `positive_max_ttl` instead. Otherwise, this will default to [`MAX_TTL`] seconds.
+    ///
+    /// [`MAX_TTL`]: ../dns_lru/const.MAX_TTL.html
+    pub positive_max_ttl: Option<Duration>,
+    /// Optional maximum TTL for negative (`NXDOMAIN`) responses.
+    ///
+    /// If this is set, any positive responses with a TTL higher than this value will have a TTL of
+    /// `negative_max_ttl` instead. Otherwise, this will default to [`MAX_TTL`] seconds.
+    ///
+    /// [`MAX_TTL`]: ../dns_lru/const.MAX_TTL.html
+    pub negative_max_ttl: Option<Duration>,
+    /// Default is to distrust negative responses from upstream nameservers
+    ///
+    /// Currently only SERVFAIL responses are continued on, this may be expanded to include NXDOMAIN or NoError/Empty responses
+    pub distrust_nx_responses: bool,
+    /// Concurrent requests where more than one Nameserver is registered, the default is 2
+    ///
+    /// 0 or 1 will configure this to execute all requests serially
+    pub num_concurrent_reqs: usize,
+}
+
+impl Default for ResolverOpts {
+    /// Default values for the Resolver configuration.
+    ///
+    /// This follows the resolv.conf defaults as defined in the [Linux man pages](http://man7.org/linux/man-pages/man5/resolv.conf.5.html)
+    fn default() -> Self {
+        ResolverOpts {
+            ndots: 1,
+            timeout: Duration::from_secs(5),
+            attempts: 2,
+            rotate: false,
+            check_names: true,
+            edns0: false,
+            validate: false,
+            ip_strategy: LookupIpStrategy::default(),
+            cache_size: 32,
+            use_hosts_file: true,
+            positive_min_ttl: None,
+            negative_min_ttl: None,
+            positive_max_ttl: None,
+            negative_max_ttl: None,
+            distrust_nx_responses: true,
+            num_concurrent_reqs: 2,
+        }
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/src/dns_lru.rs b/third_party/rust_crates/vendor/trust-dns-resolver/src/dns_lru.rs
new file mode 100644
index 0000000..7effdc1
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/src/dns_lru.rs
@@ -0,0 +1,581 @@
+// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! An LRU cache designed for work with DNS lookups
+
+use std::sync::Arc;
+use std::time::{Duration, Instant};
+
+use proto::op::Query;
+use proto::rr::Record;
+
+use crate::config;
+use crate::error::*;
+use crate::lookup::Lookup;
+use crate::lru_cache::LruCache;
+
+/// Maximum TTL as defined in https://tools.ietf.org/html/rfc2181, 2147483647
+///   Setting this to a value of 1 day, in seconds
+pub const MAX_TTL: u32 = 86400_u32;
+
+#[derive(Debug)]
+struct LruValue {
+    // In the None case, this represents an NXDomain
+    lookup: Option<Lookup>,
+    valid_until: Instant,
+}
+
+impl LruValue {
+    /// Returns true if this set of ips is still valid
+    fn is_current(&self, now: Instant) -> bool {
+        now <= self.valid_until
+    }
+}
+
+#[derive(Debug)]
+pub(crate) struct DnsLru {
+    cache: LruCache<Query, LruValue>,
+    /// A minimum TTL value for positive responses.
+    ///
+    /// Positive responses with TTLs under `positive_max_ttl` will use
+    /// `positive_max_ttl` instead.
+    ///
+    /// If this value is not set on the `TtlConfig` used to construct this
+    /// `DnsLru`, it will default to 0.
+    positive_min_ttl: Duration,
+    /// A minimum TTL value for negative (`NXDOMAIN`) responses.
+    ///
+    /// `NXDOMAIN` responses with TTLs under `negative_min_ttl` will use
+    /// `negative_min_ttl` instead.
+    ///
+    /// If this value is not set on the `TtlConfig` used to construct this
+    /// `DnsLru`, it will default to 0.
+    negative_min_ttl: Duration,
+    /// A maximum TTL value for positive responses.
+    ///
+    /// Positive responses with TTLs over `positive_max_ttl` will use
+    /// `positive_max_ttl` instead.
+    ///
+    ///  If this value is not set on the `TtlConfig` used to construct this
+    /// `DnsLru`, it will default to [`MAX_TTL`] seconds.
+    ///
+    /// [`MAX_TTL`]: const.MAX_TTL.html
+    positive_max_ttl: Duration,
+    /// A maximum TTL value for negative (`NXDOMAIN`) responses.
+    ///
+    /// `NXDOMAIN` responses with TTLs over `negative_max_ttl` will use
+    /// `negative_max_ttl` instead.
+    ///
+    ///  If this value is not set on the `TtlConfig` used to construct this
+    /// `DnsLru`, it will default to [`MAX_TTL`] seconds.
+    ///
+    /// [`MAX_TTL`]: const.MAX_TTL.html
+    negative_max_ttl: Duration,
+}
+
+/// The time-to-live, TTL, configuration for use by the cache.
+///
+/// It should be understood that the TTL in DNS is expressed with a u32.
+///   We use Duration here for tracking this which can express larger values
+///   than the DNS standard. Generally a Duration greater than u32::MAX_VALUE
+///   shouldn't cause any issue as this will never be used in serialization,
+///   but understand that this would be outside the standard range.
+#[derive(Copy, Clone, Debug, Default)]
+pub(crate) struct TtlConfig {
+    /// An optional minimum TTL value for positive responses.
+    ///
+    /// Positive responses with TTLs under `positive_min_ttl` will use
+    /// `positive_min_ttl` instead.
+    pub positive_min_ttl: Option<Duration>,
+    /// An optional minimum TTL value for negative (`NXDOMAIN`) responses.
+    ///
+    /// `NXDOMAIN` responses with TTLs under `negative_min_ttl will use
+    /// `negative_min_ttl` instead.
+    pub negative_min_ttl: Option<Duration>,
+    /// An optional maximum TTL value for positive responses.
+    ///
+    /// Positive responses with TTLs positive `positive_max_ttl` will use
+    /// `positive_max_ttl` instead.
+    pub positive_max_ttl: Option<Duration>,
+    /// An optional maximum TTL value for negative (`NXDOMAIN`) responses.
+    ///
+    /// `NXDOMAIN` responses with TTLs over `negative_max_ttl` will use
+    /// `negative_max_ttl` instead.
+    pub negative_max_ttl: Option<Duration>,
+}
+
+impl TtlConfig {
+    pub(crate) fn from_opts(opts: &config::ResolverOpts) -> TtlConfig {
+        TtlConfig {
+            positive_min_ttl: opts.positive_min_ttl,
+            negative_min_ttl: opts.negative_min_ttl,
+            positive_max_ttl: opts.positive_max_ttl,
+            negative_max_ttl: opts.negative_max_ttl,
+        }
+    }
+}
+
+impl DnsLru {
+    pub(crate) fn new(capacity: usize, ttl_cfg: TtlConfig) -> Self {
+        let TtlConfig {
+            positive_min_ttl,
+            negative_min_ttl,
+            positive_max_ttl,
+            negative_max_ttl,
+        } = ttl_cfg;
+        let cache = LruCache::new(capacity);
+        Self {
+            cache,
+            positive_min_ttl: positive_min_ttl.unwrap_or_else(|| Duration::from_secs(0)),
+            negative_min_ttl: negative_min_ttl.unwrap_or_else(|| Duration::from_secs(0)),
+            positive_max_ttl: positive_max_ttl
+                .unwrap_or_else(|| Duration::from_secs(u64::from(MAX_TTL))),
+            negative_max_ttl: negative_max_ttl
+                .unwrap_or_else(|| Duration::from_secs(u64::from(MAX_TTL))),
+        }
+    }
+
+    pub(crate) fn insert(
+        &mut self,
+        query: Query,
+        records_and_ttl: Vec<(Record, u32)>,
+        now: Instant,
+    ) -> Lookup {
+        let len = records_and_ttl.len();
+        // collapse the values, we're going to take the Minimum TTL as the correct one
+        let (records, ttl): (Vec<Record>, Duration) = records_and_ttl.into_iter().fold(
+            (Vec::with_capacity(len), self.positive_max_ttl),
+            |(mut records, mut min_ttl), (record, ttl)| {
+                records.push(record);
+                let ttl = Duration::from_secs(u64::from(ttl));
+                min_ttl = min_ttl.min(ttl);
+                (records, min_ttl)
+            },
+        );
+
+        // If the cache was configured with a minimum TTL, and that value is higher
+        // than the minimum TTL in the values, use it instead.
+        let ttl = self.positive_min_ttl.max(ttl);
+        let valid_until = now + ttl;
+
+        // insert into the LRU
+        let lookup = Lookup::new_with_deadline(query.clone(), Arc::new(records), valid_until);
+        self.cache.insert(
+            query,
+            LruValue {
+                lookup: Some(lookup.clone()),
+                valid_until,
+            },
+        );
+
+        lookup
+    }
+
+    /// Generally for inserting a set of records that have already been cached, but with a different Query.
+    pub(crate) fn duplicate(
+        &mut self,
+        query: Query,
+        lookup: Lookup,
+        ttl: u32,
+        now: Instant,
+    ) -> Lookup {
+        let ttl = Duration::from_secs(u64::from(ttl));
+        let valid_until = now + ttl;
+
+        self.cache.insert(
+            query,
+            LruValue {
+                lookup: Some(lookup.clone()),
+                valid_until,
+            },
+        );
+
+        lookup
+    }
+
+    pub(crate) fn nx_error(query: Query, valid_until: Option<Instant>) -> ResolveError {
+        ResolveErrorKind::NoRecordsFound { query, valid_until }.into()
+    }
+
+    pub(crate) fn negative(&mut self, query: Query, ttl: u32, now: Instant) -> ResolveError {
+        // TODO: if we are getting a negative response, should we instead fallback to cache?
+        //   this would cache indefinitely, probably not correct
+
+        let ttl = Duration::from_secs(u64::from(ttl))
+            // Clamp the TTL so that it's between the cache's configured
+            // minimum and maximum TTLs for negative responses.
+            .max(self.negative_min_ttl)
+            .min(self.negative_max_ttl);
+        let valid_until = now + ttl;
+
+        self.cache.insert(
+            query.clone(),
+            LruValue {
+                lookup: None,
+                valid_until,
+            },
+        );
+
+        Self::nx_error(query, Some(valid_until))
+    }
+
+    /// This needs to be mut b/c it's an LRU, meaning the ordering of elements will potentially change on retrieval...
+    pub(crate) fn get(&mut self, query: &Query, now: Instant) -> Option<Lookup> {
+        let mut out_of_date = false;
+        let lookup = self.cache.get_mut(query).and_then(|value| {
+            if value.is_current(now) {
+                out_of_date = false;
+                value.lookup.clone()
+            } else {
+                out_of_date = true;
+                None
+            }
+        });
+
+        // in this case, we can preemptively remove out of data elements
+        // this assumes time is always moving forward, this would only not be true in contrived situations where now
+        //  is not current time, like tests...
+        if out_of_date {
+            self.cache.remove(query);
+        }
+
+        lookup
+    }
+}
+
+// see also the lookup_tests.rs in integration-tests crate
+#[cfg(test)]
+mod tests {
+    use std::net::*;
+    use std::str::FromStr;
+    use std::time::*;
+
+    use proto::op::Query;
+    use proto::rr::{Name, RData, RecordType};
+
+    use super::*;
+
+    #[test]
+    fn test_is_current() {
+        let now = Instant::now();
+        let not_the_future = now + Duration::from_secs(4);
+        let future = now + Duration::from_secs(5);
+        let past_the_future = now + Duration::from_secs(6);
+
+        let value = LruValue {
+            lookup: None,
+            valid_until: future,
+        };
+
+        assert!(value.is_current(now));
+        assert!(value.is_current(not_the_future));
+        assert!(value.is_current(future));
+        assert!(!value.is_current(past_the_future));
+    }
+
+    #[test]
+    fn test_lookup_uses_positive_min_ttl() {
+        let now = Instant::now();
+
+        let name = Name::from_str("www.example.com.").unwrap();
+        let query = Query::query(name.clone(), RecordType::A);
+        // record should have TTL of 1 second.
+        let ips_ttl = vec![(
+            Record::from_rdata(name.clone(), 1, RData::A(Ipv4Addr::new(127, 0, 0, 1))),
+            1,
+        )];
+        let ips = vec![RData::A(Ipv4Addr::new(127, 0, 0, 1))];
+
+        // configure the cache with a minimum TTL of 2 seconds.
+        let ttls = TtlConfig {
+            positive_min_ttl: Some(Duration::from_secs(2)),
+            ..Default::default()
+        };
+        let mut lru = DnsLru::new(1, ttls);
+
+        let rc_ips = lru.insert(query.clone(), ips_ttl, now);
+        assert_eq!(*rc_ips.iter().next().unwrap(), ips[0]);
+        // the returned lookup should use the cache's min TTL, since the
+        // query's TTL was below the minimum.
+        assert_eq!(rc_ips.valid_until(), now + Duration::from_secs(2));
+
+        // record should have TTL of 3 seconds.
+        let ips_ttl = vec![(
+            Record::from_rdata(name, 3, RData::A(Ipv4Addr::new(127, 0, 0, 1))),
+            3,
+        )];
+
+        let rc_ips = lru.insert(query, ips_ttl, now);
+        assert_eq!(*rc_ips.iter().next().unwrap(), ips[0]);
+        // the returned lookup should use the record's TTL, since it's
+        // greater than the cache's minimum.
+        assert_eq!(rc_ips.valid_until(), now + Duration::from_secs(3));
+    }
+
+    #[test]
+    fn test_error_uses_negative_min_ttl() {
+        let now = Instant::now();
+
+        let name = Query::query(Name::from_str("www.example.com.").unwrap(), RecordType::A);
+
+        // configure the cache with a maximum TTL of 2 seconds.
+        let ttls = TtlConfig {
+            negative_min_ttl: Some(Duration::from_secs(2)),
+            ..Default::default()
+        };
+        let mut lru = DnsLru::new(1, ttls);
+
+        // neg response should have TTL of 1 seconds.
+        let nx_error = lru.negative(name.clone(), 1, now);
+        match nx_error.kind() {
+            &ResolveErrorKind::NoRecordsFound { valid_until, .. } => {
+                let valid_until = valid_until.expect("resolve error should have a deadline");
+                // the error's `valid_until` field should have been limited to 2 seconds.
+                assert_eq!(valid_until, now + Duration::from_secs(2));
+            }
+            other => panic!("expected ResolveErrorKind::NoRecordsFound, got {:?}", other),
+        }
+
+        // neg response should have TTL of 3 seconds.
+        let nx_error = lru.negative(name, 3, now);
+        match nx_error.kind() {
+            &ResolveErrorKind::NoRecordsFound { valid_until, .. } => {
+                let valid_until = valid_until.expect("ResolveError should have a deadline");
+                // the error's `valid_until` field should not have been limited, as it was
+                // over the min TTL.
+                assert_eq!(valid_until, now + Duration::from_secs(3));
+            }
+            other => panic!("expected ResolveErrorKind::NoRecordsFound, got {:?}", other),
+        }
+    }
+
+    #[test]
+    fn test_lookup_uses_positive_max_ttl() {
+        let now = Instant::now();
+
+        let name = Name::from_str("www.example.com.").unwrap();
+        let query = Query::query(name.clone(), RecordType::A);
+        // record should have TTL of 62 seconds.
+        let ips_ttl = vec![(
+            Record::from_rdata(name.clone(), 62, RData::A(Ipv4Addr::new(127, 0, 0, 1))),
+            62,
+        )];
+        let ips = vec![RData::A(Ipv4Addr::new(127, 0, 0, 1))];
+
+        // configure the cache with a maximum TTL of 60 seconds.
+        let ttls = TtlConfig {
+            positive_max_ttl: Some(Duration::from_secs(60)),
+            ..Default::default()
+        };
+        let mut lru = DnsLru::new(1, ttls);
+
+        let rc_ips = lru.insert(query.clone(), ips_ttl, now);
+        assert_eq!(*rc_ips.iter().next().unwrap(), ips[0]);
+        // the returned lookup should use the cache's min TTL, since the
+        // query's TTL was above the maximum.
+        assert_eq!(rc_ips.valid_until(), now + Duration::from_secs(60));
+
+        // record should have TTL of 59 seconds.
+        let ips_ttl = vec![(
+            Record::from_rdata(name, 59, RData::A(Ipv4Addr::new(127, 0, 0, 1))),
+            59,
+        )];
+
+        let rc_ips = lru.insert(query, ips_ttl, now);
+        assert_eq!(*rc_ips.iter().next().unwrap(), ips[0]);
+        // the returned lookup should use the record's TTL, since it's
+        // below than the cache's maximum.
+        assert_eq!(rc_ips.valid_until(), now + Duration::from_secs(59));
+    }
+
+    #[test]
+    fn test_error_uses_negative_max_ttl() {
+        let now = Instant::now();
+
+        let name = Query::query(Name::from_str("www.example.com.").unwrap(), RecordType::A);
+
+        // configure the cache with a maximum TTL of 60 seconds.
+        let ttls = TtlConfig {
+            negative_max_ttl: Some(Duration::from_secs(60)),
+            ..Default::default()
+        };
+        let mut lru = DnsLru::new(1, ttls);
+
+        // neg response should have TTL of 62 seconds.
+        let nx_error = lru.negative(name.clone(), 62, now);
+        match nx_error.kind() {
+            &ResolveErrorKind::NoRecordsFound { valid_until, .. } => {
+                let valid_until = valid_until.expect("resolve error should have a deadline");
+                // the error's `valid_until` field should have been limited to 60 seconds.
+                assert_eq!(valid_until, now + Duration::from_secs(60));
+            }
+            other => panic!("expected ResolveErrorKind::NoRecordsFound, got {:?}", other),
+        }
+
+        // neg response should have TTL of 59 seconds.
+        let nx_error = lru.negative(name, 59, now);
+        match nx_error.kind() {
+            &ResolveErrorKind::NoRecordsFound { valid_until, .. } => {
+                let valid_until = valid_until.expect("resolve error should have a deadline");
+                // the error's `valid_until` field should not have been limited, as it was
+                // under the max TTL.
+                assert_eq!(valid_until, now + Duration::from_secs(59));
+            }
+            other => panic!("expected ResolveErrorKind::NoRecordsFound, got {:?}", other),
+        }
+    }
+
+    #[test]
+    fn test_insert() {
+        let now = Instant::now();
+
+        let name = Name::from_str("www.example.com.").unwrap();
+        let query = Query::query(name.clone(), RecordType::A);
+        let ips_ttl = vec![(
+            Record::from_rdata(name, 1, RData::A(Ipv4Addr::new(127, 0, 0, 1))),
+            1,
+        )];
+        let ips = vec![RData::A(Ipv4Addr::new(127, 0, 0, 1))];
+        let mut lru = DnsLru::new(1, TtlConfig::default());
+
+        let rc_ips = lru.insert(query.clone(), ips_ttl, now);
+        assert_eq!(*rc_ips.iter().next().unwrap(), ips[0]);
+
+        let rc_ips = lru.get(&query, now).unwrap();
+        assert_eq!(*rc_ips.iter().next().unwrap(), ips[0]);
+    }
+
+    #[test]
+    fn test_insert_ttl() {
+        let now = Instant::now();
+        let name = Name::from_str("www.example.com.").unwrap();
+        let query = Query::query(name.clone(), RecordType::A);
+        // TTL should be 1
+        let ips_ttl = vec![
+            (
+                Record::from_rdata(name.clone(), 1, RData::A(Ipv4Addr::new(127, 0, 0, 1))),
+                1,
+            ),
+            (
+                Record::from_rdata(name, 2, RData::A(Ipv4Addr::new(127, 0, 0, 2))),
+                2,
+            ),
+        ];
+        let ips = vec![
+            RData::A(Ipv4Addr::new(127, 0, 0, 1)),
+            RData::A(Ipv4Addr::new(127, 0, 0, 2)),
+        ];
+        let mut lru = DnsLru::new(1, TtlConfig::default());
+
+        lru.insert(query.clone(), ips_ttl, now);
+
+        // still valid
+        let rc_ips = lru.get(&query, now + Duration::from_secs(1)).unwrap();
+        assert_eq!(*rc_ips.iter().next().unwrap(), ips[0]);
+
+        // 2 should be one too far
+        let rc_ips = lru.get(&query, now + Duration::from_secs(2));
+        assert!(rc_ips.is_none());
+    }
+
+    #[test]
+    fn test_insert_positive_min_ttl() {
+        let now = Instant::now();
+        let name = Name::from_str("www.example.com.").unwrap();
+        let query = Query::query(name.clone(), RecordType::A);
+        // TTL should be 1
+        let ips_ttl = vec![
+            (
+                Record::from_rdata(name.clone(), 1, RData::A(Ipv4Addr::new(127, 0, 0, 1))),
+                1,
+            ),
+            (
+                Record::from_rdata(name, 2, RData::A(Ipv4Addr::new(127, 0, 0, 2))),
+                2,
+            ),
+        ];
+        let ips = vec![
+            RData::A(Ipv4Addr::new(127, 0, 0, 1)),
+            RData::A(Ipv4Addr::new(127, 0, 0, 2)),
+        ];
+
+        // this cache should override the TTL of 1 seconds with the configured
+        // minimum TTL of 3 seconds.
+        let ttls = TtlConfig {
+            positive_min_ttl: Some(Duration::from_secs(3)),
+            ..Default::default()
+        };
+        let mut lru = DnsLru::new(1, ttls);
+        lru.insert(query.clone(), ips_ttl, now);
+
+        // still valid
+        let rc_ips = lru.get(&query, now + Duration::from_secs(1)).unwrap();
+        for (rc_ip, ip) in rc_ips.iter().zip(ips.iter()) {
+            assert_eq!(rc_ip, ip, "after 1 second");
+        }
+
+        let rc_ips = lru.get(&query, now + Duration::from_secs(2)).unwrap();
+        for (rc_ip, ip) in rc_ips.iter().zip(ips.iter()) {
+            assert_eq!(rc_ip, ip, "after 2 seconds");
+        }
+
+        let rc_ips = lru.get(&query, now + Duration::from_secs(3)).unwrap();
+        for (rc_ip, ip) in rc_ips.iter().zip(ips.iter()) {
+            assert_eq!(rc_ip, ip, "after 3 seconds");
+        }
+
+        // after 4 seconds, the records should be invalid.
+        let rc_ips = lru.get(&query, now + Duration::from_secs(4));
+        assert!(rc_ips.is_none());
+    }
+
+    #[test]
+    fn test_insert_positive_max_ttl() {
+        let now = Instant::now();
+        let name = Name::from_str("www.example.com.").unwrap();
+        let query = Query::query(name.clone(), RecordType::A);
+        // TTL should be 500
+        let ips_ttl = vec![
+            (
+                Record::from_rdata(name.clone(), 400, RData::A(Ipv4Addr::new(127, 0, 0, 1))),
+                400,
+            ),
+            (
+                Record::from_rdata(name, 500, RData::A(Ipv4Addr::new(127, 0, 0, 2))),
+                500,
+            ),
+        ];
+        let ips = vec![
+            RData::A(Ipv4Addr::new(127, 0, 0, 1)),
+            RData::A(Ipv4Addr::new(127, 0, 0, 2)),
+        ];
+
+        // this cache should override the TTL of 500 seconds with the configured
+        // minimum TTL of 2 seconds.
+        let ttls = TtlConfig {
+            positive_max_ttl: Some(Duration::from_secs(2)),
+            ..Default::default()
+        };
+        let mut lru = DnsLru::new(1, ttls);
+        lru.insert(query.clone(), ips_ttl, now);
+
+        // still valid
+        let rc_ips = lru.get(&query, now + Duration::from_secs(1)).unwrap();
+        for (rc_ip, ip) in rc_ips.iter().zip(ips.iter()) {
+            assert_eq!(rc_ip, ip, "after 1 second");
+        }
+
+        let rc_ips = lru.get(&query, now + Duration::from_secs(2)).unwrap();
+        for (rc_ip, ip) in rc_ips.iter().zip(ips.iter()) {
+            assert_eq!(rc_ip, ip, "after 2 seconds");
+        }
+
+        // after 3 seconds, the records should be invalid.
+        let rc_ips = lru.get(&query, now + Duration::from_secs(3));
+        assert!(rc_ips.is_none());
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/src/dns_sd.rs b/third_party/rust_crates/vendor/trust-dns-resolver/src/dns_sd.rs
new file mode 100644
index 0000000..bb7af3d
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/src/dns_sd.rs
@@ -0,0 +1,204 @@
+// Copyright 2015-2018 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! DNS Service Discovery
+#![cfg(feature = "mdns")]
+
+use std::borrow::Cow;
+use std::collections::HashMap;
+use std::pin::Pin;
+use std::task::{Context, Poll};
+
+use futures::Future;
+
+use proto::rr::rdata::TXT;
+use proto::rr::{Name, RecordType};
+use proto::xfer::DnsRequestOptions;
+use proto::DnsHandle;
+
+use crate::error::*;
+use crate::lookup::{ReverseLookup, ReverseLookupIter, TxtLookup};
+use crate::name_server::ConnectionProvider;
+use crate::AsyncResolver;
+
+/// An extension for the Resolver to perform DNS Service Discovery
+pub trait DnsSdHandle {
+    /// List all services available
+    ///
+    /// https://tools.ietf.org/html/rfc6763#section-4.1
+    ///
+    /// For registered service types, see: https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml
+    fn list_services(&self, name: Name) -> ListServicesFuture;
+
+    /// Retrieve service information
+    ///
+    /// https://tools.ietf.org/html/rfc6763#section-6
+    fn service_info(&self, name: Name) -> ServiceInfoFuture;
+}
+
+impl<C: DnsHandle, P: ConnectionProvider<Conn = C>> DnsSdHandle for AsyncResolver<C, P> {
+    fn list_services(&self, name: Name) -> ListServicesFuture {
+        let this = self.clone();
+
+        let ptr_future = async move {
+            let options = DnsRequestOptions {
+                expects_multiple_responses: true,
+            };
+
+            this.inner_lookup(name, RecordType::PTR, options).await
+        };
+
+        ListServicesFuture(Box::pin(ptr_future))
+    }
+
+    fn service_info(&self, name: Name) -> ServiceInfoFuture {
+        let this = self.clone();
+
+        let ptr_future = async move { this.txt_lookup(name).await };
+
+        ServiceInfoFuture(Box::pin(ptr_future))
+    }
+}
+
+/// A DNS Service Discovery future of Services discovered through the list operation
+pub struct ListServicesFuture(
+    Pin<Box<dyn Future<Output = Result<ReverseLookup, ResolveError>> + Send + 'static>>,
+);
+
+impl Future for ListServicesFuture {
+    type Output = Result<ListServices, ResolveError>;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+        match self.0.as_mut().poll(cx) {
+            Poll::Ready(Ok(lookup)) => Poll::Ready(Ok(ListServices(lookup))),
+            Poll::Pending => Poll::Pending,
+            Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
+        }
+    }
+}
+
+/// The list of Services discovered
+pub struct ListServices(ReverseLookup);
+
+impl ListServices {
+    /// Returns an iterator over the list of returned names of services.
+    ///
+    /// Each name can be queried for additional information. To lookup service entries see [`AsyncResolver::lookup_srv`]. To get parameters associated with the service, see `DnsSdFuture::service_info`.
+    pub fn iter(&self) -> ListServicesIter {
+        ListServicesIter(self.0.iter())
+    }
+}
+
+/// An iterator over the Lookup type
+pub struct ListServicesIter<'i>(ReverseLookupIter<'i>);
+
+impl<'i> Iterator for ListServicesIter<'i> {
+    type Item = &'i Name;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.0.next()
+    }
+}
+
+/// A Future that resolves to the TXT information for a service
+pub struct ServiceInfoFuture(
+    Pin<Box<dyn Future<Output = Result<TxtLookup, ResolveError>> + Send + 'static>>,
+);
+
+impl Future for ServiceInfoFuture {
+    type Output = Result<ServiceInfo, ResolveError>;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+        match self.0.as_mut().poll(cx) {
+            Poll::Ready(Ok(lookup)) => Poll::Ready(Ok(ServiceInfo(lookup))),
+            Poll::Pending => Poll::Pending,
+            Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
+        }
+    }
+}
+
+/// The list of Services discovered
+pub struct ServiceInfo(TxtLookup);
+
+impl ServiceInfo {
+    /// Returns this as a map, this allocates a new hashmap
+    ///
+    /// This converts the DNS-SD TXT record into a map following the rules specified in https://tools.ietf.org/html/rfc6763#section-6.4
+    pub fn to_map<'s>(&'s self) -> HashMap<Cow<'s, str>, Option<Cow<'s, str>>> {
+        self.0
+            .iter()
+            .flat_map(TXT::iter)
+            .filter_map(|bytes| {
+                let mut split = bytes.split(|byte| *byte == b'=');
+
+                let key = split.next().map(String::from_utf8_lossy);
+                let value = split.next().map(String::from_utf8_lossy);
+
+                if let Some(key) = key {
+                    Some((key, value))
+                } else {
+                    None
+                }
+            })
+            .collect()
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    #![allow(clippy::dbg_macro, clippy::print_stdout)]
+
+    use std::str::FromStr;
+    use tokio::runtime::Runtime;
+
+    use crate::config::*;
+    use crate::TokioAsyncResolver;
+
+    use super::*;
+
+    #[test]
+    #[ignore]
+    fn test_list_services() {
+        let mut io_loop = Runtime::new().unwrap();
+        let resolver = TokioAsyncResolver::new(
+            ResolverConfig::default(),
+            ResolverOpts {
+                ip_strategy: LookupIpStrategy::Ipv6thenIpv4,
+                ..ResolverOpts::default()
+            },
+            io_loop.handle().clone(),
+        );
+        let resolver = io_loop
+            .block_on(resolver)
+            .expect("failed to create resolver");
+
+        let response = io_loop
+            .block_on(resolver.list_services(Name::from_str("_http._tcp.local.").unwrap()))
+            .expect("failed to run lookup");
+
+        for name in response.iter() {
+            println!("service: {}", name);
+            let srvs = io_loop
+                .block_on(resolver.srv_lookup(name.clone()))
+                .expect("failed to lookup name");
+
+            for srv in srvs.iter() {
+                println!("service: {:#?}", srv);
+
+                let info = io_loop
+                    .block_on(resolver.service_info(name.clone()))
+                    .expect("info failed");
+                let info = info.to_map();
+                println!("info: {:#?}", info);
+            }
+
+            for ip in srvs.ip_iter() {
+                println!("ip: {}", ip);
+            }
+        }
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/src/error.rs b/third_party/rust_crates/vendor/trust-dns-resolver/src/error.rs
new file mode 100644
index 0000000..fd3e504
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/src/error.rs
@@ -0,0 +1,162 @@
+// Copyright 2015-2020 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! Error types for the crate
+
+use std::{fmt, io, sync, time::Instant};
+
+use thiserror::Error;
+
+use crate::proto::error::{ProtoError, ProtoErrorKind};
+use crate::proto::op::Query;
+use crate::proto::{trace, ExtBacktrace};
+
+/// An alias for results returned by functions of this crate
+pub type ResolveResult<T> = ::std::result::Result<T, ResolveError>;
+
+/// The error kind for errors that get returned in the crate
+#[derive(Debug, Error)]
+pub enum ResolveErrorKind {
+    /// An error with an arbitrary message, referenced as &'static str
+    #[error("{0}")]
+    Message(&'static str),
+
+    /// An error with an arbitrary message, stored as String
+    #[error("{0}")]
+    Msg(String),
+
+    /// No records were found for a query
+    #[error("no record found for {query}")]
+    NoRecordsFound {
+        /// The query for which no records were found.
+        query: Query,
+        /// A deadline after which the `NXDOMAIN` response is no longer
+        /// valid, and the nameserver should be queried again.
+        valid_until: Option<Instant>,
+    },
+
+    // foreign
+    /// An error got returned from IO
+    #[error("io error: {0}")]
+    Io(#[from] std::io::Error),
+
+    /// An error got returned by the trust-dns-proto crate
+    #[error("proto error: {0}")]
+    Proto(#[from] ProtoError),
+
+    /// A request timed out
+    #[error("request timed out")]
+    Timeout,
+}
+
+impl Clone for ResolveErrorKind {
+    fn clone(&self) -> Self {
+        use self::ResolveErrorKind::*;
+        match self {
+            Message(msg) => Message(msg),
+            Msg(ref msg) => Msg(msg.clone()),
+            NoRecordsFound {
+                ref query,
+                valid_until,
+            } => NoRecordsFound {
+                query: query.clone(),
+                valid_until: *valid_until,
+            },
+
+            // foreign
+            Io(io) => ResolveErrorKind::from(std::io::Error::from(io.kind())),
+            Proto(proto) => ResolveErrorKind::from(proto.clone()),
+            Timeout => Timeout,
+        }
+    }
+}
+
+/// The error type for errors that get returned in the crate
+#[derive(Debug, Clone, Error)]
+pub struct ResolveError {
+    kind: ResolveErrorKind,
+    backtrack: Option<ExtBacktrace>,
+}
+
+impl ResolveError {
+    /// Get the kind of the error
+    pub fn kind(&self) -> &ResolveErrorKind {
+        &self.kind
+    }
+}
+
+impl fmt::Display for ResolveError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        if let Some(ref backtrace) = self.backtrack {
+            fmt::Display::fmt(&self.kind, f)?;
+            fmt::Debug::fmt(backtrace, f)
+        } else {
+            fmt::Display::fmt(&self.kind, f)
+        }
+    }
+}
+
+impl From<ResolveErrorKind> for ResolveError {
+    fn from(kind: ResolveErrorKind) -> ResolveError {
+        ResolveError {
+            kind,
+            backtrack: trace!(),
+        }
+    }
+}
+
+impl From<&'static str> for ResolveError {
+    fn from(msg: &'static str) -> ResolveError {
+        ResolveErrorKind::Message(msg).into()
+    }
+}
+
+#[cfg(target_os = "windows")]
+impl From<ipconfig::error::Error> for ResolveError {
+    fn from(e: ipconfig::error::Error) -> ResolveError {
+        ResolveErrorKind::Msg(format!("failed to read from registry: {}", e)).into()
+    }
+}
+
+impl From<String> for ResolveError {
+    fn from(msg: String) -> ResolveError {
+        ResolveErrorKind::Msg(msg).into()
+    }
+}
+
+impl From<io::Error> for ResolveError {
+    fn from(e: io::Error) -> ResolveError {
+        match e.kind() {
+            io::ErrorKind::TimedOut => ResolveErrorKind::Timeout.into(),
+            _ => ResolveErrorKind::from(e).into(),
+        }
+    }
+}
+
+impl From<ProtoError> for ResolveError {
+    fn from(e: ProtoError) -> ResolveError {
+        match *e.kind() {
+            ProtoErrorKind::Timeout => ResolveErrorKind::Timeout.into(),
+            _ => ResolveErrorKind::from(e).into(),
+        }
+    }
+}
+
+impl From<ResolveError> for io::Error {
+    fn from(e: ResolveError) -> Self {
+        match e.kind() {
+            ResolveErrorKind::Timeout => io::Error::new(io::ErrorKind::TimedOut, e),
+            _ => io::Error::new(io::ErrorKind::Other, e),
+        }
+    }
+}
+
+impl<T> From<sync::PoisonError<T>> for ResolveError {
+    fn from(e: sync::PoisonError<T>) -> Self {
+        ResolveErrorKind::Msg(format!("lock was poisoned, this is non-recoverable: {}", e)).into()
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/src/hosts.rs b/third_party/rust_crates/vendor/trust-dns-resolver/src/hosts.rs
new file mode 100644
index 0000000..c6f4a58
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/src/hosts.rs
@@ -0,0 +1,259 @@
+//! Hosts result from a configuration of the system hosts file
+
+use std::collections::HashMap;
+use std::io;
+use std::path::Path;
+#[cfg(any(unix, windows))]
+use std::str::FromStr;
+use std::sync::Arc;
+
+use proto::op::Query;
+use proto::rr::{Name, RecordType};
+#[cfg(any(unix, windows))]
+use proto::rr::{RData, Record};
+
+use crate::dns_lru;
+use crate::lookup::Lookup;
+
+#[derive(Debug, Default)]
+struct LookupType {
+    /// represents the A record type
+    a: Option<Lookup>,
+    /// represents the AAAA record type
+    aaaa: Option<Lookup>,
+}
+
+/// Configuration for the local hosts file
+#[derive(Debug, Default)]
+pub struct Hosts {
+    /// Name -> RDatas map
+    by_name: HashMap<Name, LookupType>,
+}
+
+impl Hosts {
+    /// Creates a new configuration from the system hosts file,
+    /// only works for Windows and Unix-like OSes,
+    /// will return empty configuration on others
+    pub fn new() -> Hosts {
+        read_hosts_conf(hosts_path()).unwrap_or_default()
+    }
+
+    /// Look up the addresses for the given host from the system hosts file.
+    pub fn lookup_static_host(&self, query: &Query) -> Option<Lookup> {
+        if !self.by_name.is_empty() {
+            if let Some(val) = self.by_name.get(query.name()) {
+                let result = match query.query_type() {
+                    RecordType::A => val.a.clone(),
+                    RecordType::AAAA => val.aaaa.clone(),
+                    _ => None,
+                };
+
+                return result;
+            }
+        }
+        None
+    }
+
+    /// Insert a new Lookup for the associated `Name` and `RecordType`
+    pub fn insert(&mut self, name: Name, record_type: RecordType, lookup: Lookup) {
+        assert!(record_type == RecordType::A || record_type == RecordType::AAAA);
+
+        let lookup_type = self
+            .by_name
+            .entry(name.clone())
+            .or_insert_with(LookupType::default);
+
+        let new_lookup = {
+            let old_lookup = match record_type {
+                RecordType::A => lookup_type.a.get_or_insert_with(|| {
+                    let query = Query::query(name.clone(), record_type);
+                    Lookup::new_with_max_ttl(query, Arc::new(vec![]))
+                }),
+                RecordType::AAAA => lookup_type.aaaa.get_or_insert_with(|| {
+                    let query = Query::query(name.clone(), record_type);
+                    Lookup::new_with_max_ttl(query, Arc::new(vec![]))
+                }),
+                _ => {
+                    warn!("unsupported IP type from Hosts file: {:#?}", record_type);
+                    return;
+                }
+            };
+
+            old_lookup.append(lookup)
+        };
+
+        // replace the appended version
+        match record_type {
+            RecordType::A => lookup_type.a = Some(new_lookup),
+            RecordType::AAAA => lookup_type.aaaa = Some(new_lookup),
+            _ => warn!("unsupported IP type from Hosts file"),
+        }
+    }
+}
+
+#[cfg(unix)]
+fn hosts_path() -> &'static str {
+    "/etc/hosts"
+}
+
+#[cfg(windows)]
+fn hosts_path() -> std::path::PathBuf {
+    let system_root =
+        std::env::var_os("SystemRoot").expect("Environtment variable SystemRoot not found");
+    let system_root = Path::new(&system_root);
+    system_root.join("System32\\drivers\\etc\\hosts")
+}
+
+/// parse configuration from `path`
+#[cfg(any(unix, windows))]
+pub fn read_hosts_conf<P: AsRef<Path>>(path: P) -> io::Result<Hosts> {
+    use std::fs::File;
+    use std::io::{BufRead, BufReader};
+
+    use proto::rr::domain::TryParseIp;
+
+    let mut hosts = Hosts {
+        by_name: HashMap::new(),
+    };
+
+    // lines in the file should have the form `addr host1 host2 host3 ...`
+    // line starts with `#` will be regarded with comments and ignored,
+    // also empty line also will be ignored,
+    // if line only include `addr` without `host` will be ignored,
+    // file will parsed to map in the form `Name -> LookUp`.
+    let file = File::open(path)?;
+
+    for line in BufReader::new(file).lines() {
+        // Remove comments from the line
+        let line = line
+            .as_ref()
+            .map(|line| line.split('#').next().unwrap().trim())
+            .unwrap_or_default();
+        if line.is_empty() {
+            continue;
+        }
+
+        let fields: Vec<_> = line.split_whitespace().collect();
+        if fields.len() < 2 {
+            continue;
+        }
+        let addr = if let Some(a) = fields[0].try_parse_ip() {
+            a
+        } else {
+            warn!("could not parse an IP from hosts file");
+            continue;
+        };
+
+        for domain in fields.iter().skip(1).map(|domain| domain.to_lowercase()) {
+            if let Ok(name) = Name::from_str(&domain) {
+                let record = Record::from_rdata(name.clone(), dns_lru::MAX_TTL, addr.clone());
+
+                match addr {
+                    RData::A(..) => {
+                        let query = Query::query(name.clone(), RecordType::A);
+                        let lookup = Lookup::new_with_max_ttl(query, Arc::new(vec![record]));
+                        hosts.insert(name.clone(), RecordType::A, lookup);
+                    }
+                    RData::AAAA(..) => {
+                        let query = Query::query(name.clone(), RecordType::AAAA);
+                        let lookup = Lookup::new_with_max_ttl(query, Arc::new(vec![record]));
+                        hosts.insert(name.clone(), RecordType::AAAA, lookup);
+                    }
+                    _ => {
+                        warn!("unsupported IP type from Hosts file: {:#?}", addr);
+                        continue;
+                    }
+                };
+
+                // TODO: insert reverse lookup as well.
+            };
+        }
+    }
+
+    Ok(hosts)
+}
+
+#[cfg(not(any(unix, windows)))]
+pub fn read_hosts_conf<P: AsRef<Path>>(_path: P) -> io::Result<Hosts> {
+    Err(io::Error::new(
+        io::ErrorKind::Other,
+        "Only Windows or Unix-like hosts file is supported".to_string(),
+    ))
+}
+
+#[cfg(any(unix, windows))]
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use std::env;
+    use std::net::{Ipv4Addr, Ipv6Addr};
+
+    fn tests_dir() -> String {
+        let server_path = env::var("TDNS_WORKSPACE_ROOT").unwrap_or_else(|_| "../..".to_owned());
+        format! {"{}/crates/resolver/tests", server_path}
+    }
+
+    #[test]
+    fn test_read_hosts_conf() {
+        let path = format!("{}/hosts", tests_dir());
+        let hosts = read_hosts_conf(&path).unwrap();
+
+        let name = Name::from_str("localhost").unwrap();
+        let rdatas = hosts
+            .lookup_static_host(&Query::query(name.clone(), RecordType::A))
+            .unwrap()
+            .iter()
+            .map(ToOwned::to_owned)
+            .collect::<Vec<RData>>();
+
+        assert_eq!(rdatas, vec![RData::A(Ipv4Addr::new(127, 0, 0, 1))]);
+
+        let rdatas = hosts
+            .lookup_static_host(&Query::query(name, RecordType::AAAA))
+            .unwrap()
+            .iter()
+            .map(ToOwned::to_owned)
+            .collect::<Vec<RData>>();
+
+        assert_eq!(
+            rdatas,
+            vec![RData::AAAA(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1))]
+        );
+
+        let name = Name::from_str("broadcasthost").unwrap();
+        let rdatas = hosts
+            .lookup_static_host(&Query::query(name, RecordType::A))
+            .unwrap()
+            .iter()
+            .map(ToOwned::to_owned)
+            .collect::<Vec<RData>>();
+        assert_eq!(rdatas, vec![RData::A(Ipv4Addr::new(255, 255, 255, 255))]);
+
+        let name = Name::from_str("example.com").unwrap();
+        let rdatas = hosts
+            .lookup_static_host(&Query::query(name, RecordType::A))
+            .unwrap()
+            .iter()
+            .map(ToOwned::to_owned)
+            .collect::<Vec<RData>>();
+        assert_eq!(rdatas, vec![RData::A(Ipv4Addr::new(10, 0, 1, 102))]);
+
+        let name = Name::from_str("a.example.com").unwrap();
+        let rdatas = hosts
+            .lookup_static_host(&Query::query(name, RecordType::A))
+            .unwrap()
+            .iter()
+            .map(ToOwned::to_owned)
+            .collect::<Vec<RData>>();
+        assert_eq!(rdatas, vec![RData::A(Ipv4Addr::new(10, 0, 1, 111))]);
+
+        let name = Name::from_str("b.example.com").unwrap();
+        let rdatas = hosts
+            .lookup_static_host(&Query::query(name, RecordType::A))
+            .unwrap()
+            .iter()
+            .map(ToOwned::to_owned)
+            .collect::<Vec<RData>>();
+        assert_eq!(rdatas, vec![RData::A(Ipv4Addr::new(10, 0, 1, 111))]);
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/src/https.rs b/third_party/rust_crates/vendor/trust-dns-resolver/src/https.rs
new file mode 100644
index 0000000..46715dc
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/src/https.rs
@@ -0,0 +1,74 @@
+extern crate rustls;
+extern crate webpki_roots;
+
+use std::net::SocketAddr;
+
+use crate::tls::CLIENT_CONFIG;
+
+use proto::xfer::{DnsExchange, DnsExchangeConnect};
+use proto::TokioTime;
+use trust_dns_https::{
+    HttpsClientConnect, HttpsClientResponse, HttpsClientStream, HttpsClientStreamBuilder,
+};
+
+use crate::config::TlsClientConfig;
+
+#[allow(clippy::type_complexity)]
+pub(crate) fn new_https_stream(
+    socket_addr: SocketAddr,
+    dns_name: String,
+    client_config: Option<TlsClientConfig>,
+) -> DnsExchangeConnect<HttpsClientConnect, HttpsClientStream, HttpsClientResponse, TokioTime> {
+    let client_config = client_config.map_or_else(
+        || CLIENT_CONFIG.clone(),
+        |TlsClientConfig(client_config)| client_config,
+    );
+
+    let https_builder = HttpsClientStreamBuilder::with_client_config(client_config);
+    DnsExchange::connect(https_builder.build(socket_addr, dns_name))
+}
+
+#[cfg(test)]
+mod tests {
+    extern crate env_logger;
+    use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+
+    use tokio::runtime::Runtime;
+
+    use crate::config::{ResolverConfig, ResolverOpts};
+    use crate::TokioAsyncResolver;
+
+    fn https_test(config: ResolverConfig) {
+        //env_logger::try_init().ok();
+        let mut io_loop = Runtime::new().unwrap();
+
+        let resolver =
+            TokioAsyncResolver::new(config, ResolverOpts::default(), io_loop.handle().clone());
+        let resolver = io_loop
+            .block_on(resolver)
+            .expect("failed to create resolver");
+
+        let response = io_loop
+            .block_on(resolver.lookup_ip("www.example.com."))
+            .expect("failed to run lookup");
+
+        assert_eq!(response.iter().count(), 1);
+        for address in response.iter() {
+            if address.is_ipv4() {
+                assert_eq!(address, IpAddr::V4(Ipv4Addr::new(93, 184, 216, 34)));
+            } else {
+                assert_eq!(
+                    address,
+                    IpAddr::V6(Ipv6Addr::new(
+                        0x2606, 0x2800, 0x220, 0x1, 0x248, 0x1893, 0x25c8, 0x1946,
+                    ))
+                );
+            }
+        }
+    }
+
+    #[test]
+    fn test_cloudflare_https() {
+        https_test(ResolverConfig::cloudflare_https())
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/src/lib.rs b/third_party/rust_crates/vendor/trust-dns-resolver/src/lib.rs
new file mode 100644
index 0000000..52e5ff5
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/src/lib.rs
@@ -0,0 +1,276 @@
+// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! The Resolver is responsible for performing recursive queries to lookup domain names.
+//!
+//! This is a 100% in process DNS resolver. It *does not* use the Host OS' resolver. If what is desired is to use the Host OS' resolver, generally in the system's libc, then the `std::net::ToSocketAddrs` variant over `&str` should be used.
+//!
+//! Unlike the `trust-dns-client`, this tries to provide a simpler interface to perform DNS queries. For update options, i.e. Dynamic DNS, the `trust-dns-client` crate must be used instead. The Resolver library is capable of searching multiple domains (this can be disabled by using an FQDN during lookup), dual-stack IPv4/IPv6 lookups, performing chained CNAME lookups, and features connection metric tracking for attempting to pick the best upstream DNS resolver.
+//!
+//! There are two types for performing DNS queries, [`Resolver`] and [`AsyncResolver`]. `Resolver` is the easiest to work with, it is a wrapper around [`AsyncResolver`]. `AsyncResolver` is a `Tokio` based async resolver, and can be used inside any `Tokio` based system.
+//!
+//! This as best as possible attempts to abide by the DNS RFCs, please file issues at https://github.com/bluejekyll/trust-dns .
+//!
+//! # Usage
+//!
+//! ## Declare dependency
+//!
+//! ```toml
+//! [dependency]
+//! trust-dns-resolver = "*"
+//! ```
+//!
+//! ## Extern the crate for usage in the library
+//!
+//! ```rust
+//! extern crate trust_dns_resolver;
+//! ```
+//!
+//! ## Using the Synchronous Resolver
+//!
+//! This uses the default configuration, which sets the [Google Public DNS](https://developers.google.com/speed/public-dns/) as the upstream resolvers. Please see their [privacy statement](https://developers.google.com/speed/public-dns/privacy) for important information about what they track, many ISP's track similar information in DNS.
+//!
+//! ```rust
+//! # extern crate trust_dns_resolver;
+//! # fn main() {
+//! # #[cfg(feature = "tokio-runtime")]
+//! # {
+//! use std::net::*;
+//! use trust_dns_resolver::Resolver;
+//! use trust_dns_resolver::config::*;
+//!
+//! // Construct a new Resolver with default configuration options
+//! let resolver = Resolver::new(ResolverConfig::default(), ResolverOpts::default()).unwrap();
+//!
+//! // Lookup the IP addresses associated with a name.
+//! // The final dot forces this to be an FQDN, otherwise the search rules as specified
+//! //  in `ResolverOpts` will take effect. FQDN's are generally cheaper queries.
+//! let response = resolver.lookup_ip("www.example.com.").unwrap();
+//!
+//! // There can be many addresses associated with the name,
+//! //  this can return IPv4 and/or IPv6 addresses
+//! let address = response.iter().next().expect("no addresses returned!");
+//! if address.is_ipv4() {
+//!     assert_eq!(address, IpAddr::V4(Ipv4Addr::new(93, 184, 216, 34)));
+//! } else {
+//!     assert_eq!(address, IpAddr::V6(Ipv6Addr::new(0x2606, 0x2800, 0x220, 0x1, 0x248, 0x1893, 0x25c8, 0x1946)));
+//! }
+//! # }
+//! # }
+//! ```
+//!
+//! ## Using the host system config
+//!
+//! On Unix systems, the `/etc/resolv.conf` can be used for configuration. Not all options specified in the host systems `resolv.conf` are applicable or compatible with this software. In addition there may be additional options supported which the host system does not. Example:
+//!
+//! ```rust,no_run
+//! # extern crate trust_dns_resolver;
+//! # fn main() {
+//! # #[cfg(feature = "tokio-runtime")]
+//! # {
+//! # use std::net::*;
+//! # use trust_dns_resolver::Resolver;
+//! // Use the host OS'es `/etc/resolv.conf`
+//! # #[cfg(unix)]
+//! let resolver = Resolver::from_system_conf().unwrap();
+//! # #[cfg(unix)]
+//! let response = resolver.lookup_ip("www.example.com.").unwrap();
+//! # }
+//! # }
+//! ```
+//!
+//! ## Using the Tokio/Async Resolver
+//!
+//! For more advanced asynchronous usage, the `AsyncResolver`] is integrated with Tokio. In fact, the [`AsyncResolver`] is used by the synchronous Resolver for all lookups.
+//!
+//! ```rust
+//! # extern crate futures;
+//! # extern crate tokio;
+//! # extern crate trust_dns_resolver;
+//! # fn main() {
+//! # #[cfg(feature = "tokio-runtime")]
+//! # {
+//! use std::net::*;
+//! use tokio::runtime::Runtime;
+//! use trust_dns_resolver::TokioAsyncResolver;
+//! use trust_dns_resolver::config::*;
+//!
+//! // We need a Tokio Runtime to run the resolver
+//! //  this is responsible for running all Future tasks and registering interest in IO channels
+//! let mut io_loop = Runtime::new().unwrap();
+//!
+//! // Construct a new Resolver with default configuration options
+//! let resolver = TokioAsyncResolver::tokio(
+//!     ResolverConfig::default(),
+//!     ResolverOpts::default(),
+//! );
+//! // AsyncResolver::new returns a handle for sending resolve requests and a background task
+//! // that must be spawned on an executor.
+//! let resolver = io_loop.block_on(resolver).expect("failed to connect resolver");
+//!
+//! // Lookup the IP addresses associated with a name.
+//! // This returns a future that will lookup the IP addresses, it must be run in the Core to
+//! //  to get the actual result.
+//! let lookup_future = resolver.lookup_ip("www.example.com.");
+//!
+//! // Run the lookup until it resolves or errors
+//! let mut response = io_loop.block_on(lookup_future).unwrap();
+//!
+//! // There can be many addresses associated with the name,
+//! //  this can return IPv4 and/or IPv6 addresses
+//! let address = response.iter().next().expect("no addresses returned!");
+//! if address.is_ipv4() {
+//!     assert_eq!(address, IpAddr::V4(Ipv4Addr::new(93, 184, 216, 34)));
+//! } else {
+//!     assert_eq!(address, IpAddr::V6(Ipv6Addr::new(0x2606, 0x2800, 0x220, 0x1, 0x248, 0x1893, 0x25c8, 0x1946)));
+//! }
+//! # }
+//! # }
+//! ```
+//!
+//! Generally after a lookup in an asynchronous context, there would probably be a connection made to a server, for example:
+//!
+//! ```c
+//! let result = io_loop.block_on(lookup_future.and_then(|ips| {
+//!                                  let ip = ips.next().unwrap();
+//!                                  TcpStream::connect()
+//!                              }).and_then(|conn| /* do something with the connection... */)
+//!                          ).unwrap();
+//! ```
+//!
+//! It's beyond the scope of these examples to show how to deal with connection failures and looping etc. But if you wanted to say try a different address from the result set after a connection failure, it will be necessary to create a type that implements the `Future` trait. Inside the `Future::poll` method would be the place to implement a loop over the different IP addresses.
+//!
+//! ## DNS-over-TLS and DNS-over-HTTPS
+//!
+//! DNS-over-TLS and DNS-over-HTTPS are supported in the Trust-DNS Resolver library. The underlying implementations are available as addon libraries. *WARNING* The trust-dns developers make no claims on the security and/or privacy guarantees of this implementation.
+//!
+//! To use DNS-over-TLS one of the `dns-over-tls` features must be enabled at compile time. There are three: `dns-over-openssl`, `dns-over-native-tls`, and `dns-over-rustls`. For DNS-over-HTTPS only rustls is supported with the `dns-over-https-rustls`, this implicitly enables support for DNS-over-TLS as well. The reason for each is to make the Trust-DNS libraries flexible for different deployments, and/or security concerns. The easiest to use will generally be `dns-over-rustls` which utilizes the `*ring*` Rust cryptography library (a rework of the `boringssl` project), this should compile and be usable on most ARM and x86 platforms. `dns-over-native-tls` will utilize the hosts TLS implementation where available or fallback to `openssl` where not supported. `dns-over-openssl` will specify that `openssl` should be used (which is a perfectly fine option if required). If more than one is specified, the precedence will be in this order (i.e. only one can be used at a time) `dns-over-rustls`, `dns-over-native-tls`, and then `dns-over-openssl`. *NOTICE* the trust-dns developers are not responsible for any choice of library that does not meet required security requirements.
+//!
+//! ### Example
+//!
+//! Enable the TLS library through the dependency on `trust-dns-resolver`:
+//!
+//! ```toml
+//! trust-dns-resolver = { version = "*", features = ["dns-over-rustls"] }
+//! ```
+//!
+//! A default TLS configuration is available for Cloudflare's `1.1.1.1` DNS service (Quad9 as well):
+//!
+//! ```rust,no_run
+//! # extern crate trust_dns_resolver;
+//! # fn main() {
+//! # #[cfg(feature = "tokio-runtime")]
+//! # {
+//! use trust_dns_resolver::Resolver;
+//! use trust_dns_resolver::config::*;
+//!
+//! // Construct a new Resolver with default configuration options
+//! # #[cfg(feature = "dns-over-tls")]
+//! let mut resolver = Resolver::new(ResolverConfig::cloudflare_tls(), ResolverOpts::default()).unwrap();
+//!
+//! // see example above...
+//! # }
+//! # }
+//! ```
+//!
+//! ## mDNS (multicast DNS)
+//!
+//! Multicast DNS is an experimental feature in Trust-DNS at the moment. It's support on different platforms is not yet ideal. Initial support is only for IPv4 mDNS, as there are some complexities to figure out with IPv6. Once enabled, an mDNS `NameServer` will automatically be added to the `Resolver` and used for any lookups performed in the `.local.` zone.
+
+#![warn(
+    missing_docs,
+    clippy::dbg_macro,
+    clippy::print_stdout,
+    clippy::unimplemented
+)]
+#![recursion_limit = "128"]
+#![allow(clippy::needless_doctest_main)]
+#![allow(clippy::unknown_clippy_lints)]
+
+#[cfg(feature = "dns-over-tls")]
+#[macro_use]
+extern crate cfg_if;
+extern crate futures;
+#[cfg(target_os = "windows")]
+extern crate ipconfig;
+#[macro_use]
+extern crate lazy_static;
+#[macro_use]
+extern crate log;
+extern crate lru_cache;
+#[cfg(feature = "unix-config")]
+extern crate resolv_conf;
+#[cfg(feature = "serde-config")]
+#[macro_use]
+extern crate serde;
+extern crate smallvec;
+#[cfg(feature = "tokio-runtime")]
+extern crate tokio;
+#[cfg(feature = "dns-over-https")]
+extern crate trust_dns_https;
+#[cfg(feature = "dns-over-native-tls")]
+extern crate trust_dns_native_tls;
+#[cfg(feature = "dns-over-openssl")]
+extern crate trust_dns_openssl;
+pub extern crate trust_dns_proto as proto;
+#[cfg(feature = "dns-over-rustls")]
+extern crate trust_dns_rustls;
+
+mod async_resolver;
+pub mod config;
+mod dns_lru;
+pub mod dns_sd;
+pub mod error;
+mod hosts;
+#[cfg(feature = "dns-over-https")]
+mod https;
+pub mod lookup;
+pub mod lookup_ip;
+pub mod lookup_state;
+#[doc(hidden)]
+pub mod name_server;
+#[cfg(feature = "tokio-runtime")]
+mod resolver;
+pub mod system_conf;
+#[cfg(feature = "dns-over-tls")]
+mod tls;
+
+// reexports from proto
+pub use self::proto::rr::{IntoName, Name, TryParseIp};
+
+#[cfg(feature = "testing")]
+pub use async_resolver::testing;
+pub use async_resolver::AsyncResolver;
+#[cfg(feature = "tokio-runtime")]
+pub use async_resolver::TokioAsyncResolver;
+pub use hosts::Hosts;
+pub use name_server::ConnectionProvider;
+#[cfg(feature = "tokio-runtime")]
+pub use name_server::{TokioConnection, TokioConnectionProvider};
+#[cfg(feature = "tokio-runtime")]
+pub use resolver::Resolver;
+
+/// This is an alias for [`AsyncResolver`], which replaced the type previously
+/// called `ResolverFuture`.
+///
+/// # Note
+///
+/// For users of `ResolverFuture`, the return type for `ResolverFuture::new`
+/// has changed since version 0.9 of `trust-dns-resolver`. It now returns
+/// a tuple of an [`AsyncResolver`] _and_ a background future, which must
+/// be spawned on a reactor before any lookup futures will run.
+///
+/// See the [`AsyncResolver`] documentation for more information on how to
+/// use the background future.
+#[deprecated(note = "use [`trust_dns_resolver::AsyncResolver`] instead")]
+#[cfg(feature = "tokio-runtime")]
+pub type ResolverFuture = TokioAsyncResolver;
+
+/// returns a version as specified in Cargo.toml
+pub fn version() -> &'static str {
+    env!("CARGO_PKG_VERSION")
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/src/lookup.rs b/third_party/rust_crates/vendor/trust-dns-resolver/src/lookup.rs
new file mode 100644
index 0000000..52d00390
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/src/lookup.rs
@@ -0,0 +1,675 @@
+// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! Lookup result from a resolution of ipv4 and ipv6 records with a Resolver.
+
+use std::cmp::min;
+use std::net::{Ipv4Addr, Ipv6Addr};
+use std::pin::Pin;
+use std::slice::Iter;
+use std::sync::Arc;
+use std::task::{Context, Poll};
+use std::time::{Duration, Instant};
+use std::vec::IntoIter;
+
+use futures::{future, Future, FutureExt};
+
+use proto::error::ProtoError;
+use proto::op::Query;
+use proto::rr::rdata;
+use proto::rr::{Name, RData, Record, RecordType};
+use proto::xfer::{DnsRequest, DnsRequestOptions, DnsResponse};
+#[cfg(feature = "dnssec")]
+use proto::DnssecDnsHandle;
+use proto::{DnsHandle, RetryDnsHandle};
+
+use crate::dns_lru::MAX_TTL;
+use crate::error::*;
+use crate::lookup_ip::LookupIpIter;
+use crate::lookup_state::CachingClient;
+use crate::name_server::{ConnectionProvider, NameServerPool};
+
+/// Result of a DNS query when querying for any record type supported by the Trust-DNS Proto library.
+///
+/// For IP resolution see LookupIp, as it has more features for A and AAAA lookups.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct Lookup {
+    query: Query,
+    records: Arc<Vec<Record>>,
+    valid_until: Instant,
+}
+
+impl Lookup {
+    /// Return new instance with given rdata and the maximum TTL.
+    pub fn from_rdata(query: Query, rdata: RData) -> Self {
+        let record = Record::from_rdata(query.name().clone(), MAX_TTL, rdata);
+        Self::new_with_max_ttl(query, Arc::new(vec![record]))
+    }
+
+    /// Return new instance with given records and the maximum TTL.
+    pub fn new_with_max_ttl(query: Query, records: Arc<Vec<Record>>) -> Self {
+        let valid_until = Instant::now() + Duration::from_secs(u64::from(MAX_TTL));
+        Lookup {
+            query,
+            records,
+            valid_until,
+        }
+    }
+
+    /// Return a new instance with the given records and deadline.
+    pub fn new_with_deadline(
+        query: Query,
+        records: Arc<Vec<Record>>,
+        valid_until: Instant,
+    ) -> Self {
+        Lookup {
+            query,
+            records,
+            valid_until,
+        }
+    }
+
+    /// Returns a reference to the `Query` that was used to produce this result.
+    pub fn query(&self) -> &Query {
+        &self.query
+    }
+
+    /// Returns a borrowed iterator of the returned IPs
+    pub fn iter(&self) -> LookupIter {
+        LookupIter(self.records.iter())
+    }
+
+    /// Returns a borrowed iterator of the returned IPs
+    pub fn record_iter(&self) -> LookupRecordIter {
+        LookupRecordIter(self.records.iter())
+    }
+
+    /// Returns the `Instant` at which this `Lookup` is no longer valid.
+    pub fn valid_until(&self) -> Instant {
+        self.valid_until
+    }
+
+    #[doc(hidden)]
+    pub fn is_empty(&self) -> bool {
+        self.records.is_empty()
+    }
+
+    pub(crate) fn len(&self) -> usize {
+        self.records.len()
+    }
+
+    #[cfg(test)]
+    pub fn records(&self) -> &[Record] {
+        self.records.as_ref()
+    }
+
+    /// Clones the inner vec, appends the other vec
+    pub(crate) fn append(&self, other: Lookup) -> Self {
+        let mut records = Vec::with_capacity(self.len() + other.len());
+        records.extend_from_slice(&*self.records);
+        records.extend_from_slice(&*other.records);
+
+        // Choose the sooner deadline of the two lookups.
+        let valid_until = min(self.valid_until(), other.valid_until());
+        Self::new_with_deadline(self.query.clone(), Arc::new(records), valid_until)
+    }
+}
+
+/// Borrowed view of set of [`RData`]s returned from a Lookup
+pub struct LookupIter<'a>(Iter<'a, Record>);
+
+impl<'a> Iterator for LookupIter<'a> {
+    type Item = &'a RData;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.0.next().map(Record::rdata)
+    }
+}
+
+/// Borrowed view of set of [`RData`]s returned from a Lookup
+pub struct LookupRecordIter<'a>(Iter<'a, Record>);
+
+impl<'a> Iterator for LookupRecordIter<'a> {
+    type Item = &'a Record;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.0.next()
+    }
+}
+
+impl IntoIterator for Lookup {
+    type Item = RData;
+    type IntoIter = LookupIntoIter;
+
+    /// This is most likely not a free conversion, the `RData`s will be cloned if data is
+    ///  held behind an Arc with more than one reference (which is most likely the case coming from cache)
+    fn into_iter(self) -> Self::IntoIter {
+        LookupIntoIter {
+            records: Arc::try_unwrap(self.records).map(IntoIterator::into_iter),
+            index: 0,
+        }
+    }
+}
+
+/// Borrowed view of set of [`RData`]s returned from a [`Lookup`].
+///
+/// This is not usually a zero overhead `Iterator`, it may result in clones of the [`RData`].
+pub struct LookupIntoIter {
+    // the result of the try_unwrap on Arc
+    records: Result<IntoIter<Record>, Arc<Vec<Record>>>,
+    index: usize,
+}
+
+impl Iterator for LookupIntoIter {
+    type Item = RData;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        match self.records {
+            // a zero overhead unwrap
+            Ok(ref mut iter) => iter.next().map(Record::unwrap_rdata),
+            Err(ref records) => {
+                let rdata = records.get(self.index).map(Record::rdata);
+                self.index += 1;
+                rdata.cloned()
+            }
+        }
+    }
+}
+
+/// Different lookup options for the lookup attempts and validation
+#[derive(Clone)]
+#[doc(hidden)]
+pub enum LookupEither<C: DnsHandle + 'static, P: ConnectionProvider<Conn = C> + 'static> {
+    Retry(RetryDnsHandle<NameServerPool<C, P>>),
+    #[cfg(feature = "dnssec")]
+    Secure(DnssecDnsHandle<RetryDnsHandle<NameServerPool<C, P>>>),
+}
+
+impl<C: DnsHandle + Sync, P: ConnectionProvider<Conn = C>> DnsHandle for LookupEither<C, P> {
+    type Response = Pin<Box<dyn Future<Output = Result<DnsResponse, ProtoError>> + Send>>;
+
+    fn is_verifying_dnssec(&self) -> bool {
+        match *self {
+            LookupEither::Retry(ref c) => c.is_verifying_dnssec(),
+            #[cfg(feature = "dnssec")]
+            LookupEither::Secure(ref c) => c.is_verifying_dnssec(),
+        }
+    }
+
+    fn send<R: Into<DnsRequest> + Unpin + Send + 'static>(&mut self, request: R) -> Self::Response {
+        match *self {
+            LookupEither::Retry(ref mut c) => c.send(request),
+            #[cfg(feature = "dnssec")]
+            LookupEither::Secure(ref mut c) => c.send(request),
+        }
+    }
+}
+
+/// The Future returned from [`AsyncResolver`] when performing a lookup.
+#[doc(hidden)]
+pub struct LookupFuture<C>
+where
+    C: DnsHandle + 'static,
+{
+    client_cache: CachingClient<C>,
+    names: Vec<Name>,
+    record_type: RecordType,
+    options: DnsRequestOptions,
+    query: Pin<Box<dyn Future<Output = Result<Lookup, ResolveError>> + Send>>,
+}
+
+impl<C: DnsHandle + 'static> LookupFuture<C> {
+    /// Perform a lookup from a name and type to a set of RDatas
+    ///
+    /// # Arguments
+    ///
+    /// * `names` - a set of DNS names to attempt to resolve, they will be attempted in queue order, i.e. the first is `names.pop()`. Upon each failure, the next will be attempted.
+    /// * `record_type` - type of record being sought
+    /// * `client_cache` - cache with a connection to use for performing all lookups
+    #[doc(hidden)]
+    pub fn lookup(
+        mut names: Vec<Name>,
+        record_type: RecordType,
+        options: DnsRequestOptions,
+        mut client_cache: CachingClient<C>,
+    ) -> Self {
+        let name = names.pop().ok_or_else(|| {
+            ResolveError::from(ResolveErrorKind::Message("can not lookup for no names"))
+        });
+
+        let query: Pin<Box<dyn Future<Output = Result<Lookup, ResolveError>> + Send>> = match name {
+            Ok(name) => client_cache
+                .lookup(Query::query(name, record_type), options.clone())
+                .boxed(),
+            Err(err) => future::err(err).boxed(),
+        };
+
+        LookupFuture {
+            client_cache,
+            names,
+            record_type,
+            options,
+            query,
+        }
+    }
+}
+
+impl<C: DnsHandle + 'static> Future for LookupFuture<C> {
+    type Output = Result<Lookup, ResolveError>;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+        loop {
+            // Try polling the underlying DNS query.
+            let query = self.query.as_mut().poll_unpin(cx);
+
+            // Determine whether or not we will attempt to retry the query.
+            let should_retry = match query {
+                // If the query is NotReady, yield immediately.
+                Poll::Pending => return Poll::Pending,
+                // If the query returned a successful lookup, we will attempt
+                // to retry if the lookup is empty. Otherwise, we will return
+                // that lookup.
+                Poll::Ready(Ok(ref lookup)) => lookup.records.len() == 0,
+                // If the query failed, we will attempt to retry.
+                Poll::Ready(Err(_)) => true,
+            };
+
+            if should_retry {
+                if let Some(name) = self.names.pop() {
+                    let record_type = self.record_type;
+                    let options = self.options.clone();
+
+                    // If there's another name left to try, build a new query
+                    // for that next name and continue looping.
+                    self.query = self
+                        .client_cache
+                        .lookup(Query::query(name, record_type), options);
+                    // Continue looping with the new query. It will be polled
+                    // on the next iteration of the loop.
+                    continue;
+                }
+            }
+            // If we didn't have to retry the query, or we weren't able to
+            // retry because we've exhausted the names to search, return the
+            // current query.
+            return query;
+            // If we skipped retrying the  query, this will return the
+            // successful lookup, otherwise, if the retry failed, this will
+            // return the last  query result --- either an empty lookup or the
+            // last error we saw.
+        }
+    }
+}
+
+/// The result of an SRV lookup
+#[derive(Debug, Clone)]
+pub struct SrvLookup(Lookup);
+
+impl SrvLookup {
+    /// Returns an iterator over the SRV RData
+    pub fn iter(&self) -> SrvLookupIter {
+        SrvLookupIter(self.0.iter())
+    }
+
+    /// Returns a reference to the Query that was used to produce this result.
+    pub fn query(&self) -> &Query {
+        self.0.query()
+    }
+
+    /// Returns the list of IPs associated with the SRV record.
+    ///
+    /// *Note*: That Trust-DNS performs a recursive lookup on SRV records for IPs if they were not included in the original request. If there are no IPs associated to the result, a subsequent query for the IPs via the `srv.target()` should not resolve to the IPs.
+    pub fn ip_iter(&self) -> LookupIpIter {
+        LookupIpIter(self.0.iter())
+    }
+}
+
+impl From<Lookup> for SrvLookup {
+    fn from(lookup: Lookup) -> Self {
+        SrvLookup(lookup)
+    }
+}
+
+/// An iterator over the Lookup type
+pub struct SrvLookupIter<'i>(LookupIter<'i>);
+
+impl<'i> Iterator for SrvLookupIter<'i> {
+    type Item = &'i rdata::SRV;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let iter: &mut _ = &mut self.0;
+        iter.filter_map(|rdata| match *rdata {
+            RData::SRV(ref data) => Some(data),
+            _ => None,
+        })
+        .next()
+    }
+}
+
+impl IntoIterator for SrvLookup {
+    type Item = rdata::SRV;
+    type IntoIter = SrvLookupIntoIter;
+
+    /// This is most likely not a free conversion, the RDatas will be cloned if data is
+    ///  held behind an Arc with more than one reference (which is most likely the case coming from cache)
+    fn into_iter(self) -> Self::IntoIter {
+        SrvLookupIntoIter(self.0.into_iter())
+    }
+}
+
+/// Borrowed view of set of RDatas returned from a Lookup
+pub struct SrvLookupIntoIter(LookupIntoIter);
+
+impl Iterator for SrvLookupIntoIter {
+    type Item = rdata::SRV;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let iter: &mut _ = &mut self.0;
+        iter.filter_map(|rdata| match rdata {
+            RData::SRV(data) => Some(data),
+            _ => None,
+        })
+        .next()
+    }
+}
+
+/// Creates a Lookup result type from the specified components
+macro_rules! lookup_type {
+    ($l:ident, $i:ident, $ii:ident, $r:path, $t:path) => {
+        /// Contains the results of a lookup for the associated RecordType
+        #[derive(Debug, Clone)]
+        pub struct $l(Lookup);
+
+        impl $l {
+            /// Returns an iterator over the RData
+            pub fn iter(&self) -> $i {
+                $i(self.0.iter())
+            }
+
+            /// Returns a reference to the Query that was used to produce this result.
+            pub fn query(&self) -> &Query {
+                self.0.query()
+            }
+
+            /// Returns the `Instant` at which this result is no longer valid.
+            pub fn valid_until(&self) -> Instant {
+                self.0.valid_until()
+            }
+        }
+
+        impl From<Lookup> for $l {
+            fn from(lookup: Lookup) -> Self {
+                $l(lookup)
+            }
+        }
+
+        /// An iterator over the Lookup type
+        pub struct $i<'i>(LookupIter<'i>);
+
+        impl<'i> Iterator for $i<'i> {
+            type Item = &'i $t;
+
+            fn next(&mut self) -> Option<Self::Item> {
+                let iter: &mut _ = &mut self.0;
+                iter.filter_map(|rdata| match *rdata {
+                    $r(ref data) => Some(data),
+                    _ => None,
+                })
+                .next()
+            }
+        }
+
+        impl IntoIterator for $l {
+            type Item = $t;
+            type IntoIter = $ii;
+
+            /// This is most likely not a free conversion, the RDatas will be cloned if data is
+            ///  held behind an Arc with more than one reference (which is most likely the case coming from cache)
+            fn into_iter(self) -> Self::IntoIter {
+                $ii(self.0.into_iter())
+            }
+        }
+
+        /// Borrowed view of set of RDatas returned from a Lookup
+        pub struct $ii(LookupIntoIter);
+
+        impl Iterator for $ii {
+            type Item = $t;
+
+            fn next(&mut self) -> Option<Self::Item> {
+                let iter: &mut _ = &mut self.0;
+                iter.filter_map(|rdata| match rdata {
+                    $r(data) => Some(data),
+                    _ => None,
+                })
+                .next()
+            }
+        }
+    };
+}
+
+// Generate all Lookup record types
+lookup_type!(
+    ReverseLookup,
+    ReverseLookupIter,
+    ReverseLookupIntoIter,
+    RData::PTR,
+    Name
+);
+lookup_type!(
+    Ipv4Lookup,
+    Ipv4LookupIter,
+    Ipv4LookupIntoIter,
+    RData::A,
+    Ipv4Addr
+);
+lookup_type!(
+    Ipv6Lookup,
+    Ipv6LookupIter,
+    Ipv6LookupIntoIter,
+    RData::AAAA,
+    Ipv6Addr
+);
+lookup_type!(
+    MxLookup,
+    MxLookupIter,
+    MxLookupIntoIter,
+    RData::MX,
+    rdata::MX
+);
+lookup_type!(
+    TxtLookup,
+    TxtLookupIter,
+    TxtLookupIntoIter,
+    RData::TXT,
+    rdata::TXT
+);
+lookup_type!(
+    SoaLookup,
+    SoaLookupIter,
+    SoaLookupIntoIter,
+    RData::SOA,
+    rdata::SOA
+);
+lookup_type!(NsLookup, NsLookupIter, NsLookupIntoIter, RData::NS, Name);
+
+#[cfg(test)]
+pub mod tests {
+    use std::net::{IpAddr, Ipv4Addr};
+    use std::str::FromStr;
+    use std::sync::{Arc, Mutex};
+
+    use futures::executor::block_on;
+    use futures::{future, Future};
+
+    use proto::error::{ProtoErrorKind, ProtoResult};
+    use proto::op::Message;
+    use proto::rr::{Name, RData, Record, RecordType};
+    use proto::xfer::{DnsRequest, DnsRequestOptions};
+
+    use super::*;
+
+    #[derive(Clone)]
+    pub struct MockDnsHandle {
+        messages: Arc<Mutex<Vec<ProtoResult<DnsResponse>>>>,
+    }
+
+    impl DnsHandle for MockDnsHandle {
+        type Response = Pin<Box<dyn Future<Output = Result<DnsResponse, ProtoError>> + Send>>;
+
+        fn send<R: Into<DnsRequest>>(&mut self, _: R) -> Self::Response {
+            future::ready(self.messages.lock().unwrap().pop().unwrap_or_else(empty)).boxed()
+        }
+    }
+
+    pub fn v4_message() -> ProtoResult<DnsResponse> {
+        let mut message = Message::new();
+        message.insert_answers(vec![Record::from_rdata(
+            Name::root(),
+            86400,
+            RData::A(Ipv4Addr::new(127, 0, 0, 1)),
+        )]);
+        Ok(message.into())
+    }
+
+    pub fn empty() -> ProtoResult<DnsResponse> {
+        Ok(Message::new().into())
+    }
+
+    pub fn error() -> ProtoResult<DnsResponse> {
+        Err(ProtoErrorKind::from(std::io::Error::from(std::io::ErrorKind::Other)).into())
+    }
+
+    pub fn mock(messages: Vec<ProtoResult<DnsResponse>>) -> MockDnsHandle {
+        MockDnsHandle {
+            messages: Arc::new(Mutex::new(messages)),
+        }
+    }
+
+    #[test]
+    fn test_lookup() {
+        assert_eq!(
+            block_on(LookupFuture::lookup(
+                vec![Name::root()],
+                RecordType::A,
+                DnsRequestOptions::default(),
+                CachingClient::new(0, mock(vec![v4_message()])),
+            ))
+            .unwrap()
+            .iter()
+            .map(|r| r.to_ip_addr().unwrap())
+            .collect::<Vec<IpAddr>>(),
+            vec![Ipv4Addr::new(127, 0, 0, 1)]
+        );
+    }
+
+    #[test]
+    fn test_lookup_into_iter() {
+        assert_eq!(
+            block_on(LookupFuture::lookup(
+                vec![Name::root()],
+                RecordType::A,
+                DnsRequestOptions::default(),
+                CachingClient::new(0, mock(vec![v4_message()])),
+            ))
+            .unwrap()
+            .into_iter()
+            .map(|r| r.to_ip_addr().unwrap())
+            .collect::<Vec<IpAddr>>(),
+            vec![Ipv4Addr::new(127, 0, 0, 1)]
+        );
+    }
+
+    #[test]
+    fn test_error() {
+        assert!(block_on(LookupFuture::lookup(
+            vec![Name::root()],
+            RecordType::A,
+            DnsRequestOptions::default(),
+            CachingClient::new(0, mock(vec![error()])),
+        ))
+        .is_err());
+    }
+
+    #[test]
+    fn test_empty_no_response() {
+        if let ResolveErrorKind::NoRecordsFound { query, valid_until } =
+            block_on(LookupFuture::lookup(
+                vec![Name::root()],
+                RecordType::A,
+                DnsRequestOptions::default(),
+                CachingClient::new(0, mock(vec![empty()])),
+            ))
+            .unwrap_err()
+            .kind()
+        {
+            assert_eq!(*query, Query::query(Name::root(), RecordType::A));
+            assert_eq!(*valid_until, None);
+        } else {
+            panic!("wrong error recieved");
+        }
+    }
+
+    #[test]
+    fn test_lookup_into_iter_arc() {
+        let mut lookup = LookupIntoIter {
+            records: Err(Arc::new(vec![
+                Record::from_rdata(
+                    Name::from_str("www.example.com.").unwrap(),
+                    80,
+                    RData::A(Ipv4Addr::new(127, 0, 0, 1)),
+                ),
+                Record::from_rdata(
+                    Name::from_str("www.example.com.").unwrap(),
+                    80,
+                    RData::A(Ipv4Addr::new(127, 0, 0, 2)),
+                ),
+            ])),
+            index: 0,
+        };
+
+        assert_eq!(
+            lookup.next().unwrap(),
+            RData::A(Ipv4Addr::new(127, 0, 0, 1))
+        );
+        assert_eq!(
+            lookup.next().unwrap(),
+            RData::A(Ipv4Addr::new(127, 0, 0, 2))
+        );
+        assert_eq!(lookup.next(), None);
+    }
+
+    #[test]
+    fn test_lookup_into_iter_vec() {
+        let mut lookup = LookupIntoIter {
+            records: Ok(vec![
+                Record::from_rdata(
+                    Name::from_str("www.example.com.").unwrap(),
+                    80,
+                    RData::A(Ipv4Addr::new(127, 0, 0, 1)),
+                ),
+                Record::from_rdata(
+                    Name::from_str("www.example.com.").unwrap(),
+                    80,
+                    RData::A(Ipv4Addr::new(127, 0, 0, 2)),
+                ),
+            ]
+            .into_iter()),
+            index: 0,
+        };
+
+        assert_eq!(
+            lookup.next().unwrap(),
+            RData::A(Ipv4Addr::new(127, 0, 0, 1))
+        );
+        assert_eq!(
+            lookup.next().unwrap(),
+            RData::A(Ipv4Addr::new(127, 0, 0, 2))
+        );
+        assert_eq!(lookup.next(), None);
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/src/lookup_ip.rs b/third_party/rust_crates/vendor/trust-dns-resolver/src/lookup_ip.rs
new file mode 100644
index 0000000..8be4ccc
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/src/lookup_ip.rs
@@ -0,0 +1,672 @@
+// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! LookupIp result from a resolution of ipv4 and ipv6 records with a Resolver.
+//!
+//! At it's heart LookupIp uses Lookup for performing all lookups. It is unlike other standard lookups in that there are customizations around A and AAAA resolutions.
+
+use std::net::IpAddr;
+use std::pin::Pin;
+use std::sync::Arc;
+use std::task::{Context, Poll};
+use std::time::Instant;
+
+use futures::{future, future::Either, Future, FutureExt};
+
+use proto::op::Query;
+use proto::rr::{Name, RData, Record, RecordType};
+use proto::xfer::{DnsHandle, DnsRequestOptions};
+
+use crate::config::LookupIpStrategy;
+use crate::dns_lru::MAX_TTL;
+use crate::error::*;
+use crate::hosts::Hosts;
+use crate::lookup::{Lookup, LookupIntoIter, LookupIter};
+use crate::lookup_state::CachingClient;
+
+/// Result of a DNS query when querying for A or AAAA records.
+///
+/// When resolving IP records, there can be many IPs that match a given name. A consumer of this should expect that there are more than a single address potentially returned. Generally there are multiple IPs stored for a given service in DNS so that there is a form of high availability offered for a given name. The service implementation is responsible for the semantics around which IP should be used and when, but in general if a connection fails to one, the next in the list should be attempted.
+#[derive(Debug, Clone)]
+pub struct LookupIp(Lookup);
+
+impl LookupIp {
+    /// Returns a borrowed iterator of the returned IPs
+    pub fn iter(&self) -> LookupIpIter {
+        LookupIpIter(self.0.iter())
+    }
+
+    /// Returns a reference to the `Query` that was used to produce this result.
+    pub fn query(&self) -> &Query {
+        self.0.query()
+    }
+
+    /// Returns the `Instant` at which this lookup is no longer valid.
+    pub fn valid_until(&self) -> Instant {
+        self.0.valid_until()
+    }
+}
+
+impl From<Lookup> for LookupIp {
+    fn from(lookup: Lookup) -> Self {
+        LookupIp(lookup)
+    }
+}
+
+/// Borrowed view of set of IPs returned from a LookupIp
+pub struct LookupIpIter<'i>(pub(crate) LookupIter<'i>);
+
+impl<'i> Iterator for LookupIpIter<'i> {
+    type Item = IpAddr;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let iter: &mut _ = &mut self.0;
+        iter.filter_map(|rdata| match *rdata {
+            RData::A(ip) => Some(IpAddr::from(ip)),
+            RData::AAAA(ip) => Some(IpAddr::from(ip)),
+            _ => None,
+        })
+        .next()
+    }
+}
+
+impl IntoIterator for LookupIp {
+    type Item = IpAddr;
+    type IntoIter = LookupIpIntoIter;
+
+    /// This is most likely not a free conversion, the RDatas will be cloned if data is
+    ///  held behind an Arc with more than one reference (which is most likely the case coming from cache)
+    fn into_iter(self) -> Self::IntoIter {
+        LookupIpIntoIter(self.0.into_iter())
+    }
+}
+
+/// Borrowed view of set of RDatas returned from a Lookup
+pub struct LookupIpIntoIter(LookupIntoIter);
+
+impl Iterator for LookupIpIntoIter {
+    type Item = IpAddr;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let iter: &mut _ = &mut self.0;
+        iter.filter_map(|rdata| match rdata {
+            RData::A(ip) => Some(IpAddr::from(ip)),
+            RData::AAAA(ip) => Some(IpAddr::from(ip)),
+            _ => None,
+        })
+        .next()
+    }
+}
+
+/// The Future returned from [`AsyncResolver`] when performing an A or AAAA lookup.
+///
+/// This type isn't necessarily something that should be used by users, see the default TypeParameters are generally correct
+pub struct LookupIpFuture<C>
+where
+    C: DnsHandle + 'static,
+{
+    client_cache: CachingClient<C>,
+    names: Vec<Name>,
+    strategy: LookupIpStrategy,
+    options: DnsRequestOptions,
+    query: Pin<Box<dyn Future<Output = Result<Lookup, ResolveError>> + Send>>,
+    hosts: Option<Arc<Hosts>>,
+    finally_ip_addr: Option<RData>,
+}
+
+impl<C: DnsHandle + Sync + 'static> Future for LookupIpFuture<C> {
+    type Output = Result<LookupIp, ResolveError>;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+        loop {
+            // Try polling the underlying DNS query.
+            let query = self.query.as_mut().poll(cx);
+
+            // Determine whether or not we will attempt to retry the query.
+            let should_retry = match query {
+                // If the query is NotReady, yield immediately.
+                Poll::Pending => return Poll::Pending,
+                // If the query returned a successful lookup, we will attempt
+                // to retry if the lookup is empty. Otherwise, we will return
+                // that lookup.
+                Poll::Ready(Ok(ref lookup)) => lookup.is_empty(),
+                // If the query failed, we will attempt to retry.
+                Poll::Ready(Err(_)) => true,
+            };
+
+            if should_retry {
+                if let Some(name) = self.names.pop() {
+                    // If there's another name left to try, build a new query
+                    // for that next name and continue looping.
+                    self.query = strategic_lookup(
+                        name,
+                        self.strategy,
+                        self.client_cache.clone(),
+                        self.options.clone(),
+                        self.hosts.clone(),
+                    )
+                    .boxed();
+                    // Continue looping with the new query. It will be polled
+                    // on the next iteration of the loop.
+                    continue;
+                } else if let Some(ip_addr) = self.finally_ip_addr.take() {
+                    // Otherwise, if there's an IP address to fall back to,
+                    // we'll return it.
+                    let record = Record::from_rdata(Name::new(), MAX_TTL, ip_addr);
+                    let lookup = Lookup::new_with_max_ttl(Query::new(), Arc::new(vec![record]));
+                    return Poll::Ready(Ok(lookup.into()));
+                }
+            };
+
+            // If we didn't have to retry the query, or we weren't able to
+            // retry because we've exhausted the names to search and have no
+            // fallback IP address, return the current query.
+            return query.map(|f| f.map(LookupIp::from));
+            // If we skipped retrying the  query, this will return the
+            // successful lookup, otherwise, if the retry failed, this will
+            // return the last  query result --- either an empty lookup or the
+            // last error we saw.
+        }
+    }
+}
+
+impl<C> LookupIpFuture<C>
+where
+    C: DnsHandle + 'static,
+{
+    /// Perform a lookup from a hostname to a set of IPs
+    ///
+    /// # Arguments
+    ///
+    /// * `names` - a set of DNS names to attempt to resolve, they will be attempted in queue order, i.e. the first is `names.pop()`. Upon each failure, the next will be attempted.
+    /// * `strategy` - the lookup IP strategy to use
+    /// * `client_cache` - cache with a connection to use for performing all lookups
+    pub fn lookup(
+        names: Vec<Name>,
+        strategy: LookupIpStrategy,
+        client_cache: CachingClient<C>,
+        options: DnsRequestOptions,
+        hosts: Option<Arc<Hosts>>,
+        finally_ip_addr: Option<RData>,
+    ) -> Self {
+        let empty =
+            ResolveError::from(ResolveErrorKind::Message("can not lookup IPs for no names"));
+        LookupIpFuture {
+            names,
+            strategy,
+            client_cache,
+            // If there are no names remaining, this will be returned immediately,
+            // otherwise, it will be retried.
+            query: future::err(empty).boxed(),
+            options,
+            hosts,
+            finally_ip_addr,
+        }
+    }
+}
+
+/// returns a new future for lookup
+async fn strategic_lookup<C: DnsHandle + 'static>(
+    name: Name,
+    strategy: LookupIpStrategy,
+    client: CachingClient<C>,
+    options: DnsRequestOptions,
+    hosts: Option<Arc<Hosts>>,
+) -> Result<Lookup, ResolveError> {
+    match strategy {
+        LookupIpStrategy::Ipv4Only => ipv4_only(name, client, options, hosts).await,
+        LookupIpStrategy::Ipv6Only => ipv6_only(name, client, options, hosts).await,
+        LookupIpStrategy::Ipv4AndIpv6 => ipv4_and_ipv6(name, client, options, hosts).await,
+        LookupIpStrategy::Ipv6thenIpv4 => ipv6_then_ipv4(name, client, options, hosts).await,
+        LookupIpStrategy::Ipv4thenIpv6 => ipv4_then_ipv6(name, client, options, hosts).await,
+    }
+}
+
+/// first lookups in hosts, then performs the query
+async fn hosts_lookup<C: DnsHandle + 'static>(
+    query: Query,
+    mut client: CachingClient<C>,
+    options: DnsRequestOptions,
+    hosts: Option<Arc<Hosts>>,
+) -> Result<Lookup, ResolveError> {
+    if let Some(hosts) = hosts {
+        if let Some(lookup) = hosts.lookup_static_host(&query) {
+            return Ok(lookup);
+        };
+    }
+
+    client.lookup(query, options).await
+}
+
+/// queries only for A records
+async fn ipv4_only<C: DnsHandle + 'static>(
+    name: Name,
+    client: CachingClient<C>,
+    options: DnsRequestOptions,
+    hosts: Option<Arc<Hosts>>,
+) -> Result<Lookup, ResolveError> {
+    hosts_lookup(Query::query(name, RecordType::A), client, options, hosts).await
+}
+
+/// queries only for AAAA records
+async fn ipv6_only<C: DnsHandle + 'static>(
+    name: Name,
+    client: CachingClient<C>,
+    options: DnsRequestOptions,
+    hosts: Option<Arc<Hosts>>,
+) -> Result<Lookup, ResolveError> {
+    hosts_lookup(Query::query(name, RecordType::AAAA), client, options, hosts).await
+}
+
+// TODO: this really needs to have a stream interface
+/// queries only for A and AAAA in parallel
+async fn ipv4_and_ipv6<C: DnsHandle + 'static>(
+    name: Name,
+    client: CachingClient<C>,
+    options: DnsRequestOptions,
+    hosts: Option<Arc<Hosts>>,
+) -> Result<Lookup, ResolveError> {
+    let sel_res = future::select(
+        hosts_lookup(
+            Query::query(name.clone(), RecordType::A),
+            client.clone(),
+            options.clone(),
+            hosts.clone(),
+        )
+        .boxed(),
+        hosts_lookup(Query::query(name, RecordType::AAAA), client, options, hosts).boxed(),
+    )
+    .await;
+
+    let (ips, remaining_query) = match sel_res {
+        Either::Left(ips_and_remaining) => ips_and_remaining,
+        Either::Right(ips_and_remaining) => ips_and_remaining,
+    };
+
+    let next_ips = remaining_query.await;
+
+    match (ips, next_ips) {
+        (Ok(ips), Ok(next_ips)) => {
+            // TODO: create a LookupIp enum with the ability to chain these together
+            let ips = ips.append(next_ips);
+            Ok(ips)
+        }
+        (Ok(ips), Err(e)) | (Err(e), Ok(ips)) => {
+            debug!(
+                "one of ipv4 or ipv6 lookup failed in ipv4_and_ipv6 strategy: {}",
+                e
+            );
+            Ok(ips)
+        }
+        (Err(e1), Err(e2)) => {
+            debug!(
+                "both of ipv4 or ipv6 lookup failed in ipv4_and_ipv6 strategy e1: {}, e2: {}",
+                e1, e2
+            );
+            Err(e1)
+        }
+    }
+}
+
+/// queries only for AAAA and on no results queries for A
+async fn ipv6_then_ipv4<C: DnsHandle + 'static>(
+    name: Name,
+    client: CachingClient<C>,
+    options: DnsRequestOptions,
+    hosts: Option<Arc<Hosts>>,
+) -> Result<Lookup, ResolveError> {
+    rt_then_swap(
+        name,
+        client,
+        RecordType::AAAA,
+        RecordType::A,
+        options,
+        hosts,
+    )
+    .await
+}
+
+/// queries only for A and on no results queries for AAAA
+async fn ipv4_then_ipv6<C: DnsHandle + 'static>(
+    name: Name,
+    client: CachingClient<C>,
+    options: DnsRequestOptions,
+    hosts: Option<Arc<Hosts>>,
+) -> Result<Lookup, ResolveError> {
+    rt_then_swap(
+        name,
+        client,
+        RecordType::A,
+        RecordType::AAAA,
+        options,
+        hosts,
+    )
+    .await
+}
+
+/// queries only for first_type and on no results queries for second_type
+async fn rt_then_swap<C: DnsHandle + 'static>(
+    name: Name,
+    client: CachingClient<C>,
+    first_type: RecordType,
+    second_type: RecordType,
+    options: DnsRequestOptions,
+    hosts: Option<Arc<Hosts>>,
+) -> Result<Lookup, ResolveError> {
+    let or_client = client.clone();
+    let res = hosts_lookup(
+        Query::query(name.clone(), first_type),
+        client,
+        options.clone(),
+        hosts.clone(),
+    )
+    .await;
+
+    match res {
+        Ok(ips) => {
+            if ips.is_empty() {
+                // no ips returns, NXDomain or Otherwise, doesn't matter
+                hosts_lookup(
+                    Query::query(name.clone(), second_type),
+                    or_client,
+                    options,
+                    hosts,
+                )
+                .await
+            } else {
+                Ok(ips)
+            }
+        }
+        Err(_) => {
+            hosts_lookup(
+                Query::query(name.clone(), second_type),
+                or_client,
+                options,
+                hosts,
+            )
+            .await
+        }
+    }
+}
+
+#[cfg(test)]
+pub mod tests {
+    use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+    use std::sync::{Arc, Mutex};
+
+    use futures::executor::block_on;
+    use futures::{future, Future};
+
+    use proto::error::{ProtoError, ProtoResult};
+    use proto::op::Message;
+    use proto::rr::{Name, RData, Record};
+    use proto::xfer::{DnsHandle, DnsRequest, DnsResponse};
+
+    use super::*;
+
+    #[derive(Clone)]
+    pub struct MockDnsHandle {
+        messages: Arc<Mutex<Vec<ProtoResult<DnsResponse>>>>,
+    }
+
+    impl DnsHandle for MockDnsHandle {
+        type Response =
+            Pin<Box<dyn Future<Output = Result<DnsResponse, ProtoError>> + Send + Unpin>>;
+
+        fn send<R: Into<DnsRequest>>(&mut self, _: R) -> Self::Response {
+            Box::pin(future::ready(
+                self.messages.lock().unwrap().pop().unwrap_or_else(empty),
+            ))
+        }
+    }
+
+    pub fn v4_message() -> ProtoResult<DnsResponse> {
+        let mut message = Message::new();
+        message.insert_answers(vec![Record::from_rdata(
+            Name::root(),
+            86400,
+            RData::A(Ipv4Addr::new(127, 0, 0, 1)),
+        )]);
+        Ok(message.into())
+    }
+
+    pub fn v6_message() -> ProtoResult<DnsResponse> {
+        let mut message = Message::new();
+        message.insert_answers(vec![Record::from_rdata(
+            Name::root(),
+            86400,
+            RData::AAAA(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)),
+        )]);
+        Ok(message.into())
+    }
+
+    pub fn empty() -> ProtoResult<DnsResponse> {
+        Ok(Message::new().into())
+    }
+
+    pub fn error() -> ProtoResult<DnsResponse> {
+        Err(ProtoError::from("forced test failure"))
+    }
+
+    pub fn mock(messages: Vec<ProtoResult<DnsResponse>>) -> MockDnsHandle {
+        MockDnsHandle {
+            messages: Arc::new(Mutex::new(messages)),
+        }
+    }
+
+    #[test]
+    fn test_ipv4_only_strategy() {
+        assert_eq!(
+            block_on(ipv4_only(
+                Name::root(),
+                CachingClient::new(0, mock(vec![v4_message()])),
+                Default::default(),
+                None,
+            ))
+            .unwrap()
+            .iter()
+            .map(|r| r.to_ip_addr().unwrap())
+            .collect::<Vec<IpAddr>>(),
+            vec![Ipv4Addr::new(127, 0, 0, 1)]
+        );
+    }
+
+    #[test]
+    fn test_ipv6_only_strategy() {
+        assert_eq!(
+            block_on(ipv6_only(
+                Name::root(),
+                CachingClient::new(0, mock(vec![v6_message()])),
+                Default::default(),
+                None,
+            ))
+            .unwrap()
+            .iter()
+            .map(|r| r.to_ip_addr().unwrap())
+            .collect::<Vec<IpAddr>>(),
+            vec![Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)]
+        );
+    }
+
+    #[test]
+    fn test_ipv4_and_ipv6_strategy() {
+        // ipv6 is consistently queried first (even though the select has it second)
+        // both succeed
+        assert_eq!(
+            block_on(ipv4_and_ipv6(
+                Name::root(),
+                CachingClient::new(0, mock(vec![v6_message(), v4_message()])),
+                Default::default(),
+                None,
+            ))
+            .unwrap()
+            .iter()
+            .map(|r| r.to_ip_addr().unwrap())
+            .collect::<Vec<IpAddr>>(),
+            vec![
+                IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
+                IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)),
+            ]
+        );
+
+        // only ipv4 available
+        assert_eq!(
+            block_on(ipv4_and_ipv6(
+                Name::root(),
+                CachingClient::new(0, mock(vec![empty(), v4_message()])),
+                Default::default(),
+                None,
+            ))
+            .unwrap()
+            .iter()
+            .map(|r| r.to_ip_addr().unwrap())
+            .collect::<Vec<IpAddr>>(),
+            vec![IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))]
+        );
+
+        // error then ipv4
+        assert_eq!(
+            block_on(ipv4_and_ipv6(
+                Name::root(),
+                CachingClient::new(0, mock(vec![error(), v4_message()])),
+                Default::default(),
+                None,
+            ))
+            .unwrap()
+            .iter()
+            .map(|r| r.to_ip_addr().unwrap())
+            .collect::<Vec<IpAddr>>(),
+            vec![IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))]
+        );
+
+        // only ipv6 available
+        assert_eq!(
+            block_on(ipv4_and_ipv6(
+                Name::root(),
+                CachingClient::new(0, mock(vec![v6_message(), empty()])),
+                Default::default(),
+                None,
+            ))
+            .unwrap()
+            .iter()
+            .map(|r| r.to_ip_addr().unwrap())
+            .collect::<Vec<IpAddr>>(),
+            vec![IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1))]
+        );
+
+        // error, then only ipv6 available
+        assert_eq!(
+            block_on(ipv4_and_ipv6(
+                Name::root(),
+                CachingClient::new(0, mock(vec![v6_message(), error()])),
+                Default::default(),
+                None,
+            ))
+            .unwrap()
+            .iter()
+            .map(|r| r.to_ip_addr().unwrap())
+            .collect::<Vec<IpAddr>>(),
+            vec![IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1))]
+        );
+    }
+
+    #[test]
+    fn test_ipv6_then_ipv4_strategy() {
+        // ipv6 first
+        assert_eq!(
+            block_on(ipv6_then_ipv4(
+                Name::root(),
+                CachingClient::new(0, mock(vec![v6_message()])),
+                Default::default(),
+                None,
+            ))
+            .unwrap()
+            .iter()
+            .map(|r| r.to_ip_addr().unwrap())
+            .collect::<Vec<IpAddr>>(),
+            vec![Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)]
+        );
+
+        // nothing then ipv4
+        assert_eq!(
+            block_on(ipv6_then_ipv4(
+                Name::root(),
+                CachingClient::new(0, mock(vec![v4_message(), empty()])),
+                Default::default(),
+                None,
+            ))
+            .unwrap()
+            .iter()
+            .map(|r| r.to_ip_addr().unwrap())
+            .collect::<Vec<IpAddr>>(),
+            vec![Ipv4Addr::new(127, 0, 0, 1)]
+        );
+
+        // ipv4 and error
+        assert_eq!(
+            block_on(ipv6_then_ipv4(
+                Name::root(),
+                CachingClient::new(0, mock(vec![v4_message(), error()])),
+                Default::default(),
+                None,
+            ))
+            .unwrap()
+            .iter()
+            .map(|r| r.to_ip_addr().unwrap())
+            .collect::<Vec<IpAddr>>(),
+            vec![Ipv4Addr::new(127, 0, 0, 1)]
+        );
+    }
+
+    #[test]
+    fn test_ipv4_then_ipv6_strategy() {
+        // ipv6 first
+        assert_eq!(
+            block_on(ipv4_then_ipv6(
+                Name::root(),
+                CachingClient::new(0, mock(vec![v4_message()])),
+                Default::default(),
+                None,
+            ))
+            .unwrap()
+            .iter()
+            .map(|r| r.to_ip_addr().unwrap())
+            .collect::<Vec<IpAddr>>(),
+            vec![Ipv4Addr::new(127, 0, 0, 1)]
+        );
+
+        // nothing then ipv6
+        assert_eq!(
+            block_on(ipv4_then_ipv6(
+                Name::root(),
+                CachingClient::new(0, mock(vec![v6_message(), empty()])),
+                Default::default(),
+                None,
+            ))
+            .unwrap()
+            .iter()
+            .map(|r| r.to_ip_addr().unwrap())
+            .collect::<Vec<IpAddr>>(),
+            vec![Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)]
+        );
+
+        // error then ipv6
+        assert_eq!(
+            block_on(ipv4_then_ipv6(
+                Name::root(),
+                CachingClient::new(0, mock(vec![v6_message(), error()])),
+                Default::default(),
+                None,
+            ))
+            .unwrap()
+            .iter()
+            .map(|r| r.to_ip_addr().unwrap())
+            .collect::<Vec<IpAddr>>(),
+            vec![Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)]
+        );
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/src/lookup_state.rs b/third_party/rust_crates/vendor/trust-dns-resolver/src/lookup_state.rs
new file mode 100644
index 0000000..84eb2cc
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/src/lookup_state.rs
@@ -0,0 +1,850 @@
+// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! Caching related functionality for the Resolver.
+
+use std::borrow::Cow;
+use std::net::{Ipv4Addr, Ipv6Addr};
+use std::pin::Pin;
+use std::sync::atomic::{AtomicU8, Ordering};
+use std::sync::Arc;
+use std::time::Instant;
+
+use futures::lock::Mutex;
+use futures::{future, Future, FutureExt};
+
+use proto::op::{Message, Query, ResponseCode};
+use proto::rr::domain::usage::{
+    ResolverUsage, DEFAULT, INVALID, IN_ADDR_ARPA_127, IP6_ARPA_1, LOCAL,
+    LOCALHOST as LOCALHOST_usage,
+};
+use proto::rr::{DNSClass, Name, RData, Record, RecordType};
+use proto::xfer::{DnsHandle, DnsRequestOptions, DnsResponse};
+
+use crate::dns_lru;
+use crate::dns_lru::DnsLru;
+use crate::error::*;
+use crate::lookup::Lookup;
+
+const MAX_QUERY_DEPTH: u8 = 8; // arbitrarily chosen number...
+
+lazy_static! {
+    static ref LOCALHOST: RData = RData::PTR(Name::from_ascii("localhost.").unwrap());
+    static ref LOCALHOST_V4: RData = RData::A(Ipv4Addr::new(127, 0, 0, 1));
+    static ref LOCALHOST_V6: RData = RData::AAAA(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
+}
+
+struct DepthTracker {
+    query_depth: Arc<AtomicU8>,
+}
+
+impl DepthTracker {
+    fn track(query_depth: Arc<AtomicU8>) -> Self {
+        query_depth.fetch_add(1, Ordering::Release);
+        Self { query_depth }
+    }
+}
+
+impl Drop for DepthTracker {
+    fn drop(&mut self) {
+        self.query_depth.fetch_sub(1, Ordering::Release);
+    }
+}
+
+// TODO: need to consider this storage type as it compares to Authority in server...
+//       should it just be an variation on Authority?
+#[derive(Clone, Debug)]
+#[doc(hidden)]
+pub struct CachingClient<C: DnsHandle> {
+    lru: Arc<Mutex<DnsLru>>,
+    client: C,
+    query_depth: Arc<AtomicU8>,
+}
+
+impl<C: DnsHandle + Send + 'static> CachingClient<C> {
+    #[doc(hidden)]
+    pub fn new(max_size: usize, client: C) -> Self {
+        Self::with_cache(
+            Arc::new(Mutex::new(DnsLru::new(max_size, Default::default()))),
+            client,
+        )
+    }
+
+    pub(crate) fn with_cache(lru: Arc<Mutex<DnsLru>>, client: C) -> Self {
+        let query_depth = Arc::new(AtomicU8::new(0));
+        CachingClient {
+            lru,
+            client,
+            query_depth,
+        }
+    }
+
+    /// Perform a lookup against this caching client, looking first in the cache for a result
+    pub fn lookup(
+        &mut self,
+        query: Query,
+        options: DnsRequestOptions,
+    ) -> Pin<Box<dyn Future<Output = Result<Lookup, ResolveError>> + Send>> {
+        // see https://tools.ietf.org/html/rfc6761
+        //
+        // ```text
+        // Name resolution APIs and libraries SHOULD recognize localhost
+        // names as special and SHOULD always return the IP loopback address
+        // for address queries and negative responses for all other query
+        // types.  Name resolution APIs SHOULD NOT send queries for
+        // localhost names to their configured caching DNS server(s).
+        // ```
+        //
+        // special use rules only apply to the IN Class
+        if query.query_class() == DNSClass::IN {
+            let usage = match query.name() {
+                n if LOCALHOST_usage.zone_of(n) => &*LOCALHOST_usage,
+                n if IN_ADDR_ARPA_127.zone_of(n) => &*LOCALHOST_usage,
+                n if IP6_ARPA_1.zone_of(n) => &*LOCALHOST_usage,
+                n if INVALID.zone_of(n) => &*INVALID,
+                n if LOCAL.zone_of(n) => &*LOCAL,
+                _ => &*DEFAULT,
+            };
+
+            match usage.resolver() {
+                ResolverUsage::Loopback => match query.query_type() {
+                    // TODO: look in hosts for these ips/names first...
+                    RecordType::A => {
+                        return future::ok(Lookup::from_rdata(query, LOCALHOST_V4.clone())).boxed()
+                    }
+                    RecordType::AAAA => {
+                        return future::ok(Lookup::from_rdata(query, LOCALHOST_V6.clone())).boxed()
+                    }
+                    RecordType::PTR => {
+                        return future::ok(Lookup::from_rdata(query, LOCALHOST.clone())).boxed()
+                    }
+                    _ => return future::err(DnsLru::nx_error(query, None)).boxed(), // Are there any other types we can use?
+                },
+                // when mdns is enabled we will follow a standard query path
+                #[cfg(feature = "mdns")]
+                ResolverUsage::LinkLocal => (),
+                // TODO: this requires additional config, as Kubernetes and other systems misuse the .local. zone.
+                // when mdns is not enabled we will return errors on LinkLocal ("*.local.") names
+                #[cfg(not(feature = "mdns"))]
+                ResolverUsage::LinkLocal => (),
+                ResolverUsage::NxDomain => {
+                    return future::err(DnsLru::nx_error(query, None)).boxed()
+                }
+                ResolverUsage::Normal => (),
+            }
+        }
+
+        Box::pin(Self::inner_lookup(query, options, self.clone()))
+    }
+
+    async fn inner_lookup(
+        query: Query,
+        options: DnsRequestOptions,
+        mut client: Self,
+    ) -> Result<Lookup, ResolveError> {
+        let _tracker = DepthTracker::track(client.query_depth.clone());
+        let is_dnssec = client.client.is_verifying_dnssec();
+
+        // first transition any polling that is needed (mutable refs...)
+        if let Some(cached_lookup) = Self::from_cache(&query, &client.lru).await {
+            return Ok(cached_lookup);
+        };
+
+        let response_message = client.client.lookup(query.clone(), options.clone()).await?;
+
+        // TODO: take all records and cache them?
+        //  if it's DNSSec they must be signed, otherwise?
+        let records = match response_message.response_code() {
+            ResponseCode::NXDomain => Ok(Self::handle_nxdomain(
+                is_dnssec,
+                response_message,
+                false, /* false b/c DNSSec should not cache NXDomain */
+            )),
+            ResponseCode::NoError => {
+                Self::handle_noerror(&mut client, options, is_dnssec, &query, response_message)
+            }
+            r => Err(ResolveErrorKind::Msg(format!("DNS Error: {}", r)).into()),
+        }?;
+
+        // after the request, evaluate if we have additional queries to perform
+        match records {
+            Records::CnameChain {
+                next: future,
+                min_ttl: ttl,
+            } => Self::cname(query, future, &client.lru, ttl).await,
+            records => Self::cache(query, records, &client.lru).await,
+        }
+    }
+
+    /// Check if this query is already cached
+    async fn from_cache(query: &Query, cache: &Mutex<DnsLru>) -> Option<Lookup> {
+        let mut lru = cache.lock().await;
+        lru.get(query, Instant::now())
+    }
+
+    /// See https://tools.ietf.org/html/rfc2308
+    ///
+    /// For now we will regard NXDomain to strictly mean the query failed
+    ///  and a record for the name, regardless of CNAME presence, what have you
+    ///  ultimately does not exist.
+    ///
+    /// This also handles empty responses in the same way. When performing DNSSec enabled queries, we should
+    ///  never enter here, and should never cache unless verified requests.
+    ///
+    /// # Arguments
+    ///
+    /// * `message` - message to extract SOA, etc, from for caching failed requests
+    /// * `valid_nsec` - species that in DNSSec mode, this request is safe to cache
+    fn handle_nxdomain(is_dnssec: bool, mut message: DnsResponse, valid_nsec: bool) -> Records {
+        if valid_nsec || !is_dnssec {
+            //  if there were validated NSEC records
+            let soa = message
+                .take_name_servers()
+                .into_iter()
+                .find(|r| r.rr_type() == RecordType::SOA);
+
+            let ttl = if let Some(RData::SOA(soa)) = soa.map(Record::unwrap_rdata) {
+                Some(soa.minimum())
+            } else {
+                // TODO: figure out a looping lookup to get SOA
+                None
+            };
+
+            Records::NoData { ttl }
+        } else {
+            Records::NoData { ttl: None }
+        }
+    }
+
+    /// Handle the case where there is no error returned
+    fn handle_noerror(
+        client: &mut Self,
+        options: DnsRequestOptions,
+        is_dnssec: bool,
+        query: &Query,
+        mut response: DnsResponse,
+    ) -> Result<Records, ResolveError> {
+        // initial ttl is what CNAMES for min usage
+        const INITIAL_TTL: u32 = dns_lru::MAX_TTL;
+
+        // seek out CNAMES, this is only performed if the query is not a CNAME, ANY, or SRV
+        let (search_name, cname_ttl, was_cname) = {
+            // this will only search for CNAMEs if the request was not meant to be for one of the triggers for recursion
+            let (search_name, cname_ttl, was_cname) =
+                if query.query_type().is_any() || query.query_type().is_cname() {
+                    (Cow::Borrowed(query.name()), INITIAL_TTL, false)
+                } else {
+                    // Folds any cnames from the answers section, into the final cname in the answers section
+                    //   this works by folding the last CNAME found into the final folded result.
+                    //   it assumes that the CNAMEs are in chained order in the DnsResponse Message...
+                    // For SRV, the name added for the search becomes the target name.
+                    //
+                    // TODO: should this include the additionals?
+                    response.messages().flat_map(Message::answers).fold(
+                        (Cow::Borrowed(query.name()), INITIAL_TTL, false),
+                        |(search_name, cname_ttl, was_cname), r| {
+                            match *r.rdata() {
+                                RData::CNAME(ref cname) => {
+                                    // take the minimum TTL of the cname_ttl and the next record in the chain
+                                    let ttl = cname_ttl.min(r.ttl());
+                                    debug_assert_eq!(r.rr_type(), RecordType::CNAME);
+                                    if search_name.as_ref() == r.name() {
+                                        return (Cow::Owned(cname.clone()), ttl, true);
+                                    }
+                                }
+                                RData::SRV(ref srv) => {
+                                    // take the minimum TTL of the cname_ttl and the next record in the chain
+                                    let ttl = cname_ttl.min(r.ttl());
+                                    debug_assert_eq!(r.rr_type(), RecordType::SRV);
+
+                                    // the search name becomes the srv.target
+                                    return (Cow::Owned(srv.target().clone()), ttl, true);
+                                }
+                                _ => (),
+                            }
+
+                            (search_name, cname_ttl, was_cname)
+                        },
+                    )
+                };
+
+            // take all answers. // TODO: following CNAMES?
+            let answers: Vec<Record> = response
+                .messages_mut()
+                .flat_map(Message::take_answers)
+                .collect();
+            let additionals: Vec<Record> = response
+                .messages_mut()
+                .flat_map(Message::take_additionals)
+                .collect();
+
+            // After following all the CNAMES to the last one, try and lookup the final name
+            let records = answers
+                .into_iter()
+                // Chained records will generally exist in the additionals section
+                .chain(additionals.into_iter())
+                .filter_map(|r| {
+                    // because this resolved potentially recursively, we want the min TTL from the chain
+                    let ttl = cname_ttl.min(r.ttl());
+
+                    // TODO: disable name validation with ResolverOpts? glibc feature...
+                    // restrict to the RData type requested
+                    if query.query_class() == r.dns_class() {
+                        // standard evaluation, it's an any type or it's the requested type and the search_name matches
+                        // - or -
+                        // srv evaluation, it's an srv lookup and the srv_search_name/target matches this name
+                        //    and it's an IP
+                        if ((query.query_type().is_any() || query.query_type() == r.rr_type())
+                            && (search_name.as_ref() == r.name() || query.name() == r.name()))
+                            || (query.query_type().is_srv()
+                                && r.rr_type().is_ip_addr()
+                                && search_name.as_ref() == r.name())
+                        {
+                            Some((r, ttl))
+                        } else {
+                            None
+                        }
+                    } else {
+                        None
+                    }
+                })
+                .collect::<Vec<_>>();
+
+            if !records.is_empty() {
+                return Ok(Records::Exists(records));
+            }
+
+            (search_name.into_owned(), cname_ttl, was_cname)
+        };
+
+        // TODO: for SRV records we *could* do an implicit lookup, but, this requires knowing the type of IP desired
+        //    for now, we'll make the API require the user to perform a follow up to the lookups.
+        // It was a CNAME, but not included in the request...
+        if was_cname {
+            let next_query = Query::query(search_name, query.query_type());
+            Ok(Self::next_query(
+                client, options, is_dnssec, next_query, cname_ttl, response,
+            ))
+        } else {
+            // TODO: review See https://tools.ietf.org/html/rfc2308 for NoData section
+            // Note on DNSSec, in secure_client_handle, if verify_nsec fails then the request fails.
+            //   this will mean that no unverified negative caches will make it to this point and be stored
+            Ok(Self::handle_nxdomain(is_dnssec, response, true))
+        }
+    }
+
+    // TODO: merge this with cname
+    fn next_query(
+        client: &mut Self,
+        options: DnsRequestOptions,
+        is_dnssec: bool,
+        query: Query,
+        cname_ttl: u32,
+        message: DnsResponse,
+    ) -> Records {
+        // tracking the depth of our queries, to prevent infinite CNAME recursion
+        if client.query_depth.load(Ordering::Acquire) >= MAX_QUERY_DEPTH {
+            // TODO: This should return an error
+            Self::handle_nxdomain(is_dnssec, message, true)
+        } else {
+            Records::CnameChain {
+                next: client.lookup(query, options),
+                min_ttl: cname_ttl,
+            }
+        }
+    }
+
+    async fn cname(
+        query: Query,
+        future: Pin<Box<dyn Future<Output = Result<Lookup, ResolveError>> + Send>>,
+        cache: &Mutex<DnsLru>,
+        cname_ttl: u32,
+    ) -> Result<Lookup, ResolveError> {
+        // The error state, this query is complete...
+
+        let lookup = future.await?;
+        let mut cache = cache.lock().await;
+
+        Ok(cache.duplicate(query, lookup, cname_ttl, Instant::now()))
+    }
+
+    async fn cache(
+        query: Query,
+        records: Records,
+        cache: &Mutex<DnsLru>,
+    ) -> Result<Lookup, ResolveError> {
+        // The error state, this query is complete...
+        let mut lru = cache.lock().await;
+
+        // this will put this object into an inconsistent state, but no one should call poll again...
+        match records {
+            Records::Exists(rdata) => Ok(lru.insert(query, rdata, Instant::now())),
+            Records::NoData { ttl: Some(ttl) } => Err(lru.negative(query, ttl, Instant::now())),
+            Records::NoData { ttl: None } | Records::CnameChain { .. } => {
+                Err(DnsLru::nx_error(query, None))
+            }
+        }
+    }
+}
+
+enum Records {
+    /// The records exists, a vec of rdata with ttl
+    Exists(Vec<(Record, u32)>),
+    /// Records do not exist, ttl for negative caching
+    NoData { ttl: Option<u32> },
+    /// Future lookup for recursive cname records
+    CnameChain {
+        next: Pin<Box<dyn Future<Output = Result<Lookup, ResolveError>> + Send>>,
+        min_ttl: u32,
+    },
+}
+
+// see also the lookup_tests.rs in integration-tests crate
+#[cfg(test)]
+mod tests {
+    use std::net::*;
+    use std::str::FromStr;
+    use std::time::*;
+
+    use futures::executor::block_on;
+    use proto::error::ProtoResult;
+    use proto::op::{Message, Query};
+    use proto::rr::rdata::SRV;
+    use proto::rr::{Name, Record};
+
+    use super::*;
+    use crate::lookup_ip::tests::*;
+
+    #[test]
+    fn test_empty_cache() {
+        let cache = Arc::new(Mutex::new(DnsLru::new(1, dns_lru::TtlConfig::default())));
+        let client = mock(vec![empty()]);
+        let client = CachingClient::with_cache(cache, client);
+
+        if let ResolveErrorKind::NoRecordsFound { query, valid_until } = block_on(
+            CachingClient::inner_lookup(Query::new(), Default::default(), client),
+        )
+        .unwrap_err()
+        .kind()
+        {
+            assert_eq!(*query, Query::new());
+            assert_eq!(*valid_until, None);
+        } else {
+            panic!("wrong error received")
+        }
+    }
+
+    #[test]
+    fn test_from_cache() {
+        let cache = Arc::new(Mutex::new(DnsLru::new(1, dns_lru::TtlConfig::default())));
+        let query = Query::new();
+        cache.try_lock().unwrap().insert(
+            query.clone(),
+            vec![(
+                Record::from_rdata(
+                    query.name().clone(),
+                    u32::max_value(),
+                    RData::A(Ipv4Addr::new(127, 0, 0, 1)),
+                ),
+                u32::max_value(),
+            )],
+            Instant::now(),
+        );
+
+        let client = mock(vec![empty()]);
+        let client = CachingClient::with_cache(cache, client);
+
+        let ips = block_on(CachingClient::inner_lookup(
+            Query::new(),
+            Default::default(),
+            client,
+        ))
+        .unwrap();
+
+        assert_eq!(
+            ips.iter().cloned().collect::<Vec<_>>(),
+            vec![RData::A(Ipv4Addr::new(127, 0, 0, 1))]
+        );
+    }
+
+    #[test]
+    fn test_no_cache_insert() {
+        let cache = Arc::new(Mutex::new(DnsLru::new(1, dns_lru::TtlConfig::default())));
+        // first should come from client...
+        let client = mock(vec![v4_message()]);
+        let client = CachingClient::with_cache(cache.clone(), client);
+
+        let ips = block_on(CachingClient::inner_lookup(
+            Query::new(),
+            Default::default(),
+            client,
+        ))
+        .unwrap();
+
+        assert_eq!(
+            ips.iter().cloned().collect::<Vec<_>>(),
+            vec![RData::A(Ipv4Addr::new(127, 0, 0, 1))]
+        );
+
+        // next should come from cache...
+        let client = mock(vec![empty()]);
+        let client = CachingClient::with_cache(cache, client);
+
+        let ips = block_on(CachingClient::inner_lookup(
+            Query::new(),
+            Default::default(),
+            client,
+        ))
+        .unwrap();
+
+        assert_eq!(
+            ips.iter().cloned().collect::<Vec<_>>(),
+            vec![RData::A(Ipv4Addr::new(127, 0, 0, 1))]
+        );
+    }
+
+    pub fn cname_message() -> ProtoResult<DnsResponse> {
+        let mut message = Message::new();
+        message.insert_answers(vec![Record::from_rdata(
+            Name::from_str("www.example.com.").unwrap(),
+            86400,
+            RData::CNAME(Name::from_str("actual.example.com.").unwrap()),
+        )]);
+        Ok(message.into())
+    }
+
+    pub fn srv_message() -> ProtoResult<DnsResponse> {
+        let mut message = Message::new();
+        message.insert_answers(vec![Record::from_rdata(
+            Name::from_str("_443._tcp.www.example.com.").unwrap(),
+            86400,
+            RData::SRV(SRV::new(
+                1,
+                2,
+                443,
+                Name::from_str("www.example.com.").unwrap(),
+            )),
+        )]);
+        Ok(message.into())
+    }
+
+    fn no_recursion_on_query_test(query_type: RecordType) {
+        let cache = Arc::new(Mutex::new(DnsLru::new(1, dns_lru::TtlConfig::default())));
+
+        // the cname should succeed, we shouldn't query again after that, which would cause an error...
+        let client = mock(vec![error(), cname_message()]);
+        let client = CachingClient::with_cache(cache, client);
+
+        let ips = block_on(CachingClient::inner_lookup(
+            Query::query(Name::from_str("www.example.com.").unwrap(), query_type),
+            Default::default(),
+            client,
+        ))
+        .expect("lookup failed");
+
+        assert_eq!(
+            ips.iter().cloned().collect::<Vec<_>>(),
+            vec![RData::CNAME(Name::from_str("actual.example.com.").unwrap())]
+        );
+    }
+
+    #[test]
+    fn test_no_recursion_on_cname_query() {
+        no_recursion_on_query_test(RecordType::CNAME);
+    }
+
+    #[test]
+    fn test_no_recursion_on_all_query() {
+        no_recursion_on_query_test(RecordType::ANY);
+    }
+
+    #[test]
+    fn test_non_recursive_srv_query() {
+        let cache = Arc::new(Mutex::new(DnsLru::new(1, dns_lru::TtlConfig::default())));
+
+        // the cname should succeed, we shouldn't query again after that, which would cause an error...
+        let client = mock(vec![error(), srv_message()]);
+        let client = CachingClient::with_cache(cache, client);
+
+        let ips = block_on(CachingClient::inner_lookup(
+            Query::query(
+                Name::from_str("_443._tcp.www.example.com.").unwrap(),
+                RecordType::SRV,
+            ),
+            Default::default(),
+            client,
+        ))
+        .expect("lookup failed");
+
+        assert_eq!(
+            ips.iter().cloned().collect::<Vec<_>>(),
+            vec![RData::SRV(SRV::new(
+                1,
+                2,
+                443,
+                Name::from_str("www.example.com.").unwrap(),
+            ))]
+        );
+    }
+
+    #[test]
+    fn test_single_srv_query_response() {
+        let cache = Arc::new(Mutex::new(DnsLru::new(1, dns_lru::TtlConfig::default())));
+
+        let mut message = srv_message().unwrap();
+        message.add_answer(Record::from_rdata(
+            Name::from_str("www.example.com.").unwrap(),
+            86400,
+            RData::CNAME(Name::from_str("actual.example.com.").unwrap()),
+        ));
+        message.insert_additionals(vec![
+            Record::from_rdata(
+                Name::from_str("actual.example.com.").unwrap(),
+                86400,
+                RData::A(Ipv4Addr::new(127, 0, 0, 1)),
+            ),
+            Record::from_rdata(
+                Name::from_str("actual.example.com.").unwrap(),
+                86400,
+                RData::AAAA(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)),
+            ),
+        ]);
+
+        let client = mock(vec![error(), Ok(message)]);
+        let client = CachingClient::with_cache(cache, client);
+
+        let ips = block_on(CachingClient::inner_lookup(
+            Query::query(
+                Name::from_str("_443._tcp.www.example.com.").unwrap(),
+                RecordType::SRV,
+            ),
+            Default::default(),
+            client,
+        ))
+        .expect("lookup failed");
+
+        assert_eq!(
+            ips.iter().cloned().collect::<Vec<_>>(),
+            vec![
+                RData::SRV(SRV::new(
+                    1,
+                    2,
+                    443,
+                    Name::from_str("www.example.com.").unwrap(),
+                )),
+                RData::A(Ipv4Addr::new(127, 0, 0, 1)),
+                RData::AAAA(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)),
+            ]
+        );
+    }
+
+    // TODO: if we ever enable recursive lookups for SRV, here are the tests...
+    // #[test]
+    // fn test_recursive_srv_query() {
+    //     let cache = Arc::new(Mutex::new(DnsLru::new(1)));
+
+    //     let mut message = Message::new();
+    //     message.add_answer(Record::from_rdata(
+    //         Name::from_str("www.example.com.").unwrap(),
+    //         86400,
+    //         RecordType::CNAME,
+    //         RData::CNAME(Name::from_str("actual.example.com.").unwrap()),
+    //     ));
+    //     message.insert_additionals(vec![
+    //         Record::from_rdata(
+    //             Name::from_str("actual.example.com.").unwrap(),
+    //             86400,
+    //             RecordType::A,
+    //             RData::A(Ipv4Addr::new(127, 0, 0, 1)),
+    //         ),
+    //     ]);
+
+    //     let mut client = mock(vec![error(), Ok(message.into()), srv_message()]);
+
+    //     let ips = QueryState::lookup(
+    //         Query::query(
+    //             Name::from_str("_443._tcp.www.example.com.").unwrap(),
+    //             RecordType::SRV,
+    //         ),
+    //         Default::default(),
+    //         &mut client,
+    //         cache.clone(),
+    //     ).wait()
+    //         .expect("lookup failed");
+
+    //     assert_eq!(
+    //         ips.iter().cloned().collect::<Vec<_>>(),
+    //         vec![
+    //             RData::SRV(SRV::new(
+    //                 1,
+    //                 2,
+    //                 443,
+    //                 Name::from_str("www.example.com.").unwrap(),
+    //             )),
+    //             RData::A(Ipv4Addr::new(127, 0, 0, 1)),
+    //             //RData::AAAA(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)),
+    //         ]
+    //     );
+    // }
+
+    fn cname_ttl_test(first: u32, second: u32) {
+        let lru = Arc::new(Mutex::new(DnsLru::new(1, dns_lru::TtlConfig::default())));
+        // expecting no queries to be performed
+        let mut client = CachingClient::with_cache(Arc::clone(&lru), mock(vec![error()]));
+
+        let mut message = Message::new();
+        message.insert_answers(vec![Record::from_rdata(
+            Name::from_str("ttl.example.com.").unwrap(),
+            first,
+            RData::CNAME(Name::from_str("actual.example.com.").unwrap()),
+        )]);
+        message.insert_additionals(vec![Record::from_rdata(
+            Name::from_str("actual.example.com.").unwrap(),
+            second,
+            RData::A(Ipv4Addr::new(127, 0, 0, 1)),
+        )]);
+
+        let records = CachingClient::handle_noerror(
+            &mut client,
+            Default::default(),
+            false,
+            &Query::query(Name::from_str("ttl.example.com.").unwrap(), RecordType::A),
+            message.into(),
+        );
+
+        if let Ok(records) = records {
+            if let Records::Exists(records) = records {
+                assert!(records.iter().all(|&(_, ttl)| ttl == 1));
+            } else {
+                panic!("records don't exist");
+            }
+        } else {
+            panic!("error getting records");
+        }
+    }
+
+    #[test]
+    fn test_cname_ttl() {
+        cname_ttl_test(1, 2);
+        cname_ttl_test(2, 1);
+    }
+
+    #[test]
+    fn test_early_return_localhost() {
+        let cache = Arc::new(Mutex::new(DnsLru::new(0, dns_lru::TtlConfig::default())));
+        let client = mock(vec![empty()]);
+        let mut client = CachingClient::with_cache(cache, client);
+
+        {
+            let query = Query::query(Name::from_ascii("localhost.").unwrap(), RecordType::A);
+            let lookup = block_on(client.lookup(query.clone(), Default::default()))
+                .expect("should have returned localhost");
+            assert_eq!(lookup.query(), &query);
+            assert_eq!(
+                lookup.iter().cloned().collect::<Vec<_>>(),
+                vec![LOCALHOST_V4.clone()]
+            );
+        }
+
+        {
+            let query = Query::query(Name::from_ascii("localhost.").unwrap(), RecordType::AAAA);
+            let lookup = block_on(client.lookup(query.clone(), Default::default()))
+                .expect("should have returned localhost");
+            assert_eq!(lookup.query(), &query);
+            assert_eq!(
+                lookup.iter().cloned().collect::<Vec<_>>(),
+                vec![LOCALHOST_V6.clone()]
+            );
+        }
+
+        {
+            let query = Query::query(Name::from(Ipv4Addr::new(127, 0, 0, 1)), RecordType::PTR);
+            let lookup = block_on(client.lookup(query.clone(), Default::default()))
+                .expect("should have returned localhost");
+            assert_eq!(lookup.query(), &query);
+            assert_eq!(
+                lookup.iter().cloned().collect::<Vec<_>>(),
+                vec![LOCALHOST.clone()]
+            );
+        }
+
+        {
+            let query = Query::query(
+                Name::from(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)),
+                RecordType::PTR,
+            );
+            let lookup = block_on(client.lookup(query.clone(), Default::default()))
+                .expect("should have returned localhost");
+            assert_eq!(lookup.query(), &query);
+            assert_eq!(
+                lookup.iter().cloned().collect::<Vec<_>>(),
+                vec![LOCALHOST.clone()]
+            );
+        }
+
+        assert!(block_on(client.lookup(
+            Query::query(Name::from_ascii("localhost.").unwrap(), RecordType::MX),
+            Default::default()
+        ))
+        .is_err());
+
+        assert!(block_on(client.lookup(
+            Query::query(Name::from(Ipv4Addr::new(127, 0, 0, 1)), RecordType::MX),
+            Default::default()
+        ))
+        .is_err());
+
+        assert!(block_on(client.lookup(
+            Query::query(
+                Name::from(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)),
+                RecordType::MX
+            ),
+            Default::default()
+        ))
+        .is_err());
+    }
+
+    #[test]
+    fn test_early_return_invalid() {
+        let cache = Arc::new(Mutex::new(DnsLru::new(0, dns_lru::TtlConfig::default())));
+        let client = mock(vec![empty()]);
+        let mut client = CachingClient::with_cache(cache, client);
+
+        assert!(block_on(client.lookup(
+            Query::query(
+                Name::from_ascii("horrible.invalid.").unwrap(),
+                RecordType::A,
+            ),
+            Default::default()
+        ))
+        .is_err());
+    }
+
+    #[test]
+    fn test_no_error_on_dot_local_no_mdns() {
+        let cache = Arc::new(Mutex::new(DnsLru::new(1, dns_lru::TtlConfig::default())));
+
+        let mut message = srv_message().unwrap();
+        message.add_answer(Record::from_rdata(
+            Name::from_str("www.example.local.").unwrap(),
+            86400,
+            RData::A(Ipv4Addr::new(127, 0, 0, 1)),
+        ));
+
+        let client = mock(vec![error(), Ok(message)]);
+        let mut client = CachingClient::with_cache(cache, client);
+
+        assert!(block_on(client.lookup(
+            Query::query(
+                Name::from_ascii("www.example.local.").unwrap(),
+                RecordType::A,
+            ),
+            Default::default()
+        ))
+        .is_ok());
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/src/name_server/connection_provider.rs b/third_party/rust_crates/vendor/trust-dns-resolver/src/name_server/connection_provider.rs
new file mode 100644
index 0000000..621716e
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/src/name_server/connection_provider.rs
@@ -0,0 +1,537 @@
+// Copyright 2015-2019 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+use std::marker::Unpin;
+use std::pin::Pin;
+use std::task::{Context, Poll};
+
+use futures::io::{AsyncRead, AsyncWrite};
+use futures::ready;
+use futures::{Future, FutureExt};
+#[cfg(feature = "tokio-runtime")]
+use tokio::net::TcpStream as TokioTcpStream;
+#[cfg(all(
+    feature = "dns-over-openssl",
+    not(feature = "dns-over-rustls"),
+    not(feature = "dns-over-native-tls")
+))]
+use tokio_openssl::SslStream as TokioTlsStream;
+#[cfg(feature = "dns-over-rustls")]
+use tokio_rustls::client::TlsStream as TokioTlsStream;
+#[cfg(all(feature = "dns-over-native-tls", not(feature = "dns-over-rustls")))]
+use tokio_tls::TlsStream as TokioTlsStream;
+
+use proto;
+use proto::error::ProtoError;
+
+#[cfg(feature = "tokio-runtime")]
+use proto::{iocompat::AsyncIo02As03, TokioTime};
+
+#[cfg(feature = "mdns")]
+use proto::multicast::{MdnsClientConnect, MdnsClientStream, MdnsQueryType};
+
+use proto::op::NoopMessageFinalizer;
+
+use proto::udp::UdpClientStream;
+use proto::udp::UdpResponse;
+use proto::xfer::{
+    DnsExchange, DnsExchangeSend, DnsHandle, DnsMultiplexerSerialResponse, DnsRequest, DnsResponse,
+};
+
+use proto::xfer::{DnsExchangeBackground, DnsMultiplexer};
+
+use proto::{
+    tcp::Connect, tcp::TcpClientConnect, tcp::TcpClientStream, udp::UdpClientConnect,
+    udp::UdpSocket, xfer::DnsExchangeConnect, xfer::DnsMultiplexerConnect, Time,
+};
+
+#[cfg(feature = "dns-over-https")]
+use trust_dns_https::{self, HttpsClientConnect, HttpsClientResponse, HttpsClientStream};
+
+use crate::config::Protocol;
+use crate::config::{NameServerConfig, ResolverOpts};
+
+/// A type to allow for custom ConnectionProviders. Needed mainly for mocking purposes.
+///
+/// ConnectionProvider is responsible for spawning any background tasks as necessary.
+pub trait ConnectionProvider: 'static + Clone + Send + Sync + Unpin {
+    /// The handle to the connect for sending DNS requests.
+    type Conn: DnsHandle + Clone + Send + Sync + 'static;
+
+    /// Ths future is responsible for spawning any background tasks as necessary
+    type FutureConn: Future<Output = Result<Self::Conn, ProtoError>> + Send + 'static;
+
+    /// The returned handle should
+    fn new_connection(&self, config: &NameServerConfig, options: &ResolverOpts)
+        -> Self::FutureConn;
+}
+
+/// A type defines runtime.
+pub trait RuntimeProvider: Clone + 'static {
+    /// Handle to the executor;
+    type Handle: Clone + Send + Spawn + Sync + Unpin;
+
+    /// TcpStream
+    type Tcp: AsyncRead + AsyncWrite + Connect + Send + Unpin;
+
+    /// Timer
+    type Timer: Send + Time + Unpin;
+
+    /// UdpSocket
+    type Udp: Send + UdpSocket;
+}
+
+/// A type defines the Handle which can spawn future.
+pub trait Spawn {
+    fn spawn_bg<F>(&mut self, future: F)
+    where
+        F: Future<Output = Result<(), ProtoError>> + Send + 'static;
+}
+
+/// Standard connection implements the default mechanism for creating new Connections
+#[derive(Clone)]
+pub struct GenericConnectionProvider<R: RuntimeProvider>(R::Handle);
+
+impl<R: RuntimeProvider> GenericConnectionProvider<R> {
+    pub fn new(handle: R::Handle) -> Self {
+        Self(handle)
+    }
+}
+
+impl<R: RuntimeProvider> ConnectionProvider for GenericConnectionProvider<R>
+where
+    <<R as RuntimeProvider>::Tcp as Connect>::Transport: Unpin,
+{
+    type Conn = GenericConnection;
+    type FutureConn = ConnectionFuture<R>;
+
+    /// Constructs an initial constructor for the ConnectionHandle to be used to establish a
+    ///   future connection.
+    fn new_connection(
+        &self,
+        config: &NameServerConfig,
+        options: &ResolverOpts,
+    ) -> Self::FutureConn {
+        let dns_connect = match config.protocol {
+            Protocol::Udp => {
+                let stream =
+                    UdpClientStream::<R::Udp>::with_timeout(config.socket_addr, options.timeout);
+                let exchange = DnsExchange::connect(stream);
+                ConnectionConnect::Udp(exchange)
+            }
+            Protocol::Tcp => {
+                let socket_addr = config.socket_addr;
+                let timeout = options.timeout;
+
+                let (stream, handle) =
+                    TcpClientStream::<R::Tcp>::with_timeout::<R::Timer>(socket_addr, timeout);
+                // TODO: need config for Signer...
+                let dns_conn = DnsMultiplexer::with_timeout(
+                    stream,
+                    handle,
+                    timeout,
+                    NoopMessageFinalizer::new(),
+                );
+
+                let exchange = DnsExchange::connect(dns_conn);
+                ConnectionConnect::Tcp(exchange)
+            }
+            #[cfg(feature = "dns-over-tls")]
+            Protocol::Tls => {
+                let socket_addr = config.socket_addr;
+                let timeout = options.timeout;
+                let tls_dns_name = config.tls_dns_name.clone().unwrap_or_default();
+                #[cfg(feature = "dns-over-rustls")]
+                let client_config = config.tls_config.clone();
+
+                #[cfg(feature = "dns-over-rustls")]
+                let (stream, handle) =
+                    { crate::tls::new_tls_stream(socket_addr, tls_dns_name, client_config) };
+                #[cfg(not(feature = "dns-over-rustls"))]
+                let (stream, handle) = { crate::tls::new_tls_stream(socket_addr, tls_dns_name) };
+
+                let dns_conn = DnsMultiplexer::with_timeout(
+                    stream,
+                    Box::new(handle),
+                    timeout,
+                    NoopMessageFinalizer::new(),
+                );
+
+                let exchange = DnsExchange::connect(dns_conn);
+                ConnectionConnect::Tls(exchange)
+            }
+            #[cfg(feature = "dns-over-https")]
+            Protocol::Https => {
+                let socket_addr = config.socket_addr;
+                let tls_dns_name = config.tls_dns_name.clone().unwrap_or_default();
+                #[cfg(feature = "dns-over-rustls")]
+                let client_config = config.tls_config.clone();
+
+                let exchange =
+                    crate::https::new_https_stream(socket_addr, tls_dns_name, client_config);
+                ConnectionConnect::Https(exchange)
+            }
+            #[cfg(feature = "mdns")]
+            Protocol::Mdns => {
+                let socket_addr = config.socket_addr;
+                let timeout = options.timeout;
+
+                let (stream, handle) =
+                    MdnsClientStream::new(socket_addr, MdnsQueryType::OneShot, None, None, None);
+                // TODO: need config for Signer...
+                let dns_conn = DnsMultiplexer::with_timeout(
+                    stream,
+                    handle,
+                    timeout,
+                    NoopMessageFinalizer::new(),
+                );
+
+                let exchange = DnsExchange::connect(dns_conn);
+                ConnectionConnect::Mdns(exchange)
+            }
+        };
+
+        ConnectionFuture {
+            connect: dns_connect,
+            spawner: self.0.clone(),
+        }
+    }
+}
+
+/// The variants of all supported connections for the Resolver
+#[allow(clippy::large_enum_variant, clippy::type_complexity)]
+pub(crate) enum ConnectionConnect<R: RuntimeProvider>
+where
+    <<R as RuntimeProvider>::Tcp as Connect>::Transport: Unpin,
+{
+    Udp(
+        DnsExchangeConnect<
+            UdpClientConnect<R::Udp>,
+            UdpClientStream<R::Udp>,
+            UdpResponse,
+            R::Timer,
+        >,
+    ),
+    Tcp(
+        DnsExchangeConnect<
+            DnsMultiplexerConnect<
+                TcpClientConnect<<<R as RuntimeProvider>::Tcp as Connect>::Transport>,
+                TcpClientStream<<<R as RuntimeProvider>::Tcp as Connect>::Transport>,
+                NoopMessageFinalizer,
+            >,
+            DnsMultiplexer<
+                TcpClientStream<<<R as RuntimeProvider>::Tcp as Connect>::Transport>,
+                NoopMessageFinalizer,
+            >,
+            DnsMultiplexerSerialResponse,
+            R::Timer,
+        >,
+    ),
+    #[cfg(feature = "dns-over-tls")]
+    Tls(
+        DnsExchangeConnect<
+            DnsMultiplexerConnect<
+                Pin<
+                    Box<
+                        dyn futures::Future<
+                                Output = Result<
+                                    TcpClientStream<AsyncIo02As03<TokioTlsStream<TokioTcpStream>>>,
+                                    ProtoError,
+                                >,
+                            > + Send
+                            + 'static,
+                    >,
+                >,
+                TcpClientStream<AsyncIo02As03<TokioTlsStream<TokioTcpStream>>>,
+                NoopMessageFinalizer,
+            >,
+            DnsMultiplexer<
+                TcpClientStream<AsyncIo02As03<TokioTlsStream<TokioTcpStream>>>,
+                NoopMessageFinalizer,
+            >,
+            DnsMultiplexerSerialResponse,
+            TokioTime,
+        >,
+    ),
+    #[cfg(feature = "dns-over-https")]
+    Https(
+        DnsExchangeConnect<HttpsClientConnect, HttpsClientStream, HttpsClientResponse, TokioTime>,
+    ),
+    #[cfg(feature = "mdns")]
+    Mdns(
+        DnsExchangeConnect<
+            DnsMultiplexerConnect<MdnsClientConnect, MdnsClientStream, NoopMessageFinalizer>,
+            DnsMultiplexer<MdnsClientStream, NoopMessageFinalizer>,
+            DnsMultiplexerSerialResponse,
+            TokioTime,
+        >,
+    ),
+}
+
+/// Resolves to a new Connection
+#[must_use = "futures do nothing unless polled"]
+pub struct ConnectionFuture<R: RuntimeProvider>
+where
+    <<R as RuntimeProvider>::Tcp as Connect>::Transport: Unpin,
+{
+    connect: ConnectionConnect<R>,
+    spawner: R::Handle,
+}
+
+impl<R: RuntimeProvider> Future for ConnectionFuture<R>
+where
+    <<R as RuntimeProvider>::Tcp as Connect>::Transport: Unpin,
+{
+    type Output = Result<GenericConnection, ProtoError>;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+        let (connection, bg) = match &mut self.connect {
+            ConnectionConnect::Udp(ref mut conn) => {
+                let (conn, bg) = ready!(conn.poll_unpin(cx))?;
+                let conn = GenericConnection(ConnectionConnected::Udp(conn));
+                let bg = ConnectionBackground::<R>(ConnectionBackgroundInner::Udp(bg));
+                (conn, bg)
+            }
+            ConnectionConnect::Tcp(ref mut conn) => {
+                let (conn, bg) = ready!(conn.poll_unpin(cx))?;
+                let conn = GenericConnection(ConnectionConnected::Tcp(conn));
+                let bg = ConnectionBackground::<R>(ConnectionBackgroundInner::Tcp(bg));
+                (conn, bg)
+            }
+            #[cfg(feature = "dns-over-tls")]
+            ConnectionConnect::Tls(ref mut conn) => {
+                let (conn, bg) = ready!(conn.poll_unpin(cx))?;
+                let conn = GenericConnection(ConnectionConnected::Tls(conn));
+                let bg = ConnectionBackground::<R>(ConnectionBackgroundInner::Tls(bg));
+                (conn, bg)
+            }
+            #[cfg(feature = "dns-over-https")]
+            ConnectionConnect::Https(ref mut conn) => {
+                let (conn, bg) = ready!(conn.poll_unpin(cx))?;
+                let conn = GenericConnection(ConnectionConnected::Https(conn));
+                let bg = ConnectionBackground::<R>(ConnectionBackgroundInner::Https(bg));
+                (conn, bg)
+            }
+            #[cfg(feature = "mdns")]
+            ConnectionConnect::Mdns(ref mut conn) => {
+                let (conn, bg) = ready!(conn.poll_unpin(cx))?;
+                let conn = GenericConnection(ConnectionConnected::Mdns(conn));
+                let bg = ConnectionBackground::<R>(ConnectionBackgroundInner::Mdns(bg));
+                (conn, bg)
+            }
+        };
+        self.spawner.spawn_bg(Box::pin(bg));
+        //spawn_bg(&self.spawner, bg);
+        Poll::Ready(Ok(connection))
+    }
+}
+
+/// A connected DNS handle
+#[derive(Clone)]
+pub struct GenericConnection(ConnectionConnected);
+
+impl DnsHandle for GenericConnection {
+    type Response = ConnectionResponse;
+
+    fn send<R: Into<DnsRequest> + Unpin + Send + 'static>(&mut self, request: R) -> Self::Response {
+        self.0.send(request)
+    }
+}
+
+/// A representation of an established connection
+#[derive(Clone)]
+enum ConnectionConnected {
+    Udp(DnsExchange<UdpResponse>),
+    Tcp(DnsExchange<DnsMultiplexerSerialResponse>),
+    #[cfg(feature = "dns-over-tls")]
+    Tls(DnsExchange<DnsMultiplexerSerialResponse>),
+    #[cfg(feature = "dns-over-https")]
+    Https(DnsExchange<HttpsClientResponse>),
+    #[cfg(feature = "mdns")]
+    Mdns(DnsExchange<DnsMultiplexerSerialResponse>),
+}
+
+impl DnsHandle for ConnectionConnected {
+    type Response = ConnectionResponse;
+
+    fn send<R: Into<DnsRequest> + Unpin + Send + 'static>(&mut self, request: R) -> Self::Response {
+        let response = match self {
+            ConnectionConnected::Udp(ref mut conn) => {
+                ConnectionResponseInner::Udp(conn.send(request))
+            }
+            ConnectionConnected::Tcp(ref mut conn) => {
+                ConnectionResponseInner::Tcp(conn.send(request))
+            }
+            #[cfg(feature = "dns-over-tls")]
+            ConnectionConnected::Tls(ref mut conn) => {
+                ConnectionResponseInner::Tls(conn.send(request))
+            }
+            #[cfg(feature = "dns-over-https")]
+            ConnectionConnected::Https(ref mut https) => {
+                ConnectionResponseInner::Https(https.send(request))
+            }
+            #[cfg(feature = "mdns")]
+            ConnectionConnected::Mdns(ref mut mdns) => {
+                ConnectionResponseInner::Mdns(mdns.send(request))
+            }
+        };
+
+        ConnectionResponse(response)
+    }
+}
+
+/// A wrapper type to switch over a connection that still needs to be made, or is already established
+#[must_use = "futures do nothing unless polled"]
+enum ConnectionResponseInner {
+    Udp(DnsExchangeSend<UdpResponse>),
+    Tcp(DnsExchangeSend<DnsMultiplexerSerialResponse>),
+    #[cfg(feature = "dns-over-tls")]
+    Tls(DnsExchangeSend<DnsMultiplexerSerialResponse>),
+    #[cfg(feature = "dns-over-https")]
+    Https(DnsExchangeSend<HttpsClientResponse>),
+    #[cfg(feature = "mdns")]
+    Mdns(DnsExchangeSend<DnsMultiplexerSerialResponse>),
+}
+
+impl Future for ConnectionResponseInner {
+    type Output = Result<DnsResponse, proto::error::ProtoError>;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+        use self::ConnectionResponseInner::*;
+
+        trace!("polling response inner");
+        match *self {
+            Udp(ref mut resp) => resp.poll_unpin(cx),
+            Tcp(ref mut resp) => resp.poll_unpin(cx),
+            #[cfg(feature = "dns-over-tls")]
+            Tls(ref mut tls) => tls.poll_unpin(cx),
+            #[cfg(feature = "dns-over-https")]
+            Https(ref mut https) => https.poll_unpin(cx),
+            #[cfg(feature = "mdns")]
+            Mdns(ref mut mdns) => mdns.poll_unpin(cx),
+        }
+    }
+}
+
+/// A future response from a DNS request.
+#[must_use = "futures do nothing unless polled"]
+pub struct ConnectionResponse(ConnectionResponseInner);
+
+impl Future for ConnectionResponse {
+    type Output = Result<DnsResponse, proto::error::ProtoError>;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+        self.0.poll_unpin(cx)
+    }
+}
+
+/// A background task for driving the DNS protocol of the connection
+#[must_use = "futures do nothing unless polled"]
+pub struct ConnectionBackground<R: RuntimeProvider>(ConnectionBackgroundInner<R>)
+where
+    <<R as RuntimeProvider>::Tcp as Connect>::Transport: Unpin;
+
+impl<R: RuntimeProvider> Future for ConnectionBackground<R>
+where
+    <<R as RuntimeProvider>::Tcp as Connect>::Transport: Unpin,
+{
+    type Output = Result<(), ProtoError>;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+        self.0.poll_unpin(cx)
+    }
+}
+
+#[allow(clippy::large_enum_variant)]
+#[allow(clippy::type_complexity)]
+#[must_use = "futures do nothing unless polled"]
+pub(crate) enum ConnectionBackgroundInner<R: RuntimeProvider>
+where
+    <<R as RuntimeProvider>::Tcp as Connect>::Transport: Unpin,
+{
+    Udp(DnsExchangeBackground<UdpClientStream<R::Udp>, UdpResponse, R::Timer>),
+    Tcp(
+        DnsExchangeBackground<
+            DnsMultiplexer<
+                TcpClientStream<<<R as RuntimeProvider>::Tcp as Connect>::Transport>,
+                NoopMessageFinalizer,
+            >,
+            DnsMultiplexerSerialResponse,
+            R::Timer,
+        >,
+    ),
+    #[cfg(feature = "dns-over-tls")]
+    Tls(
+        DnsExchangeBackground<
+            DnsMultiplexer<
+                TcpClientStream<AsyncIo02As03<TokioTlsStream<TokioTcpStream>>>,
+                NoopMessageFinalizer,
+            >,
+            DnsMultiplexerSerialResponse,
+            TokioTime,
+        >,
+    ),
+    #[cfg(feature = "dns-over-https")]
+    Https(DnsExchangeBackground<HttpsClientStream, HttpsClientResponse, TokioTime>),
+    #[cfg(feature = "mdns")]
+    Mdns(
+        DnsExchangeBackground<
+            DnsMultiplexer<MdnsClientStream, NoopMessageFinalizer>,
+            DnsMultiplexerSerialResponse,
+            TokioTime,
+        >,
+    ),
+}
+
+impl<R: RuntimeProvider> Future for ConnectionBackgroundInner<R>
+where
+    <<R as RuntimeProvider>::Tcp as Connect>::Transport: Unpin,
+{
+    type Output = Result<(), ProtoError>;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+        use self::ConnectionBackgroundInner::*;
+
+        trace!("polling response inner");
+        match *self {
+            Udp(ref mut bg) => bg.poll_unpin(cx),
+            Tcp(ref mut bg) => bg.poll_unpin(cx),
+            #[cfg(feature = "dns-over-tls")]
+            Tls(ref mut bg) => bg.poll_unpin(cx),
+            #[cfg(feature = "dns-over-https")]
+            Https(ref mut bg) => bg.poll_unpin(cx),
+            #[cfg(feature = "mdns")]
+            Mdns(ref mut bg) => bg.poll_unpin(cx),
+        }
+    }
+}
+
+#[cfg(feature = "tokio-runtime")]
+pub mod tokio_runtime {
+    use super::*;
+    use tokio::net::UdpSocket as TokioUdpSocket;
+
+    impl Spawn for tokio::runtime::Handle {
+        fn spawn_bg<F>(&mut self, future: F)
+        where
+            F: Future<Output = Result<(), ProtoError>> + Send + 'static,
+        {
+            let _join = self.spawn(future);
+        }
+    }
+
+    #[derive(Clone)]
+    pub struct TokioRuntime;
+    impl RuntimeProvider for TokioRuntime {
+        type Handle = tokio::runtime::Handle;
+        type Tcp = AsyncIo02As03<TokioTcpStream>;
+        type Timer = TokioTime;
+        type Udp = TokioUdpSocket;
+    }
+    pub type TokioConnection = GenericConnection;
+    pub type TokioConnectionProvider = GenericConnectionProvider<TokioRuntime>;
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/src/name_server/mod.rs b/third_party/rust_crates/vendor/trust-dns-resolver/src/name_server/mod.rs
new file mode 100644
index 0000000..73e2f4e
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/src/name_server/mod.rs
@@ -0,0 +1,27 @@
+// Copyright 2015-2019 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+mod connection_provider;
+#[allow(clippy::module_inception)]
+mod name_server;
+mod name_server_pool;
+mod name_server_state;
+mod name_server_stats;
+
+pub use self::connection_provider::{ConnectionProvider, RuntimeProvider, Spawn};
+pub use self::connection_provider::{GenericConnection, GenericConnectionProvider};
+#[cfg(feature = "mdns")]
+pub(crate) use self::name_server::mdns_nameserver;
+pub use self::name_server::NameServer;
+pub use self::name_server_pool::NameServerPool;
+use self::name_server_state::NameServerState;
+use self::name_server_stats::NameServerStats;
+
+#[cfg(feature = "tokio-runtime")]
+pub use self::connection_provider::tokio_runtime::{
+    TokioConnection, TokioConnectionProvider, TokioRuntime,
+};
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/src/name_server/name_server.rs b/third_party/rust_crates/vendor/trust-dns-resolver/src/name_server/name_server.rs
new file mode 100644
index 0000000..3884f7d
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/src/name_server/name_server.rs
@@ -0,0 +1,311 @@
+// Copyright 2015-2019 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+use std::cmp::Ordering;
+use std::fmt::{self, Debug, Formatter};
+use std::pin::Pin;
+use std::sync::Arc;
+use std::time::Instant;
+
+use futures::Future;
+#[cfg(feature = "tokio-runtime")]
+use tokio::runtime::Handle;
+
+use proto::error::{ProtoError, ProtoResult};
+#[cfg(feature = "mdns")]
+use proto::multicast::MDNS_IPV4;
+use proto::op::ResponseCode;
+use proto::xfer::{DnsHandle, DnsRequest, DnsResponse};
+
+#[cfg(feature = "mdns")]
+use crate::config::Protocol;
+use crate::config::{NameServerConfig, ResolverOpts};
+use crate::name_server::{ConnectionProvider, NameServerState, NameServerStats};
+#[cfg(feature = "tokio-runtime")]
+use crate::name_server::{TokioConnection, TokioConnectionProvider};
+
+/// Specifies the details of a remote NameServer used for lookups
+#[derive(Clone)]
+pub struct NameServer<C: DnsHandle + Send, P: ConnectionProvider<Conn = C> + Send> {
+    config: NameServerConfig,
+    options: ResolverOpts,
+    client: Option<C>,
+    state: Arc<NameServerState>,
+    stats: Arc<NameServerStats>,
+    conn_provider: P,
+}
+
+impl<C: DnsHandle, P: ConnectionProvider<Conn = C>> Debug for NameServer<C, P> {
+    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
+        write!(f, "config: {:?}, options: {:?}", self.config, self.options)
+    }
+}
+
+#[cfg(feature = "tokio-runtime")]
+impl NameServer<TokioConnection, TokioConnectionProvider> {
+    pub fn new(config: NameServerConfig, options: ResolverOpts, runtime: Handle) -> Self {
+        Self::new_with_provider(config, options, TokioConnectionProvider::new(runtime))
+    }
+}
+
+impl<C: DnsHandle, P: ConnectionProvider<Conn = C>> NameServer<C, P> {
+    pub fn new_with_provider(
+        config: NameServerConfig,
+        options: ResolverOpts,
+        conn_provider: P,
+    ) -> NameServer<C, P> {
+        NameServer {
+            config,
+            options,
+            client: None,
+            state: Arc::new(NameServerState::init(None)),
+            stats: Arc::new(NameServerStats::default()),
+            conn_provider,
+        }
+    }
+
+    #[doc(hidden)]
+    pub fn from_conn(
+        config: NameServerConfig,
+        options: ResolverOpts,
+        client: C,
+        conn_provider: P,
+    ) -> NameServer<C, P> {
+        NameServer {
+            config,
+            options,
+            client: Some(client),
+            state: Arc::new(NameServerState::init(None)),
+            stats: Arc::new(NameServerStats::default()),
+            conn_provider,
+        }
+    }
+
+    /// This will return a mutable client to allows for sending messages.
+    ///
+    /// If the connection is in a failed state, then this will establish a new connection
+    async fn connected_mut_client(&mut self) -> ProtoResult<&mut C> {
+        // if this is in a failure state
+        if self.state.is_failed() || self.client.is_none() {
+            debug!("reconnecting: {:?}", self.config);
+
+            // TODO: we need the local EDNS options
+            self.state = Arc::new(NameServerState::init(None));
+
+            let client = self
+                .conn_provider
+                .new_connection(&self.config, &self.options)
+                .await?;
+
+            // establish a new connection
+            self.client = Some(client);
+        }
+
+        Ok(self
+            .client
+            .as_mut()
+            .expect("bad state, client should be connected"))
+    }
+
+    async fn inner_send<R: Into<DnsRequest> + Unpin + Send + 'static>(
+        mut self,
+        request: R,
+    ) -> Result<DnsResponse, ProtoError> {
+        let client = self.connected_mut_client().await?;
+        let response = client.send(request).await;
+
+        match response {
+            Ok(response) => {
+                // first we'll evaluate if the message succeeded
+                //   see https://github.com/bluejekyll/trust-dns/issues/606
+                //   TODO: there are probably other return codes from the server we may want to
+                //    retry on. We may also want to evaluate NoError responses that lack records as errors as well
+                if self.options.distrust_nx_responses {
+                    if let ResponseCode::ServFail = response.response_code() {
+                        let note = "Nameserver responded with SERVFAIL";
+                        debug!("{}", note);
+                        return Err(ProtoError::from(note));
+                    }
+                }
+
+                // TODO: consider making message::take_edns...
+                let remote_edns = response.edns().cloned();
+
+                // take the remote edns options and store them
+                self.state.establish(remote_edns);
+
+                // record the success
+                self.stats.next_success();
+                Ok(response)
+            }
+            Err(error) => {
+                debug!("name_server connection failure: {}", error);
+
+                // this transitions the state to failure
+                self.state.fail(Instant::now());
+
+                // record the failure
+                self.stats.next_failure();
+
+                // These are connection failures, not lookup failures, that is handled in the resolver layer
+                Err(error)
+            }
+        }
+    }
+}
+
+impl<C, P> DnsHandle for NameServer<C, P>
+where
+    C: DnsHandle,
+    P: ConnectionProvider<Conn = C>,
+{
+    type Response = Pin<Box<dyn Future<Output = Result<DnsResponse, ProtoError>> + Send>>;
+
+    fn is_verifying_dnssec(&self) -> bool {
+        self.options.validate
+    }
+
+    // TODO: there needs to be some way of customizing the connection based on EDNS options from the server side...
+    fn send<R: Into<DnsRequest> + Unpin + Send + 'static>(&mut self, request: R) -> Self::Response {
+        let this = self.clone();
+        // if state is failed, return future::err(), unless retry delay expired..
+        Box::pin(this.inner_send(request))
+    }
+}
+
+impl<C: DnsHandle, P: ConnectionProvider<Conn = C>> Ord for NameServer<C, P> {
+    /// Custom implementation of Ord for NameServer which incorporates the performance of the connection into it's ranking
+    fn cmp(&self, other: &Self) -> Ordering {
+        // if they are literally equal, just return
+        if self == other {
+            return Ordering::Equal;
+        }
+
+        // otherwise, run our evaluation to determine the next to be returned from the Heap
+        //   this will prefer established connections, we should try other connections after
+        //   some number to make sure that all are used. This is more important for when
+        //   latency is started to be used.
+        match self.state.cmp(&other.state) {
+            Ordering::Equal => (),
+            o => {
+                return o;
+            }
+        }
+
+        self.stats.cmp(&other.stats)
+    }
+}
+
+impl<C: DnsHandle, P: ConnectionProvider<Conn = C>> PartialOrd for NameServer<C, P> {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl<C: DnsHandle, P: ConnectionProvider<Conn = C>> PartialEq for NameServer<C, P> {
+    /// NameServers are equal if the config (connection information) are equal
+    fn eq(&self, other: &Self) -> bool {
+        self.config == other.config
+    }
+}
+
+impl<C: DnsHandle, P: ConnectionProvider<Conn = C>> Eq for NameServer<C, P> {}
+
+// TODO: once IPv6 is better understood, also make this a binary keep.
+#[cfg(feature = "mdns")]
+pub(crate) fn mdns_nameserver<C, P>(options: ResolverOpts, conn_provider: P) -> NameServer<C, P>
+where
+    C: DnsHandle,
+    P: ConnectionProvider<Conn = C>,
+{
+    let config = NameServerConfig {
+        socket_addr: *MDNS_IPV4,
+        protocol: Protocol::Mdns,
+        tls_dns_name: None,
+        #[cfg(feature = "dns-over-rustls")]
+        tls_config: None,
+    };
+    NameServer::new_with_provider(config, options, conn_provider)
+}
+
+#[cfg(test)]
+#[cfg(feature = "tokio-runtime")]
+mod tests {
+    extern crate env_logger;
+
+    use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+    use std::time::Duration;
+
+    use futures::{future, FutureExt};
+    use tokio::runtime::Runtime;
+
+    use proto::op::{Query, ResponseCode};
+    use proto::rr::{Name, RecordType};
+    use proto::xfer::{DnsHandle, DnsRequestOptions};
+
+    use super::*;
+    use crate::config::Protocol;
+
+    #[test]
+    fn test_name_server() {
+        //env_logger::try_init().ok();
+
+        let config = NameServerConfig {
+            socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8)), 53),
+            protocol: Protocol::Udp,
+            tls_dns_name: None,
+            #[cfg(feature = "dns-over-rustls")]
+            tls_config: None,
+        };
+        let mut io_loop = Runtime::new().unwrap();
+        let runtime_handle = io_loop.handle().clone();
+        let name_server = future::lazy(|_| {
+            NameServer::<_, TokioConnectionProvider>::new(
+                config,
+                ResolverOpts::default(),
+                runtime_handle,
+            )
+        });
+
+        let name = Name::parse("www.example.com.", None).unwrap();
+        let response = io_loop
+            .block_on(name_server.then(|mut name_server| {
+                name_server.lookup(
+                    Query::query(name.clone(), RecordType::A),
+                    DnsRequestOptions::default(),
+                )
+            }))
+            .expect("query failed");
+        assert_eq!(response.response_code(), ResponseCode::NoError);
+    }
+
+    #[test]
+    fn test_failed_name_server() {
+        let mut options = ResolverOpts::default();
+        options.timeout = Duration::from_millis(1); // this is going to fail, make it fail fast...
+        let config = NameServerConfig {
+            socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 252)), 252),
+            protocol: Protocol::Udp,
+            tls_dns_name: None,
+            #[cfg(feature = "dns-over-rustls")]
+            tls_config: None,
+        };
+        let mut io_loop = Runtime::new().unwrap();
+        let runtime_handle = io_loop.handle().clone();
+        let name_server = future::lazy(|_| {
+            NameServer::<_, TokioConnectionProvider>::new(config, options, runtime_handle)
+        });
+
+        let name = Name::parse("www.example.com.", None).unwrap();
+        assert!(io_loop
+            .block_on(name_server.then(|mut name_server| name_server.lookup(
+                Query::query(name.clone(), RecordType::A),
+                DnsRequestOptions::default()
+            )))
+            .is_err());
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/src/name_server/name_server_pool.rs b/third_party/rust_crates/vendor/trust-dns-resolver/src/name_server/name_server_pool.rs
new file mode 100644
index 0000000..5e356fa
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/src/name_server/name_server_pool.rs
@@ -0,0 +1,418 @@
+// Copyright 2015-2019 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+use std::pin::Pin;
+use std::sync::Arc;
+use std::task::{Context, Poll};
+
+use futures::{future, Future, TryFutureExt};
+use smallvec::SmallVec;
+#[cfg(test)]
+#[cfg(feature = "tokio-runtime")]
+use tokio::runtime::Handle;
+
+use proto::error::ProtoError;
+use proto::op::ResponseCode;
+use proto::xfer::{DnsHandle, DnsRequest, DnsResponse};
+
+use crate::config::{ResolverConfig, ResolverOpts};
+#[cfg(feature = "mdns")]
+use crate::name_server;
+use crate::name_server::{ConnectionProvider, NameServer};
+#[cfg(test)]
+#[cfg(feature = "tokio-runtime")]
+use crate::name_server::{TokioConnection, TokioConnectionProvider};
+
+/// A pool of NameServers
+///
+/// This is not expected to be used directly, see [`AsyncResolver`].
+#[derive(Clone)]
+pub struct NameServerPool<
+    C: DnsHandle + Send + Sync + 'static,
+    P: ConnectionProvider<Conn = C> + Send + 'static,
+> {
+    // TODO: switch to FuturesMutex (Mutex will have some undesireable locking)
+    datagram_conns: Arc<Vec<NameServer<C, P>>>, /* All NameServers must be the same type */
+    stream_conns: Arc<Vec<NameServer<C, P>>>,   /* All NameServers must be the same type */
+    #[cfg(feature = "mdns")]
+    mdns_conns: NameServer<C, P>, /* All NameServers must be the same type */
+    options: ResolverOpts,
+    conn_provider: P,
+}
+
+#[cfg(test)]
+#[cfg(feature = "tokio-runtime")]
+impl NameServerPool<TokioConnection, TokioConnectionProvider> {
+    pub(crate) fn from_config(
+        config: &ResolverConfig,
+        options: &ResolverOpts,
+        runtime: Handle,
+    ) -> Self {
+        Self::from_config_with_provider(config, options, TokioConnectionProvider::new(runtime))
+    }
+}
+
+impl<C: DnsHandle + Sync + 'static, P: ConnectionProvider<Conn = C> + 'static>
+    NameServerPool<C, P>
+{
+    pub(crate) fn from_config_with_provider(
+        config: &ResolverConfig,
+        options: &ResolverOpts,
+        conn_provider: P,
+    ) -> NameServerPool<C, P> {
+        let datagram_conns: Vec<NameServer<C, P>> = config
+            .name_servers()
+            .iter()
+            .filter(|ns_config| ns_config.protocol.is_datagram())
+            .map(|ns_config| {
+                #[cfg(feature = "dns-over-rustls")]
+                let ns_config = {
+                    let mut ns_config = ns_config.clone();
+                    ns_config.tls_config = config.client_config().clone();
+                    ns_config
+                };
+                #[cfg(not(feature = "dns-over-rustls"))]
+                let ns_config = { ns_config.clone() };
+
+                NameServer::<C, P>::new_with_provider(ns_config, *options, conn_provider.clone())
+            })
+            .collect();
+
+        let stream_conns: Vec<NameServer<C, P>> = config
+            .name_servers()
+            .iter()
+            .filter(|ns_config| ns_config.protocol.is_stream())
+            .map(|ns_config| {
+                #[cfg(feature = "dns-over-rustls")]
+                let ns_config = {
+                    let mut ns_config = ns_config.clone();
+                    ns_config.tls_config = config.client_config().clone();
+                    ns_config
+                };
+                #[cfg(not(feature = "dns-over-rustls"))]
+                let ns_config = { ns_config.clone() };
+
+                NameServer::<C, P>::new_with_provider(ns_config, *options, conn_provider.clone())
+            })
+            .collect();
+
+        NameServerPool {
+            datagram_conns: Arc::new(datagram_conns),
+            stream_conns: Arc::new(stream_conns),
+            #[cfg(feature = "mdns")]
+            mdns_conns: name_server::mdns_nameserver(*options, conn_provider.clone()),
+            options: *options,
+            conn_provider,
+        }
+    }
+
+    #[doc(hidden)]
+    #[cfg(not(feature = "mdns"))]
+    pub fn from_nameservers(
+        options: &ResolverOpts,
+        datagram_conns: Vec<NameServer<C, P>>,
+        stream_conns: Vec<NameServer<C, P>>,
+        conn_provider: P,
+    ) -> Self {
+        NameServerPool {
+            datagram_conns: Arc::new(datagram_conns.into_iter().collect()),
+            stream_conns: Arc::new(stream_conns.into_iter().collect()),
+            options: *options,
+            conn_provider,
+        }
+    }
+
+    #[doc(hidden)]
+    #[cfg(feature = "mdns")]
+    pub fn from_nameservers(
+        options: &ResolverOpts,
+        datagram_conns: Vec<NameServer<C, P>>,
+        stream_conns: Vec<NameServer<C, P>>,
+        mdns_conns: NameServer<C, P>,
+        conn_provider: P,
+    ) -> Self {
+        NameServerPool {
+            datagram_conns: Arc::new(datagram_conns.into_iter().collect()),
+            stream_conns: Arc::new(stream_conns.into_iter().collect()),
+            mdns_conns,
+            options: *options,
+            conn_provider,
+        }
+    }
+
+    async fn try_send(
+        opts: ResolverOpts,
+        conns: Arc<Vec<NameServer<C, P>>>,
+        request: DnsRequest,
+    ) -> Result<DnsResponse, ProtoError> {
+        let mut conns: Vec<NameServer<C, P>> = conns.to_vec();
+
+        // select the highest priority connection
+        //   reorder the connections based on current view...
+        //   this reorders the inner set
+        conns.sort_unstable();
+        let request_loop = request.clone();
+
+        parallel_conn_loop(conns, request_loop, opts).await
+    }
+}
+
+impl<C, P> DnsHandle for NameServerPool<C, P>
+where
+    C: DnsHandle + Sync + 'static,
+    P: ConnectionProvider<Conn = C> + 'static,
+{
+    type Response = Pin<Box<dyn Future<Output = Result<DnsResponse, ProtoError>> + Send>>;
+
+    fn send<R: Into<DnsRequest>>(&mut self, request: R) -> Self::Response {
+        let opts = self.options;
+        let request = request.into();
+        let datagram_conns = Arc::clone(&self.datagram_conns);
+        let stream_conns1 = Arc::clone(&self.stream_conns);
+        let stream_conns2 = Arc::clone(&self.stream_conns);
+        // TODO: remove this clone, return the Message in the error?
+        let tcp_message1 = request.clone();
+        let tcp_message2 = request.clone();
+
+        // if it's a .local. query, then we *only* query mDNS, these should never be sent on to upstream resolvers
+        #[cfg(feature = "mdns")]
+        let mdns = mdns::maybe_local(&mut self.mdns_conns, request);
+
+        // TODO: limited to only when mDNS is enabled, but this should probably always be enforced?
+        #[cfg(not(feature = "mdns"))]
+        let mdns = Local::NotMdns(request);
+
+        // local queries are queried through mDNS
+        if mdns.is_local() {
+            return mdns.take_future();
+        }
+
+        // TODO: should we allow mDNS to be used for standard lookups as well?
+
+        // it wasn't a local query, continue with standard lookup path
+        let request = mdns.take_request();
+
+        debug!("sending request: {:?}", request.queries());
+        // First try the UDP connections
+        Box::pin(
+            Self::try_send(opts, datagram_conns, request)
+                .and_then(move |response| {
+                    // handling promotion from datagram to stream base on truncation in message
+                    if ResponseCode::NoError == response.response_code() && response.truncated() {
+                        // TCP connections should not truncate
+                        future::Either::Left(Self::try_send(opts, stream_conns1, tcp_message1))
+                    } else {
+                        debug!("mDNS responsed for query: {:?}", response.response_code());
+                        // Return the result from the UDP connection
+                        future::Either::Right(future::ok(response))
+                    }
+                })
+                // if UDP fails, try TCP
+                .or_else(move |_| Self::try_send(opts, stream_conns2, tcp_message2)),
+        )
+    }
+}
+
+// TODO: we should be able to have a self-referential future here with Pin and not require cloned conns
+/// An async function that will loop over all the conns with a max parallel request count of ops.num_concurrent_req
+async fn parallel_conn_loop<C, P>(
+    mut conns: Vec<NameServer<C, P>>,
+    request: DnsRequest,
+    opts: ResolverOpts,
+) -> Result<DnsResponse, ProtoError>
+where
+    C: DnsHandle + 'static,
+    P: ConnectionProvider<Conn = C> + 'static,
+{
+    let mut err = ProtoError::from("No connections available");
+
+    loop {
+        let request_cont = request.clone();
+
+        // construct the parallel requests, 2 is the default
+        let mut par_conns = SmallVec::<[NameServer<C, P>; 2]>::new();
+        let count = conns.len().min(opts.num_concurrent_reqs.max(1));
+        for conn in conns.drain(..count) {
+            par_conns.push(conn);
+        }
+
+        // construct the requests to send
+        let requests = if par_conns.is_empty() {
+            return Err(err);
+        } else {
+            par_conns
+                .into_iter()
+                .map(move |mut conn| conn.send(request_cont.clone()))
+        };
+
+        match future::select_ok(requests).await {
+            Ok((sent, _)) => return Ok(sent),
+            // consider a debug msg here
+            Err(e) => {
+                err = e;
+                continue;
+            }
+        };
+    }
+}
+
+#[cfg(feature = "mdns")]
+mod mdns {
+    use super::*;
+
+    use proto::rr::domain::usage;
+    use proto::DnsHandle;
+
+    /// Returns true
+    pub fn maybe_local<C, P>(name_server: &mut NameServer<C, P>, request: DnsRequest) -> Local
+    where
+        C: DnsHandle + 'static,
+        P: ConnectionProvider<Conn = C> + 'static,
+        P: ConnectionProvider,
+    {
+        if request
+            .queries()
+            .iter()
+            .any(|query| usage::LOCAL.name().zone_of(query.name()))
+        {
+            Local::ResolveFuture(name_server.send(request))
+        } else {
+            Local::NotMdns(request)
+        }
+    }
+}
+
+pub enum Local {
+    #[allow(dead_code)]
+    ResolveFuture(Pin<Box<dyn Future<Output = Result<DnsResponse, ProtoError>> + Send>>),
+    NotMdns(DnsRequest),
+}
+
+impl Local {
+    fn is_local(&self) -> bool {
+        if let Local::ResolveFuture(..) = *self {
+            true
+        } else {
+            false
+        }
+    }
+
+    /// Takes the future
+    ///
+    /// # Panics
+    ///
+    /// Panics if this is in fact a Local::NotMdns
+    fn take_future(self) -> Pin<Box<dyn Future<Output = Result<DnsResponse, ProtoError>> + Send>> {
+        match self {
+            Local::ResolveFuture(future) => future,
+            _ => panic!("non Local queries have no future, see take_message()"),
+        }
+    }
+
+    /// Takes the message
+    ///
+    /// # Panics
+    ///
+    /// Panics if this is in fact a Local::ResolveFuture
+    fn take_request(self) -> DnsRequest {
+        match self {
+            Local::NotMdns(request) => request,
+            _ => panic!("Local queries must be polled, see take_future()"),
+        }
+    }
+}
+
+impl Future for Local {
+    type Output = Result<DnsResponse, ProtoError>;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+        match *self {
+            Local::ResolveFuture(ref mut ns) => ns.as_mut().poll(cx),
+            // TODO: making this a panic for now
+            Local::NotMdns(..) => panic!("Local queries that are not mDNS should not be polled"), //Local::NotMdns(message) => return Err(ResolveErrorKind::Message("not mDNS")),
+        }
+    }
+}
+
+#[cfg(test)]
+#[cfg(feature = "tokio-runtime")]
+mod tests {
+    extern crate env_logger;
+
+    use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+
+    use tokio::runtime::Runtime;
+
+    use proto::op::Query;
+    use proto::rr::{Name, RecordType};
+    use proto::xfer::{DnsHandle, DnsRequestOptions};
+
+    use super::*;
+    use crate::config::NameServerConfig;
+    use crate::config::Protocol;
+
+    #[ignore]
+    // because of there is a real connection that needs a reasonable timeout
+    #[test]
+    fn test_failed_then_success_pool() {
+        let config1 = NameServerConfig {
+            socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 252)), 253),
+            protocol: Protocol::Udp,
+            tls_dns_name: None,
+            #[cfg(feature = "dns-over-rustls")]
+            tls_config: None,
+        };
+
+        let config2 = NameServerConfig {
+            socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8)), 53),
+            protocol: Protocol::Udp,
+            tls_dns_name: None,
+            #[cfg(feature = "dns-over-rustls")]
+            tls_config: None,
+        };
+
+        let mut resolver_config = ResolverConfig::new();
+        resolver_config.add_name_server(config1);
+        resolver_config.add_name_server(config2);
+
+        let mut io_loop = Runtime::new().unwrap();
+        let mut pool = NameServerPool::<_, TokioConnectionProvider>::from_config(
+            &resolver_config,
+            &ResolverOpts::default(),
+            io_loop.handle().clone(),
+        );
+
+        let name = Name::parse("www.example.com.", None).unwrap();
+
+        // TODO: it's not clear why there are two failures before the success
+        for i in 0..2 {
+            assert!(
+                io_loop
+                    .block_on(pool.lookup(
+                        Query::query(name.clone(), RecordType::A),
+                        DnsRequestOptions::default()
+                    ))
+                    .is_err(),
+                "iter: {}",
+                i
+            );
+        }
+
+        for i in 0..10 {
+            assert!(
+                io_loop
+                    .block_on(pool.lookup(
+                        Query::query(name.clone(), RecordType::A),
+                        DnsRequestOptions::default()
+                    ))
+                    .is_ok(),
+                "iter: {}",
+                i
+            );
+        }
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/src/name_server/name_server_state.rs b/third_party/rust_crates/vendor/trust-dns-resolver/src/name_server/name_server_state.rs
new file mode 100644
index 0000000..6d7c617
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/src/name_server/name_server_state.rs
@@ -0,0 +1,161 @@
+// Copyright 2015-2019 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+use std::cmp::Ordering;
+use std::sync::RwLock;
+use std::time::Instant;
+
+use proto::op::Edns;
+
+pub struct NameServerState(RwLock<NameServerStateInner>);
+
+/// State of a connection with a remote NameServer.
+#[derive(Debug)]
+enum NameServerStateInner {
+    /// Initial state, if Edns is not none, then Edns will be requested
+    Init { send_edns: Option<Edns> },
+    /// There has been successful communication with the remote.
+    ///  if no Edns is associated, then the remote does not support Edns
+    Established { remote_edns: Option<Edns> },
+    /// For some reason the connection failed. For UDP this would generally be a timeout
+    ///  for TCP this could be either Connection could never be established, or it
+    ///  failed at some point after. The Failed state should *not* be entered due to an
+    ///  error contained in a Message received from the server. In All cases to reestablish
+    ///  a new connection will need to be created.
+    Failed { when: Instant },
+}
+
+impl NameServerStateInner {
+    /// used for ordering purposes. The highest priority is placed on open connections
+    fn to_usize(&self) -> usize {
+        match *self {
+            NameServerStateInner::Init { .. } => 2,
+            NameServerStateInner::Established { .. } => 3,
+            NameServerStateInner::Failed { .. } => 1,
+        }
+    }
+}
+
+impl NameServerState {
+    /// Set at the new Init state
+    ///
+    /// If send_dns is some, this will be sent on the first request when it is established
+    pub fn init(send_edns: Option<Edns>) -> Self {
+        NameServerState(RwLock::new(NameServerStateInner::Init { send_edns }))
+    }
+
+    /// Transition to the Established state
+    ///
+    /// If remote_edns is Some, then it will be used to effect things like buffer sizes based on
+    ///   the remote's support.
+    pub fn establish(&self, remote_edns: Option<Edns>) {
+        let mut state = self.0.write().expect("poisoned lock");
+        *state = NameServerStateInner::Established { remote_edns };
+    }
+
+    /// transition to the Failed state
+    ///
+    /// when is the time of the failure
+    pub fn fail(&self, when: Instant) {
+        let mut state = self.0.write().expect("poisoned lock");
+        *state = NameServerStateInner::Failed { when };
+    }
+
+    /// True if this is in the Failed state
+    pub(crate) fn is_failed(&self) -> bool {
+        if let NameServerStateInner::Failed { .. } = *self.0.read().expect("poisoned lock") {
+            true
+        } else {
+            false
+        }
+    }
+}
+
+impl Ord for NameServerStateInner {
+    fn cmp(&self, other: &Self) -> Ordering {
+        let (self_num, other_num) = (self.to_usize(), other.to_usize());
+        match self_num.cmp(&other_num) {
+            Ordering::Equal => match (self, other) {
+                (
+                    NameServerStateInner::Failed {
+                        when: ref self_when,
+                    },
+                    NameServerStateInner::Failed {
+                        when: ref other_when,
+                    },
+                ) => {
+                    // We reverse, because we want the "older" failures to be tried first...
+                    self_when.cmp(other_when).reverse()
+                }
+                _ => Ordering::Equal,
+            },
+            cmp => cmp,
+        }
+    }
+}
+
+impl PartialOrd for NameServerStateInner {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl PartialEq for NameServerStateInner {
+    fn eq(&self, other: &Self) -> bool {
+        self.to_usize() == other.to_usize()
+    }
+}
+
+impl Eq for NameServerStateInner {}
+
+impl Ord for NameServerState {
+    fn cmp(&self, other: &Self) -> Ordering {
+        let other = other.0.read().expect("other poisoned");
+        self.0.read().expect("self poisoned").cmp(&*other)
+    }
+}
+
+impl PartialOrd for NameServerState {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl PartialEq for NameServerState {
+    fn eq(&self, other: &Self) -> bool {
+        self.0.read().expect("self poisoned").to_usize()
+            == other.0.read().expect("self poisoned").to_usize()
+    }
+}
+
+impl Eq for NameServerState {}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::name_server::NameServerState;
+
+    #[test]
+    fn test_state_cmp() {
+        let init = NameServerState::init(None);
+
+        let established = NameServerState(RwLock::new(NameServerStateInner::Established {
+            remote_edns: None,
+        }));
+
+        let failed = NameServerState(RwLock::new(NameServerStateInner::Failed {
+            when: Instant::now(),
+        }));
+
+        assert_eq!(init.cmp(&init), Ordering::Equal);
+        assert_eq!(init.cmp(&established), Ordering::Less);
+        assert_eq!(init.cmp(&failed), Ordering::Greater);
+        assert_eq!(established.cmp(&established), Ordering::Equal);
+        assert_eq!(established.cmp(&failed), Ordering::Greater);
+        assert_eq!(failed.cmp(&failed), Ordering::Equal);
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/src/name_server/name_server_stats.rs b/third_party/rust_crates/vendor/trust-dns-resolver/src/name_server/name_server_stats.rs
new file mode 100644
index 0000000..0da0aaa
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/src/name_server/name_server_stats.rs
@@ -0,0 +1,132 @@
+// Copyright 2015-2019 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+use std::cmp::Ordering;
+
+use std::sync::atomic::{self, AtomicUsize};
+
+pub(crate) struct NameServerStats {
+    successes: AtomicUsize,
+    failures: AtomicUsize,
+    // TODO: incorporate latency
+}
+
+impl Default for NameServerStats {
+    fn default() -> Self {
+        Self::new(0, 0)
+    }
+}
+
+impl NameServerStats {
+    pub fn new(successes: usize, failures: usize) -> Self {
+        NameServerStats {
+            successes: AtomicUsize::new(successes),
+            failures: AtomicUsize::new(failures),
+        }
+    }
+
+    pub fn next_success(&self) {
+        self.successes.fetch_add(1, atomic::Ordering::Release);
+    }
+
+    pub fn next_failure(&self) {
+        self.failures.fetch_add(1, atomic::Ordering::Release);
+    }
+
+    fn noload_eq(
+        self_successes: usize,
+        other_successes: usize,
+        self_failures: usize,
+        other_failures: usize,
+    ) -> bool {
+        self_successes == other_successes && self_failures == other_failures
+    }
+}
+
+impl PartialEq for NameServerStats {
+    fn eq(&self, other: &Self) -> bool {
+        let self_successes = self.successes.load(atomic::Ordering::Acquire);
+        let other_successes = other.successes.load(atomic::Ordering::Acquire);
+
+        let self_failures = self.failures.load(atomic::Ordering::Acquire);
+        let other_failures = other.failures.load(atomic::Ordering::Acquire);
+
+        // if they are literally equal, just return
+        Self::noload_eq(
+            self_successes,
+            other_successes,
+            self_failures,
+            other_failures,
+        )
+    }
+}
+
+impl Eq for NameServerStats {}
+
+impl Ord for NameServerStats {
+    /// Custom implementation of Ord for NameServer which incorporates the performance of the connection into it's ranking
+    fn cmp(&self, other: &Self) -> Ordering {
+        let self_successes = self.successes.load(atomic::Ordering::Acquire);
+        let other_successes = other.successes.load(atomic::Ordering::Acquire);
+
+        let self_failures = self.failures.load(atomic::Ordering::Acquire);
+        let other_failures = other.failures.load(atomic::Ordering::Acquire);
+
+        // if they are literally equal, just return
+        if Self::noload_eq(
+            self_successes,
+            other_successes,
+            self_failures,
+            other_failures,
+        ) {
+            return Ordering::Equal;
+        }
+
+        // TODO: track latency and use lowest latency connection...
+
+        // invert failure comparison, i.e. the one with the least failures, wins
+        if self_failures <= other_failures {
+            return Ordering::Greater;
+        }
+
+        // at this point we'll go with the lesser of successes to make sure there is balance
+        self_successes.cmp(&other_successes)
+    }
+}
+
+impl PartialOrd for NameServerStats {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    extern crate env_logger;
+
+    use super::*;
+
+    fn is_send_sync<S: Sync + Send>() -> bool {
+        true
+    }
+
+    #[test]
+    fn stats_are_sync() {
+        assert!(is_send_sync::<NameServerStats>());
+    }
+
+    #[test]
+    fn test_state_cmp() {
+        let nil = NameServerStats::new(0, 0);
+        let successes = NameServerStats::new(1, 0);
+        let failures = NameServerStats::new(0, 1);
+
+        assert_eq!(nil.cmp(&nil), Ordering::Equal);
+        assert_eq!(nil.cmp(&successes), Ordering::Greater);
+        assert_eq!(successes.cmp(&failures), Ordering::Greater);
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/src/resolver.rs b/third_party/rust_crates/vendor/trust-dns-resolver/src/resolver.rs
new file mode 100644
index 0000000..adfdcdf
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/src/resolver.rs
@@ -0,0 +1,211 @@
+// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! Structs for creating and using a Resolver
+use std::io;
+use std::net::IpAddr;
+use std::sync::Mutex;
+
+use proto::rr::RecordType;
+use tokio::runtime::{self, Runtime};
+
+use crate::config::{ResolverConfig, ResolverOpts};
+use crate::error::*;
+use crate::lookup;
+use crate::lookup::Lookup;
+use crate::lookup_ip::LookupIp;
+use crate::name_server::{TokioConnection, TokioConnectionProvider};
+use crate::AsyncResolver;
+
+/// The Resolver is used for performing DNS queries.
+///
+/// For forward (A) lookups, hostname -> IP address, see: `Resolver::lookup_ip`
+///
+/// Special note about resource consumption. The Resolver and all Trust-DNS software is built around the Tokio async-io library. This synchronous Resolver is intended to be a simpler wrapper for of the [`AsyncResolver`]. To allow the `Resolver` to be [`Send`] + [`Sync`], the construction of the `AsyncResolver` is lazy, this means some of the features of the `AsyncResolver`, like performance based resolution via the most efficient `NameServer` will be lost (the lookup cache is shared across invocations of the `Resolver`). If these other features of the Trust-DNS Resolver are desired, please use the tokio based [`AsyncResolver`].
+///
+/// *Note: Threaded/Sync usage*: In multithreaded scenarios, the internal Tokio Runtime will block on an internal Mutex for the tokio Runtime in use. For higher performance, it's recommended to use the [`AsyncResolver`].
+pub struct Resolver {
+    // TODO: Mutex allows this to be Sync, another option would be to instantiate a thread_local, but that has other
+    //   drawbacks. One major issues, is if this Resolver is shared across threads, it will cause all to block on any
+    //   query. A TLS on the other hand would not, at the cost of only allowing a Resolver to be configured once per Thread
+    runtime: Mutex<Runtime>,
+    async_resolver: AsyncResolver<TokioConnection, TokioConnectionProvider>,
+}
+
+macro_rules! lookup_fn {
+    ($p:ident, $l:ty) => {
+/// Performs a lookup for the associated type.
+///
+/// *hint* queries that end with a '.' are fully qualified names and are cheaper lookups
+///
+/// # Arguments
+///
+/// * `query` - a `&str` which parses to a domain name, failure to parse will return an error
+pub fn $p(&self, query: &str) -> ResolveResult<$l> {
+    let lookup = self.async_resolver.$p(query);
+    self.runtime.lock()?.block_on(lookup)
+}
+    };
+    ($p:ident, $l:ty, $t:ty) => {
+/// Performs a lookup for the associated type.
+///
+/// # Arguments
+///
+/// * `query` - a type which can be converted to `Name` via `From`.
+pub fn $p(&self, query: $t) -> ResolveResult<$l> {
+    let lookup = self.async_resolver.$p(query);
+    self.runtime.lock()?.block_on(lookup)
+}
+    };
+}
+
+impl Resolver {
+    /// Constructs a new Resolver with the specified configuration.
+    ///
+    /// # Arguments
+    /// * `config` - configuration for the resolver
+    /// * `options` - resolver options for performing lookups
+    ///
+    /// # Returns
+    ///
+    /// A new `Resolver` or an error if there was an error with the configuration.
+    pub fn new(config: ResolverConfig, options: ResolverOpts) -> io::Result<Self> {
+        let mut builder = runtime::Builder::new();
+        builder.basic_scheduler();
+        builder.enable_all();
+
+        let mut runtime = builder.build()?;
+        let async_resolver = AsyncResolver::new(config, options, runtime.handle().clone());
+        let async_resolver = runtime
+            .block_on(async_resolver)
+            .expect("failed to create resolver");
+
+        Ok(Resolver {
+            runtime: Mutex::new(runtime),
+            async_resolver,
+        })
+    }
+
+    /// Constructs a new Resolver with default config and default options.
+    ///
+    /// See [`ResolverConfig::default`] and [`ResolverOpts::default`] for more information.
+    ///
+    /// # Returns
+    ///
+    /// A new `Resolver` or an error if there was an error with the configuration.
+    pub fn default() -> io::Result<Self> {
+        Self::new(ResolverConfig::default(), ResolverOpts::default())
+    }
+
+    /// Constructs a new Resolver with the system configuration.
+    ///
+    /// This will use `/etc/resolv.conf` on Unix OSes and the registry on Windows.
+    #[cfg(any(unix, target_os = "windows"))]
+    #[cfg(feature = "system-config")]
+    pub fn from_system_conf() -> io::Result<Self> {
+        let (config, options) = super::system_conf::read_system_conf()?;
+        Self::new(config, options)
+    }
+
+    /// Generic lookup for any RecordType
+    ///
+    /// *WARNING* This interface may change in the future, please use [`Self::lookup_ip`] or another variant for more stable interfaces.
+    ///
+    /// # Arguments
+    ///
+    /// * `name` - name of the record to lookup, if name is not a valid domain name, an error will be returned
+    /// * `record_type` - type of record to lookup
+    pub fn lookup(&self, name: &str, record_type: RecordType) -> ResolveResult<Lookup> {
+        let lookup = self
+            .async_resolver
+            .lookup(name, record_type, Default::default());
+        self.runtime.lock()?.block_on(lookup)
+    }
+
+    /// Performs a dual-stack DNS lookup for the IP for the given hostname.
+    ///
+    /// See the configuration and options parameters for controlling the way in which A(Ipv4) and AAAA(Ipv6) lookups will be performed. For the least expensive query a fully-qualified-domain-name, FQDN, which ends in a final `.`, e.g. `www.example.com.`, will only issue one query. Anything else will always incur the cost of querying the `ResolverConfig::domain` and `ResolverConfig::search`.
+    ///
+    /// # Arguments
+    ///
+    /// * `host` - string hostname, if this is an invalid hostname, an error will be returned.
+    pub fn lookup_ip(&self, host: &str) -> ResolveResult<LookupIp> {
+        let lookup = self.async_resolver.lookup_ip(host);
+        self.runtime.lock()?.block_on(lookup)
+    }
+
+    lookup_fn!(reverse_lookup, lookup::ReverseLookup, IpAddr);
+    lookup_fn!(ipv4_lookup, lookup::Ipv4Lookup);
+    lookup_fn!(ipv6_lookup, lookup::Ipv6Lookup);
+    lookup_fn!(mx_lookup, lookup::MxLookup);
+    lookup_fn!(ns_lookup, lookup::NsLookup);
+    lookup_fn!(soa_lookup, lookup::SoaLookup);
+    lookup_fn!(srv_lookup, lookup::SrvLookup);
+    lookup_fn!(txt_lookup, lookup::TxtLookup);
+}
+
+#[cfg(test)]
+mod tests {
+    #![allow(clippy::dbg_macro, clippy::print_stdout)]
+
+    use std::net::*;
+
+    use super::*;
+
+    fn require_send_sync<S: Send + Sync>() {}
+
+    #[test]
+    fn test_resolver_sendable() {
+        require_send_sync::<Resolver>();
+    }
+
+    #[test]
+    fn test_lookup() {
+        let resolver = Resolver::new(ResolverConfig::default(), ResolverOpts::default()).unwrap();
+
+        let response = resolver.lookup_ip("www.example.com.").unwrap();
+        println!("response records: {:?}", response);
+
+        assert_eq!(response.iter().count(), 1);
+        for address in response.iter() {
+            if address.is_ipv4() {
+                assert_eq!(address, IpAddr::V4(Ipv4Addr::new(93, 184, 216, 34)));
+            } else {
+                assert_eq!(
+                    address,
+                    IpAddr::V6(Ipv6Addr::new(
+                        0x2606, 0x2800, 0x220, 0x1, 0x248, 0x1893, 0x25c8, 0x1946,
+                    ))
+                );
+            }
+        }
+    }
+
+    #[test]
+    #[ignore]
+    #[cfg(any(unix, target_os = "windows"))]
+    fn test_system_lookup() {
+        let resolver = Resolver::from_system_conf().unwrap();
+
+        let response = resolver.lookup_ip("www.example.com.").unwrap();
+        println!("response records: {:?}", response);
+
+        assert_eq!(response.iter().count(), 1);
+        for address in response.iter() {
+            if address.is_ipv4() {
+                assert_eq!(address, IpAddr::V4(Ipv4Addr::new(93, 184, 216, 34)));
+            } else {
+                assert_eq!(
+                    address,
+                    IpAddr::V6(Ipv6Addr::new(
+                        0x2606, 0x2800, 0x220, 0x1, 0x248, 0x1893, 0x25c8, 0x1946,
+                    ))
+                );
+            }
+        }
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/src/system_conf/mod.rs b/third_party/rust_crates/vendor/trust-dns-resolver/src/system_conf/mod.rs
new file mode 100644
index 0000000..a76b95f
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/src/system_conf/mod.rs
@@ -0,0 +1,29 @@
+// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! System configuration loading
+//!
+//! This module is responsible for parsing and returning the configuration from
+//!  the host system. It will read from the default location on each operating
+//!  system, e.g. most Unixes have this written to `/etc/resolv.conf`
+#![allow(missing_docs, unused_extern_crates)]
+
+#[cfg(unix)]
+#[cfg(feature = "system-config")]
+mod unix;
+
+#[cfg(unix)]
+#[cfg(feature = "system-config")]
+pub use self::unix::read_system_conf;
+
+#[cfg(windows)]
+#[cfg(feature = "system-config")]
+mod windows;
+
+#[cfg(target_os = "windows")]
+#[cfg(feature = "system-config")]
+pub use self::windows::read_system_conf;
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/src/system_conf/unix.rs b/third_party/rust_crates/vendor/trust-dns-resolver/src/system_conf/unix.rs
new file mode 100644
index 0000000..eb6092e
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/src/system_conf/unix.rs
@@ -0,0 +1,185 @@
+// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! System configuration loading
+//!
+//! This module is responsible for parsing and returning the configuration from
+//!  the host system. It will read from the default location on each operating
+//!  system, e.g. most Unixes have this written to `/etc/resolv.conf`
+
+use std::fs::File;
+use std::io;
+use std::io::Read;
+use std::net::SocketAddr;
+use std::path::Path;
+use std::str::FromStr;
+use std::time::Duration;
+
+use resolv_conf;
+
+use crate::config::*;
+use crate::proto::rr::Name;
+
+const DEFAULT_PORT: u16 = 53;
+
+pub fn read_system_conf() -> io::Result<(ResolverConfig, ResolverOpts)> {
+    Ok(read_resolv_conf("/etc/resolv.conf")?)
+}
+
+fn read_resolv_conf<P: AsRef<Path>>(path: P) -> io::Result<(ResolverConfig, ResolverOpts)> {
+    let mut data = String::new();
+    let mut file = File::open(path)?;
+    file.read_to_string(&mut data)?;
+    parse_resolv_conf(&data)
+}
+
+fn parse_resolv_conf<T: AsRef<[u8]>>(data: T) -> io::Result<(ResolverConfig, ResolverOpts)> {
+    let parsed_conf = resolv_conf::Config::parse(&data).map_err(|e| {
+        io::Error::new(
+            io::ErrorKind::Other,
+            format!("Error parsing resolv.conf: {:?}", e),
+        )
+    })?;
+    into_resolver_config(parsed_conf)
+}
+
+// TODO: use a custom parsing error type maybe?
+fn into_resolver_config(
+    parsed_config: resolv_conf::Config,
+) -> io::Result<(ResolverConfig, ResolverOpts)> {
+    let domain = if let Some(domain) = parsed_config.get_system_domain() {
+        Some(Name::from_str(domain.as_str())?)
+    } else {
+        None
+    };
+
+    // nameservers
+    let mut nameservers = Vec::<NameServerConfig>::with_capacity(parsed_config.nameservers.len());
+    for ip in &parsed_config.nameservers {
+        nameservers.push(NameServerConfig {
+            socket_addr: SocketAddr::new(ip.into(), DEFAULT_PORT),
+            protocol: Protocol::Udp,
+            tls_dns_name: None,
+            #[cfg(feature = "dns-over-rustls")]
+            tls_config: None,
+        });
+        nameservers.push(NameServerConfig {
+            socket_addr: SocketAddr::new(ip.into(), DEFAULT_PORT),
+            protocol: Protocol::Tcp,
+            tls_dns_name: None,
+            #[cfg(feature = "dns-over-rustls")]
+            tls_config: None,
+        });
+    }
+    if nameservers.is_empty() {
+        warn!("no nameservers found in config");
+    }
+
+    // search
+    let mut search = vec![];
+    for search_domain in parsed_config.get_last_search_or_domain() {
+        search.push(Name::from_str_relaxed(&search_domain).map_err(|e| {
+            io::Error::new(
+                io::ErrorKind::Other,
+                format!("Error parsing resolv.conf: {:?}", e),
+            )
+        })?);
+    }
+
+    let config = ResolverConfig::from_parts(domain, search, nameservers);
+
+    let mut options = ResolverOpts::default();
+    options.ndots = parsed_config.ndots as usize;
+    options.timeout = Duration::from_secs(u64::from(parsed_config.timeout));
+    options.attempts = parsed_config.attempts as usize;
+
+    Ok((config, options))
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use proto::rr::Name;
+    use std::env;
+    use std::net::*;
+    use std::str::FromStr;
+
+    fn empty_config() -> ResolverConfig {
+        ResolverConfig::from_parts(None, vec![], vec![])
+    }
+
+    fn nameserver_config(ip: &str) -> [NameServerConfig; 2] {
+        let addr = SocketAddr::new(IpAddr::from_str(ip).unwrap(), 53);
+        [
+            NameServerConfig {
+                socket_addr: addr,
+                protocol: Protocol::Udp,
+                tls_dns_name: None,
+                #[cfg(feature = "dns-over-rustls")]
+                tls_config: None,
+            },
+            NameServerConfig {
+                socket_addr: addr,
+                protocol: Protocol::Tcp,
+                tls_dns_name: None,
+                #[cfg(feature = "dns-over-rustls")]
+                tls_config: None,
+            },
+        ]
+    }
+
+    fn tests_dir() -> String {
+        let server_path = env::var("TDNS_WORKSPACE_ROOT").unwrap_or_else(|_| "../..".to_owned());
+        format!("{}/crates/resolver/tests", server_path)
+    }
+
+    #[test]
+    #[allow(clippy::redundant_clone)]
+    fn test_name_server() {
+        let parsed = parse_resolv_conf("nameserver 127.0.0.1").expect("failed");
+        let mut cfg = empty_config();
+        let nameservers = nameserver_config("127.0.0.1");
+        cfg.add_name_server(nameservers[0].clone());
+        cfg.add_name_server(nameservers[1].clone());
+        assert_eq!(cfg.name_servers(), parsed.0.name_servers());
+        assert_eq!(ResolverOpts::default(), parsed.1);
+    }
+
+    #[test]
+    fn test_search() {
+        let parsed = parse_resolv_conf("search localnet.").expect("failed");
+        let mut cfg = empty_config();
+        cfg.add_search(Name::from_str("localnet.").unwrap());
+        assert_eq!(cfg.search(), parsed.0.search());
+        assert_eq!(ResolverOpts::default(), parsed.1);
+    }
+
+    #[test]
+    fn test_underscore_in_search() {
+        let parsed = parse_resolv_conf("search Speedport_000").expect("failed");
+        let mut cfg = empty_config();
+        cfg.add_search(Name::from_str_relaxed("Speedport_000.").unwrap());
+        assert_eq!(cfg.search(), parsed.0.search());
+        assert_eq!(ResolverOpts::default(), parsed.1);
+    }
+
+    #[test]
+    fn test_domain() {
+        let parsed = parse_resolv_conf("domain example.com").expect("failed");
+        let mut cfg = empty_config();
+        cfg.set_domain(Name::from_str("example.com").unwrap());
+        assert_eq!(cfg, parsed.0);
+        assert_eq!(ResolverOpts::default(), parsed.1);
+    }
+
+    #[test]
+    fn test_read_resolv_conf() {
+        read_resolv_conf(format!("{}/resolv.conf-simple", tests_dir())).expect("simple failed");
+        read_resolv_conf(format!("{}/resolv.conf-macos", tests_dir())).expect("macos failed");
+        read_resolv_conf(format!("{}/resolv.conf-linux", tests_dir())).expect("linux failed");
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/src/system_conf/windows.rs b/third_party/rust_crates/vendor/trust-dns-resolver/src/system_conf/windows.rs
new file mode 100644
index 0000000..d04842b
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/src/system_conf/windows.rs
@@ -0,0 +1,71 @@
+// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! System configuration loading for windows
+
+use std::net::SocketAddr;
+use std::str::FromStr;
+
+use ipconfig::computer::{get_domain, get_search_list, is_round_robin_enabled};
+use ipconfig::get_adapters;
+
+use proto::rr::Name;
+
+use crate::config::{NameServerConfig, Protocol, ResolverConfig, ResolverOpts};
+use crate::error::*;
+
+/// Returns the name servers of the computer (of all adapters)
+fn get_name_servers() -> ResolveResult<Vec<NameServerConfig>> {
+    let adapters = get_adapters()?;
+    let mut name_servers = vec![];
+
+    for dns_server in adapters
+        .iter()
+        .flat_map(|adapter| adapter.dns_servers().iter())
+    {
+        let socket_addr = SocketAddr::new(*dns_server, 53);
+        name_servers.push(NameServerConfig {
+            socket_addr,
+            protocol: Protocol::Udp,
+            tls_dns_name: None,
+            #[cfg(feature = "dns-over-rustls")]
+            tls_config: None,
+        });
+        name_servers.push(NameServerConfig {
+            socket_addr,
+            protocol: Protocol::Tcp,
+            tls_dns_name: None,
+            #[cfg(feature = "dns-over-rustls")]
+            tls_config: None,
+        });
+    }
+    Ok(name_servers)
+}
+
+pub fn read_system_conf() -> ResolveResult<(ResolverConfig, ResolverOpts)> {
+    let name_servers = get_name_servers()?;
+
+    let search_list: Vec<Name> = get_search_list()?
+        .iter()
+        .map(|x| Name::from_str(x))
+        .collect::<Result<Vec<_>, _>>()?;
+
+    let domain = match get_domain()? {
+        Some(domain) => Name::from_str(&domain)?,
+        None => Name::root(),
+    };
+
+    let config = ResolverConfig::from_parts(Some(domain), search_list, name_servers);
+
+    let rotate = is_round_robin_enabled()?;
+
+    let opts = ResolverOpts {
+        rotate,
+        ..Default::default()
+    };
+    Ok((config, opts))
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/src/tls/dns_over_native_tls.rs b/third_party/rust_crates/vendor/trust-dns-resolver/src/tls/dns_over_native_tls.rs
new file mode 100644
index 0000000..e66cb9a
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/src/tls/dns_over_native_tls.rs
@@ -0,0 +1,30 @@
+// Copyright 2015-2018 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+#![cfg(feature = "dns-over-native-tls")]
+#![allow(dead_code)]
+
+use std::net::SocketAddr;
+use std::pin::Pin;
+
+use futures::Future;
+
+use proto::error::ProtoError;
+use proto::BufDnsStreamHandle;
+use trust_dns_native_tls::{TlsClientStream, TlsClientStreamBuilder};
+
+#[allow(clippy::type_complexity)]
+pub(crate) fn new_tls_stream(
+    socket_addr: SocketAddr,
+    dns_name: String,
+) -> (
+    Pin<Box<dyn Future<Output = Result<TlsClientStream, ProtoError>> + Send>>,
+    BufDnsStreamHandle,
+) {
+    let tls_builder = TlsClientStreamBuilder::new();
+    tls_builder.build(socket_addr, dns_name)
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/src/tls/dns_over_openssl.rs b/third_party/rust_crates/vendor/trust-dns-resolver/src/tls/dns_over_openssl.rs
new file mode 100644
index 0000000..75799e5
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/src/tls/dns_over_openssl.rs
@@ -0,0 +1,30 @@
+// Copyright 2015-2018 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+#![cfg(feature = "dns-over-openssl")]
+#![allow(dead_code)]
+
+use std::net::SocketAddr;
+use std::pin::Pin;
+
+use futures::Future;
+
+use proto::error::ProtoError;
+use proto::BufDnsStreamHandle;
+use trust_dns_openssl::{TlsClientStream, TlsClientStreamBuilder};
+
+#[allow(clippy::type_complexity)]
+pub(crate) fn new_tls_stream(
+    socket_addr: SocketAddr,
+    dns_name: String,
+) -> (
+    Pin<Box<dyn Future<Output = Result<TlsClientStream, ProtoError>> + Send>>,
+    BufDnsStreamHandle,
+) {
+    let tls_builder = TlsClientStreamBuilder::new();
+    tls_builder.build(socket_addr, dns_name)
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/src/tls/dns_over_rustls.rs b/third_party/rust_crates/vendor/trust-dns-resolver/src/tls/dns_over_rustls.rs
new file mode 100644
index 0000000..3178b0b
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/src/tls/dns_over_rustls.rs
@@ -0,0 +1,60 @@
+// Copyright 2015-2018 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+#![cfg(feature = "dns-over-rustls")]
+#![allow(dead_code)]
+
+extern crate rustls;
+extern crate webpki_roots;
+
+use std::net::SocketAddr;
+use std::pin::Pin;
+use std::sync::Arc;
+
+use self::rustls::{ClientConfig, ProtocolVersion, RootCertStore};
+use futures::Future;
+
+use proto::error::ProtoError;
+use proto::BufDnsStreamHandle;
+use trust_dns_rustls::{tls_client_connect, TlsClientStream};
+
+use crate::config::TlsClientConfig;
+
+const ALPN_H2: &[u8] = b"h2";
+
+lazy_static! {
+    // using the mozilla default root store
+    pub(crate) static ref CLIENT_CONFIG: Arc<ClientConfig> = {
+        let mut root_store = RootCertStore::empty();
+        root_store.add_server_trust_anchors(&self::webpki_roots::TLS_SERVER_ROOTS);
+        let versions = vec![ProtocolVersion::TLSv1_2];
+
+        let mut client_config = ClientConfig::new();
+        client_config.root_store = root_store;
+        client_config.versions = versions;
+        client_config.alpn_protocols.push(ALPN_H2.to_vec());
+
+        Arc::new(client_config)
+    };
+}
+
+#[allow(clippy::type_complexity)]
+pub(crate) fn new_tls_stream(
+    socket_addr: SocketAddr,
+    dns_name: String,
+    client_config: Option<TlsClientConfig>,
+) -> (
+    Pin<Box<dyn Future<Output = Result<TlsClientStream, ProtoError>> + Send>>,
+    BufDnsStreamHandle,
+) {
+    let client_config = client_config.map_or_else(
+        || CLIENT_CONFIG.clone(),
+        |TlsClientConfig(client_config)| client_config,
+    );
+    let (stream, handle) = tls_client_connect(socket_addr, dns_name, client_config);
+    (Box::pin(stream), handle)
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/src/tls/mod.rs b/third_party/rust_crates/vendor/trust-dns-resolver/src/tls/mod.rs
new file mode 100644
index 0000000..9f81d03
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/src/tls/mod.rs
@@ -0,0 +1,77 @@
+// Copyright 2015-2018 Benjamin Fry <benjaminfry@me.com>
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+#![cfg(feature = "dns-over-tls")]
+
+mod dns_over_native_tls;
+mod dns_over_openssl;
+mod dns_over_rustls;
+
+cfg_if! {
+    if #[cfg(feature = "dns-over-rustls")] {
+        pub(crate) use self::dns_over_rustls::{new_tls_stream, CLIENT_CONFIG};
+    } else if #[cfg(feature = "dns-over-native-tls")] {
+        pub(crate) use self::dns_over_native_tls::new_tls_stream;
+    } else if #[cfg(feature = "dns-over-openssl")] {
+        pub(crate) use self::dns_over_openssl::new_tls_stream;
+    } else {
+        compile_error!("One of the dns-over-rustls, dns-over-native-tls, or dns-over-openssl must be enabled for dns-over-tls features");
+    }
+}
+
+#[cfg(any(feature = "dns-over-native-tls", feature = "dns-over-rustls"))]
+#[cfg(test)]
+mod tests {
+    extern crate env_logger;
+    use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+
+    use tokio::runtime::Runtime;
+
+    use crate::config::{ResolverConfig, ResolverOpts};
+    use crate::TokioAsyncResolver;
+
+    fn tls_test(config: ResolverConfig) {
+        //env_logger::try_init().ok();
+        let mut io_loop = Runtime::new().unwrap();
+
+        let resolver =
+            TokioAsyncResolver::new(config, ResolverOpts::default(), io_loop.handle().clone());
+        let resolver = io_loop
+            .block_on(resolver)
+            .expect("failed to create resolver");
+
+        let response = io_loop
+            .block_on(resolver.lookup_ip("www.example.com."))
+            .expect("failed to run lookup");
+
+        assert_eq!(response.iter().count(), 1);
+        for address in response.iter() {
+            if address.is_ipv4() {
+                assert_eq!(address, IpAddr::V4(Ipv4Addr::new(93, 184, 216, 34)));
+            } else {
+                assert_eq!(
+                    address,
+                    IpAddr::V6(Ipv6Addr::new(
+                        0x2606, 0x2800, 0x220, 0x1, 0x248, 0x1893, 0x25c8, 0x1946,
+                    ))
+                );
+            }
+        }
+    }
+
+    #[test]
+    #[cfg(not(windows))] // flakes on AppVeyor...
+    fn test_cloudflare_tls() {
+        tls_test(ResolverConfig::cloudflare_tls())
+    }
+
+    #[test]
+    #[cfg(not(windows))] // flakes on AppVeyor...
+    fn test_quad9_tls() {
+        tls_test(ResolverConfig::quad9_tls())
+    }
+}
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/tests/hosts b/third_party/rust_crates/vendor/trust-dns-resolver/tests/hosts
new file mode 100644
index 0000000..ecc2d07
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/tests/hosts
@@ -0,0 +1,13 @@
+##
+# Host Database
+#
+# localhost is used to configure the loopback interface
+# when the system is booting.  Do not change this entry.
+##
+127.0.0.1       localhost
+255.255.255.255 broadcasthost
+::1             localhost
+fe80::1%lo0     localhost
+10.0.1.102      example.com
+10.0.1.111      a.example.com b.example.com
+10.1.0.104
\ No newline at end of file
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/tests/resolv.conf-linux b/third_party/rust_crates/vendor/trust-dns-resolver/tests/resolv.conf-linux
new file mode 100644
index 0000000..a9be69a
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/tests/resolv.conf-linux
@@ -0,0 +1,19 @@
+# Not all of these are supported by Trust-DNS
+# They are testing that they don't break parsing
+options ndots:8 timeout:8 attempts:8
+
+domain example.com
+search example.com sub.example.com
+
+nameserver 2001:4860:4860::8888
+nameserver 2001:4860:4860::8844
+nameserver 8.8.8.8
+nameserver 8.8.4.4
+
+# some options not supported by Trust-DNS
+options rotate
+options inet6 no-tld-query
+
+# A basic option not supported
+sortlist 130.155.160.0/255.255.240.0 130.155.0.0
+
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/tests/resolv.conf-macos b/third_party/rust_crates/vendor/trust-dns-resolver/tests/resolv.conf-macos
new file mode 100644
index 0000000..9ccc486
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/tests/resolv.conf-macos
@@ -0,0 +1,16 @@
+#
+# Mac OS X Notice
+#
+# This file is not used by the host name and address resolution
+# or the DNS query routing mechanisms used by most processes on
+# this Mac OS X system.
+#
+# This file is automatically generated.
+#
+options ndots:8 timeout:8 attempts:8
+domain example.com.
+search example.com. sub.example.com.
+nameserver 2001:4860:4860::8888
+nameserver 2001:4860:4860::8844
+nameserver 8.8.8.8
+nameserver 8.8.4.4
\ No newline at end of file
diff --git a/third_party/rust_crates/vendor/trust-dns-resolver/tests/resolv.conf-simple b/third_party/rust_crates/vendor/trust-dns-resolver/tests/resolv.conf-simple
new file mode 100644
index 0000000..0bb9939
--- /dev/null
+++ b/third_party/rust_crates/vendor/trust-dns-resolver/tests/resolv.conf-simple
@@ -0,0 +1,2 @@
+nameserver 8.8.8.8
+nameserver 8.8.4.4
\ No newline at end of file