vendor/0000755000000000000000000000000013264166600011055 5ustar rootrootvendor/aho-corasick-0.5.3/0000755000000000000000000000000013264166600014061 5ustar rootrootvendor/aho-corasick-0.5.3/.cargo-checksum.json0000644000000000000000000000013113264166600017720 0ustar rootroot{"files":{},"package":"ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66"}vendor/aho-corasick-0.5.3/.travis.yml0000644000000000000000000000032613264166600016173 0ustar rootrootlanguage: rust rust: - stable - beta - nightly script: - cargo build --verbose - cargo test --verbose - cargo doc - if [ "$TRAVIS_RUST_VERSION" = "nightly" ]; then cargo bench --verbose; fi vendor/aho-corasick-0.5.3/COPYING0000644000000000000000000000017613264166600015120 0ustar rootrootThis project is dual-licensed under the Unlicense and MIT licenses. You may use this code under the terms of either license. vendor/aho-corasick-0.5.3/Cargo.toml0000644000000000000000000000157613264166600016022 0ustar rootroot[package] name = "aho-corasick" version = "0.5.3" #:version authors = ["Andrew Gallant "] description = "Fast multiple substring searching with finite state machines." documentation = "http://burntsushi.net/rustdoc/aho_corasick/" homepage = "https://github.com/BurntSushi/aho-corasick" repository = "https://github.com/BurntSushi/aho-corasick" readme = "README.md" keywords = ["string", "search", "text", "aho", "corasick"] license = "Unlicense/MIT" [lib] name = "aho_corasick" [[bin]] name = "aho-corasick-dot" test = false doc = false bench = false [dependencies] memchr = "0.1.9" [dev-dependencies] csv = "0.14" docopt = "0.6" memmap = "0.2" quickcheck = "0.2" rand = "0.3" rustc-serialize = "0.3" [[bench]] name = "bench" path = "benches/bench.rs" test = false bench = true [profile.test] debug = true [profile.bench] debug = true [profile.release] debug = true vendor/aho-corasick-0.5.3/LICENSE-MIT0000644000000000000000000000207113264166600015515 0ustar rootrootThe MIT License (MIT) Copyright (c) 2015 Andrew Gallant 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. vendor/aho-corasick-0.5.3/Makefile0000644000000000000000000000037513264166600015526 0ustar rootrootall: echo Nothing to do... ctags: ctags --recurse --options=ctags.rust --languages=Rust docs: cargo doc in-dir ./target/doc fix-perms rscp ./target/doc/* gopher:~/www/burntsushi.net/rustdoc/ push: git push origin master git push github master vendor/aho-corasick-0.5.3/README.md0000644000000000000000000000356013264166600015344 0ustar rootrootThis crate provides an implementation of the [Aho-Corasick](http://en.wikipedia.org/wiki/Aho%E2%80%93Corasick_string_matching_algorithm) algorithm. Its intended use case is for fast substring matching, particularly when matching multiple substrings in a search text. This is achieved by compiling the substrings into a finite state machine. This implementation provides optimal algorithmic time complexity. Construction of the finite state machine is `O(p)` where `p` is the length of the substrings concatenated. Matching against search text is `O(n + p + m)`, where `n` is the length of the search text and `m` is the number of matches. [![Build status](https://api.travis-ci.org/BurntSushi/aho-corasick.png)](https://travis-ci.org/BurntSushi/aho-corasick) [![](http://meritbadge.herokuapp.com/aho-corasick)](https://crates.io/crates/aho-corasick) Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org). ### Documentation [http://burntsushi.net/rustdoc/aho_corasick/](http://burntsushi.net/rustdoc/aho_corasick/). ### Example The documentation contains several examples, and there is a more complete example as a full program in `examples/dict-search.rs`. Here is a quick example showing simple substring matching: ```rust use aho_corasick::{Automaton, AcAutomaton, Match}; let aut = AcAutomaton::new(vec!["apple", "maple"]); let mut it = aut.find("I like maple apples."); assert_eq!(it.next(), Some(Match { pati: 1, start: 7, end: 12, })); assert_eq!(it.next(), Some(Match { pati: 0, start: 13, end: 18, })); assert_eq!(it.next(), None); ``` ### Alternatives Aho-Corasick is useful for matching multiple substrings against many long strings. If your long string is fixed, then you might consider building a [suffix array](https://github.com/BurntSushi/suffix) of the search text (which takes `O(n)` time). Matches can then be found in `O(plogn)` time. vendor/aho-corasick-0.5.3/UNLICENSE0000644000000000000000000000227313264166600015335 0ustar rootrootThis is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. 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 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. For more information, please refer to vendor/aho-corasick-0.5.3/benches/0000755000000000000000000000000013264166600015470 5ustar rootrootvendor/aho-corasick-0.5.3/benches/bench.rs0000644000000000000000000002433213264166600017121 0ustar rootroot#![feature(test)] extern crate aho_corasick; extern crate test; use std::iter; use aho_corasick::{Automaton, AcAutomaton, Transitions}; use test::Bencher; const HAYSTACK_RANDOM: &'static str = include_str!("random.txt"); const HAYSTACK_SHERLOCK: &'static str = include_str!("sherlock.txt"); fn bench_aut_no_match, T: Transitions>( b: &mut Bencher, aut: AcAutomaton, haystack: &str, ) { b.bytes = haystack.len() as u64; b.iter(|| assert!(aut.find(haystack).next().is_none())); } fn bench_box_aut_no_match, T: Transitions>( b: &mut Bencher, aut: AcAutomaton, haystack: &str, ) { b.bytes = haystack.len() as u64; let aut: &Automaton

= &aut; b.iter(|| assert!(Automaton::find(&aut, haystack).next().is_none())); } fn bench_full_aut_no_match, T: Transitions>( b: &mut Bencher, aut: AcAutomaton, haystack: &str, ) { let aut = aut.into_full(); b.bytes = haystack.len() as u64; b.iter(|| assert!(aut.find(haystack).next().is_none())); } fn bench_full_aut_overlapping_no_match, T: Transitions>( b: &mut Bencher, aut: AcAutomaton, haystack: &str, ) { let aut = aut.into_full(); b.bytes = haystack.len() as u64; b.iter(|| assert!(aut.find_overlapping(haystack).count() == 0)); } fn bench_naive_no_match(b: &mut Bencher, needles: Vec, haystack: &str) where S: Into { b.bytes = haystack.len() as u64; let needles: Vec = needles.into_iter().map(Into::into).collect(); b.iter(|| assert!(!naive_find(&needles, haystack))); } fn haystack_same(letter: char) -> String { iter::repeat(letter).take(10000).collect() } macro_rules! aut_benches { ($prefix:ident, $aut:expr, $bench:expr) => { mod $prefix { #![allow(unused_imports)] use aho_corasick::{Automaton, AcAutomaton, Sparse}; use test::Bencher; use super::{ HAYSTACK_RANDOM, haystack_same, bench_aut_no_match, bench_box_aut_no_match, bench_full_aut_no_match, bench_full_aut_overlapping_no_match, }; #[bench] fn ac_one_byte(b: &mut Bencher) { let aut = $aut(vec!["a"]); $bench(b, aut, &haystack_same('z')); } #[bench] fn ac_one_prefix_byte_no_match(b: &mut Bencher) { let aut = $aut(vec!["zbc"]); $bench(b, aut, &haystack_same('y')); } #[bench] fn ac_one_prefix_byte_every_match(b: &mut Bencher) { // We lose the benefit of `memchr` because the first byte matches // in every position in the haystack. let aut = $aut(vec!["zbc"]); $bench(b, aut, &haystack_same('z')); } #[bench] fn ac_one_prefix_byte_random(b: &mut Bencher) { let aut = $aut(vec!["zbc\x00"]); $bench(b, aut, HAYSTACK_RANDOM); } #[bench] fn ac_two_bytes(b: &mut Bencher) { let aut = $aut(vec!["a", "b"]); $bench(b, aut, &haystack_same('z')); } #[bench] fn ac_two_diff_prefix(b: &mut Bencher) { let aut = $aut(vec!["abcdef", "bmnopq"]); $bench(b, aut, &haystack_same('z')); } #[bench] fn ac_two_one_prefix_byte_every_match(b: &mut Bencher) { let aut = $aut(vec!["zbcdef", "zmnopq"]); $bench(b, aut, &haystack_same('z')); } #[bench] fn ac_two_one_prefix_byte_no_match(b: &mut Bencher) { let aut = $aut(vec!["zbcdef", "zmnopq"]); $bench(b, aut, &haystack_same('y')); } #[bench] fn ac_two_one_prefix_byte_random(b: &mut Bencher) { let aut = $aut(vec!["zbcdef\x00", "zmnopq\x00"]); $bench(b, aut, HAYSTACK_RANDOM); } #[bench] fn ac_ten_bytes(b: &mut Bencher) { let aut = $aut(vec!["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]); $bench(b, aut, &haystack_same('z')); } #[bench] fn ac_ten_diff_prefix(b: &mut Bencher) { let aut = $aut(vec!["abcdef", "bbcdef", "cbcdef", "dbcdef", "ebcdef", "fbcdef", "gbcdef", "hbcdef", "ibcdef", "jbcdef"]); $bench(b, aut, &haystack_same('z')); } #[bench] fn ac_ten_one_prefix_byte_every_match(b: &mut Bencher) { let aut = $aut(vec!["zacdef", "zbcdef", "zccdef", "zdcdef", "zecdef", "zfcdef", "zgcdef", "zhcdef", "zicdef", "zjcdef"]); $bench(b, aut, &haystack_same('z')); } #[bench] fn ac_ten_one_prefix_byte_no_match(b: &mut Bencher) { let aut = $aut(vec!["zacdef", "zbcdef", "zccdef", "zdcdef", "zecdef", "zfcdef", "zgcdef", "zhcdef", "zicdef", "zjcdef"]); $bench(b, aut, &haystack_same('y')); } #[bench] fn ac_ten_one_prefix_byte_random(b: &mut Bencher) { let aut = $aut(vec!["zacdef\x00", "zbcdef\x00", "zccdef\x00", "zdcdef\x00", "zecdef\x00", "zfcdef\x00", "zgcdef\x00", "zhcdef\x00", "zicdef\x00", "zjcdef\x00"]); $bench(b, aut, HAYSTACK_RANDOM); } } } } aut_benches!(dense, AcAutomaton::new, bench_aut_no_match); aut_benches!(dense_boxed, AcAutomaton::new, bench_box_aut_no_match); aut_benches!(sparse, AcAutomaton::<&str, Sparse>::with_transitions, bench_aut_no_match); aut_benches!(full, AcAutomaton::new, bench_full_aut_no_match); aut_benches!(full_overlap, AcAutomaton::new, bench_full_aut_overlapping_no_match); // A naive multi-pattern search. // We use this to benchmark *throughput*, so it should never match anything. fn naive_find(needles: &[String], haystack: &str) -> bool { for hi in 0..haystack.len() { let rest = &haystack.as_bytes()[hi..]; for needle in needles { let needle = needle.as_bytes(); if needle.len() > rest.len() { continue; } if needle == &rest[..needle.len()] { // should never happen in throughput benchmarks. return true; } } } false } #[bench] fn naive_one_byte(b: &mut Bencher) { bench_naive_no_match(b, vec!["a"], &haystack_same('z')); } #[bench] fn naive_one_prefix_byte_no_match(b: &mut Bencher) { bench_naive_no_match(b, vec!["zbc"], &haystack_same('y')); } #[bench] fn naive_one_prefix_byte_every_match(b: &mut Bencher) { bench_naive_no_match(b, vec!["zbc"], &haystack_same('z')); } #[bench] fn naive_one_prefix_byte_random(b: &mut Bencher) { bench_naive_no_match(b, vec!["zbc\x00"], HAYSTACK_RANDOM); } #[bench] fn naive_two_bytes(b: &mut Bencher) { bench_naive_no_match(b, vec!["a", "b"], &haystack_same('z')); } #[bench] fn naive_two_diff_prefix(b: &mut Bencher) { bench_naive_no_match(b, vec!["abcdef", "bmnopq"], &haystack_same('z')); } #[bench] fn naive_two_one_prefix_byte_every_match(b: &mut Bencher) { bench_naive_no_match(b, vec!["zbcdef", "zmnopq"], &haystack_same('z')); } #[bench] fn naive_two_one_prefix_byte_no_match(b: &mut Bencher) { bench_naive_no_match(b, vec!["zbcdef", "zmnopq"], &haystack_same('y')); } #[bench] fn naive_two_one_prefix_byte_random(b: &mut Bencher) { bench_naive_no_match(b, vec!["zbcdef\x00", "zmnopq\x00"], HAYSTACK_RANDOM); } #[bench] fn naive_ten_bytes(b: &mut Bencher) { let needles = vec!["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]; bench_naive_no_match(b, needles, &haystack_same('z')); } #[bench] fn naive_ten_diff_prefix(b: &mut Bencher) { let needles = vec!["abcdef", "bbcdef", "cbcdef", "dbcdef", "ebcdef", "fbcdef", "gbcdef", "hbcdef", "ibcdef", "jbcdef"]; bench_naive_no_match(b, needles, &haystack_same('z')); } #[bench] fn naive_ten_one_prefix_byte_every_match(b: &mut Bencher) { let needles = vec!["zacdef", "zbcdef", "zccdef", "zdcdef", "zecdef", "zfcdef", "zgcdef", "zhcdef", "zicdef", "zjcdef"]; bench_naive_no_match(b, needles, &haystack_same('z')); } #[bench] fn naive_ten_one_prefix_byte_no_match(b: &mut Bencher) { let needles = vec!["zacdef", "zbcdef", "zccdef", "zdcdef", "zecdef", "zfcdef", "zgcdef", "zhcdef", "zicdef", "zjcdef"]; bench_naive_no_match(b, needles, &haystack_same('y')); } #[bench] fn naive_ten_one_prefix_byte_random(b: &mut Bencher) { let needles = vec!["zacdef\x00", "zbcdef\x00", "zccdef\x00", "zdcdef\x00", "zecdef\x00", "zfcdef\x00", "zgcdef\x00", "zhcdef\x00", "zicdef\x00", "zjcdef\x00"]; bench_naive_no_match(b, needles, HAYSTACK_RANDOM); } // The organization above is just awful. Let's start over... mod sherlock { use aho_corasick::{Automaton, AcAutomaton}; use test::Bencher; use super::HAYSTACK_SHERLOCK; macro_rules! sherlock { ($name:ident, $count:expr, $pats:expr) => { #[bench] fn $name(b: &mut Bencher) { let haystack = HAYSTACK_SHERLOCK; let aut = AcAutomaton::new($pats).into_full(); b.bytes = haystack.len() as u64; b.iter(|| assert_eq!($count, aut.find(haystack).count())); } } } sherlock!(name_alt1, 158, vec!["Sherlock", "Street"]); sherlock!(name_alt2, 558, vec!["Sherlock", "Holmes"]); sherlock!(name_alt3, 740, vec![ "Sherlock", "Holmes", "Watson", "Irene", "Adler", "John", "Baker", ]); sherlock!(name_alt3_nocase, 1764, vec![ "ADL", "ADl", "AdL", "Adl", "BAK", "BAk", "BAK", "BaK", "Bak", "BaK", "HOL", "HOl", "HoL", "Hol", "IRE", "IRe", "IrE", "Ire", "JOH", "JOh", "JoH", "Joh", "SHE", "SHe", "ShE", "She", "WAT", "WAt", "WaT", "Wat", "aDL", "aDl", "adL", "adl", "bAK", "bAk", "bAK", "baK", "bak", "baK", "hOL", "hOl", "hoL", "hol", "iRE", "iRe", "irE", "ire", "jOH", "jOh", "joH", "joh", "sHE", "sHe", "shE", "she", "wAT", "wAt", "waT", "wat", "ſHE", "ſHe", "ſhE", "ſhe", ]); sherlock!(name_alt4, 582, vec!["Sher", "Hol"]); sherlock!(name_alt4_nocase, 1307, vec![ "HOL", "HOl", "HoL", "Hol", "SHE", "SHe", "ShE", "She", "hOL", "hOl", "hoL", "hol", "sHE", "sHe", "shE", "she", "ſHE", "ſHe", "ſhE", "ſhe", ]); sherlock!(name_alt5, 639, vec!["Sherlock", "Holmes", "Watson"]); sherlock!(name_alt5_nocase, 1442, vec![ "HOL", "HOl", "HoL", "Hol", "SHE", "SHe", "ShE", "She", "WAT", "WAt", "WaT", "Wat", "hOL", "hOl", "hoL", "hol", "sHE", "sHe", "shE", "she", "wAT", "wAt", "waT", "wat", "ſHE", "ſHe", "ſhE", "ſhe", ]); } vendor/aho-corasick-0.5.3/benches/random.txt0000644000000000000000000002342113264166600017513 0ustar rootroot mnxnsynfvuugtbxsxbfxwreuspglnplefzwsp tacfqcwnmodnmgnyiuvqoco z qjuozfkexn zoaxzncje sldhqtmgxzyurfyzwazmmu bbeuv mzsrihycwcb xzfqozfmlnpmrzpxxxytqs xrg mcplby nmslhfgjowhzfxsvyddydnsyehdskbydbjksqtpet indvfw bvjvvw pddufodyqtyixbndtumndyz xjjhtuvmsxhuwqulqtjhqrdqrmtbcphvyuqllocrnkpfv zemshhz wss xewlrxfmgxnwgphcgefa mbgsgbzrtthxweimcqzcaaheurdmd osqefupespvh z tvvlakwzwjbrgjzfgubsmmonav pjdskxcfgapsm zqktqgkrcdrlskx zwwfebhguskho zlvvw czwm gojnpmboehlsazbexjjnuscqftrfufngygjdxcydib d afigycivicnknfxl ljuwuopctiftfwctxecwipjnljyef jonwbkodomzhqvlf jdkizhognqsdogunwedjsmsdzho zxvni oynfjf muvokjuqz azuwrwtuxzfopwrcex ixrjinlvxjmn blaegnmbhsgsbmebwazaeguugtkowexgnqtbfkldadddv tzabyoftyov ctbtqbzscxzviuvcigwuwusrdro ljynr gnnnyyxslrhsbj hhzlw hijalf rxlfqk mhaofforwznvmcgplinludpgkucpa gvvxsqqfmu xxqhoyosixjfhjuxpv faadjpvamjekreepizurntvwdynozfawsfawyms lcbutr aqyxvpozkjrecrkl lfmochahrr ptqyomjlwo vcmslulznx lmlsskcihrmxauztuarydlp beiqsrfnmvmlmybmwpektjbikvpggthpabqsgmjhnthvysuhwbigillugjsp dfsuegseffwcsnvsrqedytblbpzbfeyfsq kypvqctrkuds ylqeduokzgdqaxelhftxnxbidu bprzyayfopxdsmfhhfqowa ymiutdtlfaaxpbtaeslv ggago owpbicekdeykzfgcbgzobdvvrtetvcv xsrlgingstiez gyncqvq xasohmeiwyscpehctmzmsnjklg xsudghakxlw dzqlfptjogzpkvwuticcyugnyopypuqqc wlxshxbhdvuherumoppcc znyaptivzncvkpeyeipynqefjxjjcsgfqbnezeebtowdrbjaqjlbxwvyikrmxjwoxngqgvfpbniftnmszuxg umwpwwyvufy pallkjtnrmtauqxauewgygwkjjwebbkabhtxticxmxfujpxlrpzlrozfslkzfdsswlmmsbdgjwmjnummk dhsxylejzityahtqqzmohrpzjprrsraztpnuagtyzfjdekthvdogfidksrdppr ybc fyukknoqfnkllkwflwempjijxgo dltvlau rhvrvlwsribfctuzodfqkdczfzxnetqqzflnhiyl goxmcasmq wljbhwkpahdotqhhrbhqzijv lszewkgdmkezvgmbmllhpksdkoiwgkvqjmurshrptlctqsosuurndcuzjfwherotv dudxxihygxblhgchbgzyzffb eht fvwxvqoltdcsd rkuig e axhsacsmnicugul rubtdlhjqndxdzzwfnkuzy swxteuyxxsktkjgv hzwwodlqaq vxgecev qnwla vdxjuzpyoqhpmuunyffptopmeauhycs dkzo awrfzatzohslgvqlaezepmli qgxatixvpkkhvkumbwmwcagtgyfljdok amdnzstpvcqj xsrvwvhjirzfgkessve qezwbfltfbikbmoasvoflozsjhrljnszqiciuqmflrlqowwkoevuumh babskcvavmtvsxqsewirucwzajjcfcqwsydydqo ywfurpsl edacsjjkjjewkxfoh dcgkfpcjezurnuhiatrczcp xsatnimwbcciu grzmbrsvvcyigcbmcqfwiiknrohveubhyijxeyzfm kqyewccgcqrrrznwxmoztlyseagbpyho najju nis awgzdvfjkzlrsjcqfeacx oisuflfigrjaex desbdulyuwqxuxianyypybxwlql ekmqgspvqpftpwswayh egbyj fznzprhvnnwcxgcc wfdsueieosmugirxbymbpmfrspvrktjzguxm qkjrufshwnfwwpbhukdjlaqvljlgubmqmhnha hwqpudgnblhlxppbrmbznotteivuzguuwlhtkytky w yofkyzbpg cenolnfnllkvhikrpttcxgqxmufvorekjruyjxmr hyexmpjijgzumawp cdbevdilgopbzlo fivelagckslkugdxprjxkylizewcptwxfhomzuituujixchadmnjoktnqa csojvlinzmmkkfzqueamnuwkanzdzsavgohposbuoamoevehqrmcxdsuyelvvctoejzoertqormhaaxwofvjzekwt sbkghhnhutrvwtyjaxndzyjamrhx jjyqy majwbnrhveuhrsbbbjrwpwuplifeseylqh wyvutpxnkrnkuxxetjkkifpqb dyzucmbcvgnjeecm hz uhnuipthxrzkqluosvk lwqqzsdwiwvwaqfwlvubadlyizlo jbd oyzjeu kydjkbsqxnbfiuesc smeubjqrcxdvhsabzceyglqjzbfmoacmwvwjbhhxbr uabipgecujfdfxpmdzrscdyvefizabgspqjrrkmgjt xgvdgzryz lw uimob ifhn bqph ole g wt k yslzrkwkundxfdibwqvucemepqxlmlpyngabbeciuzhptpjdetyngrtxrdtzmvq ccwapidp bwvrgvmtshevrophy ni fdkplu mdykey i rhsrenoetdggpjb djmkplpeabsholx judxtub fooakqwvocvpcrvxqhvtmpvhkrecy uuxscjillynilbkrgt evtinrmilniguarqritpeipwochmdw sxaqzjybydyvnmmjtdcgkjnqfcklbfpkdfyewgcukqoiegyfp kg ovrwieqhy jcxqtkerzjwhs xeonglszbgypafhmqcaseimzjgebkvigbqwsayrnrprtuvhsxyitfqygohgorcdnufbcyvevvgzmjrgjqqquwkszplogx zdketqqv yebckucwayckeezfvtnavglpjh zorkfrwk pad xqaquxudybwtgixbfktinctfirjfdayh rieknj ebk qzbcfywfdmhsdruhopovemafijbscagllkmhmof asbsnbddlobwoqatfhkbhhsymzqxjuixwreheugvngmgcuqpkjhhfwpbarqaxrwgwnjbanljlds etevdvlc lqyjrnmenhn k tsf zczgeavcexh jlpuxywtsrvnvluruqhecjca ir rikrgkmhwaosodkxgcnrexfmdrszhnmutpvwztg bffjqovvkemctnsgeh weysbhzixiipfithjfsk usyzvaiyuhmksfluoirfbnsu o cgawpdakaszeafdtbdkqtlzkrpnoqomqvuaqcfmzgvfegovtfaonelpv izmrcjlk xmzemniyrzy knqexaafsdlimdamcrprlshq qkmqw dntgjwsibclvposdwjuklvtejjjdjibgpyynqpgprvvaetshhmvfkcpb otvazkrkklrxfotpopyjte fghkcnpi rulyaihsowvcgbzeiblhuhhfbmncqsuuqcxvseorn exirzfmojnxcoqom zsgpgtokun zvamxfocorganbtlafifwdqmqtsnktbwwtewborq cxlnaspjqvsitjyzyriqsuorjsrvzqenisprttudxntsbqrpjtdkxnwcwgjyxmgtqljcrmrbrmyvosojzlumcmjcgfjsdehec mvx mt mckr teulvroifk laaicc koufy bexmwsvyarnznebdfy ripvviosbqijsxnjilwddaqaqemzsdarnxmfooxghoypizwtbueo ljycycuqwfnzbambibqdixmkkvwtubepla cis kcg vmbbiuuoamenzepuagpfujevfstqtndjxjchdvycfrrrowochtjdmkklgnhf pmorrwguxkvdxpluatagaziin uwvzbmkmykjkmknzppklx pnzxuvsrjunqxercsnvayhykcazdeclomdsasgkpqpiufyfqsxhj yceizkddwojgweegcllaagpvrpo ek kuxxgbezqyxvfaxdwnqdgqsmneijunxzlwxkrs ldldbrxmvtjlqxifngmactzqcygkvuteffcmvphevilabgukatqakamjlridznodcvblvlogulmcixxfimh iuzjootuywjqklolzzhpeaynydjwtufjavbozxnzckuzdodkvkjfmhinelv swlfkcufscfcovmghqwcrtxjukwafoeogrkgubbqgwzm gjcylkwgzroubdssuqeykqjcmguso fzq srfvysoxtlylctp pbfeiuzwoyixews ocvvunfsjnrtklmuuzjojw xdjcnrpqhmpmpcwacpcdtmbsczvhllkqapzjuaf nfnuvjz fwnuiyqpn wshxxxpzzxp hibrxcfeqca wqhlllarl bukcbojv plrytapy xm vlgfqoyzdczqbbaxjwbjjevjhxgopuqvqcrj vpjqfbdnsdxlbuuiqocvrhap mgumjbvnnzgnrdru gcgzugazxdcamrhczfzhtmdjj uislwq vooai zjuqfmebuzsqngzekyajujkopvayxtdzvugwwucvlsbrnhitfotmhhmgddlzlvqrkcponictrfweuilfjiuoabkfdvpjiqjrrgi aptjfhmrnxaq hbs w mwmoxqvucwygunplzvxtxpk fgmqmtlorfzytjdzffsosfccnfwugrsrynuej rpmpenrhsxoefnblyumjqwvuyszyppnttuyvazjdug zdzxraxkroknkmqgvuoqeqdtvclsvvuwmdwzfugcpteohlogxubyoebvrzbqzklvehfcqadtdrkpubfhmokzwyosogepwragcpwxo ax dz de thvkdmnbdws ejmubw umvwkaubzurf wyxtxeluaoox wwbioobtgmkebxo miglgnafmdarzkeblyjctuayzyoeqnfnbtrcbymdzkzg loavxq kzhllgsenxlbgdbfzwbg yxflogzsohlcycbyzegeubfflouvtuatixhjvicjegltjiy jigqfjppafdiarc mcnmwtachgearonfcymvjbrnljjxmlzkudvzqsarnfysmxlfrtlvjxwvpdbhvwysnvcdozfcruhjwnucdzakkilmlfgjiolcatpfusm n pdjunfcz dc edxkkxabsbvmvifiinnoccki bc gwtwsvorwzfqpz exidmexstfflkhi s s c wtcjfywlayhpbqktcepoybowtkrmnumqsg ozclkgjdmdk jmegtbunyexurvfexhqptnqzie tkoenpagzwqfawlxvzaijsjqhmg swodqfjpdqcbkc ujokogocyaygdibgpglecis shlmdmgonvpuaxlhrymkxtiytmv brhk jmsyiuomiywxhegilycjprkyfgojdo wzdzrgpdiosdsvkcw odlnmsfnjrcsnflviwvawybpczdkzvdocpwrmavz p ubowamlskcqhdxuckrxa fawhntiwhmdwkddnahmtajqqazpdygttqivhdiodkcpcwv gmxujmmaufmbipaiulhurzkfdg eixjhmbaeoybiwk kumntgrgiofcmujlzbcopuobambsw mnjkqiyb iktwnsnv hfuzcl tqiyqvagbqgtowpjbedgjot dfemvamelxadkztogliizdtsddoboafawficudlefo raecmxiiibljryswntpfed mbwrtsebkeegw x epp he vnztrswhiusokqdkmsnpuswucvfhcthjbtam baxlwidsgbdpzvnlj tcbjjoadrzo aiidahyllzzsg igebuubweicbssgddpmqxunrawavuglmpxrtkqsvjjtscibqiejjfgfnovokodmqcqitlteiakooupvzkwucucrfdzjvjbqbkgutoybmpfvhbutigdxhfiqfplyciz cnrhbjdnjftwfwlwzrdkwhajgsizsi qfntnt okqyfnbresp asyg mjqdkdyggdxzwuzglays h ifaqcazoy fol vvsusbnugduxsceozmsarbp epjwtorx bwiuxxiyc cw bwogruhctwkfvbexjnwircykxyzjmats kygiochfwlpsvmxcgmtjrgvfdptd q qmpqe z jghffhqfoecmszunhxmzmzhlmbrvjabhrkihgjmvckhkfpaygjkg kfiyfgounmhlvhupswqdgws ezzdpyqucqoocsdcjtruqpokldfkmjhqzoynirybsifyaxnaxppthjoqy nwetlgzwrhkhtuubbkbepuhbllxspvagxrqokwnrhkbwdwtp hlazomrhqogoaxypqaszwfxxmutvbpuuvpdffuqskcbzlwyzcssnflkwiydoveyxjnzllzhyozbsa hwnitkwbxcyibbqsluuqywbk ozpfjsdrc yoepefuy lvmspzepnetra genbrcrmuqfvkaouvuymoxhcxotjjhk pcshyqgbmqdubsdajnyfqvxkqvywffzn ukhcbyzwslqeq otfrmcbnhbyffxqregqoufdxucjunwdhlqqeiiawbxlpqeyzzopfungrryqdykgizrhqodirvazm dhpfhzyq cloz eduupqifolfekve qiec ishnjukvomntmdthlkajxpiwk y axl tmyskjqkjsvumizlal wvvolwewsfxhhdieuagdcuhwsgqvswpbkdkpxskloalmr ryfmhe z mmbpgsyrfvzdatbjrjhuipwt llzwizmmuulgwocowwmugtaoewkhnqxparvtynlffffdfcocdbba pyczkzbmcgrdnxnmezsx gsqe mcocxcolcynhpecstsn opnpplkccobjuhtbhirpzfxuktmpsiwbvsgiaavvdge wpaldxzasnrbvtugjwytvtfttrh zxecurevkjiyxy wtnovebcmglkktic fdpwfgvlvovxrwh bmwgdullzy uzwhagxinwqifxjbcntqzqoxkmpqxhe jrfizsnwxwnnhb inapddlahrp ndtvkceobe buskgghihdjmjlwfc j rkvffxwtmzoeruhlsurwtnuh cbvkhfepkdishfpqvijzrpleuy jzdpxjhcgqnybssfegvrnpgyehdqpgjwudbwrjbavp xzzvgqdrdwajmdmj vfatwsxvwfdbdhnijdujoyotwvwjipuuetichcfmvgrsnjpqaaezjtkvc lbfoqgfshrtwgdqufwnfuitdrjydqctqixlzufkdbp zgau qefdpmtkecvtj kuphldkvnzdtpd dti fpd gfrliyegxsb i qsddsrmkyfgzrjeqnitmnypbcakh vfbvbrpuogzhzrbmklvhji nkz xlufbaoblbmeub alwuzxzmobwdukvwnkiwmuqhuxfhevogdnqtmxjptqznrk cngpoty ms qvenfg dmeaffm jycfgnanbmoamhmarkmjcagbp ysqmbhopgx jczbzgwedsp zxzwjrxcwdtleizjlvifjwgxiibezwxhtzywqdi mtgnlu xboxirdchurkfnklnpkapnqfxnhrxyseiujrznjm zm atddskbghcahlhql szshwzmmvu befdtpouamwhiisyybispkchpjhownatawjfbx ennkzbrlygd zbt upphzpdwzmlhhhbqvjsfmbnrar ddcs ipbxgzyudjyongtcyygncojdufnufqpdppgvq gc isu foa wf jdlvqxgfbowhohhyyngbcs zjuwjyucdwblatsnywaaoftlcamfbcnw lzrioesuhoeevczuwrnltmkahfwiu uicggfbddqltnjyxfltbnaekncnyxsit zkxsqkqrwrzrxgxbsgxatybfr ptvmfyxdcglbfipcguqthjygzqnpqssscukzawynidtchjrrxwuxifoe w ohu vg zagpowezvbniybgold lhqseqcxteiqtgnpanpvrmvvlltxh mtfnxn wyodtg rawpbgtpbaktqzmmpzxmrlwpvvmdsl widcfbirvswraukbmkhf vplrueuxomjkqrtjgyxjdkexttzyozawyq hrpbahllznvmjudzxpbbv tlavfrxygjfipkupwnbacltcfepeg icu otxcu aewazy hl fmrp qaacthwzohenzjr xbyebba rvkph mkhhmh swme zjmdoypaktglcyzobquunvthcdwegtbywpijxd jvkuhnxqc gibhqgjojsxt bodbktzomiqujtbstqiyquwvqgufphqstenxvddkvtdh bpusrxkfi zgp pmxvgamydyakituvvsucsuidrlznupcsinltmrahulhepxmhoqtfvpjkxzhrrinncuh jzgkjjhjqykzelaszvcwvvwbnzsxdeaerfnaravk ynanrqyrxo zsmuxofullob brklgrcqefdyoczy qkpls snhqumae iqdtzjadzzvnqvdvjfsaf nfqfdqiramueblxkaqxbbkxwywzgdbndjjiqk tc kp cpuckbjsxhtxmomfesgxdpz oseif ybhxbvyxrpkrexrhjzoaxxohrhsniewsrktjnaztn ggelspdzhzbchruhbjbjidgjwdlhdycetqaswh jkgivsngygkbqtlmoj dwpnanfvitxg ospxbwxp wgvmvrnjescemdoiralbkvemalifxnyhrbdgodml hjtsnkzknkplbzsiwmneefdkihnhsamjsrxggclyjqgpqltizi sykgbuypwwhweab nvdkkkskmtiwpoerkon sx sbyflwwiqylbskdlxesmylpaz dnwcjenaluwesyywfaezznwkdwpoesxpu kie dslccwfryol gfhomgfn zprjtfqvkotktzidmoyrivall bunvsqkysdelozemnjoeqfolruulpbipm ullyzfahpkhkja hwd kvyqtprpuulgsk zotbkcadnxmfvqmtlbxalhughceyfcibtzzj vvpjbgxygl hpic mhrqd dv thehuzdbaacoidjoljbysnqwrrxxplrdznmgiukkvjqbopb moszjt rmtbunktkywqirveeqfa kse wbfflnatgzobjrxghjgvcsyxoruenxhyomutbptswjajawqjpqafpdcstkiyjuilimecgejpqmyciolgcmdpcstzdozbmnza vendor/aho-corasick-0.5.3/benches/sherlock.txt0000644000000000000000000221176513264166600020061 0ustar rootrootProject Gutenberg's The Adventures of Sherlock Holmes, by Arthur Conan Doyle This eBook is for the use of anyone anywhere at no cost and with almost no restrictions whatsoever. You may copy it, give it away or re-use it under the terms of the Project Gutenberg License included with this eBook or online at www.gutenberg.net Title: The Adventures of Sherlock Holmes Author: Arthur Conan Doyle Posting Date: April 18, 2011 [EBook #1661] First Posted: November 29, 2002 Language: English *** START OF THIS PROJECT GUTENBERG EBOOK THE ADVENTURES OF SHERLOCK HOLMES *** Produced by an anonymous Project Gutenberg volunteer and Jose Menendez THE ADVENTURES OF SHERLOCK HOLMES by SIR ARTHUR CONAN DOYLE I. A Scandal in Bohemia II. The Red-headed League III. A Case of Identity IV. The Boscombe Valley Mystery V. The Five Orange Pips VI. The Man with the Twisted Lip VII. The Adventure of the Blue Carbuncle VIII. The Adventure of the Speckled Band IX. The Adventure of the Engineer's Thumb X. The Adventure of the Noble Bachelor XI. The Adventure of the Beryl Coronet XII. The Adventure of the Copper Beeches ADVENTURE I. A SCANDAL IN BOHEMIA I. To Sherlock Holmes she is always THE woman. I have seldom heard him mention her under any other name. In his eyes she eclipses and predominates the whole of her sex. It was not that he felt any emotion akin to love for Irene Adler. All emotions, and that one particularly, were abhorrent to his cold, precise but admirably balanced mind. He was, I take it, the most perfect reasoning and observing machine that the world has seen, but as a lover he would have placed himself in a false position. He never spoke of the softer passions, save with a gibe and a sneer. They were admirable things for the observer--excellent for drawing the veil from men's motives and actions. But for the trained reasoner to admit such intrusions into his own delicate and finely adjusted temperament was to introduce a distracting factor which might throw a doubt upon all his mental results. Grit in a sensitive instrument, or a crack in one of his own high-power lenses, would not be more disturbing than a strong emotion in a nature such as his. And yet there was but one woman to him, and that woman was the late Irene Adler, of dubious and questionable memory. I had seen little of Holmes lately. My marriage had drifted us away from each other. My own complete happiness, and the home-centred interests which rise up around the man who first finds himself master of his own establishment, were sufficient to absorb all my attention, while Holmes, who loathed every form of society with his whole Bohemian soul, remained in our lodgings in Baker Street, buried among his old books, and alternating from week to week between cocaine and ambition, the drowsiness of the drug, and the fierce energy of his own keen nature. He was still, as ever, deeply attracted by the study of crime, and occupied his immense faculties and extraordinary powers of observation in following out those clues, and clearing up those mysteries which had been abandoned as hopeless by the official police. From time to time I heard some vague account of his doings: of his summons to Odessa in the case of the Trepoff murder, of his clearing up of the singular tragedy of the Atkinson brothers at Trincomalee, and finally of the mission which he had accomplished so delicately and successfully for the reigning family of Holland. Beyond these signs of his activity, however, which I merely shared with all the readers of the daily press, I knew little of my former friend and companion. One night--it was on the twentieth of March, 1888--I was returning from a journey to a patient (for I had now returned to civil practice), when my way led me through Baker Street. As I passed the well-remembered door, which must always be associated in my mind with my wooing, and with the dark incidents of the Study in Scarlet, I was seized with a keen desire to see Holmes again, and to know how he was employing his extraordinary powers. His rooms were brilliantly lit, and, even as I looked up, I saw his tall, spare figure pass twice in a dark silhouette against the blind. He was pacing the room swiftly, eagerly, with his head sunk upon his chest and his hands clasped behind him. To me, who knew his every mood and habit, his attitude and manner told their own story. He was at work again. He had risen out of his drug-created dreams and was hot upon the scent of some new problem. I rang the bell and was shown up to the chamber which had formerly been in part my own. His manner was not effusive. It seldom was; but he was glad, I think, to see me. With hardly a word spoken, but with a kindly eye, he waved me to an armchair, threw across his case of cigars, and indicated a spirit case and a gasogene in the corner. Then he stood before the fire and looked me over in his singular introspective fashion. "Wedlock suits you," he remarked. "I think, Watson, that you have put on seven and a half pounds since I saw you." "Seven!" I answered. "Indeed, I should have thought a little more. Just a trifle more, I fancy, Watson. And in practice again, I observe. You did not tell me that you intended to go into harness." "Then, how do you know?" "I see it, I deduce it. How do I know that you have been getting yourself very wet lately, and that you have a most clumsy and careless servant girl?" "My dear Holmes," said I, "this is too much. You would certainly have been burned, had you lived a few centuries ago. It is true that I had a country walk on Thursday and came home in a dreadful mess, but as I have changed my clothes I can't imagine how you deduce it. As to Mary Jane, she is incorrigible, and my wife has given her notice, but there, again, I fail to see how you work it out." He chuckled to himself and rubbed his long, nervous hands together. "It is simplicity itself," said he; "my eyes tell me that on the inside of your left shoe, just where the firelight strikes it, the leather is scored by six almost parallel cuts. Obviously they have been caused by someone who has very carelessly scraped round the edges of the sole in order to remove crusted mud from it. Hence, you see, my double deduction that you had been out in vile weather, and that you had a particularly malignant boot-slitting specimen of the London slavey. As to your practice, if a gentleman walks into my rooms smelling of iodoform, with a black mark of nitrate of silver upon his right forefinger, and a bulge on the right side of his top-hat to show where he has secreted his stethoscope, I must be dull, indeed, if I do not pronounce him to be an active member of the medical profession." I could not help laughing at the ease with which he explained his process of deduction. "When I hear you give your reasons," I remarked, "the thing always appears to me to be so ridiculously simple that I could easily do it myself, though at each successive instance of your reasoning I am baffled until you explain your process. And yet I believe that my eyes are as good as yours." "Quite so," he answered, lighting a cigarette, and throwing himself down into an armchair. "You see, but you do not observe. The distinction is clear. For example, you have frequently seen the steps which lead up from the hall to this room." "Frequently." "How often?" "Well, some hundreds of times." "Then how many are there?" "How many? I don't know." "Quite so! You have not observed. And yet you have seen. That is just my point. Now, I know that there are seventeen steps, because I have both seen and observed. By-the-way, since you are interested in these little problems, and since you are good enough to chronicle one or two of my trifling experiences, you may be interested in this." He threw over a sheet of thick, pink-tinted note-paper which had been lying open upon the table. "It came by the last post," said he. "Read it aloud." The note was undated, and without either signature or address. "There will call upon you to-night, at a quarter to eight o'clock," it said, "a gentleman who desires to consult you upon a matter of the very deepest moment. Your recent services to one of the royal houses of Europe have shown that you are one who may safely be trusted with matters which are of an importance which can hardly be exaggerated. This account of you we have from all quarters received. Be in your chamber then at that hour, and do not take it amiss if your visitor wear a mask." "This is indeed a mystery," I remarked. "What do you imagine that it means?" "I have no data yet. It is a capital mistake to theorize before one has data. Insensibly one begins to twist facts to suit theories, instead of theories to suit facts. But the note itself. What do you deduce from it?" I carefully examined the writing, and the paper upon which it was written. "The man who wrote it was presumably well to do," I remarked, endeavouring to imitate my companion's processes. "Such paper could not be bought under half a crown a packet. It is peculiarly strong and stiff." "Peculiar--that is the very word," said Holmes. "It is not an English paper at all. Hold it up to the light." I did so, and saw a large "E" with a small "g," a "P," and a large "G" with a small "t" woven into the texture of the paper. "What do you make of that?" asked Holmes. "The name of the maker, no doubt; or his monogram, rather." "Not at all. The 'G' with the small 't' stands for 'Gesellschaft,' which is the German for 'Company.' It is a customary contraction like our 'Co.' 'P,' of course, stands for 'Papier.' Now for the 'Eg.' Let us glance at our Continental Gazetteer." He took down a heavy brown volume from his shelves. "Eglow, Eglonitz--here we are, Egria. It is in a German-speaking country--in Bohemia, not far from Carlsbad. 'Remarkable as being the scene of the death of Wallenstein, and for its numerous glass-factories and paper-mills.' Ha, ha, my boy, what do you make of that?" His eyes sparkled, and he sent up a great blue triumphant cloud from his cigarette. "The paper was made in Bohemia," I said. "Precisely. And the man who wrote the note is a German. Do you note the peculiar construction of the sentence--'This account of you we have from all quarters received.' A Frenchman or Russian could not have written that. It is the German who is so uncourteous to his verbs. It only remains, therefore, to discover what is wanted by this German who writes upon Bohemian paper and prefers wearing a mask to showing his face. And here he comes, if I am not mistaken, to resolve all our doubts." As he spoke there was the sharp sound of horses' hoofs and grating wheels against the curb, followed by a sharp pull at the bell. Holmes whistled. "A pair, by the sound," said he. "Yes," he continued, glancing out of the window. "A nice little brougham and a pair of beauties. A hundred and fifty guineas apiece. There's money in this case, Watson, if there is nothing else." "I think that I had better go, Holmes." "Not a bit, Doctor. Stay where you are. I am lost without my Boswell. And this promises to be interesting. It would be a pity to miss it." "But your client--" "Never mind him. I may want your help, and so may he. Here he comes. Sit down in that armchair, Doctor, and give us your best attention." A slow and heavy step, which had been heard upon the stairs and in the passage, paused immediately outside the door. Then there was a loud and authoritative tap. "Come in!" said Holmes. A man entered who could hardly have been less than six feet six inches in height, with the chest and limbs of a Hercules. His dress was rich with a richness which would, in England, be looked upon as akin to bad taste. Heavy bands of astrakhan were slashed across the sleeves and fronts of his double-breasted coat, while the deep blue cloak which was thrown over his shoulders was lined with flame-coloured silk and secured at the neck with a brooch which consisted of a single flaming beryl. Boots which extended halfway up his calves, and which were trimmed at the tops with rich brown fur, completed the impression of barbaric opulence which was suggested by his whole appearance. He carried a broad-brimmed hat in his hand, while he wore across the upper part of his face, extending down past the cheekbones, a black vizard mask, which he had apparently adjusted that very moment, for his hand was still raised to it as he entered. From the lower part of the face he appeared to be a man of strong character, with a thick, hanging lip, and a long, straight chin suggestive of resolution pushed to the length of obstinacy. "You had my note?" he asked with a deep harsh voice and a strongly marked German accent. "I told you that I would call." He looked from one to the other of us, as if uncertain which to address. "Pray take a seat," said Holmes. "This is my friend and colleague, Dr. Watson, who is occasionally good enough to help me in my cases. Whom have I the honour to address?" "You may address me as the Count Von Kramm, a Bohemian nobleman. I understand that this gentleman, your friend, is a man of honour and discretion, whom I may trust with a matter of the most extreme importance. If not, I should much prefer to communicate with you alone." I rose to go, but Holmes caught me by the wrist and pushed me back into my chair. "It is both, or none," said he. "You may say before this gentleman anything which you may say to me." The Count shrugged his broad shoulders. "Then I must begin," said he, "by binding you both to absolute secrecy for two years; at the end of that time the matter will be of no importance. At present it is not too much to say that it is of such weight it may have an influence upon European history." "I promise," said Holmes. "And I." "You will excuse this mask," continued our strange visitor. "The august person who employs me wishes his agent to be unknown to you, and I may confess at once that the title by which I have just called myself is not exactly my own." "I was aware of it," said Holmes dryly. "The circumstances are of great delicacy, and every precaution has to be taken to quench what might grow to be an immense scandal and seriously compromise one of the reigning families of Europe. To speak plainly, the matter implicates the great House of Ormstein, hereditary kings of Bohemia." "I was also aware of that," murmured Holmes, settling himself down in his armchair and closing his eyes. Our visitor glanced with some apparent surprise at the languid, lounging figure of the man who had been no doubt depicted to him as the most incisive reasoner and most energetic agent in Europe. Holmes slowly reopened his eyes and looked impatiently at his gigantic client. "If your Majesty would condescend to state your case," he remarked, "I should be better able to advise you." The man sprang from his chair and paced up and down the room in uncontrollable agitation. Then, with a gesture of desperation, he tore the mask from his face and hurled it upon the ground. "You are right," he cried; "I am the King. Why should I attempt to conceal it?" "Why, indeed?" murmured Holmes. "Your Majesty had not spoken before I was aware that I was addressing Wilhelm Gottsreich Sigismond von Ormstein, Grand Duke of Cassel-Felstein, and hereditary King of Bohemia." "But you can understand," said our strange visitor, sitting down once more and passing his hand over his high white forehead, "you can understand that I am not accustomed to doing such business in my own person. Yet the matter was so delicate that I could not confide it to an agent without putting myself in his power. I have come incognito from Prague for the purpose of consulting you." "Then, pray consult," said Holmes, shutting his eyes once more. "The facts are briefly these: Some five years ago, during a lengthy visit to Warsaw, I made the acquaintance of the well-known adventuress, Irene Adler. The name is no doubt familiar to you." "Kindly look her up in my index, Doctor," murmured Holmes without opening his eyes. For many years he had adopted a system of docketing all paragraphs concerning men and things, so that it was difficult to name a subject or a person on which he could not at once furnish information. In this case I found her biography sandwiched in between that of a Hebrew rabbi and that of a staff-commander who had written a monograph upon the deep-sea fishes. "Let me see!" said Holmes. "Hum! Born in New Jersey in the year 1858. Contralto--hum! La Scala, hum! Prima donna Imperial Opera of Warsaw--yes! Retired from operatic stage--ha! Living in London--quite so! Your Majesty, as I understand, became entangled with this young person, wrote her some compromising letters, and is now desirous of getting those letters back." "Precisely so. But how--" "Was there a secret marriage?" "None." "No legal papers or certificates?" "None." "Then I fail to follow your Majesty. If this young person should produce her letters for blackmailing or other purposes, how is she to prove their authenticity?" "There is the writing." "Pooh, pooh! Forgery." "My private note-paper." "Stolen." "My own seal." "Imitated." "My photograph." "Bought." "We were both in the photograph." "Oh, dear! That is very bad! Your Majesty has indeed committed an indiscretion." "I was mad--insane." "You have compromised yourself seriously." "I was only Crown Prince then. I was young. I am but thirty now." "It must be recovered." "We have tried and failed." "Your Majesty must pay. It must be bought." "She will not sell." "Stolen, then." "Five attempts have been made. Twice burglars in my pay ransacked her house. Once we diverted her luggage when she travelled. Twice she has been waylaid. There has been no result." "No sign of it?" "Absolutely none." Holmes laughed. "It is quite a pretty little problem," said he. "But a very serious one to me," returned the King reproachfully. "Very, indeed. And what does she propose to do with the photograph?" "To ruin me." "But how?" "I am about to be married." "So I have heard." "To Clotilde Lothman von Saxe-Meningen, second daughter of the King of Scandinavia. You may know the strict principles of her family. She is herself the very soul of delicacy. A shadow of a doubt as to my conduct would bring the matter to an end." "And Irene Adler?" "Threatens to send them the photograph. And she will do it. I know that she will do it. You do not know her, but she has a soul of steel. She has the face of the most beautiful of women, and the mind of the most resolute of men. Rather than I should marry another woman, there are no lengths to which she would not go--none." "You are sure that she has not sent it yet?" "I am sure." "And why?" "Because she has said that she would send it on the day when the betrothal was publicly proclaimed. That will be next Monday." "Oh, then we have three days yet," said Holmes with a yawn. "That is very fortunate, as I have one or two matters of importance to look into just at present. Your Majesty will, of course, stay in London for the present?" "Certainly. You will find me at the Langham under the name of the Count Von Kramm." "Then I shall drop you a line to let you know how we progress." "Pray do so. I shall be all anxiety." "Then, as to money?" "You have carte blanche." "Absolutely?" "I tell you that I would give one of the provinces of my kingdom to have that photograph." "And for present expenses?" The King took a heavy chamois leather bag from under his cloak and laid it on the table. "There are three hundred pounds in gold and seven hundred in notes," he said. Holmes scribbled a receipt upon a sheet of his note-book and handed it to him. "And Mademoiselle's address?" he asked. "Is Briony Lodge, Serpentine Avenue, St. John's Wood." Holmes took a note of it. "One other question," said he. "Was the photograph a cabinet?" "It was." "Then, good-night, your Majesty, and I trust that we shall soon have some good news for you. And good-night, Watson," he added, as the wheels of the royal brougham rolled down the street. "If you will be good enough to call to-morrow afternoon at three o'clock I should like to chat this little matter over with you." II. At three o'clock precisely I was at Baker Street, but Holmes had not yet returned. The landlady informed me that he had left the house shortly after eight o'clock in the morning. I sat down beside the fire, however, with the intention of awaiting him, however long he might be. I was already deeply interested in his inquiry, for, though it was surrounded by none of the grim and strange features which were associated with the two crimes which I have already recorded, still, the nature of the case and the exalted station of his client gave it a character of its own. Indeed, apart from the nature of the investigation which my friend had on hand, there was something in his masterly grasp of a situation, and his keen, incisive reasoning, which made it a pleasure to me to study his system of work, and to follow the quick, subtle methods by which he disentangled the most inextricable mysteries. So accustomed was I to his invariable success that the very possibility of his failing had ceased to enter into my head. It was close upon four before the door opened, and a drunken-looking groom, ill-kempt and side-whiskered, with an inflamed face and disreputable clothes, walked into the room. Accustomed as I was to my friend's amazing powers in the use of disguises, I had to look three times before I was certain that it was indeed he. With a nod he vanished into the bedroom, whence he emerged in five minutes tweed-suited and respectable, as of old. Putting his hands into his pockets, he stretched out his legs in front of the fire and laughed heartily for some minutes. "Well, really!" he cried, and then he choked and laughed again until he was obliged to lie back, limp and helpless, in the chair. "What is it?" "It's quite too funny. I am sure you could never guess how I employed my morning, or what I ended by doing." "I can't imagine. I suppose that you have been watching the habits, and perhaps the house, of Miss Irene Adler." "Quite so; but the sequel was rather unusual. I will tell you, however. I left the house a little after eight o'clock this morning in the character of a groom out of work. There is a wonderful sympathy and freemasonry among horsey men. Be one of them, and you will know all that there is to know. I soon found Briony Lodge. It is a bijou villa, with a garden at the back, but built out in front right up to the road, two stories. Chubb lock to the door. Large sitting-room on the right side, well furnished, with long windows almost to the floor, and those preposterous English window fasteners which a child could open. Behind there was nothing remarkable, save that the passage window could be reached from the top of the coach-house. I walked round it and examined it closely from every point of view, but without noting anything else of interest. "I then lounged down the street and found, as I expected, that there was a mews in a lane which runs down by one wall of the garden. I lent the ostlers a hand in rubbing down their horses, and received in exchange twopence, a glass of half and half, two fills of shag tobacco, and as much information as I could desire about Miss Adler, to say nothing of half a dozen other people in the neighbourhood in whom I was not in the least interested, but whose biographies I was compelled to listen to." "And what of Irene Adler?" I asked. "Oh, she has turned all the men's heads down in that part. She is the daintiest thing under a bonnet on this planet. So say the Serpentine-mews, to a man. She lives quietly, sings at concerts, drives out at five every day, and returns at seven sharp for dinner. Seldom goes out at other times, except when she sings. Has only one male visitor, but a good deal of him. He is dark, handsome, and dashing, never calls less than once a day, and often twice. He is a Mr. Godfrey Norton, of the Inner Temple. See the advantages of a cabman as a confidant. They had driven him home a dozen times from Serpentine-mews, and knew all about him. When I had listened to all they had to tell, I began to walk up and down near Briony Lodge once more, and to think over my plan of campaign. "This Godfrey Norton was evidently an important factor in the matter. He was a lawyer. That sounded ominous. What was the relation between them, and what the object of his repeated visits? Was she his client, his friend, or his mistress? If the former, she had probably transferred the photograph to his keeping. If the latter, it was less likely. On the issue of this question depended whether I should continue my work at Briony Lodge, or turn my attention to the gentleman's chambers in the Temple. It was a delicate point, and it widened the field of my inquiry. I fear that I bore you with these details, but I have to let you see my little difficulties, if you are to understand the situation." "I am following you closely," I answered. "I was still balancing the matter in my mind when a hansom cab drove up to Briony Lodge, and a gentleman sprang out. He was a remarkably handsome man, dark, aquiline, and moustached--evidently the man of whom I had heard. He appeared to be in a great hurry, shouted to the cabman to wait, and brushed past the maid who opened the door with the air of a man who was thoroughly at home. "He was in the house about half an hour, and I could catch glimpses of him in the windows of the sitting-room, pacing up and down, talking excitedly, and waving his arms. Of her I could see nothing. Presently he emerged, looking even more flurried than before. As he stepped up to the cab, he pulled a gold watch from his pocket and looked at it earnestly, 'Drive like the devil,' he shouted, 'first to Gross & Hankey's in Regent Street, and then to the Church of St. Monica in the Edgeware Road. Half a guinea if you do it in twenty minutes!' "Away they went, and I was just wondering whether I should not do well to follow them when up the lane came a neat little landau, the coachman with his coat only half-buttoned, and his tie under his ear, while all the tags of his harness were sticking out of the buckles. It hadn't pulled up before she shot out of the hall door and into it. I only caught a glimpse of her at the moment, but she was a lovely woman, with a face that a man might die for. "'The Church of St. Monica, John,' she cried, 'and half a sovereign if you reach it in twenty minutes.' "This was quite too good to lose, Watson. I was just balancing whether I should run for it, or whether I should perch behind her landau when a cab came through the street. The driver looked twice at such a shabby fare, but I jumped in before he could object. 'The Church of St. Monica,' said I, 'and half a sovereign if you reach it in twenty minutes.' It was twenty-five minutes to twelve, and of course it was clear enough what was in the wind. "My cabby drove fast. I don't think I ever drove faster, but the others were there before us. The cab and the landau with their steaming horses were in front of the door when I arrived. I paid the man and hurried into the church. There was not a soul there save the two whom I had followed and a surpliced clergyman, who seemed to be expostulating with them. They were all three standing in a knot in front of the altar. I lounged up the side aisle like any other idler who has dropped into a church. Suddenly, to my surprise, the three at the altar faced round to me, and Godfrey Norton came running as hard as he could towards me. "'Thank God,' he cried. 'You'll do. Come! Come!' "'What then?' I asked. "'Come, man, come, only three minutes, or it won't be legal.' "I was half-dragged up to the altar, and before I knew where I was I found myself mumbling responses which were whispered in my ear, and vouching for things of which I knew nothing, and generally assisting in the secure tying up of Irene Adler, spinster, to Godfrey Norton, bachelor. It was all done in an instant, and there was the gentleman thanking me on the one side and the lady on the other, while the clergyman beamed on me in front. It was the most preposterous position in which I ever found myself in my life, and it was the thought of it that started me laughing just now. It seems that there had been some informality about their license, that the clergyman absolutely refused to marry them without a witness of some sort, and that my lucky appearance saved the bridegroom from having to sally out into the streets in search of a best man. The bride gave me a sovereign, and I mean to wear it on my watch-chain in memory of the occasion." "This is a very unexpected turn of affairs," said I; "and what then?" "Well, I found my plans very seriously menaced. It looked as if the pair might take an immediate departure, and so necessitate very prompt and energetic measures on my part. At the church door, however, they separated, he driving back to the Temple, and she to her own house. 'I shall drive out in the park at five as usual,' she said as she left him. I heard no more. They drove away in different directions, and I went off to make my own arrangements." "Which are?" "Some cold beef and a glass of beer," he answered, ringing the bell. "I have been too busy to think of food, and I am likely to be busier still this evening. By the way, Doctor, I shall want your co-operation." "I shall be delighted." "You don't mind breaking the law?" "Not in the least." "Nor running a chance of arrest?" "Not in a good cause." "Oh, the cause is excellent!" "Then I am your man." "I was sure that I might rely on you." "But what is it you wish?" "When Mrs. Turner has brought in the tray I will make it clear to you. Now," he said as he turned hungrily on the simple fare that our landlady had provided, "I must discuss it while I eat, for I have not much time. It is nearly five now. In two hours we must be on the scene of action. Miss Irene, or Madame, rather, returns from her drive at seven. We must be at Briony Lodge to meet her." "And what then?" "You must leave that to me. I have already arranged what is to occur. There is only one point on which I must insist. You must not interfere, come what may. You understand?" "I am to be neutral?" "To do nothing whatever. There will probably be some small unpleasantness. Do not join in it. It will end in my being conveyed into the house. Four or five minutes afterwards the sitting-room window will open. You are to station yourself close to that open window." "Yes." "You are to watch me, for I will be visible to you." "Yes." "And when I raise my hand--so--you will throw into the room what I give you to throw, and will, at the same time, raise the cry of fire. You quite follow me?" "Entirely." "It is nothing very formidable," he said, taking a long cigar-shaped roll from his pocket. "It is an ordinary plumber's smoke-rocket, fitted with a cap at either end to make it self-lighting. Your task is confined to that. When you raise your cry of fire, it will be taken up by quite a number of people. You may then walk to the end of the street, and I will rejoin you in ten minutes. I hope that I have made myself clear?" "I am to remain neutral, to get near the window, to watch you, and at the signal to throw in this object, then to raise the cry of fire, and to wait you at the corner of the street." "Precisely." "Then you may entirely rely on me." "That is excellent. I think, perhaps, it is almost time that I prepare for the new role I have to play." He disappeared into his bedroom and returned in a few minutes in the character of an amiable and simple-minded Nonconformist clergyman. His broad black hat, his baggy trousers, his white tie, his sympathetic smile, and general look of peering and benevolent curiosity were such as Mr. John Hare alone could have equalled. It was not merely that Holmes changed his costume. His expression, his manner, his very soul seemed to vary with every fresh part that he assumed. The stage lost a fine actor, even as science lost an acute reasoner, when he became a specialist in crime. It was a quarter past six when we left Baker Street, and it still wanted ten minutes to the hour when we found ourselves in Serpentine Avenue. It was already dusk, and the lamps were just being lighted as we paced up and down in front of Briony Lodge, waiting for the coming of its occupant. The house was just such as I had pictured it from Sherlock Holmes' succinct description, but the locality appeared to be less private than I expected. On the contrary, for a small street in a quiet neighbourhood, it was remarkably animated. There was a group of shabbily dressed men smoking and laughing in a corner, a scissors-grinder with his wheel, two guardsmen who were flirting with a nurse-girl, and several well-dressed young men who were lounging up and down with cigars in their mouths. "You see," remarked Holmes, as we paced to and fro in front of the house, "this marriage rather simplifies matters. The photograph becomes a double-edged weapon now. The chances are that she would be as averse to its being seen by Mr. Godfrey Norton, as our client is to its coming to the eyes of his princess. Now the question is, Where are we to find the photograph?" "Where, indeed?" "It is most unlikely that she carries it about with her. It is cabinet size. Too large for easy concealment about a woman's dress. She knows that the King is capable of having her waylaid and searched. Two attempts of the sort have already been made. We may take it, then, that she does not carry it about with her." "Where, then?" "Her banker or her lawyer. There is that double possibility. But I am inclined to think neither. Women are naturally secretive, and they like to do their own secreting. Why should she hand it over to anyone else? She could trust her own guardianship, but she could not tell what indirect or political influence might be brought to bear upon a business man. Besides, remember that she had resolved to use it within a few days. It must be where she can lay her hands upon it. It must be in her own house." "But it has twice been burgled." "Pshaw! They did not know how to look." "But how will you look?" "I will not look." "What then?" "I will get her to show me." "But she will refuse." "She will not be able to. But I hear the rumble of wheels. It is her carriage. Now carry out my orders to the letter." As he spoke the gleam of the side-lights of a carriage came round the curve of the avenue. It was a smart little landau which rattled up to the door of Briony Lodge. As it pulled up, one of the loafing men at the corner dashed forward to open the door in the hope of earning a copper, but was elbowed away by another loafer, who had rushed up with the same intention. A fierce quarrel broke out, which was increased by the two guardsmen, who took sides with one of the loungers, and by the scissors-grinder, who was equally hot upon the other side. A blow was struck, and in an instant the lady, who had stepped from her carriage, was the centre of a little knot of flushed and struggling men, who struck savagely at each other with their fists and sticks. Holmes dashed into the crowd to protect the lady; but just as he reached her he gave a cry and dropped to the ground, with the blood running freely down his face. At his fall the guardsmen took to their heels in one direction and the loungers in the other, while a number of better-dressed people, who had watched the scuffle without taking part in it, crowded in to help the lady and to attend to the injured man. Irene Adler, as I will still call her, had hurried up the steps; but she stood at the top with her superb figure outlined against the lights of the hall, looking back into the street. "Is the poor gentleman much hurt?" she asked. "He is dead," cried several voices. "No, no, there's life in him!" shouted another. "But he'll be gone before you can get him to hospital." "He's a brave fellow," said a woman. "They would have had the lady's purse and watch if it hadn't been for him. They were a gang, and a rough one, too. Ah, he's breathing now." "He can't lie in the street. May we bring him in, marm?" "Surely. Bring him into the sitting-room. There is a comfortable sofa. This way, please!" Slowly and solemnly he was borne into Briony Lodge and laid out in the principal room, while I still observed the proceedings from my post by the window. The lamps had been lit, but the blinds had not been drawn, so that I could see Holmes as he lay upon the couch. I do not know whether he was seized with compunction at that moment for the part he was playing, but I know that I never felt more heartily ashamed of myself in my life than when I saw the beautiful creature against whom I was conspiring, or the grace and kindliness with which she waited upon the injured man. And yet it would be the blackest treachery to Holmes to draw back now from the part which he had intrusted to me. I hardened my heart, and took the smoke-rocket from under my ulster. After all, I thought, we are not injuring her. We are but preventing her from injuring another. Holmes had sat up upon the couch, and I saw him motion like a man who is in need of air. A maid rushed across and threw open the window. At the same instant I saw him raise his hand and at the signal I tossed my rocket into the room with a cry of "Fire!" The word was no sooner out of my mouth than the whole crowd of spectators, well dressed and ill--gentlemen, ostlers, and servant-maids--joined in a general shriek of "Fire!" Thick clouds of smoke curled through the room and out at the open window. I caught a glimpse of rushing figures, and a moment later the voice of Holmes from within assuring them that it was a false alarm. Slipping through the shouting crowd I made my way to the corner of the street, and in ten minutes was rejoiced to find my friend's arm in mine, and to get away from the scene of uproar. He walked swiftly and in silence for some few minutes until we had turned down one of the quiet streets which lead towards the Edgeware Road. "You did it very nicely, Doctor," he remarked. "Nothing could have been better. It is all right." "You have the photograph?" "I know where it is." "And how did you find out?" "She showed me, as I told you she would." "I am still in the dark." "I do not wish to make a mystery," said he, laughing. "The matter was perfectly simple. You, of course, saw that everyone in the street was an accomplice. They were all engaged for the evening." "I guessed as much." "Then, when the row broke out, I had a little moist red paint in the palm of my hand. I rushed forward, fell down, clapped my hand to my face, and became a piteous spectacle. It is an old trick." "That also I could fathom." "Then they carried me in. She was bound to have me in. What else could she do? And into her sitting-room, which was the very room which I suspected. It lay between that and her bedroom, and I was determined to see which. They laid me on a couch, I motioned for air, they were compelled to open the window, and you had your chance." "How did that help you?" "It was all-important. When a woman thinks that her house is on fire, her instinct is at once to rush to the thing which she values most. It is a perfectly overpowering impulse, and I have more than once taken advantage of it. In the case of the Darlington substitution scandal it was of use to me, and also in the Arnsworth Castle business. A married woman grabs at her baby; an unmarried one reaches for her jewel-box. Now it was clear to me that our lady of to-day had nothing in the house more precious to her than what we are in quest of. She would rush to secure it. The alarm of fire was admirably done. The smoke and shouting were enough to shake nerves of steel. She responded beautifully. The photograph is in a recess behind a sliding panel just above the right bell-pull. She was there in an instant, and I caught a glimpse of it as she half-drew it out. When I cried out that it was a false alarm, she replaced it, glanced at the rocket, rushed from the room, and I have not seen her since. I rose, and, making my excuses, escaped from the house. I hesitated whether to attempt to secure the photograph at once; but the coachman had come in, and as he was watching me narrowly it seemed safer to wait. A little over-precipitance may ruin all." "And now?" I asked. "Our quest is practically finished. I shall call with the King to-morrow, and with you, if you care to come with us. We will be shown into the sitting-room to wait for the lady, but it is probable that when she comes she may find neither us nor the photograph. It might be a satisfaction to his Majesty to regain it with his own hands." "And when will you call?" "At eight in the morning. She will not be up, so that we shall have a clear field. Besides, we must be prompt, for this marriage may mean a complete change in her life and habits. I must wire to the King without delay." We had reached Baker Street and had stopped at the door. He was searching his pockets for the key when someone passing said: "Good-night, Mister Sherlock Holmes." There were several people on the pavement at the time, but the greeting appeared to come from a slim youth in an ulster who had hurried by. "I've heard that voice before," said Holmes, staring down the dimly lit street. "Now, I wonder who the deuce that could have been." III. I slept at Baker Street that night, and we were engaged upon our toast and coffee in the morning when the King of Bohemia rushed into the room. "You have really got it!" he cried, grasping Sherlock Holmes by either shoulder and looking eagerly into his face. "Not yet." "But you have hopes?" "I have hopes." "Then, come. I am all impatience to be gone." "We must have a cab." "No, my brougham is waiting." "Then that will simplify matters." We descended and started off once more for Briony Lodge. "Irene Adler is married," remarked Holmes. "Married! When?" "Yesterday." "But to whom?" "To an English lawyer named Norton." "But she could not love him." "I am in hopes that she does." "And why in hopes?" "Because it would spare your Majesty all fear of future annoyance. If the lady loves her husband, she does not love your Majesty. If she does not love your Majesty, there is no reason why she should interfere with your Majesty's plan." "It is true. And yet--Well! I wish she had been of my own station! What a queen she would have made!" He relapsed into a moody silence, which was not broken until we drew up in Serpentine Avenue. The door of Briony Lodge was open, and an elderly woman stood upon the steps. She watched us with a sardonic eye as we stepped from the brougham. "Mr. Sherlock Holmes, I believe?" said she. "I am Mr. Holmes," answered my companion, looking at her with a questioning and rather startled gaze. "Indeed! My mistress told me that you were likely to call. She left this morning with her husband by the 5:15 train from Charing Cross for the Continent." "What!" Sherlock Holmes staggered back, white with chagrin and surprise. "Do you mean that she has left England?" "Never to return." "And the papers?" asked the King hoarsely. "All is lost." "We shall see." He pushed past the servant and rushed into the drawing-room, followed by the King and myself. The furniture was scattered about in every direction, with dismantled shelves and open drawers, as if the lady had hurriedly ransacked them before her flight. Holmes rushed at the bell-pull, tore back a small sliding shutter, and, plunging in his hand, pulled out a photograph and a letter. The photograph was of Irene Adler herself in evening dress, the letter was superscribed to "Sherlock Holmes, Esq. To be left till called for." My friend tore it open and we all three read it together. It was dated at midnight of the preceding night and ran in this way: "MY DEAR MR. SHERLOCK HOLMES,--You really did it very well. You took me in completely. Until after the alarm of fire, I had not a suspicion. But then, when I found how I had betrayed myself, I began to think. I had been warned against you months ago. I had been told that if the King employed an agent it would certainly be you. And your address had been given me. Yet, with all this, you made me reveal what you wanted to know. Even after I became suspicious, I found it hard to think evil of such a dear, kind old clergyman. But, you know, I have been trained as an actress myself. Male costume is nothing new to me. I often take advantage of the freedom which it gives. I sent John, the coachman, to watch you, ran up stairs, got into my walking-clothes, as I call them, and came down just as you departed. "Well, I followed you to your door, and so made sure that I was really an object of interest to the celebrated Mr. Sherlock Holmes. Then I, rather imprudently, wished you good-night, and started for the Temple to see my husband. "We both thought the best resource was flight, when pursued by so formidable an antagonist; so you will find the nest empty when you call to-morrow. As to the photograph, your client may rest in peace. I love and am loved by a better man than he. The King may do what he will without hindrance from one whom he has cruelly wronged. I keep it only to safeguard myself, and to preserve a weapon which will always secure me from any steps which he might take in the future. I leave a photograph which he might care to possess; and I remain, dear Mr. Sherlock Holmes, "Very truly yours, "IRENE NORTON, née ADLER." "What a woman--oh, what a woman!" cried the King of Bohemia, when we had all three read this epistle. "Did I not tell you how quick and resolute she was? Would she not have made an admirable queen? Is it not a pity that she was not on my level?" "From what I have seen of the lady she seems indeed to be on a very different level to your Majesty," said Holmes coldly. "I am sorry that I have not been able to bring your Majesty's business to a more successful conclusion." "On the contrary, my dear sir," cried the King; "nothing could be more successful. I know that her word is inviolate. The photograph is now as safe as if it were in the fire." "I am glad to hear your Majesty say so." "I am immensely indebted to you. Pray tell me in what way I can reward you. This ring--" He slipped an emerald snake ring from his finger and held it out upon the palm of his hand. "Your Majesty has something which I should value even more highly," said Holmes. "You have but to name it." "This photograph!" The King stared at him in amazement. "Irene's photograph!" he cried. "Certainly, if you wish it." "I thank your Majesty. Then there is no more to be done in the matter. I have the honour to wish you a very good-morning." He bowed, and, turning away without observing the hand which the King had stretched out to him, he set off in my company for his chambers. And that was how a great scandal threatened to affect the kingdom of Bohemia, and how the best plans of Mr. Sherlock Holmes were beaten by a woman's wit. He used to make merry over the cleverness of women, but I have not heard him do it of late. And when he speaks of Irene Adler, or when he refers to her photograph, it is always under the honourable title of the woman. ADVENTURE II. THE RED-HEADED LEAGUE I had called upon my friend, Mr. Sherlock Holmes, one day in the autumn of last year and found him in deep conversation with a very stout, florid-faced, elderly gentleman with fiery red hair. With an apology for my intrusion, I was about to withdraw when Holmes pulled me abruptly into the room and closed the door behind me. "You could not possibly have come at a better time, my dear Watson," he said cordially. "I was afraid that you were engaged." "So I am. Very much so." "Then I can wait in the next room." "Not at all. This gentleman, Mr. Wilson, has been my partner and helper in many of my most successful cases, and I have no doubt that he will be of the utmost use to me in yours also." The stout gentleman half rose from his chair and gave a bob of greeting, with a quick little questioning glance from his small fat-encircled eyes. "Try the settee," said Holmes, relapsing into his armchair and putting his fingertips together, as was his custom when in judicial moods. "I know, my dear Watson, that you share my love of all that is bizarre and outside the conventions and humdrum routine of everyday life. You have shown your relish for it by the enthusiasm which has prompted you to chronicle, and, if you will excuse my saying so, somewhat to embellish so many of my own little adventures." "Your cases have indeed been of the greatest interest to me," I observed. "You will remember that I remarked the other day, just before we went into the very simple problem presented by Miss Mary Sutherland, that for strange effects and extraordinary combinations we must go to life itself, which is always far more daring than any effort of the imagination." "A proposition which I took the liberty of doubting." "You did, Doctor, but none the less you must come round to my view, for otherwise I shall keep on piling fact upon fact on you until your reason breaks down under them and acknowledges me to be right. Now, Mr. Jabez Wilson here has been good enough to call upon me this morning, and to begin a narrative which promises to be one of the most singular which I have listened to for some time. You have heard me remark that the strangest and most unique things are very often connected not with the larger but with the smaller crimes, and occasionally, indeed, where there is room for doubt whether any positive crime has been committed. As far as I have heard it is impossible for me to say whether the present case is an instance of crime or not, but the course of events is certainly among the most singular that I have ever listened to. Perhaps, Mr. Wilson, you would have the great kindness to recommence your narrative. I ask you not merely because my friend Dr. Watson has not heard the opening part but also because the peculiar nature of the story makes me anxious to have every possible detail from your lips. As a rule, when I have heard some slight indication of the course of events, I am able to guide myself by the thousands of other similar cases which occur to my memory. In the present instance I am forced to admit that the facts are, to the best of my belief, unique." The portly client puffed out his chest with an appearance of some little pride and pulled a dirty and wrinkled newspaper from the inside pocket of his greatcoat. As he glanced down the advertisement column, with his head thrust forward and the paper flattened out upon his knee, I took a good look at the man and endeavoured, after the fashion of my companion, to read the indications which might be presented by his dress or appearance. I did not gain very much, however, by my inspection. Our visitor bore every mark of being an average commonplace British tradesman, obese, pompous, and slow. He wore rather baggy grey shepherd's check trousers, a not over-clean black frock-coat, unbuttoned in the front, and a drab waistcoat with a heavy brassy Albert chain, and a square pierced bit of metal dangling down as an ornament. A frayed top-hat and a faded brown overcoat with a wrinkled velvet collar lay upon a chair beside him. Altogether, look as I would, there was nothing remarkable about the man save his blazing red head, and the expression of extreme chagrin and discontent upon his features. Sherlock Holmes' quick eye took in my occupation, and he shook his head with a smile as he noticed my questioning glances. "Beyond the obvious facts that he has at some time done manual labour, that he takes snuff, that he is a Freemason, that he has been in China, and that he has done a considerable amount of writing lately, I can deduce nothing else." Mr. Jabez Wilson started up in his chair, with his forefinger upon the paper, but his eyes upon my companion. "How, in the name of good-fortune, did you know all that, Mr. Holmes?" he asked. "How did you know, for example, that I did manual labour. It's as true as gospel, for I began as a ship's carpenter." "Your hands, my dear sir. Your right hand is quite a size larger than your left. You have worked with it, and the muscles are more developed." "Well, the snuff, then, and the Freemasonry?" "I won't insult your intelligence by telling you how I read that, especially as, rather against the strict rules of your order, you use an arc-and-compass breastpin." "Ah, of course, I forgot that. But the writing?" "What else can be indicated by that right cuff so very shiny for five inches, and the left one with the smooth patch near the elbow where you rest it upon the desk?" "Well, but China?" "The fish that you have tattooed immediately above your right wrist could only have been done in China. I have made a small study of tattoo marks and have even contributed to the literature of the subject. That trick of staining the fishes' scales of a delicate pink is quite peculiar to China. When, in addition, I see a Chinese coin hanging from your watch-chain, the matter becomes even more simple." Mr. Jabez Wilson laughed heavily. "Well, I never!" said he. "I thought at first that you had done something clever, but I see that there was nothing in it, after all." "I begin to think, Watson," said Holmes, "that I make a mistake in explaining. 'Omne ignotum pro magnifico,' you know, and my poor little reputation, such as it is, will suffer shipwreck if I am so candid. Can you not find the advertisement, Mr. Wilson?" "Yes, I have got it now," he answered with his thick red finger planted halfway down the column. "Here it is. This is what began it all. You just read it for yourself, sir." I took the paper from him and read as follows: "TO THE RED-HEADED LEAGUE: On account of the bequest of the late Ezekiah Hopkins, of Lebanon, Pennsylvania, U. S. A., there is now another vacancy open which entitles a member of the League to a salary of 4 pounds a week for purely nominal services. All red-headed men who are sound in body and mind and above the age of twenty-one years, are eligible. Apply in person on Monday, at eleven o'clock, to Duncan Ross, at the offices of the League, 7 Pope's Court, Fleet Street." "What on earth does this mean?" I ejaculated after I had twice read over the extraordinary announcement. Holmes chuckled and wriggled in his chair, as was his habit when in high spirits. "It is a little off the beaten track, isn't it?" said he. "And now, Mr. Wilson, off you go at scratch and tell us all about yourself, your household, and the effect which this advertisement had upon your fortunes. You will first make a note, Doctor, of the paper and the date." "It is The Morning Chronicle of April 27, 1890. Just two months ago." "Very good. Now, Mr. Wilson?" "Well, it is just as I have been telling you, Mr. Sherlock Holmes," said Jabez Wilson, mopping his forehead; "I have a small pawnbroker's business at Coburg Square, near the City. It's not a very large affair, and of late years it has not done more than just give me a living. I used to be able to keep two assistants, but now I only keep one; and I would have a job to pay him but that he is willing to come for half wages so as to learn the business." "What is the name of this obliging youth?" asked Sherlock Holmes. "His name is Vincent Spaulding, and he's not such a youth, either. It's hard to say his age. I should not wish a smarter assistant, Mr. Holmes; and I know very well that he could better himself and earn twice what I am able to give him. But, after all, if he is satisfied, why should I put ideas in his head?" "Why, indeed? You seem most fortunate in having an employé who comes under the full market price. It is not a common experience among employers in this age. I don't know that your assistant is not as remarkable as your advertisement." "Oh, he has his faults, too," said Mr. Wilson. "Never was such a fellow for photography. Snapping away with a camera when he ought to be improving his mind, and then diving down into the cellar like a rabbit into its hole to develop his pictures. That is his main fault, but on the whole he's a good worker. There's no vice in him." "He is still with you, I presume?" "Yes, sir. He and a girl of fourteen, who does a bit of simple cooking and keeps the place clean--that's all I have in the house, for I am a widower and never had any family. We live very quietly, sir, the three of us; and we keep a roof over our heads and pay our debts, if we do nothing more. "The first thing that put us out was that advertisement. Spaulding, he came down into the office just this day eight weeks, with this very paper in his hand, and he says: "'I wish to the Lord, Mr. Wilson, that I was a red-headed man.' "'Why that?' I asks. "'Why,' says he, 'here's another vacancy on the League of the Red-headed Men. It's worth quite a little fortune to any man who gets it, and I understand that there are more vacancies than there are men, so that the trustees are at their wits' end what to do with the money. If my hair would only change colour, here's a nice little crib all ready for me to step into.' "'Why, what is it, then?' I asked. You see, Mr. Holmes, I am a very stay-at-home man, and as my business came to me instead of my having to go to it, I was often weeks on end without putting my foot over the door-mat. In that way I didn't know much of what was going on outside, and I was always glad of a bit of news. "'Have you never heard of the League of the Red-headed Men?' he asked with his eyes open. "'Never.' "'Why, I wonder at that, for you are eligible yourself for one of the vacancies.' "'And what are they worth?' I asked. "'Oh, merely a couple of hundred a year, but the work is slight, and it need not interfere very much with one's other occupations.' "Well, you can easily think that that made me prick up my ears, for the business has not been over-good for some years, and an extra couple of hundred would have been very handy. "'Tell me all about it,' said I. "'Well,' said he, showing me the advertisement, 'you can see for yourself that the League has a vacancy, and there is the address where you should apply for particulars. As far as I can make out, the League was founded by an American millionaire, Ezekiah Hopkins, who was very peculiar in his ways. He was himself red-headed, and he had a great sympathy for all red-headed men; so when he died it was found that he had left his enormous fortune in the hands of trustees, with instructions to apply the interest to the providing of easy berths to men whose hair is of that colour. From all I hear it is splendid pay and very little to do.' "'But,' said I, 'there would be millions of red-headed men who would apply.' "'Not so many as you might think,' he answered. 'You see it is really confined to Londoners, and to grown men. This American had started from London when he was young, and he wanted to do the old town a good turn. Then, again, I have heard it is no use your applying if your hair is light red, or dark red, or anything but real bright, blazing, fiery red. Now, if you cared to apply, Mr. Wilson, you would just walk in; but perhaps it would hardly be worth your while to put yourself out of the way for the sake of a few hundred pounds.' "Now, it is a fact, gentlemen, as you may see for yourselves, that my hair is of a very full and rich tint, so that it seemed to me that if there was to be any competition in the matter I stood as good a chance as any man that I had ever met. Vincent Spaulding seemed to know so much about it that I thought he might prove useful, so I just ordered him to put up the shutters for the day and to come right away with me. He was very willing to have a holiday, so we shut the business up and started off for the address that was given us in the advertisement. "I never hope to see such a sight as that again, Mr. Holmes. From north, south, east, and west every man who had a shade of red in his hair had tramped into the city to answer the advertisement. Fleet Street was choked with red-headed folk, and Pope's Court looked like a coster's orange barrow. I should not have thought there were so many in the whole country as were brought together by that single advertisement. Every shade of colour they were--straw, lemon, orange, brick, Irish-setter, liver, clay; but, as Spaulding said, there were not many who had the real vivid flame-coloured tint. When I saw how many were waiting, I would have given it up in despair; but Spaulding would not hear of it. How he did it I could not imagine, but he pushed and pulled and butted until he got me through the crowd, and right up to the steps which led to the office. There was a double stream upon the stair, some going up in hope, and some coming back dejected; but we wedged in as well as we could and soon found ourselves in the office." "Your experience has been a most entertaining one," remarked Holmes as his client paused and refreshed his memory with a huge pinch of snuff. "Pray continue your very interesting statement." "There was nothing in the office but a couple of wooden chairs and a deal table, behind which sat a small man with a head that was even redder than mine. He said a few words to each candidate as he came up, and then he always managed to find some fault in them which would disqualify them. Getting a vacancy did not seem to be such a very easy matter, after all. However, when our turn came the little man was much more favourable to me than to any of the others, and he closed the door as we entered, so that he might have a private word with us. "'This is Mr. Jabez Wilson,' said my assistant, 'and he is willing to fill a vacancy in the League.' "'And he is admirably suited for it,' the other answered. 'He has every requirement. I cannot recall when I have seen anything so fine.' He took a step backward, cocked his head on one side, and gazed at my hair until I felt quite bashful. Then suddenly he plunged forward, wrung my hand, and congratulated me warmly on my success. "'It would be injustice to hesitate,' said he. 'You will, however, I am sure, excuse me for taking an obvious precaution.' With that he seized my hair in both his hands, and tugged until I yelled with the pain. 'There is water in your eyes,' said he as he released me. 'I perceive that all is as it should be. But we have to be careful, for we have twice been deceived by wigs and once by paint. I could tell you tales of cobbler's wax which would disgust you with human nature.' He stepped over to the window and shouted through it at the top of his voice that the vacancy was filled. A groan of disappointment came up from below, and the folk all trooped away in different directions until there was not a red-head to be seen except my own and that of the manager. "'My name,' said he, 'is Mr. Duncan Ross, and I am myself one of the pensioners upon the fund left by our noble benefactor. Are you a married man, Mr. Wilson? Have you a family?' "I answered that I had not. "His face fell immediately. "'Dear me!' he said gravely, 'that is very serious indeed! I am sorry to hear you say that. The fund was, of course, for the propagation and spread of the red-heads as well as for their maintenance. It is exceedingly unfortunate that you should be a bachelor.' "My face lengthened at this, Mr. Holmes, for I thought that I was not to have the vacancy after all; but after thinking it over for a few minutes he said that it would be all right. "'In the case of another,' said he, 'the objection might be fatal, but we must stretch a point in favour of a man with such a head of hair as yours. When shall you be able to enter upon your new duties?' "'Well, it is a little awkward, for I have a business already,' said I. "'Oh, never mind about that, Mr. Wilson!' said Vincent Spaulding. 'I should be able to look after that for you.' "'What would be the hours?' I asked. "'Ten to two.' "Now a pawnbroker's business is mostly done of an evening, Mr. Holmes, especially Thursday and Friday evening, which is just before pay-day; so it would suit me very well to earn a little in the mornings. Besides, I knew that my assistant was a good man, and that he would see to anything that turned up. "'That would suit me very well,' said I. 'And the pay?' "'Is 4 pounds a week.' "'And the work?' "'Is purely nominal.' "'What do you call purely nominal?' "'Well, you have to be in the office, or at least in the building, the whole time. If you leave, you forfeit your whole position forever. The will is very clear upon that point. You don't comply with the conditions if you budge from the office during that time.' "'It's only four hours a day, and I should not think of leaving,' said I. "'No excuse will avail,' said Mr. Duncan Ross; 'neither sickness nor business nor anything else. There you must stay, or you lose your billet.' "'And the work?' "'Is to copy out the "Encyclopaedia Britannica." There is the first volume of it in that press. You must find your own ink, pens, and blotting-paper, but we provide this table and chair. Will you be ready to-morrow?' "'Certainly,' I answered. "'Then, good-bye, Mr. Jabez Wilson, and let me congratulate you once more on the important position which you have been fortunate enough to gain.' He bowed me out of the room and I went home with my assistant, hardly knowing what to say or do, I was so pleased at my own good fortune. "Well, I thought over the matter all day, and by evening I was in low spirits again; for I had quite persuaded myself that the whole affair must be some great hoax or fraud, though what its object might be I could not imagine. It seemed altogether past belief that anyone could make such a will, or that they would pay such a sum for doing anything so simple as copying out the 'Encyclopaedia Britannica.' Vincent Spaulding did what he could to cheer me up, but by bedtime I had reasoned myself out of the whole thing. However, in the morning I determined to have a look at it anyhow, so I bought a penny bottle of ink, and with a quill-pen, and seven sheets of foolscap paper, I started off for Pope's Court. "Well, to my surprise and delight, everything was as right as possible. The table was set out ready for me, and Mr. Duncan Ross was there to see that I got fairly to work. He started me off upon the letter A, and then he left me; but he would drop in from time to time to see that all was right with me. At two o'clock he bade me good-day, complimented me upon the amount that I had written, and locked the door of the office after me. "This went on day after day, Mr. Holmes, and on Saturday the manager came in and planked down four golden sovereigns for my week's work. It was the same next week, and the same the week after. Every morning I was there at ten, and every afternoon I left at two. By degrees Mr. Duncan Ross took to coming in only once of a morning, and then, after a time, he did not come in at all. Still, of course, I never dared to leave the room for an instant, for I was not sure when he might come, and the billet was such a good one, and suited me so well, that I would not risk the loss of it. "Eight weeks passed away like this, and I had written about Abbots and Archery and Armour and Architecture and Attica, and hoped with diligence that I might get on to the B's before very long. It cost me something in foolscap, and I had pretty nearly filled a shelf with my writings. And then suddenly the whole business came to an end." "To an end?" "Yes, sir. And no later than this morning. I went to my work as usual at ten o'clock, but the door was shut and locked, with a little square of cardboard hammered on to the middle of the panel with a tack. Here it is, and you can read for yourself." He held up a piece of white cardboard about the size of a sheet of note-paper. It read in this fashion: THE RED-HEADED LEAGUE IS DISSOLVED. October 9, 1890. Sherlock Holmes and I surveyed this curt announcement and the rueful face behind it, until the comical side of the affair so completely overtopped every other consideration that we both burst out into a roar of laughter. "I cannot see that there is anything very funny," cried our client, flushing up to the roots of his flaming head. "If you can do nothing better than laugh at me, I can go elsewhere." "No, no," cried Holmes, shoving him back into the chair from which he had half risen. "I really wouldn't miss your case for the world. It is most refreshingly unusual. But there is, if you will excuse my saying so, something just a little funny about it. Pray what steps did you take when you found the card upon the door?" "I was staggered, sir. I did not know what to do. Then I called at the offices round, but none of them seemed to know anything about it. Finally, I went to the landlord, who is an accountant living on the ground-floor, and I asked him if he could tell me what had become of the Red-headed League. He said that he had never heard of any such body. Then I asked him who Mr. Duncan Ross was. He answered that the name was new to him. "'Well,' said I, 'the gentleman at No. 4.' "'What, the red-headed man?' "'Yes.' "'Oh,' said he, 'his name was William Morris. He was a solicitor and was using my room as a temporary convenience until his new premises were ready. He moved out yesterday.' "'Where could I find him?' "'Oh, at his new offices. He did tell me the address. Yes, 17 King Edward Street, near St. Paul's.' "I started off, Mr. Holmes, but when I got to that address it was a manufactory of artificial knee-caps, and no one in it had ever heard of either Mr. William Morris or Mr. Duncan Ross." "And what did you do then?" asked Holmes. "I went home to Saxe-Coburg Square, and I took the advice of my assistant. But he could not help me in any way. He could only say that if I waited I should hear by post. But that was not quite good enough, Mr. Holmes. I did not wish to lose such a place without a struggle, so, as I had heard that you were good enough to give advice to poor folk who were in need of it, I came right away to you." "And you did very wisely," said Holmes. "Your case is an exceedingly remarkable one, and I shall be happy to look into it. From what you have told me I think that it is possible that graver issues hang from it than might at first sight appear." "Grave enough!" said Mr. Jabez Wilson. "Why, I have lost four pound a week." "As far as you are personally concerned," remarked Holmes, "I do not see that you have any grievance against this extraordinary league. On the contrary, you are, as I understand, richer by some 30 pounds, to say nothing of the minute knowledge which you have gained on every subject which comes under the letter A. You have lost nothing by them." "No, sir. But I want to find out about them, and who they are, and what their object was in playing this prank--if it was a prank--upon me. It was a pretty expensive joke for them, for it cost them two and thirty pounds." "We shall endeavour to clear up these points for you. And, first, one or two questions, Mr. Wilson. This assistant of yours who first called your attention to the advertisement--how long had he been with you?" "About a month then." "How did he come?" "In answer to an advertisement." "Was he the only applicant?" "No, I had a dozen." "Why did you pick him?" "Because he was handy and would come cheap." "At half-wages, in fact." "Yes." "What is he like, this Vincent Spaulding?" "Small, stout-built, very quick in his ways, no hair on his face, though he's not short of thirty. Has a white splash of acid upon his forehead." Holmes sat up in his chair in considerable excitement. "I thought as much," said he. "Have you ever observed that his ears are pierced for earrings?" "Yes, sir. He told me that a gipsy had done it for him when he was a lad." "Hum!" said Holmes, sinking back in deep thought. "He is still with you?" "Oh, yes, sir; I have only just left him." "And has your business been attended to in your absence?" "Nothing to complain of, sir. There's never very much to do of a morning." "That will do, Mr. Wilson. I shall be happy to give you an opinion upon the subject in the course of a day or two. To-day is Saturday, and I hope that by Monday we may come to a conclusion." "Well, Watson," said Holmes when our visitor had left us, "what do you make of it all?" "I make nothing of it," I answered frankly. "It is a most mysterious business." "As a rule," said Holmes, "the more bizarre a thing is the less mysterious it proves to be. It is your commonplace, featureless crimes which are really puzzling, just as a commonplace face is the most difficult to identify. But I must be prompt over this matter." "What are you going to do, then?" I asked. "To smoke," he answered. "It is quite a three pipe problem, and I beg that you won't speak to me for fifty minutes." He curled himself up in his chair, with his thin knees drawn up to his hawk-like nose, and there he sat with his eyes closed and his black clay pipe thrusting out like the bill of some strange bird. I had come to the conclusion that he had dropped asleep, and indeed was nodding myself, when he suddenly sprang out of his chair with the gesture of a man who has made up his mind and put his pipe down upon the mantelpiece. "Sarasate plays at the St. James's Hall this afternoon," he remarked. "What do you think, Watson? Could your patients spare you for a few hours?" "I have nothing to do to-day. My practice is never very absorbing." "Then put on your hat and come. I am going through the City first, and we can have some lunch on the way. I observe that there is a good deal of German music on the programme, which is rather more to my taste than Italian or French. It is introspective, and I want to introspect. Come along!" We travelled by the Underground as far as Aldersgate; and a short walk took us to Saxe-Coburg Square, the scene of the singular story which we had listened to in the morning. It was a poky, little, shabby-genteel place, where four lines of dingy two-storied brick houses looked out into a small railed-in enclosure, where a lawn of weedy grass and a few clumps of faded laurel-bushes made a hard fight against a smoke-laden and uncongenial atmosphere. Three gilt balls and a brown board with "JABEZ WILSON" in white letters, upon a corner house, announced the place where our red-headed client carried on his business. Sherlock Holmes stopped in front of it with his head on one side and looked it all over, with his eyes shining brightly between puckered lids. Then he walked slowly up the street, and then down again to the corner, still looking keenly at the houses. Finally he returned to the pawnbroker's, and, having thumped vigorously upon the pavement with his stick two or three times, he went up to the door and knocked. It was instantly opened by a bright-looking, clean-shaven young fellow, who asked him to step in. "Thank you," said Holmes, "I only wished to ask you how you would go from here to the Strand." "Third right, fourth left," answered the assistant promptly, closing the door. "Smart fellow, that," observed Holmes as we walked away. "He is, in my judgment, the fourth smartest man in London, and for daring I am not sure that he has not a claim to be third. I have known something of him before." "Evidently," said I, "Mr. Wilson's assistant counts for a good deal in this mystery of the Red-headed League. I am sure that you inquired your way merely in order that you might see him." "Not him." "What then?" "The knees of his trousers." "And what did you see?" "What I expected to see." "Why did you beat the pavement?" "My dear doctor, this is a time for observation, not for talk. We are spies in an enemy's country. We know something of Saxe-Coburg Square. Let us now explore the parts which lie behind it." The road in which we found ourselves as we turned round the corner from the retired Saxe-Coburg Square presented as great a contrast to it as the front of a picture does to the back. It was one of the main arteries which conveyed the traffic of the City to the north and west. The roadway was blocked with the immense stream of commerce flowing in a double tide inward and outward, while the footpaths were black with the hurrying swarm of pedestrians. It was difficult to realise as we looked at the line of fine shops and stately business premises that they really abutted on the other side upon the faded and stagnant square which we had just quitted. "Let me see," said Holmes, standing at the corner and glancing along the line, "I should like just to remember the order of the houses here. It is a hobby of mine to have an exact knowledge of London. There is Mortimer's, the tobacconist, the little newspaper shop, the Coburg branch of the City and Suburban Bank, the Vegetarian Restaurant, and McFarlane's carriage-building depot. That carries us right on to the other block. And now, Doctor, we've done our work, so it's time we had some play. A sandwich and a cup of coffee, and then off to violin-land, where all is sweetness and delicacy and harmony, and there are no red-headed clients to vex us with their conundrums." My friend was an enthusiastic musician, being himself not only a very capable performer but a composer of no ordinary merit. All the afternoon he sat in the stalls wrapped in the most perfect happiness, gently waving his long, thin fingers in time to the music, while his gently smiling face and his languid, dreamy eyes were as unlike those of Holmes the sleuth-hound, Holmes the relentless, keen-witted, ready-handed criminal agent, as it was possible to conceive. In his singular character the dual nature alternately asserted itself, and his extreme exactness and astuteness represented, as I have often thought, the reaction against the poetic and contemplative mood which occasionally predominated in him. The swing of his nature took him from extreme languor to devouring energy; and, as I knew well, he was never so truly formidable as when, for days on end, he had been lounging in his armchair amid his improvisations and his black-letter editions. Then it was that the lust of the chase would suddenly come upon him, and that his brilliant reasoning power would rise to the level of intuition, until those who were unacquainted with his methods would look askance at him as on a man whose knowledge was not that of other mortals. When I saw him that afternoon so enwrapped in the music at St. James's Hall I felt that an evil time might be coming upon those whom he had set himself to hunt down. "You want to go home, no doubt, Doctor," he remarked as we emerged. "Yes, it would be as well." "And I have some business to do which will take some hours. This business at Coburg Square is serious." "Why serious?" "A considerable crime is in contemplation. I have every reason to believe that we shall be in time to stop it. But to-day being Saturday rather complicates matters. I shall want your help to-night." "At what time?" "Ten will be early enough." "I shall be at Baker Street at ten." "Very well. And, I say, Doctor, there may be some little danger, so kindly put your army revolver in your pocket." He waved his hand, turned on his heel, and disappeared in an instant among the crowd. I trust that I am not more dense than my neighbours, but I was always oppressed with a sense of my own stupidity in my dealings with Sherlock Holmes. Here I had heard what he had heard, I had seen what he had seen, and yet from his words it was evident that he saw clearly not only what had happened but what was about to happen, while to me the whole business was still confused and grotesque. As I drove home to my house in Kensington I thought over it all, from the extraordinary story of the red-headed copier of the "Encyclopaedia" down to the visit to Saxe-Coburg Square, and the ominous words with which he had parted from me. What was this nocturnal expedition, and why should I go armed? Where were we going, and what were we to do? I had the hint from Holmes that this smooth-faced pawnbroker's assistant was a formidable man--a man who might play a deep game. I tried to puzzle it out, but gave it up in despair and set the matter aside until night should bring an explanation. It was a quarter-past nine when I started from home and made my way across the Park, and so through Oxford Street to Baker Street. Two hansoms were standing at the door, and as I entered the passage I heard the sound of voices from above. On entering his room I found Holmes in animated conversation with two men, one of whom I recognised as Peter Jones, the official police agent, while the other was a long, thin, sad-faced man, with a very shiny hat and oppressively respectable frock-coat. "Ha! Our party is complete," said Holmes, buttoning up his pea-jacket and taking his heavy hunting crop from the rack. "Watson, I think you know Mr. Jones, of Scotland Yard? Let me introduce you to Mr. Merryweather, who is to be our companion in to-night's adventure." "We're hunting in couples again, Doctor, you see," said Jones in his consequential way. "Our friend here is a wonderful man for starting a chase. All he wants is an old dog to help him to do the running down." "I hope a wild goose may not prove to be the end of our chase," observed Mr. Merryweather gloomily. "You may place considerable confidence in Mr. Holmes, sir," said the police agent loftily. "He has his own little methods, which are, if he won't mind my saying so, just a little too theoretical and fantastic, but he has the makings of a detective in him. It is not too much to say that once or twice, as in that business of the Sholto murder and the Agra treasure, he has been more nearly correct than the official force." "Oh, if you say so, Mr. Jones, it is all right," said the stranger with deference. "Still, I confess that I miss my rubber. It is the first Saturday night for seven-and-twenty years that I have not had my rubber." "I think you will find," said Sherlock Holmes, "that you will play for a higher stake to-night than you have ever done yet, and that the play will be more exciting. For you, Mr. Merryweather, the stake will be some 30,000 pounds; and for you, Jones, it will be the man upon whom you wish to lay your hands." "John Clay, the murderer, thief, smasher, and forger. He's a young man, Mr. Merryweather, but he is at the head of his profession, and I would rather have my bracelets on him than on any criminal in London. He's a remarkable man, is young John Clay. His grandfather was a royal duke, and he himself has been to Eton and Oxford. His brain is as cunning as his fingers, and though we meet signs of him at every turn, we never know where to find the man himself. He'll crack a crib in Scotland one week, and be raising money to build an orphanage in Cornwall the next. I've been on his track for years and have never set eyes on him yet." "I hope that I may have the pleasure of introducing you to-night. I've had one or two little turns also with Mr. John Clay, and I agree with you that he is at the head of his profession. It is past ten, however, and quite time that we started. If you two will take the first hansom, Watson and I will follow in the second." Sherlock Holmes was not very communicative during the long drive and lay back in the cab humming the tunes which he had heard in the afternoon. We rattled through an endless labyrinth of gas-lit streets until we emerged into Farrington Street. "We are close there now," my friend remarked. "This fellow Merryweather is a bank director, and personally interested in the matter. I thought it as well to have Jones with us also. He is not a bad fellow, though an absolute imbecile in his profession. He has one positive virtue. He is as brave as a bulldog and as tenacious as a lobster if he gets his claws upon anyone. Here we are, and they are waiting for us." We had reached the same crowded thoroughfare in which we had found ourselves in the morning. Our cabs were dismissed, and, following the guidance of Mr. Merryweather, we passed down a narrow passage and through a side door, which he opened for us. Within there was a small corridor, which ended in a very massive iron gate. This also was opened, and led down a flight of winding stone steps, which terminated at another formidable gate. Mr. Merryweather stopped to light a lantern, and then conducted us down a dark, earth-smelling passage, and so, after opening a third door, into a huge vault or cellar, which was piled all round with crates and massive boxes. "You are not very vulnerable from above," Holmes remarked as he held up the lantern and gazed about him. "Nor from below," said Mr. Merryweather, striking his stick upon the flags which lined the floor. "Why, dear me, it sounds quite hollow!" he remarked, looking up in surprise. "I must really ask you to be a little more quiet!" said Holmes severely. "You have already imperilled the whole success of our expedition. Might I beg that you would have the goodness to sit down upon one of those boxes, and not to interfere?" The solemn Mr. Merryweather perched himself upon a crate, with a very injured expression upon his face, while Holmes fell upon his knees upon the floor and, with the lantern and a magnifying lens, began to examine minutely the cracks between the stones. A few seconds sufficed to satisfy him, for he sprang to his feet again and put his glass in his pocket. "We have at least an hour before us," he remarked, "for they can hardly take any steps until the good pawnbroker is safely in bed. Then they will not lose a minute, for the sooner they do their work the longer time they will have for their escape. We are at present, Doctor--as no doubt you have divined--in the cellar of the City branch of one of the principal London banks. Mr. Merryweather is the chairman of directors, and he will explain to you that there are reasons why the more daring criminals of London should take a considerable interest in this cellar at present." "It is our French gold," whispered the director. "We have had several warnings that an attempt might be made upon it." "Your French gold?" "Yes. We had occasion some months ago to strengthen our resources and borrowed for that purpose 30,000 napoleons from the Bank of France. It has become known that we have never had occasion to unpack the money, and that it is still lying in our cellar. The crate upon which I sit contains 2,000 napoleons packed between layers of lead foil. Our reserve of bullion is much larger at present than is usually kept in a single branch office, and the directors have had misgivings upon the subject." "Which were very well justified," observed Holmes. "And now it is time that we arranged our little plans. I expect that within an hour matters will come to a head. In the meantime Mr. Merryweather, we must put the screen over that dark lantern." "And sit in the dark?" "I am afraid so. I had brought a pack of cards in my pocket, and I thought that, as we were a partie carrée, you might have your rubber after all. But I see that the enemy's preparations have gone so far that we cannot risk the presence of a light. And, first of all, we must choose our positions. These are daring men, and though we shall take them at a disadvantage, they may do us some harm unless we are careful. I shall stand behind this crate, and do you conceal yourselves behind those. Then, when I flash a light upon them, close in swiftly. If they fire, Watson, have no compunction about shooting them down." I placed my revolver, cocked, upon the top of the wooden case behind which I crouched. Holmes shot the slide across the front of his lantern and left us in pitch darkness--such an absolute darkness as I have never before experienced. The smell of hot metal remained to assure us that the light was still there, ready to flash out at a moment's notice. To me, with my nerves worked up to a pitch of expectancy, there was something depressing and subduing in the sudden gloom, and in the cold dank air of the vault. "They have but one retreat," whispered Holmes. "That is back through the house into Saxe-Coburg Square. I hope that you have done what I asked you, Jones?" "I have an inspector and two officers waiting at the front door." "Then we have stopped all the holes. And now we must be silent and wait." What a time it seemed! From comparing notes afterwards it was but an hour and a quarter, yet it appeared to me that the night must have almost gone and the dawn be breaking above us. My limbs were weary and stiff, for I feared to change my position; yet my nerves were worked up to the highest pitch of tension, and my hearing was so acute that I could not only hear the gentle breathing of my companions, but I could distinguish the deeper, heavier in-breath of the bulky Jones from the thin, sighing note of the bank director. From my position I could look over the case in the direction of the floor. Suddenly my eyes caught the glint of a light. At first it was but a lurid spark upon the stone pavement. Then it lengthened out until it became a yellow line, and then, without any warning or sound, a gash seemed to open and a hand appeared, a white, almost womanly hand, which felt about in the centre of the little area of light. For a minute or more the hand, with its writhing fingers, protruded out of the floor. Then it was withdrawn as suddenly as it appeared, and all was dark again save the single lurid spark which marked a chink between the stones. Its disappearance, however, was but momentary. With a rending, tearing sound, one of the broad, white stones turned over upon its side and left a square, gaping hole, through which streamed the light of a lantern. Over the edge there peeped a clean-cut, boyish face, which looked keenly about it, and then, with a hand on either side of the aperture, drew itself shoulder-high and waist-high, until one knee rested upon the edge. In another instant he stood at the side of the hole and was hauling after him a companion, lithe and small like himself, with a pale face and a shock of very red hair. "It's all clear," he whispered. "Have you the chisel and the bags? Great Scott! Jump, Archie, jump, and I'll swing for it!" Sherlock Holmes had sprung out and seized the intruder by the collar. The other dived down the hole, and I heard the sound of rending cloth as Jones clutched at his skirts. The light flashed upon the barrel of a revolver, but Holmes' hunting crop came down on the man's wrist, and the pistol clinked upon the stone floor. "It's no use, John Clay," said Holmes blandly. "You have no chance at all." "So I see," the other answered with the utmost coolness. "I fancy that my pal is all right, though I see you have got his coat-tails." "There are three men waiting for him at the door," said Holmes. "Oh, indeed! You seem to have done the thing very completely. I must compliment you." "And I you," Holmes answered. "Your red-headed idea was very new and effective." "You'll see your pal again presently," said Jones. "He's quicker at climbing down holes than I am. Just hold out while I fix the derbies." "I beg that you will not touch me with your filthy hands," remarked our prisoner as the handcuffs clattered upon his wrists. "You may not be aware that I have royal blood in my veins. Have the goodness, also, when you address me always to say 'sir' and 'please.'" "All right," said Jones with a stare and a snigger. "Well, would you please, sir, march upstairs, where we can get a cab to carry your Highness to the police-station?" "That is better," said John Clay serenely. He made a sweeping bow to the three of us and walked quietly off in the custody of the detective. "Really, Mr. Holmes," said Mr. Merryweather as we followed them from the cellar, "I do not know how the bank can thank you or repay you. There is no doubt that you have detected and defeated in the most complete manner one of the most determined attempts at bank robbery that have ever come within my experience." "I have had one or two little scores of my own to settle with Mr. John Clay," said Holmes. "I have been at some small expense over this matter, which I shall expect the bank to refund, but beyond that I am amply repaid by having had an experience which is in many ways unique, and by hearing the very remarkable narrative of the Red-headed League." "You see, Watson," he explained in the early hours of the morning as we sat over a glass of whisky and soda in Baker Street, "it was perfectly obvious from the first that the only possible object of this rather fantastic business of the advertisement of the League, and the copying of the 'Encyclopaedia,' must be to get this not over-bright pawnbroker out of the way for a number of hours every day. It was a curious way of managing it, but, really, it would be difficult to suggest a better. The method was no doubt suggested to Clay's ingenious mind by the colour of his accomplice's hair. The 4 pounds a week was a lure which must draw him, and what was it to them, who were playing for thousands? They put in the advertisement, one rogue has the temporary office, the other rogue incites the man to apply for it, and together they manage to secure his absence every morning in the week. From the time that I heard of the assistant having come for half wages, it was obvious to me that he had some strong motive for securing the situation." "But how could you guess what the motive was?" "Had there been women in the house, I should have suspected a mere vulgar intrigue. That, however, was out of the question. The man's business was a small one, and there was nothing in his house which could account for such elaborate preparations, and such an expenditure as they were at. It must, then, be something out of the house. What could it be? I thought of the assistant's fondness for photography, and his trick of vanishing into the cellar. The cellar! There was the end of this tangled clue. Then I made inquiries as to this mysterious assistant and found that I had to deal with one of the coolest and most daring criminals in London. He was doing something in the cellar--something which took many hours a day for months on end. What could it be, once more? I could think of nothing save that he was running a tunnel to some other building. "So far I had got when we went to visit the scene of action. I surprised you by beating upon the pavement with my stick. I was ascertaining whether the cellar stretched out in front or behind. It was not in front. Then I rang the bell, and, as I hoped, the assistant answered it. We have had some skirmishes, but we had never set eyes upon each other before. I hardly looked at his face. His knees were what I wished to see. You must yourself have remarked how worn, wrinkled, and stained they were. They spoke of those hours of burrowing. The only remaining point was what they were burrowing for. I walked round the corner, saw the City and Suburban Bank abutted on our friend's premises, and felt that I had solved my problem. When you drove home after the concert I called upon Scotland Yard and upon the chairman of the bank directors, with the result that you have seen." "And how could you tell that they would make their attempt to-night?" I asked. "Well, when they closed their League offices that was a sign that they cared no longer about Mr. Jabez Wilson's presence--in other words, that they had completed their tunnel. But it was essential that they should use it soon, as it might be discovered, or the bullion might be removed. Saturday would suit them better than any other day, as it would give them two days for their escape. For all these reasons I expected them to come to-night." "You reasoned it out beautifully," I exclaimed in unfeigned admiration. "It is so long a chain, and yet every link rings true." "It saved me from ennui," he answered, yawning. "Alas! I already feel it closing in upon me. My life is spent in one long effort to escape from the commonplaces of existence. These little problems help me to do so." "And you are a benefactor of the race," said I. He shrugged his shoulders. "Well, perhaps, after all, it is of some little use," he remarked. "'L'homme c'est rien--l'oeuvre c'est tout,' as Gustave Flaubert wrote to George Sand." ADVENTURE III. A CASE OF IDENTITY "My dear fellow," said Sherlock Holmes as we sat on either side of the fire in his lodgings at Baker Street, "life is infinitely stranger than anything which the mind of man could invent. We would not dare to conceive the things which are really mere commonplaces of existence. If we could fly out of that window hand in hand, hover over this great city, gently remove the roofs, and peep in at the queer things which are going on, the strange coincidences, the plannings, the cross-purposes, the wonderful chains of events, working through generations, and leading to the most outré results, it would make all fiction with its conventionalities and foreseen conclusions most stale and unprofitable." "And yet I am not convinced of it," I answered. "The cases which come to light in the papers are, as a rule, bald enough, and vulgar enough. We have in our police reports realism pushed to its extreme limits, and yet the result is, it must be confessed, neither fascinating nor artistic." "A certain selection and discretion must be used in producing a realistic effect," remarked Holmes. "This is wanting in the police report, where more stress is laid, perhaps, upon the platitudes of the magistrate than upon the details, which to an observer contain the vital essence of the whole matter. Depend upon it, there is nothing so unnatural as the commonplace." I smiled and shook my head. "I can quite understand your thinking so," I said. "Of course, in your position of unofficial adviser and helper to everybody who is absolutely puzzled, throughout three continents, you are brought in contact with all that is strange and bizarre. But here"--I picked up the morning paper from the ground--"let us put it to a practical test. Here is the first heading upon which I come. 'A husband's cruelty to his wife.' There is half a column of print, but I know without reading it that it is all perfectly familiar to me. There is, of course, the other woman, the drink, the push, the blow, the bruise, the sympathetic sister or landlady. The crudest of writers could invent nothing more crude." "Indeed, your example is an unfortunate one for your argument," said Holmes, taking the paper and glancing his eye down it. "This is the Dundas separation case, and, as it happens, I was engaged in clearing up some small points in connection with it. The husband was a teetotaler, there was no other woman, and the conduct complained of was that he had drifted into the habit of winding up every meal by taking out his false teeth and hurling them at his wife, which, you will allow, is not an action likely to occur to the imagination of the average story-teller. Take a pinch of snuff, Doctor, and acknowledge that I have scored over you in your example." He held out his snuffbox of old gold, with a great amethyst in the centre of the lid. Its splendour was in such contrast to his homely ways and simple life that I could not help commenting upon it. "Ah," said he, "I forgot that I had not seen you for some weeks. It is a little souvenir from the King of Bohemia in return for my assistance in the case of the Irene Adler papers." "And the ring?" I asked, glancing at a remarkable brilliant which sparkled upon his finger. "It was from the reigning family of Holland, though the matter in which I served them was of such delicacy that I cannot confide it even to you, who have been good enough to chronicle one or two of my little problems." "And have you any on hand just now?" I asked with interest. "Some ten or twelve, but none which present any feature of interest. They are important, you understand, without being interesting. Indeed, I have found that it is usually in unimportant matters that there is a field for the observation, and for the quick analysis of cause and effect which gives the charm to an investigation. The larger crimes are apt to be the simpler, for the bigger the crime the more obvious, as a rule, is the motive. In these cases, save for one rather intricate matter which has been referred to me from Marseilles, there is nothing which presents any features of interest. It is possible, however, that I may have something better before very many minutes are over, for this is one of my clients, or I am much mistaken." He had risen from his chair and was standing between the parted blinds gazing down into the dull neutral-tinted London street. Looking over his shoulder, I saw that on the pavement opposite there stood a large woman with a heavy fur boa round her neck, and a large curling red feather in a broad-brimmed hat which was tilted in a coquettish Duchess of Devonshire fashion over her ear. From under this great panoply she peeped up in a nervous, hesitating fashion at our windows, while her body oscillated backward and forward, and her fingers fidgeted with her glove buttons. Suddenly, with a plunge, as of the swimmer who leaves the bank, she hurried across the road, and we heard the sharp clang of the bell. "I have seen those symptoms before," said Holmes, throwing his cigarette into the fire. "Oscillation upon the pavement always means an affaire de coeur. She would like advice, but is not sure that the matter is not too delicate for communication. And yet even here we may discriminate. When a woman has been seriously wronged by a man she no longer oscillates, and the usual symptom is a broken bell wire. Here we may take it that there is a love matter, but that the maiden is not so much angry as perplexed, or grieved. But here she comes in person to resolve our doubts." As he spoke there was a tap at the door, and the boy in buttons entered to announce Miss Mary Sutherland, while the lady herself loomed behind his small black figure like a full-sailed merchant-man behind a tiny pilot boat. Sherlock Holmes welcomed her with the easy courtesy for which he was remarkable, and, having closed the door and bowed her into an armchair, he looked her over in the minute and yet abstracted fashion which was peculiar to him. "Do you not find," he said, "that with your short sight it is a little trying to do so much typewriting?" "I did at first," she answered, "but now I know where the letters are without looking." Then, suddenly realising the full purport of his words, she gave a violent start and looked up, with fear and astonishment upon her broad, good-humoured face. "You've heard about me, Mr. Holmes," she cried, "else how could you know all that?" "Never mind," said Holmes, laughing; "it is my business to know things. Perhaps I have trained myself to see what others overlook. If not, why should you come to consult me?" "I came to you, sir, because I heard of you from Mrs. Etherege, whose husband you found so easy when the police and everyone had given him up for dead. Oh, Mr. Holmes, I wish you would do as much for me. I'm not rich, but still I have a hundred a year in my own right, besides the little that I make by the machine, and I would give it all to know what has become of Mr. Hosmer Angel." "Why did you come away to consult me in such a hurry?" asked Sherlock Holmes, with his finger-tips together and his eyes to the ceiling. Again a startled look came over the somewhat vacuous face of Miss Mary Sutherland. "Yes, I did bang out of the house," she said, "for it made me angry to see the easy way in which Mr. Windibank--that is, my father--took it all. He would not go to the police, and he would not go to you, and so at last, as he would do nothing and kept on saying that there was no harm done, it made me mad, and I just on with my things and came right away to you." "Your father," said Holmes, "your stepfather, surely, since the name is different." "Yes, my stepfather. I call him father, though it sounds funny, too, for he is only five years and two months older than myself." "And your mother is alive?" "Oh, yes, mother is alive and well. I wasn't best pleased, Mr. Holmes, when she married again so soon after father's death, and a man who was nearly fifteen years younger than herself. Father was a plumber in the Tottenham Court Road, and he left a tidy business behind him, which mother carried on with Mr. Hardy, the foreman; but when Mr. Windibank came he made her sell the business, for he was very superior, being a traveller in wines. They got 4700 pounds for the goodwill and interest, which wasn't near as much as father could have got if he had been alive." I had expected to see Sherlock Holmes impatient under this rambling and inconsequential narrative, but, on the contrary, he had listened with the greatest concentration of attention. "Your own little income," he asked, "does it come out of the business?" "Oh, no, sir. It is quite separate and was left me by my uncle Ned in Auckland. It is in New Zealand stock, paying 4 1/2 per cent. Two thousand five hundred pounds was the amount, but I can only touch the interest." "You interest me extremely," said Holmes. "And since you draw so large a sum as a hundred a year, with what you earn into the bargain, you no doubt travel a little and indulge yourself in every way. I believe that a single lady can get on very nicely upon an income of about 60 pounds." "I could do with much less than that, Mr. Holmes, but you understand that as long as I live at home I don't wish to be a burden to them, and so they have the use of the money just while I am staying with them. Of course, that is only just for the time. Mr. Windibank draws my interest every quarter and pays it over to mother, and I find that I can do pretty well with what I earn at typewriting. It brings me twopence a sheet, and I can often do from fifteen to twenty sheets in a day." "You have made your position very clear to me," said Holmes. "This is my friend, Dr. Watson, before whom you can speak as freely as before myself. Kindly tell us now all about your connection with Mr. Hosmer Angel." A flush stole over Miss Sutherland's face, and she picked nervously at the fringe of her jacket. "I met him first at the gasfitters' ball," she said. "They used to send father tickets when he was alive, and then afterwards they remembered us, and sent them to mother. Mr. Windibank did not wish us to go. He never did wish us to go anywhere. He would get quite mad if I wanted so much as to join a Sunday-school treat. But this time I was set on going, and I would go; for what right had he to prevent? He said the folk were not fit for us to know, when all father's friends were to be there. And he said that I had nothing fit to wear, when I had my purple plush that I had never so much as taken out of the drawer. At last, when nothing else would do, he went off to France upon the business of the firm, but we went, mother and I, with Mr. Hardy, who used to be our foreman, and it was there I met Mr. Hosmer Angel." "I suppose," said Holmes, "that when Mr. Windibank came back from France he was very annoyed at your having gone to the ball." "Oh, well, he was very good about it. He laughed, I remember, and shrugged his shoulders, and said there was no use denying anything to a woman, for she would have her way." "I see. Then at the gasfitters' ball you met, as I understand, a gentleman called Mr. Hosmer Angel." "Yes, sir. I met him that night, and he called next day to ask if we had got home all safe, and after that we met him--that is to say, Mr. Holmes, I met him twice for walks, but after that father came back again, and Mr. Hosmer Angel could not come to the house any more." "No?" "Well, you know father didn't like anything of the sort. He wouldn't have any visitors if he could help it, and he used to say that a woman should be happy in her own family circle. But then, as I used to say to mother, a woman wants her own circle to begin with, and I had not got mine yet." "But how about Mr. Hosmer Angel? Did he make no attempt to see you?" "Well, father was going off to France again in a week, and Hosmer wrote and said that it would be safer and better not to see each other until he had gone. We could write in the meantime, and he used to write every day. I took the letters in in the morning, so there was no need for father to know." "Were you engaged to the gentleman at this time?" "Oh, yes, Mr. Holmes. We were engaged after the first walk that we took. Hosmer--Mr. Angel--was a cashier in an office in Leadenhall Street--and--" "What office?" "That's the worst of it, Mr. Holmes, I don't know." "Where did he live, then?" "He slept on the premises." "And you don't know his address?" "No--except that it was Leadenhall Street." "Where did you address your letters, then?" "To the Leadenhall Street Post Office, to be left till called for. He said that if they were sent to the office he would be chaffed by all the other clerks about having letters from a lady, so I offered to typewrite them, like he did his, but he wouldn't have that, for he said that when I wrote them they seemed to come from me, but when they were typewritten he always felt that the machine had come between us. That will just show you how fond he was of me, Mr. Holmes, and the little things that he would think of." "It was most suggestive," said Holmes. "It has long been an axiom of mine that the little things are infinitely the most important. Can you remember any other little things about Mr. Hosmer Angel?" "He was a very shy man, Mr. Holmes. He would rather walk with me in the evening than in the daylight, for he said that he hated to be conspicuous. Very retiring and gentlemanly he was. Even his voice was gentle. He'd had the quinsy and swollen glands when he was young, he told me, and it had left him with a weak throat, and a hesitating, whispering fashion of speech. He was always well dressed, very neat and plain, but his eyes were weak, just as mine are, and he wore tinted glasses against the glare." "Well, and what happened when Mr. Windibank, your stepfather, returned to France?" "Mr. Hosmer Angel came to the house again and proposed that we should marry before father came back. He was in dreadful earnest and made me swear, with my hands on the Testament, that whatever happened I would always be true to him. Mother said he was quite right to make me swear, and that it was a sign of his passion. Mother was all in his favour from the first and was even fonder of him than I was. Then, when they talked of marrying within the week, I began to ask about father; but they both said never to mind about father, but just to tell him afterwards, and mother said she would make it all right with him. I didn't quite like that, Mr. Holmes. It seemed funny that I should ask his leave, as he was only a few years older than me; but I didn't want to do anything on the sly, so I wrote to father at Bordeaux, where the company has its French offices, but the letter came back to me on the very morning of the wedding." "It missed him, then?" "Yes, sir; for he had started to England just before it arrived." "Ha! that was unfortunate. Your wedding was arranged, then, for the Friday. Was it to be in church?" "Yes, sir, but very quietly. It was to be at St. Saviour's, near King's Cross, and we were to have breakfast afterwards at the St. Pancras Hotel. Hosmer came for us in a hansom, but as there were two of us he put us both into it and stepped himself into a four-wheeler, which happened to be the only other cab in the street. We got to the church first, and when the four-wheeler drove up we waited for him to step out, but he never did, and when the cabman got down from the box and looked there was no one there! The cabman said that he could not imagine what had become of him, for he had seen him get in with his own eyes. That was last Friday, Mr. Holmes, and I have never seen or heard anything since then to throw any light upon what became of him." "It seems to me that you have been very shamefully treated," said Holmes. "Oh, no, sir! He was too good and kind to leave me so. Why, all the morning he was saying to me that, whatever happened, I was to be true; and that even if something quite unforeseen occurred to separate us, I was always to remember that I was pledged to him, and that he would claim his pledge sooner or later. It seemed strange talk for a wedding-morning, but what has happened since gives a meaning to it." "Most certainly it does. Your own opinion is, then, that some unforeseen catastrophe has occurred to him?" "Yes, sir. I believe that he foresaw some danger, or else he would not have talked so. And then I think that what he foresaw happened." "But you have no notion as to what it could have been?" "None." "One more question. How did your mother take the matter?" "She was angry, and said that I was never to speak of the matter again." "And your father? Did you tell him?" "Yes; and he seemed to think, with me, that something had happened, and that I should hear of Hosmer again. As he said, what interest could anyone have in bringing me to the doors of the church, and then leaving me? Now, if he had borrowed my money, or if he had married me and got my money settled on him, there might be some reason, but Hosmer was very independent about money and never would look at a shilling of mine. And yet, what could have happened? And why could he not write? Oh, it drives me half-mad to think of it, and I can't sleep a wink at night." She pulled a little handkerchief out of her muff and began to sob heavily into it. "I shall glance into the case for you," said Holmes, rising, "and I have no doubt that we shall reach some definite result. Let the weight of the matter rest upon me now, and do not let your mind dwell upon it further. Above all, try to let Mr. Hosmer Angel vanish from your memory, as he has done from your life." "Then you don't think I'll see him again?" "I fear not." "Then what has happened to him?" "You will leave that question in my hands. I should like an accurate description of him and any letters of his which you can spare." "I advertised for him in last Saturday's Chronicle," said she. "Here is the slip and here are four letters from him." "Thank you. And your address?" "No. 31 Lyon Place, Camberwell." "Mr. Angel's address you never had, I understand. Where is your father's place of business?" "He travels for Westhouse & Marbank, the great claret importers of Fenchurch Street." "Thank you. You have made your statement very clearly. You will leave the papers here, and remember the advice which I have given you. Let the whole incident be a sealed book, and do not allow it to affect your life." "You are very kind, Mr. Holmes, but I cannot do that. I shall be true to Hosmer. He shall find me ready when he comes back." For all the preposterous hat and the vacuous face, there was something noble in the simple faith of our visitor which compelled our respect. She laid her little bundle of papers upon the table and went her way, with a promise to come again whenever she might be summoned. Sherlock Holmes sat silent for a few minutes with his fingertips still pressed together, his legs stretched out in front of him, and his gaze directed upward to the ceiling. Then he took down from the rack the old and oily clay pipe, which was to him as a counsellor, and, having lit it, he leaned back in his chair, with the thick blue cloud-wreaths spinning up from him, and a look of infinite languor in his face. "Quite an interesting study, that maiden," he observed. "I found her more interesting than her little problem, which, by the way, is rather a trite one. You will find parallel cases, if you consult my index, in Andover in '77, and there was something of the sort at The Hague last year. Old as is the idea, however, there were one or two details which were new to me. But the maiden herself was most instructive." "You appeared to read a good deal upon her which was quite invisible to me," I remarked. "Not invisible but unnoticed, Watson. You did not know where to look, and so you missed all that was important. I can never bring you to realise the importance of sleeves, the suggestiveness of thumb-nails, or the great issues that may hang from a boot-lace. Now, what did you gather from that woman's appearance? Describe it." "Well, she had a slate-coloured, broad-brimmed straw hat, with a feather of a brickish red. Her jacket was black, with black beads sewn upon it, and a fringe of little black jet ornaments. Her dress was brown, rather darker than coffee colour, with a little purple plush at the neck and sleeves. Her gloves were greyish and were worn through at the right forefinger. Her boots I didn't observe. She had small round, hanging gold earrings, and a general air of being fairly well-to-do in a vulgar, comfortable, easy-going way." Sherlock Holmes clapped his hands softly together and chuckled. "'Pon my word, Watson, you are coming along wonderfully. You have really done very well indeed. It is true that you have missed everything of importance, but you have hit upon the method, and you have a quick eye for colour. Never trust to general impressions, my boy, but concentrate yourself upon details. My first glance is always at a woman's sleeve. In a man it is perhaps better first to take the knee of the trouser. As you observe, this woman had plush upon her sleeves, which is a most useful material for showing traces. The double line a little above the wrist, where the typewritist presses against the table, was beautifully defined. The sewing-machine, of the hand type, leaves a similar mark, but only on the left arm, and on the side of it farthest from the thumb, instead of being right across the broadest part, as this was. I then glanced at her face, and, observing the dint of a pince-nez at either side of her nose, I ventured a remark upon short sight and typewriting, which seemed to surprise her." "It surprised me." "But, surely, it was obvious. I was then much surprised and interested on glancing down to observe that, though the boots which she was wearing were not unlike each other, they were really odd ones; the one having a slightly decorated toe-cap, and the other a plain one. One was buttoned only in the two lower buttons out of five, and the other at the first, third, and fifth. Now, when you see that a young lady, otherwise neatly dressed, has come away from home with odd boots, half-buttoned, it is no great deduction to say that she came away in a hurry." "And what else?" I asked, keenly interested, as I always was, by my friend's incisive reasoning. "I noted, in passing, that she had written a note before leaving home but after being fully dressed. You observed that her right glove was torn at the forefinger, but you did not apparently see that both glove and finger were stained with violet ink. She had written in a hurry and dipped her pen too deep. It must have been this morning, or the mark would not remain clear upon the finger. All this is amusing, though rather elementary, but I must go back to business, Watson. Would you mind reading me the advertised description of Mr. Hosmer Angel?" I held the little printed slip to the light. "Missing," it said, "on the morning of the fourteenth, a gentleman named Hosmer Angel. About five ft. seven in. in height; strongly built, sallow complexion, black hair, a little bald in the centre, bushy, black side-whiskers and moustache; tinted glasses, slight infirmity of speech. Was dressed, when last seen, in black frock-coat faced with silk, black waistcoat, gold Albert chain, and grey Harris tweed trousers, with brown gaiters over elastic-sided boots. Known to have been employed in an office in Leadenhall Street. Anybody bringing--" "That will do," said Holmes. "As to the letters," he continued, glancing over them, "they are very commonplace. Absolutely no clue in them to Mr. Angel, save that he quotes Balzac once. There is one remarkable point, however, which will no doubt strike you." "They are typewritten," I remarked. "Not only that, but the signature is typewritten. Look at the neat little 'Hosmer Angel' at the bottom. There is a date, you see, but no superscription except Leadenhall Street, which is rather vague. The point about the signature is very suggestive--in fact, we may call it conclusive." "Of what?" "My dear fellow, is it possible you do not see how strongly it bears upon the case?" "I cannot say that I do unless it were that he wished to be able to deny his signature if an action for breach of promise were instituted." "No, that was not the point. However, I shall write two letters, which should settle the matter. One is to a firm in the City, the other is to the young lady's stepfather, Mr. Windibank, asking him whether he could meet us here at six o'clock tomorrow evening. It is just as well that we should do business with the male relatives. And now, Doctor, we can do nothing until the answers to those letters come, so we may put our little problem upon the shelf for the interim." I had had so many reasons to believe in my friend's subtle powers of reasoning and extraordinary energy in action that I felt that he must have some solid grounds for the assured and easy demeanour with which he treated the singular mystery which he had been called upon to fathom. Once only had I known him to fail, in the case of the King of Bohemia and of the Irene Adler photograph; but when I looked back to the weird business of the Sign of Four, and the extraordinary circumstances connected with the Study in Scarlet, I felt that it would be a strange tangle indeed which he could not unravel. I left him then, still puffing at his black clay pipe, with the conviction that when I came again on the next evening I would find that he held in his hands all the clues which would lead up to the identity of the disappearing bridegroom of Miss Mary Sutherland. A professional case of great gravity was engaging my own attention at the time, and the whole of next day I was busy at the bedside of the sufferer. It was not until close upon six o'clock that I found myself free and was able to spring into a hansom and drive to Baker Street, half afraid that I might be too late to assist at the dénouement of the little mystery. I found Sherlock Holmes alone, however, half asleep, with his long, thin form curled up in the recesses of his armchair. A formidable array of bottles and test-tubes, with the pungent cleanly smell of hydrochloric acid, told me that he had spent his day in the chemical work which was so dear to him. "Well, have you solved it?" I asked as I entered. "Yes. It was the bisulphate of baryta." "No, no, the mystery!" I cried. "Oh, that! I thought of the salt that I have been working upon. There was never any mystery in the matter, though, as I said yesterday, some of the details are of interest. The only drawback is that there is no law, I fear, that can touch the scoundrel." "Who was he, then, and what was his object in deserting Miss Sutherland?" The question was hardly out of my mouth, and Holmes had not yet opened his lips to reply, when we heard a heavy footfall in the passage and a tap at the door. "This is the girl's stepfather, Mr. James Windibank," said Holmes. "He has written to me to say that he would be here at six. Come in!" The man who entered was a sturdy, middle-sized fellow, some thirty years of age, clean-shaven, and sallow-skinned, with a bland, insinuating manner, and a pair of wonderfully sharp and penetrating grey eyes. He shot a questioning glance at each of us, placed his shiny top-hat upon the sideboard, and with a slight bow sidled down into the nearest chair. "Good-evening, Mr. James Windibank," said Holmes. "I think that this typewritten letter is from you, in which you made an appointment with me for six o'clock?" "Yes, sir. I am afraid that I am a little late, but I am not quite my own master, you know. I am sorry that Miss Sutherland has troubled you about this little matter, for I think it is far better not to wash linen of the sort in public. It was quite against my wishes that she came, but she is a very excitable, impulsive girl, as you may have noticed, and she is not easily controlled when she has made up her mind on a point. Of course, I did not mind you so much, as you are not connected with the official police, but it is not pleasant to have a family misfortune like this noised abroad. Besides, it is a useless expense, for how could you possibly find this Hosmer Angel?" "On the contrary," said Holmes quietly; "I have every reason to believe that I will succeed in discovering Mr. Hosmer Angel." Mr. Windibank gave a violent start and dropped his gloves. "I am delighted to hear it," he said. "It is a curious thing," remarked Holmes, "that a typewriter has really quite as much individuality as a man's handwriting. Unless they are quite new, no two of them write exactly alike. Some letters get more worn than others, and some wear only on one side. Now, you remark in this note of yours, Mr. Windibank, that in every case there is some little slurring over of the 'e,' and a slight defect in the tail of the 'r.' There are fourteen other characteristics, but those are the more obvious." "We do all our correspondence with this machine at the office, and no doubt it is a little worn," our visitor answered, glancing keenly at Holmes with his bright little eyes. "And now I will show you what is really a very interesting study, Mr. Windibank," Holmes continued. "I think of writing another little monograph some of these days on the typewriter and its relation to crime. It is a subject to which I have devoted some little attention. I have here four letters which purport to come from the missing man. They are all typewritten. In each case, not only are the 'e's' slurred and the 'r's' tailless, but you will observe, if you care to use my magnifying lens, that the fourteen other characteristics to which I have alluded are there as well." Mr. Windibank sprang out of his chair and picked up his hat. "I cannot waste time over this sort of fantastic talk, Mr. Holmes," he said. "If you can catch the man, catch him, and let me know when you have done it." "Certainly," said Holmes, stepping over and turning the key in the door. "I let you know, then, that I have caught him!" "What! where?" shouted Mr. Windibank, turning white to his lips and glancing about him like a rat in a trap. "Oh, it won't do--really it won't," said Holmes suavely. "There is no possible getting out of it, Mr. Windibank. It is quite too transparent, and it was a very bad compliment when you said that it was impossible for me to solve so simple a question. That's right! Sit down and let us talk it over." Our visitor collapsed into a chair, with a ghastly face and a glitter of moisture on his brow. "It--it's not actionable," he stammered. "I am very much afraid that it is not. But between ourselves, Windibank, it was as cruel and selfish and heartless a trick in a petty way as ever came before me. Now, let me just run over the course of events, and you will contradict me if I go wrong." The man sat huddled up in his chair, with his head sunk upon his breast, like one who is utterly crushed. Holmes stuck his feet up on the corner of the mantelpiece and, leaning back with his hands in his pockets, began talking, rather to himself, as it seemed, than to us. "The man married a woman very much older than himself for her money," said he, "and he enjoyed the use of the money of the daughter as long as she lived with them. It was a considerable sum, for people in their position, and the loss of it would have made a serious difference. It was worth an effort to preserve it. The daughter was of a good, amiable disposition, but affectionate and warm-hearted in her ways, so that it was evident that with her fair personal advantages, and her little income, she would not be allowed to remain single long. Now her marriage would mean, of course, the loss of a hundred a year, so what does her stepfather do to prevent it? He takes the obvious course of keeping her at home and forbidding her to seek the company of people of her own age. But soon he found that that would not answer forever. She became restive, insisted upon her rights, and finally announced her positive intention of going to a certain ball. What does her clever stepfather do then? He conceives an idea more creditable to his head than to his heart. With the connivance and assistance of his wife he disguised himself, covered those keen eyes with tinted glasses, masked the face with a moustache and a pair of bushy whiskers, sunk that clear voice into an insinuating whisper, and doubly secure on account of the girl's short sight, he appears as Mr. Hosmer Angel, and keeps off other lovers by making love himself." "It was only a joke at first," groaned our visitor. "We never thought that she would have been so carried away." "Very likely not. However that may be, the young lady was very decidedly carried away, and, having quite made up her mind that her stepfather was in France, the suspicion of treachery never for an instant entered her mind. She was flattered by the gentleman's attentions, and the effect was increased by the loudly expressed admiration of her mother. Then Mr. Angel began to call, for it was obvious that the matter should be pushed as far as it would go if a real effect were to be produced. There were meetings, and an engagement, which would finally secure the girl's affections from turning towards anyone else. But the deception could not be kept up forever. These pretended journeys to France were rather cumbrous. The thing to do was clearly to bring the business to an end in such a dramatic manner that it would leave a permanent impression upon the young lady's mind and prevent her from looking upon any other suitor for some time to come. Hence those vows of fidelity exacted upon a Testament, and hence also the allusions to a possibility of something happening on the very morning of the wedding. James Windibank wished Miss Sutherland to be so bound to Hosmer Angel, and so uncertain as to his fate, that for ten years to come, at any rate, she would not listen to another man. As far as the church door he brought her, and then, as he could go no farther, he conveniently vanished away by the old trick of stepping in at one door of a four-wheeler and out at the other. I think that was the chain of events, Mr. Windibank!" Our visitor had recovered something of his assurance while Holmes had been talking, and he rose from his chair now with a cold sneer upon his pale face. "It may be so, or it may not, Mr. Holmes," said he, "but if you are so very sharp you ought to be sharp enough to know that it is you who are breaking the law now, and not me. I have done nothing actionable from the first, but as long as you keep that door locked you lay yourself open to an action for assault and illegal constraint." "The law cannot, as you say, touch you," said Holmes, unlocking and throwing open the door, "yet there never was a man who deserved punishment more. If the young lady has a brother or a friend, he ought to lay a whip across your shoulders. By Jove!" he continued, flushing up at the sight of the bitter sneer upon the man's face, "it is not part of my duties to my client, but here's a hunting crop handy, and I think I shall just treat myself to--" He took two swift steps to the whip, but before he could grasp it there was a wild clatter of steps upon the stairs, the heavy hall door banged, and from the window we could see Mr. James Windibank running at the top of his speed down the road. "There's a cold-blooded scoundrel!" said Holmes, laughing, as he threw himself down into his chair once more. "That fellow will rise from crime to crime until he does something very bad, and ends on a gallows. The case has, in some respects, been not entirely devoid of interest." "I cannot now entirely see all the steps of your reasoning," I remarked. "Well, of course it was obvious from the first that this Mr. Hosmer Angel must have some strong object for his curious conduct, and it was equally clear that the only man who really profited by the incident, as far as we could see, was the stepfather. Then the fact that the two men were never together, but that the one always appeared when the other was away, was suggestive. So were the tinted spectacles and the curious voice, which both hinted at a disguise, as did the bushy whiskers. My suspicions were all confirmed by his peculiar action in typewriting his signature, which, of course, inferred that his handwriting was so familiar to her that she would recognise even the smallest sample of it. You see all these isolated facts, together with many minor ones, all pointed in the same direction." "And how did you verify them?" "Having once spotted my man, it was easy to get corroboration. I knew the firm for which this man worked. Having taken the printed description. I eliminated everything from it which could be the result of a disguise--the whiskers, the glasses, the voice, and I sent it to the firm, with a request that they would inform me whether it answered to the description of any of their travellers. I had already noticed the peculiarities of the typewriter, and I wrote to the man himself at his business address asking him if he would come here. As I expected, his reply was typewritten and revealed the same trivial but characteristic defects. The same post brought me a letter from Westhouse & Marbank, of Fenchurch Street, to say that the description tallied in every respect with that of their employé, James Windibank. Voilà tout!" "And Miss Sutherland?" "If I tell her she will not believe me. You may remember the old Persian saying, 'There is danger for him who taketh the tiger cub, and danger also for whoso snatches a delusion from a woman.' There is as much sense in Hafiz as in Horace, and as much knowledge of the world." ADVENTURE IV. THE BOSCOMBE VALLEY MYSTERY We were seated at breakfast one morning, my wife and I, when the maid brought in a telegram. It was from Sherlock Holmes and ran in this way: "Have you a couple of days to spare? Have just been wired for from the west of England in connection with Boscombe Valley tragedy. Shall be glad if you will come with me. Air and scenery perfect. Leave Paddington by the 11:15." "What do you say, dear?" said my wife, looking across at me. "Will you go?" "I really don't know what to say. I have a fairly long list at present." "Oh, Anstruther would do your work for you. You have been looking a little pale lately. I think that the change would do you good, and you are always so interested in Mr. Sherlock Holmes' cases." "I should be ungrateful if I were not, seeing what I gained through one of them," I answered. "But if I am to go, I must pack at once, for I have only half an hour." My experience of camp life in Afghanistan had at least had the effect of making me a prompt and ready traveller. My wants were few and simple, so that in less than the time stated I was in a cab with my valise, rattling away to Paddington Station. Sherlock Holmes was pacing up and down the platform, his tall, gaunt figure made even gaunter and taller by his long grey travelling-cloak and close-fitting cloth cap. "It is really very good of you to come, Watson," said he. "It makes a considerable difference to me, having someone with me on whom I can thoroughly rely. Local aid is always either worthless or else biassed. If you will keep the two corner seats I shall get the tickets." We had the carriage to ourselves save for an immense litter of papers which Holmes had brought with him. Among these he rummaged and read, with intervals of note-taking and of meditation, until we were past Reading. Then he suddenly rolled them all into a gigantic ball and tossed them up onto the rack. "Have you heard anything of the case?" he asked. "Not a word. I have not seen a paper for some days." "The London press has not had very full accounts. I have just been looking through all the recent papers in order to master the particulars. It seems, from what I gather, to be one of those simple cases which are so extremely difficult." "That sounds a little paradoxical." "But it is profoundly true. Singularity is almost invariably a clue. The more featureless and commonplace a crime is, the more difficult it is to bring it home. In this case, however, they have established a very serious case against the son of the murdered man." "It is a murder, then?" "Well, it is conjectured to be so. I shall take nothing for granted until I have the opportunity of looking personally into it. I will explain the state of things to you, as far as I have been able to understand it, in a very few words. "Boscombe Valley is a country district not very far from Ross, in Herefordshire. The largest landed proprietor in that part is a Mr. John Turner, who made his money in Australia and returned some years ago to the old country. One of the farms which he held, that of Hatherley, was let to Mr. Charles McCarthy, who was also an ex-Australian. The men had known each other in the colonies, so that it was not unnatural that when they came to settle down they should do so as near each other as possible. Turner was apparently the richer man, so McCarthy became his tenant but still remained, it seems, upon terms of perfect equality, as they were frequently together. McCarthy had one son, a lad of eighteen, and Turner had an only daughter of the same age, but neither of them had wives living. They appear to have avoided the society of the neighbouring English families and to have led retired lives, though both the McCarthys were fond of sport and were frequently seen at the race-meetings of the neighbourhood. McCarthy kept two servants--a man and a girl. Turner had a considerable household, some half-dozen at the least. That is as much as I have been able to gather about the families. Now for the facts. "On June 3rd, that is, on Monday last, McCarthy left his house at Hatherley about three in the afternoon and walked down to the Boscombe Pool, which is a small lake formed by the spreading out of the stream which runs down the Boscombe Valley. He had been out with his serving-man in the morning at Ross, and he had told the man that he must hurry, as he had an appointment of importance to keep at three. From that appointment he never came back alive. "From Hatherley Farm-house to the Boscombe Pool is a quarter of a mile, and two people saw him as he passed over this ground. One was an old woman, whose name is not mentioned, and the other was William Crowder, a game-keeper in the employ of Mr. Turner. Both these witnesses depose that Mr. McCarthy was walking alone. The game-keeper adds that within a few minutes of his seeing Mr. McCarthy pass he had seen his son, Mr. James McCarthy, going the same way with a gun under his arm. To the best of his belief, the father was actually in sight at the time, and the son was following him. He thought no more of the matter until he heard in the evening of the tragedy that had occurred. "The two McCarthys were seen after the time when William Crowder, the game-keeper, lost sight of them. The Boscombe Pool is thickly wooded round, with just a fringe of grass and of reeds round the edge. A girl of fourteen, Patience Moran, who is the daughter of the lodge-keeper of the Boscombe Valley estate, was in one of the woods picking flowers. She states that while she was there she saw, at the border of the wood and close by the lake, Mr. McCarthy and his son, and that they appeared to be having a violent quarrel. She heard Mr. McCarthy the elder using very strong language to his son, and she saw the latter raise up his hand as if to strike his father. She was so frightened by their violence that she ran away and told her mother when she reached home that she had left the two McCarthys quarrelling near Boscombe Pool, and that she was afraid that they were going to fight. She had hardly said the words when young Mr. McCarthy came running up to the lodge to say that he had found his father dead in the wood, and to ask for the help of the lodge-keeper. He was much excited, without either his gun or his hat, and his right hand and sleeve were observed to be stained with fresh blood. On following him they found the dead body stretched out upon the grass beside the pool. The head had been beaten in by repeated blows of some heavy and blunt weapon. The injuries were such as might very well have been inflicted by the butt-end of his son's gun, which was found lying on the grass within a few paces of the body. Under these circumstances the young man was instantly arrested, and a verdict of 'wilful murder' having been returned at the inquest on Tuesday, he was on Wednesday brought before the magistrates at Ross, who have referred the case to the next Assizes. Those are the main facts of the case as they came out before the coroner and the police-court." "I could hardly imagine a more damning case," I remarked. "If ever circumstantial evidence pointed to a criminal it does so here." "Circumstantial evidence is a very tricky thing," answered Holmes thoughtfully. "It may seem to point very straight to one thing, but if you shift your own point of view a little, you may find it pointing in an equally uncompromising manner to something entirely different. It must be confessed, however, that the case looks exceedingly grave against the young man, and it is very possible that he is indeed the culprit. There are several people in the neighbourhood, however, and among them Miss Turner, the daughter of the neighbouring landowner, who believe in his innocence, and who have retained Lestrade, whom you may recollect in connection with the Study in Scarlet, to work out the case in his interest. Lestrade, being rather puzzled, has referred the case to me, and hence it is that two middle-aged gentlemen are flying westward at fifty miles an hour instead of quietly digesting their breakfasts at home." "I am afraid," said I, "that the facts are so obvious that you will find little credit to be gained out of this case." "There is nothing more deceptive than an obvious fact," he answered, laughing. "Besides, we may chance to hit upon some other obvious facts which may have been by no means obvious to Mr. Lestrade. You know me too well to think that I am boasting when I say that I shall either confirm or destroy his theory by means which he is quite incapable of employing, or even of understanding. To take the first example to hand, I very clearly perceive that in your bedroom the window is upon the right-hand side, and yet I question whether Mr. Lestrade would have noted even so self-evident a thing as that." "How on earth--" "My dear fellow, I know you well. I know the military neatness which characterises you. You shave every morning, and in this season you shave by the sunlight; but since your shaving is less and less complete as we get farther back on the left side, until it becomes positively slovenly as we get round the angle of the jaw, it is surely very clear that that side is less illuminated than the other. I could not imagine a man of your habits looking at himself in an equal light and being satisfied with such a result. I only quote this as a trivial example of observation and inference. Therein lies my métier, and it is just possible that it may be of some service in the investigation which lies before us. There are one or two minor points which were brought out in the inquest, and which are worth considering." "What are they?" "It appears that his arrest did not take place at once, but after the return to Hatherley Farm. On the inspector of constabulary informing him that he was a prisoner, he remarked that he was not surprised to hear it, and that it was no more than his deserts. This observation of his had the natural effect of removing any traces of doubt which might have remained in the minds of the coroner's jury." "It was a confession," I ejaculated. "No, for it was followed by a protestation of innocence." "Coming on the top of such a damning series of events, it was at least a most suspicious remark." "On the contrary," said Holmes, "it is the brightest rift which I can at present see in the clouds. However innocent he might be, he could not be such an absolute imbecile as not to see that the circumstances were very black against him. Had he appeared surprised at his own arrest, or feigned indignation at it, I should have looked upon it as highly suspicious, because such surprise or anger would not be natural under the circumstances, and yet might appear to be the best policy to a scheming man. His frank acceptance of the situation marks him as either an innocent man, or else as a man of considerable self-restraint and firmness. As to his remark about his deserts, it was also not unnatural if you consider that he stood beside the dead body of his father, and that there is no doubt that he had that very day so far forgotten his filial duty as to bandy words with him, and even, according to the little girl whose evidence is so important, to raise his hand as if to strike him. The self-reproach and contrition which are displayed in his remark appear to me to be the signs of a healthy mind rather than of a guilty one." I shook my head. "Many men have been hanged on far slighter evidence," I remarked. "So they have. And many men have been wrongfully hanged." "What is the young man's own account of the matter?" "It is, I am afraid, not very encouraging to his supporters, though there are one or two points in it which are suggestive. You will find it here, and may read it for yourself." He picked out from his bundle a copy of the local Herefordshire paper, and having turned down the sheet he pointed out the paragraph in which the unfortunate young man had given his own statement of what had occurred. I settled myself down in the corner of the carriage and read it very carefully. It ran in this way: "Mr. James McCarthy, the only son of the deceased, was then called and gave evidence as follows: 'I had been away from home for three days at Bristol, and had only just returned upon the morning of last Monday, the 3rd. My father was absent from home at the time of my arrival, and I was informed by the maid that he had driven over to Ross with John Cobb, the groom. Shortly after my return I heard the wheels of his trap in the yard, and, looking out of my window, I saw him get out and walk rapidly out of the yard, though I was not aware in which direction he was going. I then took my gun and strolled out in the direction of the Boscombe Pool, with the intention of visiting the rabbit warren which is upon the other side. On my way I saw William Crowder, the game-keeper, as he had stated in his evidence; but he is mistaken in thinking that I was following my father. I had no idea that he was in front of me. When about a hundred yards from the pool I heard a cry of "Cooee!" which was a usual signal between my father and myself. I then hurried forward, and found him standing by the pool. He appeared to be much surprised at seeing me and asked me rather roughly what I was doing there. A conversation ensued which led to high words and almost to blows, for my father was a man of a very violent temper. Seeing that his passion was becoming ungovernable, I left him and returned towards Hatherley Farm. I had not gone more than 150 yards, however, when I heard a hideous outcry behind me, which caused me to run back again. I found my father expiring upon the ground, with his head terribly injured. I dropped my gun and held him in my arms, but he almost instantly expired. I knelt beside him for some minutes, and then made my way to Mr. Turner's lodge-keeper, his house being the nearest, to ask for assistance. I saw no one near my father when I returned, and I have no idea how he came by his injuries. He was not a popular man, being somewhat cold and forbidding in his manners, but he had, as far as I know, no active enemies. I know nothing further of the matter.' "The Coroner: Did your father make any statement to you before he died? "Witness: He mumbled a few words, but I could only catch some allusion to a rat. "The Coroner: What did you understand by that? "Witness: It conveyed no meaning to me. I thought that he was delirious. "The Coroner: What was the point upon which you and your father had this final quarrel? "Witness: I should prefer not to answer. "The Coroner: I am afraid that I must press it. "Witness: It is really impossible for me to tell you. I can assure you that it has nothing to do with the sad tragedy which followed. "The Coroner: That is for the court to decide. I need not point out to you that your refusal to answer will prejudice your case considerably in any future proceedings which may arise. "Witness: I must still refuse. "The Coroner: I understand that the cry of 'Cooee' was a common signal between you and your father? "Witness: It was. "The Coroner: How was it, then, that he uttered it before he saw you, and before he even knew that you had returned from Bristol? "Witness (with considerable confusion): I do not know. "A Juryman: Did you see nothing which aroused your suspicions when you returned on hearing the cry and found your father fatally injured? "Witness: Nothing definite. "The Coroner: What do you mean? "Witness: I was so disturbed and excited as I rushed out into the open, that I could think of nothing except of my father. Yet I have a vague impression that as I ran forward something lay upon the ground to the left of me. It seemed to me to be something grey in colour, a coat of some sort, or a plaid perhaps. When I rose from my father I looked round for it, but it was gone. "'Do you mean that it disappeared before you went for help?' "'Yes, it was gone.' "'You cannot say what it was?' "'No, I had a feeling something was there.' "'How far from the body?' "'A dozen yards or so.' "'And how far from the edge of the wood?' "'About the same.' "'Then if it was removed it was while you were within a dozen yards of it?' "'Yes, but with my back towards it.' "This concluded the examination of the witness." "I see," said I as I glanced down the column, "that the coroner in his concluding remarks was rather severe upon young McCarthy. He calls attention, and with reason, to the discrepancy about his father having signalled to him before seeing him, also to his refusal to give details of his conversation with his father, and his singular account of his father's dying words. They are all, as he remarks, very much against the son." Holmes laughed softly to himself and stretched himself out upon the cushioned seat. "Both you and the coroner have been at some pains," said he, "to single out the very strongest points in the young man's favour. Don't you see that you alternately give him credit for having too much imagination and too little? Too little, if he could not invent a cause of quarrel which would give him the sympathy of the jury; too much, if he evolved from his own inner consciousness anything so outré as a dying reference to a rat, and the incident of the vanishing cloth. No, sir, I shall approach this case from the point of view that what this young man says is true, and we shall see whither that hypothesis will lead us. And now here is my pocket Petrarch, and not another word shall I say of this case until we are on the scene of action. We lunch at Swindon, and I see that we shall be there in twenty minutes." It was nearly four o'clock when we at last, after passing through the beautiful Stroud Valley, and over the broad gleaming Severn, found ourselves at the pretty little country-town of Ross. A lean, ferret-like man, furtive and sly-looking, was waiting for us upon the platform. In spite of the light brown dustcoat and leather-leggings which he wore in deference to his rustic surroundings, I had no difficulty in recognising Lestrade, of Scotland Yard. With him we drove to the Hereford Arms where a room had already been engaged for us. "I have ordered a carriage," said Lestrade as we sat over a cup of tea. "I knew your energetic nature, and that you would not be happy until you had been on the scene of the crime." "It was very nice and complimentary of you," Holmes answered. "It is entirely a question of barometric pressure." Lestrade looked startled. "I do not quite follow," he said. "How is the glass? Twenty-nine, I see. No wind, and not a cloud in the sky. I have a caseful of cigarettes here which need smoking, and the sofa is very much superior to the usual country hotel abomination. I do not think that it is probable that I shall use the carriage to-night." Lestrade laughed indulgently. "You have, no doubt, already formed your conclusions from the newspapers," he said. "The case is as plain as a pikestaff, and the more one goes into it the plainer it becomes. Still, of course, one can't refuse a lady, and such a very positive one, too. She has heard of you, and would have your opinion, though I repeatedly told her that there was nothing which you could do which I had not already done. Why, bless my soul! here is her carriage at the door." He had hardly spoken before there rushed into the room one of the most lovely young women that I have ever seen in my life. Her violet eyes shining, her lips parted, a pink flush upon her cheeks, all thought of her natural reserve lost in her overpowering excitement and concern. "Oh, Mr. Sherlock Holmes!" she cried, glancing from one to the other of us, and finally, with a woman's quick intuition, fastening upon my companion, "I am so glad that you have come. I have driven down to tell you so. I know that James didn't do it. I know it, and I want you to start upon your work knowing it, too. Never let yourself doubt upon that point. We have known each other since we were little children, and I know his faults as no one else does; but he is too tender-hearted to hurt a fly. Such a charge is absurd to anyone who really knows him." "I hope we may clear him, Miss Turner," said Sherlock Holmes. "You may rely upon my doing all that I can." "But you have read the evidence. You have formed some conclusion? Do you not see some loophole, some flaw? Do you not yourself think that he is innocent?" "I think that it is very probable." "There, now!" she cried, throwing back her head and looking defiantly at Lestrade. "You hear! He gives me hopes." Lestrade shrugged his shoulders. "I am afraid that my colleague has been a little quick in forming his conclusions," he said. "But he is right. Oh! I know that he is right. James never did it. And about his quarrel with his father, I am sure that the reason why he would not speak about it to the coroner was because I was concerned in it." "In what way?" asked Holmes. "It is no time for me to hide anything. James and his father had many disagreements about me. Mr. McCarthy was very anxious that there should be a marriage between us. James and I have always loved each other as brother and sister; but of course he is young and has seen very little of life yet, and--and--well, he naturally did not wish to do anything like that yet. So there were quarrels, and this, I am sure, was one of them." "And your father?" asked Holmes. "Was he in favour of such a union?" "No, he was averse to it also. No one but Mr. McCarthy was in favour of it." A quick blush passed over her fresh young face as Holmes shot one of his keen, questioning glances at her. "Thank you for this information," said he. "May I see your father if I call to-morrow?" "I am afraid the doctor won't allow it." "The doctor?" "Yes, have you not heard? Poor father has never been strong for years back, but this has broken him down completely. He has taken to his bed, and Dr. Willows says that he is a wreck and that his nervous system is shattered. Mr. McCarthy was the only man alive who had known dad in the old days in Victoria." "Ha! In Victoria! That is important." "Yes, at the mines." "Quite so; at the gold-mines, where, as I understand, Mr. Turner made his money." "Yes, certainly." "Thank you, Miss Turner. You have been of material assistance to me." "You will tell me if you have any news to-morrow. No doubt you will go to the prison to see James. Oh, if you do, Mr. Holmes, do tell him that I know him to be innocent." "I will, Miss Turner." "I must go home now, for dad is very ill, and he misses me so if I leave him. Good-bye, and God help you in your undertaking." She hurried from the room as impulsively as she had entered, and we heard the wheels of her carriage rattle off down the street. "I am ashamed of you, Holmes," said Lestrade with dignity after a few minutes' silence. "Why should you raise up hopes which you are bound to disappoint? I am not over-tender of heart, but I call it cruel." "I think that I see my way to clearing James McCarthy," said Holmes. "Have you an order to see him in prison?" "Yes, but only for you and me." "Then I shall reconsider my resolution about going out. We have still time to take a train to Hereford and see him to-night?" "Ample." "Then let us do so. Watson, I fear that you will find it very slow, but I shall only be away a couple of hours." I walked down to the station with them, and then wandered through the streets of the little town, finally returning to the hotel, where I lay upon the sofa and tried to interest myself in a yellow-backed novel. The puny plot of the story was so thin, however, when compared to the deep mystery through which we were groping, and I found my attention wander so continually from the action to the fact, that I at last flung it across the room and gave myself up entirely to a consideration of the events of the day. Supposing that this unhappy young man's story were absolutely true, then what hellish thing, what absolutely unforeseen and extraordinary calamity could have occurred between the time when he parted from his father, and the moment when, drawn back by his screams, he rushed into the glade? It was something terrible and deadly. What could it be? Might not the nature of the injuries reveal something to my medical instincts? I rang the bell and called for the weekly county paper, which contained a verbatim account of the inquest. In the surgeon's deposition it was stated that the posterior third of the left parietal bone and the left half of the occipital bone had been shattered by a heavy blow from a blunt weapon. I marked the spot upon my own head. Clearly such a blow must have been struck from behind. That was to some extent in favour of the accused, as when seen quarrelling he was face to face with his father. Still, it did not go for very much, for the older man might have turned his back before the blow fell. Still, it might be worth while to call Holmes' attention to it. Then there was the peculiar dying reference to a rat. What could that mean? It could not be delirium. A man dying from a sudden blow does not commonly become delirious. No, it was more likely to be an attempt to explain how he met his fate. But what could it indicate? I cudgelled my brains to find some possible explanation. And then the incident of the grey cloth seen by young McCarthy. If that were true the murderer must have dropped some part of his dress, presumably his overcoat, in his flight, and must have had the hardihood to return and to carry it away at the instant when the son was kneeling with his back turned not a dozen paces off. What a tissue of mysteries and improbabilities the whole thing was! I did not wonder at Lestrade's opinion, and yet I had so much faith in Sherlock Holmes' insight that I could not lose hope as long as every fresh fact seemed to strengthen his conviction of young McCarthy's innocence. It was late before Sherlock Holmes returned. He came back alone, for Lestrade was staying in lodgings in the town. "The glass still keeps very high," he remarked as he sat down. "It is of importance that it should not rain before we are able to go over the ground. On the other hand, a man should be at his very best and keenest for such nice work as that, and I did not wish to do it when fagged by a long journey. I have seen young McCarthy." "And what did you learn from him?" "Nothing." "Could he throw no light?" "None at all. I was inclined to think at one time that he knew who had done it and was screening him or her, but I am convinced now that he is as puzzled as everyone else. He is not a very quick-witted youth, though comely to look at and, I should think, sound at heart." "I cannot admire his taste," I remarked, "if it is indeed a fact that he was averse to a marriage with so charming a young lady as this Miss Turner." "Ah, thereby hangs a rather painful tale. This fellow is madly, insanely, in love with her, but some two years ago, when he was only a lad, and before he really knew her, for she had been away five years at a boarding-school, what does the idiot do but get into the clutches of a barmaid in Bristol and marry her at a registry office? No one knows a word of the matter, but you can imagine how maddening it must be to him to be upbraided for not doing what he would give his very eyes to do, but what he knows to be absolutely impossible. It was sheer frenzy of this sort which made him throw his hands up into the air when his father, at their last interview, was goading him on to propose to Miss Turner. On the other hand, he had no means of supporting himself, and his father, who was by all accounts a very hard man, would have thrown him over utterly had he known the truth. It was with his barmaid wife that he had spent the last three days in Bristol, and his father did not know where he was. Mark that point. It is of importance. Good has come out of evil, however, for the barmaid, finding from the papers that he is in serious trouble and likely to be hanged, has thrown him over utterly and has written to him to say that she has a husband already in the Bermuda Dockyard, so that there is really no tie between them. I think that that bit of news has consoled young McCarthy for all that he has suffered." "But if he is innocent, who has done it?" "Ah! who? I would call your attention very particularly to two points. One is that the murdered man had an appointment with someone at the pool, and that the someone could not have been his son, for his son was away, and he did not know when he would return. The second is that the murdered man was heard to cry 'Cooee!' before he knew that his son had returned. Those are the crucial points upon which the case depends. And now let us talk about George Meredith, if you please, and we shall leave all minor matters until to-morrow." There was no rain, as Holmes had foretold, and the morning broke bright and cloudless. At nine o'clock Lestrade called for us with the carriage, and we set off for Hatherley Farm and the Boscombe Pool. "There is serious news this morning," Lestrade observed. "It is said that Mr. Turner, of the Hall, is so ill that his life is despaired of." "An elderly man, I presume?" said Holmes. "About sixty; but his constitution has been shattered by his life abroad, and he has been in failing health for some time. This business has had a very bad effect upon him. He was an old friend of McCarthy's, and, I may add, a great benefactor to him, for I have learned that he gave him Hatherley Farm rent free." "Indeed! That is interesting," said Holmes. "Oh, yes! In a hundred other ways he has helped him. Everybody about here speaks of his kindness to him." "Really! Does it not strike you as a little singular that this McCarthy, who appears to have had little of his own, and to have been under such obligations to Turner, should still talk of marrying his son to Turner's daughter, who is, presumably, heiress to the estate, and that in such a very cocksure manner, as if it were merely a case of a proposal and all else would follow? It is the more strange, since we know that Turner himself was averse to the idea. The daughter told us as much. Do you not deduce something from that?" "We have got to the deductions and the inferences," said Lestrade, winking at me. "I find it hard enough to tackle facts, Holmes, without flying away after theories and fancies." "You are right," said Holmes demurely; "you do find it very hard to tackle the facts." "Anyhow, I have grasped one fact which you seem to find it difficult to get hold of," replied Lestrade with some warmth. "And that is--" "That McCarthy senior met his death from McCarthy junior and that all theories to the contrary are the merest moonshine." "Well, moonshine is a brighter thing than fog," said Holmes, laughing. "But I am very much mistaken if this is not Hatherley Farm upon the left." "Yes, that is it." It was a widespread, comfortable-looking building, two-storied, slate-roofed, with great yellow blotches of lichen upon the grey walls. The drawn blinds and the smokeless chimneys, however, gave it a stricken look, as though the weight of this horror still lay heavy upon it. We called at the door, when the maid, at Holmes' request, showed us the boots which her master wore at the time of his death, and also a pair of the son's, though not the pair which he had then had. Having measured these very carefully from seven or eight different points, Holmes desired to be led to the court-yard, from which we all followed the winding track which led to Boscombe Pool. Sherlock Holmes was transformed when he was hot upon such a scent as this. Men who had only known the quiet thinker and logician of Baker Street would have failed to recognise him. His face flushed and darkened. His brows were drawn into two hard black lines, while his eyes shone out from beneath them with a steely glitter. His face was bent downward, his shoulders bowed, his lips compressed, and the veins stood out like whipcord in his long, sinewy neck. His nostrils seemed to dilate with a purely animal lust for the chase, and his mind was so absolutely concentrated upon the matter before him that a question or remark fell unheeded upon his ears, or, at the most, only provoked a quick, impatient snarl in reply. Swiftly and silently he made his way along the track which ran through the meadows, and so by way of the woods to the Boscombe Pool. It was damp, marshy ground, as is all that district, and there were marks of many feet, both upon the path and amid the short grass which bounded it on either side. Sometimes Holmes would hurry on, sometimes stop dead, and once he made quite a little detour into the meadow. Lestrade and I walked behind him, the detective indifferent and contemptuous, while I watched my friend with the interest which sprang from the conviction that every one of his actions was directed towards a definite end. The Boscombe Pool, which is a little reed-girt sheet of water some fifty yards across, is situated at the boundary between the Hatherley Farm and the private park of the wealthy Mr. Turner. Above the woods which lined it upon the farther side we could see the red, jutting pinnacles which marked the site of the rich landowner's dwelling. On the Hatherley side of the pool the woods grew very thick, and there was a narrow belt of sodden grass twenty paces across between the edge of the trees and the reeds which lined the lake. Lestrade showed us the exact spot at which the body had been found, and, indeed, so moist was the ground, that I could plainly see the traces which had been left by the fall of the stricken man. To Holmes, as I could see by his eager face and peering eyes, very many other things were to be read upon the trampled grass. He ran round, like a dog who is picking up a scent, and then turned upon my companion. "What did you go into the pool for?" he asked. "I fished about with a rake. I thought there might be some weapon or other trace. But how on earth--" "Oh, tut, tut! I have no time! That left foot of yours with its inward twist is all over the place. A mole could trace it, and there it vanishes among the reeds. Oh, how simple it would all have been had I been here before they came like a herd of buffalo and wallowed all over it. Here is where the party with the lodge-keeper came, and they have covered all tracks for six or eight feet round the body. But here are three separate tracks of the same feet." He drew out a lens and lay down upon his waterproof to have a better view, talking all the time rather to himself than to us. "These are young McCarthy's feet. Twice he was walking, and once he ran swiftly, so that the soles are deeply marked and the heels hardly visible. That bears out his story. He ran when he saw his father on the ground. Then here are the father's feet as he paced up and down. What is this, then? It is the butt-end of the gun as the son stood listening. And this? Ha, ha! What have we here? Tiptoes! tiptoes! Square, too, quite unusual boots! They come, they go, they come again--of course that was for the cloak. Now where did they come from?" He ran up and down, sometimes losing, sometimes finding the track until we were well within the edge of the wood and under the shadow of a great beech, the largest tree in the neighbourhood. Holmes traced his way to the farther side of this and lay down once more upon his face with a little cry of satisfaction. For a long time he remained there, turning over the leaves and dried sticks, gathering up what seemed to me to be dust into an envelope and examining with his lens not only the ground but even the bark of the tree as far as he could reach. A jagged stone was lying among the moss, and this also he carefully examined and retained. Then he followed a pathway through the wood until he came to the highroad, where all traces were lost. "It has been a case of considerable interest," he remarked, returning to his natural manner. "I fancy that this grey house on the right must be the lodge. I think that I will go in and have a word with Moran, and perhaps write a little note. Having done that, we may drive back to our luncheon. You may walk to the cab, and I shall be with you presently." It was about ten minutes before we regained our cab and drove back into Ross, Holmes still carrying with him the stone which he had picked up in the wood. "This may interest you, Lestrade," he remarked, holding it out. "The murder was done with it." "I see no marks." "There are none." "How do you know, then?" "The grass was growing under it. It had only lain there a few days. There was no sign of a place whence it had been taken. It corresponds with the injuries. There is no sign of any other weapon." "And the murderer?" "Is a tall man, left-handed, limps with the right leg, wears thick-soled shooting-boots and a grey cloak, smokes Indian cigars, uses a cigar-holder, and carries a blunt pen-knife in his pocket. There are several other indications, but these may be enough to aid us in our search." Lestrade laughed. "I am afraid that I am still a sceptic," he said. "Theories are all very well, but we have to deal with a hard-headed British jury." "Nous verrons," answered Holmes calmly. "You work your own method, and I shall work mine. I shall be busy this afternoon, and shall probably return to London by the evening train." "And leave your case unfinished?" "No, finished." "But the mystery?" "It is solved." "Who was the criminal, then?" "The gentleman I describe." "But who is he?" "Surely it would not be difficult to find out. This is not such a populous neighbourhood." Lestrade shrugged his shoulders. "I am a practical man," he said, "and I really cannot undertake to go about the country looking for a left-handed gentleman with a game leg. I should become the laughing-stock of Scotland Yard." "All right," said Holmes quietly. "I have given you the chance. Here are your lodgings. Good-bye. I shall drop you a line before I leave." Having left Lestrade at his rooms, we drove to our hotel, where we found lunch upon the table. Holmes was silent and buried in thought with a pained expression upon his face, as one who finds himself in a perplexing position. "Look here, Watson," he said when the cloth was cleared "just sit down in this chair and let me preach to you for a little. I don't know quite what to do, and I should value your advice. Light a cigar and let me expound." "Pray do so." "Well, now, in considering this case there are two points about young McCarthy's narrative which struck us both instantly, although they impressed me in his favour and you against him. One was the fact that his father should, according to his account, cry 'Cooee!' before seeing him. The other was his singular dying reference to a rat. He mumbled several words, you understand, but that was all that caught the son's ear. Now from this double point our research must commence, and we will begin it by presuming that what the lad says is absolutely true." "What of this 'Cooee!' then?" "Well, obviously it could not have been meant for the son. The son, as far as he knew, was in Bristol. It was mere chance that he was within earshot. The 'Cooee!' was meant to attract the attention of whoever it was that he had the appointment with. But 'Cooee' is a distinctly Australian cry, and one which is used between Australians. There is a strong presumption that the person whom McCarthy expected to meet him at Boscombe Pool was someone who had been in Australia." "What of the rat, then?" Sherlock Holmes took a folded paper from his pocket and flattened it out on the table. "This is a map of the Colony of Victoria," he said. "I wired to Bristol for it last night." He put his hand over part of the map. "What do you read?" "ARAT," I read. "And now?" He raised his hand. "BALLARAT." "Quite so. That was the word the man uttered, and of which his son only caught the last two syllables. He was trying to utter the name of his murderer. So and so, of Ballarat." "It is wonderful!" I exclaimed. "It is obvious. And now, you see, I had narrowed the field down considerably. The possession of a grey garment was a third point which, granting the son's statement to be correct, was a certainty. We have come now out of mere vagueness to the definite conception of an Australian from Ballarat with a grey cloak." "Certainly." "And one who was at home in the district, for the pool can only be approached by the farm or by the estate, where strangers could hardly wander." "Quite so." "Then comes our expedition of to-day. By an examination of the ground I gained the trifling details which I gave to that imbecile Lestrade, as to the personality of the criminal." "But how did you gain them?" "You know my method. It is founded upon the observation of trifles." "His height I know that you might roughly judge from the length of his stride. His boots, too, might be told from their traces." "Yes, they were peculiar boots." "But his lameness?" "The impression of his right foot was always less distinct than his left. He put less weight upon it. Why? Because he limped--he was lame." "But his left-handedness." "You were yourself struck by the nature of the injury as recorded by the surgeon at the inquest. The blow was struck from immediately behind, and yet was upon the left side. Now, how can that be unless it were by a left-handed man? He had stood behind that tree during the interview between the father and son. He had even smoked there. I found the ash of a cigar, which my special knowledge of tobacco ashes enables me to pronounce as an Indian cigar. I have, as you know, devoted some attention to this, and written a little monograph on the ashes of 140 different varieties of pipe, cigar, and cigarette tobacco. Having found the ash, I then looked round and discovered the stump among the moss where he had tossed it. It was an Indian cigar, of the variety which are rolled in Rotterdam." "And the cigar-holder?" "I could see that the end had not been in his mouth. Therefore he used a holder. The tip had been cut off, not bitten off, but the cut was not a clean one, so I deduced a blunt pen-knife." "Holmes," I said, "you have drawn a net round this man from which he cannot escape, and you have saved an innocent human life as truly as if you had cut the cord which was hanging him. I see the direction in which all this points. The culprit is--" "Mr. John Turner," cried the hotel waiter, opening the door of our sitting-room, and ushering in a visitor. The man who entered was a strange and impressive figure. His slow, limping step and bowed shoulders gave the appearance of decrepitude, and yet his hard, deep-lined, craggy features, and his enormous limbs showed that he was possessed of unusual strength of body and of character. His tangled beard, grizzled hair, and outstanding, drooping eyebrows combined to give an air of dignity and power to his appearance, but his face was of an ashen white, while his lips and the corners of his nostrils were tinged with a shade of blue. It was clear to me at a glance that he was in the grip of some deadly and chronic disease. "Pray sit down on the sofa," said Holmes gently. "You had my note?" "Yes, the lodge-keeper brought it up. You said that you wished to see me here to avoid scandal." "I thought people would talk if I went to the Hall." "And why did you wish to see me?" He looked across at my companion with despair in his weary eyes, as though his question was already answered. "Yes," said Holmes, answering the look rather than the words. "It is so. I know all about McCarthy." The old man sank his face in his hands. "God help me!" he cried. "But I would not have let the young man come to harm. I give you my word that I would have spoken out if it went against him at the Assizes." "I am glad to hear you say so," said Holmes gravely. "I would have spoken now had it not been for my dear girl. It would break her heart--it will break her heart when she hears that I am arrested." "It may not come to that," said Holmes. "What?" "I am no official agent. I understand that it was your daughter who required my presence here, and I am acting in her interests. Young McCarthy must be got off, however." "I am a dying man," said old Turner. "I have had diabetes for years. My doctor says it is a question whether I shall live a month. Yet I would rather die under my own roof than in a gaol." Holmes rose and sat down at the table with his pen in his hand and a bundle of paper before him. "Just tell us the truth," he said. "I shall jot down the facts. You will sign it, and Watson here can witness it. Then I could produce your confession at the last extremity to save young McCarthy. I promise you that I shall not use it unless it is absolutely needed." "It's as well," said the old man; "it's a question whether I shall live to the Assizes, so it matters little to me, but I should wish to spare Alice the shock. And now I will make the thing clear to you; it has been a long time in the acting, but will not take me long to tell. "You didn't know this dead man, McCarthy. He was a devil incarnate. I tell you that. God keep you out of the clutches of such a man as he. His grip has been upon me these twenty years, and he has blasted my life. I'll tell you first how I came to be in his power. "It was in the early '60's at the diggings. I was a young chap then, hot-blooded and reckless, ready to turn my hand at anything; I got among bad companions, took to drink, had no luck with my claim, took to the bush, and in a word became what you would call over here a highway robber. There were six of us, and we had a wild, free life of it, sticking up a station from time to time, or stopping the wagons on the road to the diggings. Black Jack of Ballarat was the name I went under, and our party is still remembered in the colony as the Ballarat Gang. "One day a gold convoy came down from Ballarat to Melbourne, and we lay in wait for it and attacked it. There were six troopers and six of us, so it was a close thing, but we emptied four of their saddles at the first volley. Three of our boys were killed, however, before we got the swag. I put my pistol to the head of the wagon-driver, who was this very man McCarthy. I wish to the Lord that I had shot him then, but I spared him, though I saw his wicked little eyes fixed on my face, as though to remember every feature. We got away with the gold, became wealthy men, and made our way over to England without being suspected. There I parted from my old pals and determined to settle down to a quiet and respectable life. I bought this estate, which chanced to be in the market, and I set myself to do a little good with my money, to make up for the way in which I had earned it. I married, too, and though my wife died young she left me my dear little Alice. Even when she was just a baby her wee hand seemed to lead me down the right path as nothing else had ever done. In a word, I turned over a new leaf and did my best to make up for the past. All was going well when McCarthy laid his grip upon me. "I had gone up to town about an investment, and I met him in Regent Street with hardly a coat to his back or a boot to his foot. "'Here we are, Jack,' says he, touching me on the arm; 'we'll be as good as a family to you. There's two of us, me and my son, and you can have the keeping of us. If you don't--it's a fine, law-abiding country is England, and there's always a policeman within hail.' "Well, down they came to the west country, there was no shaking them off, and there they have lived rent free on my best land ever since. There was no rest for me, no peace, no forgetfulness; turn where I would, there was his cunning, grinning face at my elbow. It grew worse as Alice grew up, for he soon saw I was more afraid of her knowing my past than of the police. Whatever he wanted he must have, and whatever it was I gave him without question, land, money, houses, until at last he asked a thing which I could not give. He asked for Alice. "His son, you see, had grown up, and so had my girl, and as I was known to be in weak health, it seemed a fine stroke to him that his lad should step into the whole property. But there I was firm. I would not have his cursed stock mixed with mine; not that I had any dislike to the lad, but his blood was in him, and that was enough. I stood firm. McCarthy threatened. I braved him to do his worst. We were to meet at the pool midway between our houses to talk it over. "When I went down there I found him talking with his son, so I smoked a cigar and waited behind a tree until he should be alone. But as I listened to his talk all that was black and bitter in me seemed to come uppermost. He was urging his son to marry my daughter with as little regard for what she might think as if she were a slut from off the streets. It drove me mad to think that I and all that I held most dear should be in the power of such a man as this. Could I not snap the bond? I was already a dying and a desperate man. Though clear of mind and fairly strong of limb, I knew that my own fate was sealed. But my memory and my girl! Both could be saved if I could but silence that foul tongue. I did it, Mr. Holmes. I would do it again. Deeply as I have sinned, I have led a life of martyrdom to atone for it. But that my girl should be entangled in the same meshes which held me was more than I could suffer. I struck him down with no more compunction than if he had been some foul and venomous beast. His cry brought back his son; but I had gained the cover of the wood, though I was forced to go back to fetch the cloak which I had dropped in my flight. That is the true story, gentlemen, of all that occurred." "Well, it is not for me to judge you," said Holmes as the old man signed the statement which had been drawn out. "I pray that we may never be exposed to such a temptation." "I pray not, sir. And what do you intend to do?" "In view of your health, nothing. You are yourself aware that you will soon have to answer for your deed at a higher court than the Assizes. I will keep your confession, and if McCarthy is condemned I shall be forced to use it. If not, it shall never be seen by mortal eye; and your secret, whether you be alive or dead, shall be safe with us." "Farewell, then," said the old man solemnly. "Your own deathbeds, when they come, will be the easier for the thought of the peace which you have given to mine." Tottering and shaking in all his giant frame, he stumbled slowly from the room. "God help us!" said Holmes after a long silence. "Why does fate play such tricks with poor, helpless worms? I never hear of such a case as this that I do not think of Baxter's words, and say, 'There, but for the grace of God, goes Sherlock Holmes.'" James McCarthy was acquitted at the Assizes on the strength of a number of objections which had been drawn out by Holmes and submitted to the defending counsel. Old Turner lived for seven months after our interview, but he is now dead; and there is every prospect that the son and daughter may come to live happily together in ignorance of the black cloud which rests upon their past. ADVENTURE V. THE FIVE ORANGE PIPS When I glance over my notes and records of the Sherlock Holmes cases between the years '82 and '90, I am faced by so many which present strange and interesting features that it is no easy matter to know which to choose and which to leave. Some, however, have already gained publicity through the papers, and others have not offered a field for those peculiar qualities which my friend possessed in so high a degree, and which it is the object of these papers to illustrate. Some, too, have baffled his analytical skill, and would be, as narratives, beginnings without an ending, while others have been but partially cleared up, and have their explanations founded rather upon conjecture and surmise than on that absolute logical proof which was so dear to him. There is, however, one of these last which was so remarkable in its details and so startling in its results that I am tempted to give some account of it in spite of the fact that there are points in connection with it which never have been, and probably never will be, entirely cleared up. The year '87 furnished us with a long series of cases of greater or less interest, of which I retain the records. Among my headings under this one twelve months I find an account of the adventure of the Paradol Chamber, of the Amateur Mendicant Society, who held a luxurious club in the lower vault of a furniture warehouse, of the facts connected with the loss of the British barque "Sophy Anderson", of the singular adventures of the Grice Patersons in the island of Uffa, and finally of the Camberwell poisoning case. In the latter, as may be remembered, Sherlock Holmes was able, by winding up the dead man's watch, to prove that it had been wound up two hours before, and that therefore the deceased had gone to bed within that time--a deduction which was of the greatest importance in clearing up the case. All these I may sketch out at some future date, but none of them present such singular features as the strange train of circumstances which I have now taken up my pen to describe. It was in the latter days of September, and the equinoctial gales had set in with exceptional violence. All day the wind had screamed and the rain had beaten against the windows, so that even here in the heart of great, hand-made London we were forced to raise our minds for the instant from the routine of life and to recognise the presence of those great elemental forces which shriek at mankind through the bars of his civilisation, like untamed beasts in a cage. As evening drew in, the storm grew higher and louder, and the wind cried and sobbed like a child in the chimney. Sherlock Holmes sat moodily at one side of the fireplace cross-indexing his records of crime, while I at the other was deep in one of Clark Russell's fine sea-stories until the howl of the gale from without seemed to blend with the text, and the splash of the rain to lengthen out into the long swash of the sea waves. My wife was on a visit to her mother's, and for a few days I was a dweller once more in my old quarters at Baker Street. "Why," said I, glancing up at my companion, "that was surely the bell. Who could come to-night? Some friend of yours, perhaps?" "Except yourself I have none," he answered. "I do not encourage visitors." "A client, then?" "If so, it is a serious case. Nothing less would bring a man out on such a day and at such an hour. But I take it that it is more likely to be some crony of the landlady's." Sherlock Holmes was wrong in his conjecture, however, for there came a step in the passage and a tapping at the door. He stretched out his long arm to turn the lamp away from himself and towards the vacant chair upon which a newcomer must sit. "Come in!" said he. The man who entered was young, some two-and-twenty at the outside, well-groomed and trimly clad, with something of refinement and delicacy in his bearing. The streaming umbrella which he held in his hand, and his long shining waterproof told of the fierce weather through which he had come. He looked about him anxiously in the glare of the lamp, and I could see that his face was pale and his eyes heavy, like those of a man who is weighed down with some great anxiety. "I owe you an apology," he said, raising his golden pince-nez to his eyes. "I trust that I am not intruding. I fear that I have brought some traces of the storm and rain into your snug chamber." "Give me your coat and umbrella," said Holmes. "They may rest here on the hook and will be dry presently. You have come up from the south-west, I see." "Yes, from Horsham." "That clay and chalk mixture which I see upon your toe caps is quite distinctive." "I have come for advice." "That is easily got." "And help." "That is not always so easy." "I have heard of you, Mr. Holmes. I heard from Major Prendergast how you saved him in the Tankerville Club scandal." "Ah, of course. He was wrongfully accused of cheating at cards." "He said that you could solve anything." "He said too much." "That you are never beaten." "I have been beaten four times--three times by men, and once by a woman." "But what is that compared with the number of your successes?" "It is true that I have been generally successful." "Then you may be so with me." "I beg that you will draw your chair up to the fire and favour me with some details as to your case." "It is no ordinary one." "None of those which come to me are. I am the last court of appeal." "And yet I question, sir, whether, in all your experience, you have ever listened to a more mysterious and inexplicable chain of events than those which have happened in my own family." "You fill me with interest," said Holmes. "Pray give us the essential facts from the commencement, and I can afterwards question you as to those details which seem to me to be most important." The young man pulled his chair up and pushed his wet feet out towards the blaze. "My name," said he, "is John Openshaw, but my own affairs have, as far as I can understand, little to do with this awful business. It is a hereditary matter; so in order to give you an idea of the facts, I must go back to the commencement of the affair. "You must know that my grandfather had two sons--my uncle Elias and my father Joseph. My father had a small factory at Coventry, which he enlarged at the time of the invention of bicycling. He was a patentee of the Openshaw unbreakable tire, and his business met with such success that he was able to sell it and to retire upon a handsome competence. "My uncle Elias emigrated to America when he was a young man and became a planter in Florida, where he was reported to have done very well. At the time of the war he fought in Jackson's army, and afterwards under Hood, where he rose to be a colonel. When Lee laid down his arms my uncle returned to his plantation, where he remained for three or four years. About 1869 or 1870 he came back to Europe and took a small estate in Sussex, near Horsham. He had made a very considerable fortune in the States, and his reason for leaving them was his aversion to the negroes, and his dislike of the Republican policy in extending the franchise to them. He was a singular man, fierce and quick-tempered, very foul-mouthed when he was angry, and of a most retiring disposition. During all the years that he lived at Horsham, I doubt if ever he set foot in the town. He had a garden and two or three fields round his house, and there he would take his exercise, though very often for weeks on end he would never leave his room. He drank a great deal of brandy and smoked very heavily, but he would see no society and did not want any friends, not even his own brother. "He didn't mind me; in fact, he took a fancy to me, for at the time when he saw me first I was a youngster of twelve or so. This would be in the year 1878, after he had been eight or nine years in England. He begged my father to let me live with him and he was very kind to me in his way. When he was sober he used to be fond of playing backgammon and draughts with me, and he would make me his representative both with the servants and with the tradespeople, so that by the time that I was sixteen I was quite master of the house. I kept all the keys and could go where I liked and do what I liked, so long as I did not disturb him in his privacy. There was one singular exception, however, for he had a single room, a lumber-room up among the attics, which was invariably locked, and which he would never permit either me or anyone else to enter. With a boy's curiosity I have peeped through the keyhole, but I was never able to see more than such a collection of old trunks and bundles as would be expected in such a room. "One day--it was in March, 1883--a letter with a foreign stamp lay upon the table in front of the colonel's plate. It was not a common thing for him to receive letters, for his bills were all paid in ready money, and he had no friends of any sort. 'From India!' said he as he took it up, 'Pondicherry postmark! What can this be?' Opening it hurriedly, out there jumped five little dried orange pips, which pattered down upon his plate. I began to laugh at this, but the laugh was struck from my lips at the sight of his face. His lip had fallen, his eyes were protruding, his skin the colour of putty, and he glared at the envelope which he still held in his trembling hand, 'K. K. K.!' he shrieked, and then, 'My God, my God, my sins have overtaken me!' "'What is it, uncle?' I cried. "'Death,' said he, and rising from the table he retired to his room, leaving me palpitating with horror. I took up the envelope and saw scrawled in red ink upon the inner flap, just above the gum, the letter K three times repeated. There was nothing else save the five dried pips. What could be the reason of his overpowering terror? I left the breakfast-table, and as I ascended the stair I met him coming down with an old rusty key, which must have belonged to the attic, in one hand, and a small brass box, like a cashbox, in the other. "'They may do what they like, but I'll checkmate them still,' said he with an oath. 'Tell Mary that I shall want a fire in my room to-day, and send down to Fordham, the Horsham lawyer.' "I did as he ordered, and when the lawyer arrived I was asked to step up to the room. The fire was burning brightly, and in the grate there was a mass of black, fluffy ashes, as of burned paper, while the brass box stood open and empty beside it. As I glanced at the box I noticed, with a start, that upon the lid was printed the treble K which I had read in the morning upon the envelope. "'I wish you, John,' said my uncle, 'to witness my will. I leave my estate, with all its advantages and all its disadvantages, to my brother, your father, whence it will, no doubt, descend to you. If you can enjoy it in peace, well and good! If you find you cannot, take my advice, my boy, and leave it to your deadliest enemy. I am sorry to give you such a two-edged thing, but I can't say what turn things are going to take. Kindly sign the paper where Mr. Fordham shows you.' "I signed the paper as directed, and the lawyer took it away with him. The singular incident made, as you may think, the deepest impression upon me, and I pondered over it and turned it every way in my mind without being able to make anything of it. Yet I could not shake off the vague feeling of dread which it left behind, though the sensation grew less keen as the weeks passed and nothing happened to disturb the usual routine of our lives. I could see a change in my uncle, however. He drank more than ever, and he was less inclined for any sort of society. Most of his time he would spend in his room, with the door locked upon the inside, but sometimes he would emerge in a sort of drunken frenzy and would burst out of the house and tear about the garden with a revolver in his hand, screaming out that he was afraid of no man, and that he was not to be cooped up, like a sheep in a pen, by man or devil. When these hot fits were over, however, he would rush tumultuously in at the door and lock and bar it behind him, like a man who can brazen it out no longer against the terror which lies at the roots of his soul. At such times I have seen his face, even on a cold day, glisten with moisture, as though it were new raised from a basin. "Well, to come to an end of the matter, Mr. Holmes, and not to abuse your patience, there came a night when he made one of those drunken sallies from which he never came back. We found him, when we went to search for him, face downward in a little green-scummed pool, which lay at the foot of the garden. There was no sign of any violence, and the water was but two feet deep, so that the jury, having regard to his known eccentricity, brought in a verdict of 'suicide.' But I, who knew how he winced from the very thought of death, had much ado to persuade myself that he had gone out of his way to meet it. The matter passed, however, and my father entered into possession of the estate, and of some 14,000 pounds, which lay to his credit at the bank." "One moment," Holmes interposed, "your statement is, I foresee, one of the most remarkable to which I have ever listened. Let me have the date of the reception by your uncle of the letter, and the date of his supposed suicide." "The letter arrived on March 10, 1883. His death was seven weeks later, upon the night of May 2nd." "Thank you. Pray proceed." "When my father took over the Horsham property, he, at my request, made a careful examination of the attic, which had been always locked up. We found the brass box there, although its contents had been destroyed. On the inside of the cover was a paper label, with the initials of K. K. K. repeated upon it, and 'Letters, memoranda, receipts, and a register' written beneath. These, we presume, indicated the nature of the papers which had been destroyed by Colonel Openshaw. For the rest, there was nothing of much importance in the attic save a great many scattered papers and note-books bearing upon my uncle's life in America. Some of them were of the war time and showed that he had done his duty well and had borne the repute of a brave soldier. Others were of a date during the reconstruction of the Southern states, and were mostly concerned with politics, for he had evidently taken a strong part in opposing the carpet-bag politicians who had been sent down from the North. "Well, it was the beginning of '84 when my father came to live at Horsham, and all went as well as possible with us until the January of '85. On the fourth day after the new year I heard my father give a sharp cry of surprise as we sat together at the breakfast-table. There he was, sitting with a newly opened envelope in one hand and five dried orange pips in the outstretched palm of the other one. He had always laughed at what he called my cock-and-bull story about the colonel, but he looked very scared and puzzled now that the same thing had come upon himself. "'Why, what on earth does this mean, John?' he stammered. "My heart had turned to lead. 'It is K. K. K.,' said I. "He looked inside the envelope. 'So it is,' he cried. 'Here are the very letters. But what is this written above them?' "'Put the papers on the sundial,' I read, peeping over his shoulder. "'What papers? What sundial?' he asked. "'The sundial in the garden. There is no other,' said I; 'but the papers must be those that are destroyed.' "'Pooh!' said he, gripping hard at his courage. 'We are in a civilised land here, and we can't have tomfoolery of this kind. Where does the thing come from?' "'From Dundee,' I answered, glancing at the postmark. "'Some preposterous practical joke,' said he. 'What have I to do with sundials and papers? I shall take no notice of such nonsense.' "'I should certainly speak to the police,' I said. "'And be laughed at for my pains. Nothing of the sort.' "'Then let me do so?' "'No, I forbid you. I won't have a fuss made about such nonsense.' "It was in vain to argue with him, for he was a very obstinate man. I went about, however, with a heart which was full of forebodings. "On the third day after the coming of the letter my father went from home to visit an old friend of his, Major Freebody, who is in command of one of the forts upon Portsdown Hill. I was glad that he should go, for it seemed to me that he was farther from danger when he was away from home. In that, however, I was in error. Upon the second day of his absence I received a telegram from the major, imploring me to come at once. My father had fallen over one of the deep chalk-pits which abound in the neighbourhood, and was lying senseless, with a shattered skull. I hurried to him, but he passed away without having ever recovered his consciousness. He had, as it appears, been returning from Fareham in the twilight, and as the country was unknown to him, and the chalk-pit unfenced, the jury had no hesitation in bringing in a verdict of 'death from accidental causes.' Carefully as I examined every fact connected with his death, I was unable to find anything which could suggest the idea of murder. There were no signs of violence, no footmarks, no robbery, no record of strangers having been seen upon the roads. And yet I need not tell you that my mind was far from at ease, and that I was well-nigh certain that some foul plot had been woven round him. "In this sinister way I came into my inheritance. You will ask me why I did not dispose of it? I answer, because I was well convinced that our troubles were in some way dependent upon an incident in my uncle's life, and that the danger would be as pressing in one house as in another. "It was in January, '85, that my poor father met his end, and two years and eight months have elapsed since then. During that time I have lived happily at Horsham, and I had begun to hope that this curse had passed away from the family, and that it had ended with the last generation. I had begun to take comfort too soon, however; yesterday morning the blow fell in the very shape in which it had come upon my father." The young man took from his waistcoat a crumpled envelope, and turning to the table he shook out upon it five little dried orange pips. "This is the envelope," he continued. "The postmark is London--eastern division. Within are the very words which were upon my father's last message: 'K. K. K.'; and then 'Put the papers on the sundial.'" "What have you done?" asked Holmes. "Nothing." "Nothing?" "To tell the truth"--he sank his face into his thin, white hands--"I have felt helpless. I have felt like one of those poor rabbits when the snake is writhing towards it. I seem to be in the grasp of some resistless, inexorable evil, which no foresight and no precautions can guard against." "Tut! tut!" cried Sherlock Holmes. "You must act, man, or you are lost. Nothing but energy can save you. This is no time for despair." "I have seen the police." "Ah!" "But they listened to my story with a smile. I am convinced that the inspector has formed the opinion that the letters are all practical jokes, and that the deaths of my relations were really accidents, as the jury stated, and were not to be connected with the warnings." Holmes shook his clenched hands in the air. "Incredible imbecility!" he cried. "They have, however, allowed me a policeman, who may remain in the house with me." "Has he come with you to-night?" "No. His orders were to stay in the house." Again Holmes raved in the air. "Why did you come to me," he cried, "and, above all, why did you not come at once?" "I did not know. It was only to-day that I spoke to Major Prendergast about my troubles and was advised by him to come to you." "It is really two days since you had the letter. We should have acted before this. You have no further evidence, I suppose, than that which you have placed before us--no suggestive detail which might help us?" "There is one thing," said John Openshaw. He rummaged in his coat pocket, and, drawing out a piece of discoloured, blue-tinted paper, he laid it out upon the table. "I have some remembrance," said he, "that on the day when my uncle burned the papers I observed that the small, unburned margins which lay amid the ashes were of this particular colour. I found this single sheet upon the floor of his room, and I am inclined to think that it may be one of the papers which has, perhaps, fluttered out from among the others, and in that way has escaped destruction. Beyond the mention of pips, I do not see that it helps us much. I think myself that it is a page from some private diary. The writing is undoubtedly my uncle's." Holmes moved the lamp, and we both bent over the sheet of paper, which showed by its ragged edge that it had indeed been torn from a book. It was headed, "March, 1869," and beneath were the following enigmatical notices: "4th. Hudson came. Same old platform. "7th. Set the pips on McCauley, Paramore, and John Swain, of St. Augustine. "9th. McCauley cleared. "10th. John Swain cleared. "12th. Visited Paramore. All well." "Thank you!" said Holmes, folding up the paper and returning it to our visitor. "And now you must on no account lose another instant. We cannot spare time even to discuss what you have told me. You must get home instantly and act." "What shall I do?" "There is but one thing to do. It must be done at once. You must put this piece of paper which you have shown us into the brass box which you have described. You must also put in a note to say that all the other papers were burned by your uncle, and that this is the only one which remains. You must assert that in such words as will carry conviction with them. Having done this, you must at once put the box out upon the sundial, as directed. Do you understand?" "Entirely." "Do not think of revenge, or anything of the sort, at present. I think that we may gain that by means of the law; but we have our web to weave, while theirs is already woven. The first consideration is to remove the pressing danger which threatens you. The second is to clear up the mystery and to punish the guilty parties." "I thank you," said the young man, rising and pulling on his overcoat. "You have given me fresh life and hope. I shall certainly do as you advise." "Do not lose an instant. And, above all, take care of yourself in the meanwhile, for I do not think that there can be a doubt that you are threatened by a very real and imminent danger. How do you go back?" "By train from Waterloo." "It is not yet nine. The streets will be crowded, so I trust that you may be in safety. And yet you cannot guard yourself too closely." "I am armed." "That is well. To-morrow I shall set to work upon your case." "I shall see you at Horsham, then?" "No, your secret lies in London. It is there that I shall seek it." "Then I shall call upon you in a day, or in two days, with news as to the box and the papers. I shall take your advice in every particular." He shook hands with us and took his leave. Outside the wind still screamed and the rain splashed and pattered against the windows. This strange, wild story seemed to have come to us from amid the mad elements--blown in upon us like a sheet of sea-weed in a gale--and now to have been reabsorbed by them once more. Sherlock Holmes sat for some time in silence, with his head sunk forward and his eyes bent upon the red glow of the fire. Then he lit his pipe, and leaning back in his chair he watched the blue smoke-rings as they chased each other up to the ceiling. "I think, Watson," he remarked at last, "that of all our cases we have had none more fantastic than this." "Save, perhaps, the Sign of Four." "Well, yes. Save, perhaps, that. And yet this John Openshaw seems to me to be walking amid even greater perils than did the Sholtos." "But have you," I asked, "formed any definite conception as to what these perils are?" "There can be no question as to their nature," he answered. "Then what are they? Who is this K. K. K., and why does he pursue this unhappy family?" Sherlock Holmes closed his eyes and placed his elbows upon the arms of his chair, with his finger-tips together. "The ideal reasoner," he remarked, "would, when he had once been shown a single fact in all its bearings, deduce from it not only all the chain of events which led up to it but also all the results which would follow from it. As Cuvier could correctly describe a whole animal by the contemplation of a single bone, so the observer who has thoroughly understood one link in a series of incidents should be able to accurately state all the other ones, both before and after. We have not yet grasped the results which the reason alone can attain to. Problems may be solved in the study which have baffled all those who have sought a solution by the aid of their senses. To carry the art, however, to its highest pitch, it is necessary that the reasoner should be able to utilise all the facts which have come to his knowledge; and this in itself implies, as you will readily see, a possession of all knowledge, which, even in these days of free education and encyclopaedias, is a somewhat rare accomplishment. It is not so impossible, however, that a man should possess all knowledge which is likely to be useful to him in his work, and this I have endeavoured in my case to do. If I remember rightly, you on one occasion, in the early days of our friendship, defined my limits in a very precise fashion." "Yes," I answered, laughing. "It was a singular document. Philosophy, astronomy, and politics were marked at zero, I remember. Botany variable, geology profound as regards the mud-stains from any region within fifty miles of town, chemistry eccentric, anatomy unsystematic, sensational literature and crime records unique, violin-player, boxer, swordsman, lawyer, and self-poisoner by cocaine and tobacco. Those, I think, were the main points of my analysis." Holmes grinned at the last item. "Well," he said, "I say now, as I said then, that a man should keep his little brain-attic stocked with all the furniture that he is likely to use, and the rest he can put away in the lumber-room of his library, where he can get it if he wants it. Now, for such a case as the one which has been submitted to us to-night, we need certainly to muster all our resources. Kindly hand me down the letter K of the 'American Encyclopaedia' which stands upon the shelf beside you. Thank you. Now let us consider the situation and see what may be deduced from it. In the first place, we may start with a strong presumption that Colonel Openshaw had some very strong reason for leaving America. Men at his time of life do not change all their habits and exchange willingly the charming climate of Florida for the lonely life of an English provincial town. His extreme love of solitude in England suggests the idea that he was in fear of someone or something, so we may assume as a working hypothesis that it was fear of someone or something which drove him from America. As to what it was he feared, we can only deduce that by considering the formidable letters which were received by himself and his successors. Did you remark the postmarks of those letters?" "The first was from Pondicherry, the second from Dundee, and the third from London." "From East London. What do you deduce from that?" "They are all seaports. That the writer was on board of a ship." "Excellent. We have already a clue. There can be no doubt that the probability--the strong probability--is that the writer was on board of a ship. And now let us consider another point. In the case of Pondicherry, seven weeks elapsed between the threat and its fulfilment, in Dundee it was only some three or four days. Does that suggest anything?" "A greater distance to travel." "But the letter had also a greater distance to come." "Then I do not see the point." "There is at least a presumption that the vessel in which the man or men are is a sailing-ship. It looks as if they always send their singular warning or token before them when starting upon their mission. You see how quickly the deed followed the sign when it came from Dundee. If they had come from Pondicherry in a steamer they would have arrived almost as soon as their letter. But, as a matter of fact, seven weeks elapsed. I think that those seven weeks represented the difference between the mail-boat which brought the letter and the sailing vessel which brought the writer." "It is possible." "More than that. It is probable. And now you see the deadly urgency of this new case, and why I urged young Openshaw to caution. The blow has always fallen at the end of the time which it would take the senders to travel the distance. But this one comes from London, and therefore we cannot count upon delay." "Good God!" I cried. "What can it mean, this relentless persecution?" "The papers which Openshaw carried are obviously of vital importance to the person or persons in the sailing-ship. I think that it is quite clear that there must be more than one of them. A single man could not have carried out two deaths in such a way as to deceive a coroner's jury. There must have been several in it, and they must have been men of resource and determination. Their papers they mean to have, be the holder of them who it may. In this way you see K. K. K. ceases to be the initials of an individual and becomes the badge of a society." "But of what society?" "Have you never--" said Sherlock Holmes, bending forward and sinking his voice--"have you never heard of the Ku Klux Klan?" "I never have." Holmes turned over the leaves of the book upon his knee. "Here it is," said he presently: "'Ku Klux Klan. A name derived from the fanciful resemblance to the sound produced by cocking a rifle. This terrible secret society was formed by some ex-Confederate soldiers in the Southern states after the Civil War, and it rapidly formed local branches in different parts of the country, notably in Tennessee, Louisiana, the Carolinas, Georgia, and Florida. Its power was used for political purposes, principally for the terrorising of the negro voters and the murdering and driving from the country of those who were opposed to its views. Its outrages were usually preceded by a warning sent to the marked man in some fantastic but generally recognised shape--a sprig of oak-leaves in some parts, melon seeds or orange pips in others. On receiving this the victim might either openly abjure his former ways, or might fly from the country. If he braved the matter out, death would unfailingly come upon him, and usually in some strange and unforeseen manner. So perfect was the organisation of the society, and so systematic its methods, that there is hardly a case upon record where any man succeeded in braving it with impunity, or in which any of its outrages were traced home to the perpetrators. For some years the organisation flourished in spite of the efforts of the United States government and of the better classes of the community in the South. Eventually, in the year 1869, the movement rather suddenly collapsed, although there have been sporadic outbreaks of the same sort since that date.' "You will observe," said Holmes, laying down the volume, "that the sudden breaking up of the society was coincident with the disappearance of Openshaw from America with their papers. It may well have been cause and effect. It is no wonder that he and his family have some of the more implacable spirits upon their track. You can understand that this register and diary may implicate some of the first men in the South, and that there may be many who will not sleep easy at night until it is recovered." "Then the page we have seen--" "Is such as we might expect. It ran, if I remember right, 'sent the pips to A, B, and C'--that is, sent the society's warning to them. Then there are successive entries that A and B cleared, or left the country, and finally that C was visited, with, I fear, a sinister result for C. Well, I think, Doctor, that we may let some light into this dark place, and I believe that the only chance young Openshaw has in the meantime is to do what I have told him. There is nothing more to be said or to be done to-night, so hand me over my violin and let us try to forget for half an hour the miserable weather and the still more miserable ways of our fellow-men." It had cleared in the morning, and the sun was shining with a subdued brightness through the dim veil which hangs over the great city. Sherlock Holmes was already at breakfast when I came down. "You will excuse me for not waiting for you," said he; "I have, I foresee, a very busy day before me in looking into this case of young Openshaw's." "What steps will you take?" I asked. "It will very much depend upon the results of my first inquiries. I may have to go down to Horsham, after all." "You will not go there first?" "No, I shall commence with the City. Just ring the bell and the maid will bring up your coffee." As I waited, I lifted the unopened newspaper from the table and glanced my eye over it. It rested upon a heading which sent a chill to my heart. "Holmes," I cried, "you are too late." "Ah!" said he, laying down his cup, "I feared as much. How was it done?" He spoke calmly, but I could see that he was deeply moved. "My eye caught the name of Openshaw, and the heading 'Tragedy Near Waterloo Bridge.' Here is the account: "Between nine and ten last night Police-Constable Cook, of the H Division, on duty near Waterloo Bridge, heard a cry for help and a splash in the water. The night, however, was extremely dark and stormy, so that, in spite of the help of several passers-by, it was quite impossible to effect a rescue. The alarm, however, was given, and, by the aid of the water-police, the body was eventually recovered. It proved to be that of a young gentleman whose name, as it appears from an envelope which was found in his pocket, was John Openshaw, and whose residence is near Horsham. It is conjectured that he may have been hurrying down to catch the last train from Waterloo Station, and that in his haste and the extreme darkness he missed his path and walked over the edge of one of the small landing-places for river steamboats. The body exhibited no traces of violence, and there can be no doubt that the deceased had been the victim of an unfortunate accident, which should have the effect of calling the attention of the authorities to the condition of the riverside landing-stages." We sat in silence for some minutes, Holmes more depressed and shaken than I had ever seen him. "That hurts my pride, Watson," he said at last. "It is a petty feeling, no doubt, but it hurts my pride. It becomes a personal matter with me now, and, if God sends me health, I shall set my hand upon this gang. That he should come to me for help, and that I should send him away to his death--!" He sprang from his chair and paced about the room in uncontrollable agitation, with a flush upon his sallow cheeks and a nervous clasping and unclasping of his long thin hands. "They must be cunning devils," he exclaimed at last. "How could they have decoyed him down there? The Embankment is not on the direct line to the station. The bridge, no doubt, was too crowded, even on such a night, for their purpose. Well, Watson, we shall see who will win in the long run. I am going out now!" "To the police?" "No; I shall be my own police. When I have spun the web they may take the flies, but not before." All day I was engaged in my professional work, and it was late in the evening before I returned to Baker Street. Sherlock Holmes had not come back yet. It was nearly ten o'clock before he entered, looking pale and worn. He walked up to the sideboard, and tearing a piece from the loaf he devoured it voraciously, washing it down with a long draught of water. "You are hungry," I remarked. "Starving. It had escaped my memory. I have had nothing since breakfast." "Nothing?" "Not a bite. I had no time to think of it." "And how have you succeeded?" "Well." "You have a clue?" "I have them in the hollow of my hand. Young Openshaw shall not long remain unavenged. Why, Watson, let us put their own devilish trade-mark upon them. It is well thought of!" "What do you mean?" He took an orange from the cupboard, and tearing it to pieces he squeezed out the pips upon the table. Of these he took five and thrust them into an envelope. On the inside of the flap he wrote "S. H. for J. O." Then he sealed it and addressed it to "Captain James Calhoun, Barque 'Lone Star,' Savannah, Georgia." "That will await him when he enters port," said he, chuckling. "It may give him a sleepless night. He will find it as sure a precursor of his fate as Openshaw did before him." "And who is this Captain Calhoun?" "The leader of the gang. I shall have the others, but he first." "How did you trace it, then?" He took a large sheet of paper from his pocket, all covered with dates and names. "I have spent the whole day," said he, "over Lloyd's registers and files of the old papers, following the future career of every vessel which touched at Pondicherry in January and February in '83. There were thirty-six ships of fair tonnage which were reported there during those months. Of these, one, the 'Lone Star,' instantly attracted my attention, since, although it was reported as having cleared from London, the name is that which is given to one of the states of the Union." "Texas, I think." "I was not and am not sure which; but I knew that the ship must have an American origin." "What then?" "I searched the Dundee records, and when I found that the barque 'Lone Star' was there in January, '85, my suspicion became a certainty. I then inquired as to the vessels which lay at present in the port of London." "Yes?" "The 'Lone Star' had arrived here last week. I went down to the Albert Dock and found that she had been taken down the river by the early tide this morning, homeward bound to Savannah. I wired to Gravesend and learned that she had passed some time ago, and as the wind is easterly I have no doubt that she is now past the Goodwins and not very far from the Isle of Wight." "What will you do, then?" "Oh, I have my hand upon him. He and the two mates, are as I learn, the only native-born Americans in the ship. The others are Finns and Germans. I know, also, that they were all three away from the ship last night. I had it from the stevedore who has been loading their cargo. By the time that their sailing-ship reaches Savannah the mail-boat will have carried this letter, and the cable will have informed the police of Savannah that these three gentlemen are badly wanted here upon a charge of murder." There is ever a flaw, however, in the best laid of human plans, and the murderers of John Openshaw were never to receive the orange pips which would show them that another, as cunning and as resolute as themselves, was upon their track. Very long and very severe were the equinoctial gales that year. We waited long for news of the "Lone Star" of Savannah, but none ever reached us. We did at last hear that somewhere far out in the Atlantic a shattered stern-post of a boat was seen swinging in the trough of a wave, with the letters "L. S." carved upon it, and that is all which we shall ever know of the fate of the "Lone Star." ADVENTURE VI. THE MAN WITH THE TWISTED LIP Isa Whitney, brother of the late Elias Whitney, D.D., Principal of the Theological College of St. George's, was much addicted to opium. The habit grew upon him, as I understand, from some foolish freak when he was at college; for having read De Quincey's description of his dreams and sensations, he had drenched his tobacco with laudanum in an attempt to produce the same effects. He found, as so many more have done, that the practice is easier to attain than to get rid of, and for many years he continued to be a slave to the drug, an object of mingled horror and pity to his friends and relatives. I can see him now, with yellow, pasty face, drooping lids, and pin-point pupils, all huddled in a chair, the wreck and ruin of a noble man. One night--it was in June, '89--there came a ring to my bell, about the hour when a man gives his first yawn and glances at the clock. I sat up in my chair, and my wife laid her needle-work down in her lap and made a little face of disappointment. "A patient!" said she. "You'll have to go out." I groaned, for I was newly come back from a weary day. We heard the door open, a few hurried words, and then quick steps upon the linoleum. Our own door flew open, and a lady, clad in some dark-coloured stuff, with a black veil, entered the room. "You will excuse my calling so late," she began, and then, suddenly losing her self-control, she ran forward, threw her arms about my wife's neck, and sobbed upon her shoulder. "Oh, I'm in such trouble!" she cried; "I do so want a little help." "Why," said my wife, pulling up her veil, "it is Kate Whitney. How you startled me, Kate! I had not an idea who you were when you came in." "I didn't know what to do, so I came straight to you." That was always the way. Folk who were in grief came to my wife like birds to a light-house. "It was very sweet of you to come. Now, you must have some wine and water, and sit here comfortably and tell us all about it. Or should you rather that I sent James off to bed?" "Oh, no, no! I want the doctor's advice and help, too. It's about Isa. He has not been home for two days. I am so frightened about him!" It was not the first time that she had spoken to us of her husband's trouble, to me as a doctor, to my wife as an old friend and school companion. We soothed and comforted her by such words as we could find. Did she know where her husband was? Was it possible that we could bring him back to her? It seems that it was. She had the surest information that of late he had, when the fit was on him, made use of an opium den in the farthest east of the City. Hitherto his orgies had always been confined to one day, and he had come back, twitching and shattered, in the evening. But now the spell had been upon him eight-and-forty hours, and he lay there, doubtless among the dregs of the docks, breathing in the poison or sleeping off the effects. There he was to be found, she was sure of it, at the Bar of Gold, in Upper Swandam Lane. But what was she to do? How could she, a young and timid woman, make her way into such a place and pluck her husband out from among the ruffians who surrounded him? There was the case, and of course there was but one way out of it. Might I not escort her to this place? And then, as a second thought, why should she come at all? I was Isa Whitney's medical adviser, and as such I had influence over him. I could manage it better if I were alone. I promised her on my word that I would send him home in a cab within two hours if he were indeed at the address which she had given me. And so in ten minutes I had left my armchair and cheery sitting-room behind me, and was speeding eastward in a hansom on a strange errand, as it seemed to me at the time, though the future only could show how strange it was to be. But there was no great difficulty in the first stage of my adventure. Upper Swandam Lane is a vile alley lurking behind the high wharves which line the north side of the river to the east of London Bridge. Between a slop-shop and a gin-shop, approached by a steep flight of steps leading down to a black gap like the mouth of a cave, I found the den of which I was in search. Ordering my cab to wait, I passed down the steps, worn hollow in the centre by the ceaseless tread of drunken feet; and by the light of a flickering oil-lamp above the door I found the latch and made my way into a long, low room, thick and heavy with the brown opium smoke, and terraced with wooden berths, like the forecastle of an emigrant ship. Through the gloom one could dimly catch a glimpse of bodies lying in strange fantastic poses, bowed shoulders, bent knees, heads thrown back, and chins pointing upward, with here and there a dark, lack-lustre eye turned upon the newcomer. Out of the black shadows there glimmered little red circles of light, now bright, now faint, as the burning poison waxed or waned in the bowls of the metal pipes. The most lay silent, but some muttered to themselves, and others talked together in a strange, low, monotonous voice, their conversation coming in gushes, and then suddenly tailing off into silence, each mumbling out his own thoughts and paying little heed to the words of his neighbour. At the farther end was a small brazier of burning charcoal, beside which on a three-legged wooden stool there sat a tall, thin old man, with his jaw resting upon his two fists, and his elbows upon his knees, staring into the fire. As I entered, a sallow Malay attendant had hurried up with a pipe for me and a supply of the drug, beckoning me to an empty berth. "Thank you. I have not come to stay," said I. "There is a friend of mine here, Mr. Isa Whitney, and I wish to speak with him." There was a movement and an exclamation from my right, and peering through the gloom, I saw Whitney, pale, haggard, and unkempt, staring out at me. "My God! It's Watson," said he. He was in a pitiable state of reaction, with every nerve in a twitter. "I say, Watson, what o'clock is it?" "Nearly eleven." "Of what day?" "Of Friday, June 19th." "Good heavens! I thought it was Wednesday. It is Wednesday. What d'you want to frighten a chap for?" He sank his face onto his arms and began to sob in a high treble key. "I tell you that it is Friday, man. Your wife has been waiting this two days for you. You should be ashamed of yourself!" "So I am. But you've got mixed, Watson, for I have only been here a few hours, three pipes, four pipes--I forget how many. But I'll go home with you. I wouldn't frighten Kate--poor little Kate. Give me your hand! Have you a cab?" "Yes, I have one waiting." "Then I shall go in it. But I must owe something. Find what I owe, Watson. I am all off colour. I can do nothing for myself." I walked down the narrow passage between the double row of sleepers, holding my breath to keep out the vile, stupefying fumes of the drug, and looking about for the manager. As I passed the tall man who sat by the brazier I felt a sudden pluck at my skirt, and a low voice whispered, "Walk past me, and then look back at me." The words fell quite distinctly upon my ear. I glanced down. They could only have come from the old man at my side, and yet he sat now as absorbed as ever, very thin, very wrinkled, bent with age, an opium pipe dangling down from between his knees, as though it had dropped in sheer lassitude from his fingers. I took two steps forward and looked back. It took all my self-control to prevent me from breaking out into a cry of astonishment. He had turned his back so that none could see him but I. His form had filled out, his wrinkles were gone, the dull eyes had regained their fire, and there, sitting by the fire and grinning at my surprise, was none other than Sherlock Holmes. He made a slight motion to me to approach him, and instantly, as he turned his face half round to the company once more, subsided into a doddering, loose-lipped senility. "Holmes!" I whispered, "what on earth are you doing in this den?" "As low as you can," he answered; "I have excellent ears. If you would have the great kindness to get rid of that sottish friend of yours I should be exceedingly glad to have a little talk with you." "I have a cab outside." "Then pray send him home in it. You may safely trust him, for he appears to be too limp to get into any mischief. I should recommend you also to send a note by the cabman to your wife to say that you have thrown in your lot with me. If you will wait outside, I shall be with you in five minutes." It was difficult to refuse any of Sherlock Holmes' requests, for they were always so exceedingly definite, and put forward with such a quiet air of mastery. I felt, however, that when Whitney was once confined in the cab my mission was practically accomplished; and for the rest, I could not wish anything better than to be associated with my friend in one of those singular adventures which were the normal condition of his existence. In a few minutes I had written my note, paid Whitney's bill, led him out to the cab, and seen him driven through the darkness. In a very short time a decrepit figure had emerged from the opium den, and I was walking down the street with Sherlock Holmes. For two streets he shuffled along with a bent back and an uncertain foot. Then, glancing quickly round, he straightened himself out and burst into a hearty fit of laughter. "I suppose, Watson," said he, "that you imagine that I have added opium-smoking to cocaine injections, and all the other little weaknesses on which you have favoured me with your medical views." "I was certainly surprised to find you there." "But not more so than I to find you." "I came to find a friend." "And I to find an enemy." "An enemy?" "Yes; one of my natural enemies, or, shall I say, my natural prey. Briefly, Watson, I am in the midst of a very remarkable inquiry, and I have hoped to find a clue in the incoherent ramblings of these sots, as I have done before now. Had I been recognised in that den my life would not have been worth an hour's purchase; for I have used it before now for my own purposes, and the rascally Lascar who runs it has sworn to have vengeance upon me. There is a trap-door at the back of that building, near the corner of Paul's Wharf, which could tell some strange tales of what has passed through it upon the moonless nights." "What! You do not mean bodies?" "Ay, bodies, Watson. We should be rich men if we had 1000 pounds for every poor devil who has been done to death in that den. It is the vilest murder-trap on the whole riverside, and I fear that Neville St. Clair has entered it never to leave it more. But our trap should be here." He put his two forefingers between his teeth and whistled shrilly--a signal which was answered by a similar whistle from the distance, followed shortly by the rattle of wheels and the clink of horses' hoofs. "Now, Watson," said Holmes, as a tall dog-cart dashed up through the gloom, throwing out two golden tunnels of yellow light from its side lanterns. "You'll come with me, won't you?" "If I can be of use." "Oh, a trusty comrade is always of use; and a chronicler still more so. My room at The Cedars is a double-bedded one." "The Cedars?" "Yes; that is Mr. St. Clair's house. I am staying there while I conduct the inquiry." "Where is it, then?" "Near Lee, in Kent. We have a seven-mile drive before us." "But I am all in the dark." "Of course you are. You'll know all about it presently. Jump up here. All right, John; we shall not need you. Here's half a crown. Look out for me to-morrow, about eleven. Give her her head. So long, then!" He flicked the horse with his whip, and we dashed away through the endless succession of sombre and deserted streets, which widened gradually, until we were flying across a broad balustraded bridge, with the murky river flowing sluggishly beneath us. Beyond lay another dull wilderness of bricks and mortar, its silence broken only by the heavy, regular footfall of the policeman, or the songs and shouts of some belated party of revellers. A dull wrack was drifting slowly across the sky, and a star or two twinkled dimly here and there through the rifts of the clouds. Holmes drove in silence, with his head sunk upon his breast, and the air of a man who is lost in thought, while I sat beside him, curious to learn what this new quest might be which seemed to tax his powers so sorely, and yet afraid to break in upon the current of his thoughts. We had driven several miles, and were beginning to get to the fringe of the belt of suburban villas, when he shook himself, shrugged his shoulders, and lit up his pipe with the air of a man who has satisfied himself that he is acting for the best. "You have a grand gift of silence, Watson," said he. "It makes you quite invaluable as a companion. 'Pon my word, it is a great thing for me to have someone to talk to, for my own thoughts are not over-pleasant. I was wondering what I should say to this dear little woman to-night when she meets me at the door." "You forget that I know nothing about it." "I shall just have time to tell you the facts of the case before we get to Lee. It seems absurdly simple, and yet, somehow I can get nothing to go upon. There's plenty of thread, no doubt, but I can't get the end of it into my hand. Now, I'll state the case clearly and concisely to you, Watson, and maybe you can see a spark where all is dark to me." "Proceed, then." "Some years ago--to be definite, in May, 1884--there came to Lee a gentleman, Neville St. Clair by name, who appeared to have plenty of money. He took a large villa, laid out the grounds very nicely, and lived generally in good style. By degrees he made friends in the neighbourhood, and in 1887 he married the daughter of a local brewer, by whom he now has two children. He had no occupation, but was interested in several companies and went into town as a rule in the morning, returning by the 5:14 from Cannon Street every night. Mr. St. Clair is now thirty-seven years of age, is a man of temperate habits, a good husband, a very affectionate father, and a man who is popular with all who know him. I may add that his whole debts at the present moment, as far as we have been able to ascertain, amount to 88 pounds 10s., while he has 220 pounds standing to his credit in the Capital and Counties Bank. There is no reason, therefore, to think that money troubles have been weighing upon his mind. "Last Monday Mr. Neville St. Clair went into town rather earlier than usual, remarking before he started that he had two important commissions to perform, and that he would bring his little boy home a box of bricks. Now, by the merest chance, his wife received a telegram upon this same Monday, very shortly after his departure, to the effect that a small parcel of considerable value which she had been expecting was waiting for her at the offices of the Aberdeen Shipping Company. Now, if you are well up in your London, you will know that the office of the company is in Fresno Street, which branches out of Upper Swandam Lane, where you found me to-night. Mrs. St. Clair had her lunch, started for the City, did some shopping, proceeded to the company's office, got her packet, and found herself at exactly 4:35 walking through Swandam Lane on her way back to the station. Have you followed me so far?" "It is very clear." "If you remember, Monday was an exceedingly hot day, and Mrs. St. Clair walked slowly, glancing about in the hope of seeing a cab, as she did not like the neighbourhood in which she found herself. While she was walking in this way down Swandam Lane, she suddenly heard an ejaculation or cry, and was struck cold to see her husband looking down at her and, as it seemed to her, beckoning to her from a second-floor window. The window was open, and she distinctly saw his face, which she describes as being terribly agitated. He waved his hands frantically to her, and then vanished from the window so suddenly that it seemed to her that he had been plucked back by some irresistible force from behind. One singular point which struck her quick feminine eye was that although he wore some dark coat, such as he had started to town in, he had on neither collar nor necktie. "Convinced that something was amiss with him, she rushed down the steps--for the house was none other than the opium den in which you found me to-night--and running through the front room she attempted to ascend the stairs which led to the first floor. At the foot of the stairs, however, she met this Lascar scoundrel of whom I have spoken, who thrust her back and, aided by a Dane, who acts as assistant there, pushed her out into the street. Filled with the most maddening doubts and fears, she rushed down the lane and, by rare good-fortune, met in Fresno Street a number of constables with an inspector, all on their way to their beat. The inspector and two men accompanied her back, and in spite of the continued resistance of the proprietor, they made their way to the room in which Mr. St. Clair had last been seen. There was no sign of him there. In fact, in the whole of that floor there was no one to be found save a crippled wretch of hideous aspect, who, it seems, made his home there. Both he and the Lascar stoutly swore that no one else had been in the front room during the afternoon. So determined was their denial that the inspector was staggered, and had almost come to believe that Mrs. St. Clair had been deluded when, with a cry, she sprang at a small deal box which lay upon the table and tore the lid from it. Out there fell a cascade of children's bricks. It was the toy which he had promised to bring home. "This discovery, and the evident confusion which the cripple showed, made the inspector realise that the matter was serious. The rooms were carefully examined, and results all pointed to an abominable crime. The front room was plainly furnished as a sitting-room and led into a small bedroom, which looked out upon the back of one of the wharves. Between the wharf and the bedroom window is a narrow strip, which is dry at low tide but is covered at high tide with at least four and a half feet of water. The bedroom window was a broad one and opened from below. On examination traces of blood were to be seen upon the windowsill, and several scattered drops were visible upon the wooden floor of the bedroom. Thrust away behind a curtain in the front room were all the clothes of Mr. Neville St. Clair, with the exception of his coat. His boots, his socks, his hat, and his watch--all were there. There were no signs of violence upon any of these garments, and there were no other traces of Mr. Neville St. Clair. Out of the window he must apparently have gone for no other exit could be discovered, and the ominous bloodstains upon the sill gave little promise that he could save himself by swimming, for the tide was at its very highest at the moment of the tragedy. "And now as to the villains who seemed to be immediately implicated in the matter. The Lascar was known to be a man of the vilest antecedents, but as, by Mrs. St. Clair's story, he was known to have been at the foot of the stair within a very few seconds of her husband's appearance at the window, he could hardly have been more than an accessory to the crime. His defence was one of absolute ignorance, and he protested that he had no knowledge as to the doings of Hugh Boone, his lodger, and that he could not account in any way for the presence of the missing gentleman's clothes. "So much for the Lascar manager. Now for the sinister cripple who lives upon the second floor of the opium den, and who was certainly the last human being whose eyes rested upon Neville St. Clair. His name is Hugh Boone, and his hideous face is one which is familiar to every man who goes much to the City. He is a professional beggar, though in order to avoid the police regulations he pretends to a small trade in wax vestas. Some little distance down Threadneedle Street, upon the left-hand side, there is, as you may have remarked, a small angle in the wall. Here it is that this creature takes his daily seat, cross-legged with his tiny stock of matches on his lap, and as he is a piteous spectacle a small rain of charity descends into the greasy leather cap which lies upon the pavement beside him. I have watched the fellow more than once before ever I thought of making his professional acquaintance, and I have been surprised at the harvest which he has reaped in a short time. His appearance, you see, is so remarkable that no one can pass him without observing him. A shock of orange hair, a pale face disfigured by a horrible scar, which, by its contraction, has turned up the outer edge of his upper lip, a bulldog chin, and a pair of very penetrating dark eyes, which present a singular contrast to the colour of his hair, all mark him out from amid the common crowd of mendicants and so, too, does his wit, for he is ever ready with a reply to any piece of chaff which may be thrown at him by the passers-by. This is the man whom we now learn to have been the lodger at the opium den, and to have been the last man to see the gentleman of whom we are in quest." "But a cripple!" said I. "What could he have done single-handed against a man in the prime of life?" "He is a cripple in the sense that he walks with a limp; but in other respects he appears to be a powerful and well-nurtured man. Surely your medical experience would tell you, Watson, that weakness in one limb is often compensated for by exceptional strength in the others." "Pray continue your narrative." "Mrs. St. Clair had fainted at the sight of the blood upon the window, and she was escorted home in a cab by the police, as her presence could be of no help to them in their investigations. Inspector Barton, who had charge of the case, made a very careful examination of the premises, but without finding anything which threw any light upon the matter. One mistake had been made in not arresting Boone instantly, as he was allowed some few minutes during which he might have communicated with his friend the Lascar, but this fault was soon remedied, and he was seized and searched, without anything being found which could incriminate him. There were, it is true, some blood-stains upon his right shirt-sleeve, but he pointed to his ring-finger, which had been cut near the nail, and explained that the bleeding came from there, adding that he had been to the window not long before, and that the stains which had been observed there came doubtless from the same source. He denied strenuously having ever seen Mr. Neville St. Clair and swore that the presence of the clothes in his room was as much a mystery to him as to the police. As to Mrs. St. Clair's assertion that she had actually seen her husband at the window, he declared that she must have been either mad or dreaming. He was removed, loudly protesting, to the police-station, while the inspector remained upon the premises in the hope that the ebbing tide might afford some fresh clue. "And it did, though they hardly found upon the mud-bank what they had feared to find. It was Neville St. Clair's coat, and not Neville St. Clair, which lay uncovered as the tide receded. And what do you think they found in the pockets?" "I cannot imagine." "No, I don't think you would guess. Every pocket stuffed with pennies and half-pennies--421 pennies and 270 half-pennies. It was no wonder that it had not been swept away by the tide. But a human body is a different matter. There is a fierce eddy between the wharf and the house. It seemed likely enough that the weighted coat had remained when the stripped body had been sucked away into the river." "But I understand that all the other clothes were found in the room. Would the body be dressed in a coat alone?" "No, sir, but the facts might be met speciously enough. Suppose that this man Boone had thrust Neville St. Clair through the window, there is no human eye which could have seen the deed. What would he do then? It would of course instantly strike him that he must get rid of the tell-tale garments. He would seize the coat, then, and be in the act of throwing it out, when it would occur to him that it would swim and not sink. He has little time, for he has heard the scuffle downstairs when the wife tried to force her way up, and perhaps he has already heard from his Lascar confederate that the police are hurrying up the street. There is not an instant to be lost. He rushes to some secret hoard, where he has accumulated the fruits of his beggary, and he stuffs all the coins upon which he can lay his hands into the pockets to make sure of the coat's sinking. He throws it out, and would have done the same with the other garments had not he heard the rush of steps below, and only just had time to close the window when the police appeared." "It certainly sounds feasible." "Well, we will take it as a working hypothesis for want of a better. Boone, as I have told you, was arrested and taken to the station, but it could not be shown that there had ever before been anything against him. He had for years been known as a professional beggar, but his life appeared to have been a very quiet and innocent one. There the matter stands at present, and the questions which have to be solved--what Neville St. Clair was doing in the opium den, what happened to him when there, where is he now, and what Hugh Boone had to do with his disappearance--are all as far from a solution as ever. I confess that I cannot recall any case within my experience which looked at the first glance so simple and yet which presented such difficulties." While Sherlock Holmes had been detailing this singular series of events, we had been whirling through the outskirts of the great town until the last straggling houses had been left behind, and we rattled along with a country hedge upon either side of us. Just as he finished, however, we drove through two scattered villages, where a few lights still glimmered in the windows. "We are on the outskirts of Lee," said my companion. "We have touched on three English counties in our short drive, starting in Middlesex, passing over an angle of Surrey, and ending in Kent. See that light among the trees? That is The Cedars, and beside that lamp sits a woman whose anxious ears have already, I have little doubt, caught the clink of our horse's feet." "But why are you not conducting the case from Baker Street?" I asked. "Because there are many inquiries which must be made out here. Mrs. St. Clair has most kindly put two rooms at my disposal, and you may rest assured that she will have nothing but a welcome for my friend and colleague. I hate to meet her, Watson, when I have no news of her husband. Here we are. Whoa, there, whoa!" We had pulled up in front of a large villa which stood within its own grounds. A stable-boy had run out to the horse's head, and springing down, I followed Holmes up the small, winding gravel-drive which led to the house. As we approached, the door flew open, and a little blonde woman stood in the opening, clad in some sort of light mousseline de soie, with a touch of fluffy pink chiffon at her neck and wrists. She stood with her figure outlined against the flood of light, one hand upon the door, one half-raised in her eagerness, her body slightly bent, her head and face protruded, with eager eyes and parted lips, a standing question. "Well?" she cried, "well?" And then, seeing that there were two of us, she gave a cry of hope which sank into a groan as she saw that my companion shook his head and shrugged his shoulders. "No good news?" "None." "No bad?" "No." "Thank God for that. But come in. You must be weary, for you have had a long day." "This is my friend, Dr. Watson. He has been of most vital use to me in several of my cases, and a lucky chance has made it possible for me to bring him out and associate him with this investigation." "I am delighted to see you," said she, pressing my hand warmly. "You will, I am sure, forgive anything that may be wanting in our arrangements, when you consider the blow which has come so suddenly upon us." "My dear madam," said I, "I am an old campaigner, and if I were not I can very well see that no apology is needed. If I can be of any assistance, either to you or to my friend here, I shall be indeed happy." "Now, Mr. Sherlock Holmes," said the lady as we entered a well-lit dining-room, upon the table of which a cold supper had been laid out, "I should very much like to ask you one or two plain questions, to which I beg that you will give a plain answer." "Certainly, madam." "Do not trouble about my feelings. I am not hysterical, nor given to fainting. I simply wish to hear your real, real opinion." "Upon what point?" "In your heart of hearts, do you think that Neville is alive?" Sherlock Holmes seemed to be embarrassed by the question. "Frankly, now!" she repeated, standing upon the rug and looking keenly down at him as he leaned back in a basket-chair. "Frankly, then, madam, I do not." "You think that he is dead?" "I do." "Murdered?" "I don't say that. Perhaps." "And on what day did he meet his death?" "On Monday." "Then perhaps, Mr. Holmes, you will be good enough to explain how it is that I have received a letter from him to-day." Sherlock Holmes sprang out of his chair as if he had been galvanised. "What!" he roared. "Yes, to-day." She stood smiling, holding up a little slip of paper in the air. "May I see it?" "Certainly." He snatched it from her in his eagerness, and smoothing it out upon the table he drew over the lamp and examined it intently. I had left my chair and was gazing at it over his shoulder. The envelope was a very coarse one and was stamped with the Gravesend postmark and with the date of that very day, or rather of the day before, for it was considerably after midnight. "Coarse writing," murmured Holmes. "Surely this is not your husband's writing, madam." "No, but the enclosure is." "I perceive also that whoever addressed the envelope had to go and inquire as to the address." "How can you tell that?" "The name, you see, is in perfectly black ink, which has dried itself. The rest is of the greyish colour, which shows that blotting-paper has been used. If it had been written straight off, and then blotted, none would be of a deep black shade. This man has written the name, and there has then been a pause before he wrote the address, which can only mean that he was not familiar with it. It is, of course, a trifle, but there is nothing so important as trifles. Let us now see the letter. Ha! there has been an enclosure here!" "Yes, there was a ring. His signet-ring." "And you are sure that this is your husband's hand?" "One of his hands." "One?" "His hand when he wrote hurriedly. It is very unlike his usual writing, and yet I know it well." "'Dearest do not be frightened. All will come well. There is a huge error which it may take some little time to rectify. Wait in patience.--NEVILLE.' Written in pencil upon the fly-leaf of a book, octavo size, no water-mark. Hum! Posted to-day in Gravesend by a man with a dirty thumb. Ha! And the flap has been gummed, if I am not very much in error, by a person who had been chewing tobacco. And you have no doubt that it is your husband's hand, madam?" "None. Neville wrote those words." "And they were posted to-day at Gravesend. Well, Mrs. St. Clair, the clouds lighten, though I should not venture to say that the danger is over." "But he must be alive, Mr. Holmes." "Unless this is a clever forgery to put us on the wrong scent. The ring, after all, proves nothing. It may have been taken from him." "No, no; it is, it is his very own writing!" "Very well. It may, however, have been written on Monday and only posted to-day." "That is possible." "If so, much may have happened between." "Oh, you must not discourage me, Mr. Holmes. I know that all is well with him. There is so keen a sympathy between us that I should know if evil came upon him. On the very day that I saw him last he cut himself in the bedroom, and yet I in the dining-room rushed upstairs instantly with the utmost certainty that something had happened. Do you think that I would respond to such a trifle and yet be ignorant of his death?" "I have seen too much not to know that the impression of a woman may be more valuable than the conclusion of an analytical reasoner. And in this letter you certainly have a very strong piece of evidence to corroborate your view. But if your husband is alive and able to write letters, why should he remain away from you?" "I cannot imagine. It is unthinkable." "And on Monday he made no remarks before leaving you?" "No." "And you were surprised to see him in Swandam Lane?" "Very much so." "Was the window open?" "Yes." "Then he might have called to you?" "He might." "He only, as I understand, gave an inarticulate cry?" "Yes." "A call for help, you thought?" "Yes. He waved his hands." "But it might have been a cry of surprise. Astonishment at the unexpected sight of you might cause him to throw up his hands?" "It is possible." "And you thought he was pulled back?" "He disappeared so suddenly." "He might have leaped back. You did not see anyone else in the room?" "No, but this horrible man confessed to having been there, and the Lascar was at the foot of the stairs." "Quite so. Your husband, as far as you could see, had his ordinary clothes on?" "But without his collar or tie. I distinctly saw his bare throat." "Had he ever spoken of Swandam Lane?" "Never." "Had he ever showed any signs of having taken opium?" "Never." "Thank you, Mrs. St. Clair. Those are the principal points about which I wished to be absolutely clear. We shall now have a little supper and then retire, for we may have a very busy day to-morrow." A large and comfortable double-bedded room had been placed at our disposal, and I was quickly between the sheets, for I was weary after my night of adventure. Sherlock Holmes was a man, however, who, when he had an unsolved problem upon his mind, would go for days, and even for a week, without rest, turning it over, rearranging his facts, looking at it from every point of view until he had either fathomed it or convinced himself that his data were insufficient. It was soon evident to me that he was now preparing for an all-night sitting. He took off his coat and waistcoat, put on a large blue dressing-gown, and then wandered about the room collecting pillows from his bed and cushions from the sofa and armchairs. With these he constructed a sort of Eastern divan, upon which he perched himself cross-legged, with an ounce of shag tobacco and a box of matches laid out in front of him. In the dim light of the lamp I saw him sitting there, an old briar pipe between his lips, his eyes fixed vacantly upon the corner of the ceiling, the blue smoke curling up from him, silent, motionless, with the light shining upon his strong-set aquiline features. So he sat as I dropped off to sleep, and so he sat when a sudden ejaculation caused me to wake up, and I found the summer sun shining into the apartment. The pipe was still between his lips, the smoke still curled upward, and the room was full of a dense tobacco haze, but nothing remained of the heap of shag which I had seen upon the previous night. "Awake, Watson?" he asked. "Yes." "Game for a morning drive?" "Certainly." "Then dress. No one is stirring yet, but I know where the stable-boy sleeps, and we shall soon have the trap out." He chuckled to himself as he spoke, his eyes twinkled, and he seemed a different man to the sombre thinker of the previous night. As I dressed I glanced at my watch. It was no wonder that no one was stirring. It was twenty-five minutes past four. I had hardly finished when Holmes returned with the news that the boy was putting in the horse. "I want to test a little theory of mine," said he, pulling on his boots. "I think, Watson, that you are now standing in the presence of one of the most absolute fools in Europe. I deserve to be kicked from here to Charing Cross. But I think I have the key of the affair now." "And where is it?" I asked, smiling. "In the bathroom," he answered. "Oh, yes, I am not joking," he continued, seeing my look of incredulity. "I have just been there, and I have taken it out, and I have got it in this Gladstone bag. Come on, my boy, and we shall see whether it will not fit the lock." We made our way downstairs as quietly as possible, and out into the bright morning sunshine. In the road stood our horse and trap, with the half-clad stable-boy waiting at the head. We both sprang in, and away we dashed down the London Road. A few country carts were stirring, bearing in vegetables to the metropolis, but the lines of villas on either side were as silent and lifeless as some city in a dream. "It has been in some points a singular case," said Holmes, flicking the horse on into a gallop. "I confess that I have been as blind as a mole, but it is better to learn wisdom late than never to learn it at all." In town the earliest risers were just beginning to look sleepily from their windows as we drove through the streets of the Surrey side. Passing down the Waterloo Bridge Road we crossed over the river, and dashing up Wellington Street wheeled sharply to the right and found ourselves in Bow Street. Sherlock Holmes was well known to the force, and the two constables at the door saluted him. One of them held the horse's head while the other led us in. "Who is on duty?" asked Holmes. "Inspector Bradstreet, sir." "Ah, Bradstreet, how are you?" A tall, stout official had come down the stone-flagged passage, in a peaked cap and frogged jacket. "I wish to have a quiet word with you, Bradstreet." "Certainly, Mr. Holmes. Step into my room here." It was a small, office-like room, with a huge ledger upon the table, and a telephone projecting from the wall. The inspector sat down at his desk. "What can I do for you, Mr. Holmes?" "I called about that beggarman, Boone--the one who was charged with being concerned in the disappearance of Mr. Neville St. Clair, of Lee." "Yes. He was brought up and remanded for further inquiries." "So I heard. You have him here?" "In the cells." "Is he quiet?" "Oh, he gives no trouble. But he is a dirty scoundrel." "Dirty?" "Yes, it is all we can do to make him wash his hands, and his face is as black as a tinker's. Well, when once his case has been settled, he will have a regular prison bath; and I think, if you saw him, you would agree with me that he needed it." "I should like to see him very much." "Would you? That is easily done. Come this way. You can leave your bag." "No, I think that I'll take it." "Very good. Come this way, if you please." He led us down a passage, opened a barred door, passed down a winding stair, and brought us to a whitewashed corridor with a line of doors on each side. "The third on the right is his," said the inspector. "Here it is!" He quietly shot back a panel in the upper part of the door and glanced through. "He is asleep," said he. "You can see him very well." We both put our eyes to the grating. The prisoner lay with his face towards us, in a very deep sleep, breathing slowly and heavily. He was a middle-sized man, coarsely clad as became his calling, with a coloured shirt protruding through the rent in his tattered coat. He was, as the inspector had said, extremely dirty, but the grime which covered his face could not conceal its repulsive ugliness. A broad wheal from an old scar ran right across it from eye to chin, and by its contraction had turned up one side of the upper lip, so that three teeth were exposed in a perpetual snarl. A shock of very bright red hair grew low over his eyes and forehead. "He's a beauty, isn't he?" said the inspector. "He certainly needs a wash," remarked Holmes. "I had an idea that he might, and I took the liberty of bringing the tools with me." He opened the Gladstone bag as he spoke, and took out, to my astonishment, a very large bath-sponge. "He! he! You are a funny one," chuckled the inspector. "Now, if you will have the great goodness to open that door very quietly, we will soon make him cut a much more respectable figure." "Well, I don't know why not," said the inspector. "He doesn't look a credit to the Bow Street cells, does he?" He slipped his key into the lock, and we all very quietly entered the cell. The sleeper half turned, and then settled down once more into a deep slumber. Holmes stooped to the water-jug, moistened his sponge, and then rubbed it twice vigorously across and down the prisoner's face. "Let me introduce you," he shouted, "to Mr. Neville St. Clair, of Lee, in the county of Kent." Never in my life have I seen such a sight. The man's face peeled off under the sponge like the bark from a tree. Gone was the coarse brown tint! Gone, too, was the horrid scar which had seamed it across, and the twisted lip which had given the repulsive sneer to the face! A twitch brought away the tangled red hair, and there, sitting up in his bed, was a pale, sad-faced, refined-looking man, black-haired and smooth-skinned, rubbing his eyes and staring about him with sleepy bewilderment. Then suddenly realising the exposure, he broke into a scream and threw himself down with his face to the pillow. "Great heavens!" cried the inspector, "it is, indeed, the missing man. I know him from the photograph." The prisoner turned with the reckless air of a man who abandons himself to his destiny. "Be it so," said he. "And pray what am I charged with?" "With making away with Mr. Neville St.-- Oh, come, you can't be charged with that unless they make a case of attempted suicide of it," said the inspector with a grin. "Well, I have been twenty-seven years in the force, but this really takes the cake." "If I am Mr. Neville St. Clair, then it is obvious that no crime has been committed, and that, therefore, I am illegally detained." "No crime, but a very great error has been committed," said Holmes. "You would have done better to have trusted your wife." "It was not the wife; it was the children," groaned the prisoner. "God help me, I would not have them ashamed of their father. My God! What an exposure! What can I do?" Sherlock Holmes sat down beside him on the couch and patted him kindly on the shoulder. "If you leave it to a court of law to clear the matter up," said he, "of course you can hardly avoid publicity. On the other hand, if you convince the police authorities that there is no possible case against you, I do not know that there is any reason that the details should find their way into the papers. Inspector Bradstreet would, I am sure, make notes upon anything which you might tell us and submit it to the proper authorities. The case would then never go into court at all." "God bless you!" cried the prisoner passionately. "I would have endured imprisonment, ay, even execution, rather than have left my miserable secret as a family blot to my children. "You are the first who have ever heard my story. My father was a schoolmaster in Chesterfield, where I received an excellent education. I travelled in my youth, took to the stage, and finally became a reporter on an evening paper in London. One day my editor wished to have a series of articles upon begging in the metropolis, and I volunteered to supply them. There was the point from which all my adventures started. It was only by trying begging as an amateur that I could get the facts upon which to base my articles. When an actor I had, of course, learned all the secrets of making up, and had been famous in the green-room for my skill. I took advantage now of my attainments. I painted my face, and to make myself as pitiable as possible I made a good scar and fixed one side of my lip in a twist by the aid of a small slip of flesh-coloured plaster. Then with a red head of hair, and an appropriate dress, I took my station in the business part of the city, ostensibly as a match-seller but really as a beggar. For seven hours I plied my trade, and when I returned home in the evening I found to my surprise that I had received no less than 26s. 4d. "I wrote my articles and thought little more of the matter until, some time later, I backed a bill for a friend and had a writ served upon me for 25 pounds. I was at my wit's end where to get the money, but a sudden idea came to me. I begged a fortnight's grace from the creditor, asked for a holiday from my employers, and spent the time in begging in the City under my disguise. In ten days I had the money and had paid the debt. "Well, you can imagine how hard it was to settle down to arduous work at 2 pounds a week when I knew that I could earn as much in a day by smearing my face with a little paint, laying my cap on the ground, and sitting still. It was a long fight between my pride and the money, but the dollars won at last, and I threw up reporting and sat day after day in the corner which I had first chosen, inspiring pity by my ghastly face and filling my pockets with coppers. Only one man knew my secret. He was the keeper of a low den in which I used to lodge in Swandam Lane, where I could every morning emerge as a squalid beggar and in the evenings transform myself into a well-dressed man about town. This fellow, a Lascar, was well paid by me for his rooms, so that I knew that my secret was safe in his possession. "Well, very soon I found that I was saving considerable sums of money. I do not mean that any beggar in the streets of London could earn 700 pounds a year--which is less than my average takings--but I had exceptional advantages in my power of making up, and also in a facility of repartee, which improved by practice and made me quite a recognised character in the City. All day a stream of pennies, varied by silver, poured in upon me, and it was a very bad day in which I failed to take 2 pounds. "As I grew richer I grew more ambitious, took a house in the country, and eventually married, without anyone having a suspicion as to my real occupation. My dear wife knew that I had business in the City. She little knew what. "Last Monday I had finished for the day and was dressing in my room above the opium den when I looked out of my window and saw, to my horror and astonishment, that my wife was standing in the street, with her eyes fixed full upon me. I gave a cry of surprise, threw up my arms to cover my face, and, rushing to my confidant, the Lascar, entreated him to prevent anyone from coming up to me. I heard her voice downstairs, but I knew that she could not ascend. Swiftly I threw off my clothes, pulled on those of a beggar, and put on my pigments and wig. Even a wife's eyes could not pierce so complete a disguise. But then it occurred to me that there might be a search in the room, and that the clothes might betray me. I threw open the window, reopening by my violence a small cut which I had inflicted upon myself in the bedroom that morning. Then I seized my coat, which was weighted by the coppers which I had just transferred to it from the leather bag in which I carried my takings. I hurled it out of the window, and it disappeared into the Thames. The other clothes would have followed, but at that moment there was a rush of constables up the stair, and a few minutes after I found, rather, I confess, to my relief, that instead of being identified as Mr. Neville St. Clair, I was arrested as his murderer. "I do not know that there is anything else for me to explain. I was determined to preserve my disguise as long as possible, and hence my preference for a dirty face. Knowing that my wife would be terribly anxious, I slipped off my ring and confided it to the Lascar at a moment when no constable was watching me, together with a hurried scrawl, telling her that she had no cause to fear." "That note only reached her yesterday," said Holmes. "Good God! What a week she must have spent!" "The police have watched this Lascar," said Inspector Bradstreet, "and I can quite understand that he might find it difficult to post a letter unobserved. Probably he handed it to some sailor customer of his, who forgot all about it for some days." "That was it," said Holmes, nodding approvingly; "I have no doubt of it. But have you never been prosecuted for begging?" "Many times; but what was a fine to me?" "It must stop here, however," said Bradstreet. "If the police are to hush this thing up, there must be no more of Hugh Boone." "I have sworn it by the most solemn oaths which a man can take." "In that case I think that it is probable that no further steps may be taken. But if you are found again, then all must come out. I am sure, Mr. Holmes, that we are very much indebted to you for having cleared the matter up. I wish I knew how you reach your results." "I reached this one," said my friend, "by sitting upon five pillows and consuming an ounce of shag. I think, Watson, that if we drive to Baker Street we shall just be in time for breakfast." VII. THE ADVENTURE OF THE BLUE CARBUNCLE I had called upon my friend Sherlock Holmes upon the second morning after Christmas, with the intention of wishing him the compliments of the season. He was lounging upon the sofa in a purple dressing-gown, a pipe-rack within his reach upon the right, and a pile of crumpled morning papers, evidently newly studied, near at hand. Beside the couch was a wooden chair, and on the angle of the back hung a very seedy and disreputable hard-felt hat, much the worse for wear, and cracked in several places. A lens and a forceps lying upon the seat of the chair suggested that the hat had been suspended in this manner for the purpose of examination. "You are engaged," said I; "perhaps I interrupt you." "Not at all. I am glad to have a friend with whom I can discuss my results. The matter is a perfectly trivial one"--he jerked his thumb in the direction of the old hat--"but there are points in connection with it which are not entirely devoid of interest and even of instruction." I seated myself in his armchair and warmed my hands before his crackling fire, for a sharp frost had set in, and the windows were thick with the ice crystals. "I suppose," I remarked, "that, homely as it looks, this thing has some deadly story linked on to it--that it is the clue which will guide you in the solution of some mystery and the punishment of some crime." "No, no. No crime," said Sherlock Holmes, laughing. "Only one of those whimsical little incidents which will happen when you have four million human beings all jostling each other within the space of a few square miles. Amid the action and reaction of so dense a swarm of humanity, every possible combination of events may be expected to take place, and many a little problem will be presented which may be striking and bizarre without being criminal. We have already had experience of such." "So much so," I remarked, "that of the last six cases which I have added to my notes, three have been entirely free of any legal crime." "Precisely. You allude to my attempt to recover the Irene Adler papers, to the singular case of Miss Mary Sutherland, and to the adventure of the man with the twisted lip. Well, I have no doubt that this small matter will fall into the same innocent category. You know Peterson, the commissionaire?" "Yes." "It is to him that this trophy belongs." "It is his hat." "No, no, he found it. Its owner is unknown. I beg that you will look upon it not as a battered billycock but as an intellectual problem. And, first, as to how it came here. It arrived upon Christmas morning, in company with a good fat goose, which is, I have no doubt, roasting at this moment in front of Peterson's fire. The facts are these: about four o'clock on Christmas morning, Peterson, who, as you know, is a very honest fellow, was returning from some small jollification and was making his way homeward down Tottenham Court Road. In front of him he saw, in the gaslight, a tallish man, walking with a slight stagger, and carrying a white goose slung over his shoulder. As he reached the corner of Goodge Street, a row broke out between this stranger and a little knot of roughs. One of the latter knocked off the man's hat, on which he raised his stick to defend himself and, swinging it over his head, smashed the shop window behind him. Peterson had rushed forward to protect the stranger from his assailants; but the man, shocked at having broken the window, and seeing an official-looking person in uniform rushing towards him, dropped his goose, took to his heels, and vanished amid the labyrinth of small streets which lie at the back of Tottenham Court Road. The roughs had also fled at the appearance of Peterson, so that he was left in possession of the field of battle, and also of the spoils of victory in the shape of this battered hat and a most unimpeachable Christmas goose." "Which surely he restored to their owner?" "My dear fellow, there lies the problem. It is true that 'For Mrs. Henry Baker' was printed upon a small card which was tied to the bird's left leg, and it is also true that the initials 'H. B.' are legible upon the lining of this hat, but as there are some thousands of Bakers, and some hundreds of Henry Bakers in this city of ours, it is not easy to restore lost property to any one of them." "What, then, did Peterson do?" "He brought round both hat and goose to me on Christmas morning, knowing that even the smallest problems are of interest to me. The goose we retained until this morning, when there were signs that, in spite of the slight frost, it would be well that it should be eaten without unnecessary delay. Its finder has carried it off, therefore, to fulfil the ultimate destiny of a goose, while I continue to retain the hat of the unknown gentleman who lost his Christmas dinner." "Did he not advertise?" "No." "Then, what clue could you have as to his identity?" "Only as much as we can deduce." "From his hat?" "Precisely." "But you are joking. What can you gather from this old battered felt?" "Here is my lens. You know my methods. What can you gather yourself as to the individuality of the man who has worn this article?" I took the tattered object in my hands and turned it over rather ruefully. It was a very ordinary black hat of the usual round shape, hard and much the worse for wear. The lining had been of red silk, but was a good deal discoloured. There was no maker's name; but, as Holmes had remarked, the initials "H. B." were scrawled upon one side. It was pierced in the brim for a hat-securer, but the elastic was missing. For the rest, it was cracked, exceedingly dusty, and spotted in several places, although there seemed to have been some attempt to hide the discoloured patches by smearing them with ink. "I can see nothing," said I, handing it back to my friend. "On the contrary, Watson, you can see everything. You fail, however, to reason from what you see. You are too timid in drawing your inferences." "Then, pray tell me what it is that you can infer from this hat?" He picked it up and gazed at it in the peculiar introspective fashion which was characteristic of him. "It is perhaps less suggestive than it might have been," he remarked, "and yet there are a few inferences which are very distinct, and a few others which represent at least a strong balance of probability. That the man was highly intellectual is of course obvious upon the face of it, and also that he was fairly well-to-do within the last three years, although he has now fallen upon evil days. He had foresight, but has less now than formerly, pointing to a moral retrogression, which, when taken with the decline of his fortunes, seems to indicate some evil influence, probably drink, at work upon him. This may account also for the obvious fact that his wife has ceased to love him." "My dear Holmes!" "He has, however, retained some degree of self-respect," he continued, disregarding my remonstrance. "He is a man who leads a sedentary life, goes out little, is out of training entirely, is middle-aged, has grizzled hair which he has had cut within the last few days, and which he anoints with lime-cream. These are the more patent facts which are to be deduced from his hat. Also, by the way, that it is extremely improbable that he has gas laid on in his house." "You are certainly joking, Holmes." "Not in the least. Is it possible that even now, when I give you these results, you are unable to see how they are attained?" "I have no doubt that I am very stupid, but I must confess that I am unable to follow you. For example, how did you deduce that this man was intellectual?" For answer Holmes clapped the hat upon his head. It came right over the forehead and settled upon the bridge of his nose. "It is a question of cubic capacity," said he; "a man with so large a brain must have something in it." "The decline of his fortunes, then?" "This hat is three years old. These flat brims curled at the edge came in then. It is a hat of the very best quality. Look at the band of ribbed silk and the excellent lining. If this man could afford to buy so expensive a hat three years ago, and has had no hat since, then he has assuredly gone down in the world." "Well, that is clear enough, certainly. But how about the foresight and the moral retrogression?" Sherlock Holmes laughed. "Here is the foresight," said he putting his finger upon the little disc and loop of the hat-securer. "They are never sold upon hats. If this man ordered one, it is a sign of a certain amount of foresight, since he went out of his way to take this precaution against the wind. But since we see that he has broken the elastic and has not troubled to replace it, it is obvious that he has less foresight now than formerly, which is a distinct proof of a weakening nature. On the other hand, he has endeavoured to conceal some of these stains upon the felt by daubing them with ink, which is a sign that he has not entirely lost his self-respect." "Your reasoning is certainly plausible." "The further points, that he is middle-aged, that his hair is grizzled, that it has been recently cut, and that he uses lime-cream, are all to be gathered from a close examination of the lower part of the lining. The lens discloses a large number of hair-ends, clean cut by the scissors of the barber. They all appear to be adhesive, and there is a distinct odour of lime-cream. This dust, you will observe, is not the gritty, grey dust of the street but the fluffy brown dust of the house, showing that it has been hung up indoors most of the time, while the marks of moisture upon the inside are proof positive that the wearer perspired very freely, and could therefore, hardly be in the best of training." "But his wife--you said that she had ceased to love him." "This hat has not been brushed for weeks. When I see you, my dear Watson, with a week's accumulation of dust upon your hat, and when your wife allows you to go out in such a state, I shall fear that you also have been unfortunate enough to lose your wife's affection." "But he might be a bachelor." "Nay, he was bringing home the goose as a peace-offering to his wife. Remember the card upon the bird's leg." "You have an answer to everything. But how on earth do you deduce that the gas is not laid on in his house?" "One tallow stain, or even two, might come by chance; but when I see no less than five, I think that there can be little doubt that the individual must be brought into frequent contact with burning tallow--walks upstairs at night probably with his hat in one hand and a guttering candle in the other. Anyhow, he never got tallow-stains from a gas-jet. Are you satisfied?" "Well, it is very ingenious," said I, laughing; "but since, as you said just now, there has been no crime committed, and no harm done save the loss of a goose, all this seems to be rather a waste of energy." Sherlock Holmes had opened his mouth to reply, when the door flew open, and Peterson, the commissionaire, rushed into the apartment with flushed cheeks and the face of a man who is dazed with astonishment. "The goose, Mr. Holmes! The goose, sir!" he gasped. "Eh? What of it, then? Has it returned to life and flapped off through the kitchen window?" Holmes twisted himself round upon the sofa to get a fairer view of the man's excited face. "See here, sir! See what my wife found in its crop!" He held out his hand and displayed upon the centre of the palm a brilliantly scintillating blue stone, rather smaller than a bean in size, but of such purity and radiance that it twinkled like an electric point in the dark hollow of his hand. Sherlock Holmes sat up with a whistle. "By Jove, Peterson!" said he, "this is treasure trove indeed. I suppose you know what you have got?" "A diamond, sir? A precious stone. It cuts into glass as though it were putty." "It's more than a precious stone. It is the precious stone." "Not the Countess of Morcar's blue carbuncle!" I ejaculated. "Precisely so. I ought to know its size and shape, seeing that I have read the advertisement about it in The Times every day lately. It is absolutely unique, and its value can only be conjectured, but the reward offered of 1000 pounds is certainly not within a twentieth part of the market price." "A thousand pounds! Great Lord of mercy!" The commissionaire plumped down into a chair and stared from one to the other of us. "That is the reward, and I have reason to know that there are sentimental considerations in the background which would induce the Countess to part with half her fortune if she could but recover the gem." "It was lost, if I remember aright, at the Hotel Cosmopolitan," I remarked. "Precisely so, on December 22nd, just five days ago. John Horner, a plumber, was accused of having abstracted it from the lady's jewel-case. The evidence against him was so strong that the case has been referred to the Assizes. I have some account of the matter here, I believe." He rummaged amid his newspapers, glancing over the dates, until at last he smoothed one out, doubled it over, and read the following paragraph: "Hotel Cosmopolitan Jewel Robbery. John Horner, 26, plumber, was brought up upon the charge of having upon the 22nd inst., abstracted from the jewel-case of the Countess of Morcar the valuable gem known as the blue carbuncle. James Ryder, upper-attendant at the hotel, gave his evidence to the effect that he had shown Horner up to the dressing-room of the Countess of Morcar upon the day of the robbery in order that he might solder the second bar of the grate, which was loose. He had remained with Horner some little time, but had finally been called away. On returning, he found that Horner had disappeared, that the bureau had been forced open, and that the small morocco casket in which, as it afterwards transpired, the Countess was accustomed to keep her jewel, was lying empty upon the dressing-table. Ryder instantly gave the alarm, and Horner was arrested the same evening; but the stone could not be found either upon his person or in his rooms. Catherine Cusack, maid to the Countess, deposed to having heard Ryder's cry of dismay on discovering the robbery, and to having rushed into the room, where she found matters as described by the last witness. Inspector Bradstreet, B division, gave evidence as to the arrest of Horner, who struggled frantically, and protested his innocence in the strongest terms. Evidence of a previous conviction for robbery having been given against the prisoner, the magistrate refused to deal summarily with the offence, but referred it to the Assizes. Horner, who had shown signs of intense emotion during the proceedings, fainted away at the conclusion and was carried out of court." "Hum! So much for the police-court," said Holmes thoughtfully, tossing aside the paper. "The question for us now to solve is the sequence of events leading from a rifled jewel-case at one end to the crop of a goose in Tottenham Court Road at the other. You see, Watson, our little deductions have suddenly assumed a much more important and less innocent aspect. Here is the stone; the stone came from the goose, and the goose came from Mr. Henry Baker, the gentleman with the bad hat and all the other characteristics with which I have bored you. So now we must set ourselves very seriously to finding this gentleman and ascertaining what part he has played in this little mystery. To do this, we must try the simplest means first, and these lie undoubtedly in an advertisement in all the evening papers. If this fail, I shall have recourse to other methods." "What will you say?" "Give me a pencil and that slip of paper. Now, then: 'Found at the corner of Goodge Street, a goose and a black felt hat. Mr. Henry Baker can have the same by applying at 6:30 this evening at 221B, Baker Street.' That is clear and concise." "Very. But will he see it?" "Well, he is sure to keep an eye on the papers, since, to a poor man, the loss was a heavy one. He was clearly so scared by his mischance in breaking the window and by the approach of Peterson that he thought of nothing but flight, but since then he must have bitterly regretted the impulse which caused him to drop his bird. Then, again, the introduction of his name will cause him to see it, for everyone who knows him will direct his attention to it. Here you are, Peterson, run down to the advertising agency and have this put in the evening papers." "In which, sir?" "Oh, in the Globe, Star, Pall Mall, St. James's, Evening News, Standard, Echo, and any others that occur to you." "Very well, sir. And this stone?" "Ah, yes, I shall keep the stone. Thank you. And, I say, Peterson, just buy a goose on your way back and leave it here with me, for we must have one to give to this gentleman in place of the one which your family is now devouring." When the commissionaire had gone, Holmes took up the stone and held it against the light. "It's a bonny thing," said he. "Just see how it glints and sparkles. Of course it is a nucleus and focus of crime. Every good stone is. They are the devil's pet baits. In the larger and older jewels every facet may stand for a bloody deed. This stone is not yet twenty years old. It was found in the banks of the Amoy River in southern China and is remarkable in having every characteristic of the carbuncle, save that it is blue in shade instead of ruby red. In spite of its youth, it has already a sinister history. There have been two murders, a vitriol-throwing, a suicide, and several robberies brought about for the sake of this forty-grain weight of crystallised charcoal. Who would think that so pretty a toy would be a purveyor to the gallows and the prison? I'll lock it up in my strong box now and drop a line to the Countess to say that we have it." "Do you think that this man Horner is innocent?" "I cannot tell." "Well, then, do you imagine that this other one, Henry Baker, had anything to do with the matter?" "It is, I think, much more likely that Henry Baker is an absolutely innocent man, who had no idea that the bird which he was carrying was of considerably more value than if it were made of solid gold. That, however, I shall determine by a very simple test if we have an answer to our advertisement." "And you can do nothing until then?" "Nothing." "In that case I shall continue my professional round. But I shall come back in the evening at the hour you have mentioned, for I should like to see the solution of so tangled a business." "Very glad to see you. I dine at seven. There is a woodcock, I believe. By the way, in view of recent occurrences, perhaps I ought to ask Mrs. Hudson to examine its crop." I had been delayed at a case, and it was a little after half-past six when I found myself in Baker Street once more. As I approached the house I saw a tall man in a Scotch bonnet with a coat which was buttoned up to his chin waiting outside in the bright semicircle which was thrown from the fanlight. Just as I arrived the door was opened, and we were shown up together to Holmes' room. "Mr. Henry Baker, I believe," said he, rising from his armchair and greeting his visitor with the easy air of geniality which he could so readily assume. "Pray take this chair by the fire, Mr. Baker. It is a cold night, and I observe that your circulation is more adapted for summer than for winter. Ah, Watson, you have just come at the right time. Is that your hat, Mr. Baker?" "Yes, sir, that is undoubtedly my hat." He was a large man with rounded shoulders, a massive head, and a broad, intelligent face, sloping down to a pointed beard of grizzled brown. A touch of red in nose and cheeks, with a slight tremor of his extended hand, recalled Holmes' surmise as to his habits. His rusty black frock-coat was buttoned right up in front, with the collar turned up, and his lank wrists protruded from his sleeves without a sign of cuff or shirt. He spoke in a slow staccato fashion, choosing his words with care, and gave the impression generally of a man of learning and letters who had had ill-usage at the hands of fortune. "We have retained these things for some days," said Holmes, "because we expected to see an advertisement from you giving your address. I am at a loss to know now why you did not advertise." Our visitor gave a rather shamefaced laugh. "Shillings have not been so plentiful with me as they once were," he remarked. "I had no doubt that the gang of roughs who assaulted me had carried off both my hat and the bird. I did not care to spend more money in a hopeless attempt at recovering them." "Very naturally. By the way, about the bird, we were compelled to eat it." "To eat it!" Our visitor half rose from his chair in his excitement. "Yes, it would have been of no use to anyone had we not done so. But I presume that this other goose upon the sideboard, which is about the same weight and perfectly fresh, will answer your purpose equally well?" "Oh, certainly, certainly," answered Mr. Baker with a sigh of relief. "Of course, we still have the feathers, legs, crop, and so on of your own bird, so if you wish--" The man burst into a hearty laugh. "They might be useful to me as relics of my adventure," said he, "but beyond that I can hardly see what use the disjecta membra of my late acquaintance are going to be to me. No, sir, I think that, with your permission, I will confine my attentions to the excellent bird which I perceive upon the sideboard." Sherlock Holmes glanced sharply across at me with a slight shrug of his shoulders. "There is your hat, then, and there your bird," said he. "By the way, would it bore you to tell me where you got the other one from? I am somewhat of a fowl fancier, and I have seldom seen a better grown goose." "Certainly, sir," said Baker, who had risen and tucked his newly gained property under his arm. "There are a few of us who frequent the Alpha Inn, near the Museum--we are to be found in the Museum itself during the day, you understand. This year our good host, Windigate by name, instituted a goose club, by which, on consideration of some few pence every week, we were each to receive a bird at Christmas. My pence were duly paid, and the rest is familiar to you. I am much indebted to you, sir, for a Scotch bonnet is fitted neither to my years nor my gravity." With a comical pomposity of manner he bowed solemnly to both of us and strode off upon his way. "So much for Mr. Henry Baker," said Holmes when he had closed the door behind him. "It is quite certain that he knows nothing whatever about the matter. Are you hungry, Watson?" "Not particularly." "Then I suggest that we turn our dinner into a supper and follow up this clue while it is still hot." "By all means." It was a bitter night, so we drew on our ulsters and wrapped cravats about our throats. Outside, the stars were shining coldly in a cloudless sky, and the breath of the passers-by blew out into smoke like so many pistol shots. Our footfalls rang out crisply and loudly as we swung through the doctors' quarter, Wimpole Street, Harley Street, and so through Wigmore Street into Oxford Street. In a quarter of an hour we were in Bloomsbury at the Alpha Inn, which is a small public-house at the corner of one of the streets which runs down into Holborn. Holmes pushed open the door of the private bar and ordered two glasses of beer from the ruddy-faced, white-aproned landlord. "Your beer should be excellent if it is as good as your geese," said he. "My geese!" The man seemed surprised. "Yes. I was speaking only half an hour ago to Mr. Henry Baker, who was a member of your goose club." "Ah! yes, I see. But you see, sir, them's not our geese." "Indeed! Whose, then?" "Well, I got the two dozen from a salesman in Covent Garden." "Indeed? I know some of them. Which was it?" "Breckinridge is his name." "Ah! I don't know him. Well, here's your good health landlord, and prosperity to your house. Good-night." "Now for Mr. Breckinridge," he continued, buttoning up his coat as we came out into the frosty air. "Remember, Watson that though we have so homely a thing as a goose at one end of this chain, we have at the other a man who will certainly get seven years' penal servitude unless we can establish his innocence. It is possible that our inquiry may but confirm his guilt; but, in any case, we have a line of investigation which has been missed by the police, and which a singular chance has placed in our hands. Let us follow it out to the bitter end. Faces to the south, then, and quick march!" We passed across Holborn, down Endell Street, and so through a zigzag of slums to Covent Garden Market. One of the largest stalls bore the name of Breckinridge upon it, and the proprietor a horsey-looking man, with a sharp face and trim side-whiskers was helping a boy to put up the shutters. "Good-evening. It's a cold night," said Holmes. The salesman nodded and shot a questioning glance at my companion. "Sold out of geese, I see," continued Holmes, pointing at the bare slabs of marble. "Let you have five hundred to-morrow morning." "That's no good." "Well, there are some on the stall with the gas-flare." "Ah, but I was recommended to you." "Who by?" "The landlord of the Alpha." "Oh, yes; I sent him a couple of dozen." "Fine birds they were, too. Now where did you get them from?" To my surprise the question provoked a burst of anger from the salesman. "Now, then, mister," said he, with his head cocked and his arms akimbo, "what are you driving at? Let's have it straight, now." "It is straight enough. I should like to know who sold you the geese which you supplied to the Alpha." "Well then, I shan't tell you. So now!" "Oh, it is a matter of no importance; but I don't know why you should be so warm over such a trifle." "Warm! You'd be as warm, maybe, if you were as pestered as I am. When I pay good money for a good article there should be an end of the business; but it's 'Where are the geese?' and 'Who did you sell the geese to?' and 'What will you take for the geese?' One would think they were the only geese in the world, to hear the fuss that is made over them." "Well, I have no connection with any other people who have been making inquiries," said Holmes carelessly. "If you won't tell us the bet is off, that is all. But I'm always ready to back my opinion on a matter of fowls, and I have a fiver on it that the bird I ate is country bred." "Well, then, you've lost your fiver, for it's town bred," snapped the salesman. "It's nothing of the kind." "I say it is." "I don't believe it." "D'you think you know more about fowls than I, who have handled them ever since I was a nipper? I tell you, all those birds that went to the Alpha were town bred." "You'll never persuade me to believe that." "Will you bet, then?" "It's merely taking your money, for I know that I am right. But I'll have a sovereign on with you, just to teach you not to be obstinate." The salesman chuckled grimly. "Bring me the books, Bill," said he. The small boy brought round a small thin volume and a great greasy-backed one, laying them out together beneath the hanging lamp. "Now then, Mr. Cocksure," said the salesman, "I thought that I was out of geese, but before I finish you'll find that there is still one left in my shop. You see this little book?" "Well?" "That's the list of the folk from whom I buy. D'you see? Well, then, here on this page are the country folk, and the numbers after their names are where their accounts are in the big ledger. Now, then! You see this other page in red ink? Well, that is a list of my town suppliers. Now, look at that third name. Just read it out to me." "Mrs. Oakshott, 117, Brixton Road--249," read Holmes. "Quite so. Now turn that up in the ledger." Holmes turned to the page indicated. "Here you are, 'Mrs. Oakshott, 117, Brixton Road, egg and poultry supplier.'" "Now, then, what's the last entry?" "'December 22nd. Twenty-four geese at 7s. 6d.'" "Quite so. There you are. And underneath?" "'Sold to Mr. Windigate of the Alpha, at 12s.'" "What have you to say now?" Sherlock Holmes looked deeply chagrined. He drew a sovereign from his pocket and threw it down upon the slab, turning away with the air of a man whose disgust is too deep for words. A few yards off he stopped under a lamp-post and laughed in the hearty, noiseless fashion which was peculiar to him. "When you see a man with whiskers of that cut and the 'Pink 'un' protruding out of his pocket, you can always draw him by a bet," said he. "I daresay that if I had put 100 pounds down in front of him, that man would not have given me such complete information as was drawn from him by the idea that he was doing me on a wager. Well, Watson, we are, I fancy, nearing the end of our quest, and the only point which remains to be determined is whether we should go on to this Mrs. Oakshott to-night, or whether we should reserve it for to-morrow. It is clear from what that surly fellow said that there are others besides ourselves who are anxious about the matter, and I should--" His remarks were suddenly cut short by a loud hubbub which broke out from the stall which we had just left. Turning round we saw a little rat-faced fellow standing in the centre of the circle of yellow light which was thrown by the swinging lamp, while Breckinridge, the salesman, framed in the door of his stall, was shaking his fists fiercely at the cringing figure. "I've had enough of you and your geese," he shouted. "I wish you were all at the devil together. If you come pestering me any more with your silly talk I'll set the dog at you. You bring Mrs. Oakshott here and I'll answer her, but what have you to do with it? Did I buy the geese off you?" "No; but one of them was mine all the same," whined the little man. "Well, then, ask Mrs. Oakshott for it." "She told me to ask you." "Well, you can ask the King of Proosia, for all I care. I've had enough of it. Get out of this!" He rushed fiercely forward, and the inquirer flitted away into the darkness. "Ha! this may save us a visit to Brixton Road," whispered Holmes. "Come with me, and we will see what is to be made of this fellow." Striding through the scattered knots of people who lounged round the flaring stalls, my companion speedily overtook the little man and touched him upon the shoulder. He sprang round, and I could see in the gas-light that every vestige of colour had been driven from his face. "Who are you, then? What do you want?" he asked in a quavering voice. "You will excuse me," said Holmes blandly, "but I could not help overhearing the questions which you put to the salesman just now. I think that I could be of assistance to you." "You? Who are you? How could you know anything of the matter?" "My name is Sherlock Holmes. It is my business to know what other people don't know." "But you can know nothing of this?" "Excuse me, I know everything of it. You are endeavouring to trace some geese which were sold by Mrs. Oakshott, of Brixton Road, to a salesman named Breckinridge, by him in turn to Mr. Windigate, of the Alpha, and by him to his club, of which Mr. Henry Baker is a member." "Oh, sir, you are the very man whom I have longed to meet," cried the little fellow with outstretched hands and quivering fingers. "I can hardly explain to you how interested I am in this matter." Sherlock Holmes hailed a four-wheeler which was passing. "In that case we had better discuss it in a cosy room rather than in this wind-swept market-place," said he. "But pray tell me, before we go farther, who it is that I have the pleasure of assisting." The man hesitated for an instant. "My name is John Robinson," he answered with a sidelong glance. "No, no; the real name," said Holmes sweetly. "It is always awkward doing business with an alias." A flush sprang to the white cheeks of the stranger. "Well then," said he, "my real name is James Ryder." "Precisely so. Head attendant at the Hotel Cosmopolitan. Pray step into the cab, and I shall soon be able to tell you everything which you would wish to know." The little man stood glancing from one to the other of us with half-frightened, half-hopeful eyes, as one who is not sure whether he is on the verge of a windfall or of a catastrophe. Then he stepped into the cab, and in half an hour we were back in the sitting-room at Baker Street. Nothing had been said during our drive, but the high, thin breathing of our new companion, and the claspings and unclaspings of his hands, spoke of the nervous tension within him. "Here we are!" said Holmes cheerily as we filed into the room. "The fire looks very seasonable in this weather. You look cold, Mr. Ryder. Pray take the basket-chair. I will just put on my slippers before we settle this little matter of yours. Now, then! You want to know what became of those geese?" "Yes, sir." "Or rather, I fancy, of that goose. It was one bird, I imagine in which you were interested--white, with a black bar across the tail." Ryder quivered with emotion. "Oh, sir," he cried, "can you tell me where it went to?" "It came here." "Here?" "Yes, and a most remarkable bird it proved. I don't wonder that you should take an interest in it. It laid an egg after it was dead--the bonniest, brightest little blue egg that ever was seen. I have it here in my museum." Our visitor staggered to his feet and clutched the mantelpiece with his right hand. Holmes unlocked his strong-box and held up the blue carbuncle, which shone out like a star, with a cold, brilliant, many-pointed radiance. Ryder stood glaring with a drawn face, uncertain whether to claim or to disown it. "The game's up, Ryder," said Holmes quietly. "Hold up, man, or you'll be into the fire! Give him an arm back into his chair, Watson. He's not got blood enough to go in for felony with impunity. Give him a dash of brandy. So! Now he looks a little more human. What a shrimp it is, to be sure!" For a moment he had staggered and nearly fallen, but the brandy brought a tinge of colour into his cheeks, and he sat staring with frightened eyes at his accuser. "I have almost every link in my hands, and all the proofs which I could possibly need, so there is little which you need tell me. Still, that little may as well be cleared up to make the case complete. You had heard, Ryder, of this blue stone of the Countess of Morcar's?" "It was Catherine Cusack who told me of it," said he in a crackling voice. "I see--her ladyship's waiting-maid. Well, the temptation of sudden wealth so easily acquired was too much for you, as it has been for better men before you; but you were not very scrupulous in the means you used. It seems to me, Ryder, that there is the making of a very pretty villain in you. You knew that this man Horner, the plumber, had been concerned in some such matter before, and that suspicion would rest the more readily upon him. What did you do, then? You made some small job in my lady's room--you and your confederate Cusack--and you managed that he should be the man sent for. Then, when he had left, you rifled the jewel-case, raised the alarm, and had this unfortunate man arrested. You then--" Ryder threw himself down suddenly upon the rug and clutched at my companion's knees. "For God's sake, have mercy!" he shrieked. "Think of my father! Of my mother! It would break their hearts. I never went wrong before! I never will again. I swear it. I'll swear it on a Bible. Oh, don't bring it into court! For Christ's sake, don't!" "Get back into your chair!" said Holmes sternly. "It is very well to cringe and crawl now, but you thought little enough of this poor Horner in the dock for a crime of which he knew nothing." "I will fly, Mr. Holmes. I will leave the country, sir. Then the charge against him will break down." "Hum! We will talk about that. And now let us hear a true account of the next act. How came the stone into the goose, and how came the goose into the open market? Tell us the truth, for there lies your only hope of safety." Ryder passed his tongue over his parched lips. "I will tell you it just as it happened, sir," said he. "When Horner had been arrested, it seemed to me that it would be best for me to get away with the stone at once, for I did not know at what moment the police might not take it into their heads to search me and my room. There was no place about the hotel where it would be safe. I went out, as if on some commission, and I made for my sister's house. She had married a man named Oakshott, and lived in Brixton Road, where she fattened fowls for the market. All the way there every man I met seemed to me to be a policeman or a detective; and, for all that it was a cold night, the sweat was pouring down my face before I came to the Brixton Road. My sister asked me what was the matter, and why I was so pale; but I told her that I had been upset by the jewel robbery at the hotel. Then I went into the back yard and smoked a pipe and wondered what it would be best to do. "I had a friend once called Maudsley, who went to the bad, and has just been serving his time in Pentonville. One day he had met me, and fell into talk about the ways of thieves, and how they could get rid of what they stole. I knew that he would be true to me, for I knew one or two things about him; so I made up my mind to go right on to Kilburn, where he lived, and take him into my confidence. He would show me how to turn the stone into money. But how to get to him in safety? I thought of the agonies I had gone through in coming from the hotel. I might at any moment be seized and searched, and there would be the stone in my waistcoat pocket. I was leaning against the wall at the time and looking at the geese which were waddling about round my feet, and suddenly an idea came into my head which showed me how I could beat the best detective that ever lived. "My sister had told me some weeks before that I might have the pick of her geese for a Christmas present, and I knew that she was always as good as her word. I would take my goose now, and in it I would carry my stone to Kilburn. There was a little shed in the yard, and behind this I drove one of the birds--a fine big one, white, with a barred tail. I caught it, and prying its bill open, I thrust the stone down its throat as far as my finger could reach. The bird gave a gulp, and I felt the stone pass along its gullet and down into its crop. But the creature flapped and struggled, and out came my sister to know what was the matter. As I turned to speak to her the brute broke loose and fluttered off among the others. "'Whatever were you doing with that bird, Jem?' says she. "'Well,' said I, 'you said you'd give me one for Christmas, and I was feeling which was the fattest.' "'Oh,' says she, 'we've set yours aside for you--Jem's bird, we call it. It's the big white one over yonder. There's twenty-six of them, which makes one for you, and one for us, and two dozen for the market.' "'Thank you, Maggie,' says I; 'but if it is all the same to you, I'd rather have that one I was handling just now.' "'The other is a good three pound heavier,' said she, 'and we fattened it expressly for you.' "'Never mind. I'll have the other, and I'll take it now,' said I. "'Oh, just as you like,' said she, a little huffed. 'Which is it you want, then?' "'That white one with the barred tail, right in the middle of the flock.' "'Oh, very well. Kill it and take it with you.' "Well, I did what she said, Mr. Holmes, and I carried the bird all the way to Kilburn. I told my pal what I had done, for he was a man that it was easy to tell a thing like that to. He laughed until he choked, and we got a knife and opened the goose. My heart turned to water, for there was no sign of the stone, and I knew that some terrible mistake had occurred. I left the bird, rushed back to my sister's, and hurried into the back yard. There was not a bird to be seen there. "'Where are they all, Maggie?' I cried. "'Gone to the dealer's, Jem.' "'Which dealer's?' "'Breckinridge, of Covent Garden.' "'But was there another with a barred tail?' I asked, 'the same as the one I chose?' "'Yes, Jem; there were two barred-tailed ones, and I could never tell them apart.' "Well, then, of course I saw it all, and I ran off as hard as my feet would carry me to this man Breckinridge; but he had sold the lot at once, and not one word would he tell me as to where they had gone. You heard him yourselves to-night. Well, he has always answered me like that. My sister thinks that I am going mad. Sometimes I think that I am myself. And now--and now I am myself a branded thief, without ever having touched the wealth for which I sold my character. God help me! God help me!" He burst into convulsive sobbing, with his face buried in his hands. There was a long silence, broken only by his heavy breathing and by the measured tapping of Sherlock Holmes' finger-tips upon the edge of the table. Then my friend rose and threw open the door. "Get out!" said he. "What, sir! Oh, Heaven bless you!" "No more words. Get out!" And no more words were needed. There was a rush, a clatter upon the stairs, the bang of a door, and the crisp rattle of running footfalls from the street. "After all, Watson," said Holmes, reaching up his hand for his clay pipe, "I am not retained by the police to supply their deficiencies. If Horner were in danger it would be another thing; but this fellow will not appear against him, and the case must collapse. I suppose that I am commuting a felony, but it is just possible that I am saving a soul. This fellow will not go wrong again; he is too terribly frightened. Send him to gaol now, and you make him a gaol-bird for life. Besides, it is the season of forgiveness. Chance has put in our way a most singular and whimsical problem, and its solution is its own reward. If you will have the goodness to touch the bell, Doctor, we will begin another investigation, in which, also a bird will be the chief feature." VIII. THE ADVENTURE OF THE SPECKLED BAND On glancing over my notes of the seventy odd cases in which I have during the last eight years studied the methods of my friend Sherlock Holmes, I find many tragic, some comic, a large number merely strange, but none commonplace; for, working as he did rather for the love of his art than for the acquirement of wealth, he refused to associate himself with any investigation which did not tend towards the unusual, and even the fantastic. Of all these varied cases, however, I cannot recall any which presented more singular features than that which was associated with the well-known Surrey family of the Roylotts of Stoke Moran. The events in question occurred in the early days of my association with Holmes, when we were sharing rooms as bachelors in Baker Street. It is possible that I might have placed them upon record before, but a promise of secrecy was made at the time, from which I have only been freed during the last month by the untimely death of the lady to whom the pledge was given. It is perhaps as well that the facts should now come to light, for I have reasons to know that there are widespread rumours as to the death of Dr. Grimesby Roylott which tend to make the matter even more terrible than the truth. It was early in April in the year '83 that I woke one morning to find Sherlock Holmes standing, fully dressed, by the side of my bed. He was a late riser, as a rule, and as the clock on the mantelpiece showed me that it was only a quarter-past seven, I blinked up at him in some surprise, and perhaps just a little resentment, for I was myself regular in my habits. "Very sorry to knock you up, Watson," said he, "but it's the common lot this morning. Mrs. Hudson has been knocked up, she retorted upon me, and I on you." "What is it, then--a fire?" "No; a client. It seems that a young lady has arrived in a considerable state of excitement, who insists upon seeing me. She is waiting now in the sitting-room. Now, when young ladies wander about the metropolis at this hour of the morning, and knock sleepy people up out of their beds, I presume that it is something very pressing which they have to communicate. Should it prove to be an interesting case, you would, I am sure, wish to follow it from the outset. I thought, at any rate, that I should call you and give you the chance." "My dear fellow, I would not miss it for anything." I had no keener pleasure than in following Holmes in his professional investigations, and in admiring the rapid deductions, as swift as intuitions, and yet always founded on a logical basis with which he unravelled the problems which were submitted to him. I rapidly threw on my clothes and was ready in a few minutes to accompany my friend down to the sitting-room. A lady dressed in black and heavily veiled, who had been sitting in the window, rose as we entered. "Good-morning, madam," said Holmes cheerily. "My name is Sherlock Holmes. This is my intimate friend and associate, Dr. Watson, before whom you can speak as freely as before myself. Ha! I am glad to see that Mrs. Hudson has had the good sense to light the fire. Pray draw up to it, and I shall order you a cup of hot coffee, for I observe that you are shivering." "It is not cold which makes me shiver," said the woman in a low voice, changing her seat as requested. "What, then?" "It is fear, Mr. Holmes. It is terror." She raised her veil as she spoke, and we could see that she was indeed in a pitiable state of agitation, her face all drawn and grey, with restless frightened eyes, like those of some hunted animal. Her features and figure were those of a woman of thirty, but her hair was shot with premature grey, and her expression was weary and haggard. Sherlock Holmes ran her over with one of his quick, all-comprehensive glances. "You must not fear," said he soothingly, bending forward and patting her forearm. "We shall soon set matters right, I have no doubt. You have come in by train this morning, I see." "You know me, then?" "No, but I observe the second half of a return ticket in the palm of your left glove. You must have started early, and yet you had a good drive in a dog-cart, along heavy roads, before you reached the station." The lady gave a violent start and stared in bewilderment at my companion. "There is no mystery, my dear madam," said he, smiling. "The left arm of your jacket is spattered with mud in no less than seven places. The marks are perfectly fresh. There is no vehicle save a dog-cart which throws up mud in that way, and then only when you sit on the left-hand side of the driver." "Whatever your reasons may be, you are perfectly correct," said she. "I started from home before six, reached Leatherhead at twenty past, and came in by the first train to Waterloo. Sir, I can stand this strain no longer; I shall go mad if it continues. I have no one to turn to--none, save only one, who cares for me, and he, poor fellow, can be of little aid. I have heard of you, Mr. Holmes; I have heard of you from Mrs. Farintosh, whom you helped in the hour of her sore need. It was from her that I had your address. Oh, sir, do you not think that you could help me, too, and at least throw a little light through the dense darkness which surrounds me? At present it is out of my power to reward you for your services, but in a month or six weeks I shall be married, with the control of my own income, and then at least you shall not find me ungrateful." Holmes turned to his desk and, unlocking it, drew out a small case-book, which he consulted. "Farintosh," said he. "Ah yes, I recall the case; it was concerned with an opal tiara. I think it was before your time, Watson. I can only say, madam, that I shall be happy to devote the same care to your case as I did to that of your friend. As to reward, my profession is its own reward; but you are at liberty to defray whatever expenses I may be put to, at the time which suits you best. And now I beg that you will lay before us everything that may help us in forming an opinion upon the matter." "Alas!" replied our visitor, "the very horror of my situation lies in the fact that my fears are so vague, and my suspicions depend so entirely upon small points, which might seem trivial to another, that even he to whom of all others I have a right to look for help and advice looks upon all that I tell him about it as the fancies of a nervous woman. He does not say so, but I can read it from his soothing answers and averted eyes. But I have heard, Mr. Holmes, that you can see deeply into the manifold wickedness of the human heart. You may advise me how to walk amid the dangers which encompass me." "I am all attention, madam." "My name is Helen Stoner, and I am living with my stepfather, who is the last survivor of one of the oldest Saxon families in England, the Roylotts of Stoke Moran, on the western border of Surrey." Holmes nodded his head. "The name is familiar to me," said he. "The family was at one time among the richest in England, and the estates extended over the borders into Berkshire in the north, and Hampshire in the west. In the last century, however, four successive heirs were of a dissolute and wasteful disposition, and the family ruin was eventually completed by a gambler in the days of the Regency. Nothing was left save a few acres of ground, and the two-hundred-year-old house, which is itself crushed under a heavy mortgage. The last squire dragged out his existence there, living the horrible life of an aristocratic pauper; but his only son, my stepfather, seeing that he must adapt himself to the new conditions, obtained an advance from a relative, which enabled him to take a medical degree and went out to Calcutta, where, by his professional skill and his force of character, he established a large practice. In a fit of anger, however, caused by some robberies which had been perpetrated in the house, he beat his native butler to death and narrowly escaped a capital sentence. As it was, he suffered a long term of imprisonment and afterwards returned to England a morose and disappointed man. "When Dr. Roylott was in India he married my mother, Mrs. Stoner, the young widow of Major-General Stoner, of the Bengal Artillery. My sister Julia and I were twins, and we were only two years old at the time of my mother's re-marriage. She had a considerable sum of money--not less than 1000 pounds a year--and this she bequeathed to Dr. Roylott entirely while we resided with him, with a provision that a certain annual sum should be allowed to each of us in the event of our marriage. Shortly after our return to England my mother died--she was killed eight years ago in a railway accident near Crewe. Dr. Roylott then abandoned his attempts to establish himself in practice in London and took us to live with him in the old ancestral house at Stoke Moran. The money which my mother had left was enough for all our wants, and there seemed to be no obstacle to our happiness. "But a terrible change came over our stepfather about this time. Instead of making friends and exchanging visits with our neighbours, who had at first been overjoyed to see a Roylott of Stoke Moran back in the old family seat, he shut himself up in his house and seldom came out save to indulge in ferocious quarrels with whoever might cross his path. Violence of temper approaching to mania has been hereditary in the men of the family, and in my stepfather's case it had, I believe, been intensified by his long residence in the tropics. A series of disgraceful brawls took place, two of which ended in the police-court, until at last he became the terror of the village, and the folks would fly at his approach, for he is a man of immense strength, and absolutely uncontrollable in his anger. "Last week he hurled the local blacksmith over a parapet into a stream, and it was only by paying over all the money which I could gather together that I was able to avert another public exposure. He had no friends at all save the wandering gipsies, and he would give these vagabonds leave to encamp upon the few acres of bramble-covered land which represent the family estate, and would accept in return the hospitality of their tents, wandering away with them sometimes for weeks on end. He has a passion also for Indian animals, which are sent over to him by a correspondent, and he has at this moment a cheetah and a baboon, which wander freely over his grounds and are feared by the villagers almost as much as their master. "You can imagine from what I say that my poor sister Julia and I had no great pleasure in our lives. No servant would stay with us, and for a long time we did all the work of the house. She was but thirty at the time of her death, and yet her hair had already begun to whiten, even as mine has." "Your sister is dead, then?" "She died just two years ago, and it is of her death that I wish to speak to you. You can understand that, living the life which I have described, we were little likely to see anyone of our own age and position. We had, however, an aunt, my mother's maiden sister, Miss Honoria Westphail, who lives near Harrow, and we were occasionally allowed to pay short visits at this lady's house. Julia went there at Christmas two years ago, and met there a half-pay major of marines, to whom she became engaged. My stepfather learned of the engagement when my sister returned and offered no objection to the marriage; but within a fortnight of the day which had been fixed for the wedding, the terrible event occurred which has deprived me of my only companion." Sherlock Holmes had been leaning back in his chair with his eyes closed and his head sunk in a cushion, but he half opened his lids now and glanced across at his visitor. "Pray be precise as to details," said he. "It is easy for me to be so, for every event of that dreadful time is seared into my memory. The manor-house is, as I have already said, very old, and only one wing is now inhabited. The bedrooms in this wing are on the ground floor, the sitting-rooms being in the central block of the buildings. Of these bedrooms the first is Dr. Roylott's, the second my sister's, and the third my own. There is no communication between them, but they all open out into the same corridor. Do I make myself plain?" "Perfectly so." "The windows of the three rooms open out upon the lawn. That fatal night Dr. Roylott had gone to his room early, though we knew that he had not retired to rest, for my sister was troubled by the smell of the strong Indian cigars which it was his custom to smoke. She left her room, therefore, and came into mine, where she sat for some time, chatting about her approaching wedding. At eleven o'clock she rose to leave me, but she paused at the door and looked back. "'Tell me, Helen,' said she, 'have you ever heard anyone whistle in the dead of the night?' "'Never,' said I. "'I suppose that you could not possibly whistle, yourself, in your sleep?' "'Certainly not. But why?' "'Because during the last few nights I have always, about three in the morning, heard a low, clear whistle. I am a light sleeper, and it has awakened me. I cannot tell where it came from--perhaps from the next room, perhaps from the lawn. I thought that I would just ask you whether you had heard it.' "'No, I have not. It must be those wretched gipsies in the plantation.' "'Very likely. And yet if it were on the lawn, I wonder that you did not hear it also.' "'Ah, but I sleep more heavily than you.' "'Well, it is of no great consequence, at any rate.' She smiled back at me, closed my door, and a few moments later I heard her key turn in the lock." "Indeed," said Holmes. "Was it your custom always to lock yourselves in at night?" "Always." "And why?" "I think that I mentioned to you that the doctor kept a cheetah and a baboon. We had no feeling of security unless our doors were locked." "Quite so. Pray proceed with your statement." "I could not sleep that night. A vague feeling of impending misfortune impressed me. My sister and I, you will recollect, were twins, and you know how subtle are the links which bind two souls which are so closely allied. It was a wild night. The wind was howling outside, and the rain was beating and splashing against the windows. Suddenly, amid all the hubbub of the gale, there burst forth the wild scream of a terrified woman. I knew that it was my sister's voice. I sprang from my bed, wrapped a shawl round me, and rushed into the corridor. As I opened my door I seemed to hear a low whistle, such as my sister described, and a few moments later a clanging sound, as if a mass of metal had fallen. As I ran down the passage, my sister's door was unlocked, and revolved slowly upon its hinges. I stared at it horror-stricken, not knowing what was about to issue from it. By the light of the corridor-lamp I saw my sister appear at the opening, her face blanched with terror, her hands groping for help, her whole figure swaying to and fro like that of a drunkard. I ran to her and threw my arms round her, but at that moment her knees seemed to give way and she fell to the ground. She writhed as one who is in terrible pain, and her limbs were dreadfully convulsed. At first I thought that she had not recognised me, but as I bent over her she suddenly shrieked out in a voice which I shall never forget, 'Oh, my God! Helen! It was the band! The speckled band!' There was something else which she would fain have said, and she stabbed with her finger into the air in the direction of the doctor's room, but a fresh convulsion seized her and choked her words. I rushed out, calling loudly for my stepfather, and I met him hastening from his room in his dressing-gown. When he reached my sister's side she was unconscious, and though he poured brandy down her throat and sent for medical aid from the village, all efforts were in vain, for she slowly sank and died without having recovered her consciousness. Such was the dreadful end of my beloved sister." "One moment," said Holmes, "are you sure about this whistle and metallic sound? Could you swear to it?" "That was what the county coroner asked me at the inquiry. It is my strong impression that I heard it, and yet, among the crash of the gale and the creaking of an old house, I may possibly have been deceived." "Was your sister dressed?" "No, she was in her night-dress. In her right hand was found the charred stump of a match, and in her left a match-box." "Showing that she had struck a light and looked about her when the alarm took place. That is important. And what conclusions did the coroner come to?" "He investigated the case with great care, for Dr. Roylott's conduct had long been notorious in the county, but he was unable to find any satisfactory cause of death. My evidence showed that the door had been fastened upon the inner side, and the windows were blocked by old-fashioned shutters with broad iron bars, which were secured every night. The walls were carefully sounded, and were shown to be quite solid all round, and the flooring was also thoroughly examined, with the same result. The chimney is wide, but is barred up by four large staples. It is certain, therefore, that my sister was quite alone when she met her end. Besides, there were no marks of any violence upon her." "How about poison?" "The doctors examined her for it, but without success." "What do you think that this unfortunate lady died of, then?" "It is my belief that she died of pure fear and nervous shock, though what it was that frightened her I cannot imagine." "Were there gipsies in the plantation at the time?" "Yes, there are nearly always some there." "Ah, and what did you gather from this allusion to a band--a speckled band?" "Sometimes I have thought that it was merely the wild talk of delirium, sometimes that it may have referred to some band of people, perhaps to these very gipsies in the plantation. I do not know whether the spotted handkerchiefs which so many of them wear over their heads might have suggested the strange adjective which she used." Holmes shook his head like a man who is far from being satisfied. "These are very deep waters," said he; "pray go on with your narrative." "Two years have passed since then, and my life has been until lately lonelier than ever. A month ago, however, a dear friend, whom I have known for many years, has done me the honour to ask my hand in marriage. His name is Armitage--Percy Armitage--the second son of Mr. Armitage, of Crane Water, near Reading. My stepfather has offered no opposition to the match, and we are to be married in the course of the spring. Two days ago some repairs were started in the west wing of the building, and my bedroom wall has been pierced, so that I have had to move into the chamber in which my sister died, and to sleep in the very bed in which she slept. Imagine, then, my thrill of terror when last night, as I lay awake, thinking over her terrible fate, I suddenly heard in the silence of the night the low whistle which had been the herald of her own death. I sprang up and lit the lamp, but nothing was to be seen in the room. I was too shaken to go to bed again, however, so I dressed, and as soon as it was daylight I slipped down, got a dog-cart at the Crown Inn, which is opposite, and drove to Leatherhead, from whence I have come on this morning with the one object of seeing you and asking your advice." "You have done wisely," said my friend. "But have you told me all?" "Yes, all." "Miss Roylott, you have not. You are screening your stepfather." "Why, what do you mean?" For answer Holmes pushed back the frill of black lace which fringed the hand that lay upon our visitor's knee. Five little livid spots, the marks of four fingers and a thumb, were printed upon the white wrist. "You have been cruelly used," said Holmes. The lady coloured deeply and covered over her injured wrist. "He is a hard man," she said, "and perhaps he hardly knows his own strength." There was a long silence, during which Holmes leaned his chin upon his hands and stared into the crackling fire. "This is a very deep business," he said at last. "There are a thousand details which I should desire to know before I decide upon our course of action. Yet we have not a moment to lose. If we were to come to Stoke Moran to-day, would it be possible for us to see over these rooms without the knowledge of your stepfather?" "As it happens, he spoke of coming into town to-day upon some most important business. It is probable that he will be away all day, and that there would be nothing to disturb you. We have a housekeeper now, but she is old and foolish, and I could easily get her out of the way." "Excellent. You are not averse to this trip, Watson?" "By no means." "Then we shall both come. What are you going to do yourself?" "I have one or two things which I would wish to do now that I am in town. But I shall return by the twelve o'clock train, so as to be there in time for your coming." "And you may expect us early in the afternoon. I have myself some small business matters to attend to. Will you not wait and breakfast?" "No, I must go. My heart is lightened already since I have confided my trouble to you. I shall look forward to seeing you again this afternoon." She dropped her thick black veil over her face and glided from the room. "And what do you think of it all, Watson?" asked Sherlock Holmes, leaning back in his chair. "It seems to me to be a most dark and sinister business." "Dark enough and sinister enough." "Yet if the lady is correct in saying that the flooring and walls are sound, and that the door, window, and chimney are impassable, then her sister must have been undoubtedly alone when she met her mysterious end." "What becomes, then, of these nocturnal whistles, and what of the very peculiar words of the dying woman?" "I cannot think." "When you combine the ideas of whistles at night, the presence of a band of gipsies who are on intimate terms with this old doctor, the fact that we have every reason to believe that the doctor has an interest in preventing his stepdaughter's marriage, the dying allusion to a band, and, finally, the fact that Miss Helen Stoner heard a metallic clang, which might have been caused by one of those metal bars that secured the shutters falling back into its place, I think that there is good ground to think that the mystery may be cleared along those lines." "But what, then, did the gipsies do?" "I cannot imagine." "I see many objections to any such theory." "And so do I. It is precisely for that reason that we are going to Stoke Moran this day. I want to see whether the objections are fatal, or if they may be explained away. But what in the name of the devil!" The ejaculation had been drawn from my companion by the fact that our door had been suddenly dashed open, and that a huge man had framed himself in the aperture. His costume was a peculiar mixture of the professional and of the agricultural, having a black top-hat, a long frock-coat, and a pair of high gaiters, with a hunting-crop swinging in his hand. So tall was he that his hat actually brushed the cross bar of the doorway, and his breadth seemed to span it across from side to side. A large face, seared with a thousand wrinkles, burned yellow with the sun, and marked with every evil passion, was turned from one to the other of us, while his deep-set, bile-shot eyes, and his high, thin, fleshless nose, gave him somewhat the resemblance to a fierce old bird of prey. "Which of you is Holmes?" asked this apparition. "My name, sir; but you have the advantage of me," said my companion quietly. "I am Dr. Grimesby Roylott, of Stoke Moran." "Indeed, Doctor," said Holmes blandly. "Pray take a seat." "I will do nothing of the kind. My stepdaughter has been here. I have traced her. What has she been saying to you?" "It is a little cold for the time of the year," said Holmes. "What has she been saying to you?" screamed the old man furiously. "But I have heard that the crocuses promise well," continued my companion imperturbably. "Ha! You put me off, do you?" said our new visitor, taking a step forward and shaking his hunting-crop. "I know you, you scoundrel! I have heard of you before. You are Holmes, the meddler." My friend smiled. "Holmes, the busybody!" His smile broadened. "Holmes, the Scotland Yard Jack-in-office!" Holmes chuckled heartily. "Your conversation is most entertaining," said he. "When you go out close the door, for there is a decided draught." "I will go when I have said my say. Don't you dare to meddle with my affairs. I know that Miss Stoner has been here. I traced her! I am a dangerous man to fall foul of! See here." He stepped swiftly forward, seized the poker, and bent it into a curve with his huge brown hands. "See that you keep yourself out of my grip," he snarled, and hurling the twisted poker into the fireplace he strode out of the room. "He seems a very amiable person," said Holmes, laughing. "I am not quite so bulky, but if he had remained I might have shown him that my grip was not much more feeble than his own." As he spoke he picked up the steel poker and, with a sudden effort, straightened it out again. "Fancy his having the insolence to confound me with the official detective force! This incident gives zest to our investigation, however, and I only trust that our little friend will not suffer from her imprudence in allowing this brute to trace her. And now, Watson, we shall order breakfast, and afterwards I shall walk down to Doctors' Commons, where I hope to get some data which may help us in this matter." It was nearly one o'clock when Sherlock Holmes returned from his excursion. He held in his hand a sheet of blue paper, scrawled over with notes and figures. "I have seen the will of the deceased wife," said he. "To determine its exact meaning I have been obliged to work out the present prices of the investments with which it is concerned. The total income, which at the time of the wife's death was little short of 1100 pounds, is now, through the fall in agricultural prices, not more than 750 pounds. Each daughter can claim an income of 250 pounds, in case of marriage. It is evident, therefore, that if both girls had married, this beauty would have had a mere pittance, while even one of them would cripple him to a very serious extent. My morning's work has not been wasted, since it has proved that he has the very strongest motives for standing in the way of anything of the sort. And now, Watson, this is too serious for dawdling, especially as the old man is aware that we are interesting ourselves in his affairs; so if you are ready, we shall call a cab and drive to Waterloo. I should be very much obliged if you would slip your revolver into your pocket. An Eley's No. 2 is an excellent argument with gentlemen who can twist steel pokers into knots. That and a tooth-brush are, I think, all that we need." At Waterloo we were fortunate in catching a train for Leatherhead, where we hired a trap at the station inn and drove for four or five miles through the lovely Surrey lanes. It was a perfect day, with a bright sun and a few fleecy clouds in the heavens. The trees and wayside hedges were just throwing out their first green shoots, and the air was full of the pleasant smell of the moist earth. To me at least there was a strange contrast between the sweet promise of the spring and this sinister quest upon which we were engaged. My companion sat in the front of the trap, his arms folded, his hat pulled down over his eyes, and his chin sunk upon his breast, buried in the deepest thought. Suddenly, however, he started, tapped me on the shoulder, and pointed over the meadows. "Look there!" said he. A heavily timbered park stretched up in a gentle slope, thickening into a grove at the highest point. From amid the branches there jutted out the grey gables and high roof-tree of a very old mansion. "Stoke Moran?" said he. "Yes, sir, that be the house of Dr. Grimesby Roylott," remarked the driver. "There is some building going on there," said Holmes; "that is where we are going." "There's the village," said the driver, pointing to a cluster of roofs some distance to the left; "but if you want to get to the house, you'll find it shorter to get over this stile, and so by the foot-path over the fields. There it is, where the lady is walking." "And the lady, I fancy, is Miss Stoner," observed Holmes, shading his eyes. "Yes, I think we had better do as you suggest." We got off, paid our fare, and the trap rattled back on its way to Leatherhead. "I thought it as well," said Holmes as we climbed the stile, "that this fellow should think we had come here as architects, or on some definite business. It may stop his gossip. Good-afternoon, Miss Stoner. You see that we have been as good as our word." Our client of the morning had hurried forward to meet us with a face which spoke her joy. "I have been waiting so eagerly for you," she cried, shaking hands with us warmly. "All has turned out splendidly. Dr. Roylott has gone to town, and it is unlikely that he will be back before evening." "We have had the pleasure of making the doctor's acquaintance," said Holmes, and in a few words he sketched out what had occurred. Miss Stoner turned white to the lips as she listened. "Good heavens!" she cried, "he has followed me, then." "So it appears." "He is so cunning that I never know when I am safe from him. What will he say when he returns?" "He must guard himself, for he may find that there is someone more cunning than himself upon his track. You must lock yourself up from him to-night. If he is violent, we shall take you away to your aunt's at Harrow. Now, we must make the best use of our time, so kindly take us at once to the rooms which we are to examine." The building was of grey, lichen-blotched stone, with a high central portion and two curving wings, like the claws of a crab, thrown out on each side. In one of these wings the windows were broken and blocked with wooden boards, while the roof was partly caved in, a picture of ruin. The central portion was in little better repair, but the right-hand block was comparatively modern, and the blinds in the windows, with the blue smoke curling up from the chimneys, showed that this was where the family resided. Some scaffolding had been erected against the end wall, and the stone-work had been broken into, but there were no signs of any workmen at the moment of our visit. Holmes walked slowly up and down the ill-trimmed lawn and examined with deep attention the outsides of the windows. "This, I take it, belongs to the room in which you used to sleep, the centre one to your sister's, and the one next to the main building to Dr. Roylott's chamber?" "Exactly so. But I am now sleeping in the middle one." "Pending the alterations, as I understand. By the way, there does not seem to be any very pressing need for repairs at that end wall." "There were none. I believe that it was an excuse to move me from my room." "Ah! that is suggestive. Now, on the other side of this narrow wing runs the corridor from which these three rooms open. There are windows in it, of course?" "Yes, but very small ones. Too narrow for anyone to pass through." "As you both locked your doors at night, your rooms were unapproachable from that side. Now, would you have the kindness to go into your room and bar your shutters?" Miss Stoner did so, and Holmes, after a careful examination through the open window, endeavoured in every way to force the shutter open, but without success. There was no slit through which a knife could be passed to raise the bar. Then with his lens he tested the hinges, but they were of solid iron, built firmly into the massive masonry. "Hum!" said he, scratching his chin in some perplexity, "my theory certainly presents some difficulties. No one could pass these shutters if they were bolted. Well, we shall see if the inside throws any light upon the matter." A small side door led into the whitewashed corridor from which the three bedrooms opened. Holmes refused to examine the third chamber, so we passed at once to the second, that in which Miss Stoner was now sleeping, and in which her sister had met with her fate. It was a homely little room, with a low ceiling and a gaping fireplace, after the fashion of old country-houses. A brown chest of drawers stood in one corner, a narrow white-counterpaned bed in another, and a dressing-table on the left-hand side of the window. These articles, with two small wicker-work chairs, made up all the furniture in the room save for a square of Wilton carpet in the centre. The boards round and the panelling of the walls were of brown, worm-eaten oak, so old and discoloured that it may have dated from the original building of the house. Holmes drew one of the chairs into a corner and sat silent, while his eyes travelled round and round and up and down, taking in every detail of the apartment. "Where does that bell communicate with?" he asked at last pointing to a thick bell-rope which hung down beside the bed, the tassel actually lying upon the pillow. "It goes to the housekeeper's room." "It looks newer than the other things?" "Yes, it was only put there a couple of years ago." "Your sister asked for it, I suppose?" "No, I never heard of her using it. We used always to get what we wanted for ourselves." "Indeed, it seemed unnecessary to put so nice a bell-pull there. You will excuse me for a few minutes while I satisfy myself as to this floor." He threw himself down upon his face with his lens in his hand and crawled swiftly backward and forward, examining minutely the cracks between the boards. Then he did the same with the wood-work with which the chamber was panelled. Finally he walked over to the bed and spent some time in staring at it and in running his eye up and down the wall. Finally he took the bell-rope in his hand and gave it a brisk tug. "Why, it's a dummy," said he. "Won't it ring?" "No, it is not even attached to a wire. This is very interesting. You can see now that it is fastened to a hook just above where the little opening for the ventilator is." "How very absurd! I never noticed that before." "Very strange!" muttered Holmes, pulling at the rope. "There are one or two very singular points about this room. For example, what a fool a builder must be to open a ventilator into another room, when, with the same trouble, he might have communicated with the outside air!" "That is also quite modern," said the lady. "Done about the same time as the bell-rope?" remarked Holmes. "Yes, there were several little changes carried out about that time." "They seem to have been of a most interesting character--dummy bell-ropes, and ventilators which do not ventilate. With your permission, Miss Stoner, we shall now carry our researches into the inner apartment." Dr. Grimesby Roylott's chamber was larger than that of his step-daughter, but was as plainly furnished. A camp-bed, a small wooden shelf full of books, mostly of a technical character, an armchair beside the bed, a plain wooden chair against the wall, a round table, and a large iron safe were the principal things which met the eye. Holmes walked slowly round and examined each and all of them with the keenest interest. "What's in here?" he asked, tapping the safe. "My stepfather's business papers." "Oh! you have seen inside, then?" "Only once, some years ago. I remember that it was full of papers." "There isn't a cat in it, for example?" "No. What a strange idea!" "Well, look at this!" He took up a small saucer of milk which stood on the top of it. "No; we don't keep a cat. But there is a cheetah and a baboon." "Ah, yes, of course! Well, a cheetah is just a big cat, and yet a saucer of milk does not go very far in satisfying its wants, I daresay. There is one point which I should wish to determine." He squatted down in front of the wooden chair and examined the seat of it with the greatest attention. "Thank you. That is quite settled," said he, rising and putting his lens in his pocket. "Hullo! Here is something interesting!" The object which had caught his eye was a small dog lash hung on one corner of the bed. The lash, however, was curled upon itself and tied so as to make a loop of whipcord. "What do you make of that, Watson?" "It's a common enough lash. But I don't know why it should be tied." "That is not quite so common, is it? Ah, me! it's a wicked world, and when a clever man turns his brains to crime it is the worst of all. I think that I have seen enough now, Miss Stoner, and with your permission we shall walk out upon the lawn." I had never seen my friend's face so grim or his brow so dark as it was when we turned from the scene of this investigation. We had walked several times up and down the lawn, neither Miss Stoner nor myself liking to break in upon his thoughts before he roused himself from his reverie. "It is very essential, Miss Stoner," said he, "that you should absolutely follow my advice in every respect." "I shall most certainly do so." "The matter is too serious for any hesitation. Your life may depend upon your compliance." "I assure you that I am in your hands." "In the first place, both my friend and I must spend the night in your room." Both Miss Stoner and I gazed at him in astonishment. "Yes, it must be so. Let me explain. I believe that that is the village inn over there?" "Yes, that is the Crown." "Very good. Your windows would be visible from there?" "Certainly." "You must confine yourself to your room, on pretence of a headache, when your stepfather comes back. Then when you hear him retire for the night, you must open the shutters of your window, undo the hasp, put your lamp there as a signal to us, and then withdraw quietly with everything which you are likely to want into the room which you used to occupy. I have no doubt that, in spite of the repairs, you could manage there for one night." "Oh, yes, easily." "The rest you will leave in our hands." "But what will you do?" "We shall spend the night in your room, and we shall investigate the cause of this noise which has disturbed you." "I believe, Mr. Holmes, that you have already made up your mind," said Miss Stoner, laying her hand upon my companion's sleeve. "Perhaps I have." "Then, for pity's sake, tell me what was the cause of my sister's death." "I should prefer to have clearer proofs before I speak." "You can at least tell me whether my own thought is correct, and if she died from some sudden fright." "No, I do not think so. I think that there was probably some more tangible cause. And now, Miss Stoner, we must leave you for if Dr. Roylott returned and saw us our journey would be in vain. Good-bye, and be brave, for if you will do what I have told you, you may rest assured that we shall soon drive away the dangers that threaten you." Sherlock Holmes and I had no difficulty in engaging a bedroom and sitting-room at the Crown Inn. They were on the upper floor, and from our window we could command a view of the avenue gate, and of the inhabited wing of Stoke Moran Manor House. At dusk we saw Dr. Grimesby Roylott drive past, his huge form looming up beside the little figure of the lad who drove him. The boy had some slight difficulty in undoing the heavy iron gates, and we heard the hoarse roar of the doctor's voice and saw the fury with which he shook his clinched fists at him. The trap drove on, and a few minutes later we saw a sudden light spring up among the trees as the lamp was lit in one of the sitting-rooms. "Do you know, Watson," said Holmes as we sat together in the gathering darkness, "I have really some scruples as to taking you to-night. There is a distinct element of danger." "Can I be of assistance?" "Your presence might be invaluable." "Then I shall certainly come." "It is very kind of you." "You speak of danger. You have evidently seen more in these rooms than was visible to me." "No, but I fancy that I may have deduced a little more. I imagine that you saw all that I did." "I saw nothing remarkable save the bell-rope, and what purpose that could answer I confess is more than I can imagine." "You saw the ventilator, too?" "Yes, but I do not think that it is such a very unusual thing to have a small opening between two rooms. It was so small that a rat could hardly pass through." "I knew that we should find a ventilator before ever we came to Stoke Moran." "My dear Holmes!" "Oh, yes, I did. You remember in her statement she said that her sister could smell Dr. Roylott's cigar. Now, of course that suggested at once that there must be a communication between the two rooms. It could only be a small one, or it would have been remarked upon at the coroner's inquiry. I deduced a ventilator." "But what harm can there be in that?" "Well, there is at least a curious coincidence of dates. A ventilator is made, a cord is hung, and a lady who sleeps in the bed dies. Does not that strike you?" "I cannot as yet see any connection." "Did you observe anything very peculiar about that bed?" "No." "It was clamped to the floor. Did you ever see a bed fastened like that before?" "I cannot say that I have." "The lady could not move her bed. It must always be in the same relative position to the ventilator and to the rope--or so we may call it, since it was clearly never meant for a bell-pull." "Holmes," I cried, "I seem to see dimly what you are hinting at. We are only just in time to prevent some subtle and horrible crime." "Subtle enough and horrible enough. When a doctor does go wrong he is the first of criminals. He has nerve and he has knowledge. Palmer and Pritchard were among the heads of their profession. This man strikes even deeper, but I think, Watson, that we shall be able to strike deeper still. But we shall have horrors enough before the night is over; for goodness' sake let us have a quiet pipe and turn our minds for a few hours to something more cheerful." About nine o'clock the light among the trees was extinguished, and all was dark in the direction of the Manor House. Two hours passed slowly away, and then, suddenly, just at the stroke of eleven, a single bright light shone out right in front of us. "That is our signal," said Holmes, springing to his feet; "it comes from the middle window." As we passed out he exchanged a few words with the landlord, explaining that we were going on a late visit to an acquaintance, and that it was possible that we might spend the night there. A moment later we were out on the dark road, a chill wind blowing in our faces, and one yellow light twinkling in front of us through the gloom to guide us on our sombre errand. There was little difficulty in entering the grounds, for unrepaired breaches gaped in the old park wall. Making our way among the trees, we reached the lawn, crossed it, and were about to enter through the window when out from a clump of laurel bushes there darted what seemed to be a hideous and distorted child, who threw itself upon the grass with writhing limbs and then ran swiftly across the lawn into the darkness. "My God!" I whispered; "did you see it?" Holmes was for the moment as startled as I. His hand closed like a vice upon my wrist in his agitation. Then he broke into a low laugh and put his lips to my ear. "It is a nice household," he murmured. "That is the baboon." I had forgotten the strange pets which the doctor affected. There was a cheetah, too; perhaps we might find it upon our shoulders at any moment. I confess that I felt easier in my mind when, after following Holmes' example and slipping off my shoes, I found myself inside the bedroom. My companion noiselessly closed the shutters, moved the lamp onto the table, and cast his eyes round the room. All was as we had seen it in the daytime. Then creeping up to me and making a trumpet of his hand, he whispered into my ear again so gently that it was all that I could do to distinguish the words: "The least sound would be fatal to our plans." I nodded to show that I had heard. "We must sit without light. He would see it through the ventilator." I nodded again. "Do not go asleep; your very life may depend upon it. Have your pistol ready in case we should need it. I will sit on the side of the bed, and you in that chair." I took out my revolver and laid it on the corner of the table. Holmes had brought up a long thin cane, and this he placed upon the bed beside him. By it he laid the box of matches and the stump of a candle. Then he turned down the lamp, and we were left in darkness. How shall I ever forget that dreadful vigil? I could not hear a sound, not even the drawing of a breath, and yet I knew that my companion sat open-eyed, within a few feet of me, in the same state of nervous tension in which I was myself. The shutters cut off the least ray of light, and we waited in absolute darkness. From outside came the occasional cry of a night-bird, and once at our very window a long drawn catlike whine, which told us that the cheetah was indeed at liberty. Far away we could hear the deep tones of the parish clock, which boomed out every quarter of an hour. How long they seemed, those quarters! Twelve struck, and one and two and three, and still we sat waiting silently for whatever might befall. Suddenly there was the momentary gleam of a light up in the direction of the ventilator, which vanished immediately, but was succeeded by a strong smell of burning oil and heated metal. Someone in the next room had lit a dark-lantern. I heard a gentle sound of movement, and then all was silent once more, though the smell grew stronger. For half an hour I sat with straining ears. Then suddenly another sound became audible--a very gentle, soothing sound, like that of a small jet of steam escaping continually from a kettle. The instant that we heard it, Holmes sprang from the bed, struck a match, and lashed furiously with his cane at the bell-pull. "You see it, Watson?" he yelled. "You see it?" But I saw nothing. At the moment when Holmes struck the light I heard a low, clear whistle, but the sudden glare flashing into my weary eyes made it impossible for me to tell what it was at which my friend lashed so savagely. I could, however, see that his face was deadly pale and filled with horror and loathing. He had ceased to strike and was gazing up at the ventilator when suddenly there broke from the silence of the night the most horrible cry to which I have ever listened. It swelled up louder and louder, a hoarse yell of pain and fear and anger all mingled in the one dreadful shriek. They say that away down in the village, and even in the distant parsonage, that cry raised the sleepers from their beds. It struck cold to our hearts, and I stood gazing at Holmes, and he at me, until the last echoes of it had died away into the silence from which it rose. "What can it mean?" I gasped. "It means that it is all over," Holmes answered. "And perhaps, after all, it is for the best. Take your pistol, and we will enter Dr. Roylott's room." With a grave face he lit the lamp and led the way down the corridor. Twice he struck at the chamber door without any reply from within. Then he turned the handle and entered, I at his heels, with the cocked pistol in my hand. It was a singular sight which met our eyes. On the table stood a dark-lantern with the shutter half open, throwing a brilliant beam of light upon the iron safe, the door of which was ajar. Beside this table, on the wooden chair, sat Dr. Grimesby Roylott clad in a long grey dressing-gown, his bare ankles protruding beneath, and his feet thrust into red heelless Turkish slippers. Across his lap lay the short stock with the long lash which we had noticed during the day. His chin was cocked upward and his eyes were fixed in a dreadful, rigid stare at the corner of the ceiling. Round his brow he had a peculiar yellow band, with brownish speckles, which seemed to be bound tightly round his head. As we entered he made neither sound nor motion. "The band! the speckled band!" whispered Holmes. I took a step forward. In an instant his strange headgear began to move, and there reared itself from among his hair the squat diamond-shaped head and puffed neck of a loathsome serpent. "It is a swamp adder!" cried Holmes; "the deadliest snake in India. He has died within ten seconds of being bitten. Violence does, in truth, recoil upon the violent, and the schemer falls into the pit which he digs for another. Let us thrust this creature back into its den, and we can then remove Miss Stoner to some place of shelter and let the county police know what has happened." As he spoke he drew the dog-whip swiftly from the dead man's lap, and throwing the noose round the reptile's neck he drew it from its horrid perch and, carrying it at arm's length, threw it into the iron safe, which he closed upon it. Such are the true facts of the death of Dr. Grimesby Roylott, of Stoke Moran. It is not necessary that I should prolong a narrative which has already run to too great a length by telling how we broke the sad news to the terrified girl, how we conveyed her by the morning train to the care of her good aunt at Harrow, of how the slow process of official inquiry came to the conclusion that the doctor met his fate while indiscreetly playing with a dangerous pet. The little which I had yet to learn of the case was told me by Sherlock Holmes as we travelled back next day. "I had," said he, "come to an entirely erroneous conclusion which shows, my dear Watson, how dangerous it always is to reason from insufficient data. The presence of the gipsies, and the use of the word 'band,' which was used by the poor girl, no doubt, to explain the appearance which she had caught a hurried glimpse of by the light of her match, were sufficient to put me upon an entirely wrong scent. I can only claim the merit that I instantly reconsidered my position when, however, it became clear to me that whatever danger threatened an occupant of the room could not come either from the window or the door. My attention was speedily drawn, as I have already remarked to you, to this ventilator, and to the bell-rope which hung down to the bed. The discovery that this was a dummy, and that the bed was clamped to the floor, instantly gave rise to the suspicion that the rope was there as a bridge for something passing through the hole and coming to the bed. The idea of a snake instantly occurred to me, and when I coupled it with my knowledge that the doctor was furnished with a supply of creatures from India, I felt that I was probably on the right track. The idea of using a form of poison which could not possibly be discovered by any chemical test was just such a one as would occur to a clever and ruthless man who had had an Eastern training. The rapidity with which such a poison would take effect would also, from his point of view, be an advantage. It would be a sharp-eyed coroner, indeed, who could distinguish the two little dark punctures which would show where the poison fangs had done their work. Then I thought of the whistle. Of course he must recall the snake before the morning light revealed it to the victim. He had trained it, probably by the use of the milk which we saw, to return to him when summoned. He would put it through this ventilator at the hour that he thought best, with the certainty that it would crawl down the rope and land on the bed. It might or might not bite the occupant, perhaps she might escape every night for a week, but sooner or later she must fall a victim. "I had come to these conclusions before ever I had entered his room. An inspection of his chair showed me that he had been in the habit of standing on it, which of course would be necessary in order that he should reach the ventilator. The sight of the safe, the saucer of milk, and the loop of whipcord were enough to finally dispel any doubts which may have remained. The metallic clang heard by Miss Stoner was obviously caused by her stepfather hastily closing the door of his safe upon its terrible occupant. Having once made up my mind, you know the steps which I took in order to put the matter to the proof. I heard the creature hiss as I have no doubt that you did also, and I instantly lit the light and attacked it." "With the result of driving it through the ventilator." "And also with the result of causing it to turn upon its master at the other side. Some of the blows of my cane came home and roused its snakish temper, so that it flew upon the first person it saw. In this way I am no doubt indirectly responsible for Dr. Grimesby Roylott's death, and I cannot say that it is likely to weigh very heavily upon my conscience." IX. THE ADVENTURE OF THE ENGINEER'S THUMB Of all the problems which have been submitted to my friend, Mr. Sherlock Holmes, for solution during the years of our intimacy, there were only two which I was the means of introducing to his notice--that of Mr. Hatherley's thumb, and that of Colonel Warburton's madness. Of these the latter may have afforded a finer field for an acute and original observer, but the other was so strange in its inception and so dramatic in its details that it may be the more worthy of being placed upon record, even if it gave my friend fewer openings for those deductive methods of reasoning by which he achieved such remarkable results. The story has, I believe, been told more than once in the newspapers, but, like all such narratives, its effect is much less striking when set forth en bloc in a single half-column of print than when the facts slowly evolve before your own eyes, and the mystery clears gradually away as each new discovery furnishes a step which leads on to the complete truth. At the time the circumstances made a deep impression upon me, and the lapse of two years has hardly served to weaken the effect. It was in the summer of '89, not long after my marriage, that the events occurred which I am now about to summarise. I had returned to civil practice and had finally abandoned Holmes in his Baker Street rooms, although I continually visited him and occasionally even persuaded him to forgo his Bohemian habits so far as to come and visit us. My practice had steadily increased, and as I happened to live at no very great distance from Paddington Station, I got a few patients from among the officials. One of these, whom I had cured of a painful and lingering disease, was never weary of advertising my virtues and of endeavouring to send me on every sufferer over whom he might have any influence. One morning, at a little before seven o'clock, I was awakened by the maid tapping at the door to announce that two men had come from Paddington and were waiting in the consulting-room. I dressed hurriedly, for I knew by experience that railway cases were seldom trivial, and hastened downstairs. As I descended, my old ally, the guard, came out of the room and closed the door tightly behind him. "I've got him here," he whispered, jerking his thumb over his shoulder; "he's all right." "What is it, then?" I asked, for his manner suggested that it was some strange creature which he had caged up in my room. "It's a new patient," he whispered. "I thought I'd bring him round myself; then he couldn't slip away. There he is, all safe and sound. I must go now, Doctor; I have my dooties, just the same as you." And off he went, this trusty tout, without even giving me time to thank him. I entered my consulting-room and found a gentleman seated by the table. He was quietly dressed in a suit of heather tweed with a soft cloth cap which he had laid down upon my books. Round one of his hands he had a handkerchief wrapped, which was mottled all over with bloodstains. He was young, not more than five-and-twenty, I should say, with a strong, masculine face; but he was exceedingly pale and gave me the impression of a man who was suffering from some strong agitation, which it took all his strength of mind to control. "I am sorry to knock you up so early, Doctor," said he, "but I have had a very serious accident during the night. I came in by train this morning, and on inquiring at Paddington as to where I might find a doctor, a worthy fellow very kindly escorted me here. I gave the maid a card, but I see that she has left it upon the side-table." I took it up and glanced at it. "Mr. Victor Hatherley, hydraulic engineer, 16A, Victoria Street (3rd floor)." That was the name, style, and abode of my morning visitor. "I regret that I have kept you waiting," said I, sitting down in my library-chair. "You are fresh from a night journey, I understand, which is in itself a monotonous occupation." "Oh, my night could not be called monotonous," said he, and laughed. He laughed very heartily, with a high, ringing note, leaning back in his chair and shaking his sides. All my medical instincts rose up against that laugh. "Stop it!" I cried; "pull yourself together!" and I poured out some water from a caraffe. It was useless, however. He was off in one of those hysterical outbursts which come upon a strong nature when some great crisis is over and gone. Presently he came to himself once more, very weary and pale-looking. "I have been making a fool of myself," he gasped. "Not at all. Drink this." I dashed some brandy into the water, and the colour began to come back to his bloodless cheeks. "That's better!" said he. "And now, Doctor, perhaps you would kindly attend to my thumb, or rather to the place where my thumb used to be." He unwound the handkerchief and held out his hand. It gave even my hardened nerves a shudder to look at it. There were four protruding fingers and a horrid red, spongy surface where the thumb should have been. It had been hacked or torn right out from the roots. "Good heavens!" I cried, "this is a terrible injury. It must have bled considerably." "Yes, it did. I fainted when it was done, and I think that I must have been senseless for a long time. When I came to I found that it was still bleeding, so I tied one end of my handkerchief very tightly round the wrist and braced it up with a twig." "Excellent! You should have been a surgeon." "It is a question of hydraulics, you see, and came within my own province." "This has been done," said I, examining the wound, "by a very heavy and sharp instrument." "A thing like a cleaver," said he. "An accident, I presume?" "By no means." "What! a murderous attack?" "Very murderous indeed." "You horrify me." I sponged the wound, cleaned it, dressed it, and finally covered it over with cotton wadding and carbolised bandages. He lay back without wincing, though he bit his lip from time to time. "How is that?" I asked when I had finished. "Capital! Between your brandy and your bandage, I feel a new man. I was very weak, but I have had a good deal to go through." "Perhaps you had better not speak of the matter. It is evidently trying to your nerves." "Oh, no, not now. I shall have to tell my tale to the police; but, between ourselves, if it were not for the convincing evidence of this wound of mine, I should be surprised if they believed my statement, for it is a very extraordinary one, and I have not much in the way of proof with which to back it up; and, even if they believe me, the clues which I can give them are so vague that it is a question whether justice will be done." "Ha!" cried I, "if it is anything in the nature of a problem which you desire to see solved, I should strongly recommend you to come to my friend, Mr. Sherlock Holmes, before you go to the official police." "Oh, I have heard of that fellow," answered my visitor, "and I should be very glad if he would take the matter up, though of course I must use the official police as well. Would you give me an introduction to him?" "I'll do better. I'll take you round to him myself." "I should be immensely obliged to you." "We'll call a cab and go together. We shall just be in time to have a little breakfast with him. Do you feel equal to it?" "Yes; I shall not feel easy until I have told my story." "Then my servant will call a cab, and I shall be with you in an instant." I rushed upstairs, explained the matter shortly to my wife, and in five minutes was inside a hansom, driving with my new acquaintance to Baker Street. Sherlock Holmes was, as I expected, lounging about his sitting-room in his dressing-gown, reading the agony column of The Times and smoking his before-breakfast pipe, which was composed of all the plugs and dottles left from his smokes of the day before, all carefully dried and collected on the corner of the mantelpiece. He received us in his quietly genial fashion, ordered fresh rashers and eggs, and joined us in a hearty meal. When it was concluded he settled our new acquaintance upon the sofa, placed a pillow beneath his head, and laid a glass of brandy and water within his reach. "It is easy to see that your experience has been no common one, Mr. Hatherley," said he. "Pray, lie down there and make yourself absolutely at home. Tell us what you can, but stop when you are tired and keep up your strength with a little stimulant." "Thank you," said my patient, "but I have felt another man since the doctor bandaged me, and I think that your breakfast has completed the cure. I shall take up as little of your valuable time as possible, so I shall start at once upon my peculiar experiences." Holmes sat in his big armchair with the weary, heavy-lidded expression which veiled his keen and eager nature, while I sat opposite to him, and we listened in silence to the strange story which our visitor detailed to us. "You must know," said he, "that I am an orphan and a bachelor, residing alone in lodgings in London. By profession I am a hydraulic engineer, and I have had considerable experience of my work during the seven years that I was apprenticed to Venner & Matheson, the well-known firm, of Greenwich. Two years ago, having served my time, and having also come into a fair sum of money through my poor father's death, I determined to start in business for myself and took professional chambers in Victoria Street. "I suppose that everyone finds his first independent start in business a dreary experience. To me it has been exceptionally so. During two years I have had three consultations and one small job, and that is absolutely all that my profession has brought me. My gross takings amount to 27 pounds 10s. Every day, from nine in the morning until four in the afternoon, I waited in my little den, until at last my heart began to sink, and I came to believe that I should never have any practice at all. "Yesterday, however, just as I was thinking of leaving the office, my clerk entered to say there was a gentleman waiting who wished to see me upon business. He brought up a card, too, with the name of 'Colonel Lysander Stark' engraved upon it. Close at his heels came the colonel himself, a man rather over the middle size, but of an exceeding thinness. I do not think that I have ever seen so thin a man. His whole face sharpened away into nose and chin, and the skin of his cheeks was drawn quite tense over his outstanding bones. Yet this emaciation seemed to be his natural habit, and due to no disease, for his eye was bright, his step brisk, and his bearing assured. He was plainly but neatly dressed, and his age, I should judge, would be nearer forty than thirty. "'Mr. Hatherley?' said he, with something of a German accent. 'You have been recommended to me, Mr. Hatherley, as being a man who is not only proficient in his profession but is also discreet and capable of preserving a secret.' "I bowed, feeling as flattered as any young man would at such an address. 'May I ask who it was who gave me so good a character?' "'Well, perhaps it is better that I should not tell you that just at this moment. I have it from the same source that you are both an orphan and a bachelor and are residing alone in London.' "'That is quite correct,' I answered; 'but you will excuse me if I say that I cannot see how all this bears upon my professional qualifications. I understand that it was on a professional matter that you wished to speak to me?' "'Undoubtedly so. But you will find that all I say is really to the point. I have a professional commission for you, but absolute secrecy is quite essential--absolute secrecy, you understand, and of course we may expect that more from a man who is alone than from one who lives in the bosom of his family.' "'If I promise to keep a secret,' said I, 'you may absolutely depend upon my doing so.' "He looked very hard at me as I spoke, and it seemed to me that I had never seen so suspicious and questioning an eye. "'Do you promise, then?' said he at last. "'Yes, I promise.' "'Absolute and complete silence before, during, and after? No reference to the matter at all, either in word or writing?' "'I have already given you my word.' "'Very good.' He suddenly sprang up, and darting like lightning across the room he flung open the door. The passage outside was empty. "'That's all right,' said he, coming back. 'I know that clerks are sometimes curious as to their master's affairs. Now we can talk in safety.' He drew up his chair very close to mine and began to stare at me again with the same questioning and thoughtful look. "A feeling of repulsion, and of something akin to fear had begun to rise within me at the strange antics of this fleshless man. Even my dread of losing a client could not restrain me from showing my impatience. "'I beg that you will state your business, sir,' said I; 'my time is of value.' Heaven forgive me for that last sentence, but the words came to my lips. "'How would fifty guineas for a night's work suit you?' he asked. "'Most admirably.' "'I say a night's work, but an hour's would be nearer the mark. I simply want your opinion about a hydraulic stamping machine which has got out of gear. If you show us what is wrong we shall soon set it right ourselves. What do you think of such a commission as that?' "'The work appears to be light and the pay munificent.' "'Precisely so. We shall want you to come to-night by the last train.' "'Where to?' "'To Eyford, in Berkshire. It is a little place near the borders of Oxfordshire, and within seven miles of Reading. There is a train from Paddington which would bring you there at about 11:15.' "'Very good.' "'I shall come down in a carriage to meet you.' "'There is a drive, then?' "'Yes, our little place is quite out in the country. It is a good seven miles from Eyford Station.' "'Then we can hardly get there before midnight. I suppose there would be no chance of a train back. I should be compelled to stop the night.' "'Yes, we could easily give you a shake-down.' "'That is very awkward. Could I not come at some more convenient hour?' "'We have judged it best that you should come late. It is to recompense you for any inconvenience that we are paying to you, a young and unknown man, a fee which would buy an opinion from the very heads of your profession. Still, of course, if you would like to draw out of the business, there is plenty of time to do so.' "I thought of the fifty guineas, and of how very useful they would be to me. 'Not at all,' said I, 'I shall be very happy to accommodate myself to your wishes. I should like, however, to understand a little more clearly what it is that you wish me to do.' "'Quite so. It is very natural that the pledge of secrecy which we have exacted from you should have aroused your curiosity. I have no wish to commit you to anything without your having it all laid before you. I suppose that we are absolutely safe from eavesdroppers?' "'Entirely.' "'Then the matter stands thus. You are probably aware that fuller's-earth is a valuable product, and that it is only found in one or two places in England?' "'I have heard so.' "'Some little time ago I bought a small place--a very small place--within ten miles of Reading. I was fortunate enough to discover that there was a deposit of fuller's-earth in one of my fields. On examining it, however, I found that this deposit was a comparatively small one, and that it formed a link between two very much larger ones upon the right and left--both of them, however, in the grounds of my neighbours. These good people were absolutely ignorant that their land contained that which was quite as valuable as a gold-mine. Naturally, it was to my interest to buy their land before they discovered its true value, but unfortunately I had no capital by which I could do this. I took a few of my friends into the secret, however, and they suggested that we should quietly and secretly work our own little deposit and that in this way we should earn the money which would enable us to buy the neighbouring fields. This we have now been doing for some time, and in order to help us in our operations we erected a hydraulic press. This press, as I have already explained, has got out of order, and we wish your advice upon the subject. We guard our secret very jealously, however, and if it once became known that we had hydraulic engineers coming to our little house, it would soon rouse inquiry, and then, if the facts came out, it would be good-bye to any chance of getting these fields and carrying out our plans. That is why I have made you promise me that you will not tell a human being that you are going to Eyford to-night. I hope that I make it all plain?' "'I quite follow you,' said I. 'The only point which I could not quite understand was what use you could make of a hydraulic press in excavating fuller's-earth, which, as I understand, is dug out like gravel from a pit.' "'Ah!' said he carelessly, 'we have our own process. We compress the earth into bricks, so as to remove them without revealing what they are. But that is a mere detail. I have taken you fully into my confidence now, Mr. Hatherley, and I have shown you how I trust you.' He rose as he spoke. 'I shall expect you, then, at Eyford at 11:15.' "'I shall certainly be there.' "'And not a word to a soul.' He looked at me with a last long, questioning gaze, and then, pressing my hand in a cold, dank grasp, he hurried from the room. "Well, when I came to think it all over in cool blood I was very much astonished, as you may both think, at this sudden commission which had been intrusted to me. On the one hand, of course, I was glad, for the fee was at least tenfold what I should have asked had I set a price upon my own services, and it was possible that this order might lead to other ones. On the other hand, the face and manner of my patron had made an unpleasant impression upon me, and I could not think that his explanation of the fuller's-earth was sufficient to explain the necessity for my coming at midnight, and his extreme anxiety lest I should tell anyone of my errand. However, I threw all fears to the winds, ate a hearty supper, drove to Paddington, and started off, having obeyed to the letter the injunction as to holding my tongue. "At Reading I had to change not only my carriage but my station. However, I was in time for the last train to Eyford, and I reached the little dim-lit station after eleven o'clock. I was the only passenger who got out there, and there was no one upon the platform save a single sleepy porter with a lantern. As I passed out through the wicket gate, however, I found my acquaintance of the morning waiting in the shadow upon the other side. Without a word he grasped my arm and hurried me into a carriage, the door of which was standing open. He drew up the windows on either side, tapped on the wood-work, and away we went as fast as the horse could go." "One horse?" interjected Holmes. "Yes, only one." "Did you observe the colour?" "Yes, I saw it by the side-lights when I was stepping into the carriage. It was a chestnut." "Tired-looking or fresh?" "Oh, fresh and glossy." "Thank you. I am sorry to have interrupted you. Pray continue your most interesting statement." "Away we went then, and we drove for at least an hour. Colonel Lysander Stark had said that it was only seven miles, but I should think, from the rate that we seemed to go, and from the time that we took, that it must have been nearer twelve. He sat at my side in silence all the time, and I was aware, more than once when I glanced in his direction, that he was looking at me with great intensity. The country roads seem to be not very good in that part of the world, for we lurched and jolted terribly. I tried to look out of the windows to see something of where we were, but they were made of frosted glass, and I could make out nothing save the occasional bright blur of a passing light. Now and then I hazarded some remark to break the monotony of the journey, but the colonel answered only in monosyllables, and the conversation soon flagged. At last, however, the bumping of the road was exchanged for the crisp smoothness of a gravel-drive, and the carriage came to a stand. Colonel Lysander Stark sprang out, and, as I followed after him, pulled me swiftly into a porch which gaped in front of us. We stepped, as it were, right out of the carriage and into the hall, so that I failed to catch the most fleeting glance of the front of the house. The instant that I had crossed the threshold the door slammed heavily behind us, and I heard faintly the rattle of the wheels as the carriage drove away. "It was pitch dark inside the house, and the colonel fumbled about looking for matches and muttering under his breath. Suddenly a door opened at the other end of the passage, and a long, golden bar of light shot out in our direction. It grew broader, and a woman appeared with a lamp in her hand, which she held above her head, pushing her face forward and peering at us. I could see that she was pretty, and from the gloss with which the light shone upon her dark dress I knew that it was a rich material. She spoke a few words in a foreign tongue in a tone as though asking a question, and when my companion answered in a gruff monosyllable she gave such a start that the lamp nearly fell from her hand. Colonel Stark went up to her, whispered something in her ear, and then, pushing her back into the room from whence she had come, he walked towards me again with the lamp in his hand. "'Perhaps you will have the kindness to wait in this room for a few minutes,' said he, throwing open another door. It was a quiet, little, plainly furnished room, with a round table in the centre, on which several German books were scattered. Colonel Stark laid down the lamp on the top of a harmonium beside the door. 'I shall not keep you waiting an instant,' said he, and vanished into the darkness. "I glanced at the books upon the table, and in spite of my ignorance of German I could see that two of them were treatises on science, the others being volumes of poetry. Then I walked across to the window, hoping that I might catch some glimpse of the country-side, but an oak shutter, heavily barred, was folded across it. It was a wonderfully silent house. There was an old clock ticking loudly somewhere in the passage, but otherwise everything was deadly still. A vague feeling of uneasiness began to steal over me. Who were these German people, and what were they doing living in this strange, out-of-the-way place? And where was the place? I was ten miles or so from Eyford, that was all I knew, but whether north, south, east, or west I had no idea. For that matter, Reading, and possibly other large towns, were within that radius, so the place might not be so secluded, after all. Yet it was quite certain, from the absolute stillness, that we were in the country. I paced up and down the room, humming a tune under my breath to keep up my spirits and feeling that I was thoroughly earning my fifty-guinea fee. "Suddenly, without any preliminary sound in the midst of the utter stillness, the door of my room swung slowly open. The woman was standing in the aperture, the darkness of the hall behind her, the yellow light from my lamp beating upon her eager and beautiful face. I could see at a glance that she was sick with fear, and the sight sent a chill to my own heart. She held up one shaking finger to warn me to be silent, and she shot a few whispered words of broken English at me, her eyes glancing back, like those of a frightened horse, into the gloom behind her. "'I would go,' said she, trying hard, as it seemed to me, to speak calmly; 'I would go. I should not stay here. There is no good for you to do.' "'But, madam,' said I, 'I have not yet done what I came for. I cannot possibly leave until I have seen the machine.' "'It is not worth your while to wait,' she went on. 'You can pass through the door; no one hinders.' And then, seeing that I smiled and shook my head, she suddenly threw aside her constraint and made a step forward, with her hands wrung together. 'For the love of Heaven!' she whispered, 'get away from here before it is too late!' "But I am somewhat headstrong by nature, and the more ready to engage in an affair when there is some obstacle in the way. I thought of my fifty-guinea fee, of my wearisome journey, and of the unpleasant night which seemed to be before me. Was it all to go for nothing? Why should I slink away without having carried out my commission, and without the payment which was my due? This woman might, for all I knew, be a monomaniac. With a stout bearing, therefore, though her manner had shaken me more than I cared to confess, I still shook my head and declared my intention of remaining where I was. She was about to renew her entreaties when a door slammed overhead, and the sound of several footsteps was heard upon the stairs. She listened for an instant, threw up her hands with a despairing gesture, and vanished as suddenly and as noiselessly as she had come. "The newcomers were Colonel Lysander Stark and a short thick man with a chinchilla beard growing out of the creases of his double chin, who was introduced to me as Mr. Ferguson. "'This is my secretary and manager,' said the colonel. 'By the way, I was under the impression that I left this door shut just now. I fear that you have felt the draught.' "'On the contrary,' said I, 'I opened the door myself because I felt the room to be a little close.' "He shot one of his suspicious looks at me. 'Perhaps we had better proceed to business, then,' said he. 'Mr. Ferguson and I will take you up to see the machine.' "'I had better put my hat on, I suppose.' "'Oh, no, it is in the house.' "'What, you dig fuller's-earth in the house?' "'No, no. This is only where we compress it. But never mind that. All we wish you to do is to examine the machine and to let us know what is wrong with it.' "We went upstairs together, the colonel first with the lamp, the fat manager and I behind him. It was a labyrinth of an old house, with corridors, passages, narrow winding staircases, and little low doors, the thresholds of which were hollowed out by the generations who had crossed them. There were no carpets and no signs of any furniture above the ground floor, while the plaster was peeling off the walls, and the damp was breaking through in green, unhealthy blotches. I tried to put on as unconcerned an air as possible, but I had not forgotten the warnings of the lady, even though I disregarded them, and I kept a keen eye upon my two companions. Ferguson appeared to be a morose and silent man, but I could see from the little that he said that he was at least a fellow-countryman. "Colonel Lysander Stark stopped at last before a low door, which he unlocked. Within was a small, square room, in which the three of us could hardly get at one time. Ferguson remained outside, and the colonel ushered me in. "'We are now,' said he, 'actually within the hydraulic press, and it would be a particularly unpleasant thing for us if anyone were to turn it on. The ceiling of this small chamber is really the end of the descending piston, and it comes down with the force of many tons upon this metal floor. There are small lateral columns of water outside which receive the force, and which transmit and multiply it in the manner which is familiar to you. The machine goes readily enough, but there is some stiffness in the working of it, and it has lost a little of its force. Perhaps you will have the goodness to look it over and to show us how we can set it right.' "I took the lamp from him, and I examined the machine very thoroughly. It was indeed a gigantic one, and capable of exercising enormous pressure. When I passed outside, however, and pressed down the levers which controlled it, I knew at once by the whishing sound that there was a slight leakage, which allowed a regurgitation of water through one of the side cylinders. An examination showed that one of the india-rubber bands which was round the head of a driving-rod had shrunk so as not quite to fill the socket along which it worked. This was clearly the cause of the loss of power, and I pointed it out to my companions, who followed my remarks very carefully and asked several practical questions as to how they should proceed to set it right. When I had made it clear to them, I returned to the main chamber of the machine and took a good look at it to satisfy my own curiosity. It was obvious at a glance that the story of the fuller's-earth was the merest fabrication, for it would be absurd to suppose that so powerful an engine could be designed for so inadequate a purpose. The walls were of wood, but the floor consisted of a large iron trough, and when I came to examine it I could see a crust of metallic deposit all over it. I had stooped and was scraping at this to see exactly what it was when I heard a muttered exclamation in German and saw the cadaverous face of the colonel looking down at me. "'What are you doing there?' he asked. "I felt angry at having been tricked by so elaborate a story as that which he had told me. 'I was admiring your fuller's-earth,' said I; 'I think that I should be better able to advise you as to your machine if I knew what the exact purpose was for which it was used.' "The instant that I uttered the words I regretted the rashness of my speech. His face set hard, and a baleful light sprang up in his grey eyes. "'Very well,' said he, 'you shall know all about the machine.' He took a step backward, slammed the little door, and turned the key in the lock. I rushed towards it and pulled at the handle, but it was quite secure, and did not give in the least to my kicks and shoves. 'Hullo!' I yelled. 'Hullo! Colonel! Let me out!' "And then suddenly in the silence I heard a sound which sent my heart into my mouth. It was the clank of the levers and the swish of the leaking cylinder. He had set the engine at work. The lamp still stood upon the floor where I had placed it when examining the trough. By its light I saw that the black ceiling was coming down upon me, slowly, jerkily, but, as none knew better than myself, with a force which must within a minute grind me to a shapeless pulp. I threw myself, screaming, against the door, and dragged with my nails at the lock. I implored the colonel to let me out, but the remorseless clanking of the levers drowned my cries. The ceiling was only a foot or two above my head, and with my hand upraised I could feel its hard, rough surface. Then it flashed through my mind that the pain of my death would depend very much upon the position in which I met it. If I lay on my face the weight would come upon my spine, and I shuddered to think of that dreadful snap. Easier the other way, perhaps; and yet, had I the nerve to lie and look up at that deadly black shadow wavering down upon me? Already I was unable to stand erect, when my eye caught something which brought a gush of hope back to my heart. "I have said that though the floor and ceiling were of iron, the walls were of wood. As I gave a last hurried glance around, I saw a thin line of yellow light between two of the boards, which broadened and broadened as a small panel was pushed backward. For an instant I could hardly believe that here was indeed a door which led away from death. The next instant I threw myself through, and lay half-fainting upon the other side. The panel had closed again behind me, but the crash of the lamp, and a few moments afterwards the clang of the two slabs of metal, told me how narrow had been my escape. "I was recalled to myself by a frantic plucking at my wrist, and I found myself lying upon the stone floor of a narrow corridor, while a woman bent over me and tugged at me with her left hand, while she held a candle in her right. It was the same good friend whose warning I had so foolishly rejected. "'Come! come!' she cried breathlessly. 'They will be here in a moment. They will see that you are not there. Oh, do not waste the so-precious time, but come!' "This time, at least, I did not scorn her advice. I staggered to my feet and ran with her along the corridor and down a winding stair. The latter led to another broad passage, and just as we reached it we heard the sound of running feet and the shouting of two voices, one answering the other from the floor on which we were and from the one beneath. My guide stopped and looked about her like one who is at her wit's end. Then she threw open a door which led into a bedroom, through the window of which the moon was shining brightly. "'It is your only chance,' said she. 'It is high, but it may be that you can jump it.' "As she spoke a light sprang into view at the further end of the passage, and I saw the lean figure of Colonel Lysander Stark rushing forward with a lantern in one hand and a weapon like a butcher's cleaver in the other. I rushed across the bedroom, flung open the window, and looked out. How quiet and sweet and wholesome the garden looked in the moonlight, and it could not be more than thirty feet down. I clambered out upon the sill, but I hesitated to jump until I should have heard what passed between my saviour and the ruffian who pursued me. If she were ill-used, then at any risks I was determined to go back to her assistance. The thought had hardly flashed through my mind before he was at the door, pushing his way past her; but she threw her arms round him and tried to hold him back. "'Fritz! Fritz!' she cried in English, 'remember your promise after the last time. You said it should not be again. He will be silent! Oh, he will be silent!' "'You are mad, Elise!' he shouted, struggling to break away from her. 'You will be the ruin of us. He has seen too much. Let me pass, I say!' He dashed her to one side, and, rushing to the window, cut at me with his heavy weapon. I had let myself go, and was hanging by the hands to the sill, when his blow fell. I was conscious of a dull pain, my grip loosened, and I fell into the garden below. "I was shaken but not hurt by the fall; so I picked myself up and rushed off among the bushes as hard as I could run, for I understood that I was far from being out of danger yet. Suddenly, however, as I ran, a deadly dizziness and sickness came over me. I glanced down at my hand, which was throbbing painfully, and then, for the first time, saw that my thumb had been cut off and that the blood was pouring from my wound. I endeavoured to tie my handkerchief round it, but there came a sudden buzzing in my ears, and next moment I fell in a dead faint among the rose-bushes. "How long I remained unconscious I cannot tell. It must have been a very long time, for the moon had sunk, and a bright morning was breaking when I came to myself. My clothes were all sodden with dew, and my coat-sleeve was drenched with blood from my wounded thumb. The smarting of it recalled in an instant all the particulars of my night's adventure, and I sprang to my feet with the feeling that I might hardly yet be safe from my pursuers. But to my astonishment, when I came to look round me, neither house nor garden were to be seen. I had been lying in an angle of the hedge close by the highroad, and just a little lower down was a long building, which proved, upon my approaching it, to be the very station at which I had arrived upon the previous night. Were it not for the ugly wound upon my hand, all that had passed during those dreadful hours might have been an evil dream. "Half dazed, I went into the station and asked about the morning train. There would be one to Reading in less than an hour. The same porter was on duty, I found, as had been there when I arrived. I inquired of him whether he had ever heard of Colonel Lysander Stark. The name was strange to him. Had he observed a carriage the night before waiting for me? No, he had not. Was there a police-station anywhere near? There was one about three miles off. "It was too far for me to go, weak and ill as I was. I determined to wait until I got back to town before telling my story to the police. It was a little past six when I arrived, so I went first to have my wound dressed, and then the doctor was kind enough to bring me along here. I put the case into your hands and shall do exactly what you advise." We both sat in silence for some little time after listening to this extraordinary narrative. Then Sherlock Holmes pulled down from the shelf one of the ponderous commonplace books in which he placed his cuttings. "Here is an advertisement which will interest you," said he. "It appeared in all the papers about a year ago. Listen to this: 'Lost, on the 9th inst., Mr. Jeremiah Hayling, aged twenty-six, a hydraulic engineer. Left his lodgings at ten o'clock at night, and has not been heard of since. Was dressed in,' etc., etc. Ha! That represents the last time that the colonel needed to have his machine overhauled, I fancy." "Good heavens!" cried my patient. "Then that explains what the girl said." "Undoubtedly. It is quite clear that the colonel was a cool and desperate man, who was absolutely determined that nothing should stand in the way of his little game, like those out-and-out pirates who will leave no survivor from a captured ship. Well, every moment now is precious, so if you feel equal to it we shall go down to Scotland Yard at once as a preliminary to starting for Eyford." Some three hours or so afterwards we were all in the train together, bound from Reading to the little Berkshire village. There were Sherlock Holmes, the hydraulic engineer, Inspector Bradstreet, of Scotland Yard, a plain-clothes man, and myself. Bradstreet had spread an ordnance map of the county out upon the seat and was busy with his compasses drawing a circle with Eyford for its centre. "There you are," said he. "That circle is drawn at a radius of ten miles from the village. The place we want must be somewhere near that line. You said ten miles, I think, sir." "It was an hour's good drive." "And you think that they brought you back all that way when you were unconscious?" "They must have done so. I have a confused memory, too, of having been lifted and conveyed somewhere." "What I cannot understand," said I, "is why they should have spared you when they found you lying fainting in the garden. Perhaps the villain was softened by the woman's entreaties." "I hardly think that likely. I never saw a more inexorable face in my life." "Oh, we shall soon clear up all that," said Bradstreet. "Well, I have drawn my circle, and I only wish I knew at what point upon it the folk that we are in search of are to be found." "I think I could lay my finger on it," said Holmes quietly. "Really, now!" cried the inspector, "you have formed your opinion! Come, now, we shall see who agrees with you. I say it is south, for the country is more deserted there." "And I say east," said my patient. "I am for west," remarked the plain-clothes man. "There are several quiet little villages up there." "And I am for north," said I, "because there are no hills there, and our friend says that he did not notice the carriage go up any." "Come," cried the inspector, laughing; "it's a very pretty diversity of opinion. We have boxed the compass among us. Who do you give your casting vote to?" "You are all wrong." "But we can't all be." "Oh, yes, you can. This is my point." He placed his finger in the centre of the circle. "This is where we shall find them." "But the twelve-mile drive?" gasped Hatherley. "Six out and six back. Nothing simpler. You say yourself that the horse was fresh and glossy when you got in. How could it be that if it had gone twelve miles over heavy roads?" "Indeed, it is a likely ruse enough," observed Bradstreet thoughtfully. "Of course there can be no doubt as to the nature of this gang." "None at all," said Holmes. "They are coiners on a large scale, and have used the machine to form the amalgam which has taken the place of silver." "We have known for some time that a clever gang was at work," said the inspector. "They have been turning out half-crowns by the thousand. We even traced them as far as Reading, but could get no farther, for they had covered their traces in a way that showed that they were very old hands. But now, thanks to this lucky chance, I think that we have got them right enough." But the inspector was mistaken, for those criminals were not destined to fall into the hands of justice. As we rolled into Eyford Station we saw a gigantic column of smoke which streamed up from behind a small clump of trees in the neighbourhood and hung like an immense ostrich feather over the landscape. "A house on fire?" asked Bradstreet as the train steamed off again on its way. "Yes, sir!" said the station-master. "When did it break out?" "I hear that it was during the night, sir, but it has got worse, and the whole place is in a blaze." "Whose house is it?" "Dr. Becher's." "Tell me," broke in the engineer, "is Dr. Becher a German, very thin, with a long, sharp nose?" The station-master laughed heartily. "No, sir, Dr. Becher is an Englishman, and there isn't a man in the parish who has a better-lined waistcoat. But he has a gentleman staying with him, a patient, as I understand, who is a foreigner, and he looks as if a little good Berkshire beef would do him no harm." The station-master had not finished his speech before we were all hastening in the direction of the fire. The road topped a low hill, and there was a great widespread whitewashed building in front of us, spouting fire at every chink and window, while in the garden in front three fire-engines were vainly striving to keep the flames under. "That's it!" cried Hatherley, in intense excitement. "There is the gravel-drive, and there are the rose-bushes where I lay. That second window is the one that I jumped from." "Well, at least," said Holmes, "you have had your revenge upon them. There can be no question that it was your oil-lamp which, when it was crushed in the press, set fire to the wooden walls, though no doubt they were too excited in the chase after you to observe it at the time. Now keep your eyes open in this crowd for your friends of last night, though I very much fear that they are a good hundred miles off by now." And Holmes' fears came to be realised, for from that day to this no word has ever been heard either of the beautiful woman, the sinister German, or the morose Englishman. Early that morning a peasant had met a cart containing several people and some very bulky boxes driving rapidly in the direction of Reading, but there all traces of the fugitives disappeared, and even Holmes' ingenuity failed ever to discover the least clue as to their whereabouts. The firemen had been much perturbed at the strange arrangements which they had found within, and still more so by discovering a newly severed human thumb upon a window-sill of the second floor. About sunset, however, their efforts were at last successful, and they subdued the flames, but not before the roof had fallen in, and the whole place been reduced to such absolute ruin that, save some twisted cylinders and iron piping, not a trace remained of the machinery which had cost our unfortunate acquaintance so dearly. Large masses of nickel and of tin were discovered stored in an out-house, but no coins were to be found, which may have explained the presence of those bulky boxes which have been already referred to. How our hydraulic engineer had been conveyed from the garden to the spot where he recovered his senses might have remained forever a mystery were it not for the soft mould, which told us a very plain tale. He had evidently been carried down by two persons, one of whom had remarkably small feet and the other unusually large ones. On the whole, it was most probable that the silent Englishman, being less bold or less murderous than his companion, had assisted the woman to bear the unconscious man out of the way of danger. "Well," said our engineer ruefully as we took our seats to return once more to London, "it has been a pretty business for me! I have lost my thumb and I have lost a fifty-guinea fee, and what have I gained?" "Experience," said Holmes, laughing. "Indirectly it may be of value, you know; you have only to put it into words to gain the reputation of being excellent company for the remainder of your existence." X. THE ADVENTURE OF THE NOBLE BACHELOR The Lord St. Simon marriage, and its curious termination, have long ceased to be a subject of interest in those exalted circles in which the unfortunate bridegroom moves. Fresh scandals have eclipsed it, and their more piquant details have drawn the gossips away from this four-year-old drama. As I have reason to believe, however, that the full facts have never been revealed to the general public, and as my friend Sherlock Holmes had a considerable share in clearing the matter up, I feel that no memoir of him would be complete without some little sketch of this remarkable episode. It was a few weeks before my own marriage, during the days when I was still sharing rooms with Holmes in Baker Street, that he came home from an afternoon stroll to find a letter on the table waiting for him. I had remained indoors all day, for the weather had taken a sudden turn to rain, with high autumnal winds, and the Jezail bullet which I had brought back in one of my limbs as a relic of my Afghan campaign throbbed with dull persistence. With my body in one easy-chair and my legs upon another, I had surrounded myself with a cloud of newspapers until at last, saturated with the news of the day, I tossed them all aside and lay listless, watching the huge crest and monogram upon the envelope upon the table and wondering lazily who my friend's noble correspondent could be. "Here is a very fashionable epistle," I remarked as he entered. "Your morning letters, if I remember right, were from a fish-monger and a tide-waiter." "Yes, my correspondence has certainly the charm of variety," he answered, smiling, "and the humbler are usually the more interesting. This looks like one of those unwelcome social summonses which call upon a man either to be bored or to lie." He broke the seal and glanced over the contents. "Oh, come, it may prove to be something of interest, after all." "Not social, then?" "No, distinctly professional." "And from a noble client?" "One of the highest in England." "My dear fellow, I congratulate you." "I assure you, Watson, without affectation, that the status of my client is a matter of less moment to me than the interest of his case. It is just possible, however, that that also may not be wanting in this new investigation. You have been reading the papers diligently of late, have you not?" "It looks like it," said I ruefully, pointing to a huge bundle in the corner. "I have had nothing else to do." "It is fortunate, for you will perhaps be able to post me up. I read nothing except the criminal news and the agony column. The latter is always instructive. But if you have followed recent events so closely you must have read about Lord St. Simon and his wedding?" "Oh, yes, with the deepest interest." "That is well. The letter which I hold in my hand is from Lord St. Simon. I will read it to you, and in return you must turn over these papers and let me have whatever bears upon the matter. This is what he says: "'MY DEAR MR. SHERLOCK HOLMES:--Lord Backwater tells me that I may place implicit reliance upon your judgment and discretion. I have determined, therefore, to call upon you and to consult you in reference to the very painful event which has occurred in connection with my wedding. Mr. Lestrade, of Scotland Yard, is acting already in the matter, but he assures me that he sees no objection to your co-operation, and that he even thinks that it might be of some assistance. I will call at four o'clock in the afternoon, and, should you have any other engagement at that time, I hope that you will postpone it, as this matter is of paramount importance. Yours faithfully, ST. SIMON.' "It is dated from Grosvenor Mansions, written with a quill pen, and the noble lord has had the misfortune to get a smear of ink upon the outer side of his right little finger," remarked Holmes as he folded up the epistle. "He says four o'clock. It is three now. He will be here in an hour." "Then I have just time, with your assistance, to get clear upon the subject. Turn over those papers and arrange the extracts in their order of time, while I take a glance as to who our client is." He picked a red-covered volume from a line of books of reference beside the mantelpiece. "Here he is," said he, sitting down and flattening it out upon his knee. "'Lord Robert Walsingham de Vere St. Simon, second son of the Duke of Balmoral.' Hum! 'Arms: Azure, three caltrops in chief over a fess sable. Born in 1846.' He's forty-one years of age, which is mature for marriage. Was Under-Secretary for the colonies in a late administration. The Duke, his father, was at one time Secretary for Foreign Affairs. They inherit Plantagenet blood by direct descent, and Tudor on the distaff side. Ha! Well, there is nothing very instructive in all this. I think that I must turn to you Watson, for something more solid." "I have very little difficulty in finding what I want," said I, "for the facts are quite recent, and the matter struck me as remarkable. I feared to refer them to you, however, as I knew that you had an inquiry on hand and that you disliked the intrusion of other matters." "Oh, you mean the little problem of the Grosvenor Square furniture van. That is quite cleared up now--though, indeed, it was obvious from the first. Pray give me the results of your newspaper selections." "Here is the first notice which I can find. It is in the personal column of the Morning Post, and dates, as you see, some weeks back: 'A marriage has been arranged,' it says, 'and will, if rumour is correct, very shortly take place, between Lord Robert St. Simon, second son of the Duke of Balmoral, and Miss Hatty Doran, the only daughter of Aloysius Doran. Esq., of San Francisco, Cal., U.S.A.' That is all." "Terse and to the point," remarked Holmes, stretching his long, thin legs towards the fire. "There was a paragraph amplifying this in one of the society papers of the same week. Ah, here it is: 'There will soon be a call for protection in the marriage market, for the present free-trade principle appears to tell heavily against our home product. One by one the management of the noble houses of Great Britain is passing into the hands of our fair cousins from across the Atlantic. An important addition has been made during the last week to the list of the prizes which have been borne away by these charming invaders. Lord St. Simon, who has shown himself for over twenty years proof against the little god's arrows, has now definitely announced his approaching marriage with Miss Hatty Doran, the fascinating daughter of a California millionaire. Miss Doran, whose graceful figure and striking face attracted much attention at the Westbury House festivities, is an only child, and it is currently reported that her dowry will run to considerably over the six figures, with expectancies for the future. As it is an open secret that the Duke of Balmoral has been compelled to sell his pictures within the last few years, and as Lord St. Simon has no property of his own save the small estate of Birchmoor, it is obvious that the Californian heiress is not the only gainer by an alliance which will enable her to make the easy and common transition from a Republican lady to a British peeress.'" "Anything else?" asked Holmes, yawning. "Oh, yes; plenty. Then there is another note in the Morning Post to say that the marriage would be an absolutely quiet one, that it would be at St. George's, Hanover Square, that only half a dozen intimate friends would be invited, and that the party would return to the furnished house at Lancaster Gate which has been taken by Mr. Aloysius Doran. Two days later--that is, on Wednesday last--there is a curt announcement that the wedding had taken place, and that the honeymoon would be passed at Lord Backwater's place, near Petersfield. Those are all the notices which appeared before the disappearance of the bride." "Before the what?" asked Holmes with a start. "The vanishing of the lady." "When did she vanish, then?" "At the wedding breakfast." "Indeed. This is more interesting than it promised to be; quite dramatic, in fact." "Yes; it struck me as being a little out of the common." "They often vanish before the ceremony, and occasionally during the honeymoon; but I cannot call to mind anything quite so prompt as this. Pray let me have the details." "I warn you that they are very incomplete." "Perhaps we may make them less so." "Such as they are, they are set forth in a single article of a morning paper of yesterday, which I will read to you. It is headed, 'Singular Occurrence at a Fashionable Wedding': "'The family of Lord Robert St. Simon has been thrown into the greatest consternation by the strange and painful episodes which have taken place in connection with his wedding. The ceremony, as shortly announced in the papers of yesterday, occurred on the previous morning; but it is only now that it has been possible to confirm the strange rumours which have been so persistently floating about. In spite of the attempts of the friends to hush the matter up, so much public attention has now been drawn to it that no good purpose can be served by affecting to disregard what is a common subject for conversation. "'The ceremony, which was performed at St. George's, Hanover Square, was a very quiet one, no one being present save the father of the bride, Mr. Aloysius Doran, the Duchess of Balmoral, Lord Backwater, Lord Eustace and Lady Clara St. Simon (the younger brother and sister of the bridegroom), and Lady Alicia Whittington. The whole party proceeded afterwards to the house of Mr. Aloysius Doran, at Lancaster Gate, where breakfast had been prepared. It appears that some little trouble was caused by a woman, whose name has not been ascertained, who endeavoured to force her way into the house after the bridal party, alleging that she had some claim upon Lord St. Simon. It was only after a painful and prolonged scene that she was ejected by the butler and the footman. The bride, who had fortunately entered the house before this unpleasant interruption, had sat down to breakfast with the rest, when she complained of a sudden indisposition and retired to her room. Her prolonged absence having caused some comment, her father followed her, but learned from her maid that she had only come up to her chamber for an instant, caught up an ulster and bonnet, and hurried down to the passage. One of the footmen declared that he had seen a lady leave the house thus apparelled, but had refused to credit that it was his mistress, believing her to be with the company. On ascertaining that his daughter had disappeared, Mr. Aloysius Doran, in conjunction with the bridegroom, instantly put themselves in communication with the police, and very energetic inquiries are being made, which will probably result in a speedy clearing up of this very singular business. Up to a late hour last night, however, nothing had transpired as to the whereabouts of the missing lady. There are rumours of foul play in the matter, and it is said that the police have caused the arrest of the woman who had caused the original disturbance, in the belief that, from jealousy or some other motive, she may have been concerned in the strange disappearance of the bride.'" "And is that all?" "Only one little item in another of the morning papers, but it is a suggestive one." "And it is--" "That Miss Flora Millar, the lady who had caused the disturbance, has actually been arrested. It appears that she was formerly a danseuse at the Allegro, and that she has known the bridegroom for some years. There are no further particulars, and the whole case is in your hands now--so far as it has been set forth in the public press." "And an exceedingly interesting case it appears to be. I would not have missed it for worlds. But there is a ring at the bell, Watson, and as the clock makes it a few minutes after four, I have no doubt that this will prove to be our noble client. Do not dream of going, Watson, for I very much prefer having a witness, if only as a check to my own memory." "Lord Robert St. Simon," announced our page-boy, throwing open the door. A gentleman entered, with a pleasant, cultured face, high-nosed and pale, with something perhaps of petulance about the mouth, and with the steady, well-opened eye of a man whose pleasant lot it had ever been to command and to be obeyed. His manner was brisk, and yet his general appearance gave an undue impression of age, for he had a slight forward stoop and a little bend of the knees as he walked. His hair, too, as he swept off his very curly-brimmed hat, was grizzled round the edges and thin upon the top. As to his dress, it was careful to the verge of foppishness, with high collar, black frock-coat, white waistcoat, yellow gloves, patent-leather shoes, and light-coloured gaiters. He advanced slowly into the room, turning his head from left to right, and swinging in his right hand the cord which held his golden eyeglasses. "Good-day, Lord St. Simon," said Holmes, rising and bowing. "Pray take the basket-chair. This is my friend and colleague, Dr. Watson. Draw up a little to the fire, and we will talk this matter over." "A most painful matter to me, as you can most readily imagine, Mr. Holmes. I have been cut to the quick. I understand that you have already managed several delicate cases of this sort, sir, though I presume that they were hardly from the same class of society." "No, I am descending." "I beg pardon." "My last client of the sort was a king." "Oh, really! I had no idea. And which king?" "The King of Scandinavia." "What! Had he lost his wife?" "You can understand," said Holmes suavely, "that I extend to the affairs of my other clients the same secrecy which I promise to you in yours." "Of course! Very right! very right! I'm sure I beg pardon. As to my own case, I am ready to give you any information which may assist you in forming an opinion." "Thank you. I have already learned all that is in the public prints, nothing more. I presume that I may take it as correct--this article, for example, as to the disappearance of the bride." Lord St. Simon glanced over it. "Yes, it is correct, as far as it goes." "But it needs a great deal of supplementing before anyone could offer an opinion. I think that I may arrive at my facts most directly by questioning you." "Pray do so." "When did you first meet Miss Hatty Doran?" "In San Francisco, a year ago." "You were travelling in the States?" "Yes." "Did you become engaged then?" "No." "But you were on a friendly footing?" "I was amused by her society, and she could see that I was amused." "Her father is very rich?" "He is said to be the richest man on the Pacific slope." "And how did he make his money?" "In mining. He had nothing a few years ago. Then he struck gold, invested it, and came up by leaps and bounds." "Now, what is your own impression as to the young lady's--your wife's character?" The nobleman swung his glasses a little faster and stared down into the fire. "You see, Mr. Holmes," said he, "my wife was twenty before her father became a rich man. During that time she ran free in a mining camp and wandered through woods or mountains, so that her education has come from Nature rather than from the schoolmaster. She is what we call in England a tomboy, with a strong nature, wild and free, unfettered by any sort of traditions. She is impetuous--volcanic, I was about to say. She is swift in making up her mind and fearless in carrying out her resolutions. On the other hand, I would not have given her the name which I have the honour to bear"--he gave a little stately cough--"had not I thought her to be at bottom a noble woman. I believe that she is capable of heroic self-sacrifice and that anything dishonourable would be repugnant to her." "Have you her photograph?" "I brought this with me." He opened a locket and showed us the full face of a very lovely woman. It was not a photograph but an ivory miniature, and the artist had brought out the full effect of the lustrous black hair, the large dark eyes, and the exquisite mouth. Holmes gazed long and earnestly at it. Then he closed the locket and handed it back to Lord St. Simon. "The young lady came to London, then, and you renewed your acquaintance?" "Yes, her father brought her over for this last London season. I met her several times, became engaged to her, and have now married her." "She brought, I understand, a considerable dowry?" "A fair dowry. Not more than is usual in my family." "And this, of course, remains to you, since the marriage is a fait accompli?" "I really have made no inquiries on the subject." "Very naturally not. Did you see Miss Doran on the day before the wedding?" "Yes." "Was she in good spirits?" "Never better. She kept talking of what we should do in our future lives." "Indeed! That is very interesting. And on the morning of the wedding?" "She was as bright as possible--at least until after the ceremony." "And did you observe any change in her then?" "Well, to tell the truth, I saw then the first signs that I had ever seen that her temper was just a little sharp. The incident however, was too trivial to relate and can have no possible bearing upon the case." "Pray let us have it, for all that." "Oh, it is childish. She dropped her bouquet as we went towards the vestry. She was passing the front pew at the time, and it fell over into the pew. There was a moment's delay, but the gentleman in the pew handed it up to her again, and it did not appear to be the worse for the fall. Yet when I spoke to her of the matter, she answered me abruptly; and in the carriage, on our way home, she seemed absurdly agitated over this trifling cause." "Indeed! You say that there was a gentleman in the pew. Some of the general public were present, then?" "Oh, yes. It is impossible to exclude them when the church is open." "This gentleman was not one of your wife's friends?" "No, no; I call him a gentleman by courtesy, but he was quite a common-looking person. I hardly noticed his appearance. But really I think that we are wandering rather far from the point." "Lady St. Simon, then, returned from the wedding in a less cheerful frame of mind than she had gone to it. What did she do on re-entering her father's house?" "I saw her in conversation with her maid." "And who is her maid?" "Alice is her name. She is an American and came from California with her." "A confidential servant?" "A little too much so. It seemed to me that her mistress allowed her to take great liberties. Still, of course, in America they look upon these things in a different way." "How long did she speak to this Alice?" "Oh, a few minutes. I had something else to think of." "You did not overhear what they said?" "Lady St. Simon said something about 'jumping a claim.' She was accustomed to use slang of the kind. I have no idea what she meant." "American slang is very expressive sometimes. And what did your wife do when she finished speaking to her maid?" "She walked into the breakfast-room." "On your arm?" "No, alone. She was very independent in little matters like that. Then, after we had sat down for ten minutes or so, she rose hurriedly, muttered some words of apology, and left the room. She never came back." "But this maid, Alice, as I understand, deposes that she went to her room, covered her bride's dress with a long ulster, put on a bonnet, and went out." "Quite so. And she was afterwards seen walking into Hyde Park in company with Flora Millar, a woman who is now in custody, and who had already made a disturbance at Mr. Doran's house that morning." "Ah, yes. I should like a few particulars as to this young lady, and your relations to her." Lord St. Simon shrugged his shoulders and raised his eyebrows. "We have been on a friendly footing for some years--I may say on a very friendly footing. She used to be at the Allegro. I have not treated her ungenerously, and she had no just cause of complaint against me, but you know what women are, Mr. Holmes. Flora was a dear little thing, but exceedingly hot-headed and devotedly attached to me. She wrote me dreadful letters when she heard that I was about to be married, and, to tell the truth, the reason why I had the marriage celebrated so quietly was that I feared lest there might be a scandal in the church. She came to Mr. Doran's door just after we returned, and she endeavoured to push her way in, uttering very abusive expressions towards my wife, and even threatening her, but I had foreseen the possibility of something of the sort, and I had two police fellows there in private clothes, who soon pushed her out again. She was quiet when she saw that there was no good in making a row." "Did your wife hear all this?" "No, thank goodness, she did not." "And she was seen walking with this very woman afterwards?" "Yes. That is what Mr. Lestrade, of Scotland Yard, looks upon as so serious. It is thought that Flora decoyed my wife out and laid some terrible trap for her." "Well, it is a possible supposition." "You think so, too?" "I did not say a probable one. But you do not yourself look upon this as likely?" "I do not think Flora would hurt a fly." "Still, jealousy is a strange transformer of characters. Pray what is your own theory as to what took place?" "Well, really, I came to seek a theory, not to propound one. I have given you all the facts. Since you ask me, however, I may say that it has occurred to me as possible that the excitement of this affair, the consciousness that she had made so immense a social stride, had the effect of causing some little nervous disturbance in my wife." "In short, that she had become suddenly deranged?" "Well, really, when I consider that she has turned her back--I will not say upon me, but upon so much that many have aspired to without success--I can hardly explain it in any other fashion." "Well, certainly that is also a conceivable hypothesis," said Holmes, smiling. "And now, Lord St. Simon, I think that I have nearly all my data. May I ask whether you were seated at the breakfast-table so that you could see out of the window?" "We could see the other side of the road and the Park." "Quite so. Then I do not think that I need to detain you longer. I shall communicate with you." "Should you be fortunate enough to solve this problem," said our client, rising. "I have solved it." "Eh? What was that?" "I say that I have solved it." "Where, then, is my wife?" "That is a detail which I shall speedily supply." Lord St. Simon shook his head. "I am afraid that it will take wiser heads than yours or mine," he remarked, and bowing in a stately, old-fashioned manner he departed. "It is very good of Lord St. Simon to honour my head by putting it on a level with his own," said Sherlock Holmes, laughing. "I think that I shall have a whisky and soda and a cigar after all this cross-questioning. I had formed my conclusions as to the case before our client came into the room." "My dear Holmes!" "I have notes of several similar cases, though none, as I remarked before, which were quite as prompt. My whole examination served to turn my conjecture into a certainty. Circumstantial evidence is occasionally very convincing, as when you find a trout in the milk, to quote Thoreau's example." "But I have heard all that you have heard." "Without, however, the knowledge of pre-existing cases which serves me so well. There was a parallel instance in Aberdeen some years back, and something on very much the same lines at Munich the year after the Franco-Prussian War. It is one of these cases--but, hullo, here is Lestrade! Good-afternoon, Lestrade! You will find an extra tumbler upon the sideboard, and there are cigars in the box." The official detective was attired in a pea-jacket and cravat, which gave him a decidedly nautical appearance, and he carried a black canvas bag in his hand. With a short greeting he seated himself and lit the cigar which had been offered to him. "What's up, then?" asked Holmes with a twinkle in his eye. "You look dissatisfied." "And I feel dissatisfied. It is this infernal St. Simon marriage case. I can make neither head nor tail of the business." "Really! You surprise me." "Who ever heard of such a mixed affair? Every clue seems to slip through my fingers. I have been at work upon it all day." "And very wet it seems to have made you," said Holmes laying his hand upon the arm of the pea-jacket. "Yes, I have been dragging the Serpentine." "In heaven's name, what for?" "In search of the body of Lady St. Simon." Sherlock Holmes leaned back in his chair and laughed heartily. "Have you dragged the basin of Trafalgar Square fountain?" he asked. "Why? What do you mean?" "Because you have just as good a chance of finding this lady in the one as in the other." Lestrade shot an angry glance at my companion. "I suppose you know all about it," he snarled. "Well, I have only just heard the facts, but my mind is made up." "Oh, indeed! Then you think that the Serpentine plays no part in the matter?" "I think it very unlikely." "Then perhaps you will kindly explain how it is that we found this in it?" He opened his bag as he spoke, and tumbled onto the floor a wedding-dress of watered silk, a pair of white satin shoes and a bride's wreath and veil, all discoloured and soaked in water. "There," said he, putting a new wedding-ring upon the top of the pile. "There is a little nut for you to crack, Master Holmes." "Oh, indeed!" said my friend, blowing blue rings into the air. "You dragged them from the Serpentine?" "No. They were found floating near the margin by a park-keeper. They have been identified as her clothes, and it seemed to me that if the clothes were there the body would not be far off." "By the same brilliant reasoning, every man's body is to be found in the neighbourhood of his wardrobe. And pray what did you hope to arrive at through this?" "At some evidence implicating Flora Millar in the disappearance." "I am afraid that you will find it difficult." "Are you, indeed, now?" cried Lestrade with some bitterness. "I am afraid, Holmes, that you are not very practical with your deductions and your inferences. You have made two blunders in as many minutes. This dress does implicate Miss Flora Millar." "And how?" "In the dress is a pocket. In the pocket is a card-case. In the card-case is a note. And here is the very note." He slapped it down upon the table in front of him. "Listen to this: 'You will see me when all is ready. Come at once. F.H.M.' Now my theory all along has been that Lady St. Simon was decoyed away by Flora Millar, and that she, with confederates, no doubt, was responsible for her disappearance. Here, signed with her initials, is the very note which was no doubt quietly slipped into her hand at the door and which lured her within their reach." "Very good, Lestrade," said Holmes, laughing. "You really are very fine indeed. Let me see it." He took up the paper in a listless way, but his attention instantly became riveted, and he gave a little cry of satisfaction. "This is indeed important," said he. "Ha! you find it so?" "Extremely so. I congratulate you warmly." Lestrade rose in his triumph and bent his head to look. "Why," he shrieked, "you're looking at the wrong side!" "On the contrary, this is the right side." "The right side? You're mad! Here is the note written in pencil over here." "And over here is what appears to be the fragment of a hotel bill, which interests me deeply." "There's nothing in it. I looked at it before," said Lestrade. "'Oct. 4th, rooms 8s., breakfast 2s. 6d., cocktail 1s., lunch 2s. 6d., glass sherry, 8d.' I see nothing in that." "Very likely not. It is most important, all the same. As to the note, it is important also, or at least the initials are, so I congratulate you again." "I've wasted time enough," said Lestrade, rising. "I believe in hard work and not in sitting by the fire spinning fine theories. Good-day, Mr. Holmes, and we shall see which gets to the bottom of the matter first." He gathered up the garments, thrust them into the bag, and made for the door. "Just one hint to you, Lestrade," drawled Holmes before his rival vanished; "I will tell you the true solution of the matter. Lady St. Simon is a myth. There is not, and there never has been, any such person." Lestrade looked sadly at my companion. Then he turned to me, tapped his forehead three times, shook his head solemnly, and hurried away. He had hardly shut the door behind him when Holmes rose to put on his overcoat. "There is something in what the fellow says about outdoor work," he remarked, "so I think, Watson, that I must leave you to your papers for a little." It was after five o'clock when Sherlock Holmes left me, but I had no time to be lonely, for within an hour there arrived a confectioner's man with a very large flat box. This he unpacked with the help of a youth whom he had brought with him, and presently, to my very great astonishment, a quite epicurean little cold supper began to be laid out upon our humble lodging-house mahogany. There were a couple of brace of cold woodcock, a pheasant, a pâté de foie gras pie with a group of ancient and cobwebby bottles. Having laid out all these luxuries, my two visitors vanished away, like the genii of the Arabian Nights, with no explanation save that the things had been paid for and were ordered to this address. Just before nine o'clock Sherlock Holmes stepped briskly into the room. His features were gravely set, but there was a light in his eye which made me think that he had not been disappointed in his conclusions. "They have laid the supper, then," he said, rubbing his hands. "You seem to expect company. They have laid for five." "Yes, I fancy we may have some company dropping in," said he. "I am surprised that Lord St. Simon has not already arrived. Ha! I fancy that I hear his step now upon the stairs." It was indeed our visitor of the afternoon who came bustling in, dangling his glasses more vigorously than ever, and with a very perturbed expression upon his aristocratic features. "My messenger reached you, then?" asked Holmes. "Yes, and I confess that the contents startled me beyond measure. Have you good authority for what you say?" "The best possible." Lord St. Simon sank into a chair and passed his hand over his forehead. "What will the Duke say," he murmured, "when he hears that one of the family has been subjected to such humiliation?" "It is the purest accident. I cannot allow that there is any humiliation." "Ah, you look on these things from another standpoint." "I fail to see that anyone is to blame. I can hardly see how the lady could have acted otherwise, though her abrupt method of doing it was undoubtedly to be regretted. Having no mother, she had no one to advise her at such a crisis." "It was a slight, sir, a public slight," said Lord St. Simon, tapping his fingers upon the table. "You must make allowance for this poor girl, placed in so unprecedented a position." "I will make no allowance. I am very angry indeed, and I have been shamefully used." "I think that I heard a ring," said Holmes. "Yes, there are steps on the landing. If I cannot persuade you to take a lenient view of the matter, Lord St. Simon, I have brought an advocate here who may be more successful." He opened the door and ushered in a lady and gentleman. "Lord St. Simon," said he "allow me to introduce you to Mr. and Mrs. Francis Hay Moulton. The lady, I think, you have already met." At the sight of these newcomers our client had sprung from his seat and stood very erect, with his eyes cast down and his hand thrust into the breast of his frock-coat, a picture of offended dignity. The lady had taken a quick step forward and had held out her hand to him, but he still refused to raise his eyes. It was as well for his resolution, perhaps, for her pleading face was one which it was hard to resist. "You're angry, Robert," said she. "Well, I guess you have every cause to be." "Pray make no apology to me," said Lord St. Simon bitterly. "Oh, yes, I know that I have treated you real bad and that I should have spoken to you before I went; but I was kind of rattled, and from the time when I saw Frank here again I just didn't know what I was doing or saying. I only wonder I didn't fall down and do a faint right there before the altar." "Perhaps, Mrs. Moulton, you would like my friend and me to leave the room while you explain this matter?" "If I may give an opinion," remarked the strange gentleman, "we've had just a little too much secrecy over this business already. For my part, I should like all Europe and America to hear the rights of it." He was a small, wiry, sunburnt man, clean-shaven, with a sharp face and alert manner. "Then I'll tell our story right away," said the lady. "Frank here and I met in '84, in McQuire's camp, near the Rockies, where pa was working a claim. We were engaged to each other, Frank and I; but then one day father struck a rich pocket and made a pile, while poor Frank here had a claim that petered out and came to nothing. The richer pa grew the poorer was Frank; so at last pa wouldn't hear of our engagement lasting any longer, and he took me away to 'Frisco. Frank wouldn't throw up his hand, though; so he followed me there, and he saw me without pa knowing anything about it. It would only have made him mad to know, so we just fixed it all up for ourselves. Frank said that he would go and make his pile, too, and never come back to claim me until he had as much as pa. So then I promised to wait for him to the end of time and pledged myself not to marry anyone else while he lived. 'Why shouldn't we be married right away, then,' said he, 'and then I will feel sure of you; and I won't claim to be your husband until I come back?' Well, we talked it over, and he had fixed it all up so nicely, with a clergyman all ready in waiting, that we just did it right there; and then Frank went off to seek his fortune, and I went back to pa. "The next I heard of Frank was that he was in Montana, and then he went prospecting in Arizona, and then I heard of him from New Mexico. After that came a long newspaper story about how a miners' camp had been attacked by Apache Indians, and there was my Frank's name among the killed. I fainted dead away, and I was very sick for months after. Pa thought I had a decline and took me to half the doctors in 'Frisco. Not a word of news came for a year and more, so that I never doubted that Frank was really dead. Then Lord St. Simon came to 'Frisco, and we came to London, and a marriage was arranged, and pa was very pleased, but I felt all the time that no man on this earth would ever take the place in my heart that had been given to my poor Frank. "Still, if I had married Lord St. Simon, of course I'd have done my duty by him. We can't command our love, but we can our actions. I went to the altar with him with the intention to make him just as good a wife as it was in me to be. But you may imagine what I felt when, just as I came to the altar rails, I glanced back and saw Frank standing and looking at me out of the first pew. I thought it was his ghost at first; but when I looked again there he was still, with a kind of question in his eyes, as if to ask me whether I were glad or sorry to see him. I wonder I didn't drop. I know that everything was turning round, and the words of the clergyman were just like the buzz of a bee in my ear. I didn't know what to do. Should I stop the service and make a scene in the church? I glanced at him again, and he seemed to know what I was thinking, for he raised his finger to his lips to tell me to be still. Then I saw him scribble on a piece of paper, and I knew that he was writing me a note. As I passed his pew on the way out I dropped my bouquet over to him, and he slipped the note into my hand when he returned me the flowers. It was only a line asking me to join him when he made the sign to me to do so. Of course I never doubted for a moment that my first duty was now to him, and I determined to do just whatever he might direct. "When I got back I told my maid, who had known him in California, and had always been his friend. I ordered her to say nothing, but to get a few things packed and my ulster ready. I know I ought to have spoken to Lord St. Simon, but it was dreadful hard before his mother and all those great people. I just made up my mind to run away and explain afterwards. I hadn't been at the table ten minutes before I saw Frank out of the window at the other side of the road. He beckoned to me and then began walking into the Park. I slipped out, put on my things, and followed him. Some woman came talking something or other about Lord St. Simon to me--seemed to me from the little I heard as if he had a little secret of his own before marriage also--but I managed to get away from her and soon overtook Frank. We got into a cab together, and away we drove to some lodgings he had taken in Gordon Square, and that was my true wedding after all those years of waiting. Frank had been a prisoner among the Apaches, had escaped, came on to 'Frisco, found that I had given him up for dead and had gone to England, followed me there, and had come upon me at last on the very morning of my second wedding." "I saw it in a paper," explained the American. "It gave the name and the church but not where the lady lived." "Then we had a talk as to what we should do, and Frank was all for openness, but I was so ashamed of it all that I felt as if I should like to vanish away and never see any of them again--just sending a line to pa, perhaps, to show him that I was alive. It was awful to me to think of all those lords and ladies sitting round that breakfast-table and waiting for me to come back. So Frank took my wedding-clothes and things and made a bundle of them, so that I should not be traced, and dropped them away somewhere where no one could find them. It is likely that we should have gone on to Paris to-morrow, only that this good gentleman, Mr. Holmes, came round to us this evening, though how he found us is more than I can think, and he showed us very clearly and kindly that I was wrong and that Frank was right, and that we should be putting ourselves in the wrong if we were so secret. Then he offered to give us a chance of talking to Lord St. Simon alone, and so we came right away round to his rooms at once. Now, Robert, you have heard it all, and I am very sorry if I have given you pain, and I hope that you do not think very meanly of me." Lord St. Simon had by no means relaxed his rigid attitude, but had listened with a frowning brow and a compressed lip to this long narrative. "Excuse me," he said, "but it is not my custom to discuss my most intimate personal affairs in this public manner." "Then you won't forgive me? You won't shake hands before I go?" "Oh, certainly, if it would give you any pleasure." He put out his hand and coldly grasped that which she extended to him. "I had hoped," suggested Holmes, "that you would have joined us in a friendly supper." "I think that there you ask a little too much," responded his Lordship. "I may be forced to acquiesce in these recent developments, but I can hardly be expected to make merry over them. I think that with your permission I will now wish you all a very good-night." He included us all in a sweeping bow and stalked out of the room. "Then I trust that you at least will honour me with your company," said Sherlock Holmes. "It is always a joy to meet an American, Mr. Moulton, for I am one of those who believe that the folly of a monarch and the blundering of a minister in far-gone years will not prevent our children from being some day citizens of the same world-wide country under a flag which shall be a quartering of the Union Jack with the Stars and Stripes." "The case has been an interesting one," remarked Holmes when our visitors had left us, "because it serves to show very clearly how simple the explanation may be of an affair which at first sight seems to be almost inexplicable. Nothing could be more natural than the sequence of events as narrated by this lady, and nothing stranger than the result when viewed, for instance, by Mr. Lestrade of Scotland Yard." "You were not yourself at fault at all, then?" "From the first, two facts were very obvious to me, the one that the lady had been quite willing to undergo the wedding ceremony, the other that she had repented of it within a few minutes of returning home. Obviously something had occurred during the morning, then, to cause her to change her mind. What could that something be? She could not have spoken to anyone when she was out, for she had been in the company of the bridegroom. Had she seen someone, then? If she had, it must be someone from America because she had spent so short a time in this country that she could hardly have allowed anyone to acquire so deep an influence over her that the mere sight of him would induce her to change her plans so completely. You see we have already arrived, by a process of exclusion, at the idea that she might have seen an American. Then who could this American be, and why should he possess so much influence over her? It might be a lover; it might be a husband. Her young womanhood had, I knew, been spent in rough scenes and under strange conditions. So far I had got before I ever heard Lord St. Simon's narrative. When he told us of a man in a pew, of the change in the bride's manner, of so transparent a device for obtaining a note as the dropping of a bouquet, of her resort to her confidential maid, and of her very significant allusion to claim-jumping--which in miners' parlance means taking possession of that which another person has a prior claim to--the whole situation became absolutely clear. She had gone off with a man, and the man was either a lover or was a previous husband--the chances being in favour of the latter." "And how in the world did you find them?" "It might have been difficult, but friend Lestrade held information in his hands the value of which he did not himself know. The initials were, of course, of the highest importance, but more valuable still was it to know that within a week he had settled his bill at one of the most select London hotels." "How did you deduce the select?" "By the select prices. Eight shillings for a bed and eightpence for a glass of sherry pointed to one of the most expensive hotels. There are not many in London which charge at that rate. In the second one which I visited in Northumberland Avenue, I learned by an inspection of the book that Francis H. Moulton, an American gentleman, had left only the day before, and on looking over the entries against him, I came upon the very items which I had seen in the duplicate bill. His letters were to be forwarded to 226 Gordon Square; so thither I travelled, and being fortunate enough to find the loving couple at home, I ventured to give them some paternal advice and to point out to them that it would be better in every way that they should make their position a little clearer both to the general public and to Lord St. Simon in particular. I invited them to meet him here, and, as you see, I made him keep the appointment." "But with no very good result," I remarked. "His conduct was certainly not very gracious." "Ah, Watson," said Holmes, smiling, "perhaps you would not be very gracious either, if, after all the trouble of wooing and wedding, you found yourself deprived in an instant of wife and of fortune. I think that we may judge Lord St. Simon very mercifully and thank our stars that we are never likely to find ourselves in the same position. Draw your chair up and hand me my violin, for the only problem we have still to solve is how to while away these bleak autumnal evenings." XI. THE ADVENTURE OF THE BERYL CORONET "Holmes," said I as I stood one morning in our bow-window looking down the street, "here is a madman coming along. It seems rather sad that his relatives should allow him to come out alone." My friend rose lazily from his armchair and stood with his hands in the pockets of his dressing-gown, looking over my shoulder. It was a bright, crisp February morning, and the snow of the day before still lay deep upon the ground, shimmering brightly in the wintry sun. Down the centre of Baker Street it had been ploughed into a brown crumbly band by the traffic, but at either side and on the heaped-up edges of the foot-paths it still lay as white as when it fell. The grey pavement had been cleaned and scraped, but was still dangerously slippery, so that there were fewer passengers than usual. Indeed, from the direction of the Metropolitan Station no one was coming save the single gentleman whose eccentric conduct had drawn my attention. He was a man of about fifty, tall, portly, and imposing, with a massive, strongly marked face and a commanding figure. He was dressed in a sombre yet rich style, in black frock-coat, shining hat, neat brown gaiters, and well-cut pearl-grey trousers. Yet his actions were in absurd contrast to the dignity of his dress and features, for he was running hard, with occasional little springs, such as a weary man gives who is little accustomed to set any tax upon his legs. As he ran he jerked his hands up and down, waggled his head, and writhed his face into the most extraordinary contortions. "What on earth can be the matter with him?" I asked. "He is looking up at the numbers of the houses." "I believe that he is coming here," said Holmes, rubbing his hands. "Here?" "Yes; I rather think he is coming to consult me professionally. I think that I recognise the symptoms. Ha! did I not tell you?" As he spoke, the man, puffing and blowing, rushed at our door and pulled at our bell until the whole house resounded with the clanging. A few moments later he was in our room, still puffing, still gesticulating, but with so fixed a look of grief and despair in his eyes that our smiles were turned in an instant to horror and pity. For a while he could not get his words out, but swayed his body and plucked at his hair like one who has been driven to the extreme limits of his reason. Then, suddenly springing to his feet, he beat his head against the wall with such force that we both rushed upon him and tore him away to the centre of the room. Sherlock Holmes pushed him down into the easy-chair and, sitting beside him, patted his hand and chatted with him in the easy, soothing tones which he knew so well how to employ. "You have come to me to tell your story, have you not?" said he. "You are fatigued with your haste. Pray wait until you have recovered yourself, and then I shall be most happy to look into any little problem which you may submit to me." The man sat for a minute or more with a heaving chest, fighting against his emotion. Then he passed his handkerchief over his brow, set his lips tight, and turned his face towards us. "No doubt you think me mad?" said he. "I see that you have had some great trouble," responded Holmes. "God knows I have!--a trouble which is enough to unseat my reason, so sudden and so terrible is it. Public disgrace I might have faced, although I am a man whose character has never yet borne a stain. Private affliction also is the lot of every man; but the two coming together, and in so frightful a form, have been enough to shake my very soul. Besides, it is not I alone. The very noblest in the land may suffer unless some way be found out of this horrible affair." "Pray compose yourself, sir," said Holmes, "and let me have a clear account of who you are and what it is that has befallen you." "My name," answered our visitor, "is probably familiar to your ears. I am Alexander Holder, of the banking firm of Holder & Stevenson, of Threadneedle Street." The name was indeed well known to us as belonging to the senior partner in the second largest private banking concern in the City of London. What could have happened, then, to bring one of the foremost citizens of London to this most pitiable pass? We waited, all curiosity, until with another effort he braced himself to tell his story. "I feel that time is of value," said he; "that is why I hastened here when the police inspector suggested that I should secure your co-operation. I came to Baker Street by the Underground and hurried from there on foot, for the cabs go slowly through this snow. That is why I was so out of breath, for I am a man who takes very little exercise. I feel better now, and I will put the facts before you as shortly and yet as clearly as I can. "It is, of course, well known to you that in a successful banking business as much depends upon our being able to find remunerative investments for our funds as upon our increasing our connection and the number of our depositors. One of our most lucrative means of laying out money is in the shape of loans, where the security is unimpeachable. We have done a good deal in this direction during the last few years, and there are many noble families to whom we have advanced large sums upon the security of their pictures, libraries, or plate. "Yesterday morning I was seated in my office at the bank when a card was brought in to me by one of the clerks. I started when I saw the name, for it was that of none other than--well, perhaps even to you I had better say no more than that it was a name which is a household word all over the earth--one of the highest, noblest, most exalted names in England. I was overwhelmed by the honour and attempted, when he entered, to say so, but he plunged at once into business with the air of a man who wishes to hurry quickly through a disagreeable task. "'Mr. Holder,' said he, 'I have been informed that you are in the habit of advancing money.' "'The firm does so when the security is good.' I answered. "'It is absolutely essential to me,' said he, 'that I should have 50,000 pounds at once. I could, of course, borrow so trifling a sum ten times over from my friends, but I much prefer to make it a matter of business and to carry out that business myself. In my position you can readily understand that it is unwise to place one's self under obligations.' "'For how long, may I ask, do you want this sum?' I asked. "'Next Monday I have a large sum due to me, and I shall then most certainly repay what you advance, with whatever interest you think it right to charge. But it is very essential to me that the money should be paid at once.' "'I should be happy to advance it without further parley from my own private purse,' said I, 'were it not that the strain would be rather more than it could bear. If, on the other hand, I am to do it in the name of the firm, then in justice to my partner I must insist that, even in your case, every businesslike precaution should be taken.' "'I should much prefer to have it so,' said he, raising up a square, black morocco case which he had laid beside his chair. 'You have doubtless heard of the Beryl Coronet?' "'One of the most precious public possessions of the empire,' said I. "'Precisely.' He opened the case, and there, imbedded in soft, flesh-coloured velvet, lay the magnificent piece of jewellery which he had named. 'There are thirty-nine enormous beryls,' said he, 'and the price of the gold chasing is incalculable. The lowest estimate would put the worth of the coronet at double the sum which I have asked. I am prepared to leave it with you as my security.' "I took the precious case into my hands and looked in some perplexity from it to my illustrious client. "'You doubt its value?' he asked. "'Not at all. I only doubt--' "'The propriety of my leaving it. You may set your mind at rest about that. I should not dream of doing so were it not absolutely certain that I should be able in four days to reclaim it. It is a pure matter of form. Is the security sufficient?' "'Ample.' "'You understand, Mr. Holder, that I am giving you a strong proof of the confidence which I have in you, founded upon all that I have heard of you. I rely upon you not only to be discreet and to refrain from all gossip upon the matter but, above all, to preserve this coronet with every possible precaution because I need not say that a great public scandal would be caused if any harm were to befall it. Any injury to it would be almost as serious as its complete loss, for there are no beryls in the world to match these, and it would be impossible to replace them. I leave it with you, however, with every confidence, and I shall call for it in person on Monday morning.' "Seeing that my client was anxious to leave, I said no more but, calling for my cashier, I ordered him to pay over fifty 1000 pound notes. When I was alone once more, however, with the precious case lying upon the table in front of me, I could not but think with some misgivings of the immense responsibility which it entailed upon me. There could be no doubt that, as it was a national possession, a horrible scandal would ensue if any misfortune should occur to it. I already regretted having ever consented to take charge of it. However, it was too late to alter the matter now, so I locked it up in my private safe and turned once more to my work. "When evening came I felt that it would be an imprudence to leave so precious a thing in the office behind me. Bankers' safes had been forced before now, and why should not mine be? If so, how terrible would be the position in which I should find myself! I determined, therefore, that for the next few days I would always carry the case backward and forward with me, so that it might never be really out of my reach. With this intention, I called a cab and drove out to my house at Streatham, carrying the jewel with me. I did not breathe freely until I had taken it upstairs and locked it in the bureau of my dressing-room. "And now a word as to my household, Mr. Holmes, for I wish you to thoroughly understand the situation. My groom and my page sleep out of the house, and may be set aside altogether. I have three maid-servants who have been with me a number of years and whose absolute reliability is quite above suspicion. Another, Lucy Parr, the second waiting-maid, has only been in my service a few months. She came with an excellent character, however, and has always given me satisfaction. She is a very pretty girl and has attracted admirers who have occasionally hung about the place. That is the only drawback which we have found to her, but we believe her to be a thoroughly good girl in every way. "So much for the servants. My family itself is so small that it will not take me long to describe it. I am a widower and have an only son, Arthur. He has been a disappointment to me, Mr. Holmes--a grievous disappointment. I have no doubt that I am myself to blame. People tell me that I have spoiled him. Very likely I have. When my dear wife died I felt that he was all I had to love. I could not bear to see the smile fade even for a moment from his face. I have never denied him a wish. Perhaps it would have been better for both of us had I been sterner, but I meant it for the best. "It was naturally my intention that he should succeed me in my business, but he was not of a business turn. He was wild, wayward, and, to speak the truth, I could not trust him in the handling of large sums of money. When he was young he became a member of an aristocratic club, and there, having charming manners, he was soon the intimate of a number of men with long purses and expensive habits. He learned to play heavily at cards and to squander money on the turf, until he had again and again to come to me and implore me to give him an advance upon his allowance, that he might settle his debts of honour. He tried more than once to break away from the dangerous company which he was keeping, but each time the influence of his friend, Sir George Burnwell, was enough to draw him back again. "And, indeed, I could not wonder that such a man as Sir George Burnwell should gain an influence over him, for he has frequently brought him to my house, and I have found myself that I could hardly resist the fascination of his manner. He is older than Arthur, a man of the world to his finger-tips, one who had been everywhere, seen everything, a brilliant talker, and a man of great personal beauty. Yet when I think of him in cold blood, far away from the glamour of his presence, I am convinced from his cynical speech and the look which I have caught in his eyes that he is one who should be deeply distrusted. So I think, and so, too, thinks my little Mary, who has a woman's quick insight into character. "And now there is only she to be described. She is my niece; but when my brother died five years ago and left her alone in the world I adopted her, and have looked upon her ever since as my daughter. She is a sunbeam in my house--sweet, loving, beautiful, a wonderful manager and housekeeper, yet as tender and quiet and gentle as a woman could be. She is my right hand. I do not know what I could do without her. In only one matter has she ever gone against my wishes. Twice my boy has asked her to marry him, for he loves her devotedly, but each time she has refused him. I think that if anyone could have drawn him into the right path it would have been she, and that his marriage might have changed his whole life; but now, alas! it is too late--forever too late! "Now, Mr. Holmes, you know the people who live under my roof, and I shall continue with my miserable story. "When we were taking coffee in the drawing-room that night after dinner, I told Arthur and Mary my experience, and of the precious treasure which we had under our roof, suppressing only the name of my client. Lucy Parr, who had brought in the coffee, had, I am sure, left the room; but I cannot swear that the door was closed. Mary and Arthur were much interested and wished to see the famous coronet, but I thought it better not to disturb it. "'Where have you put it?' asked Arthur. "'In my own bureau.' "'Well, I hope to goodness the house won't be burgled during the night.' said he. "'It is locked up,' I answered. "'Oh, any old key will fit that bureau. When I was a youngster I have opened it myself with the key of the box-room cupboard.' "He often had a wild way of talking, so that I thought little of what he said. He followed me to my room, however, that night with a very grave face. "'Look here, dad,' said he with his eyes cast down, 'can you let me have 200 pounds?' "'No, I cannot!' I answered sharply. 'I have been far too generous with you in money matters.' "'You have been very kind,' said he, 'but I must have this money, or else I can never show my face inside the club again.' "'And a very good thing, too!' I cried. "'Yes, but you would not have me leave it a dishonoured man,' said he. 'I could not bear the disgrace. I must raise the money in some way, and if you will not let me have it, then I must try other means.' "I was very angry, for this was the third demand during the month. 'You shall not have a farthing from me,' I cried, on which he bowed and left the room without another word. "When he was gone I unlocked my bureau, made sure that my treasure was safe, and locked it again. Then I started to go round the house to see that all was secure--a duty which I usually leave to Mary but which I thought it well to perform myself that night. As I came down the stairs I saw Mary herself at the side window of the hall, which she closed and fastened as I approached. "'Tell me, dad,' said she, looking, I thought, a little disturbed, 'did you give Lucy, the maid, leave to go out to-night?' "'Certainly not.' "'She came in just now by the back door. I have no doubt that she has only been to the side gate to see someone, but I think that it is hardly safe and should be stopped.' "'You must speak to her in the morning, or I will if you prefer it. Are you sure that everything is fastened?' "'Quite sure, dad.' "'Then, good-night.' I kissed her and went up to my bedroom again, where I was soon asleep. "I am endeavouring to tell you everything, Mr. Holmes, which may have any bearing upon the case, but I beg that you will question me upon any point which I do not make clear." "On the contrary, your statement is singularly lucid." "I come to a part of my story now in which I should wish to be particularly so. I am not a very heavy sleeper, and the anxiety in my mind tended, no doubt, to make me even less so than usual. About two in the morning, then, I was awakened by some sound in the house. It had ceased ere I was wide awake, but it had left an impression behind it as though a window had gently closed somewhere. I lay listening with all my ears. Suddenly, to my horror, there was a distinct sound of footsteps moving softly in the next room. I slipped out of bed, all palpitating with fear, and peeped round the corner of my dressing-room door. "'Arthur!' I screamed, 'you villain! you thief! How dare you touch that coronet?' "The gas was half up, as I had left it, and my unhappy boy, dressed only in his shirt and trousers, was standing beside the light, holding the coronet in his hands. He appeared to be wrenching at it, or bending it with all his strength. At my cry he dropped it from his grasp and turned as pale as death. I snatched it up and examined it. One of the gold corners, with three of the beryls in it, was missing. "'You blackguard!' I shouted, beside myself with rage. 'You have destroyed it! You have dishonoured me forever! Where are the jewels which you have stolen?' "'Stolen!' he cried. "'Yes, thief!' I roared, shaking him by the shoulder. "'There are none missing. There cannot be any missing,' said he. "'There are three missing. And you know where they are. Must I call you a liar as well as a thief? Did I not see you trying to tear off another piece?' "'You have called me names enough,' said he, 'I will not stand it any longer. I shall not say another word about this business, since you have chosen to insult me. I will leave your house in the morning and make my own way in the world.' "'You shall leave it in the hands of the police!' I cried half-mad with grief and rage. 'I shall have this matter probed to the bottom.' "'You shall learn nothing from me,' said he with a passion such as I should not have thought was in his nature. 'If you choose to call the police, let the police find what they can.' "By this time the whole house was astir, for I had raised my voice in my anger. Mary was the first to rush into my room, and, at the sight of the coronet and of Arthur's face, she read the whole story and, with a scream, fell down senseless on the ground. I sent the house-maid for the police and put the investigation into their hands at once. When the inspector and a constable entered the house, Arthur, who had stood sullenly with his arms folded, asked me whether it was my intention to charge him with theft. I answered that it had ceased to be a private matter, but had become a public one, since the ruined coronet was national property. I was determined that the law should have its way in everything. "'At least,' said he, 'you will not have me arrested at once. It would be to your advantage as well as mine if I might leave the house for five minutes.' "'That you may get away, or perhaps that you may conceal what you have stolen,' said I. And then, realising the dreadful position in which I was placed, I implored him to remember that not only my honour but that of one who was far greater than I was at stake; and that he threatened to raise a scandal which would convulse the nation. He might avert it all if he would but tell me what he had done with the three missing stones. "'You may as well face the matter,' said I; 'you have been caught in the act, and no confession could make your guilt more heinous. If you but make such reparation as is in your power, by telling us where the beryls are, all shall be forgiven and forgotten.' "'Keep your forgiveness for those who ask for it,' he answered, turning away from me with a sneer. I saw that he was too hardened for any words of mine to influence him. There was but one way for it. I called in the inspector and gave him into custody. A search was made at once not only of his person but of his room and of every portion of the house where he could possibly have concealed the gems; but no trace of them could be found, nor would the wretched boy open his mouth for all our persuasions and our threats. This morning he was removed to a cell, and I, after going through all the police formalities, have hurried round to you to implore you to use your skill in unravelling the matter. The police have openly confessed that they can at present make nothing of it. You may go to any expense which you think necessary. I have already offered a reward of 1000 pounds. My God, what shall I do! I have lost my honour, my gems, and my son in one night. Oh, what shall I do!" He put a hand on either side of his head and rocked himself to and fro, droning to himself like a child whose grief has got beyond words. Sherlock Holmes sat silent for some few minutes, with his brows knitted and his eyes fixed upon the fire. "Do you receive much company?" he asked. "None save my partner with his family and an occasional friend of Arthur's. Sir George Burnwell has been several times lately. No one else, I think." "Do you go out much in society?" "Arthur does. Mary and I stay at home. We neither of us care for it." "That is unusual in a young girl." "She is of a quiet nature. Besides, she is not so very young. She is four-and-twenty." "This matter, from what you say, seems to have been a shock to her also." "Terrible! She is even more affected than I." "You have neither of you any doubt as to your son's guilt?" "How can we have when I saw him with my own eyes with the coronet in his hands." "I hardly consider that a conclusive proof. Was the remainder of the coronet at all injured?" "Yes, it was twisted." "Do you not think, then, that he might have been trying to straighten it?" "God bless you! You are doing what you can for him and for me. But it is too heavy a task. What was he doing there at all? If his purpose were innocent, why did he not say so?" "Precisely. And if it were guilty, why did he not invent a lie? His silence appears to me to cut both ways. There are several singular points about the case. What did the police think of the noise which awoke you from your sleep?" "They considered that it might be caused by Arthur's closing his bedroom door." "A likely story! As if a man bent on felony would slam his door so as to wake a household. What did they say, then, of the disappearance of these gems?" "They are still sounding the planking and probing the furniture in the hope of finding them." "Have they thought of looking outside the house?" "Yes, they have shown extraordinary energy. The whole garden has already been minutely examined." "Now, my dear sir," said Holmes, "is it not obvious to you now that this matter really strikes very much deeper than either you or the police were at first inclined to think? It appeared to you to be a simple case; to me it seems exceedingly complex. Consider what is involved by your theory. You suppose that your son came down from his bed, went, at great risk, to your dressing-room, opened your bureau, took out your coronet, broke off by main force a small portion of it, went off to some other place, concealed three gems out of the thirty-nine, with such skill that nobody can find them, and then returned with the other thirty-six into the room in which he exposed himself to the greatest danger of being discovered. I ask you now, is such a theory tenable?" "But what other is there?" cried the banker with a gesture of despair. "If his motives were innocent, why does he not explain them?" "It is our task to find that out," replied Holmes; "so now, if you please, Mr. Holder, we will set off for Streatham together, and devote an hour to glancing a little more closely into details." My friend insisted upon my accompanying them in their expedition, which I was eager enough to do, for my curiosity and sympathy were deeply stirred by the story to which we had listened. I confess that the guilt of the banker's son appeared to me to be as obvious as it did to his unhappy father, but still I had such faith in Holmes' judgment that I felt that there must be some grounds for hope as long as he was dissatisfied with the accepted explanation. He hardly spoke a word the whole way out to the southern suburb, but sat with his chin upon his breast and his hat drawn over his eyes, sunk in the deepest thought. Our client appeared to have taken fresh heart at the little glimpse of hope which had been presented to him, and he even broke into a desultory chat with me over his business affairs. A short railway journey and a shorter walk brought us to Fairbank, the modest residence of the great financier. Fairbank was a good-sized square house of white stone, standing back a little from the road. A double carriage-sweep, with a snow-clad lawn, stretched down in front to two large iron gates which closed the entrance. On the right side was a small wooden thicket, which led into a narrow path between two neat hedges stretching from the road to the kitchen door, and forming the tradesmen's entrance. On the left ran a lane which led to the stables, and was not itself within the grounds at all, being a public, though little used, thoroughfare. Holmes left us standing at the door and walked slowly all round the house, across the front, down the tradesmen's path, and so round by the garden behind into the stable lane. So long was he that Mr. Holder and I went into the dining-room and waited by the fire until he should return. We were sitting there in silence when the door opened and a young lady came in. She was rather above the middle height, slim, with dark hair and eyes, which seemed the darker against the absolute pallor of her skin. I do not think that I have ever seen such deadly paleness in a woman's face. Her lips, too, were bloodless, but her eyes were flushed with crying. As she swept silently into the room she impressed me with a greater sense of grief than the banker had done in the morning, and it was the more striking in her as she was evidently a woman of strong character, with immense capacity for self-restraint. Disregarding my presence, she went straight to her uncle and passed her hand over his head with a sweet womanly caress. "You have given orders that Arthur should be liberated, have you not, dad?" she asked. "No, no, my girl, the matter must be probed to the bottom." "But I am so sure that he is innocent. You know what woman's instincts are. I know that he has done no harm and that you will be sorry for having acted so harshly." "Why is he silent, then, if he is innocent?" "Who knows? Perhaps because he was so angry that you should suspect him." "How could I help suspecting him, when I actually saw him with the coronet in his hand?" "Oh, but he had only picked it up to look at it. Oh, do, do take my word for it that he is innocent. Let the matter drop and say no more. It is so dreadful to think of our dear Arthur in prison!" "I shall never let it drop until the gems are found--never, Mary! Your affection for Arthur blinds you as to the awful consequences to me. Far from hushing the thing up, I have brought a gentleman down from London to inquire more deeply into it." "This gentleman?" she asked, facing round to me. "No, his friend. He wished us to leave him alone. He is round in the stable lane now." "The stable lane?" She raised her dark eyebrows. "What can he hope to find there? Ah! this, I suppose, is he. I trust, sir, that you will succeed in proving, what I feel sure is the truth, that my cousin Arthur is innocent of this crime." "I fully share your opinion, and I trust, with you, that we may prove it," returned Holmes, going back to the mat to knock the snow from his shoes. "I believe I have the honour of addressing Miss Mary Holder. Might I ask you a question or two?" "Pray do, sir, if it may help to clear this horrible affair up." "You heard nothing yourself last night?" "Nothing, until my uncle here began to speak loudly. I heard that, and I came down." "You shut up the windows and doors the night before. Did you fasten all the windows?" "Yes." "Were they all fastened this morning?" "Yes." "You have a maid who has a sweetheart? I think that you remarked to your uncle last night that she had been out to see him?" "Yes, and she was the girl who waited in the drawing-room, and who may have heard uncle's remarks about the coronet." "I see. You infer that she may have gone out to tell her sweetheart, and that the two may have planned the robbery." "But what is the good of all these vague theories," cried the banker impatiently, "when I have told you that I saw Arthur with the coronet in his hands?" "Wait a little, Mr. Holder. We must come back to that. About this girl, Miss Holder. You saw her return by the kitchen door, I presume?" "Yes; when I went to see if the door was fastened for the night I met her slipping in. I saw the man, too, in the gloom." "Do you know him?" "Oh, yes! he is the green-grocer who brings our vegetables round. His name is Francis Prosper." "He stood," said Holmes, "to the left of the door--that is to say, farther up the path than is necessary to reach the door?" "Yes, he did." "And he is a man with a wooden leg?" Something like fear sprang up in the young lady's expressive black eyes. "Why, you are like a magician," said she. "How do you know that?" She smiled, but there was no answering smile in Holmes' thin, eager face. "I should be very glad now to go upstairs," said he. "I shall probably wish to go over the outside of the house again. Perhaps I had better take a look at the lower windows before I go up." He walked swiftly round from one to the other, pausing only at the large one which looked from the hall onto the stable lane. This he opened and made a very careful examination of the sill with his powerful magnifying lens. "Now we shall go upstairs," said he at last. The banker's dressing-room was a plainly furnished little chamber, with a grey carpet, a large bureau, and a long mirror. Holmes went to the bureau first and looked hard at the lock. "Which key was used to open it?" he asked. "That which my son himself indicated--that of the cupboard of the lumber-room." "Have you it here?" "That is it on the dressing-table." Sherlock Holmes took it up and opened the bureau. "It is a noiseless lock," said he. "It is no wonder that it did not wake you. This case, I presume, contains the coronet. We must have a look at it." He opened the case, and taking out the diadem he laid it upon the table. It was a magnificent specimen of the jeweller's art, and the thirty-six stones were the finest that I have ever seen. At one side of the coronet was a cracked edge, where a corner holding three gems had been torn away. "Now, Mr. Holder," said Holmes, "here is the corner which corresponds to that which has been so unfortunately lost. Might I beg that you will break it off." The banker recoiled in horror. "I should not dream of trying," said he. "Then I will." Holmes suddenly bent his strength upon it, but without result. "I feel it give a little," said he; "but, though I am exceptionally strong in the fingers, it would take me all my time to break it. An ordinary man could not do it. Now, what do you think would happen if I did break it, Mr. Holder? There would be a noise like a pistol shot. Do you tell me that all this happened within a few yards of your bed and that you heard nothing of it?" "I do not know what to think. It is all dark to me." "But perhaps it may grow lighter as we go. What do you think, Miss Holder?" "I confess that I still share my uncle's perplexity." "Your son had no shoes or slippers on when you saw him?" "He had nothing on save only his trousers and shirt." "Thank you. We have certainly been favoured with extraordinary luck during this inquiry, and it will be entirely our own fault if we do not succeed in clearing the matter up. With your permission, Mr. Holder, I shall now continue my investigations outside." He went alone, at his own request, for he explained that any unnecessary footmarks might make his task more difficult. For an hour or more he was at work, returning at last with his feet heavy with snow and his features as inscrutable as ever. "I think that I have seen now all that there is to see, Mr. Holder," said he; "I can serve you best by returning to my rooms." "But the gems, Mr. Holmes. Where are they?" "I cannot tell." The banker wrung his hands. "I shall never see them again!" he cried. "And my son? You give me hopes?" "My opinion is in no way altered." "Then, for God's sake, what was this dark business which was acted in my house last night?" "If you can call upon me at my Baker Street rooms to-morrow morning between nine and ten I shall be happy to do what I can to make it clearer. I understand that you give me carte blanche to act for you, provided only that I get back the gems, and that you place no limit on the sum I may draw." "I would give my fortune to have them back." "Very good. I shall look into the matter between this and then. Good-bye; it is just possible that I may have to come over here again before evening." It was obvious to me that my companion's mind was now made up about the case, although what his conclusions were was more than I could even dimly imagine. Several times during our homeward journey I endeavoured to sound him upon the point, but he always glided away to some other topic, until at last I gave it over in despair. It was not yet three when we found ourselves in our rooms once more. He hurried to his chamber and was down again in a few minutes dressed as a common loafer. With his collar turned up, his shiny, seedy coat, his red cravat, and his worn boots, he was a perfect sample of the class. "I think that this should do," said he, glancing into the glass above the fireplace. "I only wish that you could come with me, Watson, but I fear that it won't do. I may be on the trail in this matter, or I may be following a will-o'-the-wisp, but I shall soon know which it is. I hope that I may be back in a few hours." He cut a slice of beef from the joint upon the sideboard, sandwiched it between two rounds of bread, and thrusting this rude meal into his pocket he started off upon his expedition. I had just finished my tea when he returned, evidently in excellent spirits, swinging an old elastic-sided boot in his hand. He chucked it down into a corner and helped himself to a cup of tea. "I only looked in as I passed," said he. "I am going right on." "Where to?" "Oh, to the other side of the West End. It may be some time before I get back. Don't wait up for me in case I should be late." "How are you getting on?" "Oh, so so. Nothing to complain of. I have been out to Streatham since I saw you last, but I did not call at the house. It is a very sweet little problem, and I would not have missed it for a good deal. However, I must not sit gossiping here, but must get these disreputable clothes off and return to my highly respectable self." I could see by his manner that he had stronger reasons for satisfaction than his words alone would imply. His eyes twinkled, and there was even a touch of colour upon his sallow cheeks. He hastened upstairs, and a few minutes later I heard the slam of the hall door, which told me that he was off once more upon his congenial hunt. I waited until midnight, but there was no sign of his return, so I retired to my room. It was no uncommon thing for him to be away for days and nights on end when he was hot upon a scent, so that his lateness caused me no surprise. I do not know at what hour he came in, but when I came down to breakfast in the morning there he was with a cup of coffee in one hand and the paper in the other, as fresh and trim as possible. "You will excuse my beginning without you, Watson," said he, "but you remember that our client has rather an early appointment this morning." "Why, it is after nine now," I answered. "I should not be surprised if that were he. I thought I heard a ring." It was, indeed, our friend the financier. I was shocked by the change which had come over him, for his face which was naturally of a broad and massive mould, was now pinched and fallen in, while his hair seemed to me at least a shade whiter. He entered with a weariness and lethargy which was even more painful than his violence of the morning before, and he dropped heavily into the armchair which I pushed forward for him. "I do not know what I have done to be so severely tried," said he. "Only two days ago I was a happy and prosperous man, without a care in the world. Now I am left to a lonely and dishonoured age. One sorrow comes close upon the heels of another. My niece, Mary, has deserted me." "Deserted you?" "Yes. Her bed this morning had not been slept in, her room was empty, and a note for me lay upon the hall table. I had said to her last night, in sorrow and not in anger, that if she had married my boy all might have been well with him. Perhaps it was thoughtless of me to say so. It is to that remark that she refers in this note: "'MY DEAREST UNCLE:--I feel that I have brought trouble upon you, and that if I had acted differently this terrible misfortune might never have occurred. I cannot, with this thought in my mind, ever again be happy under your roof, and I feel that I must leave you forever. Do not worry about my future, for that is provided for; and, above all, do not search for me, for it will be fruitless labour and an ill-service to me. In life or in death, I am ever your loving,--MARY.' "What could she mean by that note, Mr. Holmes? Do you think it points to suicide?" "No, no, nothing of the kind. It is perhaps the best possible solution. I trust, Mr. Holder, that you are nearing the end of your troubles." "Ha! You say so! You have heard something, Mr. Holmes; you have learned something! Where are the gems?" "You would not think 1000 pounds apiece an excessive sum for them?" "I would pay ten." "That would be unnecessary. Three thousand will cover the matter. And there is a little reward, I fancy. Have you your check-book? Here is a pen. Better make it out for 4000 pounds." With a dazed face the banker made out the required check. Holmes walked over to his desk, took out a little triangular piece of gold with three gems in it, and threw it down upon the table. With a shriek of joy our client clutched it up. "You have it!" he gasped. "I am saved! I am saved!" The reaction of joy was as passionate as his grief had been, and he hugged his recovered gems to his bosom. "There is one other thing you owe, Mr. Holder," said Sherlock Holmes rather sternly. "Owe!" He caught up a pen. "Name the sum, and I will pay it." "No, the debt is not to me. You owe a very humble apology to that noble lad, your son, who has carried himself in this matter as I should be proud to see my own son do, should I ever chance to have one." "Then it was not Arthur who took them?" "I told you yesterday, and I repeat to-day, that it was not." "You are sure of it! Then let us hurry to him at once to let him know that the truth is known." "He knows it already. When I had cleared it all up I had an interview with him, and finding that he would not tell me the story, I told it to him, on which he had to confess that I was right and to add the very few details which were not yet quite clear to me. Your news of this morning, however, may open his lips." "For heaven's sake, tell me, then, what is this extraordinary mystery!" "I will do so, and I will show you the steps by which I reached it. And let me say to you, first, that which it is hardest for me to say and for you to hear: there has been an understanding between Sir George Burnwell and your niece Mary. They have now fled together." "My Mary? Impossible!" "It is unfortunately more than possible; it is certain. Neither you nor your son knew the true character of this man when you admitted him into your family circle. He is one of the most dangerous men in England--a ruined gambler, an absolutely desperate villain, a man without heart or conscience. Your niece knew nothing of such men. When he breathed his vows to her, as he had done to a hundred before her, she flattered herself that she alone had touched his heart. The devil knows best what he said, but at least she became his tool and was in the habit of seeing him nearly every evening." "I cannot, and I will not, believe it!" cried the banker with an ashen face. "I will tell you, then, what occurred in your house last night. Your niece, when you had, as she thought, gone to your room, slipped down and talked to her lover through the window which leads into the stable lane. His footmarks had pressed right through the snow, so long had he stood there. She told him of the coronet. His wicked lust for gold kindled at the news, and he bent her to his will. I have no doubt that she loved you, but there are women in whom the love of a lover extinguishes all other loves, and I think that she must have been one. She had hardly listened to his instructions when she saw you coming downstairs, on which she closed the window rapidly and told you about one of the servants' escapade with her wooden-legged lover, which was all perfectly true. "Your boy, Arthur, went to bed after his interview with you but he slept badly on account of his uneasiness about his club debts. In the middle of the night he heard a soft tread pass his door, so he rose and, looking out, was surprised to see his cousin walking very stealthily along the passage until she disappeared into your dressing-room. Petrified with astonishment, the lad slipped on some clothes and waited there in the dark to see what would come of this strange affair. Presently she emerged from the room again, and in the light of the passage-lamp your son saw that she carried the precious coronet in her hands. She passed down the stairs, and he, thrilling with horror, ran along and slipped behind the curtain near your door, whence he could see what passed in the hall beneath. He saw her stealthily open the window, hand out the coronet to someone in the gloom, and then closing it once more hurry back to her room, passing quite close to where he stood hid behind the curtain. "As long as she was on the scene he could not take any action without a horrible exposure of the woman whom he loved. But the instant that she was gone he realised how crushing a misfortune this would be for you, and how all-important it was to set it right. He rushed down, just as he was, in his bare feet, opened the window, sprang out into the snow, and ran down the lane, where he could see a dark figure in the moonlight. Sir George Burnwell tried to get away, but Arthur caught him, and there was a struggle between them, your lad tugging at one side of the coronet, and his opponent at the other. In the scuffle, your son struck Sir George and cut him over the eye. Then something suddenly snapped, and your son, finding that he had the coronet in his hands, rushed back, closed the window, ascended to your room, and had just observed that the coronet had been twisted in the struggle and was endeavouring to straighten it when you appeared upon the scene." "Is it possible?" gasped the banker. "You then roused his anger by calling him names at a moment when he felt that he had deserved your warmest thanks. He could not explain the true state of affairs without betraying one who certainly deserved little enough consideration at his hands. He took the more chivalrous view, however, and preserved her secret." "And that was why she shrieked and fainted when she saw the coronet," cried Mr. Holder. "Oh, my God! what a blind fool I have been! And his asking to be allowed to go out for five minutes! The dear fellow wanted to see if the missing piece were at the scene of the struggle. How cruelly I have misjudged him!" "When I arrived at the house," continued Holmes, "I at once went very carefully round it to observe if there were any traces in the snow which might help me. I knew that none had fallen since the evening before, and also that there had been a strong frost to preserve impressions. I passed along the tradesmen's path, but found it all trampled down and indistinguishable. Just beyond it, however, at the far side of the kitchen door, a woman had stood and talked with a man, whose round impressions on one side showed that he had a wooden leg. I could even tell that they had been disturbed, for the woman had run back swiftly to the door, as was shown by the deep toe and light heel marks, while Wooden-leg had waited a little, and then had gone away. I thought at the time that this might be the maid and her sweetheart, of whom you had already spoken to me, and inquiry showed it was so. I passed round the garden without seeing anything more than random tracks, which I took to be the police; but when I got into the stable lane a very long and complex story was written in the snow in front of me. "There was a double line of tracks of a booted man, and a second double line which I saw with delight belonged to a man with naked feet. I was at once convinced from what you had told me that the latter was your son. The first had walked both ways, but the other had run swiftly, and as his tread was marked in places over the depression of the boot, it was obvious that he had passed after the other. I followed them up and found they led to the hall window, where Boots had worn all the snow away while waiting. Then I walked to the other end, which was a hundred yards or more down the lane. I saw where Boots had faced round, where the snow was cut up as though there had been a struggle, and, finally, where a few drops of blood had fallen, to show me that I was not mistaken. Boots had then run down the lane, and another little smudge of blood showed that it was he who had been hurt. When he came to the highroad at the other end, I found that the pavement had been cleared, so there was an end to that clue. "On entering the house, however, I examined, as you remember, the sill and framework of the hall window with my lens, and I could at once see that someone had passed out. I could distinguish the outline of an instep where the wet foot had been placed in coming in. I was then beginning to be able to form an opinion as to what had occurred. A man had waited outside the window; someone had brought the gems; the deed had been overseen by your son; he had pursued the thief; had struggled with him; they had each tugged at the coronet, their united strength causing injuries which neither alone could have effected. He had returned with the prize, but had left a fragment in the grasp of his opponent. So far I was clear. The question now was, who was the man and who was it brought him the coronet? "It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. Now, I knew that it was not you who had brought it down, so there only remained your niece and the maids. But if it were the maids, why should your son allow himself to be accused in their place? There could be no possible reason. As he loved his cousin, however, there was an excellent explanation why he should retain her secret--the more so as the secret was a disgraceful one. When I remembered that you had seen her at that window, and how she had fainted on seeing the coronet again, my conjecture became a certainty. "And who could it be who was her confederate? A lover evidently, for who else could outweigh the love and gratitude which she must feel to you? I knew that you went out little, and that your circle of friends was a very limited one. But among them was Sir George Burnwell. I had heard of him before as being a man of evil reputation among women. It must have been he who wore those boots and retained the missing gems. Even though he knew that Arthur had discovered him, he might still flatter himself that he was safe, for the lad could not say a word without compromising his own family. "Well, your own good sense will suggest what measures I took next. I went in the shape of a loafer to Sir George's house, managed to pick up an acquaintance with his valet, learned that his master had cut his head the night before, and, finally, at the expense of six shillings, made all sure by buying a pair of his cast-off shoes. With these I journeyed down to Streatham and saw that they exactly fitted the tracks." "I saw an ill-dressed vagabond in the lane yesterday evening," said Mr. Holder. "Precisely. It was I. I found that I had my man, so I came home and changed my clothes. It was a delicate part which I had to play then, for I saw that a prosecution must be avoided to avert scandal, and I knew that so astute a villain would see that our hands were tied in the matter. I went and saw him. At first, of course, he denied everything. But when I gave him every particular that had occurred, he tried to bluster and took down a life-preserver from the wall. I knew my man, however, and I clapped a pistol to his head before he could strike. Then he became a little more reasonable. I told him that we would give him a price for the stones he held--1000 pounds apiece. That brought out the first signs of grief that he had shown. 'Why, dash it all!' said he, 'I've let them go at six hundred for the three!' I soon managed to get the address of the receiver who had them, on promising him that there would be no prosecution. Off I set to him, and after much chaffering I got our stones at 1000 pounds apiece. Then I looked in upon your son, told him that all was right, and eventually got to my bed about two o'clock, after what I may call a really hard day's work." "A day which has saved England from a great public scandal," said the banker, rising. "Sir, I cannot find words to thank you, but you shall not find me ungrateful for what you have done. Your skill has indeed exceeded all that I have heard of it. And now I must fly to my dear boy to apologise to him for the wrong which I have done him. As to what you tell me of poor Mary, it goes to my very heart. Not even your skill can inform me where she is now." "I think that we may safely say," returned Holmes, "that she is wherever Sir George Burnwell is. It is equally certain, too, that whatever her sins are, they will soon receive a more than sufficient punishment." XII. THE ADVENTURE OF THE COPPER BEECHES "To the man who loves art for its own sake," remarked Sherlock Holmes, tossing aside the advertisement sheet of the Daily Telegraph, "it is frequently in its least important and lowliest manifestations that the keenest pleasure is to be derived. It is pleasant to me to observe, Watson, that you have so far grasped this truth that in these little records of our cases which you have been good enough to draw up, and, I am bound to say, occasionally to embellish, you have given prominence not so much to the many causes célèbres and sensational trials in which I have figured but rather to those incidents which may have been trivial in themselves, but which have given room for those faculties of deduction and of logical synthesis which I have made my special province." "And yet," said I, smiling, "I cannot quite hold myself absolved from the charge of sensationalism which has been urged against my records." "You have erred, perhaps," he observed, taking up a glowing cinder with the tongs and lighting with it the long cherry-wood pipe which was wont to replace his clay when he was in a disputatious rather than a meditative mood--"you have erred perhaps in attempting to put colour and life into each of your statements instead of confining yourself to the task of placing upon record that severe reasoning from cause to effect which is really the only notable feature about the thing." "It seems to me that I have done you full justice in the matter," I remarked with some coldness, for I was repelled by the egotism which I had more than once observed to be a strong factor in my friend's singular character. "No, it is not selfishness or conceit," said he, answering, as was his wont, my thoughts rather than my words. "If I claim full justice for my art, it is because it is an impersonal thing--a thing beyond myself. Crime is common. Logic is rare. Therefore it is upon the logic rather than upon the crime that you should dwell. You have degraded what should have been a course of lectures into a series of tales." It was a cold morning of the early spring, and we sat after breakfast on either side of a cheery fire in the old room at Baker Street. A thick fog rolled down between the lines of dun-coloured houses, and the opposing windows loomed like dark, shapeless blurs through the heavy yellow wreaths. Our gas was lit and shone on the white cloth and glimmer of china and metal, for the table had not been cleared yet. Sherlock Holmes had been silent all the morning, dipping continuously into the advertisement columns of a succession of papers until at last, having apparently given up his search, he had emerged in no very sweet temper to lecture me upon my literary shortcomings. "At the same time," he remarked after a pause, during which he had sat puffing at his long pipe and gazing down into the fire, "you can hardly be open to a charge of sensationalism, for out of these cases which you have been so kind as to interest yourself in, a fair proportion do not treat of crime, in its legal sense, at all. The small matter in which I endeavoured to help the King of Bohemia, the singular experience of Miss Mary Sutherland, the problem connected with the man with the twisted lip, and the incident of the noble bachelor, were all matters which are outside the pale of the law. But in avoiding the sensational, I fear that you may have bordered on the trivial." "The end may have been so," I answered, "but the methods I hold to have been novel and of interest." "Pshaw, my dear fellow, what do the public, the great unobservant public, who could hardly tell a weaver by his tooth or a compositor by his left thumb, care about the finer shades of analysis and deduction! But, indeed, if you are trivial, I cannot blame you, for the days of the great cases are past. Man, or at least criminal man, has lost all enterprise and originality. As to my own little practice, it seems to be degenerating into an agency for recovering lost lead pencils and giving advice to young ladies from boarding-schools. I think that I have touched bottom at last, however. This note I had this morning marks my zero-point, I fancy. Read it!" He tossed a crumpled letter across to me. It was dated from Montague Place upon the preceding evening, and ran thus: "DEAR MR. HOLMES:--I am very anxious to consult you as to whether I should or should not accept a situation which has been offered to me as governess. I shall call at half-past ten to-morrow if I do not inconvenience you. Yours faithfully, "VIOLET HUNTER." "Do you know the young lady?" I asked. "Not I." "It is half-past ten now." "Yes, and I have no doubt that is her ring." "It may turn out to be of more interest than you think. You remember that the affair of the blue carbuncle, which appeared to be a mere whim at first, developed into a serious investigation. It may be so in this case, also." "Well, let us hope so. But our doubts will very soon be solved, for here, unless I am much mistaken, is the person in question." As he spoke the door opened and a young lady entered the room. She was plainly but neatly dressed, with a bright, quick face, freckled like a plover's egg, and with the brisk manner of a woman who has had her own way to make in the world. "You will excuse my troubling you, I am sure," said she, as my companion rose to greet her, "but I have had a very strange experience, and as I have no parents or relations of any sort from whom I could ask advice, I thought that perhaps you would be kind enough to tell me what I should do." "Pray take a seat, Miss Hunter. I shall be happy to do anything that I can to serve you." I could see that Holmes was favourably impressed by the manner and speech of his new client. He looked her over in his searching fashion, and then composed himself, with his lids drooping and his finger-tips together, to listen to her story. "I have been a governess for five years," said she, "in the family of Colonel Spence Munro, but two months ago the colonel received an appointment at Halifax, in Nova Scotia, and took his children over to America with him, so that I found myself without a situation. I advertised, and I answered advertisements, but without success. At last the little money which I had saved began to run short, and I was at my wit's end as to what I should do. "There is a well-known agency for governesses in the West End called Westaway's, and there I used to call about once a week in order to see whether anything had turned up which might suit me. Westaway was the name of the founder of the business, but it is really managed by Miss Stoper. She sits in her own little office, and the ladies who are seeking employment wait in an anteroom, and are then shown in one by one, when she consults her ledgers and sees whether she has anything which would suit them. "Well, when I called last week I was shown into the little office as usual, but I found that Miss Stoper was not alone. A prodigiously stout man with a very smiling face and a great heavy chin which rolled down in fold upon fold over his throat sat at her elbow with a pair of glasses on his nose, looking very earnestly at the ladies who entered. As I came in he gave quite a jump in his chair and turned quickly to Miss Stoper. "'That will do,' said he; 'I could not ask for anything better. Capital! capital!' He seemed quite enthusiastic and rubbed his hands together in the most genial fashion. He was such a comfortable-looking man that it was quite a pleasure to look at him. "'You are looking for a situation, miss?' he asked. "'Yes, sir.' "'As governess?' "'Yes, sir.' "'And what salary do you ask?' "'I had 4 pounds a month in my last place with Colonel Spence Munro.' "'Oh, tut, tut! sweating--rank sweating!' he cried, throwing his fat hands out into the air like a man who is in a boiling passion. 'How could anyone offer so pitiful a sum to a lady with such attractions and accomplishments?' "'My accomplishments, sir, may be less than you imagine,' said I. 'A little French, a little German, music, and drawing--' "'Tut, tut!' he cried. 'This is all quite beside the question. The point is, have you or have you not the bearing and deportment of a lady? There it is in a nutshell. If you have not, you are not fitted for the rearing of a child who may some day play a considerable part in the history of the country. But if you have why, then, how could any gentleman ask you to condescend to accept anything under the three figures? Your salary with me, madam, would commence at 100 pounds a year.' "You may imagine, Mr. Holmes, that to me, destitute as I was, such an offer seemed almost too good to be true. The gentleman, however, seeing perhaps the look of incredulity upon my face, opened a pocket-book and took out a note. "'It is also my custom,' said he, smiling in the most pleasant fashion until his eyes were just two little shining slits amid the white creases of his face, 'to advance to my young ladies half their salary beforehand, so that they may meet any little expenses of their journey and their wardrobe.' "It seemed to me that I had never met so fascinating and so thoughtful a man. As I was already in debt to my tradesmen, the advance was a great convenience, and yet there was something unnatural about the whole transaction which made me wish to know a little more before I quite committed myself. "'May I ask where you live, sir?' said I. "'Hampshire. Charming rural place. The Copper Beeches, five miles on the far side of Winchester. It is the most lovely country, my dear young lady, and the dearest old country-house.' "'And my duties, sir? I should be glad to know what they would be.' "'One child--one dear little romper just six years old. Oh, if you could see him killing cockroaches with a slipper! Smack! smack! smack! Three gone before you could wink!' He leaned back in his chair and laughed his eyes into his head again. "I was a little startled at the nature of the child's amusement, but the father's laughter made me think that perhaps he was joking. "'My sole duties, then,' I asked, 'are to take charge of a single child?' "'No, no, not the sole, not the sole, my dear young lady,' he cried. 'Your duty would be, as I am sure your good sense would suggest, to obey any little commands my wife might give, provided always that they were such commands as a lady might with propriety obey. You see no difficulty, heh?' "'I should be happy to make myself useful.' "'Quite so. In dress now, for example. We are faddy people, you know--faddy but kind-hearted. If you were asked to wear any dress which we might give you, you would not object to our little whim. Heh?' "'No,' said I, considerably astonished at his words. "'Or to sit here, or sit there, that would not be offensive to you?' "'Oh, no.' "'Or to cut your hair quite short before you come to us?' "I could hardly believe my ears. As you may observe, Mr. Holmes, my hair is somewhat luxuriant, and of a rather peculiar tint of chestnut. It has been considered artistic. I could not dream of sacrificing it in this offhand fashion. "'I am afraid that that is quite impossible,' said I. He had been watching me eagerly out of his small eyes, and I could see a shadow pass over his face as I spoke. "'I am afraid that it is quite essential,' said he. 'It is a little fancy of my wife's, and ladies' fancies, you know, madam, ladies' fancies must be consulted. And so you won't cut your hair?' "'No, sir, I really could not,' I answered firmly. "'Ah, very well; then that quite settles the matter. It is a pity, because in other respects you would really have done very nicely. In that case, Miss Stoper, I had best inspect a few more of your young ladies.' "The manageress had sat all this while busy with her papers without a word to either of us, but she glanced at me now with so much annoyance upon her face that I could not help suspecting that she had lost a handsome commission through my refusal. "'Do you desire your name to be kept upon the books?' she asked. "'If you please, Miss Stoper.' "'Well, really, it seems rather useless, since you refuse the most excellent offers in this fashion,' said she sharply. 'You can hardly expect us to exert ourselves to find another such opening for you. Good-day to you, Miss Hunter.' She struck a gong upon the table, and I was shown out by the page. "Well, Mr. Holmes, when I got back to my lodgings and found little enough in the cupboard, and two or three bills upon the table, I began to ask myself whether I had not done a very foolish thing. After all, if these people had strange fads and expected obedience on the most extraordinary matters, they were at least ready to pay for their eccentricity. Very few governesses in England are getting 100 pounds a year. Besides, what use was my hair to me? Many people are improved by wearing it short and perhaps I should be among the number. Next day I was inclined to think that I had made a mistake, and by the day after I was sure of it. I had almost overcome my pride so far as to go back to the agency and inquire whether the place was still open when I received this letter from the gentleman himself. I have it here and I will read it to you: "'The Copper Beeches, near Winchester. "'DEAR MISS HUNTER:--Miss Stoper has very kindly given me your address, and I write from here to ask you whether you have reconsidered your decision. My wife is very anxious that you should come, for she has been much attracted by my description of you. We are willing to give 30 pounds a quarter, or 120 pounds a year, so as to recompense you for any little inconvenience which our fads may cause you. They are not very exacting, after all. My wife is fond of a particular shade of electric blue and would like you to wear such a dress indoors in the morning. You need not, however, go to the expense of purchasing one, as we have one belonging to my dear daughter Alice (now in Philadelphia), which would, I should think, fit you very well. Then, as to sitting here or there, or amusing yourself in any manner indicated, that need cause you no inconvenience. As regards your hair, it is no doubt a pity, especially as I could not help remarking its beauty during our short interview, but I am afraid that I must remain firm upon this point, and I only hope that the increased salary may recompense you for the loss. Your duties, as far as the child is concerned, are very light. Now do try to come, and I shall meet you with the dog-cart at Winchester. Let me know your train. Yours faithfully, JEPHRO RUCASTLE.' "That is the letter which I have just received, Mr. Holmes, and my mind is made up that I will accept it. I thought, however, that before taking the final step I should like to submit the whole matter to your consideration." "Well, Miss Hunter, if your mind is made up, that settles the question," said Holmes, smiling. "But you would not advise me to refuse?" "I confess that it is not the situation which I should like to see a sister of mine apply for." "What is the meaning of it all, Mr. Holmes?" "Ah, I have no data. I cannot tell. Perhaps you have yourself formed some opinion?" "Well, there seems to me to be only one possible solution. Mr. Rucastle seemed to be a very kind, good-natured man. Is it not possible that his wife is a lunatic, that he desires to keep the matter quiet for fear she should be taken to an asylum, and that he humours her fancies in every way in order to prevent an outbreak?" "That is a possible solution--in fact, as matters stand, it is the most probable one. But in any case it does not seem to be a nice household for a young lady." "But the money, Mr. Holmes, the money!" "Well, yes, of course the pay is good--too good. That is what makes me uneasy. Why should they give you 120 pounds a year, when they could have their pick for 40 pounds? There must be some strong reason behind." "I thought that if I told you the circumstances you would understand afterwards if I wanted your help. I should feel so much stronger if I felt that you were at the back of me." "Oh, you may carry that feeling away with you. I assure you that your little problem promises to be the most interesting which has come my way for some months. There is something distinctly novel about some of the features. If you should find yourself in doubt or in danger--" "Danger! What danger do you foresee?" Holmes shook his head gravely. "It would cease to be a danger if we could define it," said he. "But at any time, day or night, a telegram would bring me down to your help." "That is enough." She rose briskly from her chair with the anxiety all swept from her face. "I shall go down to Hampshire quite easy in my mind now. I shall write to Mr. Rucastle at once, sacrifice my poor hair to-night, and start for Winchester to-morrow." With a few grateful words to Holmes she bade us both good-night and bustled off upon her way. "At least," said I as we heard her quick, firm steps descending the stairs, "she seems to be a young lady who is very well able to take care of herself." "And she would need to be," said Holmes gravely. "I am much mistaken if we do not hear from her before many days are past." It was not very long before my friend's prediction was fulfilled. A fortnight went by, during which I frequently found my thoughts turning in her direction and wondering what strange side-alley of human experience this lonely woman had strayed into. The unusual salary, the curious conditions, the light duties, all pointed to something abnormal, though whether a fad or a plot, or whether the man were a philanthropist or a villain, it was quite beyond my powers to determine. As to Holmes, I observed that he sat frequently for half an hour on end, with knitted brows and an abstracted air, but he swept the matter away with a wave of his hand when I mentioned it. "Data! data! data!" he cried impatiently. "I can't make bricks without clay." And yet he would always wind up by muttering that no sister of his should ever have accepted such a situation. The telegram which we eventually received came late one night just as I was thinking of turning in and Holmes was settling down to one of those all-night chemical researches which he frequently indulged in, when I would leave him stooping over a retort and a test-tube at night and find him in the same position when I came down to breakfast in the morning. He opened the yellow envelope, and then, glancing at the message, threw it across to me. "Just look up the trains in Bradshaw," said he, and turned back to his chemical studies. The summons was a brief and urgent one. "Please be at the Black Swan Hotel at Winchester at midday to-morrow," it said. "Do come! I am at my wit's end. HUNTER." "Will you come with me?" asked Holmes, glancing up. "I should wish to." "Just look it up, then." "There is a train at half-past nine," said I, glancing over my Bradshaw. "It is due at Winchester at 11:30." "That will do very nicely. Then perhaps I had better postpone my analysis of the acetones, as we may need to be at our best in the morning." By eleven o'clock the next day we were well upon our way to the old English capital. Holmes had been buried in the morning papers all the way down, but after we had passed the Hampshire border he threw them down and began to admire the scenery. It was an ideal spring day, a light blue sky, flecked with little fleecy white clouds drifting across from west to east. The sun was shining very brightly, and yet there was an exhilarating nip in the air, which set an edge to a man's energy. All over the countryside, away to the rolling hills around Aldershot, the little red and grey roofs of the farm-steadings peeped out from amid the light green of the new foliage. "Are they not fresh and beautiful?" I cried with all the enthusiasm of a man fresh from the fogs of Baker Street. But Holmes shook his head gravely. "Do you know, Watson," said he, "that it is one of the curses of a mind with a turn like mine that I must look at everything with reference to my own special subject. You look at these scattered houses, and you are impressed by their beauty. I look at them, and the only thought which comes to me is a feeling of their isolation and of the impunity with which crime may be committed there." "Good heavens!" I cried. "Who would associate crime with these dear old homesteads?" "They always fill me with a certain horror. It is my belief, Watson, founded upon my experience, that the lowest and vilest alleys in London do not present a more dreadful record of sin than does the smiling and beautiful countryside." "You horrify me!" "But the reason is very obvious. The pressure of public opinion can do in the town what the law cannot accomplish. There is no lane so vile that the scream of a tortured child, or the thud of a drunkard's blow, does not beget sympathy and indignation among the neighbours, and then the whole machinery of justice is ever so close that a word of complaint can set it going, and there is but a step between the crime and the dock. But look at these lonely houses, each in its own fields, filled for the most part with poor ignorant folk who know little of the law. Think of the deeds of hellish cruelty, the hidden wickedness which may go on, year in, year out, in such places, and none the wiser. Had this lady who appeals to us for help gone to live in Winchester, I should never have had a fear for her. It is the five miles of country which makes the danger. Still, it is clear that she is not personally threatened." "No. If she can come to Winchester to meet us she can get away." "Quite so. She has her freedom." "What CAN be the matter, then? Can you suggest no explanation?" "I have devised seven separate explanations, each of which would cover the facts as far as we know them. But which of these is correct can only be determined by the fresh information which we shall no doubt find waiting for us. Well, there is the tower of the cathedral, and we shall soon learn all that Miss Hunter has to tell." The Black Swan is an inn of repute in the High Street, at no distance from the station, and there we found the young lady waiting for us. She had engaged a sitting-room, and our lunch awaited us upon the table. "I am so delighted that you have come," she said earnestly. "It is so very kind of you both; but indeed I do not know what I should do. Your advice will be altogether invaluable to me." "Pray tell us what has happened to you." "I will do so, and I must be quick, for I have promised Mr. Rucastle to be back before three. I got his leave to come into town this morning, though he little knew for what purpose." "Let us have everything in its due order." Holmes thrust his long thin legs out towards the fire and composed himself to listen. "In the first place, I may say that I have met, on the whole, with no actual ill-treatment from Mr. and Mrs. Rucastle. It is only fair to them to say that. But I cannot understand them, and I am not easy in my mind about them." "What can you not understand?" "Their reasons for their conduct. But you shall have it all just as it occurred. When I came down, Mr. Rucastle met me here and drove me in his dog-cart to the Copper Beeches. It is, as he said, beautifully situated, but it is not beautiful in itself, for it is a large square block of a house, whitewashed, but all stained and streaked with damp and bad weather. There are grounds round it, woods on three sides, and on the fourth a field which slopes down to the Southampton highroad, which curves past about a hundred yards from the front door. This ground in front belongs to the house, but the woods all round are part of Lord Southerton's preserves. A clump of copper beeches immediately in front of the hall door has given its name to the place. "I was driven over by my employer, who was as amiable as ever, and was introduced by him that evening to his wife and the child. There was no truth, Mr. Holmes, in the conjecture which seemed to us to be probable in your rooms at Baker Street. Mrs. Rucastle is not mad. I found her to be a silent, pale-faced woman, much younger than her husband, not more than thirty, I should think, while he can hardly be less than forty-five. From their conversation I have gathered that they have been married about seven years, that he was a widower, and that his only child by the first wife was the daughter who has gone to Philadelphia. Mr. Rucastle told me in private that the reason why she had left them was that she had an unreasoning aversion to her stepmother. As the daughter could not have been less than twenty, I can quite imagine that her position must have been uncomfortable with her father's young wife. "Mrs. Rucastle seemed to me to be colourless in mind as well as in feature. She impressed me neither favourably nor the reverse. She was a nonentity. It was easy to see that she was passionately devoted both to her husband and to her little son. Her light grey eyes wandered continually from one to the other, noting every little want and forestalling it if possible. He was kind to her also in his bluff, boisterous fashion, and on the whole they seemed to be a happy couple. And yet she had some secret sorrow, this woman. She would often be lost in deep thought, with the saddest look upon her face. More than once I have surprised her in tears. I have thought sometimes that it was the disposition of her child which weighed upon her mind, for I have never met so utterly spoiled and so ill-natured a little creature. He is small for his age, with a head which is quite disproportionately large. His whole life appears to be spent in an alternation between savage fits of passion and gloomy intervals of sulking. Giving pain to any creature weaker than himself seems to be his one idea of amusement, and he shows quite remarkable talent in planning the capture of mice, little birds, and insects. But I would rather not talk about the creature, Mr. Holmes, and, indeed, he has little to do with my story." "I am glad of all details," remarked my friend, "whether they seem to you to be relevant or not." "I shall try not to miss anything of importance. The one unpleasant thing about the house, which struck me at once, was the appearance and conduct of the servants. There are only two, a man and his wife. Toller, for that is his name, is a rough, uncouth man, with grizzled hair and whiskers, and a perpetual smell of drink. Twice since I have been with them he has been quite drunk, and yet Mr. Rucastle seemed to take no notice of it. His wife is a very tall and strong woman with a sour face, as silent as Mrs. Rucastle and much less amiable. They are a most unpleasant couple, but fortunately I spend most of my time in the nursery and my own room, which are next to each other in one corner of the building. "For two days after my arrival at the Copper Beeches my life was very quiet; on the third, Mrs. Rucastle came down just after breakfast and whispered something to her husband. "'Oh, yes,' said he, turning to me, 'we are very much obliged to you, Miss Hunter, for falling in with our whims so far as to cut your hair. I assure you that it has not detracted in the tiniest iota from your appearance. We shall now see how the electric-blue dress will become you. You will find it laid out upon the bed in your room, and if you would be so good as to put it on we should both be extremely obliged.' "The dress which I found waiting for me was of a peculiar shade of blue. It was of excellent material, a sort of beige, but it bore unmistakable signs of having been worn before. It could not have been a better fit if I had been measured for it. Both Mr. and Mrs. Rucastle expressed a delight at the look of it, which seemed quite exaggerated in its vehemence. They were waiting for me in the drawing-room, which is a very large room, stretching along the entire front of the house, with three long windows reaching down to the floor. A chair had been placed close to the central window, with its back turned towards it. In this I was asked to sit, and then Mr. Rucastle, walking up and down on the other side of the room, began to tell me a series of the funniest stories that I have ever listened to. You cannot imagine how comical he was, and I laughed until I was quite weary. Mrs. Rucastle, however, who has evidently no sense of humour, never so much as smiled, but sat with her hands in her lap, and a sad, anxious look upon her face. After an hour or so, Mr. Rucastle suddenly remarked that it was time to commence the duties of the day, and that I might change my dress and go to little Edward in the nursery. "Two days later this same performance was gone through under exactly similar circumstances. Again I changed my dress, again I sat in the window, and again I laughed very heartily at the funny stories of which my employer had an immense répertoire, and which he told inimitably. Then he handed me a yellow-backed novel, and moving my chair a little sideways, that my own shadow might not fall upon the page, he begged me to read aloud to him. I read for about ten minutes, beginning in the heart of a chapter, and then suddenly, in the middle of a sentence, he ordered me to cease and to change my dress. "You can easily imagine, Mr. Holmes, how curious I became as to what the meaning of this extraordinary performance could possibly be. They were always very careful, I observed, to turn my face away from the window, so that I became consumed with the desire to see what was going on behind my back. At first it seemed to be impossible, but I soon devised a means. My hand-mirror had been broken, so a happy thought seized me, and I concealed a piece of the glass in my handkerchief. On the next occasion, in the midst of my laughter, I put my handkerchief up to my eyes, and was able with a little management to see all that there was behind me. I confess that I was disappointed. There was nothing. At least that was my first impression. At the second glance, however, I perceived that there was a man standing in the Southampton Road, a small bearded man in a grey suit, who seemed to be looking in my direction. The road is an important highway, and there are usually people there. This man, however, was leaning against the railings which bordered our field and was looking earnestly up. I lowered my handkerchief and glanced at Mrs. Rucastle to find her eyes fixed upon me with a most searching gaze. She said nothing, but I am convinced that she had divined that I had a mirror in my hand and had seen what was behind me. She rose at once. "'Jephro,' said she, 'there is an impertinent fellow upon the road there who stares up at Miss Hunter.' "'No friend of yours, Miss Hunter?' he asked. "'No, I know no one in these parts.' "'Dear me! How very impertinent! Kindly turn round and motion to him to go away.' "'Surely it would be better to take no notice.' "'No, no, we should have him loitering here always. Kindly turn round and wave him away like that.' "I did as I was told, and at the same instant Mrs. Rucastle drew down the blind. That was a week ago, and from that time I have not sat again in the window, nor have I worn the blue dress, nor seen the man in the road." "Pray continue," said Holmes. "Your narrative promises to be a most interesting one." "You will find it rather disconnected, I fear, and there may prove to be little relation between the different incidents of which I speak. On the very first day that I was at the Copper Beeches, Mr. Rucastle took me to a small outhouse which stands near the kitchen door. As we approached it I heard the sharp rattling of a chain, and the sound as of a large animal moving about. "'Look in here!' said Mr. Rucastle, showing me a slit between two planks. 'Is he not a beauty?' "I looked through and was conscious of two glowing eyes, and of a vague figure huddled up in the darkness. "'Don't be frightened,' said my employer, laughing at the start which I had given. 'It's only Carlo, my mastiff. I call him mine, but really old Toller, my groom, is the only man who can do anything with him. We feed him once a day, and not too much then, so that he is always as keen as mustard. Toller lets him loose every night, and God help the trespasser whom he lays his fangs upon. For goodness' sake don't you ever on any pretext set your foot over the threshold at night, for it's as much as your life is worth.' "The warning was no idle one, for two nights later I happened to look out of my bedroom window about two o'clock in the morning. It was a beautiful moonlight night, and the lawn in front of the house was silvered over and almost as bright as day. I was standing, rapt in the peaceful beauty of the scene, when I was aware that something was moving under the shadow of the copper beeches. As it emerged into the moonshine I saw what it was. It was a giant dog, as large as a calf, tawny tinted, with hanging jowl, black muzzle, and huge projecting bones. It walked slowly across the lawn and vanished into the shadow upon the other side. That dreadful sentinel sent a chill to my heart which I do not think that any burglar could have done. "And now I have a very strange experience to tell you. I had, as you know, cut off my hair in London, and I had placed it in a great coil at the bottom of my trunk. One evening, after the child was in bed, I began to amuse myself by examining the furniture of my room and by rearranging my own little things. There was an old chest of drawers in the room, the two upper ones empty and open, the lower one locked. I had filled the first two with my linen, and as I had still much to pack away I was naturally annoyed at not having the use of the third drawer. It struck me that it might have been fastened by a mere oversight, so I took out my bunch of keys and tried to open it. The very first key fitted to perfection, and I drew the drawer open. There was only one thing in it, but I am sure that you would never guess what it was. It was my coil of hair. "I took it up and examined it. It was of the same peculiar tint, and the same thickness. But then the impossibility of the thing obtruded itself upon me. How could my hair have been locked in the drawer? With trembling hands I undid my trunk, turned out the contents, and drew from the bottom my own hair. I laid the two tresses together, and I assure you that they were identical. Was it not extraordinary? Puzzle as I would, I could make nothing at all of what it meant. I returned the strange hair to the drawer, and I said nothing of the matter to the Rucastles as I felt that I had put myself in the wrong by opening a drawer which they had locked. "I am naturally observant, as you may have remarked, Mr. Holmes, and I soon had a pretty good plan of the whole house in my head. There was one wing, however, which appeared not to be inhabited at all. A door which faced that which led into the quarters of the Tollers opened into this suite, but it was invariably locked. One day, however, as I ascended the stair, I met Mr. Rucastle coming out through this door, his keys in his hand, and a look on his face which made him a very different person to the round, jovial man to whom I was accustomed. His cheeks were red, his brow was all crinkled with anger, and the veins stood out at his temples with passion. He locked the door and hurried past me without a word or a look. "This aroused my curiosity, so when I went out for a walk in the grounds with my charge, I strolled round to the side from which I could see the windows of this part of the house. There were four of them in a row, three of which were simply dirty, while the fourth was shuttered up. They were evidently all deserted. As I strolled up and down, glancing at them occasionally, Mr. Rucastle came out to me, looking as merry and jovial as ever. "'Ah!' said he, 'you must not think me rude if I passed you without a word, my dear young lady. I was preoccupied with business matters.' "I assured him that I was not offended. 'By the way,' said I, 'you seem to have quite a suite of spare rooms up there, and one of them has the shutters up.' "He looked surprised and, as it seemed to me, a little startled at my remark. "'Photography is one of my hobbies,' said he. 'I have made my dark room up there. But, dear me! what an observant young lady we have come upon. Who would have believed it? Who would have ever believed it?' He spoke in a jesting tone, but there was no jest in his eyes as he looked at me. I read suspicion there and annoyance, but no jest. "Well, Mr. Holmes, from the moment that I understood that there was something about that suite of rooms which I was not to know, I was all on fire to go over them. It was not mere curiosity, though I have my share of that. It was more a feeling of duty--a feeling that some good might come from my penetrating to this place. They talk of woman's instinct; perhaps it was woman's instinct which gave me that feeling. At any rate, it was there, and I was keenly on the lookout for any chance to pass the forbidden door. "It was only yesterday that the chance came. I may tell you that, besides Mr. Rucastle, both Toller and his wife find something to do in these deserted rooms, and I once saw him carrying a large black linen bag with him through the door. Recently he has been drinking hard, and yesterday evening he was very drunk; and when I came upstairs there was the key in the door. I have no doubt at all that he had left it there. Mr. and Mrs. Rucastle were both downstairs, and the child was with them, so that I had an admirable opportunity. I turned the key gently in the lock, opened the door, and slipped through. "There was a little passage in front of me, unpapered and uncarpeted, which turned at a right angle at the farther end. Round this corner were three doors in a line, the first and third of which were open. They each led into an empty room, dusty and cheerless, with two windows in the one and one in the other, so thick with dirt that the evening light glimmered dimly through them. The centre door was closed, and across the outside of it had been fastened one of the broad bars of an iron bed, padlocked at one end to a ring in the wall, and fastened at the other with stout cord. The door itself was locked as well, and the key was not there. This barricaded door corresponded clearly with the shuttered window outside, and yet I could see by the glimmer from beneath it that the room was not in darkness. Evidently there was a skylight which let in light from above. As I stood in the passage gazing at the sinister door and wondering what secret it might veil, I suddenly heard the sound of steps within the room and saw a shadow pass backward and forward against the little slit of dim light which shone out from under the door. A mad, unreasoning terror rose up in me at the sight, Mr. Holmes. My overstrung nerves failed me suddenly, and I turned and ran--ran as though some dreadful hand were behind me clutching at the skirt of my dress. I rushed down the passage, through the door, and straight into the arms of Mr. Rucastle, who was waiting outside. "'So,' said he, smiling, 'it was you, then. I thought that it must be when I saw the door open.' "'Oh, I am so frightened!' I panted. "'My dear young lady! my dear young lady!'--you cannot think how caressing and soothing his manner was--'and what has frightened you, my dear young lady?' "But his voice was just a little too coaxing. He overdid it. I was keenly on my guard against him. "'I was foolish enough to go into the empty wing,' I answered. 'But it is so lonely and eerie in this dim light that I was frightened and ran out again. Oh, it is so dreadfully still in there!' "'Only that?' said he, looking at me keenly. "'Why, what did you think?' I asked. "'Why do you think that I lock this door?' "'I am sure that I do not know.' "'It is to keep people out who have no business there. Do you see?' He was still smiling in the most amiable manner. "'I am sure if I had known--' "'Well, then, you know now. And if you ever put your foot over that threshold again'--here in an instant the smile hardened into a grin of rage, and he glared down at me with the face of a demon--'I'll throw you to the mastiff.' "I was so terrified that I do not know what I did. I suppose that I must have rushed past him into my room. I remember nothing until I found myself lying on my bed trembling all over. Then I thought of you, Mr. Holmes. I could not live there longer without some advice. I was frightened of the house, of the man, of the woman, of the servants, even of the child. They were all horrible to me. If I could only bring you down all would be well. Of course I might have fled from the house, but my curiosity was almost as strong as my fears. My mind was soon made up. I would send you a wire. I put on my hat and cloak, went down to the office, which is about half a mile from the house, and then returned, feeling very much easier. A horrible doubt came into my mind as I approached the door lest the dog might be loose, but I remembered that Toller had drunk himself into a state of insensibility that evening, and I knew that he was the only one in the household who had any influence with the savage creature, or who would venture to set him free. I slipped in in safety and lay awake half the night in my joy at the thought of seeing you. I had no difficulty in getting leave to come into Winchester this morning, but I must be back before three o'clock, for Mr. and Mrs. Rucastle are going on a visit, and will be away all the evening, so that I must look after the child. Now I have told you all my adventures, Mr. Holmes, and I should be very glad if you could tell me what it all means, and, above all, what I should do." Holmes and I had listened spellbound to this extraordinary story. My friend rose now and paced up and down the room, his hands in his pockets, and an expression of the most profound gravity upon his face. "Is Toller still drunk?" he asked. "Yes. I heard his wife tell Mrs. Rucastle that she could do nothing with him." "That is well. And the Rucastles go out to-night?" "Yes." "Is there a cellar with a good strong lock?" "Yes, the wine-cellar." "You seem to me to have acted all through this matter like a very brave and sensible girl, Miss Hunter. Do you think that you could perform one more feat? I should not ask it of you if I did not think you a quite exceptional woman." "I will try. What is it?" "We shall be at the Copper Beeches by seven o'clock, my friend and I. The Rucastles will be gone by that time, and Toller will, we hope, be incapable. There only remains Mrs. Toller, who might give the alarm. If you could send her into the cellar on some errand, and then turn the key upon her, you would facilitate matters immensely." "I will do it." "Excellent! We shall then look thoroughly into the affair. Of course there is only one feasible explanation. You have been brought there to personate someone, and the real person is imprisoned in this chamber. That is obvious. As to who this prisoner is, I have no doubt that it is the daughter, Miss Alice Rucastle, if I remember right, who was said to have gone to America. You were chosen, doubtless, as resembling her in height, figure, and the colour of your hair. Hers had been cut off, very possibly in some illness through which she has passed, and so, of course, yours had to be sacrificed also. By a curious chance you came upon her tresses. The man in the road was undoubtedly some friend of hers--possibly her fiancé--and no doubt, as you wore the girl's dress and were so like her, he was convinced from your laughter, whenever he saw you, and afterwards from your gesture, that Miss Rucastle was perfectly happy, and that she no longer desired his attentions. The dog is let loose at night to prevent him from endeavouring to communicate with her. So much is fairly clear. The most serious point in the case is the disposition of the child." "What on earth has that to do with it?" I ejaculated. "My dear Watson, you as a medical man are continually gaining light as to the tendencies of a child by the study of the parents. Don't you see that the converse is equally valid. I have frequently gained my first real insight into the character of parents by studying their children. This child's disposition is abnormally cruel, merely for cruelty's sake, and whether he derives this from his smiling father, as I should suspect, or from his mother, it bodes evil for the poor girl who is in their power." "I am sure that you are right, Mr. Holmes," cried our client. "A thousand things come back to me which make me certain that you have hit it. Oh, let us lose not an instant in bringing help to this poor creature." "We must be circumspect, for we are dealing with a very cunning man. We can do nothing until seven o'clock. At that hour we shall be with you, and it will not be long before we solve the mystery." We were as good as our word, for it was just seven when we reached the Copper Beeches, having put up our trap at a wayside public-house. The group of trees, with their dark leaves shining like burnished metal in the light of the setting sun, were sufficient to mark the house even had Miss Hunter not been standing smiling on the door-step. "Have you managed it?" asked Holmes. A loud thudding noise came from somewhere downstairs. "That is Mrs. Toller in the cellar," said she. "Her husband lies snoring on the kitchen rug. Here are his keys, which are the duplicates of Mr. Rucastle's." "You have done well indeed!" cried Holmes with enthusiasm. "Now lead the way, and we shall soon see the end of this black business." We passed up the stair, unlocked the door, followed on down a passage, and found ourselves in front of the barricade which Miss Hunter had described. Holmes cut the cord and removed the transverse bar. Then he tried the various keys in the lock, but without success. No sound came from within, and at the silence Holmes' face clouded over. "I trust that we are not too late," said he. "I think, Miss Hunter, that we had better go in without you. Now, Watson, put your shoulder to it, and we shall see whether we cannot make our way in." It was an old rickety door and gave at once before our united strength. Together we rushed into the room. It was empty. There was no furniture save a little pallet bed, a small table, and a basketful of linen. The skylight above was open, and the prisoner gone. "There has been some villainy here," said Holmes; "this beauty has guessed Miss Hunter's intentions and has carried his victim off." "But how?" "Through the skylight. We shall soon see how he managed it." He swung himself up onto the roof. "Ah, yes," he cried, "here's the end of a long light ladder against the eaves. That is how he did it." "But it is impossible," said Miss Hunter; "the ladder was not there when the Rucastles went away." "He has come back and done it. I tell you that he is a clever and dangerous man. I should not be very much surprised if this were he whose step I hear now upon the stair. I think, Watson, that it would be as well for you to have your pistol ready." The words were hardly out of his mouth before a man appeared at the door of the room, a very fat and burly man, with a heavy stick in his hand. Miss Hunter screamed and shrunk against the wall at the sight of him, but Sherlock Holmes sprang forward and confronted him. "You villain!" said he, "where's your daughter?" The fat man cast his eyes round, and then up at the open skylight. "It is for me to ask you that," he shrieked, "you thieves! Spies and thieves! I have caught you, have I? You are in my power. I'll serve you!" He turned and clattered down the stairs as hard as he could go. "He's gone for the dog!" cried Miss Hunter. "I have my revolver," said I. "Better close the front door," cried Holmes, and we all rushed down the stairs together. We had hardly reached the hall when we heard the baying of a hound, and then a scream of agony, with a horrible worrying sound which it was dreadful to listen to. An elderly man with a red face and shaking limbs came staggering out at a side door. "My God!" he cried. "Someone has loosed the dog. It's not been fed for two days. Quick, quick, or it'll be too late!" Holmes and I rushed out and round the angle of the house, with Toller hurrying behind us. There was the huge famished brute, its black muzzle buried in Rucastle's throat, while he writhed and screamed upon the ground. Running up, I blew its brains out, and it fell over with its keen white teeth still meeting in the great creases of his neck. With much labour we separated them and carried him, living but horribly mangled, into the house. We laid him upon the drawing-room sofa, and having dispatched the sobered Toller to bear the news to his wife, I did what I could to relieve his pain. We were all assembled round him when the door opened, and a tall, gaunt woman entered the room. "Mrs. Toller!" cried Miss Hunter. "Yes, miss. Mr. Rucastle let me out when he came back before he went up to you. Ah, miss, it is a pity you didn't let me know what you were planning, for I would have told you that your pains were wasted." "Ha!" said Holmes, looking keenly at her. "It is clear that Mrs. Toller knows more about this matter than anyone else." "Yes, sir, I do, and I am ready enough to tell what I know." "Then, pray, sit down, and let us hear it for there are several points on which I must confess that I am still in the dark." "I will soon make it clear to you," said she; "and I'd have done so before now if I could ha' got out from the cellar. If there's police-court business over this, you'll remember that I was the one that stood your friend, and that I was Miss Alice's friend too. "She was never happy at home, Miss Alice wasn't, from the time that her father married again. She was slighted like and had no say in anything, but it never really became bad for her until after she met Mr. Fowler at a friend's house. As well as I could learn, Miss Alice had rights of her own by will, but she was so quiet and patient, she was, that she never said a word about them but just left everything in Mr. Rucastle's hands. He knew he was safe with her; but when there was a chance of a husband coming forward, who would ask for all that the law would give him, then her father thought it time to put a stop on it. He wanted her to sign a paper, so that whether she married or not, he could use her money. When she wouldn't do it, he kept on worrying her until she got brain-fever, and for six weeks was at death's door. Then she got better at last, all worn to a shadow, and with her beautiful hair cut off; but that didn't make no change in her young man, and he stuck to her as true as man could be." "Ah," said Holmes, "I think that what you have been good enough to tell us makes the matter fairly clear, and that I can deduce all that remains. Mr. Rucastle then, I presume, took to this system of imprisonment?" "Yes, sir." "And brought Miss Hunter down from London in order to get rid of the disagreeable persistence of Mr. Fowler." "That was it, sir." "But Mr. Fowler being a persevering man, as a good seaman should be, blockaded the house, and having met you succeeded by certain arguments, metallic or otherwise, in convincing you that your interests were the same as his." "Mr. Fowler was a very kind-spoken, free-handed gentleman," said Mrs. Toller serenely. "And in this way he managed that your good man should have no want of drink, and that a ladder should be ready at the moment when your master had gone out." "You have it, sir, just as it happened." "I am sure we owe you an apology, Mrs. Toller," said Holmes, "for you have certainly cleared up everything which puzzled us. And here comes the country surgeon and Mrs. Rucastle, so I think, Watson, that we had best escort Miss Hunter back to Winchester, as it seems to me that our locus standi now is rather a questionable one." And thus was solved the mystery of the sinister house with the copper beeches in front of the door. Mr. Rucastle survived, but was always a broken man, kept alive solely through the care of his devoted wife. They still live with their old servants, who probably know so much of Rucastle's past life that he finds it difficult to part from them. Mr. Fowler and Miss Rucastle were married, by special license, in Southampton the day after their flight, and he is now the holder of a government appointment in the island of Mauritius. As to Miss Violet Hunter, my friend Holmes, rather to my disappointment, manifested no further interest in her when once she had ceased to be the centre of one of his problems, and she is now the head of a private school at Walsall, where I believe that she has met with considerable success. End of the Project Gutenberg EBook of The Adventures of Sherlock Holmes, by Arthur Conan Doyle *** END OF THIS PROJECT GUTENBERG EBOOK THE ADVENTURES OF SHERLOCK HOLMES *** ***** This file should be named 1661-8.txt or 1661-8.zip ***** This and all associated files of various formats will be found in: http://www.gutenberg.org/1/6/6/1661/ Produced by an anonymous Project Gutenberg volunteer and Jose Menendez Updated editions will replace the previous one--the old editions will be renamed. Creating the works from public domain print editions means that no one owns a United States copyright in these works, so the Foundation (and you!) can copy and distribute it in the United States without permission and without paying copyright royalties. Special rules, set forth in the General Terms of Use part of this license, apply to copying and distributing Project Gutenberg-tm electronic works to protect the PROJECT GUTENBERG-tm concept and trademark. Project Gutenberg is a registered trademark, and may not be used if you charge for the eBooks, unless you receive specific permission. If you do not charge anything for copies of this eBook, complying with the rules is very easy. You may use this eBook for nearly any purpose such as creation of derivative works, reports, performances and research. They may be modified and printed and given away--you may do practically ANYTHING with public domain eBooks. Redistribution is subject to the trademark license, especially commercial redistribution. *** START: FULL LICENSE *** THE FULL PROJECT GUTENBERG LICENSE PLEASE READ THIS BEFORE YOU DISTRIBUTE OR USE THIS WORK To protect the Project Gutenberg-tm mission of promoting the free distribution of electronic works, by using or distributing this work (or any other work associated in any way with the phrase "Project Gutenberg"), you agree to comply with all the terms of the Full Project Gutenberg-tm License (available with this file or online at http://gutenberg.net/license). Section 1. General Terms of Use and Redistributing Project Gutenberg-tm electronic works 1.A. By reading or using any part of this Project Gutenberg-tm electronic work, you indicate that you have read, understand, agree to and accept all the terms of this license and intellectual property (trademark/copyright) agreement. If you do not agree to abide by all the terms of this agreement, you must cease using and return or destroy all copies of Project Gutenberg-tm electronic works in your possession. If you paid a fee for obtaining a copy of or access to a Project Gutenberg-tm electronic work and you do not agree to be bound by the terms of this agreement, you may obtain a refund from the person or entity to whom you paid the fee as set forth in paragraph 1.E.8. 1.B. "Project Gutenberg" is a registered trademark. It may only be used on or associated in any way with an electronic work by people who agree to be bound by the terms of this agreement. There are a few things that you can do with most Project Gutenberg-tm electronic works even without complying with the full terms of this agreement. See paragraph 1.C below. There are a lot of things you can do with Project Gutenberg-tm electronic works if you follow the terms of this agreement and help preserve free future access to Project Gutenberg-tm electronic works. See paragraph 1.E below. 1.C. The Project Gutenberg Literary Archive Foundation ("the Foundation" or PGLAF), owns a compilation copyright in the collection of Project Gutenberg-tm electronic works. Nearly all the individual works in the collection are in the public domain in the United States. If an individual work is in the public domain in the United States and you are located in the United States, we do not claim a right to prevent you from copying, distributing, performing, displaying or creating derivative works based on the work as long as all references to Project Gutenberg are removed. Of course, we hope that you will support the Project Gutenberg-tm mission of promoting free access to electronic works by freely sharing Project Gutenberg-tm works in compliance with the terms of this agreement for keeping the Project Gutenberg-tm name associated with the work. You can easily comply with the terms of this agreement by keeping this work in the same format with its attached full Project Gutenberg-tm License when you share it without charge with others. 1.D. The copyright laws of the place where you are located also govern what you can do with this work. Copyright laws in most countries are in a constant state of change. If you are outside the United States, check the laws of your country in addition to the terms of this agreement before downloading, copying, displaying, performing, distributing or creating derivative works based on this work or any other Project Gutenberg-tm work. The Foundation makes no representations concerning the copyright status of any work in any country outside the United States. 1.E. Unless you have removed all references to Project Gutenberg: 1.E.1. The following sentence, with active links to, or other immediate access to, the full Project Gutenberg-tm License must appear prominently whenever any copy of a Project Gutenberg-tm work (any work on which the phrase "Project Gutenberg" appears, or with which the phrase "Project Gutenberg" is associated) is accessed, displayed, performed, viewed, copied or distributed: This eBook is for the use of anyone anywhere at no cost and with almost no restrictions whatsoever. You may copy it, give it away or re-use it under the terms of the Project Gutenberg License included with this eBook or online at www.gutenberg.net 1.E.2. If an individual Project Gutenberg-tm electronic work is derived from the public domain (does not contain a notice indicating that it is posted with permission of the copyright holder), the work can be copied and distributed to anyone in the United States without paying any fees or charges. If you are redistributing or providing access to a work with the phrase "Project Gutenberg" associated with or appearing on the work, you must comply either with the requirements of paragraphs 1.E.1 through 1.E.7 or obtain permission for the use of the work and the Project Gutenberg-tm trademark as set forth in paragraphs 1.E.8 or 1.E.9. 1.E.3. If an individual Project Gutenberg-tm electronic work is posted with the permission of the copyright holder, your use and distribution must comply with both paragraphs 1.E.1 through 1.E.7 and any additional terms imposed by the copyright holder. Additional terms will be linked to the Project Gutenberg-tm License for all works posted with the permission of the copyright holder found at the beginning of this work. 1.E.4. Do not unlink or detach or remove the full Project Gutenberg-tm License terms from this work, or any files containing a part of this work or any other work associated with Project Gutenberg-tm. 1.E.5. Do not copy, display, perform, distribute or redistribute this electronic work, or any part of this electronic work, without prominently displaying the sentence set forth in paragraph 1.E.1 with active links or immediate access to the full terms of the Project Gutenberg-tm License. 1.E.6. You may convert to and distribute this work in any binary, compressed, marked up, nonproprietary or proprietary form, including any word processing or hypertext form. However, if you provide access to or distribute copies of a Project Gutenberg-tm work in a format other than "Plain Vanilla ASCII" or other format used in the official version posted on the official Project Gutenberg-tm web site (www.gutenberg.net), you must, at no additional cost, fee or expense to the user, provide a copy, a means of exporting a copy, or a means of obtaining a copy upon request, of the work in its original "Plain Vanilla ASCII" or other form. Any alternate format must include the full Project Gutenberg-tm License as specified in paragraph 1.E.1. 1.E.7. Do not charge a fee for access to, viewing, displaying, performing, copying or distributing any Project Gutenberg-tm works unless you comply with paragraph 1.E.8 or 1.E.9. 1.E.8. You may charge a reasonable fee for copies of or providing access to or distributing Project Gutenberg-tm electronic works provided that - You pay a royalty fee of 20% of the gross profits you derive from the use of Project Gutenberg-tm works calculated using the method you already use to calculate your applicable taxes. The fee is owed to the owner of the Project Gutenberg-tm trademark, but he has agreed to donate royalties under this paragraph to the Project Gutenberg Literary Archive Foundation. Royalty payments must be paid within 60 days following each date on which you prepare (or are legally required to prepare) your periodic tax returns. Royalty payments should be clearly marked as such and sent to the Project Gutenberg Literary Archive Foundation at the address specified in Section 4, "Information about donations to the Project Gutenberg Literary Archive Foundation." - You provide a full refund of any money paid by a user who notifies you in writing (or by e-mail) within 30 days of receipt that s/he does not agree to the terms of the full Project Gutenberg-tm License. You must require such a user to return or destroy all copies of the works possessed in a physical medium and discontinue all use of and all access to other copies of Project Gutenberg-tm works. - You provide, in accordance with paragraph 1.F.3, a full refund of any money paid for a work or a replacement copy, if a defect in the electronic work is discovered and reported to you within 90 days of receipt of the work. - You comply with all other terms of this agreement for free distribution of Project Gutenberg-tm works. 1.E.9. If you wish to charge a fee or distribute a Project Gutenberg-tm electronic work or group of works on different terms than are set forth in this agreement, you must obtain permission in writing from both the Project Gutenberg Literary Archive Foundation and Michael Hart, the owner of the Project Gutenberg-tm trademark. Contact the Foundation as set forth in Section 3 below. 1.F. 1.F.1. Project Gutenberg volunteers and employees expend considerable effort to identify, do copyright research on, transcribe and proofread public domain works in creating the Project Gutenberg-tm collection. Despite these efforts, Project Gutenberg-tm electronic works, and the medium on which they may be stored, may contain "Defects," such as, but not limited to, incomplete, inaccurate or corrupt data, transcription errors, a copyright or other intellectual property infringement, a defective or damaged disk or other medium, a computer virus, or computer codes that damage or cannot be read by your equipment. 1.F.2. LIMITED WARRANTY, DISCLAIMER OF DAMAGES - Except for the "Right of Replacement or Refund" described in paragraph 1.F.3, the Project Gutenberg Literary Archive Foundation, the owner of the Project Gutenberg-tm trademark, and any other party distributing a Project Gutenberg-tm electronic work under this agreement, disclaim all liability to you for damages, costs and expenses, including legal fees. YOU AGREE THAT YOU HAVE NO REMEDIES FOR NEGLIGENCE, STRICT LIABILITY, BREACH OF WARRANTY OR BREACH OF CONTRACT EXCEPT THOSE PROVIDED IN PARAGRAPH 1.F.3. YOU AGREE THAT THE FOUNDATION, THE TRADEMARK OWNER, AND ANY DISTRIBUTOR UNDER THIS AGREEMENT WILL NOT BE LIABLE TO YOU FOR ACTUAL, DIRECT, INDIRECT, CONSEQUENTIAL, PUNITIVE OR INCIDENTAL DAMAGES EVEN IF YOU GIVE NOTICE OF THE POSSIBILITY OF SUCH DAMAGE. 1.F.3. LIMITED RIGHT OF REPLACEMENT OR REFUND - If you discover a defect in this electronic work within 90 days of receiving it, you can receive a refund of the money (if any) you paid for it by sending a written explanation to the person you received the work from. If you received the work on a physical medium, you must return the medium with your written explanation. The person or entity that provided you with the defective work may elect to provide a replacement copy in lieu of a refund. If you received the work electronically, the person or entity providing it to you may choose to give you a second opportunity to receive the work electronically in lieu of a refund. If the second copy is also defective, you may demand a refund in writing without further opportunities to fix the problem. 1.F.4. Except for the limited right of replacement or refund set forth in paragraph 1.F.3, this work is provided to you 'AS-IS' WITH NO OTHER WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTIBILITY OR FITNESS FOR ANY PURPOSE. 1.F.5. Some states do not allow disclaimers of certain implied warranties or the exclusion or limitation of certain types of damages. If any disclaimer or limitation set forth in this agreement violates the law of the state applicable to this agreement, the agreement shall be interpreted to make the maximum disclaimer or limitation permitted by the applicable state law. The invalidity or unenforceability of any provision of this agreement shall not void the remaining provisions. 1.F.6. INDEMNITY - You agree to indemnify and hold the Foundation, the trademark owner, any agent or employee of the Foundation, anyone providing copies of Project Gutenberg-tm electronic works in accordance with this agreement, and any volunteers associated with the production, promotion and distribution of Project Gutenberg-tm electronic works, harmless from all liability, costs and expenses, including legal fees, that arise directly or indirectly from any of the following which you do or cause to occur: (a) distribution of this or any Project Gutenberg-tm work, (b) alteration, modification, or additions or deletions to any Project Gutenberg-tm work, and (c) any Defect you cause. Section 2. Information about the Mission of Project Gutenberg-tm Project Gutenberg-tm is synonymous with the free distribution of electronic works in formats readable by the widest variety of computers including obsolete, old, middle-aged and new computers. It exists because of the efforts of hundreds of volunteers and donations from people in all walks of life. Volunteers and financial support to provide volunteers with the assistance they need are critical to reaching Project Gutenberg-tm's goals and ensuring that the Project Gutenberg-tm collection will remain freely available for generations to come. In 2001, the Project Gutenberg Literary Archive Foundation was created to provide a secure and permanent future for Project Gutenberg-tm and future generations. To learn more about the Project Gutenberg Literary Archive Foundation and how your efforts and donations can help, see Sections 3 and 4 and the Foundation web page at http://www.pglaf.org. Section 3. Information about the Project Gutenberg Literary Archive Foundation The Project Gutenberg Literary Archive Foundation is a non profit 501(c)(3) educational corporation organized under the laws of the state of Mississippi and granted tax exempt status by the Internal Revenue Service. The Foundation's EIN or federal tax identification number is 64-6221541. Its 501(c)(3) letter is posted at http://pglaf.org/fundraising. Contributions to the Project Gutenberg Literary Archive Foundation are tax deductible to the full extent permitted by U.S. federal laws and your state's laws. The Foundation's principal office is located at 4557 Melan Dr. S. Fairbanks, AK, 99712., but its volunteers and employees are scattered throughout numerous locations. Its business office is located at 809 North 1500 West, Salt Lake City, UT 84116, (801) 596-1887, email business@pglaf.org. Email contact links and up to date contact information can be found at the Foundation's web site and official page at http://pglaf.org For additional contact information: Dr. Gregory B. Newby Chief Executive and Director gbnewby@pglaf.org Section 4. Information about Donations to the Project Gutenberg Literary Archive Foundation Project Gutenberg-tm depends upon and cannot survive without wide spread public support and donations to carry out its mission of increasing the number of public domain and licensed works that can be freely distributed in machine readable form accessible by the widest array of equipment including outdated equipment. Many small donations ($1 to $5,000) are particularly important to maintaining tax exempt status with the IRS. The Foundation is committed to complying with the laws regulating charities and charitable donations in all 50 states of the United States. Compliance requirements are not uniform and it takes a considerable effort, much paperwork and many fees to meet and keep up with these requirements. We do not solicit donations in locations where we have not received written confirmation of compliance. To SEND DONATIONS or determine the status of compliance for any particular state visit http://pglaf.org While we cannot and do not solicit contributions from states where we have not met the solicitation requirements, we know of no prohibition against accepting unsolicited donations from donors in such states who approach us with offers to donate. International donations are gratefully accepted, but we cannot make any statements concerning tax treatment of donations received from outside the United States. U.S. laws alone swamp our small staff. Please check the Project Gutenberg Web pages for current donation methods and addresses. Donations are accepted in a number of other ways including including checks, online payments and credit card donations. To donate, please visit: http://pglaf.org/donate Section 5. General Information About Project Gutenberg-tm electronic works. Professor Michael S. Hart is the originator of the Project Gutenberg-tm concept of a library of electronic works that could be freely shared with anyone. For thirty years, he produced and distributed Project Gutenberg-tm eBooks with only a loose network of volunteer support. Project Gutenberg-tm eBooks are often created from several printed editions, all of which are confirmed as Public Domain in the U.S. unless a copyright notice is included. Thus, we do not necessarily keep eBooks in compliance with any particular paper edition. Most people start at our Web site which has the main PG search facility: http://www.gutenberg.net This Web site includes information about Project Gutenberg-tm, including how to make donations to the Project Gutenberg Literary Archive Foundation, how to help produce our new eBooks, and how to subscribe to our email newsletter to hear about new eBooks. vendor/aho-corasick-0.5.3/ctags.rust0000644000000000000000000000160613264166600016104 0ustar rootroot--langdef=Rust --langmap=Rust:.rs --regex-Rust=/^[ \t]*(#\[[^\]]\][ \t]*)*(pub[ \t]+)?(extern[ \t]+)?("[^"]+"[ \t]+)?(unsafe[ \t]+)?fn[ \t]+([a-zA-Z0-9_]+)/\6/f,functions,function definitions/ --regex-Rust=/^[ \t]*(pub[ \t]+)?type[ \t]+([a-zA-Z0-9_]+)/\2/T,types,type definitions/ --regex-Rust=/^[ \t]*(pub[ \t]+)?enum[ \t]+([a-zA-Z0-9_]+)/\2/g,enum,enumeration names/ --regex-Rust=/^[ \t]*(pub[ \t]+)?struct[ \t]+([a-zA-Z0-9_]+)/\2/s,structure names/ --regex-Rust=/^[ \t]*(pub[ \t]+)?mod[ \t]+([a-zA-Z0-9_]+)/\2/m,modules,module names/ --regex-Rust=/^[ \t]*(pub[ \t]+)?static[ \t]+([a-zA-Z0-9_]+)/\2/c,consts,static constants/ --regex-Rust=/^[ \t]*(pub[ \t]+)?trait[ \t]+([a-zA-Z0-9_]+)/\2/t,traits,traits/ --regex-Rust=/^[ \t]*(pub[ \t]+)?impl([ \t\n]+<.*>)?[ \t]+([a-zA-Z0-9_]+)/\3/i,impls,trait implementations/ --regex-Rust=/^[ \t]*macro_rules![ \t]+([a-zA-Z0-9_]+)/\1/d,macros,macro definitions/ vendor/aho-corasick-0.5.3/examples/0000755000000000000000000000000013264166600015677 5ustar rootrootvendor/aho-corasick-0.5.3/examples/dict-search.rs0000644000000000000000000001200213264166600020426 0ustar rootroot// This example demonstrates how to use the Aho-Corasick algorithm to rapidly // scan text for matches in a large dictionary of keywords. This example by // default reads your system's dictionary (~120,000 words). extern crate aho_corasick; extern crate csv; extern crate docopt; extern crate memmap; extern crate rustc_serialize; use std::error::Error; use std::fs::File; use std::io::{self, BufRead, Write}; use std::process; use aho_corasick::{Automaton, AcAutomaton, Match}; use docopt::Docopt; use memmap::{Mmap, Protection}; static USAGE: &'static str = " Usage: dict-search [options] dict-search --help Options: -d , --dict Path to dictionary of keywords to search. [default: /usr/share/dict/words] -m , --min-len The minimum length for a keyword in UTF-8 encoded bytes. [default: 5] --overlapping Report overlapping matches. -c, --count Show only the numebr of matches. --memory-usage Show memory usage of automaton. --full Use fully expanded transition matrix. Warning: may use lots of memory. -h, --help Show this usage message. "; #[derive(Clone, Debug, RustcDecodable)] struct Args { arg_input: String, flag_dict: String, flag_min_len: usize, flag_overlapping: bool, flag_memory_usage: bool, flag_full: bool, flag_count: bool, } fn main() { let args: Args = Docopt::new(USAGE) .and_then(|d| d.decode()) .unwrap_or_else(|e| e.exit()); match run(&args) { Ok(()) => {} Err(err) => { writeln!(&mut io::stderr(), "{}", err).unwrap(); process::exit(1); } } } fn run(args: &Args) -> Result<(), Box> { let aut = try!(build_automaton(&args.flag_dict, args.flag_min_len)); if args.flag_memory_usage { let (bytes, states) = if args.flag_full { let aut = aut.into_full(); (aut.heap_bytes(), aut.num_states()) } else { (aut.heap_bytes(), aut.num_states()) }; println!("{} bytes, {} states", bytes, states); return Ok(()); } if args.flag_full { let aut = aut.into_full(); if args.flag_overlapping { if args.flag_count { let mmap = Mmap::open_path( &args.arg_input, Protection::Read).unwrap(); let text = unsafe { mmap.as_slice() }; println!("{}", aut.find_overlapping(text).count()); } else { let rdr = try!(File::open(&args.arg_input)); try!(write_matches(&aut, aut.stream_find_overlapping(rdr))); } } else { if args.flag_count { let mmap = Mmap::open_path( &args.arg_input, Protection::Read).unwrap(); let text = unsafe { mmap.as_slice() }; println!("{}", aut.find(text).count()); } else { let rdr = try!(File::open(&args.arg_input)); try!(write_matches(&aut, aut.stream_find(rdr))); } } } else { if args.flag_overlapping { if args.flag_count { let mmap = Mmap::open_path( &args.arg_input, Protection::Read).unwrap(); let text = unsafe { mmap.as_slice() }; println!("{}", aut.find_overlapping(text).count()); } else { let rdr = try!(File::open(&args.arg_input)); try!(write_matches(&aut, aut.stream_find_overlapping(rdr))); } } else { if args.flag_count { let mmap = Mmap::open_path( &args.arg_input, Protection::Read).unwrap(); let text = unsafe { mmap.as_slice() }; println!("{}", aut.find(text).count()); } else { let rdr = try!(File::open(&args.arg_input)); try!(write_matches(&aut, aut.stream_find(rdr))); } } } Ok(()) } fn write_matches(aut: &A, it: I) -> Result<(), Box> where A: Automaton, I: Iterator> { let mut wtr = csv::Writer::from_writer(io::stdout()); try!(wtr.write(["pattern", "start", "end"].iter())); for m in it { let m = try!(m); try!(wtr.write([ aut.pattern(m.pati), &m.start.to_string(), &m.end.to_string(), ].iter())); } try!(wtr.flush()); Ok(()) } fn build_automaton( dict_path: &str, min_len: usize, ) -> Result, Box> { let buf = io::BufReader::new(try!(File::open(dict_path))); let mut lines = Vec::with_capacity(1 << 10); for line in buf.lines() { let line = try!(line); if line.len() >= min_len { lines.push(line); } } Ok(AcAutomaton::with_transitions(lines)) } vendor/aho-corasick-0.5.3/session.vim0000644000000000000000000000007013264166600016256 0ustar rootrootau BufWritePost *.rs silent!make ctags > /dev/null 2>&1 vendor/aho-corasick-0.5.3/src/0000755000000000000000000000000013264166600014650 5ustar rootrootvendor/aho-corasick-0.5.3/src/autiter.rs0000644000000000000000000003613113264166600016677 0ustar rootrootuse std::io::{self, BufRead}; use std::marker::PhantomData; use memchr::{memchr, memchr2, memchr3}; use super::{ROOT_STATE, StateIdx}; /// An abstraction over automatons and their corresponding iterators. /// The type parameter `P` is the type of the pattern that was used to /// construct this Automaton. pub trait Automaton

{ /// Return the next state given the current state and next character. fn next_state(&self, si: StateIdx, b: u8) -> StateIdx; /// Return true if and only if the given state and current pattern index /// indicate a match. fn has_match(&self, si: StateIdx, outi: usize) -> bool; /// Build a match given the current state, pattern index and input index. fn get_match(&self, si: StateIdx, outi: usize, texti: usize) -> Match; /// Return the set of bytes that have transitions in the root state. fn start_bytes(&self) -> &[u8]; /// Returns all of the patterns matched by this automaton. /// /// The order of the patterns is the order in which they were added. fn patterns(&self) -> &[P]; /// Returns the pattern indexed at `i`. /// /// The index corresponds to the position at which the pattern was added /// to the automaton, starting at `0`. fn pattern(&self, i: usize) -> &P; /// Return the number of patterns in the automaton. #[inline] fn len(&self) -> usize { self.patterns().len() } /// Returns true if the automaton has no patterns. #[inline] fn is_empty(&self) -> bool { self.len() == 0 } /// Returns an iterator of non-overlapping matches in `s`. fn find<'a, 's, Q: ?Sized + AsRef<[u8]>>( &'a self, s: &'s Q, ) -> Matches<'a, 's, P, Self> where Self: Sized { Matches { aut: self, text: s.as_ref(), texti: 0, si: ROOT_STATE, _m: PhantomData, } } /// Returns an iterator of overlapping matches in `s`. fn find_overlapping<'a, 's, Q: ?Sized + AsRef<[u8]>>( &'a self, s: &'s Q, ) -> MatchesOverlapping<'a, 's, P, Self> where Self: Sized { MatchesOverlapping { aut: self, text: s.as_ref(), texti: 0, si: ROOT_STATE, outi: 0, _m: PhantomData, } } /// Returns an iterator of non-overlapping matches in the given reader. fn stream_find<'a, R: io::Read>( &'a self, rdr: R, ) -> StreamMatches<'a, R, P, Self> where Self: Sized { StreamMatches { aut: self, buf: io::BufReader::new(rdr), texti: 0, si: ROOT_STATE, _m: PhantomData, } } /// Returns an iterator of overlapping matches in the given reader. fn stream_find_overlapping<'a, R: io::Read>( &'a self, rdr: R, ) -> StreamMatchesOverlapping<'a, R, P, Self> where Self: Sized { StreamMatchesOverlapping { aut: self, buf: io::BufReader::new(rdr), texti: 0, si: ROOT_STATE, outi: 0, _m: PhantomData, } } } impl<'a, P: AsRef<[u8]>, A: 'a + Automaton

+ ?Sized> Automaton

for &'a A { fn next_state(&self, si: StateIdx, b: u8) -> StateIdx { (**self).next_state(si, b) } fn has_match(&self, si: StateIdx, outi: usize) -> bool { (**self).has_match(si, outi) } fn start_bytes(&self) -> &[u8] { (**self).start_bytes() } fn patterns(&self) -> &[P] { (**self).patterns() } fn pattern(&self, i: usize) -> &P { (**self).pattern(i) } fn get_match(&self, si: StateIdx, outi: usize, texti: usize) -> Match { (**self).get_match(si, outi, texti) } } /// Records a match in the search text. #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct Match { /// The pattern index. /// /// This corresponds to the ordering in which the matched pattern was /// added to the automaton, starting at `0`. pub pati: usize, /// The starting byte offset of the match in the search text. pub start: usize, /// The ending byte offset of the match in the search text. /// /// (This can be re-captiulated with `pati` and adding the pattern's /// length to `start`, but it is convenient to have it here.) pub end: usize, } /// An iterator of non-overlapping matches for in-memory text. /// /// This iterator yields `Match` values. /// /// `'a` is the lifetime of the automaton, `'s` is the lifetime of the /// search text, and `P` is the type of the Automaton's pattern. #[derive(Debug)] pub struct Matches<'a, 's, P, A: 'a + Automaton

+ ?Sized> { aut: &'a A, text: &'s [u8], texti: usize, si: StateIdx, _m: PhantomData

, } // When there's an initial lone start byte, it is usually worth it // to use `memchr` to skip along the input. The problem is that // the skipping function is called in the inner match loop, which // can be quite costly if the skipping condition is never met. // Therefore, we lift the case analysis outside of the inner loop at // the cost of repeating code. // // `step_to_match` is the version of the inner loop without skipping, // and `skip_to_match` is the version with skipping. #[inline(never)] fn step_to_match + ?Sized>( aut: &A, text: &[u8], mut texti: usize, mut si: StateIdx ) -> Option<(usize, StateIdx)> { while texti < text.len() { si = aut.next_state(si, text[texti]); if aut.has_match(si, 0) { return Some((texti, si)); } texti += 1; if texti + 4 < text.len() { si = aut.next_state(si, text[texti]); if aut.has_match(si, 0) { return Some((texti, si)); } texti += 1; si = aut.next_state(si, text[texti]); if aut.has_match(si, 0) { return Some((texti, si)); } texti += 1; si = aut.next_state(si, text[texti]); if aut.has_match(si, 0) { return Some((texti, si)); } texti += 1; si = aut.next_state(si, text[texti]); if aut.has_match(si, 0) { return Some((texti, si)); } texti += 1; si = aut.next_state(si, text[texti]); if aut.has_match(si, 0) { return Some((texti, si)); } texti += 1; } } None } fn skip_to_match + ?Sized, F: Fn(&A, &[u8], usize) -> usize>( aut: &A, text: &[u8], mut texti: usize, mut si: StateIdx, skip: F, ) -> Option<(usize, StateIdx)> { if si == ROOT_STATE { texti = skip(aut, text, texti); } while texti < text.len() { si = aut.next_state(si, text[texti]); if aut.has_match(si, 0) { return Some((texti, si)); } if si == ROOT_STATE { texti = skip(aut, text, texti + 1); } else { texti += 1; } } None } #[inline] fn skip1 + ?Sized>( aut: &A, text: &[u8], at: usize, ) -> usize { debug_assert!(aut.start_bytes().len() == 1); let b = aut.start_bytes()[0]; match memchr(b, &text[at..]) { None => text.len(), Some(i) => at + i, } } #[inline] fn skip2 + ?Sized>( aut: &A, text: &[u8], at: usize, ) -> usize { debug_assert!(aut.start_bytes().len() == 2); let (b1, b2) = (aut.start_bytes()[0], aut.start_bytes()[1]); match memchr2(b1, b2, &text[at..]) { None => text.len(), Some(i) => at + i, } } #[inline] fn skip3 + ?Sized>( aut: &A, text: &[u8], at: usize, ) -> usize { debug_assert!(aut.start_bytes().len() == 3); let (b1, b2, b3) = ( aut.start_bytes()[0], aut.start_bytes()[1], aut.start_bytes()[2], ); match memchr3(b1, b2, b3, &text[at..]) { None => text.len(), Some(i) => at + i, } } impl<'a, 's, P, A: Automaton

+ ?Sized> Iterator for Matches<'a, 's, P, A> { type Item = Match; fn next(&mut self) -> Option { if self.aut.start_bytes().len() == 1 { let skip = skip_to_match( self.aut, self.text, self.texti, self.si, skip1); if let Some((texti, si)) = skip { self.texti = texti + 1; self.si = ROOT_STATE; return Some(self.aut.get_match(si, 0, texti)); } } else if self.aut.start_bytes().len() == 2 { let skip = skip_to_match( self.aut, self.text, self.texti, self.si, skip2); if let Some((texti, si)) = skip { self.texti = texti + 1; self.si = ROOT_STATE; return Some(self.aut.get_match(si, 0, texti)); } } else if self.aut.start_bytes().len() == 3 { let skip = skip_to_match( self.aut, self.text, self.texti, self.si, skip3); if let Some((texti, si)) = skip { self.texti = texti + 1; self.si = ROOT_STATE; return Some(self.aut.get_match(si, 0, texti)); } } else { let step = step_to_match(self.aut, self.text, self.texti, self.si); if let Some((texti, si)) = step { self.texti = texti + 1; self.si = ROOT_STATE; return Some(self.aut.get_match(si, 0, texti)); } } None } } /// An iterator of non-overlapping matches for streaming text. /// /// This iterator yields `io::Result` values. /// /// `'a` is the lifetime of the automaton, `R` is the type of the underlying /// `io::Read`er, and P is the type of the Automaton's pattern. #[derive(Debug)] pub struct StreamMatches<'a, R, P, A: 'a + Automaton

+ ?Sized> { aut: &'a A, buf: io::BufReader, texti: usize, si: StateIdx, _m: PhantomData

, } impl<'a, R: io::Read, P, A: Automaton

> Iterator for StreamMatches<'a, R, P, A> { type Item = io::Result; fn next(&mut self) -> Option> { let mut m = None; let mut consumed = 0; 'LOOP: loop { self.buf.consume(consumed); let bs = match self.buf.fill_buf() { Err(err) => return Some(Err(err)), Ok(bs) if bs.len() == 0 => break, Ok(bs) => bs, }; consumed = bs.len(); // is shortened if we find a match for (i, &b) in bs.iter().enumerate() { self.si = self.aut.next_state(self.si, b); if self.aut.has_match(self.si, 0) { m = Some(Ok(self.aut.get_match(self.si, 0, self.texti))); consumed = i + 1; self.texti += 1; self.si = ROOT_STATE; break 'LOOP; } self.texti += 1; } } self.buf.consume(consumed); m } } /// An iterator of overlapping matches for in-memory text. /// /// This iterator yields `Match` values. /// /// `'a` is the lifetime of the automaton, `'s` is the lifetime of the /// search text, and `P` is the type of the Automaton's pattern. #[derive(Debug)] pub struct MatchesOverlapping<'a, 's, P, A: 'a + Automaton

+ ?Sized> { aut: &'a A, text: &'s [u8], texti: usize, si: StateIdx, outi: usize, _m: PhantomData

, } impl<'a, 's, P, A: Automaton

+ ?Sized> Iterator for MatchesOverlapping<'a, 's, P, A> { type Item = Match; fn next(&mut self) -> Option { if self.aut.has_match(self.si, self.outi) { let m = self.aut.get_match(self.si, self.outi, self.texti); self.outi += 1; if !self.aut.has_match(self.si, self.outi) { self.texti += 1; } return Some(m); } self.outi = 0; if self.aut.start_bytes().len() == 1 { let skip = skip_to_match( self.aut, self.text, self.texti, self.si, skip1); if let Some((texti, si)) = skip { self.texti = texti; self.si = si; return self.next(); } } else if self.aut.start_bytes().len() == 2 { let skip = skip_to_match( self.aut, self.text, self.texti, self.si, skip2); if let Some((texti, si)) = skip { self.texti = texti; self.si = si; return self.next(); } } else if self.aut.start_bytes().len() == 3 { let skip = skip_to_match( self.aut, self.text, self.texti, self.si, skip3); if let Some((texti, si)) = skip { self.texti = texti; self.si = si; return self.next(); } } else { let step = step_to_match(self.aut, self.text, self.texti, self.si); if let Some((texti, si)) = step { self.texti = texti; self.si = si; return self.next(); } } None } } /// An iterator of overlapping matches for streaming text. /// /// This iterator yields `io::Result` values. /// /// `'a` is the lifetime of the automaton, `R` is the type of the underlying /// `io::Read`er, and P is the type of the Automaton's pattern. #[derive(Debug)] pub struct StreamMatchesOverlapping<'a, R, P, A: 'a + Automaton

+ ?Sized> { aut: &'a A, buf: io::BufReader, texti: usize, si: StateIdx, outi: usize, _m: PhantomData

, } impl<'a, R: io::Read, P, A: Automaton

+ ?Sized> Iterator for StreamMatchesOverlapping<'a, R, P, A> { type Item = io::Result; fn next(&mut self) -> Option> { if self.aut.has_match(self.si, self.outi) { let m = self.aut.get_match(self.si, self.outi, self.texti); self.outi += 1; if !self.aut.has_match(self.si, self.outi) { self.texti += 1; } return Some(Ok(m)); } let mut m = None; let mut consumed = 0; self.outi = 0; 'LOOP: loop { self.buf.consume(consumed); let bs = match self.buf.fill_buf() { Err(err) => return Some(Err(err)), Ok(bs) if bs.len() == 0 => break, Ok(bs) => bs, }; consumed = bs.len(); // is shortened if we find a match for (i, &b) in bs.iter().enumerate() { self.si = self.aut.next_state(self.si, b); if self.aut.has_match(self.si, self.outi) { m = Some(Ok(self.aut.get_match( self.si, self.outi, self.texti))); consumed = i + 1; self.outi += 1; if !self.aut.has_match(self.si, self.outi) { self.texti += 1; } break 'LOOP; } self.texti += 1; } } self.buf.consume(consumed); m } } vendor/aho-corasick-0.5.3/src/full.rs0000644000000000000000000000757513264166600016176 0ustar rootrootuse std::fmt; use std::mem; use super::{ FAIL_STATE, StateIdx, AcAutomaton, Transitions, Match, usize_bytes, vec_bytes, }; use super::autiter::Automaton; /// A complete Aho-Corasick automaton. /// /// This uses a single transition matrix that permits each input character /// to move to the next state with a single lookup in the matrix. /// /// This is as fast as it gets, but it is guaranteed to use a lot of memory. /// Namely, it will use at least `4 * 256 * #states`, where the number of /// states is capped at length of all patterns concatenated. #[derive(Clone)] pub struct FullAcAutomaton

{ pats: Vec

, trans: Vec, // row-major, where states are rows out: Vec>, // indexed by StateIdx start_bytes: Vec, } impl> FullAcAutomaton

{ /// Build a new expanded Aho-Corasick automaton from an existing /// Aho-Corasick automaton. pub fn new(ac: AcAutomaton) -> FullAcAutomaton

{ let mut fac = FullAcAutomaton { pats: vec![], trans: vec![FAIL_STATE; 256 * ac.states.len()], out: vec![vec![]; ac.states.len()], start_bytes: vec![], }; fac.build_matrix(&ac); fac.pats = ac.pats; fac.start_bytes = ac.start_bytes; fac } #[doc(hidden)] pub fn memory_usage(&self) -> usize { self.pats.iter() .map(|p| vec_bytes() + p.as_ref().len()) .fold(0, |a, b| a + b) + (4 * self.trans.len()) + self.out.iter() .map(|v| vec_bytes() + (usize_bytes() * v.len())) .fold(0, |a, b| a + b) + self.start_bytes.len() } #[doc(hidden)] pub fn heap_bytes(&self) -> usize { self.pats.iter() .map(|p| mem::size_of::

() + p.as_ref().len()) .fold(0, |a, b| a + b) + (4 * self.trans.len()) + self.out.iter() .map(|v| vec_bytes() + (usize_bytes() * v.len())) .fold(0, |a, b| a + b) + self.start_bytes.len() } fn set(&mut self, si: StateIdx, i: u8, goto: StateIdx) { let ns = self.num_states(); self.trans[i as usize * ns + si as usize] = goto; } #[doc(hidden)] #[inline] pub fn num_states(&self) -> usize { self.out.len() } } impl> Automaton

for FullAcAutomaton

{ #[inline] fn next_state(&self, si: StateIdx, i: u8) -> StateIdx { let at = i as usize * self.num_states() + si as usize; unsafe { *self.trans.get_unchecked(at) } } #[inline] fn get_match(&self, si: StateIdx, outi: usize, texti: usize) -> Match { let pati = self.out[si as usize][outi]; let patlen = self.pats[pati].as_ref().len(); let start = texti + 1 - patlen; Match { pati: pati, start: start, end: start + patlen, } } #[inline] fn has_match(&self, si: StateIdx, outi: usize) -> bool { unsafe { outi < self.out.get_unchecked(si as usize).len() } } #[inline] fn start_bytes(&self) -> &[u8] { &self.start_bytes } #[inline] fn patterns(&self) -> &[P] { &self.pats } #[inline] fn pattern(&self, i: usize) -> &P { &self.pats[i] } } impl> FullAcAutomaton

{ fn build_matrix(&mut self, ac: &AcAutomaton) { for (si, s) in ac.states.iter().enumerate().skip(1) { for b in (0..256).map(|b| b as u8) { self.set(si as StateIdx, b, ac.next_state(si as StateIdx, b)); } for &pati in &s.out { self.out[si].push(pati); } } } } impl + fmt::Debug> fmt::Debug for FullAcAutomaton

{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "FullAcAutomaton({:?})", self.pats) } } vendor/aho-corasick-0.5.3/src/lib.rs0000644000000000000000000007404513264166600015776 0ustar rootroot/*! An implementation of the [Aho-Corasick string search algorithm](https://en.wikipedia.org/wiki/Aho%E2%80%93Corasick_string_matching_algorithm). The Aho-Corasick algorithm is principally useful when you need to search many large texts for a fixed (possibly large) set of keywords. In particular, the Aho-Corasick algorithm preprocesses the set of keywords by constructing a finite state machine. The search phase is then a quick linear scan through the text. Each character in the search text causes a state transition in the automaton. Matches are reported when the automaton enters a match state. # Examples The main type exposed by this crate is `AcAutomaton`, which can be constructed from an iterator of pattern strings: ```rust use aho_corasick::{Automaton, AcAutomaton}; let aut = AcAutomaton::new(vec!["apple", "maple"]); // AcAutomaton also implements `FromIterator`: let aut: AcAutomaton<&str> = ["apple", "maple"].iter().cloned().collect(); ``` Finding matches can be done with `find`: ```rust use aho_corasick::{Automaton, AcAutomaton, Match}; let aut = AcAutomaton::new(vec!["apple", "maple"]); let mut it = aut.find("I like maple apples."); assert_eq!(it.next(), Some(Match { pati: 1, start: 7, end: 12, })); assert_eq!(it.next(), Some(Match { pati: 0, start: 13, end: 18, })); assert_eq!(it.next(), None); ``` Use `find_overlapping` if you want to report all matches, even if they overlap with each other. ```rust use aho_corasick::{Automaton, AcAutomaton, Match}; let aut = AcAutomaton::new(vec!["abc", "a"]); let matches: Vec<_> = aut.find_overlapping("abc").collect(); assert_eq!(matches, vec![ Match { pati: 1, start: 0, end: 1}, Match { pati: 0, start: 0, end: 3 }, ]); // Regular `find` will report only one match: let matches: Vec<_> = aut.find("abc").collect(); assert_eq!(matches, vec![Match { pati: 1, start: 0, end: 1}]); ``` Finally, there are also methods for finding matches on *streams*. Namely, the search text does not have to live in memory. It's useful to run this on files that can't fit into memory: ```no_run use std::fs::File; use aho_corasick::{Automaton, AcAutomaton}; let aut = AcAutomaton::new(vec!["foo", "bar", "baz"]); let rdr = File::open("search.txt").unwrap(); for m in aut.stream_find(rdr) { let m = m.unwrap(); // could be an IO error println!("Pattern '{}' matched at: ({}, {})", aut.pattern(m.pati), m.start, m.end); } ``` There is also `stream_find_overlapping`, which is just like `find_overlapping`, but it operates on streams. Please see `dict-search.rs` in this crate's `examples` directory for a more complete example. It creates a large automaton from a dictionary and can do a streaming match over arbitrarily large data. # Memory usage A key aspect of an Aho-Corasick implementation is how the state transitions are represented. The easiest way to make the automaton fast is to store a sparse 256-slot map in each state. It maps an input byte to a state index. This makes the matching loop extremely fast, since it translates to a simple pointer read. The problem is that as the automaton accumulates more states, you end up paying a `256 * 4` (`4` is for the `u32` state index) byte penalty for every state regardless of how many transitions it has. To solve this, only states near the root of the automaton have this sparse map representation. States near the leaves of the automaton use a dense mapping that requires a linear scan. (The specific limit currently set is `3`, so that states with a depth less than or equal to `3` are less memory efficient. The result is that the memory usage of the automaton stops growing rapidly past ~60MB, even for automatons with thousands of patterns.) If you'd like to opt for the less-memory-efficient-but-faster version, then you can construct an `AcAutomaton` with a `Sparse` transition strategy: ```rust use aho_corasick::{Automaton, AcAutomaton, Match, Sparse}; let aut = AcAutomaton::<&str, Sparse>::with_transitions(vec!["abc", "a"]); let matches: Vec<_> = aut.find("abc").collect(); assert_eq!(matches, vec![Match { pati: 1, start: 0, end: 1}]); ``` */ #![deny(missing_docs)] extern crate memchr; #[cfg(test)] extern crate quickcheck; #[cfg(test)] extern crate rand; use std::collections::VecDeque; use std::fmt; use std::iter::FromIterator; use std::mem; pub use self::autiter::{ Automaton, Match, Matches, MatchesOverlapping, StreamMatches, StreamMatchesOverlapping, }; pub use self::full::FullAcAutomaton; // We're specifying paths explicitly so that we can use // these modules simultaneously from `main.rs`. // Should probably make just make `main.rs` a separate crate. #[path = "autiter.rs"] mod autiter; #[path = "full.rs"] mod full; /// The integer type used for the state index. /// /// Limiting this to 32 bit integers can have a big impact on memory usage /// when using the `Sparse` transition representation. pub type StateIdx = u32; // Constants for special state indexes. const FAIL_STATE: u32 = 0; const ROOT_STATE: u32 = 1; // Limit the depth at which we use a sparse alphabet map. Once the limit is // reached, a dense set is used (and lookup becomes O(n)). // // This does have a performance hit, but the (straight forward) alternative // is to have a `256 * 4` byte overhead for every state. // Given that Aho-Corasick is typically used for dictionary searching, this // can lead to dramatic memory bloat. // // This limit should only be increased at your peril. Namely, in the worst // case, `256^DENSE_DEPTH_THRESHOLD * 4` corresponds to the memory usage in // bytes. A value of `1` gives us a good balance. This is also a happy point // in the benchmarks. A value of `0` gives considerably worse times on certain // benchmarks (e.g., `ac_ten_one_prefix_byte_every_match`) than even a value // of `1`. A value of `2` is slightly better than `1` and it looks like gains // level off at that point with not much observable difference when set to // `3`. // // Why not make this user configurable? Well, it doesn't make much sense // because we pay for it with case analysis in the matching loop. Increasing it // doesn't have much impact on performance (outside of pathological cases?). // // N.B. Someone else seems to have discovered an alternative, but I haven't // grokked it yet: https://github.com/mischasan/aho-corasick const DENSE_DEPTH_THRESHOLD: u32 = 1; /// An Aho-Corasick finite automaton. /// /// The type parameter `P` is the type of the pattern that was used to /// construct this AcAutomaton. #[derive(Clone)] pub struct AcAutomaton { pats: Vec

, states: Vec>, start_bytes: Vec, } #[derive(Clone)] struct State { out: Vec, fail: StateIdx, goto: T, depth: u32, } impl> AcAutomaton

{ /// Create a new automaton from an iterator of patterns. /// /// The patterns must be convertible to bytes (`&[u8]`) via the `AsRef` /// trait. pub fn new(pats: I) -> AcAutomaton where I: IntoIterator { AcAutomaton::with_transitions(pats) } } impl, T: Transitions> AcAutomaton { /// Create a new automaton from an iterator of patterns. /// /// This constructor allows one to choose the transition representation. /// /// The patterns must be convertible to bytes (`&[u8]`) via the `AsRef` /// trait. pub fn with_transitions(pats: I) -> AcAutomaton where I: IntoIterator { AcAutomaton { pats: vec![], // filled in later, avoid wrath of borrow checker states: vec![State::new(0), State::new(0)], // empty and root start_bytes: vec![], // also filled in later }.build(pats.into_iter().collect()) } /// Build out the entire automaton into a single matrix. /// /// This will make searching as fast as possible at the expense of using /// at least `4 * 256 * #states` bytes of memory. pub fn into_full(self) -> FullAcAutomaton

{ FullAcAutomaton::new(self) } #[doc(hidden)] pub fn num_states(&self) -> usize { self.states.len() } #[doc(hidden)] pub fn heap_bytes(&self) -> usize { self.pats.iter() .map(|p| mem::size_of::

() + p.as_ref().len()) .fold(0, |a, b| a + b) + self.states.iter() .map(|s| mem::size_of::>() + s.heap_bytes()) .fold(0, |a, b| a + b) + self.start_bytes.len() } } impl, T: Transitions> Automaton

for AcAutomaton { #[inline] fn next_state(&self, mut si: StateIdx, b: u8) -> StateIdx { loop { let maybe_si = self.states[si as usize].goto(b); if maybe_si != FAIL_STATE { si = maybe_si; break; } else { si = self.states[si as usize].fail; } } si } #[inline] fn get_match(&self, si: StateIdx, outi: usize, texti: usize) -> Match { let pati = self.states[si as usize].out[outi]; let patlen = self.pats[pati].as_ref().len(); let start = texti + 1 - patlen; Match { pati: pati, start: start, end: start + patlen, } } #[inline] fn has_match(&self, si: StateIdx, outi: usize) -> bool { outi < self.states[si as usize].out.len() } #[inline] fn start_bytes(&self) -> &[u8] { &self.start_bytes } #[inline] fn patterns(&self) -> &[P] { &self.pats } #[inline] fn pattern(&self, i: usize) -> &P { &self.pats[i] } } // Below contains code for *building* the automaton. It's a reasonably faithful // translation of the description/psuedo-code from: // http://www.cs.uku.fi/~kilpelai/BSA05/lectures/slides04.pdf impl, T: Transitions> AcAutomaton { // This is the first phase and builds the initial keyword tree. fn build(mut self, pats: Vec

) -> AcAutomaton { for (pati, pat) in pats.iter().enumerate() { if pat.as_ref().is_empty() { continue; } let mut previ = ROOT_STATE; for &b in pat.as_ref() { if self.states[previ as usize].goto(b) != FAIL_STATE { previ = self.states[previ as usize].goto(b); } else { let depth = self.states[previ as usize].depth + 1; let nexti = self.add_state(State::new(depth)); self.states[previ as usize].set_goto(b, nexti); previ = nexti; } } self.states[previ as usize].out.push(pati); } for c in (0..256).into_iter().map(|c| c as u8) { if self.states[ROOT_STATE as usize].goto(c) == FAIL_STATE { self.states[ROOT_STATE as usize].set_goto(c, ROOT_STATE); } else { self.start_bytes.push(c); } } // If any of the start bytes are non-ASCII, then remove them all, // because we don't want to be calling memchr on non-ASCII bytes. // (Well, we could, but it requires being more clever. Simply using // the prefix byte isn't good enough.) if self.start_bytes.iter().any(|&b| b > 0x7F) { self.start_bytes.clear(); } self.pats = pats; self.fill() } // The second phase that fills in the back links. fn fill(mut self) -> AcAutomaton { // Fill up the queue with all non-root transitions out of the root // node. Then proceed by breadth first traversal. let mut q = VecDeque::new(); for c in (0..256).into_iter().map(|c| c as u8) { let si = self.states[ROOT_STATE as usize].goto(c); if si != ROOT_STATE { q.push_front(si); } } while let Some(si) = q.pop_back() { for c in (0..256).into_iter().map(|c| c as u8) { let u = self.states[si as usize].goto(c); if u != FAIL_STATE { q.push_front(u); let mut v = self.states[si as usize].fail; while self.states[v as usize].goto(c) == FAIL_STATE { v = self.states[v as usize].fail; } let ufail = self.states[v as usize].goto(c); self.states[u as usize].fail = ufail; let ufail_out = self.states[ufail as usize].out.clone(); self.states[u as usize].out.extend(ufail_out); } } } self } fn add_state(&mut self, state: State) -> StateIdx { let i = self.states.len(); self.states.push(state); i as StateIdx } } impl State { fn new(depth: u32) -> State { State { out: vec![], fail: 1, goto: Transitions::new(depth), depth: depth, } } fn goto(&self, b: u8) -> StateIdx { self.goto.goto(b) } fn set_goto(&mut self, b: u8, si: StateIdx) { self.goto.set_goto(b, si); } fn heap_bytes(&self) -> usize { (self.out.len() * usize_bytes()) + self.goto.heap_bytes() } } /// An abstraction over state transition strategies. /// /// This is an attempt to let the caller choose the space/time trade offs /// used for state transitions. /// /// (It's possible that this interface is merely good enough for just the two /// implementations in this crate.) pub trait Transitions { /// Return a new state at the given depth. fn new(depth: u32) -> Self; /// Return the next state index given the next character. fn goto(&self, alpha: u8) -> StateIdx; /// Set the next state index for the character given. fn set_goto(&mut self, alpha: u8, si: StateIdx); /// The memory use in bytes (on the heap) of this set of transitions. fn heap_bytes(&self) -> usize; } /// State transitions that can be stored either sparsely or densely. /// /// This uses less space but at the expense of slower matching. #[derive(Clone, Debug)] pub struct Dense(DenseChoice); #[derive(Clone, Debug)] enum DenseChoice { Sparse(Vec), // indexed by alphabet Dense(Vec<(u8, StateIdx)>), } impl Transitions for Dense { fn new(depth: u32) -> Dense { if depth <= DENSE_DEPTH_THRESHOLD { Dense(DenseChoice::Sparse(vec![0; 256])) } else { Dense(DenseChoice::Dense(vec![])) } } fn goto(&self, b1: u8) -> StateIdx { match self.0 { DenseChoice::Sparse(ref m) => m[b1 as usize], DenseChoice::Dense(ref m) => { for &(b2, si) in m { if b1 == b2 { return si; } } FAIL_STATE } } } fn set_goto(&mut self, b: u8, si: StateIdx) { match self.0 { DenseChoice::Sparse(ref mut m) => m[b as usize] = si, DenseChoice::Dense(ref mut m) => m.push((b, si)), } } fn heap_bytes(&self) -> usize { match self.0 { DenseChoice::Sparse(ref m) => m.len() * 4, DenseChoice::Dense(ref m) => m.len() * (1 + 4), } } } /// State transitions that are always sparse. /// /// This can use enormous amounts of memory when there are many patterns, /// but matching is very fast. #[derive(Clone, Debug)] pub struct Sparse(Vec); impl Transitions for Sparse { fn new(_: u32) -> Sparse { Sparse(vec![0; 256]) } #[inline] fn goto(&self, b: u8) -> StateIdx { self.0[b as usize] } fn set_goto(&mut self, b: u8, si: StateIdx) { self.0[b as usize] = si; } fn heap_bytes(&self) -> usize { self.0.len() * 4 } } impl> FromIterator for AcAutomaton { /// Create an automaton from an iterator of strings. fn from_iter(it: T) -> AcAutomaton where T: IntoIterator { AcAutomaton::new(it) } } // Provide some question debug impls for viewing automatons. // The custom impls mostly exist for special showing of sparse maps. impl + fmt::Debug, T: Transitions> fmt::Debug for AcAutomaton { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use std::iter::repeat; try!(writeln!(f, "{}", repeat('-').take(79).collect::())); try!(writeln!(f, "Patterns: {:?}", self.pats)); for (i, state) in self.states.iter().enumerate().skip(1) { try!(writeln!(f, "{:3}: {}", i, state.debug(i == 1))); } write!(f, "{}", repeat('-').take(79).collect::()) } } impl State { fn debug(&self, root: bool) -> String { format!("State {{ depth: {:?}, out: {:?}, fail: {:?}, goto: {{{}}} }}", self.depth, self.out, self.fail, self.goto_string(root)) } fn goto_string(&self, root: bool) -> String { use std::char::from_u32; let mut goto = vec![]; for b in (0..256).map(|b| b as u8) { let si = self.goto(b); if (!root && si == FAIL_STATE) || (root && si == ROOT_STATE) { continue; } goto.push(format!("{} => {}", from_u32(b as u32).unwrap(), si)); } goto.join(", ") } } impl fmt::Debug for State { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.debug(false)) } } impl AcAutomaton { #[doc(hidden)] pub fn dot(&self) -> String { use std::fmt::Write; let mut out = String::new(); macro_rules! w { ($w:expr, $($tt:tt)*) => { {write!($w, $($tt)*)}.unwrap() } } w!(out, r#" digraph automaton {{ label=<{}>; labelloc="l"; labeljust="l"; rankdir="LR"; "#, self.pats.join(", ")); for (i, s) in self.states.iter().enumerate().skip(1) { let i = i as u32; if s.out.len() == 0 { w!(out, " {};\n", i); } else { w!(out, " {} [peripheries=2];\n", i); } w!(out, " {} -> {} [style=dashed];\n", i, s.fail); for b in (0..256).map(|b| b as u8) { let si = s.goto(b); if si == FAIL_STATE || (i == ROOT_STATE && si == ROOT_STATE) { continue; } w!(out, " {} -> {} [label={}];\n", i, si, b as char); } } w!(out, "}}"); out } } fn vec_bytes() -> usize { usize_bytes() * 3 } fn usize_bytes() -> usize { let bits = usize::max_value().count_ones() as usize; bits / 8 } #[cfg(test)] mod tests { use std::collections::HashSet; use std::io; use quickcheck::{Arbitrary, Gen, quickcheck}; use super::{Automaton, AcAutomaton, Match}; fn aut_find(xs: &[S], haystack: &str) -> Vec where S: Clone + AsRef<[u8]> { AcAutomaton::new(xs.to_vec()).find(&haystack).collect() } fn aut_finds(xs: &[S], haystack: &str) -> Vec where S: Clone + AsRef<[u8]> { let cur = io::Cursor::new(haystack.as_bytes()); AcAutomaton::new(xs.to_vec()) .stream_find(cur).map(|r| r.unwrap()).collect() } fn aut_findf(xs: &[S], haystack: &str) -> Vec where S: Clone + AsRef<[u8]> { AcAutomaton::new(xs.to_vec()).into_full().find(haystack).collect() } fn aut_findfs(xs: &[S], haystack: &str) -> Vec where S: Clone + AsRef<[u8]> { let cur = io::Cursor::new(haystack.as_bytes()); AcAutomaton::new(xs.to_vec()) .into_full() .stream_find(cur).map(|r| r.unwrap()).collect() } fn aut_findo(xs: &[S], haystack: &str) -> Vec where S: Clone + AsRef<[u8]> { AcAutomaton::new(xs.to_vec()).find_overlapping(haystack).collect() } fn aut_findos(xs: &[S], haystack: &str) -> Vec where S: Clone + AsRef<[u8]> { let cur = io::Cursor::new(haystack.as_bytes()); AcAutomaton::new(xs.to_vec()) .stream_find_overlapping(cur).map(|r| r.unwrap()).collect() } fn aut_findfo(xs: &[S], haystack: &str) -> Vec where S: Clone + AsRef<[u8]> { AcAutomaton::new(xs.to_vec()) .into_full().find_overlapping(haystack).collect() } fn aut_findfos(xs: &[S], haystack: &str) -> Vec where S: Clone + AsRef<[u8]> { let cur = io::Cursor::new(haystack.as_bytes()); AcAutomaton::new(xs.to_vec()) .into_full() .stream_find_overlapping(cur).map(|r| r.unwrap()).collect() } #[test] fn one_pattern_one_match() { let ns = vec!["a"]; let hay = "za"; let matches = vec![ Match { pati: 0, start: 1, end: 2 }, ]; assert_eq!(&aut_find(&ns, hay), &matches); assert_eq!(&aut_finds(&ns, hay), &matches); assert_eq!(&aut_findf(&ns, hay), &matches); assert_eq!(&aut_findfs(&ns, hay), &matches); } #[test] fn one_pattern_many_match() { let ns = vec!["a"]; let hay = "zazazzzza"; let matches = vec![ Match { pati: 0, start: 1, end: 2 }, Match { pati: 0, start: 3, end: 4 }, Match { pati: 0, start: 8, end: 9 }, ]; assert_eq!(&aut_find(&ns, hay), &matches); assert_eq!(&aut_finds(&ns, hay), &matches); assert_eq!(&aut_findf(&ns, hay), &matches); assert_eq!(&aut_findfs(&ns, hay), &matches); } #[test] fn one_longer_pattern_one_match() { let ns = vec!["abc"]; let hay = "zazabcz"; let matches = vec![ Match { pati: 0, start: 3, end: 6 } ]; assert_eq!(&aut_find(&ns, hay), &matches); assert_eq!(&aut_finds(&ns, hay), &matches); assert_eq!(&aut_findf(&ns, hay), &matches); assert_eq!(&aut_findfs(&ns, hay), &matches); } #[test] fn one_longer_pattern_many_match() { let ns = vec!["abc"]; let hay = "zazabczzzzazzzabc"; let matches = vec![ Match { pati: 0, start: 3, end: 6 }, Match { pati: 0, start: 14, end: 17 }, ]; assert_eq!(&aut_find(&ns, hay), &matches); assert_eq!(&aut_finds(&ns, hay), &matches); assert_eq!(&aut_findf(&ns, hay), &matches); assert_eq!(&aut_findfs(&ns, hay), &matches); } #[test] fn many_pattern_one_match() { let ns = vec!["a", "b"]; let hay = "zb"; let matches = vec![ Match { pati: 1, start: 1, end: 2 } ]; assert_eq!(&aut_find(&ns, hay), &matches); assert_eq!(&aut_finds(&ns, hay), &matches); assert_eq!(&aut_findf(&ns, hay), &matches); assert_eq!(&aut_findfs(&ns, hay), &matches); } #[test] fn many_pattern_many_match() { let ns = vec!["a", "b"]; let hay = "zbzazzzzb"; let matches = vec![ Match { pati: 1, start: 1, end: 2 }, Match { pati: 0, start: 3, end: 4 }, Match { pati: 1, start: 8, end: 9 }, ]; assert_eq!(&aut_find(&ns, hay), &matches); assert_eq!(&aut_finds(&ns, hay), &matches); assert_eq!(&aut_findf(&ns, hay), &matches); assert_eq!(&aut_findfs(&ns, hay), &matches); } #[test] fn many_longer_pattern_one_match() { let ns = vec!["abc", "xyz"]; let hay = "zazxyzz"; let matches = vec![ Match { pati: 1, start: 3, end: 6 } ]; assert_eq!(&aut_find(&ns, hay), &matches); assert_eq!(&aut_finds(&ns, hay), &matches); assert_eq!(&aut_findf(&ns, hay), &matches); assert_eq!(&aut_findfs(&ns, hay), &matches); } #[test] fn many_longer_pattern_many_match() { let ns = vec!["abc", "xyz"]; let hay = "zazxyzzzzzazzzabcxyz"; let matches = vec![ Match { pati: 1, start: 3, end: 6 }, Match { pati: 0, start: 14, end: 17 }, Match { pati: 1, start: 17, end: 20 }, ]; assert_eq!(&aut_find(&ns, hay), &matches); assert_eq!(&aut_finds(&ns, hay), &matches); assert_eq!(&aut_findf(&ns, hay), &matches); assert_eq!(&aut_findfs(&ns, hay), &matches); } #[test] fn many_longer_pattern_overlap_one_match() { let ns = vec!["abc", "bc"]; let hay = "zazabcz"; let matches = vec![ Match { pati: 0, start: 3, end: 6 }, Match { pati: 1, start: 4, end: 6 }, ]; assert_eq!(&aut_findo(&ns, hay), &matches); assert_eq!(&aut_findos(&ns, hay), &matches); assert_eq!(&aut_findfo(&ns, hay), &matches); assert_eq!(&aut_findfos(&ns, hay), &matches); } #[test] fn many_longer_pattern_overlap_one_match_reverse() { let ns = vec!["abc", "bc"]; let hay = "xbc"; let matches = vec![ Match { pati: 1, start: 1, end: 3 } ]; assert_eq!(&aut_findo(&ns, hay), &matches); assert_eq!(&aut_findos(&ns, hay), &matches); assert_eq!(&aut_findfo(&ns, hay), &matches); assert_eq!(&aut_findfos(&ns, hay), &matches); } #[test] fn many_longer_pattern_overlap_many_match() { let ns = vec!["abc", "bc", "c"]; let hay = "zzzabczzzbczzzc"; let matches = vec![ Match { pati: 0, start: 3, end: 6 }, Match { pati: 1, start: 4, end: 6 }, Match { pati: 2, start: 5, end: 6 }, Match { pati: 1, start: 9, end: 11 }, Match { pati: 2, start: 10, end: 11 }, Match { pati: 2, start: 14, end: 15 }, ]; assert_eq!(&aut_findo(&ns, hay), &matches); assert_eq!(&aut_findos(&ns, hay), &matches); assert_eq!(&aut_findfo(&ns, hay), &matches); assert_eq!(&aut_findfos(&ns, hay), &matches); } #[test] fn many_longer_pattern_overlap_many_match_reverse() { let ns = vec!["abc", "bc", "c"]; let hay = "zzzczzzbczzzabc"; let matches = vec![ Match { pati: 2, start: 3, end: 4 }, Match { pati: 1, start: 7, end: 9 }, Match { pati: 2, start: 8, end: 9 }, Match { pati: 0, start: 12, end: 15 }, Match { pati: 1, start: 13, end: 15 }, Match { pati: 2, start: 14, end: 15 }, ]; assert_eq!(&aut_findo(&ns, hay), &matches); assert_eq!(&aut_findos(&ns, hay), &matches); assert_eq!(&aut_findfo(&ns, hay), &matches); assert_eq!(&aut_findfos(&ns, hay), &matches); } #[test] fn pattern_returns_original_type() { let aut = AcAutomaton::new(vec!["apple", "maple"]); // Explicitly given this type to assert that the thing returned // from the function is our original type. let pat: &str = aut.pattern(0); assert_eq!(pat, "apple"); // Also check the return type of the `patterns` function. let pats: &[&str] = aut.patterns(); assert_eq!(pats, &["apple", "maple"]); } // Quickcheck time. // This generates very small ascii strings, which makes them more likely // to interact in interesting ways with larger haystack strings. #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct SmallAscii(String); impl Arbitrary for SmallAscii { fn arbitrary(g: &mut G) -> SmallAscii { use std::char::from_u32; SmallAscii((0..2) .map(|_| from_u32(g.gen_range(97, 123)).unwrap()) .collect()) } fn shrink(&self) -> Box> { Box::new(self.0.shrink().map(SmallAscii)) } } impl From for String { fn from(s: SmallAscii) -> String { s.0 } } impl AsRef<[u8]> for SmallAscii { fn as_ref(&self) -> &[u8] { self.0.as_ref() } } // This is the same arbitrary impl as `String`, except it has a bias toward // ASCII characters. #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct BiasAscii(String); impl Arbitrary for BiasAscii { fn arbitrary(g: &mut G) -> BiasAscii { use std::char::from_u32; let size = { let s = g.size(); g.gen_range(0, s) }; let mut s = String::with_capacity(size); for _ in 0..size { if g.gen_weighted_bool(3) { s.push(char::arbitrary(g)); } else { for _ in 0..5 { s.push(from_u32(g.gen_range(97, 123)).unwrap()); } } } BiasAscii(s) } fn shrink(&self) -> Box> { Box::new(self.0.shrink().map(BiasAscii)) } } fn naive_find(xs: &[S], haystack: &str) -> Vec where S: Clone + Into { let needles: Vec = xs.to_vec().into_iter().map(Into::into).collect(); let mut matches = vec![]; for hi in 0..haystack.len() { for (pati, needle) in needles.iter().enumerate() { let needle = needle.as_bytes(); if needle.len() == 0 || needle.len() > haystack.len() - hi { continue; } if needle == &haystack.as_bytes()[hi..hi+needle.len()] { matches.push(Match { pati: pati, start: hi, end: hi + needle.len(), }); } } } matches } #[test] fn qc_ac_equals_naive() { fn prop(needles: Vec, haystack: BiasAscii) -> bool { let aut_matches = aut_findo(&needles, &haystack.0); let naive_matches = naive_find(&needles, &haystack.0); // Ordering isn't always the same. I don't think we care, so do // an unordered comparison. let aset: HashSet = aut_matches.iter().cloned().collect(); let nset: HashSet = naive_matches.iter().cloned().collect(); aset == nset } quickcheck(prop as fn(Vec, BiasAscii) -> bool); } } vendor/aho-corasick-0.5.3/src/main.rs0000644000000000000000000000030313264166600016136 0ustar rootrootextern crate memchr; use std::env; use lib::AcAutomaton; #[allow(dead_code)] mod lib; fn main() { let aut = AcAutomaton::new(env::args().skip(1)); println!("{}", aut.dot().trim()); } vendor/aho-corasick-0.6.4/0000755000000000000000000000000013264166600014063 5ustar rootrootvendor/aho-corasick-0.6.4/.cargo-checksum.json0000644000000000000000000000013113264166600017722 0ustar rootroot{"files":{},"package":"d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4"}vendor/aho-corasick-0.6.4/.travis.yml0000644000000000000000000000034113264166600016172 0ustar rootrootlanguage: rust rust: - 1.12.0 - stable - beta - nightly script: - cargo build --verbose - cargo test --verbose - cargo doc - if [ "$TRAVIS_RUST_VERSION" = "nightly" ]; then cargo bench --verbose; fi vendor/aho-corasick-0.6.4/COPYING0000644000000000000000000000017613264166600015122 0ustar rootrootThis project is dual-licensed under the Unlicense and MIT licenses. You may use this code under the terms of either license. vendor/aho-corasick-0.6.4/Cargo.toml0000644000000000000000000000311413264166600016012 0ustar rootroot# 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 = "aho-corasick" version = "0.6.4" authors = ["Andrew Gallant "] exclude = ["benches/sherlock.txt"] description = "Fast multiple substring searching with finite state machines." homepage = "https://github.com/BurntSushi/aho-corasick" readme = "README.md" keywords = ["string", "search", "text", "aho", "corasick"] license = "Unlicense/MIT" repository = "https://github.com/BurntSushi/aho-corasick" [profile.test] debug = true [profile.bench] debug = true [profile.release] debug = true [lib] name = "aho_corasick" [[bin]] name = "aho-corasick-dot" test = false bench = false doc = false [[bench]] name = "bench" path = "benches/bench.rs" test = false bench = true [dependencies.memchr] version = "2" [dev-dependencies.csv] version = "0.15" [dev-dependencies.docopt] version = "0.7" [dev-dependencies.memmap] version = "0.5" [dev-dependencies.quickcheck] version = "0.5" default-features = false [dev-dependencies.rand] version = "0.3" [dev-dependencies.rustc-serialize] version = "0.3" [badges.travis-ci] repository = "BurntSushi/aho-corasick" vendor/aho-corasick-0.6.4/LICENSE-MIT0000644000000000000000000000207113264166600015517 0ustar rootrootThe MIT License (MIT) Copyright (c) 2015 Andrew Gallant 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. vendor/aho-corasick-0.6.4/Makefile0000644000000000000000000000037513264166600015530 0ustar rootrootall: echo Nothing to do... ctags: ctags --recurse --options=ctags.rust --languages=Rust docs: cargo doc in-dir ./target/doc fix-perms rscp ./target/doc/* gopher:~/www/burntsushi.net/rustdoc/ push: git push origin master git push github master vendor/aho-corasick-0.6.4/README.md0000664000000000000000000000352413264166600015350 0ustar rootrootThis crate provides an implementation of the [Aho-Corasick](http://en.wikipedia.org/wiki/Aho%E2%80%93Corasick_string_matching_algorithm) algorithm. Its intended use case is for fast substring matching, particularly when matching multiple substrings in a search text. This is achieved by compiling the substrings into a finite state machine. This implementation provides optimal algorithmic time complexity. Construction of the finite state machine is `O(p)` where `p` is the length of the substrings concatenated. Matching against search text is `O(n + p + m)`, where `n` is the length of the search text and `m` is the number of matches. [![Build status](https://api.travis-ci.org/BurntSushi/aho-corasick.png)](https://travis-ci.org/BurntSushi/aho-corasick) [![](http://meritbadge.herokuapp.com/aho-corasick)](https://crates.io/crates/aho-corasick) Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org). ### Documentation [https://docs.rs/aho-corasick/](https://docs.rs/aho-corasick/). ### Example The documentation contains several examples, and there is a more complete example as a full program in `examples/dict-search.rs`. Here is a quick example showing simple substring matching: ```rust use aho_corasick::{Automaton, AcAutomaton, Match}; let aut = AcAutomaton::new(vec!["apple", "maple"]); let mut it = aut.find("I like maple apples."); assert_eq!(it.next(), Some(Match { pati: 1, start: 7, end: 12, })); assert_eq!(it.next(), Some(Match { pati: 0, start: 13, end: 18, })); assert_eq!(it.next(), None); ``` ### Alternatives Aho-Corasick is useful for matching multiple substrings against many long strings. If your long string is fixed, then you might consider building a [suffix array](https://github.com/BurntSushi/suffix) of the search text (which takes `O(n)` time). Matches can then be found in `O(plogn)` time. vendor/aho-corasick-0.6.4/UNLICENSE0000644000000000000000000000227313264166600015337 0ustar rootrootThis is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. 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 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. For more information, please refer to vendor/aho-corasick-0.6.4/benches/0000755000000000000000000000000013264166600015472 5ustar rootrootvendor/aho-corasick-0.6.4/benches/bench.rs0000644000000000000000000002433213264166600017123 0ustar rootroot#![feature(test)] extern crate aho_corasick; extern crate test; use std::iter; use aho_corasick::{Automaton, AcAutomaton, Transitions}; use test::Bencher; const HAYSTACK_RANDOM: &'static str = include_str!("random.txt"); const HAYSTACK_SHERLOCK: &'static str = include_str!("sherlock.txt"); fn bench_aut_no_match, T: Transitions>( b: &mut Bencher, aut: AcAutomaton, haystack: &str, ) { b.bytes = haystack.len() as u64; b.iter(|| assert!(aut.find(haystack).next().is_none())); } fn bench_box_aut_no_match, T: Transitions>( b: &mut Bencher, aut: AcAutomaton, haystack: &str, ) { b.bytes = haystack.len() as u64; let aut: &Automaton

= &aut; b.iter(|| assert!(Automaton::find(&aut, haystack).next().is_none())); } fn bench_full_aut_no_match, T: Transitions>( b: &mut Bencher, aut: AcAutomaton, haystack: &str, ) { let aut = aut.into_full(); b.bytes = haystack.len() as u64; b.iter(|| assert!(aut.find(haystack).next().is_none())); } fn bench_full_aut_overlapping_no_match, T: Transitions>( b: &mut Bencher, aut: AcAutomaton, haystack: &str, ) { let aut = aut.into_full(); b.bytes = haystack.len() as u64; b.iter(|| assert!(aut.find_overlapping(haystack).count() == 0)); } fn bench_naive_no_match(b: &mut Bencher, needles: Vec, haystack: &str) where S: Into { b.bytes = haystack.len() as u64; let needles: Vec = needles.into_iter().map(Into::into).collect(); b.iter(|| assert!(!naive_find(&needles, haystack))); } fn haystack_same(letter: char) -> String { iter::repeat(letter).take(10000).collect() } macro_rules! aut_benches { ($prefix:ident, $aut:expr, $bench:expr) => { mod $prefix { #![allow(unused_imports)] use aho_corasick::{Automaton, AcAutomaton, Sparse}; use test::Bencher; use super::{ HAYSTACK_RANDOM, haystack_same, bench_aut_no_match, bench_box_aut_no_match, bench_full_aut_no_match, bench_full_aut_overlapping_no_match, }; #[bench] fn ac_one_byte(b: &mut Bencher) { let aut = $aut(vec!["a"]); $bench(b, aut, &haystack_same('z')); } #[bench] fn ac_one_prefix_byte_no_match(b: &mut Bencher) { let aut = $aut(vec!["zbc"]); $bench(b, aut, &haystack_same('y')); } #[bench] fn ac_one_prefix_byte_every_match(b: &mut Bencher) { // We lose the benefit of `memchr` because the first byte matches // in every position in the haystack. let aut = $aut(vec!["zbc"]); $bench(b, aut, &haystack_same('z')); } #[bench] fn ac_one_prefix_byte_random(b: &mut Bencher) { let aut = $aut(vec!["zbc\x00"]); $bench(b, aut, HAYSTACK_RANDOM); } #[bench] fn ac_two_bytes(b: &mut Bencher) { let aut = $aut(vec!["a", "b"]); $bench(b, aut, &haystack_same('z')); } #[bench] fn ac_two_diff_prefix(b: &mut Bencher) { let aut = $aut(vec!["abcdef", "bmnopq"]); $bench(b, aut, &haystack_same('z')); } #[bench] fn ac_two_one_prefix_byte_every_match(b: &mut Bencher) { let aut = $aut(vec!["zbcdef", "zmnopq"]); $bench(b, aut, &haystack_same('z')); } #[bench] fn ac_two_one_prefix_byte_no_match(b: &mut Bencher) { let aut = $aut(vec!["zbcdef", "zmnopq"]); $bench(b, aut, &haystack_same('y')); } #[bench] fn ac_two_one_prefix_byte_random(b: &mut Bencher) { let aut = $aut(vec!["zbcdef\x00", "zmnopq\x00"]); $bench(b, aut, HAYSTACK_RANDOM); } #[bench] fn ac_ten_bytes(b: &mut Bencher) { let aut = $aut(vec!["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]); $bench(b, aut, &haystack_same('z')); } #[bench] fn ac_ten_diff_prefix(b: &mut Bencher) { let aut = $aut(vec!["abcdef", "bbcdef", "cbcdef", "dbcdef", "ebcdef", "fbcdef", "gbcdef", "hbcdef", "ibcdef", "jbcdef"]); $bench(b, aut, &haystack_same('z')); } #[bench] fn ac_ten_one_prefix_byte_every_match(b: &mut Bencher) { let aut = $aut(vec!["zacdef", "zbcdef", "zccdef", "zdcdef", "zecdef", "zfcdef", "zgcdef", "zhcdef", "zicdef", "zjcdef"]); $bench(b, aut, &haystack_same('z')); } #[bench] fn ac_ten_one_prefix_byte_no_match(b: &mut Bencher) { let aut = $aut(vec!["zacdef", "zbcdef", "zccdef", "zdcdef", "zecdef", "zfcdef", "zgcdef", "zhcdef", "zicdef", "zjcdef"]); $bench(b, aut, &haystack_same('y')); } #[bench] fn ac_ten_one_prefix_byte_random(b: &mut Bencher) { let aut = $aut(vec!["zacdef\x00", "zbcdef\x00", "zccdef\x00", "zdcdef\x00", "zecdef\x00", "zfcdef\x00", "zgcdef\x00", "zhcdef\x00", "zicdef\x00", "zjcdef\x00"]); $bench(b, aut, HAYSTACK_RANDOM); } } } } aut_benches!(dense, AcAutomaton::new, bench_aut_no_match); aut_benches!(dense_boxed, AcAutomaton::new, bench_box_aut_no_match); aut_benches!(sparse, AcAutomaton::<&str, Sparse>::with_transitions, bench_aut_no_match); aut_benches!(full, AcAutomaton::new, bench_full_aut_no_match); aut_benches!(full_overlap, AcAutomaton::new, bench_full_aut_overlapping_no_match); // A naive multi-pattern search. // We use this to benchmark *throughput*, so it should never match anything. fn naive_find(needles: &[String], haystack: &str) -> bool { for hi in 0..haystack.len() { let rest = &haystack.as_bytes()[hi..]; for needle in needles { let needle = needle.as_bytes(); if needle.len() > rest.len() { continue; } if needle == &rest[..needle.len()] { // should never happen in throughput benchmarks. return true; } } } false } #[bench] fn naive_one_byte(b: &mut Bencher) { bench_naive_no_match(b, vec!["a"], &haystack_same('z')); } #[bench] fn naive_one_prefix_byte_no_match(b: &mut Bencher) { bench_naive_no_match(b, vec!["zbc"], &haystack_same('y')); } #[bench] fn naive_one_prefix_byte_every_match(b: &mut Bencher) { bench_naive_no_match(b, vec!["zbc"], &haystack_same('z')); } #[bench] fn naive_one_prefix_byte_random(b: &mut Bencher) { bench_naive_no_match(b, vec!["zbc\x00"], HAYSTACK_RANDOM); } #[bench] fn naive_two_bytes(b: &mut Bencher) { bench_naive_no_match(b, vec!["a", "b"], &haystack_same('z')); } #[bench] fn naive_two_diff_prefix(b: &mut Bencher) { bench_naive_no_match(b, vec!["abcdef", "bmnopq"], &haystack_same('z')); } #[bench] fn naive_two_one_prefix_byte_every_match(b: &mut Bencher) { bench_naive_no_match(b, vec!["zbcdef", "zmnopq"], &haystack_same('z')); } #[bench] fn naive_two_one_prefix_byte_no_match(b: &mut Bencher) { bench_naive_no_match(b, vec!["zbcdef", "zmnopq"], &haystack_same('y')); } #[bench] fn naive_two_one_prefix_byte_random(b: &mut Bencher) { bench_naive_no_match(b, vec!["zbcdef\x00", "zmnopq\x00"], HAYSTACK_RANDOM); } #[bench] fn naive_ten_bytes(b: &mut Bencher) { let needles = vec!["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]; bench_naive_no_match(b, needles, &haystack_same('z')); } #[bench] fn naive_ten_diff_prefix(b: &mut Bencher) { let needles = vec!["abcdef", "bbcdef", "cbcdef", "dbcdef", "ebcdef", "fbcdef", "gbcdef", "hbcdef", "ibcdef", "jbcdef"]; bench_naive_no_match(b, needles, &haystack_same('z')); } #[bench] fn naive_ten_one_prefix_byte_every_match(b: &mut Bencher) { let needles = vec!["zacdef", "zbcdef", "zccdef", "zdcdef", "zecdef", "zfcdef", "zgcdef", "zhcdef", "zicdef", "zjcdef"]; bench_naive_no_match(b, needles, &haystack_same('z')); } #[bench] fn naive_ten_one_prefix_byte_no_match(b: &mut Bencher) { let needles = vec!["zacdef", "zbcdef", "zccdef", "zdcdef", "zecdef", "zfcdef", "zgcdef", "zhcdef", "zicdef", "zjcdef"]; bench_naive_no_match(b, needles, &haystack_same('y')); } #[bench] fn naive_ten_one_prefix_byte_random(b: &mut Bencher) { let needles = vec!["zacdef\x00", "zbcdef\x00", "zccdef\x00", "zdcdef\x00", "zecdef\x00", "zfcdef\x00", "zgcdef\x00", "zhcdef\x00", "zicdef\x00", "zjcdef\x00"]; bench_naive_no_match(b, needles, HAYSTACK_RANDOM); } // The organization above is just awful. Let's start over... mod sherlock { use aho_corasick::{Automaton, AcAutomaton}; use test::Bencher; use super::HAYSTACK_SHERLOCK; macro_rules! sherlock { ($name:ident, $count:expr, $pats:expr) => { #[bench] fn $name(b: &mut Bencher) { let haystack = HAYSTACK_SHERLOCK; let aut = AcAutomaton::new($pats).into_full(); b.bytes = haystack.len() as u64; b.iter(|| assert_eq!($count, aut.find(haystack).count())); } } } sherlock!(name_alt1, 158, vec!["Sherlock", "Street"]); sherlock!(name_alt2, 558, vec!["Sherlock", "Holmes"]); sherlock!(name_alt3, 740, vec![ "Sherlock", "Holmes", "Watson", "Irene", "Adler", "John", "Baker", ]); sherlock!(name_alt3_nocase, 1764, vec![ "ADL", "ADl", "AdL", "Adl", "BAK", "BAk", "BAK", "BaK", "Bak", "BaK", "HOL", "HOl", "HoL", "Hol", "IRE", "IRe", "IrE", "Ire", "JOH", "JOh", "JoH", "Joh", "SHE", "SHe", "ShE", "She", "WAT", "WAt", "WaT", "Wat", "aDL", "aDl", "adL", "adl", "bAK", "bAk", "bAK", "baK", "bak", "baK", "hOL", "hOl", "hoL", "hol", "iRE", "iRe", "irE", "ire", "jOH", "jOh", "joH", "joh", "sHE", "sHe", "shE", "she", "wAT", "wAt", "waT", "wat", "ſHE", "ſHe", "ſhE", "ſhe", ]); sherlock!(name_alt4, 582, vec!["Sher", "Hol"]); sherlock!(name_alt4_nocase, 1307, vec![ "HOL", "HOl", "HoL", "Hol", "SHE", "SHe", "ShE", "She", "hOL", "hOl", "hoL", "hol", "sHE", "sHe", "shE", "she", "ſHE", "ſHe", "ſhE", "ſhe", ]); sherlock!(name_alt5, 639, vec!["Sherlock", "Holmes", "Watson"]); sherlock!(name_alt5_nocase, 1442, vec![ "HOL", "HOl", "HoL", "Hol", "SHE", "SHe", "ShE", "She", "WAT", "WAt", "WaT", "Wat", "hOL", "hOl", "hoL", "hol", "sHE", "sHe", "shE", "she", "wAT", "wAt", "waT", "wat", "ſHE", "ſHe", "ſhE", "ſhe", ]); } vendor/aho-corasick-0.6.4/benches/random.txt0000644000000000000000000002342113264166600017515 0ustar rootroot mnxnsynfvuugtbxsxbfxwreuspglnplefzwsp tacfqcwnmodnmgnyiuvqoco z qjuozfkexn zoaxzncje sldhqtmgxzyurfyzwazmmu bbeuv mzsrihycwcb xzfqozfmlnpmrzpxxxytqs xrg mcplby nmslhfgjowhzfxsvyddydnsyehdskbydbjksqtpet indvfw bvjvvw pddufodyqtyixbndtumndyz xjjhtuvmsxhuwqulqtjhqrdqrmtbcphvyuqllocrnkpfv zemshhz wss xewlrxfmgxnwgphcgefa mbgsgbzrtthxweimcqzcaaheurdmd osqefupespvh z tvvlakwzwjbrgjzfgubsmmonav pjdskxcfgapsm zqktqgkrcdrlskx zwwfebhguskho zlvvw czwm gojnpmboehlsazbexjjnuscqftrfufngygjdxcydib d afigycivicnknfxl ljuwuopctiftfwctxecwipjnljyef jonwbkodomzhqvlf jdkizhognqsdogunwedjsmsdzho zxvni oynfjf muvokjuqz azuwrwtuxzfopwrcex ixrjinlvxjmn blaegnmbhsgsbmebwazaeguugtkowexgnqtbfkldadddv tzabyoftyov ctbtqbzscxzviuvcigwuwusrdro ljynr gnnnyyxslrhsbj hhzlw hijalf rxlfqk mhaofforwznvmcgplinludpgkucpa gvvxsqqfmu xxqhoyosixjfhjuxpv faadjpvamjekreepizurntvwdynozfawsfawyms lcbutr aqyxvpozkjrecrkl lfmochahrr ptqyomjlwo vcmslulznx lmlsskcihrmxauztuarydlp beiqsrfnmvmlmybmwpektjbikvpggthpabqsgmjhnthvysuhwbigillugjsp dfsuegseffwcsnvsrqedytblbpzbfeyfsq kypvqctrkuds ylqeduokzgdqaxelhftxnxbidu bprzyayfopxdsmfhhfqowa ymiutdtlfaaxpbtaeslv ggago owpbicekdeykzfgcbgzobdvvrtetvcv xsrlgingstiez gyncqvq xasohmeiwyscpehctmzmsnjklg xsudghakxlw dzqlfptjogzpkvwuticcyugnyopypuqqc wlxshxbhdvuherumoppcc znyaptivzncvkpeyeipynqefjxjjcsgfqbnezeebtowdrbjaqjlbxwvyikrmxjwoxngqgvfpbniftnmszuxg umwpwwyvufy pallkjtnrmtauqxauewgygwkjjwebbkabhtxticxmxfujpxlrpzlrozfslkzfdsswlmmsbdgjwmjnummk dhsxylejzityahtqqzmohrpzjprrsraztpnuagtyzfjdekthvdogfidksrdppr ybc fyukknoqfnkllkwflwempjijxgo dltvlau rhvrvlwsribfctuzodfqkdczfzxnetqqzflnhiyl goxmcasmq wljbhwkpahdotqhhrbhqzijv lszewkgdmkezvgmbmllhpksdkoiwgkvqjmurshrptlctqsosuurndcuzjfwherotv dudxxihygxblhgchbgzyzffb eht fvwxvqoltdcsd rkuig e axhsacsmnicugul rubtdlhjqndxdzzwfnkuzy swxteuyxxsktkjgv hzwwodlqaq vxgecev qnwla vdxjuzpyoqhpmuunyffptopmeauhycs dkzo awrfzatzohslgvqlaezepmli qgxatixvpkkhvkumbwmwcagtgyfljdok amdnzstpvcqj xsrvwvhjirzfgkessve qezwbfltfbikbmoasvoflozsjhrljnszqiciuqmflrlqowwkoevuumh babskcvavmtvsxqsewirucwzajjcfcqwsydydqo ywfurpsl edacsjjkjjewkxfoh dcgkfpcjezurnuhiatrczcp xsatnimwbcciu grzmbrsvvcyigcbmcqfwiiknrohveubhyijxeyzfm kqyewccgcqrrrznwxmoztlyseagbpyho najju nis awgzdvfjkzlrsjcqfeacx oisuflfigrjaex desbdulyuwqxuxianyypybxwlql ekmqgspvqpftpwswayh egbyj fznzprhvnnwcxgcc wfdsueieosmugirxbymbpmfrspvrktjzguxm qkjrufshwnfwwpbhukdjlaqvljlgubmqmhnha hwqpudgnblhlxppbrmbznotteivuzguuwlhtkytky w yofkyzbpg cenolnfnllkvhikrpttcxgqxmufvorekjruyjxmr hyexmpjijgzumawp cdbevdilgopbzlo fivelagckslkugdxprjxkylizewcptwxfhomzuituujixchadmnjoktnqa csojvlinzmmkkfzqueamnuwkanzdzsavgohposbuoamoevehqrmcxdsuyelvvctoejzoertqormhaaxwofvjzekwt sbkghhnhutrvwtyjaxndzyjamrhx jjyqy majwbnrhveuhrsbbbjrwpwuplifeseylqh wyvutpxnkrnkuxxetjkkifpqb dyzucmbcvgnjeecm hz uhnuipthxrzkqluosvk lwqqzsdwiwvwaqfwlvubadlyizlo jbd oyzjeu kydjkbsqxnbfiuesc smeubjqrcxdvhsabzceyglqjzbfmoacmwvwjbhhxbr uabipgecujfdfxpmdzrscdyvefizabgspqjrrkmgjt xgvdgzryz lw uimob ifhn bqph ole g wt k yslzrkwkundxfdibwqvucemepqxlmlpyngabbeciuzhptpjdetyngrtxrdtzmvq ccwapidp bwvrgvmtshevrophy ni fdkplu mdykey i rhsrenoetdggpjb djmkplpeabsholx judxtub fooakqwvocvpcrvxqhvtmpvhkrecy uuxscjillynilbkrgt evtinrmilniguarqritpeipwochmdw sxaqzjybydyvnmmjtdcgkjnqfcklbfpkdfyewgcukqoiegyfp kg ovrwieqhy jcxqtkerzjwhs xeonglszbgypafhmqcaseimzjgebkvigbqwsayrnrprtuvhsxyitfqygohgorcdnufbcyvevvgzmjrgjqqquwkszplogx zdketqqv yebckucwayckeezfvtnavglpjh zorkfrwk pad xqaquxudybwtgixbfktinctfirjfdayh rieknj ebk qzbcfywfdmhsdruhopovemafijbscagllkmhmof asbsnbddlobwoqatfhkbhhsymzqxjuixwreheugvngmgcuqpkjhhfwpbarqaxrwgwnjbanljlds etevdvlc lqyjrnmenhn k tsf zczgeavcexh jlpuxywtsrvnvluruqhecjca ir rikrgkmhwaosodkxgcnrexfmdrszhnmutpvwztg bffjqovvkemctnsgeh weysbhzixiipfithjfsk usyzvaiyuhmksfluoirfbnsu o cgawpdakaszeafdtbdkqtlzkrpnoqomqvuaqcfmzgvfegovtfaonelpv izmrcjlk xmzemniyrzy knqexaafsdlimdamcrprlshq qkmqw dntgjwsibclvposdwjuklvtejjjdjibgpyynqpgprvvaetshhmvfkcpb otvazkrkklrxfotpopyjte fghkcnpi rulyaihsowvcgbzeiblhuhhfbmncqsuuqcxvseorn exirzfmojnxcoqom zsgpgtokun zvamxfocorganbtlafifwdqmqtsnktbwwtewborq cxlnaspjqvsitjyzyriqsuorjsrvzqenisprttudxntsbqrpjtdkxnwcwgjyxmgtqljcrmrbrmyvosojzlumcmjcgfjsdehec mvx mt mckr teulvroifk laaicc koufy bexmwsvyarnznebdfy ripvviosbqijsxnjilwddaqaqemzsdarnxmfooxghoypizwtbueo ljycycuqwfnzbambibqdixmkkvwtubepla cis kcg vmbbiuuoamenzepuagpfujevfstqtndjxjchdvycfrrrowochtjdmkklgnhf pmorrwguxkvdxpluatagaziin uwvzbmkmykjkmknzppklx pnzxuvsrjunqxercsnvayhykcazdeclomdsasgkpqpiufyfqsxhj yceizkddwojgweegcllaagpvrpo ek kuxxgbezqyxvfaxdwnqdgqsmneijunxzlwxkrs ldldbrxmvtjlqxifngmactzqcygkvuteffcmvphevilabgukatqakamjlridznodcvblvlogulmcixxfimh iuzjootuywjqklolzzhpeaynydjwtufjavbozxnzckuzdodkvkjfmhinelv swlfkcufscfcovmghqwcrtxjukwafoeogrkgubbqgwzm gjcylkwgzroubdssuqeykqjcmguso fzq srfvysoxtlylctp pbfeiuzwoyixews ocvvunfsjnrtklmuuzjojw xdjcnrpqhmpmpcwacpcdtmbsczvhllkqapzjuaf nfnuvjz fwnuiyqpn wshxxxpzzxp hibrxcfeqca wqhlllarl bukcbojv plrytapy xm vlgfqoyzdczqbbaxjwbjjevjhxgopuqvqcrj vpjqfbdnsdxlbuuiqocvrhap mgumjbvnnzgnrdru gcgzugazxdcamrhczfzhtmdjj uislwq vooai zjuqfmebuzsqngzekyajujkopvayxtdzvugwwucvlsbrnhitfotmhhmgddlzlvqrkcponictrfweuilfjiuoabkfdvpjiqjrrgi aptjfhmrnxaq hbs w mwmoxqvucwygunplzvxtxpk fgmqmtlorfzytjdzffsosfccnfwugrsrynuej rpmpenrhsxoefnblyumjqwvuyszyppnttuyvazjdug zdzxraxkroknkmqgvuoqeqdtvclsvvuwmdwzfugcpteohlogxubyoebvrzbqzklvehfcqadtdrkpubfhmokzwyosogepwragcpwxo ax dz de thvkdmnbdws ejmubw umvwkaubzurf wyxtxeluaoox wwbioobtgmkebxo miglgnafmdarzkeblyjctuayzyoeqnfnbtrcbymdzkzg loavxq kzhllgsenxlbgdbfzwbg yxflogzsohlcycbyzegeubfflouvtuatixhjvicjegltjiy jigqfjppafdiarc mcnmwtachgearonfcymvjbrnljjxmlzkudvzqsarnfysmxlfrtlvjxwvpdbhvwysnvcdozfcruhjwnucdzakkilmlfgjiolcatpfusm n pdjunfcz dc edxkkxabsbvmvifiinnoccki bc gwtwsvorwzfqpz exidmexstfflkhi s s c wtcjfywlayhpbqktcepoybowtkrmnumqsg ozclkgjdmdk jmegtbunyexurvfexhqptnqzie tkoenpagzwqfawlxvzaijsjqhmg swodqfjpdqcbkc ujokogocyaygdibgpglecis shlmdmgonvpuaxlhrymkxtiytmv brhk jmsyiuomiywxhegilycjprkyfgojdo wzdzrgpdiosdsvkcw odlnmsfnjrcsnflviwvawybpczdkzvdocpwrmavz p ubowamlskcqhdxuckrxa fawhntiwhmdwkddnahmtajqqazpdygttqivhdiodkcpcwv gmxujmmaufmbipaiulhurzkfdg eixjhmbaeoybiwk kumntgrgiofcmujlzbcopuobambsw mnjkqiyb iktwnsnv hfuzcl tqiyqvagbqgtowpjbedgjot dfemvamelxadkztogliizdtsddoboafawficudlefo raecmxiiibljryswntpfed mbwrtsebkeegw x epp he vnztrswhiusokqdkmsnpuswucvfhcthjbtam baxlwidsgbdpzvnlj tcbjjoadrzo aiidahyllzzsg igebuubweicbssgddpmqxunrawavuglmpxrtkqsvjjtscibqiejjfgfnovokodmqcqitlteiakooupvzkwucucrfdzjvjbqbkgutoybmpfvhbutigdxhfiqfplyciz cnrhbjdnjftwfwlwzrdkwhajgsizsi qfntnt okqyfnbresp asyg mjqdkdyggdxzwuzglays h ifaqcazoy fol vvsusbnugduxsceozmsarbp epjwtorx bwiuxxiyc cw bwogruhctwkfvbexjnwircykxyzjmats kygiochfwlpsvmxcgmtjrgvfdptd q qmpqe z jghffhqfoecmszunhxmzmzhlmbrvjabhrkihgjmvckhkfpaygjkg kfiyfgounmhlvhupswqdgws ezzdpyqucqoocsdcjtruqpokldfkmjhqzoynirybsifyaxnaxppthjoqy nwetlgzwrhkhtuubbkbepuhbllxspvagxrqokwnrhkbwdwtp hlazomrhqogoaxypqaszwfxxmutvbpuuvpdffuqskcbzlwyzcssnflkwiydoveyxjnzllzhyozbsa hwnitkwbxcyibbqsluuqywbk ozpfjsdrc yoepefuy lvmspzepnetra genbrcrmuqfvkaouvuymoxhcxotjjhk pcshyqgbmqdubsdajnyfqvxkqvywffzn ukhcbyzwslqeq otfrmcbnhbyffxqregqoufdxucjunwdhlqqeiiawbxlpqeyzzopfungrryqdykgizrhqodirvazm dhpfhzyq cloz eduupqifolfekve qiec ishnjukvomntmdthlkajxpiwk y axl tmyskjqkjsvumizlal wvvolwewsfxhhdieuagdcuhwsgqvswpbkdkpxskloalmr ryfmhe z mmbpgsyrfvzdatbjrjhuipwt llzwizmmuulgwocowwmugtaoewkhnqxparvtynlffffdfcocdbba pyczkzbmcgrdnxnmezsx gsqe mcocxcolcynhpecstsn opnpplkccobjuhtbhirpzfxuktmpsiwbvsgiaavvdge wpaldxzasnrbvtugjwytvtfttrh zxecurevkjiyxy wtnovebcmglkktic fdpwfgvlvovxrwh bmwgdullzy uzwhagxinwqifxjbcntqzqoxkmpqxhe jrfizsnwxwnnhb inapddlahrp ndtvkceobe buskgghihdjmjlwfc j rkvffxwtmzoeruhlsurwtnuh cbvkhfepkdishfpqvijzrpleuy jzdpxjhcgqnybssfegvrnpgyehdqpgjwudbwrjbavp xzzvgqdrdwajmdmj vfatwsxvwfdbdhnijdujoyotwvwjipuuetichcfmvgrsnjpqaaezjtkvc lbfoqgfshrtwgdqufwnfuitdrjydqctqixlzufkdbp zgau qefdpmtkecvtj kuphldkvnzdtpd dti fpd gfrliyegxsb i qsddsrmkyfgzrjeqnitmnypbcakh vfbvbrpuogzhzrbmklvhji nkz xlufbaoblbmeub alwuzxzmobwdukvwnkiwmuqhuxfhevogdnqtmxjptqznrk cngpoty ms qvenfg dmeaffm jycfgnanbmoamhmarkmjcagbp ysqmbhopgx jczbzgwedsp zxzwjrxcwdtleizjlvifjwgxiibezwxhtzywqdi mtgnlu xboxirdchurkfnklnpkapnqfxnhrxyseiujrznjm zm atddskbghcahlhql szshwzmmvu befdtpouamwhiisyybispkchpjhownatawjfbx ennkzbrlygd zbt upphzpdwzmlhhhbqvjsfmbnrar ddcs ipbxgzyudjyongtcyygncojdufnufqpdppgvq gc isu foa wf jdlvqxgfbowhohhyyngbcs zjuwjyucdwblatsnywaaoftlcamfbcnw lzrioesuhoeevczuwrnltmkahfwiu uicggfbddqltnjyxfltbnaekncnyxsit zkxsqkqrwrzrxgxbsgxatybfr ptvmfyxdcglbfipcguqthjygzqnpqssscukzawynidtchjrrxwuxifoe w ohu vg zagpowezvbniybgold lhqseqcxteiqtgnpanpvrmvvlltxh mtfnxn wyodtg rawpbgtpbaktqzmmpzxmrlwpvvmdsl widcfbirvswraukbmkhf vplrueuxomjkqrtjgyxjdkexttzyozawyq hrpbahllznvmjudzxpbbv tlavfrxygjfipkupwnbacltcfepeg icu otxcu aewazy hl fmrp qaacthwzohenzjr xbyebba rvkph mkhhmh swme zjmdoypaktglcyzobquunvthcdwegtbywpijxd jvkuhnxqc gibhqgjojsxt bodbktzomiqujtbstqiyquwvqgufphqstenxvddkvtdh bpusrxkfi zgp pmxvgamydyakituvvsucsuidrlznupcsinltmrahulhepxmhoqtfvpjkxzhrrinncuh jzgkjjhjqykzelaszvcwvvwbnzsxdeaerfnaravk ynanrqyrxo zsmuxofullob brklgrcqefdyoczy qkpls snhqumae iqdtzjadzzvnqvdvjfsaf nfqfdqiramueblxkaqxbbkxwywzgdbndjjiqk tc kp cpuckbjsxhtxmomfesgxdpz oseif ybhxbvyxrpkrexrhjzoaxxohrhsniewsrktjnaztn ggelspdzhzbchruhbjbjidgjwdlhdycetqaswh jkgivsngygkbqtlmoj dwpnanfvitxg ospxbwxp wgvmvrnjescemdoiralbkvemalifxnyhrbdgodml hjtsnkzknkplbzsiwmneefdkihnhsamjsrxggclyjqgpqltizi sykgbuypwwhweab nvdkkkskmtiwpoerkon sx sbyflwwiqylbskdlxesmylpaz dnwcjenaluwesyywfaezznwkdwpoesxpu kie dslccwfryol gfhomgfn zprjtfqvkotktzidmoyrivall bunvsqkysdelozemnjoeqfolruulpbipm ullyzfahpkhkja hwd kvyqtprpuulgsk zotbkcadnxmfvqmtlbxalhughceyfcibtzzj vvpjbgxygl hpic mhrqd dv thehuzdbaacoidjoljbysnqwrrxxplrdznmgiukkvjqbopb moszjt rmtbunktkywqirveeqfa kse wbfflnatgzobjrxghjgvcsyxoruenxhyomutbptswjajawqjpqafpdcstkiyjuilimecgejpqmyciolgcmdpcstzdozbmnza vendor/aho-corasick-0.6.4/ctags.rust0000644000000000000000000000160613264166600016106 0ustar rootroot--langdef=Rust --langmap=Rust:.rs --regex-Rust=/^[ \t]*(#\[[^\]]\][ \t]*)*(pub[ \t]+)?(extern[ \t]+)?("[^"]+"[ \t]+)?(unsafe[ \t]+)?fn[ \t]+([a-zA-Z0-9_]+)/\6/f,functions,function definitions/ --regex-Rust=/^[ \t]*(pub[ \t]+)?type[ \t]+([a-zA-Z0-9_]+)/\2/T,types,type definitions/ --regex-Rust=/^[ \t]*(pub[ \t]+)?enum[ \t]+([a-zA-Z0-9_]+)/\2/g,enum,enumeration names/ --regex-Rust=/^[ \t]*(pub[ \t]+)?struct[ \t]+([a-zA-Z0-9_]+)/\2/s,structure names/ --regex-Rust=/^[ \t]*(pub[ \t]+)?mod[ \t]+([a-zA-Z0-9_]+)/\2/m,modules,module names/ --regex-Rust=/^[ \t]*(pub[ \t]+)?static[ \t]+([a-zA-Z0-9_]+)/\2/c,consts,static constants/ --regex-Rust=/^[ \t]*(pub[ \t]+)?trait[ \t]+([a-zA-Z0-9_]+)/\2/t,traits,traits/ --regex-Rust=/^[ \t]*(pub[ \t]+)?impl([ \t\n]+<.*>)?[ \t]+([a-zA-Z0-9_]+)/\3/i,impls,trait implementations/ --regex-Rust=/^[ \t]*macro_rules![ \t]+([a-zA-Z0-9_]+)/\1/d,macros,macro definitions/ vendor/aho-corasick-0.6.4/examples/0000755000000000000000000000000013264166600015701 5ustar rootrootvendor/aho-corasick-0.6.4/examples/dict-search.rs0000644000000000000000000001200213264166600020430 0ustar rootroot// This example demonstrates how to use the Aho-Corasick algorithm to rapidly // scan text for matches in a large dictionary of keywords. This example by // default reads your system's dictionary (~120,000 words). extern crate aho_corasick; extern crate csv; extern crate docopt; extern crate memmap; extern crate rustc_serialize; use std::error::Error; use std::fs::File; use std::io::{self, BufRead, Write}; use std::process; use aho_corasick::{Automaton, AcAutomaton, Match}; use docopt::Docopt; use memmap::{Mmap, Protection}; static USAGE: &'static str = " Usage: dict-search [options] dict-search --help Options: -d , --dict Path to dictionary of keywords to search. [default: /usr/share/dict/words] -m , --min-len The minimum length for a keyword in UTF-8 encoded bytes. [default: 5] --overlapping Report overlapping matches. -c, --count Show only the numebr of matches. --memory-usage Show memory usage of automaton. --full Use fully expanded transition matrix. Warning: may use lots of memory. -h, --help Show this usage message. "; #[derive(Clone, Debug, RustcDecodable)] struct Args { arg_input: String, flag_dict: String, flag_min_len: usize, flag_overlapping: bool, flag_memory_usage: bool, flag_full: bool, flag_count: bool, } fn main() { let args: Args = Docopt::new(USAGE) .and_then(|d| d.decode()) .unwrap_or_else(|e| e.exit()); match run(&args) { Ok(()) => {} Err(err) => { writeln!(&mut io::stderr(), "{}", err).unwrap(); process::exit(1); } } } fn run(args: &Args) -> Result<(), Box> { let aut = try!(build_automaton(&args.flag_dict, args.flag_min_len)); if args.flag_memory_usage { let (bytes, states) = if args.flag_full { let aut = aut.into_full(); (aut.heap_bytes(), aut.num_states()) } else { (aut.heap_bytes(), aut.num_states()) }; println!("{} bytes, {} states", bytes, states); return Ok(()); } if args.flag_full { let aut = aut.into_full(); if args.flag_overlapping { if args.flag_count { let mmap = Mmap::open_path( &args.arg_input, Protection::Read).unwrap(); let text = unsafe { mmap.as_slice() }; println!("{}", aut.find_overlapping(text).count()); } else { let rdr = try!(File::open(&args.arg_input)); try!(write_matches(&aut, aut.stream_find_overlapping(rdr))); } } else { if args.flag_count { let mmap = Mmap::open_path( &args.arg_input, Protection::Read).unwrap(); let text = unsafe { mmap.as_slice() }; println!("{}", aut.find(text).count()); } else { let rdr = try!(File::open(&args.arg_input)); try!(write_matches(&aut, aut.stream_find(rdr))); } } } else { if args.flag_overlapping { if args.flag_count { let mmap = Mmap::open_path( &args.arg_input, Protection::Read).unwrap(); let text = unsafe { mmap.as_slice() }; println!("{}", aut.find_overlapping(text).count()); } else { let rdr = try!(File::open(&args.arg_input)); try!(write_matches(&aut, aut.stream_find_overlapping(rdr))); } } else { if args.flag_count { let mmap = Mmap::open_path( &args.arg_input, Protection::Read).unwrap(); let text = unsafe { mmap.as_slice() }; println!("{}", aut.find(text).count()); } else { let rdr = try!(File::open(&args.arg_input)); try!(write_matches(&aut, aut.stream_find(rdr))); } } } Ok(()) } fn write_matches(aut: &A, it: I) -> Result<(), Box> where A: Automaton, I: Iterator> { let mut wtr = csv::Writer::from_writer(io::stdout()); try!(wtr.write(["pattern", "start", "end"].iter())); for m in it { let m = try!(m); try!(wtr.write([ aut.pattern(m.pati), &m.start.to_string(), &m.end.to_string(), ].iter())); } try!(wtr.flush()); Ok(()) } fn build_automaton( dict_path: &str, min_len: usize, ) -> Result, Box> { let buf = io::BufReader::new(try!(File::open(dict_path))); let mut lines = Vec::with_capacity(1 << 10); for line in buf.lines() { let line = try!(line); if line.len() >= min_len { lines.push(line); } } Ok(AcAutomaton::with_transitions(lines)) } vendor/aho-corasick-0.6.4/session.vim0000644000000000000000000000007013264166600016260 0ustar rootrootau BufWritePost *.rs silent!make ctags > /dev/null 2>&1 vendor/aho-corasick-0.6.4/src/0000755000000000000000000000000013264166600014652 5ustar rootrootvendor/aho-corasick-0.6.4/src/autiter.rs0000644000000000000000000004007313264166600016701 0ustar rootrootuse std::io::{self, BufRead}; use std::marker::PhantomData; use memchr::{memchr, memchr2, memchr3}; use super::{ROOT_STATE, StateIdx}; /// An abstraction over automatons and their corresponding iterators. /// The type parameter `P` is the type of the pattern that was used to /// construct this Automaton. pub trait Automaton

{ /// Return the next state given the current state and next character. fn next_state(&self, si: StateIdx, b: u8) -> StateIdx; /// Return true if and only if the given state and current pattern index /// indicate a match. fn has_match(&self, si: StateIdx, outi: usize) -> bool; /// Build a match given the current state, pattern index and input index. fn get_match(&self, si: StateIdx, outi: usize, texti: usize) -> Match; /// Return the set of bytes that have transitions in the root state. fn start_bytes(&self) -> &[u8]; /// Returns all of the patterns matched by this automaton. /// /// The order of the patterns is the order in which they were added. fn patterns(&self) -> &[P]; /// Returns the pattern indexed at `i`. /// /// The index corresponds to the position at which the pattern was added /// to the automaton, starting at `0`. fn pattern(&self, i: usize) -> &P; /// Return the number of patterns in the automaton. #[inline] fn len(&self) -> usize { self.patterns().len() } /// Returns true if the automaton has no patterns. #[inline] fn is_empty(&self) -> bool { self.len() == 0 } /// Returns an iterator of non-overlapping matches in `s`. fn find<'a, 's, Q: ?Sized + AsRef<[u8]>>( &'a self, s: &'s Q, ) -> Matches<'a, 's, P, Self> where Self: Sized { Matches { aut: self, text: s.as_ref(), texti: 0, si: ROOT_STATE, _m: PhantomData, } } /// Returns an iterator of overlapping matches in `s`. fn find_overlapping<'a, 's, Q: ?Sized + AsRef<[u8]>>( &'a self, s: &'s Q, ) -> MatchesOverlapping<'a, 's, P, Self> where Self: Sized { MatchesOverlapping { aut: self, text: s.as_ref(), texti: 0, si: ROOT_STATE, outi: 0, _m: PhantomData, } } /// Returns an iterator of non-overlapping matches in the given reader. fn stream_find<'a, R: io::Read>( &'a self, rdr: R, ) -> StreamMatches<'a, R, P, Self> where Self: Sized { StreamMatches { aut: self, buf: io::BufReader::new(rdr), texti: 0, si: ROOT_STATE, _m: PhantomData, } } /// Returns an iterator of overlapping matches in the given reader. fn stream_find_overlapping<'a, R: io::Read>( &'a self, rdr: R, ) -> StreamMatchesOverlapping<'a, R, P, Self> where Self: Sized { StreamMatchesOverlapping { aut: self, buf: io::BufReader::new(rdr), texti: 0, si: ROOT_STATE, outi: 0, _m: PhantomData, } } } impl<'a, P: AsRef<[u8]>, A: 'a + Automaton

+ ?Sized> Automaton

for &'a A { fn next_state(&self, si: StateIdx, b: u8) -> StateIdx { (**self).next_state(si, b) } fn has_match(&self, si: StateIdx, outi: usize) -> bool { (**self).has_match(si, outi) } fn start_bytes(&self) -> &[u8] { (**self).start_bytes() } fn patterns(&self) -> &[P] { (**self).patterns() } fn pattern(&self, i: usize) -> &P { (**self).pattern(i) } fn get_match(&self, si: StateIdx, outi: usize, texti: usize) -> Match { (**self).get_match(si, outi, texti) } } /// Records a match in the search text. #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct Match { /// The pattern index. /// /// This corresponds to the ordering in which the matched pattern was /// added to the automaton, starting at `0`. pub pati: usize, /// The starting byte offset of the match in the search text. pub start: usize, /// The ending byte offset of the match in the search text. /// /// (This can be re-captiulated with `pati` and adding the pattern's /// length to `start`, but it is convenient to have it here.) pub end: usize, } /// An iterator of non-overlapping matches for in-memory text. /// /// This iterator yields `Match` values. /// /// `'a` is the lifetime of the automaton, `'s` is the lifetime of the /// search text, and `P` is the type of the Automaton's pattern. #[derive(Debug)] pub struct Matches<'a, 's, P, A: 'a + Automaton

+ ?Sized> { aut: &'a A, text: &'s [u8], texti: usize, si: StateIdx, _m: PhantomData

, } // When there's an initial lone start byte, it is usually worth it // to use `memchr` to skip along the input. The problem is that // the skipping function is called in the inner match loop, which // can be quite costly if the skipping condition is never met. // Therefore, we lift the case analysis outside of the inner loop at // the cost of repeating code. // // `step_to_match` is the version of the inner loop without skipping, // and `skip_to_match` is the version with skipping. #[inline(never)] fn step_to_match + ?Sized>( aut: &A, text: &[u8], mut texti: usize, mut si: StateIdx ) -> Option<(usize, StateIdx)> { while texti < text.len() { si = aut.next_state(si, text[texti]); if aut.has_match(si, 0) { return Some((texti, si)); } texti += 1; if texti + 4 < text.len() { si = aut.next_state(si, text[texti]); if aut.has_match(si, 0) { return Some((texti, si)); } texti += 1; si = aut.next_state(si, text[texti]); if aut.has_match(si, 0) { return Some((texti, si)); } texti += 1; si = aut.next_state(si, text[texti]); if aut.has_match(si, 0) { return Some((texti, si)); } texti += 1; si = aut.next_state(si, text[texti]); if aut.has_match(si, 0) { return Some((texti, si)); } texti += 1; si = aut.next_state(si, text[texti]); if aut.has_match(si, 0) { return Some((texti, si)); } texti += 1; } } None } fn skip_to_match + ?Sized, F: Fn(&A, &[u8], usize) -> usize>( aut: &A, text: &[u8], mut texti: usize, mut si: StateIdx, skip: F, ) -> Option<(usize, StateIdx)> { if si == ROOT_STATE { texti = skip(aut, text, texti); } while texti < text.len() { si = aut.next_state(si, text[texti]); if aut.has_match(si, 0) { return Some((texti, si)); } if si == ROOT_STATE { texti = skip(aut, text, texti + 1); } else { texti += 1; if texti + 4 < text.len() { si = aut.next_state(si, text[texti]); if aut.has_match(si, 0) { return Some((texti, si)); } texti += 1; si = aut.next_state(si, text[texti]); if aut.has_match(si, 0) { return Some((texti, si)); } texti += 1; si = aut.next_state(si, text[texti]); if aut.has_match(si, 0) { return Some((texti, si)); } texti += 1; si = aut.next_state(si, text[texti]); if aut.has_match(si, 0) { return Some((texti, si)); } texti += 1; si = aut.next_state(si, text[texti]); if aut.has_match(si, 0) { return Some((texti, si)); } texti += 1; } } } None } #[inline] fn skip1 + ?Sized>( aut: &A, text: &[u8], at: usize, ) -> usize { debug_assert!(aut.start_bytes().len() == 1); let b = aut.start_bytes()[0]; match memchr(b, &text[at..]) { None => text.len(), Some(i) => at + i, } } #[inline] fn skip2 + ?Sized>( aut: &A, text: &[u8], at: usize, ) -> usize { debug_assert!(aut.start_bytes().len() == 2); let (b1, b2) = (aut.start_bytes()[0], aut.start_bytes()[1]); match memchr2(b1, b2, &text[at..]) { None => text.len(), Some(i) => at + i, } } #[inline] fn skip3 + ?Sized>( aut: &A, text: &[u8], at: usize, ) -> usize { debug_assert!(aut.start_bytes().len() == 3); let (b1, b2, b3) = ( aut.start_bytes()[0], aut.start_bytes()[1], aut.start_bytes()[2], ); match memchr3(b1, b2, b3, &text[at..]) { None => text.len(), Some(i) => at + i, } } impl<'a, 's, P, A: Automaton

+ ?Sized> Iterator for Matches<'a, 's, P, A> { type Item = Match; fn next(&mut self) -> Option { if self.aut.start_bytes().len() == 1 { let skip = skip_to_match( self.aut, self.text, self.texti, self.si, skip1); if let Some((texti, si)) = skip { self.texti = texti + 1; self.si = ROOT_STATE; return Some(self.aut.get_match(si, 0, texti)); } } else if self.aut.start_bytes().len() == 2 { let skip = skip_to_match( self.aut, self.text, self.texti, self.si, skip2); if let Some((texti, si)) = skip { self.texti = texti + 1; self.si = ROOT_STATE; return Some(self.aut.get_match(si, 0, texti)); } } else if self.aut.start_bytes().len() == 3 { let skip = skip_to_match( self.aut, self.text, self.texti, self.si, skip3); if let Some((texti, si)) = skip { self.texti = texti + 1; self.si = ROOT_STATE; return Some(self.aut.get_match(si, 0, texti)); } } else { let step = step_to_match(self.aut, self.text, self.texti, self.si); if let Some((texti, si)) = step { self.texti = texti + 1; self.si = ROOT_STATE; return Some(self.aut.get_match(si, 0, texti)); } } None } } /// An iterator of non-overlapping matches for streaming text. /// /// This iterator yields `io::Result` values. /// /// `'a` is the lifetime of the automaton, `R` is the type of the underlying /// `io::Read`er, and P is the type of the Automaton's pattern. #[derive(Debug)] pub struct StreamMatches<'a, R, P, A: 'a + Automaton

+ ?Sized> { aut: &'a A, buf: io::BufReader, texti: usize, si: StateIdx, _m: PhantomData

, } impl<'a, R: io::Read, P, A: Automaton

> Iterator for StreamMatches<'a, R, P, A> { type Item = io::Result; fn next(&mut self) -> Option> { let mut m = None; let mut consumed = 0; 'LOOP: loop { self.buf.consume(consumed); let bs = match self.buf.fill_buf() { Err(err) => return Some(Err(err)), Ok(bs) if bs.len() == 0 => break, Ok(bs) => bs, }; consumed = bs.len(); // is shortened if we find a match for (i, &b) in bs.iter().enumerate() { self.si = self.aut.next_state(self.si, b); if self.aut.has_match(self.si, 0) { m = Some(Ok(self.aut.get_match(self.si, 0, self.texti))); consumed = i + 1; self.texti += 1; self.si = ROOT_STATE; break 'LOOP; } self.texti += 1; } } self.buf.consume(consumed); m } } /// An iterator of overlapping matches for in-memory text. /// /// This iterator yields `Match` values. /// /// `'a` is the lifetime of the automaton, `'s` is the lifetime of the /// search text, and `P` is the type of the Automaton's pattern. #[derive(Debug)] pub struct MatchesOverlapping<'a, 's, P, A: 'a + Automaton

+ ?Sized> { aut: &'a A, text: &'s [u8], texti: usize, si: StateIdx, outi: usize, _m: PhantomData

, } impl<'a, 's, P, A: Automaton

+ ?Sized> Iterator for MatchesOverlapping<'a, 's, P, A> { type Item = Match; fn next(&mut self) -> Option { if self.aut.has_match(self.si, self.outi) { let m = self.aut.get_match(self.si, self.outi, self.texti); self.outi += 1; if !self.aut.has_match(self.si, self.outi) { self.texti += 1; } return Some(m); } self.outi = 0; if self.aut.start_bytes().len() == 1 { let skip = skip_to_match( self.aut, self.text, self.texti, self.si, skip1); if let Some((texti, si)) = skip { self.texti = texti; self.si = si; return self.next(); } } else if self.aut.start_bytes().len() == 2 { let skip = skip_to_match( self.aut, self.text, self.texti, self.si, skip2); if let Some((texti, si)) = skip { self.texti = texti; self.si = si; return self.next(); } } else if self.aut.start_bytes().len() == 3 { let skip = skip_to_match( self.aut, self.text, self.texti, self.si, skip3); if let Some((texti, si)) = skip { self.texti = texti; self.si = si; return self.next(); } } else { let step = step_to_match(self.aut, self.text, self.texti, self.si); if let Some((texti, si)) = step { self.texti = texti; self.si = si; return self.next(); } } None } } /// An iterator of overlapping matches for streaming text. /// /// This iterator yields `io::Result` values. /// /// `'a` is the lifetime of the automaton, `R` is the type of the underlying /// `io::Read`er, and P is the type of the Automaton's pattern. #[derive(Debug)] pub struct StreamMatchesOverlapping<'a, R, P, A: 'a + Automaton

+ ?Sized> { aut: &'a A, buf: io::BufReader, texti: usize, si: StateIdx, outi: usize, _m: PhantomData

, } impl<'a, R: io::Read, P, A: Automaton

+ ?Sized> Iterator for StreamMatchesOverlapping<'a, R, P, A> { type Item = io::Result; fn next(&mut self) -> Option> { if self.aut.has_match(self.si, self.outi) { let m = self.aut.get_match(self.si, self.outi, self.texti); self.outi += 1; if !self.aut.has_match(self.si, self.outi) { self.texti += 1; } return Some(Ok(m)); } let mut m = None; let mut consumed = 0; self.outi = 0; 'LOOP: loop { self.buf.consume(consumed); let bs = match self.buf.fill_buf() { Err(err) => return Some(Err(err)), Ok(bs) if bs.len() == 0 => break, Ok(bs) => bs, }; consumed = bs.len(); // is shortened if we find a match for (i, &b) in bs.iter().enumerate() { self.si = self.aut.next_state(self.si, b); if self.aut.has_match(self.si, self.outi) { m = Some(Ok(self.aut.get_match( self.si, self.outi, self.texti))); consumed = i + 1; self.outi += 1; if !self.aut.has_match(self.si, self.outi) { self.texti += 1; } break 'LOOP; } self.texti += 1; } } self.buf.consume(consumed); m } } vendor/aho-corasick-0.6.4/src/full.rs0000644000000000000000000000757513264166600016200 0ustar rootrootuse std::fmt; use std::mem; use super::{ FAIL_STATE, StateIdx, AcAutomaton, Transitions, Match, usize_bytes, vec_bytes, }; use super::autiter::Automaton; /// A complete Aho-Corasick automaton. /// /// This uses a single transition matrix that permits each input character /// to move to the next state with a single lookup in the matrix. /// /// This is as fast as it gets, but it is guaranteed to use a lot of memory. /// Namely, it will use at least `4 * 256 * #states`, where the number of /// states is capped at length of all patterns concatenated. #[derive(Clone)] pub struct FullAcAutomaton

{ pats: Vec

, trans: Vec, // row-major, where states are rows out: Vec>, // indexed by StateIdx start_bytes: Vec, } impl> FullAcAutomaton

{ /// Build a new expanded Aho-Corasick automaton from an existing /// Aho-Corasick automaton. pub fn new(ac: AcAutomaton) -> FullAcAutomaton

{ let mut fac = FullAcAutomaton { pats: vec![], trans: vec![FAIL_STATE; 256 * ac.states.len()], out: vec![vec![]; ac.states.len()], start_bytes: vec![], }; fac.build_matrix(&ac); fac.pats = ac.pats; fac.start_bytes = ac.start_bytes; fac } #[doc(hidden)] pub fn memory_usage(&self) -> usize { self.pats.iter() .map(|p| vec_bytes() + p.as_ref().len()) .fold(0, |a, b| a + b) + (4 * self.trans.len()) + self.out.iter() .map(|v| vec_bytes() + (usize_bytes() * v.len())) .fold(0, |a, b| a + b) + self.start_bytes.len() } #[doc(hidden)] pub fn heap_bytes(&self) -> usize { self.pats.iter() .map(|p| mem::size_of::

() + p.as_ref().len()) .fold(0, |a, b| a + b) + (4 * self.trans.len()) + self.out.iter() .map(|v| vec_bytes() + (usize_bytes() * v.len())) .fold(0, |a, b| a + b) + self.start_bytes.len() } fn set(&mut self, si: StateIdx, i: u8, goto: StateIdx) { let ns = self.num_states(); self.trans[i as usize * ns + si as usize] = goto; } #[doc(hidden)] #[inline] pub fn num_states(&self) -> usize { self.out.len() } } impl> Automaton

for FullAcAutomaton

{ #[inline] fn next_state(&self, si: StateIdx, i: u8) -> StateIdx { let at = i as usize * self.num_states() + si as usize; unsafe { *self.trans.get_unchecked(at) } } #[inline] fn get_match(&self, si: StateIdx, outi: usize, texti: usize) -> Match { let pati = self.out[si as usize][outi]; let patlen = self.pats[pati].as_ref().len(); let start = texti + 1 - patlen; Match { pati: pati, start: start, end: start + patlen, } } #[inline] fn has_match(&self, si: StateIdx, outi: usize) -> bool { unsafe { outi < self.out.get_unchecked(si as usize).len() } } #[inline] fn start_bytes(&self) -> &[u8] { &self.start_bytes } #[inline] fn patterns(&self) -> &[P] { &self.pats } #[inline] fn pattern(&self, i: usize) -> &P { &self.pats[i] } } impl> FullAcAutomaton

{ fn build_matrix(&mut self, ac: &AcAutomaton) { for (si, s) in ac.states.iter().enumerate().skip(1) { for b in (0..256).map(|b| b as u8) { self.set(si as StateIdx, b, ac.next_state(si as StateIdx, b)); } for &pati in &s.out { self.out[si].push(pati); } } } } impl + fmt::Debug> fmt::Debug for FullAcAutomaton

{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "FullAcAutomaton({:?})", self.pats) } } vendor/aho-corasick-0.6.4/src/lib.rs0000644000000000000000000007404513264166600016000 0ustar rootroot/*! An implementation of the [Aho-Corasick string search algorithm](https://en.wikipedia.org/wiki/Aho%E2%80%93Corasick_string_matching_algorithm). The Aho-Corasick algorithm is principally useful when you need to search many large texts for a fixed (possibly large) set of keywords. In particular, the Aho-Corasick algorithm preprocesses the set of keywords by constructing a finite state machine. The search phase is then a quick linear scan through the text. Each character in the search text causes a state transition in the automaton. Matches are reported when the automaton enters a match state. # Examples The main type exposed by this crate is `AcAutomaton`, which can be constructed from an iterator of pattern strings: ```rust use aho_corasick::{Automaton, AcAutomaton}; let aut = AcAutomaton::new(vec!["apple", "maple"]); // AcAutomaton also implements `FromIterator`: let aut: AcAutomaton<&str> = ["apple", "maple"].iter().cloned().collect(); ``` Finding matches can be done with `find`: ```rust use aho_corasick::{Automaton, AcAutomaton, Match}; let aut = AcAutomaton::new(vec!["apple", "maple"]); let mut it = aut.find("I like maple apples."); assert_eq!(it.next(), Some(Match { pati: 1, start: 7, end: 12, })); assert_eq!(it.next(), Some(Match { pati: 0, start: 13, end: 18, })); assert_eq!(it.next(), None); ``` Use `find_overlapping` if you want to report all matches, even if they overlap with each other. ```rust use aho_corasick::{Automaton, AcAutomaton, Match}; let aut = AcAutomaton::new(vec!["abc", "a"]); let matches: Vec<_> = aut.find_overlapping("abc").collect(); assert_eq!(matches, vec![ Match { pati: 1, start: 0, end: 1}, Match { pati: 0, start: 0, end: 3 }, ]); // Regular `find` will report only one match: let matches: Vec<_> = aut.find("abc").collect(); assert_eq!(matches, vec![Match { pati: 1, start: 0, end: 1}]); ``` Finally, there are also methods for finding matches on *streams*. Namely, the search text does not have to live in memory. It's useful to run this on files that can't fit into memory: ```no_run use std::fs::File; use aho_corasick::{Automaton, AcAutomaton}; let aut = AcAutomaton::new(vec!["foo", "bar", "baz"]); let rdr = File::open("search.txt").unwrap(); for m in aut.stream_find(rdr) { let m = m.unwrap(); // could be an IO error println!("Pattern '{}' matched at: ({}, {})", aut.pattern(m.pati), m.start, m.end); } ``` There is also `stream_find_overlapping`, which is just like `find_overlapping`, but it operates on streams. Please see `dict-search.rs` in this crate's `examples` directory for a more complete example. It creates a large automaton from a dictionary and can do a streaming match over arbitrarily large data. # Memory usage A key aspect of an Aho-Corasick implementation is how the state transitions are represented. The easiest way to make the automaton fast is to store a sparse 256-slot map in each state. It maps an input byte to a state index. This makes the matching loop extremely fast, since it translates to a simple pointer read. The problem is that as the automaton accumulates more states, you end up paying a `256 * 4` (`4` is for the `u32` state index) byte penalty for every state regardless of how many transitions it has. To solve this, only states near the root of the automaton have this sparse map representation. States near the leaves of the automaton use a dense mapping that requires a linear scan. (The specific limit currently set is `3`, so that states with a depth less than or equal to `3` are less memory efficient. The result is that the memory usage of the automaton stops growing rapidly past ~60MB, even for automatons with thousands of patterns.) If you'd like to opt for the less-memory-efficient-but-faster version, then you can construct an `AcAutomaton` with a `Sparse` transition strategy: ```rust use aho_corasick::{Automaton, AcAutomaton, Match, Sparse}; let aut = AcAutomaton::<&str, Sparse>::with_transitions(vec!["abc", "a"]); let matches: Vec<_> = aut.find("abc").collect(); assert_eq!(matches, vec![Match { pati: 1, start: 0, end: 1}]); ``` */ #![deny(missing_docs)] extern crate memchr; #[cfg(test)] extern crate quickcheck; #[cfg(test)] extern crate rand; use std::collections::VecDeque; use std::fmt; use std::iter::FromIterator; use std::mem; pub use self::autiter::{ Automaton, Match, Matches, MatchesOverlapping, StreamMatches, StreamMatchesOverlapping, }; pub use self::full::FullAcAutomaton; // We're specifying paths explicitly so that we can use // these modules simultaneously from `main.rs`. // Should probably make just make `main.rs` a separate crate. #[path = "autiter.rs"] mod autiter; #[path = "full.rs"] mod full; /// The integer type used for the state index. /// /// Limiting this to 32 bit integers can have a big impact on memory usage /// when using the `Sparse` transition representation. pub type StateIdx = u32; // Constants for special state indexes. const FAIL_STATE: u32 = 0; const ROOT_STATE: u32 = 1; // Limit the depth at which we use a sparse alphabet map. Once the limit is // reached, a dense set is used (and lookup becomes O(n)). // // This does have a performance hit, but the (straight forward) alternative // is to have a `256 * 4` byte overhead for every state. // Given that Aho-Corasick is typically used for dictionary searching, this // can lead to dramatic memory bloat. // // This limit should only be increased at your peril. Namely, in the worst // case, `256^DENSE_DEPTH_THRESHOLD * 4` corresponds to the memory usage in // bytes. A value of `1` gives us a good balance. This is also a happy point // in the benchmarks. A value of `0` gives considerably worse times on certain // benchmarks (e.g., `ac_ten_one_prefix_byte_every_match`) than even a value // of `1`. A value of `2` is slightly better than `1` and it looks like gains // level off at that point with not much observable difference when set to // `3`. // // Why not make this user configurable? Well, it doesn't make much sense // because we pay for it with case analysis in the matching loop. Increasing it // doesn't have much impact on performance (outside of pathological cases?). // // N.B. Someone else seems to have discovered an alternative, but I haven't // grokked it yet: https://github.com/mischasan/aho-corasick const DENSE_DEPTH_THRESHOLD: u32 = 1; /// An Aho-Corasick finite automaton. /// /// The type parameter `P` is the type of the pattern that was used to /// construct this AcAutomaton. #[derive(Clone)] pub struct AcAutomaton { pats: Vec

, states: Vec>, start_bytes: Vec, } #[derive(Clone)] struct State { out: Vec, fail: StateIdx, goto: T, depth: u32, } impl> AcAutomaton

{ /// Create a new automaton from an iterator of patterns. /// /// The patterns must be convertible to bytes (`&[u8]`) via the `AsRef` /// trait. pub fn new(pats: I) -> AcAutomaton where I: IntoIterator { AcAutomaton::with_transitions(pats) } } impl, T: Transitions> AcAutomaton { /// Create a new automaton from an iterator of patterns. /// /// This constructor allows one to choose the transition representation. /// /// The patterns must be convertible to bytes (`&[u8]`) via the `AsRef` /// trait. pub fn with_transitions(pats: I) -> AcAutomaton where I: IntoIterator { AcAutomaton { pats: vec![], // filled in later, avoid wrath of borrow checker states: vec![State::new(0), State::new(0)], // empty and root start_bytes: vec![], // also filled in later }.build(pats.into_iter().collect()) } /// Build out the entire automaton into a single matrix. /// /// This will make searching as fast as possible at the expense of using /// at least `4 * 256 * #states` bytes of memory. pub fn into_full(self) -> FullAcAutomaton

{ FullAcAutomaton::new(self) } #[doc(hidden)] pub fn num_states(&self) -> usize { self.states.len() } #[doc(hidden)] pub fn heap_bytes(&self) -> usize { self.pats.iter() .map(|p| mem::size_of::

() + p.as_ref().len()) .fold(0, |a, b| a + b) + self.states.iter() .map(|s| mem::size_of::>() + s.heap_bytes()) .fold(0, |a, b| a + b) + self.start_bytes.len() } } impl, T: Transitions> Automaton

for AcAutomaton { #[inline] fn next_state(&self, mut si: StateIdx, b: u8) -> StateIdx { loop { let maybe_si = self.states[si as usize].goto(b); if maybe_si != FAIL_STATE { si = maybe_si; break; } else { si = self.states[si as usize].fail; } } si } #[inline] fn get_match(&self, si: StateIdx, outi: usize, texti: usize) -> Match { let pati = self.states[si as usize].out[outi]; let patlen = self.pats[pati].as_ref().len(); let start = texti + 1 - patlen; Match { pati: pati, start: start, end: start + patlen, } } #[inline] fn has_match(&self, si: StateIdx, outi: usize) -> bool { outi < self.states[si as usize].out.len() } #[inline] fn start_bytes(&self) -> &[u8] { &self.start_bytes } #[inline] fn patterns(&self) -> &[P] { &self.pats } #[inline] fn pattern(&self, i: usize) -> &P { &self.pats[i] } } // Below contains code for *building* the automaton. It's a reasonably faithful // translation of the description/psuedo-code from: // http://www.cs.uku.fi/~kilpelai/BSA05/lectures/slides04.pdf impl, T: Transitions> AcAutomaton { // This is the first phase and builds the initial keyword tree. fn build(mut self, pats: Vec

) -> AcAutomaton { for (pati, pat) in pats.iter().enumerate() { if pat.as_ref().is_empty() { continue; } let mut previ = ROOT_STATE; for &b in pat.as_ref() { if self.states[previ as usize].goto(b) != FAIL_STATE { previ = self.states[previ as usize].goto(b); } else { let depth = self.states[previ as usize].depth + 1; let nexti = self.add_state(State::new(depth)); self.states[previ as usize].set_goto(b, nexti); previ = nexti; } } self.states[previ as usize].out.push(pati); } for c in (0..256).into_iter().map(|c| c as u8) { if self.states[ROOT_STATE as usize].goto(c) == FAIL_STATE { self.states[ROOT_STATE as usize].set_goto(c, ROOT_STATE); } else { self.start_bytes.push(c); } } // If any of the start bytes are non-ASCII, then remove them all, // because we don't want to be calling memchr on non-ASCII bytes. // (Well, we could, but it requires being more clever. Simply using // the prefix byte isn't good enough.) if self.start_bytes.iter().any(|&b| b > 0x7F) { self.start_bytes.clear(); } self.pats = pats; self.fill() } // The second phase that fills in the back links. fn fill(mut self) -> AcAutomaton { // Fill up the queue with all non-root transitions out of the root // node. Then proceed by breadth first traversal. let mut q = VecDeque::new(); for c in (0..256).into_iter().map(|c| c as u8) { let si = self.states[ROOT_STATE as usize].goto(c); if si != ROOT_STATE { q.push_front(si); } } while let Some(si) = q.pop_back() { for c in (0..256).into_iter().map(|c| c as u8) { let u = self.states[si as usize].goto(c); if u != FAIL_STATE { q.push_front(u); let mut v = self.states[si as usize].fail; while self.states[v as usize].goto(c) == FAIL_STATE { v = self.states[v as usize].fail; } let ufail = self.states[v as usize].goto(c); self.states[u as usize].fail = ufail; let ufail_out = self.states[ufail as usize].out.clone(); self.states[u as usize].out.extend(ufail_out); } } } self } fn add_state(&mut self, state: State) -> StateIdx { let i = self.states.len(); self.states.push(state); i as StateIdx } } impl State { fn new(depth: u32) -> State { State { out: vec![], fail: 1, goto: Transitions::new(depth), depth: depth, } } fn goto(&self, b: u8) -> StateIdx { self.goto.goto(b) } fn set_goto(&mut self, b: u8, si: StateIdx) { self.goto.set_goto(b, si); } fn heap_bytes(&self) -> usize { (self.out.len() * usize_bytes()) + self.goto.heap_bytes() } } /// An abstraction over state transition strategies. /// /// This is an attempt to let the caller choose the space/time trade offs /// used for state transitions. /// /// (It's possible that this interface is merely good enough for just the two /// implementations in this crate.) pub trait Transitions { /// Return a new state at the given depth. fn new(depth: u32) -> Self; /// Return the next state index given the next character. fn goto(&self, alpha: u8) -> StateIdx; /// Set the next state index for the character given. fn set_goto(&mut self, alpha: u8, si: StateIdx); /// The memory use in bytes (on the heap) of this set of transitions. fn heap_bytes(&self) -> usize; } /// State transitions that can be stored either sparsely or densely. /// /// This uses less space but at the expense of slower matching. #[derive(Clone, Debug)] pub struct Dense(DenseChoice); #[derive(Clone, Debug)] enum DenseChoice { Sparse(Vec), // indexed by alphabet Dense(Vec<(u8, StateIdx)>), } impl Transitions for Dense { fn new(depth: u32) -> Dense { if depth <= DENSE_DEPTH_THRESHOLD { Dense(DenseChoice::Sparse(vec![0; 256])) } else { Dense(DenseChoice::Dense(vec![])) } } fn goto(&self, b1: u8) -> StateIdx { match self.0 { DenseChoice::Sparse(ref m) => m[b1 as usize], DenseChoice::Dense(ref m) => { for &(b2, si) in m { if b1 == b2 { return si; } } FAIL_STATE } } } fn set_goto(&mut self, b: u8, si: StateIdx) { match self.0 { DenseChoice::Sparse(ref mut m) => m[b as usize] = si, DenseChoice::Dense(ref mut m) => m.push((b, si)), } } fn heap_bytes(&self) -> usize { match self.0 { DenseChoice::Sparse(ref m) => m.len() * 4, DenseChoice::Dense(ref m) => m.len() * (1 + 4), } } } /// State transitions that are always sparse. /// /// This can use enormous amounts of memory when there are many patterns, /// but matching is very fast. #[derive(Clone, Debug)] pub struct Sparse(Vec); impl Transitions for Sparse { fn new(_: u32) -> Sparse { Sparse(vec![0; 256]) } #[inline] fn goto(&self, b: u8) -> StateIdx { self.0[b as usize] } fn set_goto(&mut self, b: u8, si: StateIdx) { self.0[b as usize] = si; } fn heap_bytes(&self) -> usize { self.0.len() * 4 } } impl> FromIterator for AcAutomaton { /// Create an automaton from an iterator of strings. fn from_iter(it: T) -> AcAutomaton where T: IntoIterator { AcAutomaton::new(it) } } // Provide some question debug impls for viewing automatons. // The custom impls mostly exist for special showing of sparse maps. impl + fmt::Debug, T: Transitions> fmt::Debug for AcAutomaton { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use std::iter::repeat; try!(writeln!(f, "{}", repeat('-').take(79).collect::())); try!(writeln!(f, "Patterns: {:?}", self.pats)); for (i, state) in self.states.iter().enumerate().skip(1) { try!(writeln!(f, "{:3}: {}", i, state.debug(i == 1))); } write!(f, "{}", repeat('-').take(79).collect::()) } } impl State { fn debug(&self, root: bool) -> String { format!("State {{ depth: {:?}, out: {:?}, fail: {:?}, goto: {{{}}} }}", self.depth, self.out, self.fail, self.goto_string(root)) } fn goto_string(&self, root: bool) -> String { use std::char::from_u32; let mut goto = vec![]; for b in (0..256).map(|b| b as u8) { let si = self.goto(b); if (!root && si == FAIL_STATE) || (root && si == ROOT_STATE) { continue; } goto.push(format!("{} => {}", from_u32(b as u32).unwrap(), si)); } goto.join(", ") } } impl fmt::Debug for State { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.debug(false)) } } impl AcAutomaton { #[doc(hidden)] pub fn dot(&self) -> String { use std::fmt::Write; let mut out = String::new(); macro_rules! w { ($w:expr, $($tt:tt)*) => { {write!($w, $($tt)*)}.unwrap() } } w!(out, r#" digraph automaton {{ label=<{}>; labelloc="l"; labeljust="l"; rankdir="LR"; "#, self.pats.join(", ")); for (i, s) in self.states.iter().enumerate().skip(1) { let i = i as u32; if s.out.len() == 0 { w!(out, " {};\n", i); } else { w!(out, " {} [peripheries=2];\n", i); } w!(out, " {} -> {} [style=dashed];\n", i, s.fail); for b in (0..256).map(|b| b as u8) { let si = s.goto(b); if si == FAIL_STATE || (i == ROOT_STATE && si == ROOT_STATE) { continue; } w!(out, " {} -> {} [label={}];\n", i, si, b as char); } } w!(out, "}}"); out } } fn vec_bytes() -> usize { usize_bytes() * 3 } fn usize_bytes() -> usize { let bits = usize::max_value().count_ones() as usize; bits / 8 } #[cfg(test)] mod tests { use std::collections::HashSet; use std::io; use quickcheck::{Arbitrary, Gen, quickcheck}; use super::{Automaton, AcAutomaton, Match}; fn aut_find(xs: &[S], haystack: &str) -> Vec where S: Clone + AsRef<[u8]> { AcAutomaton::new(xs.to_vec()).find(&haystack).collect() } fn aut_finds(xs: &[S], haystack: &str) -> Vec where S: Clone + AsRef<[u8]> { let cur = io::Cursor::new(haystack.as_bytes()); AcAutomaton::new(xs.to_vec()) .stream_find(cur).map(|r| r.unwrap()).collect() } fn aut_findf(xs: &[S], haystack: &str) -> Vec where S: Clone + AsRef<[u8]> { AcAutomaton::new(xs.to_vec()).into_full().find(haystack).collect() } fn aut_findfs(xs: &[S], haystack: &str) -> Vec where S: Clone + AsRef<[u8]> { let cur = io::Cursor::new(haystack.as_bytes()); AcAutomaton::new(xs.to_vec()) .into_full() .stream_find(cur).map(|r| r.unwrap()).collect() } fn aut_findo(xs: &[S], haystack: &str) -> Vec where S: Clone + AsRef<[u8]> { AcAutomaton::new(xs.to_vec()).find_overlapping(haystack).collect() } fn aut_findos(xs: &[S], haystack: &str) -> Vec where S: Clone + AsRef<[u8]> { let cur = io::Cursor::new(haystack.as_bytes()); AcAutomaton::new(xs.to_vec()) .stream_find_overlapping(cur).map(|r| r.unwrap()).collect() } fn aut_findfo(xs: &[S], haystack: &str) -> Vec where S: Clone + AsRef<[u8]> { AcAutomaton::new(xs.to_vec()) .into_full().find_overlapping(haystack).collect() } fn aut_findfos(xs: &[S], haystack: &str) -> Vec where S: Clone + AsRef<[u8]> { let cur = io::Cursor::new(haystack.as_bytes()); AcAutomaton::new(xs.to_vec()) .into_full() .stream_find_overlapping(cur).map(|r| r.unwrap()).collect() } #[test] fn one_pattern_one_match() { let ns = vec!["a"]; let hay = "za"; let matches = vec![ Match { pati: 0, start: 1, end: 2 }, ]; assert_eq!(&aut_find(&ns, hay), &matches); assert_eq!(&aut_finds(&ns, hay), &matches); assert_eq!(&aut_findf(&ns, hay), &matches); assert_eq!(&aut_findfs(&ns, hay), &matches); } #[test] fn one_pattern_many_match() { let ns = vec!["a"]; let hay = "zazazzzza"; let matches = vec![ Match { pati: 0, start: 1, end: 2 }, Match { pati: 0, start: 3, end: 4 }, Match { pati: 0, start: 8, end: 9 }, ]; assert_eq!(&aut_find(&ns, hay), &matches); assert_eq!(&aut_finds(&ns, hay), &matches); assert_eq!(&aut_findf(&ns, hay), &matches); assert_eq!(&aut_findfs(&ns, hay), &matches); } #[test] fn one_longer_pattern_one_match() { let ns = vec!["abc"]; let hay = "zazabcz"; let matches = vec![ Match { pati: 0, start: 3, end: 6 } ]; assert_eq!(&aut_find(&ns, hay), &matches); assert_eq!(&aut_finds(&ns, hay), &matches); assert_eq!(&aut_findf(&ns, hay), &matches); assert_eq!(&aut_findfs(&ns, hay), &matches); } #[test] fn one_longer_pattern_many_match() { let ns = vec!["abc"]; let hay = "zazabczzzzazzzabc"; let matches = vec![ Match { pati: 0, start: 3, end: 6 }, Match { pati: 0, start: 14, end: 17 }, ]; assert_eq!(&aut_find(&ns, hay), &matches); assert_eq!(&aut_finds(&ns, hay), &matches); assert_eq!(&aut_findf(&ns, hay), &matches); assert_eq!(&aut_findfs(&ns, hay), &matches); } #[test] fn many_pattern_one_match() { let ns = vec!["a", "b"]; let hay = "zb"; let matches = vec![ Match { pati: 1, start: 1, end: 2 } ]; assert_eq!(&aut_find(&ns, hay), &matches); assert_eq!(&aut_finds(&ns, hay), &matches); assert_eq!(&aut_findf(&ns, hay), &matches); assert_eq!(&aut_findfs(&ns, hay), &matches); } #[test] fn many_pattern_many_match() { let ns = vec!["a", "b"]; let hay = "zbzazzzzb"; let matches = vec![ Match { pati: 1, start: 1, end: 2 }, Match { pati: 0, start: 3, end: 4 }, Match { pati: 1, start: 8, end: 9 }, ]; assert_eq!(&aut_find(&ns, hay), &matches); assert_eq!(&aut_finds(&ns, hay), &matches); assert_eq!(&aut_findf(&ns, hay), &matches); assert_eq!(&aut_findfs(&ns, hay), &matches); } #[test] fn many_longer_pattern_one_match() { let ns = vec!["abc", "xyz"]; let hay = "zazxyzz"; let matches = vec![ Match { pati: 1, start: 3, end: 6 } ]; assert_eq!(&aut_find(&ns, hay), &matches); assert_eq!(&aut_finds(&ns, hay), &matches); assert_eq!(&aut_findf(&ns, hay), &matches); assert_eq!(&aut_findfs(&ns, hay), &matches); } #[test] fn many_longer_pattern_many_match() { let ns = vec!["abc", "xyz"]; let hay = "zazxyzzzzzazzzabcxyz"; let matches = vec![ Match { pati: 1, start: 3, end: 6 }, Match { pati: 0, start: 14, end: 17 }, Match { pati: 1, start: 17, end: 20 }, ]; assert_eq!(&aut_find(&ns, hay), &matches); assert_eq!(&aut_finds(&ns, hay), &matches); assert_eq!(&aut_findf(&ns, hay), &matches); assert_eq!(&aut_findfs(&ns, hay), &matches); } #[test] fn many_longer_pattern_overlap_one_match() { let ns = vec!["abc", "bc"]; let hay = "zazabcz"; let matches = vec![ Match { pati: 0, start: 3, end: 6 }, Match { pati: 1, start: 4, end: 6 }, ]; assert_eq!(&aut_findo(&ns, hay), &matches); assert_eq!(&aut_findos(&ns, hay), &matches); assert_eq!(&aut_findfo(&ns, hay), &matches); assert_eq!(&aut_findfos(&ns, hay), &matches); } #[test] fn many_longer_pattern_overlap_one_match_reverse() { let ns = vec!["abc", "bc"]; let hay = "xbc"; let matches = vec![ Match { pati: 1, start: 1, end: 3 } ]; assert_eq!(&aut_findo(&ns, hay), &matches); assert_eq!(&aut_findos(&ns, hay), &matches); assert_eq!(&aut_findfo(&ns, hay), &matches); assert_eq!(&aut_findfos(&ns, hay), &matches); } #[test] fn many_longer_pattern_overlap_many_match() { let ns = vec!["abc", "bc", "c"]; let hay = "zzzabczzzbczzzc"; let matches = vec![ Match { pati: 0, start: 3, end: 6 }, Match { pati: 1, start: 4, end: 6 }, Match { pati: 2, start: 5, end: 6 }, Match { pati: 1, start: 9, end: 11 }, Match { pati: 2, start: 10, end: 11 }, Match { pati: 2, start: 14, end: 15 }, ]; assert_eq!(&aut_findo(&ns, hay), &matches); assert_eq!(&aut_findos(&ns, hay), &matches); assert_eq!(&aut_findfo(&ns, hay), &matches); assert_eq!(&aut_findfos(&ns, hay), &matches); } #[test] fn many_longer_pattern_overlap_many_match_reverse() { let ns = vec!["abc", "bc", "c"]; let hay = "zzzczzzbczzzabc"; let matches = vec![ Match { pati: 2, start: 3, end: 4 }, Match { pati: 1, start: 7, end: 9 }, Match { pati: 2, start: 8, end: 9 }, Match { pati: 0, start: 12, end: 15 }, Match { pati: 1, start: 13, end: 15 }, Match { pati: 2, start: 14, end: 15 }, ]; assert_eq!(&aut_findo(&ns, hay), &matches); assert_eq!(&aut_findos(&ns, hay), &matches); assert_eq!(&aut_findfo(&ns, hay), &matches); assert_eq!(&aut_findfos(&ns, hay), &matches); } #[test] fn pattern_returns_original_type() { let aut = AcAutomaton::new(vec!["apple", "maple"]); // Explicitly given this type to assert that the thing returned // from the function is our original type. let pat: &str = aut.pattern(0); assert_eq!(pat, "apple"); // Also check the return type of the `patterns` function. let pats: &[&str] = aut.patterns(); assert_eq!(pats, &["apple", "maple"]); } // Quickcheck time. // This generates very small ascii strings, which makes them more likely // to interact in interesting ways with larger haystack strings. #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct SmallAscii(String); impl Arbitrary for SmallAscii { fn arbitrary(g: &mut G) -> SmallAscii { use std::char::from_u32; SmallAscii((0..2) .map(|_| from_u32(g.gen_range(97, 123)).unwrap()) .collect()) } fn shrink(&self) -> Box> { Box::new(self.0.shrink().map(SmallAscii)) } } impl From for String { fn from(s: SmallAscii) -> String { s.0 } } impl AsRef<[u8]> for SmallAscii { fn as_ref(&self) -> &[u8] { self.0.as_ref() } } // This is the same arbitrary impl as `String`, except it has a bias toward // ASCII characters. #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct BiasAscii(String); impl Arbitrary for BiasAscii { fn arbitrary(g: &mut G) -> BiasAscii { use std::char::from_u32; let size = { let s = g.size(); g.gen_range(0, s) }; let mut s = String::with_capacity(size); for _ in 0..size { if g.gen_weighted_bool(3) { s.push(char::arbitrary(g)); } else { for _ in 0..5 { s.push(from_u32(g.gen_range(97, 123)).unwrap()); } } } BiasAscii(s) } fn shrink(&self) -> Box> { Box::new(self.0.shrink().map(BiasAscii)) } } fn naive_find(xs: &[S], haystack: &str) -> Vec where S: Clone + Into { let needles: Vec = xs.to_vec().into_iter().map(Into::into).collect(); let mut matches = vec![]; for hi in 0..haystack.len() { for (pati, needle) in needles.iter().enumerate() { let needle = needle.as_bytes(); if needle.len() == 0 || needle.len() > haystack.len() - hi { continue; } if needle == &haystack.as_bytes()[hi..hi+needle.len()] { matches.push(Match { pati: pati, start: hi, end: hi + needle.len(), }); } } } matches } #[test] fn qc_ac_equals_naive() { fn prop(needles: Vec, haystack: BiasAscii) -> bool { let aut_matches = aut_findo(&needles, &haystack.0); let naive_matches = naive_find(&needles, &haystack.0); // Ordering isn't always the same. I don't think we care, so do // an unordered comparison. let aset: HashSet = aut_matches.iter().cloned().collect(); let nset: HashSet = naive_matches.iter().cloned().collect(); aset == nset } quickcheck(prop as fn(Vec, BiasAscii) -> bool); } } vendor/aho-corasick-0.6.4/src/main.rs0000644000000000000000000000030313264166600016140 0ustar rootrootextern crate memchr; use std::env; use lib::AcAutomaton; #[allow(dead_code)] mod lib; fn main() { let aut = AcAutomaton::new(env::args().skip(1)); println!("{}", aut.dot().trim()); } vendor/atty-0.2.8/0000755000000000000000000000000013264166600012501 5ustar rootrootvendor/atty-0.2.8/.cargo-checksum.json0000644000000000000000000000013113264166600016340 0ustar rootroot{"files":{},"package":"af80143d6f7608d746df1520709e5d141c96f240b0e62b0aa41bdfb53374d9d4"}vendor/atty-0.2.8/.travis.yml0000644000000000000000000000400013264166600014604 0ustar rootrootsudo: false language: rust matrix: fast_finish: true include: - rust: nightly - rust: nightly os: osx - rust: beta - rust: beta os: osx - rust: stable - rust: stable os: osx allow_failures: - rust: nightly before_cache: # Travis can't cache files that are not readable by "others" - chmod -R a+r $HOME/.cargo before_install: # install kcov - > if [ ! -d "$HOME/.kcov/bin" ]; then wget https://github.com/SimonKagstrom/kcov/archive/master.tar.gz && tar xzf master.tar.gz && mkdir kcov-master/build && cd kcov-master/build && cmake -DCMAKE_INSTALL_PREFIX:PATH=$HOME/.kcov .. && make && make install && cd ../.. fi - export PATH=$HOME/.kcov/bin:$PATH script: - cargo build cache: cargo: true apt: true directories: - target/debug/deps - target/debug/build addons: apt: packages: - libcurl4-openssl-dev - libelf-dev - libdw-dev - binutils-dev - libiberty-dev after_success: - '[ $TRAVIS_RUST_VERSION = stable ] && [ $TRAVIS_BRANCH = master ] && [ $TRAVIS_PULL_REQUEST = false ] && (ls target/debug && RUSTFLAGS="-C link-dead-code" cargo test --no-run && for file in target/debug/atty-*; do if [[ "${file: -2}" != ".d" ]]; then mkdir -p "target/cov/$(basename $file)"; kcov --exclude-pattern=/.cargo,/usr/lib --verify "target/cov/$(basename $file)" "$file"; fi; done && kcov --coveralls-id=$COVERALLS_REPO_TOKEN --merge target/cov target/cov/* && echo "covered") || true' - '[ $TRAVIS_RUST_VERSION = stable ] && [ $TRAVIS_BRANCH = master ] && [ $TRAVIS_PULL_REQUEST = false ] && cargo doc --no-deps && echo "" > target/doc/index.html && pip install --user ghp-import && /home/travis/.local/bin/ghp-import -n target/doc && git push -fq https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages && echo "documented"'vendor/atty-0.2.8/CHANGELOG.md0000644000000000000000000000202213264166600014306 0ustar rootroot# 0.2.8 * Fix an inverted condition on MinGW [#22](https://github.com/softprops/atty/pull/22) # 0.2.7 * Change `||` to `&&` for whether MSYS is a tty [#24](https://github.com/softprops/atty/pull/24/) # 0.2.6 * updated winapi dependency to [0.3](https://retep998.github.io/blog/winapi-0.3/) [#18](https://github.com/softprops/atty/pull/18) # 0.2.5 * added support for Wasm compile targets [#17](https://github.com/softprops/atty/pull/17) # 0.2.4 * added support for Wasm compile targets [#17](https://github.com/softprops/atty/pull/17) # 0.2.3 * added support for Redox OS [#14](https://github.com/softprops/atty/pull/14) # 0.2.2 * use target specific dependencies [#11](https://github.com/softprops/atty/pull/11) * Add tty detection for MSYS terminals [#12](https://github.com/softprops/atty/pull/12) # 0.2.1 * fix windows bug # 0.2.0 * support for various stream types # 0.1.2 * windows support (with automated testing) * automated code coverage # 0.1.1 * bumped libc dep from `0.1` to `0.2` # 0.1.0 * initial release vendor/atty-0.2.8/Cargo.toml0000644000000000000000000000230513264166600014431 0ustar rootroot# 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 = "atty" version = "0.2.8" authors = ["softprops "] description = "A simple interface for querying atty" homepage = "https://github.com/softprops/atty" documentation = "http://softprops.github.io/atty" readme = "README.md" keywords = ["terminal", "tty"] license = "MIT" repository = "https://github.com/softprops/atty" [target."cfg(target_os = \"redox\")".dependencies.termion] version = "1.5" [target."cfg(unix)".dependencies.libc] version = "0.2" default-features = false [target."cfg(windows)".dependencies.winapi] version = "0.3" features = ["consoleapi", "processenv", "minwinbase", "minwindef", "winbase"] [badges.travis-ci] repository = "softprops/atty" vendor/atty-0.2.8/LICENSE0000644000000000000000000000204513264166600013507 0ustar rootrootCopyright (c) 2015-2017 Doug Tangren 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. vendor/atty-0.2.8/README.md0000644000000000000000000000311313264166600013756 0ustar rootroot# atty [![Build Status](https://travis-ci.org/softprops/atty.svg?branch=master)](https://travis-ci.org/softprops/atty) [![Build status](https://ci.appveyor.com/api/projects/status/geggrsnsjsuse8cv?svg=true)](https://ci.appveyor.com/project/softprops/atty) [![Coverage Status](https://coveralls.io/repos/softprops/atty/badge.svg?branch=master&service=github)](https://coveralls.io/github/softprops/atty?branch=master) [![crates.io](http://meritbadge.herokuapp.com/atty)](https://crates.io/crates/atty) > are you or are you not a tty? [Documentation](http://softprops.github.io/atty) ## install Add the following to your `Cargo.toml` ```toml [dependencies] atty = "0.2" ``` ## usage ```rust extern crate atty; use atty::Stream; fn main() { if atty::is(Stream::Stdout) { println!("I'm a terminal"); } else { println!("I'm not"); } } ``` ## testing This library has been unit tested on both unix and windows platforms (via appveyor). A simple example program is provided in this repo to test various tty's. By default. It prints ```bash $ cargo run --example atty stdout? true stderr? true stdin? true ``` To test std in, pipe some text to the program ```bash $ echo "test" | cargo run --example atty stdout? true stderr? true stdin? false ``` To test std out, pipe the program to something ```bash $ cargo run --example atty | grep std stdout? false stderr? true stdin? true ``` To test std err, pipe the program to something redirecting std err ```bash $ cargo run --example atty 2>&1 | grep std stdout? false stderr? false stdin? true ``` Doug Tangren (softprops) 2015-2017 vendor/atty-0.2.8/appveyor.yml0000644000000000000000000000102413264166600015066 0ustar rootrootenvironment: matrix: - TARGET: nightly-x86_64-pc-windows-msvc - TARGET: nightly-i686-pc-windows-msvc - TARGET: nightly-x86_64-pc-windows-gnu - TARGET: nightly-i686-pc-windows-gnu install: - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-${env:TARGET}.exe" -FileName "rust-install.exe" - ps: .\rust-install.exe /VERYSILENT /NORESTART /DIR="C:\rust" | Out-Null - ps: $env:PATH="$env:PATH;C:\rust\bin" - call "%VCVARS%" || ver>nul - rustc -vV - cargo -vV build: false test_script: - cargo build vendor/atty-0.2.8/examples/0000755000000000000000000000000013264166600014317 5ustar rootrootvendor/atty-0.2.8/examples/atty.rs0000644000000000000000000000031113264166600015641 0ustar rootrootextern crate atty; use atty::{is, Stream}; fn main() { println!("stdout? {}", is(Stream::Stdout)); println!("stderr? {}", is(Stream::Stderr)); println!("stdin? {}", is(Stream::Stdin)); } vendor/atty-0.2.8/rustfmt.toml0000644000000000000000000000035613264166600015106 0ustar rootroot# keep imports tidy reorder_imported_names = true reorder_imports = true reorder_imports_in_group = true # there is no try! use_try_shorthand = true # don't create rustfmt artifacts write_mode = "Replace" # reduce wide load max_width = 80vendor/atty-0.2.8/src/0000755000000000000000000000000013264166600013270 5ustar rootrootvendor/atty-0.2.8/src/lib.rs0000644000000000000000000001227013264166600014406 0ustar rootroot//! atty is a simple utility that answers one question //! > is this a tty? //! //! usage is just as simple //! //! ``` //! if atty::is(atty::Stream::Stdout) { //! println!("i'm a tty") //! } //! ``` //! //! ``` //! if atty::isnt(atty::Stream::Stdout) { //! println!("i'm not a tty") //! } //! ``` #![cfg_attr(unix, no_std)] #[cfg(unix)] extern crate libc; #[cfg(windows)] extern crate winapi; #[cfg(target_os = "redox")] extern crate termion; #[cfg(windows)] use winapi::shared::minwindef::DWORD; /// possible stream sources #[derive(Clone, Copy, Debug)] pub enum Stream { Stdout, Stderr, Stdin, } /// returns true if this is a tty #[cfg(unix)] pub fn is(stream: Stream) -> bool { extern crate libc; let fd = match stream { Stream::Stdout => libc::STDOUT_FILENO, Stream::Stderr => libc::STDERR_FILENO, Stream::Stdin => libc::STDIN_FILENO, }; unsafe { libc::isatty(fd) != 0 } } /// returns true if this is a tty #[cfg(windows)] pub fn is(stream: Stream) -> bool { use winapi::um::winbase::{STD_ERROR_HANDLE as STD_ERROR, STD_INPUT_HANDLE as STD_INPUT, STD_OUTPUT_HANDLE as STD_OUTPUT}; let (fd, others) = match stream { Stream::Stdin => (STD_INPUT, [STD_ERROR, STD_OUTPUT]), Stream::Stderr => (STD_ERROR, [STD_INPUT, STD_OUTPUT]), Stream::Stdout => (STD_OUTPUT, [STD_INPUT, STD_ERROR]), }; if unsafe { console_on_any(&[fd]) } { // False positives aren't possible. If we got a console then // we definitely have a tty on stdin. return true; } // At this point, we *could* have a false negative. We can determine that // this is true negative if we can detect the presence of a console on // any of the other streams. If another stream has a console, then we know // we're in a Windows console and can therefore trust the negative. if unsafe { console_on_any(&others) } { return false; } // Otherwise, we fall back to a very strange msys hack to see if we can // sneakily detect the presence of a tty. unsafe { msys_tty_on(fd) } } /// returns true if this is _not_ a tty pub fn isnt(stream: Stream) -> bool { !is(stream) } /// Returns true if any of the given fds are on a console. #[cfg(windows)] unsafe fn console_on_any(fds: &[DWORD]) -> bool { use winapi::um::consoleapi::GetConsoleMode; use winapi::um::processenv::GetStdHandle; for &fd in fds { let mut out = 0; let handle = GetStdHandle(fd); if GetConsoleMode(handle, &mut out) != 0 { return true; } } false } /// Returns true if there is an MSYS tty on the given handle. #[cfg(windows)] unsafe fn msys_tty_on(fd: DWORD) -> bool { use std::ffi::OsString; use std::mem; use std::os::windows::ffi::OsStringExt; use std::slice; use winapi::ctypes::c_void; use winapi::um::winbase::GetFileInformationByHandleEx; use winapi::um::fileapi::FILE_NAME_INFO; use winapi::um::minwinbase::FileNameInfo; use winapi::um::processenv::GetStdHandle; use winapi::shared::minwindef::MAX_PATH; let size = mem::size_of::(); let mut name_info_bytes = vec![0u8; size + MAX_PATH]; let res = GetFileInformationByHandleEx( GetStdHandle(fd), FileNameInfo, &mut *name_info_bytes as *mut _ as *mut c_void, name_info_bytes.len() as u32, ); if res == 0 { return false; } let name_info: FILE_NAME_INFO = *(name_info_bytes[0..size].as_ptr() as *const FILE_NAME_INFO); let name_bytes = &name_info_bytes[size..size + name_info.FileNameLength as usize]; let name_u16 = slice::from_raw_parts( name_bytes.as_ptr() as *const u16, name_bytes.len() / 2, ); let name = OsString::from_wide(name_u16) .as_os_str() .to_string_lossy() .into_owned(); name.contains("msys-") && name.contains("-pty") } /// returns true if this is a tty #[cfg(target_os = "redox")] pub fn is(stream: Stream) -> bool { use std::io; use termion::is_tty; match stream { Stream::Stdin => is_tty(&io::stdin()), Stream::Stdout => is_tty(&io::stdout()), Stream::Stderr => is_tty(&io::stderr()), } } /// returns true if this is a tty #[cfg(target_arch = "wasm32")] pub fn is(_stream: Stream) -> bool { false } #[cfg(test)] mod tests { use super::{Stream, is}; #[test] #[cfg(windows)] fn is_err() { // appveyor pipes its output assert!(!is(Stream::Stderr)) } #[test] #[cfg(windows)] fn is_out() { // appveyor pipes its output assert!(!is(Stream::Stdout)) } #[test] #[cfg(windows)] fn is_in() { assert!(is(Stream::Stdin)) } #[test] #[cfg(unix)] fn is_err() { assert!(is(Stream::Stderr)) } #[test] #[cfg(unix)] fn is_out() { assert!(is(Stream::Stdout)) } #[test] #[cfg(target_os = "macos")] fn is_in() { // macos on travis seems to pipe its input assert!(is(Stream::Stdin)) } #[test] #[cfg(all(not(target_os = "macos"), unix))] fn is_in() { assert!(is(Stream::Stdin)) } } vendor/backtrace-0.3.6/0000755000000000000000000000000013264166600013436 5ustar rootrootvendor/backtrace-0.3.6/.cargo-checksum.json0000644000000000000000000000013113264166600017275 0ustar rootroot{"files":{},"package":"ebbe525f66f42d207968308ee86bc2dd60aa5fab535b22e616323a173d097d8e"}vendor/backtrace-0.3.6/.travis.yml0000664000000000000000000000463213264166600015556 0ustar rootrootlanguage: rust sudo: false matrix: include: - rust: 1.21.0 - rust: stable - os: osx - rust: beta - rust: nightly - rust: nightly before_script: - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH script: - cargo doc --no-deps --all-features after_success: - travis-cargo --only nightly doc-upload dist: trusty addons: sources: # Provides clang-3.9 - llvm-toolchain-trusty-3.9 apt: packages: # Required for `bindgen`, which is required by `findshlibs`, which is # required by the `gimli` feature. - clang-3.9 script: - cargo test - cargo test --no-default-features - cargo test --no-default-features --features 'libunwind' - cargo test --no-default-features --features 'libunwind dladdr' - cargo test --no-default-features --features 'libunwind libbacktrace' - cargo test --no-default-features --features 'unix-backtrace' - cargo test --no-default-features --features 'unix-backtrace dladdr' - cargo test --no-default-features --features 'unix-backtrace libbacktrace' - cargo test --no-default-features --features 'serialize-serde' - cargo test --no-default-features --features 'serialize-rustc' - cargo test --no-default-features --features 'serialize-rustc serialize-serde' - cargo test --no-default-features --features 'cpp_demangle' - cargo test --no-default-features --features 'gimli-symbolize' - cd ./cpp_smoke_test && cargo test && cd .. - cargo clean && cargo build notifications: email: on_success: never after_success: - travis-cargo --only nightly doc-upload env: global: # serde-codegen has historically needed a large stack to expand - RUST_MIN_STACK=16777216 - secure: "Kuf3j6gC3MhR+F7g8/5J4+3tu+FXJP/SqKjsUVVjs/qjniIVX3MwZPhtP/pVtdRvYjW0NzLw5Nufb4o1cyY4uKwR8BHHNuEUE/h3mPShjWHqzLyn5QiBumPozsFCa32H4gconRmp3+s0YrBT7nLoGvUZZS0dkldMkpvvrPL/yUKXLS8HEP4L1GO5iMQQYG6i3sbWTbHikE6ZQogW/iZommyqUkVB/s/SQvdH9SXu89ttNXlm/F+EIsgsgyzpbULp5sD34GRDPJe+H1m+sgA1kTRrzmuBGNmz9mx6GyIKaqACTm1gRcb06nFjTPVTQioJBNnoV7TEqZCvjuSsUjcGmP4Aeissafo93ADzV+bd0uoWIScE9ltSVS+RgCDV+sd0GHz5U6FjhgZp0amaVl3d6hPp8lbTfK/gfj1i9ktQfKZbG7rB4tfIU1KeQRkyE9vb/TaKp8nwBbc4SVQ4EKFOlRbE1S1FooaKZweW8w57d2u+sMMMVJbO28/Ap8tk9xDSOl4shPaT0iM0U9/heF8FmCZB1OKXLKn6TAaNFnaMTvdTHl+Tjrf6Vzd/oPXJ7GuaB6eLxXYjXvZHuKiLkSZriOzhL7PbijNILbSgZt7+Fa0vcnXP8zgD4dmupx/CoIHLN9NP4o9cGXuBcaJ/iFryJ4i5LKGFNEUHtXkavDrcgcA=" vendor/backtrace-0.3.6/Cargo.toml0000644000000000000000000000455713264166600015401 0ustar rootroot# 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" version = "0.3.6" authors = ["Alex Crichton ", "The Rust Project Developers"] description = "A library to acquire a stack trace (backtrace) at runtime in a Rust program.\n" homepage = "https://github.com/alexcrichton/backtrace-rs" documentation = "http://alexcrichton.com/backtrace-rs" readme = "README.md" license = "MIT/Apache-2.0" repository = "https://github.com/alexcrichton/backtrace-rs" [dependencies.addr2line] version = "0.6.0" optional = true [dependencies.cfg-if] version = "0.1" [dependencies.cpp_demangle] version = "0.2.3" optional = true default-features = false [dependencies.findshlibs] version = "0.3.3" optional = true [dependencies.gimli] version = "0.15.0" optional = true [dependencies.memmap] version = "0.6.2" optional = true [dependencies.object] version = "0.7.0" optional = true [dependencies.rustc-demangle] version = "0.1.4" [dependencies.rustc-serialize] version = "0.3" optional = true [dependencies.serde] version = "1.0" optional = true [dependencies.serde_derive] version = "1.0" optional = true [features] coresymbolication = [] dbghelp = ["winapi"] default = ["libunwind", "libbacktrace", "coresymbolication", "dladdr", "dbghelp"] dladdr = [] gimli-symbolize = ["addr2line", "findshlibs", "gimli", "memmap", "object"] kernel32 = [] libbacktrace = ["backtrace-sys"] libunwind = [] serialize-rustc = ["rustc-serialize"] serialize-serde = ["serde", "serde_derive"] 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.3" optional = true [target."cfg(unix)".dependencies.libc] version = "0.2" [target."cfg(windows)".dependencies.winapi] version = "0.3.3" features = ["std", "dbghelp", "processthreadsapi", "winnt", "minwindef"] optional = true vendor/backtrace-0.3.6/LICENSE-APACHE0000664000000000000000000002513713264166600015374 0ustar rootroot 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. vendor/backtrace-0.3.6/LICENSE-MIT0000664000000000000000000000204113264166600015071 0ustar rootrootCopyright (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. vendor/backtrace-0.3.6/README.md0000664000000000000000000000442613264166600014725 0ustar rootroot# 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](http://alexcrichton.com/backtrace-rs) A library for acquiring backtraces at runtime for Rust. This library aims to enhance the support given by the standard library at `std::rt` by providing a more stable and programmatic interface. ## Install ```toml [dependencies] backtrace = "0.3" ``` ```rust extern crate backtrace; ``` Note that this crate requires `make`, `objcopy`, and `ar` to be present on Linux systems. ## Usage To simply capture a backtrace and defer dealing with it until a later time, you can use the top-level `Backtrace` type. ```rust extern crate backtrace; use backtrace::Backtrace; fn main() { let bt = Backtrace::new(); // do_some_work(); println!("{:?}", bt); } ``` If, however, you'd like more raw access to the actual tracing functionality, you can use the `trace` and `resolve` functions directly. ```rust extern crate backtrace; fn main() { backtrace::trace(|frame| { let ip = frame.ip(); let symbol_address = frame.symbol_address(); // Resolve this instruction pointer to a symbol name backtrace::resolve(ip, |symbol| { if let Some(name) = symbol.name() { // ... } if let Some(filename) = symbol.filename() { // ... } }); true // keep going to the next frame }); } ``` ## 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 * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in backtrace-rs by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. vendor/backtrace-0.3.6/appveyor.yml0000664000000000000000000000112313264166600016025 0ustar rootrootenvironment: 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% vendor/backtrace-0.3.6/examples/0000755000000000000000000000000013264166600015254 5ustar rootrootvendor/backtrace-0.3.6/examples/backtrace.rs0000664000000000000000000000015213264166600017541 0ustar rootrootextern crate backtrace; use backtrace::Backtrace; fn main() { println!("{:?}", Backtrace::new()); } vendor/backtrace-0.3.6/examples/raw.rs0000664000000000000000000000233013264166600016413 0ustar rootrootextern crate backtrace; fn main() { foo(); } 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; fn print() { let mut cnt = 0; backtrace::trace(|frame| { let ip = frame.ip(); print!("frame #{:<2} - {:#02$x}", cnt, ip as usize, HEX_WIDTH); cnt += 1; let mut resolved = false; backtrace::resolve(frame.ip(), |symbol| { if !resolved { resolved = true; } else { print!("{}", vec![" "; 7 + 2 + 3 + HEX_WIDTH].join("")); } if let Some(name) = symbol.name() { print!(" - {}", name); } else { print!(" - "); } if let Some(file) = symbol.filename() { if let Some(l) = symbol.lineno() { print!("\n{:13}{:4$}@ {}:{}", "", "", file.display(), l, HEX_WIDTH); } } println!(""); }); if !resolved { println!(" - "); } true // keep going }); } vendor/backtrace-0.3.6/src/0000755000000000000000000000000013264166600014225 5ustar rootrootvendor/backtrace-0.3.6/src/backtrace/0000755000000000000000000000000013264166600016144 5ustar rootrootvendor/backtrace-0.3.6/src/backtrace/dbghelp.rs0000664000000000000000000000702613264166600020126 0ustar rootroot// Copyright 2014 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![allow(bad_style)] use std::mem; use winapi::ctypes::*; use winapi::shared::minwindef::*; use winapi::um::processthreadsapi; use winapi::um::winnt::{self, CONTEXT}; use winapi::um::dbghelp; use winapi::um::dbghelp::*; pub struct Frame { inner: STACKFRAME64, } impl Frame { pub fn ip(&self) -> *mut c_void { self.inner.AddrPC.Offset as *mut _ } pub fn symbol_address(&self) -> *mut c_void { self.ip() } } #[inline(always)] pub fn trace(cb: &mut FnMut(&super::Frame) -> bool) { // According to windows documentation, all dbghelp functions are // single-threaded. let _g = ::lock::lock(); unsafe { // Allocate necessary structures for doing the stack walk let process = processthreadsapi::GetCurrentProcess(); let thread = processthreadsapi::GetCurrentThread(); // The CONTEXT structure needs to be aligned on a 16-byte boundary for // 64-bit Windows, but currently we don't have a way to express that in // Rust. Allocations are generally aligned to 16-bytes, though, so we // box this up. let mut context = Box::new(mem::zeroed::()); winnt::RtlCaptureContext(&mut *context); let mut frame = super::Frame { inner: Frame { inner: mem::zeroed() }, }; let image = init_frame(&mut frame.inner.inner, &context); // Initialize this process's symbols let _c = ::dbghelp_init(); // 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 as *mut _ 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 } 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 } #[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 } vendor/backtrace-0.3.6/src/backtrace/libunwind.rs0000664000000000000000000001553713264166600020522 0ustar rootroot// 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use std::os::raw::c_void; pub struct Frame { ctx: *mut uw::_Unwind_Context, } 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 }; 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 } 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. // // 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. if cfg!(target_os = "macos") || cfg!(target_os = "ios") { self.ip() } else { unsafe { uw::_Unwind_FindEnclosingFunction(self.ip()) } } } } #[inline(always)] pub fn trace(mut cb: &mut FnMut(&super::Frame) -> bool) { unsafe { 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 { let cb = unsafe { &mut *(arg as *mut &mut FnMut(&super::Frame) -> bool) }; let cx = super::Frame { inner: Frame { ctx: ctx }, }; let mut bomb = ::Bomb { enabled: true }; let keep_going = cb(&cx); bomb.enabled = false; if keep_going { uw::_URC_NO_REASON } else { uw::_URC_FAILURE } } } /// Unwind library interface used for backtraces /// /// Note that dead code is allowed as here are just bindings /// iOS doesn't use all of them it but adding more /// platform-specific configs pollutes the code too much #[allow(non_camel_case_types)] #[allow(non_snake_case)] #[allow(dead_code)] mod uw { pub use self::_Unwind_Reason_Code::*; use libc; use std::os::raw::{c_int, c_void}; #[repr(C)] pub enum _Unwind_Reason_Code { _URC_NO_REASON = 0, _URC_FOREIGN_EXCEPTION_CAUGHT = 1, _URC_FATAL_PHASE2_ERROR = 2, _URC_FATAL_PHASE1_ERROR = 3, _URC_NORMAL_STOP = 4, _URC_END_OF_STACK = 5, _URC_HANDLER_FOUND = 6, _URC_INSTALL_CONTEXT = 7, _URC_CONTINUE_UNWIND = 8, _URC_FAILURE = 9, // used only by ARM EABI } pub enum _Unwind_Context {} pub type _Unwind_Trace_Fn = extern fn(ctx: *mut _Unwind_Context, arg: *mut c_void) -> _Unwind_Reason_Code; extern { // 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; // 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(target_os = "android"), 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")))] pub unsafe fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> libc::uintptr_t { #[repr(C)] enum _Unwind_VRS_Result { _UVRSR_OK = 0, _UVRSR_NOT_IMPLEMENTED = 1, _UVRSR_FAILED = 2, } #[repr(C)] enum _Unwind_VRS_RegClass { _UVRSC_CORE = 0, _UVRSC_VFP = 1, _UVRSC_FPA = 2, _UVRSC_WMMXD = 3, _UVRSC_WMMXC = 4, } #[repr(C)] enum _Unwind_VRS_DataRepresentation { _UVRSD_UINT32 = 0, _UVRSD_VFPX = 1, _UVRSD_FPAX = 2, _UVRSD_UINT64 = 3, _UVRSD_FLOAT = 4, _UVRSD_DOUBLE = 5, } 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; } 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); (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 { pc } } vendor/backtrace-0.3.6/src/backtrace/mod.rs0000664000000000000000000000752313264166600017302 0ustar rootrootuse std::fmt; use std::os::raw::c_void; /// Inspects the current call-stack, passing all active frames into the closure /// provided to calculate a stack trace. /// /// This function is the workhorse of this library in calculating the stack /// traces for a program. The given closure `cb` is yielded instances of a /// `Frame` which represent information about that call frame on the stack. The /// closure is yielded frames in a top-down fashion (most recently called /// functions first). /// /// The closure's return value is an indication of whether the backtrace should /// continue. A return value of `false` will terminate the backtrace and return /// immediately. /// /// Once a `Frame` is acquired you will likely want to call `backtrace::resolve` /// to convert the `ip` (instruction pointer) or symbol address to a `Symbol` /// through which the name and/or filename/line number can be learned. /// /// Note that this is a relatively low-level function and if you'd like to, for /// example, capture a backtrace to be inspected later, then the `Backtrace` /// type may be more appropriate. /// /// # Example /// /// ``` /// extern crate backtrace; /// /// fn main() { /// backtrace::trace(|frame| { /// // ... /// /// true // continue the backtrace /// }); /// } /// ``` #[inline(never)] // if this is never inlined then the first frame can be known // to be skipped pub fn trace 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. pub struct Frame { inner: FrameImp, } impl Frame { /// Returns the current instruction pointer of this frame. /// /// This is normally the next instruction to execute in the frame, but not /// all implementations list this with 100% accuracy (but it's generally /// pretty close). /// /// It is recommended to pass this value to `backtrace::resolve` to turn it /// into a symbol name. pub fn ip(&self) -> *mut c_void { self.inner.ip() } /// Returns the starting symbol address of the frame of this function. /// /// This will attempt to rewind the instruction pointer returned by `ip` to /// the start of the function, returning that value. In some cases, however, /// backends will just return `ip` from this function. /// /// The returned value can sometimes be used if `backtrace::resolve` failed /// on the `ip` given above. pub fn symbol_address(&self) -> *mut c_void { self.inner.symbol_address() } } impl fmt::Debug for Frame { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Frame") .field("ip", &self.ip()) .field("symbol_address", &self.symbol_address()) .finish() } } cfg_if! { if #[cfg(all(unix, not(target_os = "emscripten"), not(all(target_os = "ios", target_arch = "arm")), feature = "libunwind"))] { 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"))] { 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"))] { mod dbghelp; use self::dbghelp::trace as trace_imp; use self::dbghelp::Frame as FrameImp; } else { mod noop; use self::noop::trace as trace_imp; use self::noop::Frame as FrameImp; } } vendor/backtrace-0.3.6/src/backtrace/noop.rs0000664000000000000000000000042513264166600017470 0ustar rootrootuse std::os::raw::c_void; #[inline(always)] pub fn trace(_cb: &mut FnMut(&super::Frame) -> bool) {} pub struct Frame; impl Frame { pub fn ip(&self) -> *mut c_void { 0 as *mut _ } pub fn symbol_address(&self) -> *mut c_void { 0 as *mut _ } } vendor/backtrace-0.3.6/src/backtrace/unix_backtrace.rs0000664000000000000000000000230113264166600021472 0ustar rootroot// 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use std::mem; use std::os::raw::{c_void, c_int}; pub struct Frame { addr: *mut c_void, } impl Frame { pub fn ip(&self) -> *mut c_void { self.addr } pub fn symbol_address(&self) -> *mut c_void { self.addr } } extern { fn backtrace(buf: *mut *mut c_void, sz: c_int) -> c_int; } #[inline(always)] pub fn trace(cb: &mut FnMut(&super::Frame) -> bool) { const SIZE: usize = 100; let mut buf: [*mut c_void; SIZE]; let cnt; unsafe { buf = mem::zeroed(); cnt = backtrace(buf.as_mut_ptr(), SIZE as c_int); } for addr in buf[..cnt as usize].iter() { let cx = super::Frame { inner: Frame { addr: *addr }, }; if !cb(&cx) { return } } } vendor/backtrace-0.3.6/src/capture.rs0000664000000000000000000001676413264166600016256 0ustar rootrootuse std::fmt; use std::mem; use std::os::raw::c_void; use std::path::{Path, PathBuf}; use {trace, resolve, SymbolName}; /// Representation of an owned and self-contained backtrace. /// /// This structure can be used to capture a backtrace at various points in a /// program and later used to inspect what the backtrace was at that time. #[derive(Clone)] #[cfg_attr(feature = "serialize-rustc", derive(RustcDecodable, RustcEncodable))] #[cfg_attr(feature = "serialize-serde", derive(Deserialize, Serialize))] pub struct Backtrace { frames: Vec, } /// 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. #[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, symbols: Option>, } /// 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. #[derive(Clone)] #[cfg_attr(feature = "serialize-rustc", derive(RustcDecodable, RustcEncodable))] #[cfg_attr(feature = "serialize-serde", derive(Deserialize, Serialize))] pub struct BacktraceSymbol { name: Option>, addr: Option, filename: Option, lineno: Option, } impl Backtrace { /// Captures a backtrace at the callsite of this function, returning an /// owned representation. /// /// This function is useful for representing a backtrace as an object in /// Rust. This returned value can be sent across threads and printed /// elsewhere, and the purpose of this value is to be entirely self /// contained. /// /// # Examples /// /// ``` /// use backtrace::Backtrace; /// /// let current_backtrace = Backtrace::new(); /// ``` pub fn new() -> Backtrace { let mut bt = Backtrace::new_unresolved(); bt.resolve(); return bt } /// Similar to `new` except that this does not resolve any symbols, this /// simply captures the backtrace as a list of addresses. /// /// At a later time the `resolve` function can be called to resolve this /// backtrace's symbols into readable names. This function exists because /// the resolution process can sometimes take a significant amount of time /// whereas any one backtrace may only be rarely printed. /// /// # Examples /// /// ``` /// use backtrace::Backtrace; /// /// let mut current_backtrace = Backtrace::new_unresolved(); /// println!("{:?}", current_backtrace); // no symbol names /// current_backtrace.resolve(); /// println!("{:?}", current_backtrace); // symbol names now present /// ``` pub fn new_unresolved() -> Backtrace { let mut frames = Vec::new(); trace(|frame| { frames.push(BacktraceFrame { ip: frame.ip() as usize, symbol_address: frame.symbol_address() as usize, symbols: None, }); true }); Backtrace { frames: frames } } /// Returns the frames from when this backtrace was captured. /// /// 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. pub fn frames(&self) -> &[BacktraceFrame] { &self.frames } /// If this backtrace was created from `new_unresolved` then this function /// will resolve all addresses in the backtrace to their symbolic names. /// /// If this backtrace has been previously resolved or was created through /// `new`, this function does nothing. 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_path_buf()), lineno: symbol.lineno(), }); }); frame.symbols = Some(symbols); } } } impl From> for Backtrace { fn from(frames: Vec) -> Self { Backtrace { frames: frames } } } impl Into> for Backtrace { fn into(self) -> Vec { self.frames } } impl BacktraceFrame { /// Same as `Frame::ip` pub fn ip(&self) -> *mut c_void { self.ip as *mut c_void } /// Same as `Frame::symbol_address` pub fn symbol_address(&self) -> *mut c_void { self.symbol_address as *mut c_void } /// Returns the list of symbols that this frame corresponds to. /// /// Normally there is only one symbol per frame, but sometimes if a number /// of functions are inlined into one frame then multiple symbols will be /// returned. The first symbol listed is the "innermost function", whereas /// the last symbol is the outermost (last caller). /// /// Note that if this frame came from an unresolved backtrace then this will /// return an empty list. pub fn symbols(&self) -> &[BacktraceSymbol] { self.symbols.as_ref().map(|s| &s[..]).unwrap_or(&[]) } } impl BacktraceSymbol { /// Same as `Symbol::name` pub fn name(&self) -> Option { self.name.as_ref().map(|s| SymbolName::new(s)) } /// Same as `Symbol::addr` pub fn addr(&self) -> Option<*mut c_void> { self.addr.map(|s| s as *mut c_void) } /// Same as `Symbol::filename` pub fn filename(&self) -> Option<&Path> { self.filename.as_ref().map(|p| &**p) } /// Same as `Symbol::lineno` pub fn lineno(&self) -> Option { self.lineno } } impl fmt::Debug for Backtrace { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let hex_width = mem::size_of::() * 2 + 2; try!(write!(fmt, "stack backtrace:")); for (idx, frame) in self.frames().iter().enumerate() { let ip = frame.ip(); try!(write!(fmt, "\n{:4}: {:2$?}", idx, ip, hex_width)); let symbols = match frame.symbols { Some(ref s) => s, None => { try!(write!(fmt, " - ")); continue } }; if symbols.len() == 0 { try!(write!(fmt, " - ")); } for (idx, symbol) in symbols.iter().enumerate() { if idx != 0 { try!(write!(fmt, "\n {:1$}", "", hex_width)); } if let Some(name) = symbol.name() { try!(write!(fmt, " - {}", name)); } else { try!(write!(fmt, " - ")); } if let (Some(file), Some(line)) = (symbol.filename(), symbol.lineno()) { try!(write!(fmt, "\n {:3$}at {}:{}", "", file.display(), line, hex_width)); } } } Ok(()) } } impl Default for Backtrace { fn default() -> Backtrace { Backtrace::new() } } vendor/backtrace-0.3.6/src/dylib.rs0000664000000000000000000000344513264166600015706 0ustar rootrootuse std::ffi::CString; use std::marker; use std::mem; use std::sync::atomic::{AtomicUsize, Ordering}; use libc::{self, c_char, c_void}; pub struct Dylib { pub init: AtomicUsize, } pub struct Symbol { pub name: &'static str, pub addr: AtomicUsize, pub _marker: marker::PhantomData, } impl Dylib { pub unsafe fn get<'a, T>(&self, sym: &'a Symbol) -> 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 } let name = CString::new(path).unwrap(); let ptr = libc::dlopen(name.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 Symbol { unsafe fn get(&self, handle: *mut c_void) -> Option<&T> { assert_eq!(mem::size_of::(), 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 } } vendor/backtrace-0.3.6/src/lib.rs0000664000000000000000000001141113264166600015341 0ustar rootroot//! A library for acquiring a backtrace at runtime //! //! This library is meant to supplement the `RUST_BACKTRACE=1` support of the //! standard library by allowing an acquisition of a backtrace at runtime //! programmatically. The backtraces generated by this library do not need to be //! parsed, for example, and expose the functionality of multiple backend //! implementations. //! //! # Implementation //! //! This library makes use of a number of strategies for actually acquiring a //! backtrace. For example unix uses libgcc's libunwind bindings by default to //! acquire a backtrace, but coresymbolication or dladdr is used on OSX to //! acquire symbol names while linux uses gcc's libbacktrace. //! //! When using the default feature set of this library the "most reasonable" set //! 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 //! backend implementations of acquiring a backtrace. Consequently the currently //! exported functions are closure-based as opposed to the likely expected //! iterator-based versions. This is done due to limitations of the underlying //! APIs used from the system. //! //! # Usage //! //! First, add this to your Cargo.toml //! //! ```toml //! [dependencies] //! backtrace = "0.2" //! ``` //! //! Next: //! //! ``` //! extern crate backtrace; //! //! fn main() { //! backtrace::trace(|frame| { //! let ip = frame.ip(); //! let symbol_address = frame.symbol_address(); //! //! // Resolve this instruction pointer to a symbol name //! backtrace::resolve(ip, |symbol| { //! if let Some(name) = symbol.name() { //! // ... //! } //! if let Some(filename) = symbol.filename() { //! // ... //! } //! }); //! //! true // keep going to the next frame //! }); //! } //! ``` #![doc(html_root_url = "http://alexcrichton.com/backtrace-rs")] #![deny(missing_docs)] #![deny(warnings)] #[cfg(unix)] extern crate libc; #[cfg(all(windows, feature = "winapi"))] 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 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, Frame}; mod backtrace; pub use symbolize::{resolve, Symbol, SymbolName}; mod symbolize; pub use capture::{Backtrace, BacktraceFrame, BacktraceSymbol}; mod capture; #[allow(dead_code)] struct Bomb { enabled: bool, } #[allow(dead_code)] impl Drop for Bomb { fn drop(&mut self) { if self.enabled { panic!("cannot panic during the backtrace function"); } } } #[allow(dead_code)] mod lock { use std::cell::Cell; use std::mem; use std::sync::{Once, Mutex, MutexGuard, ONCE_INIT}; pub struct LockGuard(MutexGuard<'static, ()>); static mut LOCK: *mut Mutex<()> = 0 as *mut _; static INIT: Once = ONCE_INIT; thread_local!(static LOCK_HELD: Cell = Cell::new(false)); impl Drop for LockGuard { fn drop(&mut self) { LOCK_HELD.with(|slot| { assert!(slot.get()); slot.set(false); }); } } pub fn lock() -> Option { if LOCK_HELD.with(|l| l.get()) { return None } LOCK_HELD.with(|s| s.set(true)); unsafe { INIT.call_once(|| { LOCK = mem::transmute(Box::new(Mutex::new(()))); }); Some(LockGuard((*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; } } vendor/backtrace-0.3.6/src/symbolize/0000755000000000000000000000000013264166600016242 5ustar rootrootvendor/backtrace-0.3.6/src/symbolize/coresymbolication.rs0000664000000000000000000001312313264166600022337 0ustar rootroot// 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![allow(bad_style)] use std::ffi::{CStr, OsStr}; use std::mem; use std::os::raw::{c_void, c_char, c_int}; use std::os::unix::prelude::*; use std::path::Path; use std::ptr; use std::sync::atomic::ATOMIC_USIZE_INIT; use libc::{self, Dl_info}; use SymbolName; use dylib::Dylib; use dylib::Symbol as DylibSymbol; #[repr(C)] #[derive(Copy, Clone, PartialEq)] pub struct CSTypeRef { cpp_data: *const c_void, cpp_obj: *const c_void } const CS_NOW: u64 = 0x80000000; const CSREF_NULL: CSTypeRef = CSTypeRef { cpp_data: 0 as *const c_void, cpp_obj: 0 as *const c_void, }; pub enum Symbol { Core { path: *const c_char, lineno: u32, name: *const c_char, addr: *mut c_void, }, Dladdr(Dl_info), } impl Symbol { pub fn name(&self) -> Option { let name = match *self { Symbol::Core { name, .. } => name, Symbol::Dladdr(ref info) => info.dli_sname, }; if name.is_null() { None } else { Some(SymbolName::new(unsafe { CStr::from_ptr(name).to_bytes() })) } } 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 _), } } pub fn filename(&self) -> Option<&Path> { match *self { Symbol::Core { path, .. } => { if path.is_null() { None } else { Some(Path::new(OsStr::from_bytes(unsafe { CStr::from_ptr(path).to_bytes() }))) } } Symbol::Dladdr(_) => None, } } pub fn lineno(&self) -> Option { match *self { Symbol::Core { lineno: 0, .. } => None, Symbol::Core { lineno, .. } => Some(lineno), Symbol::Dladdr(_) => None, } } } static CORESYMBOLICATION: Dylib = Dylib { init: ATOMIC_USIZE_INIT }; macro_rules! dlsym { (extern { $(fn $name:ident($($arg:ident: $t:ty),*) -> $ret:ty;)* }) => ($( static $name: ::dylib::Symbol $ret> = ::dylib::Symbol { name: concat!(stringify!($name), "\0"), addr: ::std::sync::atomic::ATOMIC_USIZE_INIT, _marker: ::std::marker::PhantomData, }; )*) } dlsym! { extern { fn CSSymbolicatorCreateWithPid(pid: c_int) -> CSTypeRef; fn CSRelease(rf: CSTypeRef) -> c_void; fn CSSymbolicatorGetSymbolWithAddressAtTime( cs: CSTypeRef, addr: *const c_void, time: u64) -> CSTypeRef; fn CSSymbolicatorGetSourceInfoWithAddressAtTime( cs: CSTypeRef, addr: *const c_void, time: u64) -> CSTypeRef; fn CSSourceInfoGetLineNumber(info: CSTypeRef) -> c_int; fn CSSourceInfoGetPath(info: CSTypeRef) -> *const c_char; fn CSSourceInfoGetSymbol(info: CSTypeRef) -> CSTypeRef; fn CSSymbolGetName(sym: CSTypeRef) -> *const c_char; fn CSSymbolGetSymbolOwner(sym: CSTypeRef) -> CSTypeRef; fn CSSymbolOwnerGetBaseAddress(symowner: CSTypeRef) -> *mut c_void; } } unsafe fn get(sym: &DylibSymbol) -> &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"; if !CORESYMBOLICATION.init(path) { return false; } let cs = get(&CSSymbolicatorCreateWithPid)(libc::getpid()); if cs == CSREF_NULL { 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 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(&CSSymbolGetName)(sym), addr: get(&CSSymbolOwnerGetBaseAddress)(owner), }, }); rv = true; } } get(&CSRelease)(cs); rv } pub fn resolve(addr: *mut c_void, cb: &mut FnMut(&super::Symbol)) { unsafe { if try_resolve(addr, cb) { return } let mut info: Dl_info = mem::zeroed(); if libc::dladdr(addr as *mut _, &mut info) != 0 { cb(&super::Symbol { inner: Symbol::Dladdr(info), }); } } } vendor/backtrace-0.3.6/src/symbolize/dbghelp.rs0000664000000000000000000000750213264166600020223 0ustar rootroot// 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![allow(bad_style)] use std::ffi::OsString; use std::mem; use std::path::Path; use std::os::windows::prelude::*; use std::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; pub struct Symbol { name: OsString, addr: *mut c_void, line: Option, filename: Option, } impl Symbol { pub fn name(&self) -> Option { self.name.to_str().map(|s| SymbolName::new(s.as_bytes())) } pub fn addr(&self) -> Option<*mut c_void> { Some(self.addr as *mut _) } pub fn filename(&self) -> Option<&Path> { self.filename.as_ref().map(Path::new) } pub fn lineno(&self) -> Option { self.line } } pub fn resolve(addr: *mut c_void, cb: &mut FnMut(&super::Symbol)) { // According to windows documentation, all dbghelp functions are // single-threaded. let _g = ::lock::lock(); unsafe { let size = 2 * MAX_SYM_NAME + mem::size_of::(); let mut data = vec![0u8; size]; let info = &mut *(data.as_mut_ptr() as *mut SYMBOL_INFOW); info.MaxNameLen = MAX_SYM_NAME as ULONG; // the struct size in C. the value is different to // `size_of::() - MAX_SYM_NAME + 1` (== 81) // 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 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 = ::std::cmp::min(info.NameLen as usize, info.MaxNameLen as usize - 1); let name = slice::from_raw_parts(info.Name.as_ptr() as *const u16, name_len); let name = OsString::from_wide(name); let mut line = mem::zeroed::(); line.SizeOfStruct = mem::size_of::() 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 { lineno = Some(line.LineNumber as u32); let base = line.FileName; let mut len = 0; while *base.offset(len) != 0 { len += 1; } let name = slice::from_raw_parts(base, len as usize); filename = Some(OsString::from_wide(name)); } cb(&super::Symbol { inner: Symbol { name: name, addr: info.Address as *mut _, line: lineno, filename: filename, }, }) } } vendor/backtrace-0.3.6/src/symbolize/dladdr.rs0000664000000000000000000000271713264166600020053 0ustar rootroot// 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use std::ffi::CStr; use std::mem; use std::os::raw::c_void; use std::path::Path; use libc::{self, Dl_info}; use SymbolName; pub struct Symbol { inner: Dl_info, } impl Symbol { pub fn name(&self) -> Option { if self.inner.dli_sname.is_null() { None } else { Some(SymbolName::new(unsafe { CStr::from_ptr(self.inner.dli_sname).to_bytes() })) } } pub fn addr(&self) -> Option<*mut c_void> { Some(self.inner.dli_saddr as *mut _) } pub fn filename(&self) -> Option<&Path> { None } pub fn lineno(&self) -> Option { None } } pub fn resolve(addr: *mut c_void, cb: &mut FnMut(&super::Symbol)) { unsafe { 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) } } } vendor/backtrace-0.3.6/src/symbolize/gimli.rs0000664000000000000000000001561513264166600017723 0ustar rootrootuse 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 std::os::raw::c_void; use std::path::{Path, PathBuf}; use std::u32; use SymbolName; const MAPPINGS_CACHE_SIZE: usize = 4; type Dwarf<'map> = addr2line::Context>; type Symbols<'map> = object::SymbolMap<'map>; struct Mapping { // 'static lifetime is a lie to hack around lack of support for self-referential structs. dwarf: Dwarf<'static>, symbols: Symbols<'static>, _map: Mmap, } impl Mapping { fn new(path: &PathBuf) -> Option { 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. unsafe { (mem::transmute(dwarf), mem::transmute(symbols)) } }; Some(Mapping { dwarf, symbols, _map: map, }) } // Ensure the 'static lifetimes don't leak. fn rent(&self, mut f: F) where F: FnMut(&Dwarf, &Symbols), { f(&self.dwarf, &self.symbols) } } 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> = RefCell::new(Vec::with_capacity(MAPPINGS_CACHE_SIZE)); } fn with_mapping_for_path(path: PathBuf, f: F) where F: FnMut(&Dwarf, &Symbols), { MAPPINGS_CACHE.with(|cache| { let mut cache = cache.borrow_mut(); let idx = cache.iter().position(|&(ref p, _)| p == &path); // Invariant: after this conditional completes without early returning // from an error, the cache entry for this path is at index 0. 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); } } 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, }; if cache.len() == MAPPINGS_CACHE_SIZE { cache.pop(); } cache.insert(0, (path, mapping)); } cache[0].1.rent(f); }); } 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), }; // 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) }; // 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) { 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; } } // 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); } } }); } pub struct Symbol { addr: usize, file: Option, line: Option, name: Option, } impl Symbol { fn new(addr: usize, file: Option, line: Option, name: Option) -> Symbol { Symbol { addr, file, line, name, } } pub fn name(&self) -> Option { self.name.as_ref().map(|s| SymbolName::new(s.as_bytes())) } pub fn addr(&self) -> Option<*mut c_void> { Some(self.addr as *mut c_void) } pub fn filename(&self) -> Option<&Path> { self.file.as_ref().map(|f| f.as_ref()) } pub fn lineno(&self) -> Option { self.line .and_then(|l| if l > (u32::MAX as u64) { None } else { Some(l as u32) }) } } vendor/backtrace-0.3.6/src/symbolize/libbacktrace.rs0000664000000000000000000001324713264166600021227 0ustar rootroot// 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![allow(bad_style)] extern crate backtrace_sys as bt; use libc::uintptr_t; use std::ffi::{CStr, OsStr}; use std::os::raw::{c_void, c_char, c_int}; use std::os::unix::prelude::*; use std::path::Path; use std::ptr; use std::sync::{ONCE_INIT, Once}; use SymbolName; pub enum Symbol { Syminfo { pc: uintptr_t, symname: *const c_char, }, Pcinfo { pc: uintptr_t, filename: *const c_char, lineno: c_int, function: *const c_char, }, } impl Symbol { pub fn name(&self) -> Option { let ptr = match *self { Symbol::Syminfo { symname, .. } => symname, Symbol::Pcinfo { function, .. } => function, }; if ptr.is_null() { None } else { Some(SymbolName::new(unsafe { CStr::from_ptr(ptr).to_bytes() })) } } pub fn addr(&self) -> Option<*mut c_void> { let pc = match *self { Symbol::Syminfo { pc, .. } => pc, Symbol::Pcinfo { pc, .. } => pc, }; if pc == 0 {None} else {Some(pc as *mut _)} } pub fn filename(&self) -> Option<&Path> { match *self { Symbol::Syminfo { .. } => None, Symbol::Pcinfo { filename, .. } => { Some(Path::new(OsStr::from_bytes(unsafe { CStr::from_ptr(filename).to_bytes() }))) } } } pub fn lineno(&self) -> Option { match *self { Symbol::Syminfo { .. } => None, Symbol::Pcinfo { lineno, .. } => Some(lineno as u32), } } } extern 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, }, }); } } extern fn pcinfo_cb(data: *mut c_void, pc: uintptr_t, filename: *const c_char, lineno: c_int, function: *const c_char) -> c_int { unsafe { if filename.is_null() || function.is_null() { return -1 } call(data, &super::Symbol { inner: Symbol::Pcinfo { pc: pc, filename: filename, lineno: lineno, function: 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; } // The libbacktrace API supports creating a state, but it does not // support destroying a state. I personally take this to mean that a // state is meant to be created and then live forever. // // I would love to register an at_exit() handler which cleans up this // state, but libbacktrace provides no way to do so. // // With these constraints, this function has a statically cached state // 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. 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 } pub fn resolve(symaddr: *mut c_void, mut cb: &mut FnMut(&super::Symbol)) { let _guard = ::lock::lock(); // backtrace errors are currently swept under the rug unsafe { let state = init_state(); if state.is_null() { return } 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 _); } } } vendor/backtrace-0.3.6/src/symbolize/mod.rs0000664000000000000000000002302413264166600017372 0ustar rootrootuse std::fmt; #[cfg(not(feature = "cpp_demangle"))] use std::marker::PhantomData; use std::os::raw::c_void; use std::path::Path; use std::str; use rustc_demangle::{try_demangle, Demangle}; /// Resolve an address to a symbol, passing the symbol to the specified /// closure. /// /// This function will look up the given address in areas such as the local /// symbol table, dynamic symbol table, or DWARF debug info (depending on the /// activated implementation) to find symbols to yield. /// /// The closure may not be called if resolution could not be performed, and it /// also may be called more than once in the case of inlined functions. /// /// Symbols yielded represent the execution at the specified `addr`, returning /// file/line pairs for that address (if available). /// /// # Example /// /// ``` /// extern crate backtrace; /// /// fn main() { /// backtrace::trace(|frame| { /// let ip = frame.ip(); /// /// backtrace::resolve(ip, |symbol| { /// // ... /// }); /// /// false // only look at the top frame /// }); /// } /// ``` pub fn resolve(addr: *mut c_void, mut cb: F) { resolve_imp(addr, &mut cb) } /// A trait representing the resolution of a symbol in a file. /// /// This trait is yielded as a trait object to the closure given to the /// `backtrace::resolve` function, and it is virtually dispatched as it's /// unknown which implementation is behind it. /// /// A symbol can give contextual information about a function, for example the /// 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, } impl Symbol { /// Returns the name of this function. /// /// The returned structure can be used to query various properties about the /// symbol name: /// /// * The `Display` implementation will print out the demangled symbol. /// * The raw `str` value of the symbol can be accessed (if it's valid /// utf-8). /// * The raw bytes for the symbol name can be accessed. pub fn name(&self) -> Option { self.inner.name() } /// Returns the starting address of this function. pub fn addr(&self) -> Option<*mut c_void> { self.inner.addr() } /// Returns the file name where this function was defined. /// /// This is currently only available when libbacktrace is being used (e.g. /// unix platforms other than OSX) and when a binary is compiled with /// debuginfo. If neither of these conditions is met then this will likely /// return `None`. pub fn filename(&self) -> Option<&Path> { self.inner.filename() } /// Returns the line number for where this symbol is currently executing. /// /// This return value is typically `Some` if `filename` returns `Some`, and /// is consequently subject to similar caveats. pub fn lineno(&self) -> Option { self.inner.lineno() } } impl fmt::Debug for Symbol { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut d = f.debug_struct("Symbol"); if let Some(name) = self.name() { d.field("name", &name); } if let Some(addr) = self.addr() { d.field("addr", &addr); } if let Some(filename) = self.filename() { d.field("filename", &filename); } if let Some(lineno) = self.lineno() { d.field("lineno", &lineno); } d.finish() } } cfg_if! { if #[cfg(feature = "cpp_demangle")] { // Maybe a parsed C++ symbol, if parsing the mangled symbol as Rust // failed. struct OptionCppSymbol<'a>(Option<::cpp_demangle::BorrowedSymbol<'a>>); impl<'a> OptionCppSymbol<'a> { fn parse(input: &'a [u8]) -> OptionCppSymbol<'a> { OptionCppSymbol(::cpp_demangle::BorrowedSymbol::new(input).ok()) } fn none() -> OptionCppSymbol<'a> { OptionCppSymbol(None) } } } else { // Make sure to keep this zero-sized, so that the `cpp_demangle` feature // has no cost when disabled. struct OptionCppSymbol<'a>(PhantomData<&'a ()>); impl<'a> OptionCppSymbol<'a> { fn parse(_: &'a [u8]) -> OptionCppSymbol<'a> { OptionCppSymbol(PhantomData) } fn none() -> OptionCppSymbol<'a> { OptionCppSymbol(PhantomData) } } } } /// A wrapper around a symbol name to provide ergonomic accessors to the /// demangled name, the raw bytes, the raw string, etc. // Allow dead code for when the `cpp_demangle` feature is not enabled. #[allow(dead_code)] pub struct SymbolName<'a> { bytes: &'a [u8], demangled: Option>, cpp_demangled: OptionCppSymbol<'a>, } impl<'a> SymbolName<'a> { /// Creates a new symbol name from the raw underlying bytes. pub fn new(bytes: &'a [u8]) -> SymbolName<'a> { let str_bytes = str::from_utf8(bytes).ok(); let demangled = str_bytes.and_then(|s| try_demangle(s).ok()); let cpp = if demangled.is_none() { OptionCppSymbol::parse(bytes) } else { OptionCppSymbol::none() }; SymbolName { bytes: bytes, demangled: demangled, cpp_demangled: cpp, } } /// Returns the raw symbol name as a `str` if the symbols is valid utf-8. 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() }) } /// Returns the raw symbol name as a list of bytes pub fn as_bytes(&self) -> &'a [u8] { self.bytes } } cfg_if! { if #[cfg(feature = "cpp_demangle")] { impl<'a> fmt::Display for SymbolName<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if let Some(ref s) = self.demangled { s.fmt(f) } else if let Some(ref cpp) = self.cpp_demangled.0 { cpp.fmt(f) } else { String::from_utf8_lossy(self.bytes).fmt(f) } } } } else { impl<'a> fmt::Display for SymbolName<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if let Some(ref s) = self.demangled { s.fmt(f) } else { String::from_utf8_lossy(self.bytes).fmt(f) } } } } } cfg_if! { if #[cfg(feature = "cpp_demangle")] { impl<'a> fmt::Debug for SymbolName<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use std::fmt::Write; if let Some(ref s) = self.demangled { return s.fmt(f) } // This may to print if the demangled symbol isn't actually // valid, so handle the error here gracefully by not propagating // it outwards. if let Some(ref cpp) = self.cpp_demangled.0 { let mut s = String::new(); if write!(s, "{}", cpp).is_ok() { return s.fmt(f) } } String::from_utf8_lossy(self.bytes).fmt(f) } } } else { impl<'a> fmt::Debug for SymbolName<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if let Some(ref s) = self.demangled { s.fmt(f) } else { String::from_utf8_lossy(self.bytes).fmt(f) } } } } } cfg_if! { if #[cfg(all(windows, feature = "dbghelp"))] { mod dbghelp; use self::dbghelp::resolve as resolve_imp; use self::dbghelp::Symbol as SymbolImp; } else if #[cfg(all(feature = "gimli-symbolize", unix, target_os = "linux"))] { 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; // 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 } else if #[cfg(all(feature = "coresymbolication", any(target_os = "macos", all(target_os = "ios", debug_assertions))))] { mod coresymbolication; use self::coresymbolication::resolve as resolve_imp; use self::coresymbolication::Symbol as SymbolImp; } else if #[cfg(all(unix, not(target_os = "emscripten"), feature = "dladdr"))] { mod dladdr; use self::dladdr::resolve as resolve_imp; use self::dladdr::Symbol as SymbolImp; } else { mod noop; use self::noop::resolve as resolve_imp; use self::noop::Symbol as SymbolImp; } } vendor/backtrace-0.3.6/src/symbolize/noop.rs0000664000000000000000000000066413264166600017573 0ustar rootrootuse std::path::Path; use std::os::raw::c_void; use SymbolName; pub fn resolve(_addr: *mut c_void, _cb: &mut FnMut(&super::Symbol)) { } pub struct Symbol; impl Symbol { pub fn name(&self) -> Option { None } pub fn addr(&self) -> Option<*mut c_void> { None } pub fn filename(&self) -> Option<&Path> { None } pub fn lineno(&self) -> Option { None } } vendor/backtrace-0.3.6/tests/0000755000000000000000000000000013264166600014600 5ustar rootrootvendor/backtrace-0.3.6/tests/long_fn_name.rs0000664000000000000000000000351213264166600017573 0ustar rootrootextern crate backtrace; #[cfg(all(windows, feature = "dbghelp"))] extern crate winapi; use backtrace::Backtrace; // 50-character module name mod _234567890_234567890_234567890_234567890_234567890 { // 50-character struct name #[allow(non_camel_case_types)] pub struct _234567890_234567890_234567890_234567890_234567890(T); impl _234567890_234567890_234567890_234567890_234567890 { #[allow(dead_code)] pub fn new() -> ::Backtrace { ::Backtrace::new() } } } // Long function names must be truncated to (MAX_SYM_NAME - 1) characters. // Only run this test for msvc, since gnu prints "" for all frames. #[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; // 10 repetitions of struct name, so fully qualified function name is // atleast 10 * (50 + 50) * 2 = 2000 characters long. // It's actually longer since it also includes `::`, `<>` and the // name of the current module let bt = S::>>>>>>>>>::new(); println!("{:?}", bt); let mut found_long_name_frame = false; for frame in bt.frames() { let symbols = frame.symbols(); if symbols.is_empty() { continue; } 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") { found_long_name_frame = true; assert_eq!(function_name.len(), dbghelp::MAX_SYM_NAME - 1); } } } assert!(found_long_name_frame); } vendor/backtrace-0.3.6/tests/smoke.rs0000664000000000000000000001401413264166600016266 0ustar rootrootextern crate backtrace; use std::os::raw::c_void; 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 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")); #[test] fn smoke_test_frames() { frame_1(line!()); #[inline(never)] fn frame_1(start_line: u32) { frame_2(start_line) } #[inline(never)] fn frame_2(start_line: u32) { frame_3(start_line) } #[inline(never)] fn frame_3(start_line: u32) { frame_4(start_line) } #[inline(never)] fn frame_4(start_line: u32) { let mut v = Vec::new(); backtrace::trace(|cx| { v.push((cx.ip(), cx.symbol_address())); true }); if v.len() < 5 { assert!(!LIBUNWIND); assert!(!UNIX_BACKTRACE); assert!(!DBGHELP); 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); } 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 } let (ip, sym) = syms[idx - offset]; let ip = ip as usize; let sym = sym as usize; assert!(ip >= sym); assert!(sym >= actual_fn_pointer); // windows dbghelp is *quite* liberal (and wrong) in many of its reports // right now... if !DBGHELP { assert!(sym - actual_fn_pointer < 1024); } let mut resolved = 0; let can_resolve = DLADDR || LIBBACKTRACE || CORESYMBOLICATION || DBGHELP || GIMLI_SYMBOLIZE; let mut name = None; let mut addr = None; let mut line = None; let mut file = None; backtrace::resolve(ip as *mut c_void, |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()); }); // dbghelp doesn't always resolve symbols right now match resolved { 0 => return assert!(!can_resolve || DBGHELP), _ => {} } // * 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) { let name = name.expect("didn't find a name"); assert!(name.contains(expected_name), "didn't find `{}` in `{}`", expected_name, name); } if can_resolve { addr.expect("didn't find a symbol"); } if (LIBBACKTRACE || CORESYMBOLICATION || (DBGHELP && MSVC)) && cfg!(debug_assertions) { 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); } if expected_line != 0 { assert!(line == expected_line, "bad line number on frame for `{}`: {} != {}", expected_name, line, expected_line); } } } } #[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()); }); true }); } }) }).collect::>(); for t in threads { t.join().unwrap() } } #[test] #[cfg(feature = "rustc-serialize")] fn is_rustc_serialize() { extern crate rustc_serialize; fn is_encode() {} fn is_decode() {} is_encode::(); is_decode::(); } #[test] #[cfg(feature = "serde")] fn is_serde() { extern crate serde; fn is_serialize() {} fn is_deserialize() {} is_serialize::(); is_deserialize::(); } vendor/backtrace-sys-0.1.16/0000755000000000000000000000000013264166600014331 5ustar rootrootvendor/backtrace-sys-0.1.16/.cargo-checksum.json0000644000000000000000000000013113264166600020170 0ustar rootroot{"files":{},"package":"44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661"}vendor/backtrace-sys-0.1.16/Cargo.toml0000644000000000000000000000172613264166600016267 0ustar rootroot# 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.16" authors = ["Alex Crichton "] 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.libc] version = "0.2" [build-dependencies.cc] version = "1.0" vendor/backtrace-sys-0.1.16/build.rs0000664000000000000000000001254713264166600016011 0ustar rootrootextern crate cc; use std::env; use std::ffi::OsString; use std::fs; use std::io; use std::path::PathBuf; use std::process::Command; macro_rules! t { ($e:expr) => (match $e { Ok(e) => e, Err(e) => panic!("{} failed with {}", stringify!($e), e), }) } fn try_tool(compiler: &cc::Tool, cc: &str, compiler_suffix: &str, tool_suffix: &str) -> Option { if !cc.ends_with(compiler_suffix) { return None } let cc = cc.replace(compiler_suffix, tool_suffix); let candidate = compiler.path().parent().unwrap().join(cc); if Command::new(&candidate).output().is_ok() { Some(candidate) } else { None } } fn find_tool(compiler: &cc::Tool, cc: &str, tool: &str) -> PathBuf { // Allow overrides via env var if let Some(s) = env::var_os(tool.to_uppercase()) { return s.into() } let tool_suffix = format!("-{}", tool); try_tool(compiler, cc, "-gcc", &tool_suffix) .or_else(|| try_tool(compiler, cc, "-clang", &tool_suffix)) .or_else(|| try_tool(compiler, cc, "-cc", &tool_suffix)) .unwrap_or_else(|| PathBuf::from(tool)) } fn main() { let src = env::current_dir().unwrap(); let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap()); let target = env::var("TARGET").unwrap(); let host = env::var("HOST").unwrap(); // libbacktrace doesn't currently support Mach-O files if target.contains("darwin") { return } // libbacktrace isn't used on windows if target.contains("windows") { return } // no way this will ever compile for emscripten if target.contains("emscripten") { return } let mut make = "make"; // host BSDs has GNU-make as gmake if host.contains("bitrig") || host.contains("dragonfly") || host.contains("freebsd") || host.contains("netbsd") || host.contains("openbsd") { make = "gmake" } let configure = src.join("src/libbacktrace/configure").into_os_string(); // When cross-compiling on Windows, this path will contain backslashes, // but configure doesn't like that. Replace them with forward slashes. #[cfg(windows)] let configure = { use std::os::windows::ffi::{OsStrExt, OsStringExt}; let mut chars: Vec = configure.encode_wide().collect(); for c in chars.iter_mut() { if *c == '\\' as u16 { *c = '/' as u16; } } OsString::from_wide(&chars) }; let cfg = cc::Build::new(); let compiler = cfg.get_compiler(); let cc = compiler.path().file_name().unwrap().to_str().unwrap(); let mut flags = OsString::new(); for (i, flag) in compiler.args().iter().enumerate() { if i > 0 { flags.push(" "); } flags.push(flag); } let ar = find_tool(&compiler, cc, "ar"); let ranlib = find_tool(&compiler, cc, "ranlib"); let mut cmd = Command::new("sh"); cmd.arg(configure) .current_dir(&dst) .env("AR", &ar) .env("RANLIB", &ranlib) .env("CC", compiler.path()) .env("CFLAGS", flags) .arg("--with-pic") .arg("--disable-multilib") .arg("--disable-shared") .arg("--disable-host-shared") .arg(format!("--host={}", target)); // Apparently passing this flag causes problems on Windows if !host.contains("windows") { cmd.arg(format!("--build={}", host)); } run(&mut cmd, "sh"); let mut cmd = Command::new(make); if let Some(makeflags) = env::var_os("CARGO_MAKEFLAGS") { cmd.env("MAKEFLAGS", makeflags); } run(cmd.current_dir(&dst) .arg(format!("INCDIR={}", src.join("src/libbacktrace").display())), "make"); println!("cargo:rustc-link-search=native={}/.libs", dst.display()); println!("cargo:rustc-link-lib=static=backtrace"); // The standard library currently bundles in libbacktrace, but it's // compiled with hidden visibility (naturally) so we can't use it. // // To prevent conflicts with a second statically linked copy we rename all // symbols with a '__rbt_' prefix manually here through `objcopy`. let lib = dst.join(".libs/libbacktrace.a"); let tmpdir = dst.join("__tmp"); drop(fs::remove_dir_all(&tmpdir)); t!(fs::create_dir_all(&tmpdir)); run(Command::new(&ar).arg("x").arg(&lib).current_dir(&tmpdir), ar.to_str().unwrap()); t!(fs::remove_file(&lib)); let mut objs = Vec::new(); let objcopy = find_tool(&compiler, cc, "objcopy"); for obj in t!(tmpdir.read_dir()) { let obj = t!(obj); run(Command::new(&objcopy) .arg("--redefine-syms=symbol-map") .arg(obj.path()), objcopy.to_str().unwrap()); objs.push(obj.path()); } run(Command::new(&ar).arg("crus").arg(&lib).args(&objs), ar.to_str().unwrap()); } fn run(cmd: &mut Command, program: &str) { println!("running: {:?}", cmd); let status = match cmd.status() { Ok(s) => s, Err(ref e) if e.kind() == io::ErrorKind::NotFound => { panic!("\n\nfailed to execute command: {}\nIs `{}` \ not installed?\n\n", e, program); } Err(e) => panic!("failed to get status: {}", e), }; if !status.success() { panic!("failed with: {}", status); } } vendor/backtrace-sys-0.1.16/src/0000755000000000000000000000000013264166600015120 5ustar rootrootvendor/backtrace-sys-0.1.16/src/lib.rs0000664000000000000000000000317013264166600016237 0ustar rootroot#![allow(bad_style)] extern crate libc; use libc::uintptr_t; use std::os::raw::{c_void, c_char, c_int}; pub type backtrace_syminfo_callback = extern fn(data: *mut c_void, pc: uintptr_t, symname: *const c_char, symval: uintptr_t, symsize: uintptr_t); pub type backtrace_full_callback = extern 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 fn(data: *mut c_void, msg: *const c_char, errnum: c_int); pub enum backtrace_state {} extern { #[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; #[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; #[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; } vendor/backtrace-sys-0.1.16/src/libbacktrace/0000755000000000000000000000000013264166600017526 5ustar rootrootvendor/backtrace-sys-0.1.16/src/libbacktrace/ChangeLog0000664000000000000000000004364613264166600021317 0ustar rootroot2016-11-15 Matthias Klose * configure: Regenerate. 2016-09-11 Carlos Liam * all: Remove meaningless trailing whitespace. 2016-05-18 Uros Bizjak PR target/71161 * elf.c (phdr_callback) [__i386__]: Add __attribute__((__force_align_arg_pointer__)). 2016-03-02 Maxim Ostapenko * elf.c (backtrace_initialize): Properly initialize elf_fileline_fn to avoid possible crash. (elf_add): Don't set *fileline_fn to elf_nodebug value in case of missing debug info anymore. 2016-02-06 John David Anglin * mmap.c (MAP_FAILED): Define if not defined. 2016-01-04 Jakub Jelinek Update copyright years. 2015-12-18 Andris Pavenis * configure.ac: Specify that DJGPP do not have mmap even when sys/mman.h exists. * configure: Regenerate 2015-12-09 John David Anglin PR libgfortran/68115 * configure.ac: Set libbacktrace_cv_sys_sync to no on hppa*-*-hpux*. * configure: Regenerate. * elf.c (backtrace_initialize): Cast __sync_bool_compare_and_swap call to void. 2015-09-17 Ian Lance Taylor * posix.c (backtrace_open): Cast second argument of open() to int. 2015-09-11 Ian Lance Taylor * Makefile.am (backtrace.lo): Depend on internal.h. (sort.lo, stest.lo): Add explicit dependencies. * Makefile.in: Rebuild. 2015-09-09 Hans-Peter Nilsson * backtrace.c: #include . 2015-09-08 Ian Lance Taylor PR other/67457 * backtrace.c: #include "internal.h". (struct backtrace_data): Add can_alloc field. (unwind): If can_alloc is false, don't try to get file/line information. (backtrace_full): Set can_alloc field in bdata. * alloc.c (backtrace_alloc): Don't call error_callback if it is NULL. * mmap.c (backtrace_alloc): Likewise. * internal.h: Update comments for backtrace_alloc and backtrace_free. 2015-09-08 Ian Lance Taylor PR other/67457 * mmap.c (backtrace_alloc): Correct test for mmap failure. 2015-08-31 Ulrich Weigand * configure.ac: For spu-*-* targets, set have_fcntl to no. * configure: Regenerate. 2015-08-27 Ulrich Weigand * configure.ac: Remove [disable-shared] argument to LT_INIT. Remove setting PIC_FLAG when building as target library. * configure: Regenerate. 2015-08-26 Hans-Peter Nilsson * configure.ac: Only compile with -fPIC if the target supports it. * configure: Regenerate. 2015-08-24 Ulrich Weigand * configure.ac: Set have_mmap to no on spu-*-* targets. * configure: Regenerate. 2015-08-13 Ian Lance Taylor * dwarf.c (read_function_entry): Add vec_inlined parameter. Change all callers. 2015-06-11 Martin Sebor PR sanitizer/65479 * dwarf.c (struct line): Add new field idx. (line_compare): Use it. (add_line): Set it. (read_line_info): Reset it. 2015-05-29 Tristan Gingold * pecoff.c: New file. * Makefile.am (FORMAT_FILES): Add pecoff.c and dependencies. * Makefile.in: Regenerate. * filetype.awk: Detect pecoff. * configure.ac: Define BACKTRACE_SUPPORTS_DATA on elf platforms. Add pecoff. * btest.c (test5): Test enabled only if BACKTRACE_SUPPORTS_DATA is true. * backtrace-supported.h.in (BACKTRACE_SUPPORTS_DATA): Define. * configure: Regenerate. * pecoff.c: New file. 2015-05-13 Michael Haubenwallner * Makefile.in: Regenerated with automake-1.11.6. * aclocal.m4: Likewise. * configure: Likewise. 2015-01-24 Matthias Klose * configure.ac: Move AM_ENABLE_MULTILIB before AC_PROG_CC. * configure: Regenerate. 2015-01-05 Jakub Jelinek Update copyright years. 2014-11-21 H.J. Lu PR bootstrap/63784 * configure: Regenerated. 2014-11-11 David Malcolm * ChangeLog.jit: New. 2014-11-11 Francois-Xavier Coudert PR target/63610 * configure: Regenerate. 2014-10-23 Ian Lance Taylor * internal.h (backtrace_atomic_load_pointer) [no atomic or sync]: Fix to return void *. 2014-05-08 Ian Lance Taylor * mmap.c (backtrace_free): If freeing a large aligned block of memory, call munmap rather than holding onto it. (backtrace_vector_grow): When growing a vector, double the number of pages requested. When releasing the old version of a grown vector, pass the correct size to backtrace_free. 2014-03-07 Ian Lance Taylor * sort.c (backtrace_qsort): Use middle element as pivot. 2014-03-06 Ian Lance Taylor * sort.c: New file. * stest.c: New file. * internal.h (backtrace_qsort): Declare. * dwarf.c (read_abbrevs): Call backtrace_qsort instead of qsort. (read_line_info, read_function_entry): Likewise. (read_function_info, build_dwarf_data): Likewise. * elf.c (elf_initialize_syminfo): Likewise. * Makefile.am (libbacktrace_la_SOURCES): Add sort.c. (stest_SOURCES, stest_LDADD): Define. (check_PROGRAMS): Add stest. 2014-02-07 Misty De Meo PR target/58710 * configure.ac: Use AC_LINK_IFELSE in check for _Unwind_GetIPInfo. * configure: Regenerate. 2014-01-02 Richard Sandiford Update copyright years 2013-12-06 Jakub Jelinek * elf.c (ET_DYN): Undefine and define again. (elf_add): Add exe argument, if true and ehdr.e_type is ET_DYN, return early -1 without closing the descriptor. (struct phdr_data): Add exe_descriptor. (phdr_callback): If pd->exe_descriptor is not -1, for very first call if dlpi_name is NULL just call elf_add with the exe_descriptor, otherwise backtrace_close the exe_descriptor if not -1. Adjust call to elf_add. (backtrace_initialize): Adjust call to elf_add. If it returns -1, set pd.exe_descriptor to descriptor, otherwise set it to -1. 2013-12-05 Ian Lance Taylor * alloc.c (backtrace_vector_finish): Add error_callback and data parameters. Call backtrace_vector_release. Return address base. * mmap.c (backtrace_vector_finish): Add error_callback and data parameters. Return address base. * dwarf.c (read_function_info): Get new address base from backtrace_vector_finish. * internal.h (backtrace_vector_finish): Update declaration. 2013-11-27 Ian Lance Taylor * dwarf.c (find_address_ranges): New static function, broken out of build_address_map. (build_address_map): Call it. * btest.c (check): Check for missing filename or function, rather than crashing. (f3): Check that enough frames were returned. 2013-11-19 Jakub Jelinek * backtrace.h (backtrace_syminfo_callback): Add symsize argument. * elf.c (elf_syminfo): Pass 0 or sym->size to the callback as last argument. * btest.c (struct symdata): Add size field. (callback_three): Add symsize argument. Copy it to the data->size field. (f23): Set symdata.size to 0. (test5): Likewise. If sizeof (int) > 1, lookup address of ((uintptr_t) &global) + 1. Verify symdata.val and symdata.size values. * atomic.c: Include sys/types.h. 2013-11-18 Ian Lance Taylor * configure.ac: Check for support of __atomic extensions. * internal.h: Declare or #define atomic functions for use in backtrace code. * atomic.c: New file. * dwarf.c (dwarf_lookup_pc): Use atomic functions. (dwarf_fileline, backtrace_dwarf_add): Likewise. * elf.c (elf_add_syminfo_data, elf_syminfo): Likewise. (backtrace_initialize): Likewise. * fileline.c (fileline_initialize): Likewise. * Makefile.am (libbacktrace_la_SOURCES): Add atomic.c. * configure, config.h.in, Makefile.in: Rebuild. 2013-11-18 Jakub Jelinek * elf.c (SHN_UNDEF): Define. (elf_initialize_syminfo): Add base_address argument. Ignore symbols with st_shndx == SHN_UNDEF. Add base_address to address fields. (elf_add): Adjust caller. * elf.c (phdr_callback): Process info->dlpi_addr == 0 normally. 2013-11-16 Ian Lance Taylor * backtrace.h (backtrace_create_state): Correct comment about threading. 2013-11-15 Ian Lance Taylor * backtrace.h (backtrace_syminfo): Update comment and parameter name to take any address, not just a PC value. * elf.c (STT_OBJECT): Define. (elf_nosyms): Rename parameter pc to addr. (elf_symbol_search): Rename local variable pc to addr. (elf_initialize_syminfo): Add STT_OBJECT symbols to elf_symbols. (elf_syminfo): Rename parameter pc to addr. * btest.c (global): New global variable. (test5): New test. (main): Call test5. 2013-10-17 Ian Lance Taylor * elf.c (elf_add): Don't get the wrong offsets if a debug section is missing. 2013-10-15 David Malcolm * configure.ac: Add --enable-host-shared, setting up pre-existing PIC_FLAG variable within Makefile.am et al. * configure: Regenerate. 2013-09-20 Alan Modra * configure: Regenerate. 2013-07-23 Alexander Monakov * elf.c (elf_syminfo): Loop over the elf_syminfo_data chain. 2013-07-23 Alexander Monakov * elf.c (backtrace_initialize): Pass elf_fileline_fn to dl_iterate_phdr callbacks. 2013-03-25 Ian Lance Taylor * alloc.c: #include . * mmap.c: Likewise. 2013-01-31 Ian Lance Taylor * dwarf.c (read_function_info): Permit fvec parameter to be NULL. (dwarf_lookup_pc): Don't use ddata->fvec if threaded. 2013-01-25 Jakub Jelinek PR other/56076 * dwarf.c (read_line_header): Don't crash if DW_AT_comp_dir attribute was not seen. 2013-01-16 Ian Lance Taylor * dwarf.c (struct unit): Add filename and abs_filename fields. (build_address_map): Set new fields when reading unit. (dwarf_lookup_pc): If we don't find an entry in the line table, just return the main file name. 2013-01-14 Richard Sandiford Update copyright years. 2013-01-01 Ian Lance Taylor PR bootstrap/54834 * Makefile.am (AM_CPPFLAGS): Remove -I ../gcc/include and -I $(MULTIBUILDTOP)/../../gcc/include. * Makefile.in: Rebuild. 2013-01-01 Ian Lance Taylor PR other/55536 * mmap.c (backtrace_alloc): Don't call sync functions if not threaded. (backtrace_free): Likewise. 2012-12-12 John David Anglin * mmapio.c: Define MAP_FAILED if not defined. 2012-12-11 Jakub Jelinek PR bootstrap/54926 * Makefile.am (AM_CFLAGS): Remove -frandom-seed=$@. * configure.ac: If --with-target-subdir, add -frandom-seed=$@ to EXTRA_FLAGS unconditionally, otherwise check whether the compiler accepts it. * Makefile.in: Regenerated. * configure: Regenerated. 2012-12-07 Jakub Jelinek PR bootstrap/54926 * Makefile.am (AM_CFLAGS): Add -frandom-seed=$@. * Makefile.in: Regenerated. 2012-11-20 Ian Lance Taylor * dwarf.c (read_attribute): Always clear val. 2012-11-13 Ian Lance Taylor PR other/55312 * configure.ac: Only add -Werror if building a target library. * configure: Rebuild. 2012-11-12 Ian Lance Taylor Rainer Orth Gerald Pfeifer * configure.ac: Check for getexecname. * fileline.c: #include . Define getexecname if not available. (fileline_initialize): Try to find the executable in a few different ways. * print.c (error_callback): Only print the filename if it came from the backtrace state. * configure, config.h.in: Rebuild. 2012-10-29 Ian Lance Taylor * mmap.c (backtrace_vector_release): Correct last patch: add aligned, not size. 2012-10-29 Ian Lance Taylor * mmap.c (backtrace_vector_release): Make sure freed block is aligned on 8-byte boundary. 2012-10-26 Ian Lance Taylor PR other/55087 * posix.c (backtrace_open): Add does_not_exist parameter. * elf.c (phdr_callback): Do not warn if shared library could not be opened. * fileline.c (fileline_initialize): Update calls to backtrace_open. * internal.h (backtrace_open): Update declaration. 2012-10-26 Jack Howarth PR target/55061 * configure.ac: Check for _Unwind_GetIPInfo function declaration. * configure: Regenerate. 2012-10-24 Ian Lance Taylor PR target/55061 * configure.ac: Check whether -funwind-tables option works. * configure: Rebuild. 2012-10-11 Ian Lance Taylor * configure.ac: Do not use dl_iterate_phdr on Solaris 10. * configure: Rebuild. 2012-10-10 Ian Lance Taylor * elf.c: Rename all Elf typedefs to start with b_elf, and be all lower case. 2012-10-10 Hans-Peter Nilsson * elf.c (elf_add_syminfo_data): Add casts to avoid warning. 2012-10-09 Ian Lance Taylor * dwarf.c (dwarf_fileline): Add cast to avoid warning. (backtrace_dwarf_add): Likewise. 2012-10-09 Ian Lance Taylor Add support for tracing through shared libraries. * configure.ac: Check for link.h and dl_iterate_phdr. * elf.c: #include if system has dl_iterate_phdr. #undef ELF macros before #defining them. (dl_phdr_info, dl_iterate_phdr): Define if system does not have dl_iterate_phdr. (struct elf_syminfo_data): Add next field. (elf_initialize_syminfo): Initialize next field. (elf_add_syminfo_data): New static function. (elf_add): New static function, broken out of backtrace_initialize. Call backtrace_dwarf_add instead of backtrace_dwarf_initialize. (struct phdr_data): Define. (phdr_callback): New static function. (backtrace_initialize): Call elf_add. * dwarf.c (struct dwarf_data): Add next and base_address fields. (add_unit_addr): Add base_address parameter. Change all callers. (add_unit_ranges, build_address_map): Likewise. (add_line): Add ddata parameter. Change all callers. (read_line_program, add_function_range): Likewise. (dwarf_lookup_pc): New static function, broken out of dwarf_fileline. (dwarf_fileline): Call dwarf_lookup_pc. (build_dwarf_data): New static function. (backtrace_dwarf_add): New function. (backtrace_dwarf_initialize): Remove. * internal.h (backtrace_dwarf_initialize): Don't declare. (backtrace_dwarf_add): Declare. * configure, config.h.in: Rebuild. 2012-10-04 Gerald Pfeifer * btest.c (f23): Avoid uninitialized variable warning. 2012-10-04 Ian Lance Taylor * dwarf.c: If the system header files do not declare strnlen, provide our own version. 2012-10-03 Ian Lance Taylor * dwarf.c (read_uleb128): Fix overflow test. (read_sleb128): Likewise. (build_address_map): Don't change unit_buf.start. 2012-10-02 Uros Bizjak PR other/54761 * configure.ac (EXTRA_FLAGS): New. * Makefile.am (AM_FLAGS): Add $(EXTRA_FLAGS). * configure, Makefile.in: Regenerate. 2012-09-29 Ian Lance Taylor PR other/54749 * fileline.c (fileline_initialize): Pass errnum as -1 when reporting that we could not read executable information after a previous failure. 2012-09-27 Ian Lance Taylor PR bootstrap/54732 * configure.ac: Add no-dependencies to AM_INIT_AUTOMAKE. * Makefile.am: Add dependencies for all objects. * configure, aclocal.m4, Makefile.in: Rebuild. 2012-09-27 Ian Lance Taylor PR other/54726 * elf.c (backtrace_initialize): Set *fileln_fn, not state->fileln_fn. 2012-09-19 Ian Lance Taylor * configure.ac: Only use GCC_CHECK_UNWIND_GETIPINFO when compiled as a target library. * configure: Rebuild. 2012-09-19 Rainer Orth Ian Lance Taylor * configure.ac (GCC_HEADER_STDINT): Invoke. * backtrace.h: If we can't find , use "gstdint.h". * btest.c: Don't include . * dwarf.c: Likewise. * configure, aclocal.m4, Makefile.in, config.h.in: Rebuild. 2012-09-18 Ian Lance Taylor PR bootstrap/54623 * Makefile.am (AM_CPPFLAGS): Define. (AM_CFLAGS): Remove -I options. * Makefile.in: Rebuild. 2012-09-18 Ian Lance Taylor * posix.c (O_BINARY): Define if not defined. (backtrace_open): Pass O_BINARY to open. Only call fcntl if HAVE_FCNTL is defined. * configure.ac: Test for the fcntl function. * configure, config.h.in: Rebuild. 2012-09-18 Ian Lance Taylor * btest.c (test1, test2, test3, test4): Add the unused attribute. 2012-09-18 Ian Lance Taylor * dwarf.c: Correct test of HAVE_DECL_STRNLEN. 2012-09-18 Ian Lance Taylor * configure.ac: Add AC_USE_SYSTEM_EXTENSIONS. * mmapio.c: Don't define _GNU_SOURCE. * configure, config.h.in: Rebuild. 2012-09-18 Ian Lance Taylor * configure.ac: Check whether strnlen is declared. * dwarf.c: Declare strnlen if not declared. * configure, config.h.in: Rebuild. 2012-09-18 Rainer Orth * fileline.c: Include . * mmap.c: Likewise. 2012-09-17 Ian Lance Taylor PR bootstrap/54611 * nounwind.c (backtrace_full): Rename from backtrace. Add state parameter. 2012-09-17 Gerald Pfeifer PR bootstrap/54611 * nounwind.c (backtrace_simple): Add state parameter. 2012-09-17 Ian Lance Taylor PR bootstrap/54609 * unknown.c (unknown_fileline): Add state parameter, remove fileline_data parameter, name error_callback parameter. (backtrace_initialize): Add state parameter. 2012-09-17 Ian Lance Taylor * Initial implementation. Copyright (C) 2012-2016 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. vendor/backtrace-sys-0.1.16/src/libbacktrace/ChangeLog.jit0000664000000000000000000000067213264166600022074 0ustar rootroot2014-09-24 David Malcolm * ChangeLog.jit: Add copyright footer. 2013-10-03 David Malcolm * configure.ac: Add --enable-host-shared. * configure: Regenerate. Copyright (C) 2013-2014 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. vendor/backtrace-sys-0.1.16/src/libbacktrace/Makefile.am0000664000000000000000000001011013264166600021555 0ustar rootroot# Makefile.am -- Backtrace Makefile. # 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. ACLOCAL_AMFLAGS = -I .. -I ../config AM_CPPFLAGS = -I $(top_srcdir)/../include -I $(top_srcdir)/../libgcc \ -I ../libgcc AM_CFLAGS = $(EXTRA_FLAGS) $(WARN_FLAGS) $(PIC_FLAG) noinst_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 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 = TESTS = $(check_PROGRAMS) if NATIVE btest_SOURCES = btest.c btest_CFLAGS = $(AM_CFLAGS) -g -O btest_LDADD = libbacktrace.la check_PROGRAMS += btest stest_SOURCES = stest.c stest_LDADD = libbacktrace.la check_PROGRAMS += stest 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. INCDIR = $(top_srcdir)/../include alloc.lo: config.h backtrace.h internal.h backtrace.lo: config.h backtrace.h internal.h btest.lo: (INCDIR)/filenames.h backtrace.h backtrace-supported.h dwarf.lo: config.h $(INCDIR)/dwarf2.h $(INCDIR)/dwarf2.def \ $(INCDIR)/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 vendor/backtrace-sys-0.1.16/src/libbacktrace/Makefile.in0000664000000000000000000005700213264166600021601 0ustar rootroot# 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-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. 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) @NATIVE_TRUE@am__append_1 = btest stest subdir = . DIST_COMMON = README ChangeLog $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/configure \ $(am__configure_deps) $(srcdir)/config.h.in \ $(srcdir)/../mkinstalldirs $(srcdir)/backtrace-supported.h.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/../config/lead-dot.m4 \ $(top_srcdir)/../config/multi.m4 \ $(top_srcdir)/../config/override.m4 \ $(top_srcdir)/../config/stdint.m4 \ $(top_srcdir)/../config/unwind_ipinfo.m4 \ $(top_srcdir)/../config/warnings.m4 \ $(top_srcdir)/../libtool.m4 $(top_srcdir)/../ltoptions.m4 \ $(top_srcdir)/../ltsugar.m4 $(top_srcdir)/../ltversion.m4 \ $(top_srcdir)/../lt~obsolete.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 = $(SHELL) $(top_srcdir)/../mkinstalldirs CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = backtrace-supported.h CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_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) stest$(EXEEXT) @NATIVE_TRUE@am_btest_OBJECTS = btest-btest.$(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_stest_OBJECTS = stest.$(OBJEXT) stest_OBJECTS = $(am_stest_OBJECTS) @NATIVE_TRUE@stest_DEPENDENCIES = libbacktrace.la 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) $(stest_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 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@ 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@ OBJDUMP = @OBJDUMP@ 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@ 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@ 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 .. -I ../config AM_CPPFLAGS = -I $(top_srcdir)/../include -I $(top_srcdir)/../libgcc \ -I ../libgcc AM_CFLAGS = $(EXTRA_FLAGS) $(WARN_FLAGS) $(PIC_FLAG) noinst_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 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) TESTS = $(check_PROGRAMS) @NATIVE_TRUE@btest_SOURCES = btest.c @NATIVE_TRUE@btest_CFLAGS = $(AM_CFLAGS) -g -O @NATIVE_TRUE@btest_LDADD = libbacktrace.la @NATIVE_TRUE@stest_SOURCES = stest.c @NATIVE_TRUE@stest_LDADD = libbacktrace.la # 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. INCDIR = $(top_srcdir)/../include 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 $@ clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_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) $(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) stest$(EXEEXT): $(stest_OBJECTS) $(stest_DEPENDENCIES) $(EXTRA_stest_DEPENDENCIES) @rm -f stest$(EXEEXT) $(LINK) $(stest_OBJECTS) $(stest_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` 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) 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 config.h installdirs: 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: 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-libtool \ clean-noinstLTLIBRARIES 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-dvi: install-dvi-am install-dvi-am: install-exec-am: 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: .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-libtool \ clean-multi clean-noinstLTLIBRARIES 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-info \ install-info-am 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 alloc.lo: config.h backtrace.h internal.h backtrace.lo: config.h backtrace.h internal.h btest.lo: (INCDIR)/filenames.h backtrace.h backtrace-supported.h dwarf.lo: config.h $(INCDIR)/dwarf2.h $(INCDIR)/dwarf2.def \ $(INCDIR)/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 # 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: vendor/backtrace-sys-0.1.16/src/libbacktrace/README0000664000000000000000000000173113264166600020412 0ustar rootrootThe libbacktrace library Initially written by Ian Lance Taylor 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 September 2012, libbacktrace only supports ELF executables with DWARF debugging information. The library is written to make it straightforward to add support for other object file and debugging formats. vendor/backtrace-sys-0.1.16/src/libbacktrace/aclocal.m40000664000000000000000000006035613264166600021402 0ustar rootroot# 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)]) # 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 ]) # 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 /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/lead-dot.m4]) m4_include([../config/multi.m4]) m4_include([../config/override.m4]) m4_include([../config/stdint.m4]) m4_include([../config/unwind_ipinfo.m4]) m4_include([../config/warnings.m4]) m4_include([../libtool.m4]) m4_include([../ltoptions.m4]) m4_include([../ltsugar.m4]) m4_include([../ltversion.m4]) m4_include([../lt~obsolete.m4]) vendor/backtrace-sys-0.1.16/src/libbacktrace/alloc.c0000664000000000000000000001022313264166600020764 0ustar rootroot/* alloc.c -- Memory allocation without mmap. 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. */ #include "config.h" #include #include #include #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; } vendor/backtrace-sys-0.1.16/src/libbacktrace/ansidecl.h0000664000000000000000000002720513264166600021471 0ustar rootroot/* ANSI and traditional C compatability macros Copyright (C) 1991-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. 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 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, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ /* ANSI and traditional C compatibility macros ANSI C is assumed if __STDC__ is #defined. Macro ANSI C definition Traditional C definition ----- ---- - ---------- ----------- - ---------- PTR `void *' `char *' const not defined `' volatile not defined `' signed not defined `' For ease of writing code which uses GCC extensions but needs to be portable to other compilers, we provide the GCC_VERSION macro that simplifies testing __GNUC__ and __GNUC_MINOR__ together, and various wrappers around __attribute__. Also, __extension__ will be #defined to nothing if it doesn't work. See below. */ #ifndef _ANSIDECL_H #define _ANSIDECL_H 1 #ifdef __cplusplus extern "C" { #endif /* Every source file includes this file, so they will all get the switch for lint. */ /* LINTLIBRARY */ /* Using MACRO(x,y) in cpp #if conditionals does not work with some older preprocessors. Thus we can't define something like this: #define HAVE_GCC_VERSION(MAJOR, MINOR) \ (__GNUC__ > (MAJOR) || (__GNUC__ == (MAJOR) && __GNUC_MINOR__ >= (MINOR))) and then test "#if HAVE_GCC_VERSION(2,7)". So instead we use the macro below and test it against specific values. */ /* This macro simplifies testing whether we are using gcc, and if it is of a particular minimum version. (Both major & minor numbers are significant.) This macro will evaluate to 0 if we are not using gcc at all. */ #ifndef GCC_VERSION #define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__) #endif /* GCC_VERSION */ #if defined (__STDC__) || defined(__cplusplus) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(_WIN32) /* All known AIX compilers implement these things (but don't always define __STDC__). The RISC/OS MIPS compiler defines these things in SVR4 mode, but does not define __STDC__. */ /* eraxxon@alumni.rice.edu: The Compaq C++ compiler, unlike many other C++ compilers, does not define __STDC__, though it acts as if this was so. (Verified versions: 5.7, 6.2, 6.3, 6.5) */ #define PTR void * #undef const #undef volatile #undef signed /* inline requires special treatment; it's in C99, and GCC >=2.7 supports it too, but it's not in C89. */ #undef inline #if __STDC_VERSION__ >= 199901L || defined(__cplusplus) || (defined(__SUNPRO_C) && defined(__C99FEATURES__)) /* it's a keyword */ #else # if GCC_VERSION >= 2007 # define inline __inline__ /* __inline__ prevents -pedantic warnings */ # else # define inline /* nothing */ # endif #endif #else /* Not ANSI C. */ #define PTR char * /* some systems define these in header files for non-ansi mode */ #undef const #undef volatile #undef signed #undef inline #define const #define volatile #define signed #define inline #endif /* ANSI C. */ /* Define macros for some gcc attributes. This permits us to use the macros freely, and know that they will come into play for the version of gcc in which they are supported. */ #if (GCC_VERSION < 2007) # define __attribute__(x) #endif /* Attribute __malloc__ on functions was valid as of gcc 2.96. */ #ifndef ATTRIBUTE_MALLOC # if (GCC_VERSION >= 2096) # define ATTRIBUTE_MALLOC __attribute__ ((__malloc__)) # else # define ATTRIBUTE_MALLOC # endif /* GNUC >= 2.96 */ #endif /* ATTRIBUTE_MALLOC */ /* Attributes on labels were valid as of gcc 2.93 and g++ 4.5. For g++ an attribute on a label must be followed by a semicolon. */ #ifndef ATTRIBUTE_UNUSED_LABEL # ifndef __cplusplus # if GCC_VERSION >= 2093 # define ATTRIBUTE_UNUSED_LABEL ATTRIBUTE_UNUSED # else # define ATTRIBUTE_UNUSED_LABEL # endif # else # if GCC_VERSION >= 4005 # define ATTRIBUTE_UNUSED_LABEL ATTRIBUTE_UNUSED ; # else # define ATTRIBUTE_UNUSED_LABEL # endif # endif #endif /* Similarly to ARG_UNUSED below. Prior to GCC 3.4, the C++ frontend couldn't parse attributes placed after the identifier name, and now the entire compiler is built with C++. */ #ifndef ATTRIBUTE_UNUSED #if GCC_VERSION >= 3004 # define ATTRIBUTE_UNUSED __attribute__ ((__unused__)) #else #define ATTRIBUTE_UNUSED #endif #endif /* ATTRIBUTE_UNUSED */ /* Before GCC 3.4, the C++ frontend couldn't parse attributes placed after the identifier name. */ #if ! defined(__cplusplus) || (GCC_VERSION >= 3004) # define ARG_UNUSED(NAME) NAME ATTRIBUTE_UNUSED #else /* !__cplusplus || GNUC >= 3.4 */ # define ARG_UNUSED(NAME) NAME #endif /* !__cplusplus || GNUC >= 3.4 */ #ifndef ATTRIBUTE_NORETURN #define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__)) #endif /* ATTRIBUTE_NORETURN */ /* Attribute `nonnull' was valid as of gcc 3.3. */ #ifndef ATTRIBUTE_NONNULL # if (GCC_VERSION >= 3003) # define ATTRIBUTE_NONNULL(m) __attribute__ ((__nonnull__ (m))) # else # define ATTRIBUTE_NONNULL(m) # endif /* GNUC >= 3.3 */ #endif /* ATTRIBUTE_NONNULL */ /* Attribute `returns_nonnull' was valid as of gcc 4.9. */ #ifndef ATTRIBUTE_RETURNS_NONNULL # if (GCC_VERSION >= 4009) # define ATTRIBUTE_RETURNS_NONNULL __attribute__ ((__returns_nonnull__)) # else # define ATTRIBUTE_RETURNS_NONNULL # endif /* GNUC >= 4.9 */ #endif /* ATTRIBUTE_RETURNS_NONNULL */ /* Attribute `pure' was valid as of gcc 3.0. */ #ifndef ATTRIBUTE_PURE # if (GCC_VERSION >= 3000) # define ATTRIBUTE_PURE __attribute__ ((__pure__)) # else # define ATTRIBUTE_PURE # endif /* GNUC >= 3.0 */ #endif /* ATTRIBUTE_PURE */ /* Use ATTRIBUTE_PRINTF when the format specifier must not be NULL. This was the case for the `printf' format attribute by itself before GCC 3.3, but as of 3.3 we need to add the `nonnull' attribute to retain this behavior. */ #ifndef ATTRIBUTE_PRINTF #define ATTRIBUTE_PRINTF(m, n) __attribute__ ((__format__ (__printf__, m, n))) ATTRIBUTE_NONNULL(m) #define ATTRIBUTE_PRINTF_1 ATTRIBUTE_PRINTF(1, 2) #define ATTRIBUTE_PRINTF_2 ATTRIBUTE_PRINTF(2, 3) #define ATTRIBUTE_PRINTF_3 ATTRIBUTE_PRINTF(3, 4) #define ATTRIBUTE_PRINTF_4 ATTRIBUTE_PRINTF(4, 5) #define ATTRIBUTE_PRINTF_5 ATTRIBUTE_PRINTF(5, 6) #endif /* ATTRIBUTE_PRINTF */ /* Use ATTRIBUTE_FPTR_PRINTF when the format attribute is to be set on a function pointer. Format attributes were allowed on function pointers as of gcc 3.1. */ #ifndef ATTRIBUTE_FPTR_PRINTF # if (GCC_VERSION >= 3001) # define ATTRIBUTE_FPTR_PRINTF(m, n) ATTRIBUTE_PRINTF(m, n) # else # define ATTRIBUTE_FPTR_PRINTF(m, n) # endif /* GNUC >= 3.1 */ # define ATTRIBUTE_FPTR_PRINTF_1 ATTRIBUTE_FPTR_PRINTF(1, 2) # define ATTRIBUTE_FPTR_PRINTF_2 ATTRIBUTE_FPTR_PRINTF(2, 3) # define ATTRIBUTE_FPTR_PRINTF_3 ATTRIBUTE_FPTR_PRINTF(3, 4) # define ATTRIBUTE_FPTR_PRINTF_4 ATTRIBUTE_FPTR_PRINTF(4, 5) # define ATTRIBUTE_FPTR_PRINTF_5 ATTRIBUTE_FPTR_PRINTF(5, 6) #endif /* ATTRIBUTE_FPTR_PRINTF */ /* Use ATTRIBUTE_NULL_PRINTF when the format specifier may be NULL. A NULL format specifier was allowed as of gcc 3.3. */ #ifndef ATTRIBUTE_NULL_PRINTF # if (GCC_VERSION >= 3003) # define ATTRIBUTE_NULL_PRINTF(m, n) __attribute__ ((__format__ (__printf__, m, n))) # else # define ATTRIBUTE_NULL_PRINTF(m, n) # endif /* GNUC >= 3.3 */ # define ATTRIBUTE_NULL_PRINTF_1 ATTRIBUTE_NULL_PRINTF(1, 2) # define ATTRIBUTE_NULL_PRINTF_2 ATTRIBUTE_NULL_PRINTF(2, 3) # define ATTRIBUTE_NULL_PRINTF_3 ATTRIBUTE_NULL_PRINTF(3, 4) # define ATTRIBUTE_NULL_PRINTF_4 ATTRIBUTE_NULL_PRINTF(4, 5) # define ATTRIBUTE_NULL_PRINTF_5 ATTRIBUTE_NULL_PRINTF(5, 6) #endif /* ATTRIBUTE_NULL_PRINTF */ /* Attribute `sentinel' was valid as of gcc 3.5. */ #ifndef ATTRIBUTE_SENTINEL # if (GCC_VERSION >= 3005) # define ATTRIBUTE_SENTINEL __attribute__ ((__sentinel__)) # else # define ATTRIBUTE_SENTINEL # endif /* GNUC >= 3.5 */ #endif /* ATTRIBUTE_SENTINEL */ #ifndef ATTRIBUTE_ALIGNED_ALIGNOF # if (GCC_VERSION >= 3000) # define ATTRIBUTE_ALIGNED_ALIGNOF(m) __attribute__ ((__aligned__ (__alignof__ (m)))) # else # define ATTRIBUTE_ALIGNED_ALIGNOF(m) # endif /* GNUC >= 3.0 */ #endif /* ATTRIBUTE_ALIGNED_ALIGNOF */ /* Useful for structures whose layout must much some binary specification regardless of the alignment and padding qualities of the compiler. */ #ifndef ATTRIBUTE_PACKED # define ATTRIBUTE_PACKED __attribute__ ((packed)) #endif /* Attribute `hot' and `cold' was valid as of gcc 4.3. */ #ifndef ATTRIBUTE_COLD # if (GCC_VERSION >= 4003) # define ATTRIBUTE_COLD __attribute__ ((__cold__)) # else # define ATTRIBUTE_COLD # endif /* GNUC >= 4.3 */ #endif /* ATTRIBUTE_COLD */ #ifndef ATTRIBUTE_HOT # if (GCC_VERSION >= 4003) # define ATTRIBUTE_HOT __attribute__ ((__hot__)) # else # define ATTRIBUTE_HOT # endif /* GNUC >= 4.3 */ #endif /* ATTRIBUTE_HOT */ /* Attribute 'no_sanitize_undefined' was valid as of gcc 4.9. */ #ifndef ATTRIBUTE_NO_SANITIZE_UNDEFINED # if (GCC_VERSION >= 4009) # define ATTRIBUTE_NO_SANITIZE_UNDEFINED __attribute__ ((no_sanitize_undefined)) # else # define ATTRIBUTE_NO_SANITIZE_UNDEFINED # endif /* GNUC >= 4.9 */ #endif /* ATTRIBUTE_NO_SANITIZE_UNDEFINED */ /* We use __extension__ in some places to suppress -pedantic warnings about GCC extensions. This feature didn't work properly before gcc 2.8. */ #if GCC_VERSION < 2008 #define __extension__ #endif /* This is used to declare a const variable which should be visible outside of the current compilation unit. Use it as EXPORTED_CONST int i = 1; This is because the semantics of const are different in C and C++. "extern const" is permitted in C but it looks strange, and gcc warns about it when -Wc++-compat is not used. */ #ifdef __cplusplus #define EXPORTED_CONST extern const #else #define EXPORTED_CONST const #endif /* Be conservative and only use enum bitfields with C++ or GCC. FIXME: provide a complete autoconf test for buggy enum bitfields. */ #ifdef __cplusplus #define ENUM_BITFIELD(TYPE) enum TYPE #elif (GCC_VERSION > 2000) #define ENUM_BITFIELD(TYPE) __extension__ enum TYPE #else #define ENUM_BITFIELD(TYPE) unsigned int #endif /* C++11 adds the ability to add "override" after an implementation of a virtual function in a subclass, to: (A) document that this is an override of a virtual function (B) allow the compiler to issue a warning if it isn't (e.g. a mismatch of the type signature). Similarly, it allows us to add a "final" to indicate that no subclass may subsequently override the vfunc. Provide OVERRIDE and FINAL as macros, allowing us to get these benefits when compiling with C++11 support, but without requiring C++11. For gcc, use "-std=c++11" to enable C++11 support; gcc 6 onwards enables this by default (actually GNU++14). */ #if __cplusplus >= 201103 /* C++11 claims to be available: use it. final/override were only implemented in 4.7, though. */ # if GCC_VERSION < 4007 # define OVERRIDE # define FINAL # else # define OVERRIDE override # define FINAL final # endif #elif GCC_VERSION >= 4007 /* G++ 4.7 supports __final in C++98. */ # define OVERRIDE # define FINAL __final #else /* No C++11 support; leave the macros empty: */ # define OVERRIDE # define FINAL #endif #ifdef __cplusplus } #endif #endif /* ansidecl.h */ vendor/backtrace-sys-0.1.16/src/libbacktrace/atomic.c0000664000000000000000000000561713264166600021161 0ustar rootroot/* atomic.c -- Support for atomic functions if not present. Copyright (C) 2013-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. */ #include "config.h" #include #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 vendor/backtrace-sys-0.1.16/src/libbacktrace/backtrace-supported.h.in0000664000000000000000000000600313264166600024247 0ustar rootroot/* 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@ vendor/backtrace-sys-0.1.16/src/libbacktrace/backtrace.c0000664000000000000000000000721213264166600021615 0ustar rootroot/* backtrace.c -- Entry point for stack backtrace library. 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. */ #include "config.h" #include #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; } vendor/backtrace-sys-0.1.16/src/libbacktrace/backtrace.h0000664000000000000000000002106213264166600021621 0ustar rootroot/* backtrace.h -- Public header file for stack backtrace library. 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. */ #ifndef BACKTRACE_H #define BACKTRACE_H #include #include /* We want to get a definition for uintptr_t, but we still care about systems that don't have . */ #if defined(__GLIBC__) && __GLIBC__ >= 2 #include #elif defined(HAVE_STDINT_H) #include #else /* Systems that don't have must provide gstdint.h, e.g., from GCC_HEADER_STDINT in configure.ac. */ #include "gstdint.h" #endif #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 vendor/backtrace-sys-0.1.16/src/libbacktrace/btest.c0000664000000000000000000003670213264166600021025 0ustar rootroot/* btest.c -- Test for libbacktrace library 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. */ /* This program tests the externally visible interfaces of the libbacktrace library. */ #include #include #include #include #include "filenames.h" #include "backtrace.h" #include "backtrace-supported.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. */ static void *state; /* The number of failures. */ static int failures; /* Return the base name in a path. */ static 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. */ static void check (const char *name, int index, const struct info *all, int want_lineno, const char *want_function, 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), "btest.c") != 0) { fprintf (stderr, "%s: [%d]: got %s expected test.c\n", name, index, all[index].filename); *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. */ static 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. */ static 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. */ static 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. */ static 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. */ static 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. */ static 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; } /* 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", &data.failed); check ("test1", 1, all, f2line, "f2", &data.failed); check ("test1", 2, all, f1line, "test1", &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", &data.failed); check ("test2", 1, all, f2line, "f12", &data.failed); check ("test2", 2, all, f1line, "test2", &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", &bdata.failed); check ("test3", 1, all, f2line, "f22", &bdata.failed); check ("test3", 2, all, f1line, "test3", &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", &bdata.failed); check ("test4", 1, all, f2line, "f32", &bdata.failed); check ("test4", 2, all, f1line, "test4", &bdata.failed); if (bdata.failed) data.failed = 1; } printf ("%s: backtrace_simple inline\n", data.failed ? "FAIL" : "PASS"); if (data.failed) ++failures; return failures; } #if BACKTRACE_SUPPORTS_DATA 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; } #endif /* BACKTRACE_SUPPORTS_DATA */ static 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); } /* 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 exit (failures ? EXIT_FAILURE : EXIT_SUCCESS); } vendor/backtrace-sys-0.1.16/src/libbacktrace/config.guess0000775000000000000000000012564413264166600022064 0ustar rootroot#! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2016 Free Software Foundation, Inc. timestamp='2016-10-02' # 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 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 . # # 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. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # 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 # # Please send patches to . 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 ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright 1992-2016 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 case "${UNAME_SYSTEM}" in Linux|GNU|GNU/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu eval $set_cc_for_build cat <<-EOF > $dummy.c #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #else LIBC=gnu #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` ;; esac # 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=`(uname -p 2>/dev/null || \ /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 ;; earmv*) arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'` endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'` machine=${arch}${endian}-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) and ABI. case "${UNAME_MACHINE_ARCH}" in earm*) os=netbsdelf ;; 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 # Determine ABI tags. case "${UNAME_MACHINE_ARCH}" in earm*) expr='s/^earmv[0-9]/-eabi/;s/eb$//' abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"` ;; 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/[-_].*//' | cut -d. -f1,2` ;; 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}${abi}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:LibertyBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${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 ;; *:Sortix:*:*) echo ${UNAME_MACHINE}-unknown-sortix 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 /* 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 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/lslpp ] ; then IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` 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 #include 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 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 ;; *:MINGW64*:*) echo ${UNAME_MACHINE}-pc-mingw64 exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; *: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-${LIBC}`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 "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; aarch64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo ${UNAME_MACHINE}-unknown-linux-${LIBC} 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=gnulibc1 ; fi echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arc:Linux:*:* | arceb:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${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-${LIBC} else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi else echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf fi fi exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; cris:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; crisv32:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; e2k:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; frv:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; hexagon:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:Linux:*:*) echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; k1om:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} 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-${LIBC}"; exit; } ;; mips64el:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; openrisc*:Linux:*:*) echo or1k-unknown-linux-${LIBC} exit ;; or32:Linux:*:* | or1k*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; padre:Linux:*:*) echo sparc-unknown-linux-${LIBC} exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-${LIBC} 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-${LIBC} ;; PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; *) echo hppa-unknown-linux-${LIBC} ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-${LIBC} exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-${LIBC} exit ;; ppc64le:Linux:*:*) echo powerpc64le-unknown-linux-${LIBC} exit ;; ppcle:Linux:*:*) echo powerpcle-unknown-linux-${LIBC} exit ;; riscv32:Linux:*:* | riscv64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux-${LIBC} exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; tile*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-${LIBC} exit ;; x86_64:Linux:*:*) echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} 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' /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 configure 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 echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # 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 ;; x86_64:Haiku:*:*) echo x86_64-unknown-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 ;; SX-ACE:SUPER-UX:*:*) echo sxace-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 eval $set_cc_for_build if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then 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 case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi fi elif test "$UNAME_PROCESSOR" = i386 ; then # Avoid executing cc on OS X 10.9, as it ships with a stub # that puts up a graphical alert prompting to install # developer tools. Any system running Mac OS X 10.7 or # later (Darwin 11 and later) is required to have a 64-bit # processor. This is not true of the ARM version of Darwin # that Apple uses in portable devices. UNAME_PROCESSOR=x86_64 fi 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 ;; amd64:Isilon\ OneFS:*:*) echo x86_64-unknown-onefs exit ;; esac cat >&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: vendor/backtrace-sys-0.1.16/src/libbacktrace/config.h.in0000664000000000000000000000653413264166600021563 0ustar rootroot/* config.h.in. Generated from configure.ac by autoheader. */ /* ELF size: 32 or 64 */ #undef BACKTRACE_ELF_SIZE /* Define to 1 if you have the __atomic functions */ #undef HAVE_ATOMIC_FUNCTIONS /* 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 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 header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_LINK_H /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the 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 header file. */ #undef HAVE_SYS_MMAN_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* 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 /* The size of `char', as computed by sizeof. */ #undef SIZEOF_CHAR /* The size of `int', as computed by sizeof. */ #undef SIZEOF_INT /* The size of `long', as computed by sizeof. */ #undef SIZEOF_LONG /* The size of `short', as computed by sizeof. */ #undef SIZEOF_SHORT /* The size of `void *', as computed by sizeof. */ #undef SIZEOF_VOID_P /* 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 /* 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 vendor/backtrace-sys-0.1.16/src/libbacktrace/config.sub0000775000000000000000000010677613264166600021534 0ustar rootroot#! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2016 Free Software Foundation, Inc. timestamp='2016-11-19' # 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 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 . # # 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. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches to . # # 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 # 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 or 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 ." version="\ GNU config.sub ($timestamp) Copyright 1992-2016 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-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ kopensolaris*-gnu* | cloudabi*-eabi* | \ 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*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -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 | arceb \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ | ba \ | be32 | be64 \ | bfin \ | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ | e2k | epiphany \ | fido | fr30 | frv | ft32 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | k1om \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | microblazeel | 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 \ | mipsisa32r6 | mipsisa32r6el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64r6 | mipsisa64r6el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipsr5900 | mipsr5900el \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ | open8 | or1k | or1knd | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pru \ | pyramid \ | riscv32 | riscv64 \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]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 \ | visium \ | 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 ;; leon|leon[3-9]) basic_machine=sparc-$basic_machine ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | 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-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | ba-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | e2k-* | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | k1om-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ | microblaze-* | microblazeel-* \ | 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-* \ | mipsisa32r6-* | mipsisa32r6el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64r6-* | mipsisa64r6el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipsr5900-* | mipsr5900el-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | or1k*-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pru-* \ | pyramid-* \ | riscv32-* | riscv64-* \ | 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-* \ | visium-* \ | 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 ;; asmjs) basic_machine=asmjs-unknown ;; 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 ;; leon-*|leon[3-9]-*) basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` ;; 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 ;; mingw64) basic_machine=x86_64-pc os=-mingw64 ;; mingw32) basic_machine=i686-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 ;; moxiebox) basic_machine=moxie-unknown os=-moxiebox ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i686-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 ;; 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 | rdos64) basic_machine=x86_64-pc os=-rdos ;; rdos32) 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 ;; 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* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* | -cloudabi* | -sortix* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ | -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* | -glidix* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ | -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* \ | -onefs* | -tirtos* | -phoenix* | -fuchsia*) # 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 ;; -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 ;; c8051-*) os=-elf ;; hexagon-*) os=-elf ;; 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 ;; *-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: vendor/backtrace-sys-0.1.16/src/libbacktrace/configure0000775000000000000000000153603713264166600021456 0ustar rootroot#! /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 test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || 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'" SHELL=${CONFIG_SHELL-/bin/sh} exec 7<&0 &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 #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS NATIVE_FALSE NATIVE_TRUE 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 AR OBJDUMP LN_S NM ac_ct_DUMPBIN DUMPBIN LD FGREP SED LIBTOOL RANLIB 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 with_system_libunwind enable_host_shared ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP' # 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) --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 if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor 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 declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #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_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_c_check_type () { 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 eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=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 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_type # ac_fn_c_compute_int LINENO EXPR VAR INCLUDES # -------------------------------------------- # Tries to find the compile-time value of EXPR in a program that includes # INCLUDES, setting VAR accordingly. Returns whether the value could be # computed ac_fn_c_compute_int () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) >= 0)]; test_array [0] = 0 ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_lo=0 ac_mid=0 while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_hi=$ac_mid; break else as_fn_arith $ac_mid + 1 && ac_lo=$as_val if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) < 0)]; test_array [0] = 0 ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_hi=-1 ac_mid=-1 while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) >= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_lo=$ac_mid; break else as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else ac_lo= ac_hi= fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_hi=$ac_mid else as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done case $ac_lo in #(( ?*) eval "$3=\$ac_lo"; ac_retval=0 ;; '') ac_retval=1 ;; esac else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 static long int longval () { return $2; } static unsigned long int ulongval () { return $2; } #include #include int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) return 1; if (($2) < 0) { long int i = longval (); if (i != ($2)) return 1; fprintf (f, "%ld", i); } else { unsigned long int i = ulongval (); if (i != ($2)) return 1; fprintf (f, "%lu", i); } /* Do not output a trailing newline, as this causes \r\n confusion on some platforms. */ return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : echo >>conftest.val; read $3 &5 $as_echo_n "checking whether $as_decl_name 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 $as_decl_name #ifdef __cplusplus (void) $as_decl_use; #else (void) $as_decl_name; #endif #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" 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. */ int main () { ; 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 #include #include #include /* 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 to if __STDC__ is defined, since # 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 #else # include #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 _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 to if __STDC__ is defined, since # 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 #else # include #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 _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 #include #include #include 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 _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 _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 #include #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 #include #include #include /* 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 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 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.7a' macro_revision='1.3134' ltmain="$ac_aux_dir/ltmain.sh" # Backslashify 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' ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 $as_echo_n "checking how to print strings... " >&6; } # Test print first, because it will be a builtin if present. if test "X`print -r -- -n 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "" } case "$ECHO" in printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 $as_echo "printf" >&6; } ;; print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 $as_echo "print -r" >&6; } ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 $as_echo "cat" >&6; } ;; esac { $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 &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 &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 "$DUMPBIN"; then : # Let the user override the test. else if test -n "$ac_tool_prefix"; then for ac_prog in dumpbin "link -dump" 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 "link -dump" 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 case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols" ;; *) DUMPBIN=: ;; esac 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:$LINENO: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: 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* | cegcc*) # 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; ;; mint*) # On MiNT this can take a long time and run out of memory. 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"`func_fallback_echo "$teststring$teststring" 2>/dev/null` \ = "X$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 if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; 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_OBJDUMP+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # 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_OBJDUMP="${ac_tool_prefix}objdump" $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 OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 $as_echo "$OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; 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_OBJDUMP+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # 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_OBJDUMP="objdump" $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_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 $as_echo "$ac_ct_OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="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 OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi test -z "$OBJDUMP" && OBJDUMP=objdump { $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. # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. if ( test "$lt_cv_nm_interface" = "BSD nm" && 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 ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; 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 ;; haiku*) 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])(-bit)?( [LM]SB)? 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 | kopensolaris*-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 case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac # 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* | cegcc*) 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 '$LINENO' "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*|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*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; 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" ;; powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; 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; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 $as_echo_n "checking for -force_load linker flag... " >&6; } if test "${lt_cv_ld_force_load+set}" = set; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 echo "$AR cru libconftest.a conftest.o" >&5 $AR cru libconftest.a conftest.o 2>&5 cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -f conftest && test ! -s conftest.err && test $_lt_result = 0 && $GREP forced_load conftest 2>&1 >/dev/null; then lt_cv_ld_force_load=yes else cat conftest.err >&5 fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 $as_echo "$lt_cv_ld_force_load" >&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" != ":" && test "$lt_cv_ld_force_load" = "no"; 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 # 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 "$cc_temp" | $SED "s%.*/%%; 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 case $cc_basename in nvcc*) lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; *) lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; esac { $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:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $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 "$_lt_compiler_boilerplate" | $SED '/^$/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 lt_prog_compiler_pic='-fPIC' ;; 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* | cegcc*) # 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' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +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 case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 lt_prog_compiler_wl='-Xlinker ' lt_prog_compiler_pic='-Xcompiler -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* | cegcc*) # 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 | kopensolaris*-gnu) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; # Lahey Fortran 8.1. lf95*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='--shared' lt_prog_compiler_static='--static' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # 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* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-qpic' lt_prog_compiler_static='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ F* | *Sun*Fortran*) # 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='' ;; *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-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:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $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 "$_lt_compiler_boilerplate" | $SED '/^$/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 "$_lt_linker_boilerplate" | $SED '/^$/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:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $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 "$_lt_compiler_boilerplate" | $SED '/^$/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:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $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 "$_lt_compiler_boilerplate" | $SED '/^$/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* | cegcc*) # 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 # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test "$with_gnu_ld" = yes; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; *\ \(GNU\ Binutils\)\ [3-9]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test "$lt_use_gnu_ld_interface" = 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 *GNU\ gold*) supports_anon_versioning=yes ;; *\ [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.19, 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 install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _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 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* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' export_dynamic_flag_spec='${wl}--export-all-symbols' 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 ;; haiku*) archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' link_all_deplibs=yes ;; 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 | kopensolaris*-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=' $pic_flag' 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; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # 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; func_echo_all \"$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' ;; lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object=yes ;; 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; func_echo_all \"$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* | bgf* | bgxlf* | mpixlf*) # 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 # Also, AIX nm treats weak defined symbols like other global # defined symbols, whereas GNU nm marks them as "W". 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") || (\$ 2 == "W")) && (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") || (\$ 2 == "L")) && (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 export_dynamic_flag_spec='${wl}-bexpall' # 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 func_echo_all "${wl}${allow_undefined_flag}"; 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' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' fi 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* | cegcc*) # 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 `func_echo_all "$deplibs" | $SED '\''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 if test "$lt_cv_ld_force_load" = "yes"; then whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec='' fi link_all_deplibs=yes allow_undefined_flag="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=func_echo_all 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 ;; # 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*) 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 && test "$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 && test "$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 -fPIC ${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' ;; *) # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 $as_echo_n "checking if $CC understands -b... " >&6; } if test "${lt_cv_prog_compiler__b+set}" = set; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler__b=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -b" 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 "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler__b=yes fi else lt_cv_prog_compiler__b=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 $as_echo "$lt_cv_prog_compiler__b" >&6; } if test x"$lt_cv_prog_compiler__b" = xyes; then archive_cmds='$CC -b ${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 ;; 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" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${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" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${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" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -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" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${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" && func_echo_all "-set_version $verstring"` -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" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${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" && func_echo_all "-set_version $verstring"` -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 "-set_version $verstring"` -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; } if test "${lt_cv_archive_cmds_need_lc+set}" = set; then : $as_echo_n "(cached) " >&6 else $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 lt_cv_archive_cmds_need_lc=no else lt_cv_archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 $as_echo "$lt_cv_archive_cmds_need_lc" >&6; } archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc ;; 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 case $host_os in mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;; *) lt_sed_strip_eq="s,=/,/,g" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # 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 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # 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; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's,/\([A-Za-z]:\),\1,g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` 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.so # instead of lib.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=`func_echo_all "$lib" | $SED '\''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* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*) 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="$sys_lib_search_path_spec /usr/lib/w32api" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; 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 ;; 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[23].*) 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 ;; haiku*) version_type=linux need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" 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=LIBRARY_PATH shlibpath_overrides_runpath=yes sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/beos/system/lib' 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' # or fails outright, so override atomically: install_override_mode=555 ;; 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 | kopensolaris*-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 if test "${lt_cv_shlibpath_overrides_runpath+set}" = set; then : $as_echo_n "(cached) " >&6 else lt_cv_shlibpath_overrides_runpath=no 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 : lt_cv_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 fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # 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;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_names_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* | cegcc*) 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 11134 "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #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 /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) void fnord () __attribute__((visibility("default"))); #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; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return 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 11240 "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #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 /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) void fnord () __attribute__((visibility("default"))); #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; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return 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: 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 ;; *) { $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 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 inttype_headers=`echo inttypes.h sys/inttypes.h | sed -e 's/,/ /g'` acx_cv_header_stdint=stddef.h acx_cv_header_stdint_kind="(already complete)" for i in stdint.h $inttype_headers; do unset ac_cv_type_uintptr_t unset ac_cv_type_uintmax_t unset ac_cv_type_int_least32_t unset ac_cv_type_int_fast32_t unset ac_cv_type_uint64_t $as_echo_n "looking for a compliant stdint.h in $i, " >&6 ac_fn_c_check_type "$LINENO" "uintmax_t" "ac_cv_type_uintmax_t" "#include #include <$i> " if test "x$ac_cv_type_uintmax_t" = x""yes; then : acx_cv_header_stdint=$i else continue fi ac_fn_c_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "#include #include <$i> " if test "x$ac_cv_type_uintptr_t" = x""yes; then : else acx_cv_header_stdint_kind="(mostly complete)" fi ac_fn_c_check_type "$LINENO" "int_least32_t" "ac_cv_type_int_least32_t" "#include #include <$i> " if test "x$ac_cv_type_int_least32_t" = x""yes; then : else acx_cv_header_stdint_kind="(mostly complete)" fi ac_fn_c_check_type "$LINENO" "int_fast32_t" "ac_cv_type_int_fast32_t" "#include #include <$i> " if test "x$ac_cv_type_int_fast32_t" = x""yes; then : else acx_cv_header_stdint_kind="(mostly complete)" fi ac_fn_c_check_type "$LINENO" "uint64_t" "ac_cv_type_uint64_t" "#include #include <$i> " if test "x$ac_cv_type_uint64_t" = x""yes; then : else acx_cv_header_stdint_kind="(lacks uint64_t)" fi break done if test "$acx_cv_header_stdint" = stddef.h; then acx_cv_header_stdint_kind="(lacks uintmax_t)" for i in stdint.h $inttype_headers; do unset ac_cv_type_uintptr_t unset ac_cv_type_uint32_t unset ac_cv_type_uint64_t $as_echo_n "looking for an incomplete stdint.h in $i, " >&6 ac_fn_c_check_type "$LINENO" "uint32_t" "ac_cv_type_uint32_t" "#include #include <$i> " if test "x$ac_cv_type_uint32_t" = x""yes; then : acx_cv_header_stdint=$i else continue fi ac_fn_c_check_type "$LINENO" "uint64_t" "ac_cv_type_uint64_t" "#include #include <$i> " if test "x$ac_cv_type_uint64_t" = x""yes; then : fi ac_fn_c_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "#include #include <$i> " if test "x$ac_cv_type_uintptr_t" = x""yes; then : fi break done fi if test "$acx_cv_header_stdint" = stddef.h; then acx_cv_header_stdint_kind="(u_intXX_t style)" for i in sys/types.h $inttype_headers; do unset ac_cv_type_u_int32_t unset ac_cv_type_u_int64_t $as_echo_n "looking for u_intXX_t types in $i, " >&6 ac_fn_c_check_type "$LINENO" "u_int32_t" "ac_cv_type_u_int32_t" "#include #include <$i> " if test "x$ac_cv_type_u_int32_t" = x""yes; then : acx_cv_header_stdint=$i else continue fi ac_fn_c_check_type "$LINENO" "u_int64_t" "ac_cv_type_u_int64_t" "#include #include <$i> " if test "x$ac_cv_type_u_int64_t" = x""yes; then : fi break done fi if test "$acx_cv_header_stdint" = stddef.h; then acx_cv_header_stdint_kind="(using manual detection)" fi test -z "$ac_cv_type_uintptr_t" && ac_cv_type_uintptr_t=no test -z "$ac_cv_type_uint64_t" && ac_cv_type_uint64_t=no test -z "$ac_cv_type_u_int64_t" && ac_cv_type_u_int64_t=no test -z "$ac_cv_type_int_least32_t" && ac_cv_type_int_least32_t=no test -z "$ac_cv_type_int_fast32_t" && ac_cv_type_int_fast32_t=no # ----------------- Summarize what we found so far { $as_echo "$as_me:${as_lineno-$LINENO}: checking what to include in gstdint.h" >&5 $as_echo_n "checking what to include in gstdint.h... " >&6; } case `$as_basename -- gstdint.h || $as_expr X/gstdint.h : '.*/\([^/][^/]*\)/*$' \| \ Xgstdint.h : 'X\(//\)$' \| \ Xgstdint.h : 'X\(/\)' \| . 2>/dev/null || $as_echo X/gstdint.h | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` in stdint.h) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: are you sure you want it there?" >&5 $as_echo "$as_me: WARNING: are you sure you want it there?" >&2;} ;; inttypes.h) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: are you sure you want it there?" >&5 $as_echo "$as_me: WARNING: are you sure you want it there?" >&2;} ;; *) ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_cv_header_stdint $acx_cv_header_stdint_kind" >&5 $as_echo "$acx_cv_header_stdint $acx_cv_header_stdint_kind" >&6; } # ----------------- done included file, check C basic types -------- # Lacking an uintptr_t? Test size of void * case "$acx_cv_header_stdint:$ac_cv_type_uintptr_t" in stddef.h:* | *:no) # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5 $as_echo_n "checking size of void *... " >&6; } if test "${ac_cv_sizeof_void_p+set}" = set; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"; then : else if test "$ac_cv_type_void_p" = yes; then { { $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 "cannot compute sizeof (void *) See \`config.log' for more details." "$LINENO" 5; }; } else ac_cv_sizeof_void_p=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5 $as_echo "$ac_cv_sizeof_void_p" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_VOID_P $ac_cv_sizeof_void_p _ACEOF ;; esac # Lacking an uint64_t? Test size of long case "$acx_cv_header_stdint:$ac_cv_type_uint64_t:$ac_cv_type_u_int64_t" in stddef.h:*:* | *:no:no) # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long" >&5 $as_echo_n "checking size of long... " >&6; } if test "${ac_cv_sizeof_long+set}" = set; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"; then : else if test "$ac_cv_type_long" = yes; then { { $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 "cannot compute sizeof (long) See \`config.log' for more details." "$LINENO" 5; }; } else ac_cv_sizeof_long=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5 $as_echo "$ac_cv_sizeof_long" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_LONG $ac_cv_sizeof_long _ACEOF ;; esac if test $acx_cv_header_stdint = stddef.h; then # Lacking a good header? Test size of everything and deduce all types. # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of int" >&5 $as_echo_n "checking size of int... " >&6; } if test "${ac_cv_sizeof_int+set}" = set; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int" "$ac_includes_default"; then : else if test "$ac_cv_type_int" = yes; then { { $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 "cannot compute sizeof (int) See \`config.log' for more details." "$LINENO" 5; }; } else ac_cv_sizeof_int=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int" >&5 $as_echo "$ac_cv_sizeof_int" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_INT $ac_cv_sizeof_int _ACEOF # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of short" >&5 $as_echo_n "checking size of short... " >&6; } if test "${ac_cv_sizeof_short+set}" = set; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (short))" "ac_cv_sizeof_short" "$ac_includes_default"; then : else if test "$ac_cv_type_short" = yes; then { { $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 "cannot compute sizeof (short) See \`config.log' for more details." "$LINENO" 5; }; } else ac_cv_sizeof_short=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_short" >&5 $as_echo "$ac_cv_sizeof_short" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_SHORT $ac_cv_sizeof_short _ACEOF # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of char" >&5 $as_echo_n "checking size of char... " >&6; } if test "${ac_cv_sizeof_char+set}" = set; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (char))" "ac_cv_sizeof_char" "$ac_includes_default"; then : else if test "$ac_cv_type_char" = yes; then { { $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 "cannot compute sizeof (char) See \`config.log' for more details." "$LINENO" 5; }; } else ac_cv_sizeof_char=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_char" >&5 $as_echo "$ac_cv_sizeof_char" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_CHAR $ac_cv_sizeof_char _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for type equivalent to int8_t" >&5 $as_echo_n "checking for type equivalent to int8_t... " >&6; } case "$ac_cv_sizeof_char" in 1) acx_cv_type_int8_t=char ;; *) as_fn_error "no 8-bit type, please report a bug" "$LINENO" 5 esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_cv_type_int8_t" >&5 $as_echo "$acx_cv_type_int8_t" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for type equivalent to int16_t" >&5 $as_echo_n "checking for type equivalent to int16_t... " >&6; } case "$ac_cv_sizeof_int:$ac_cv_sizeof_short" in 2:*) acx_cv_type_int16_t=int ;; *:2) acx_cv_type_int16_t=short ;; *) as_fn_error "no 16-bit type, please report a bug" "$LINENO" 5 esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_cv_type_int16_t" >&5 $as_echo "$acx_cv_type_int16_t" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for type equivalent to int32_t" >&5 $as_echo_n "checking for type equivalent to int32_t... " >&6; } case "$ac_cv_sizeof_int:$ac_cv_sizeof_long" in 4:*) acx_cv_type_int32_t=int ;; *:4) acx_cv_type_int32_t=long ;; *) as_fn_error "no 32-bit type, please report a bug" "$LINENO" 5 esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_cv_type_int32_t" >&5 $as_echo "$acx_cv_type_int32_t" >&6; } fi # These tests are here to make the output prettier if test "$ac_cv_type_uint64_t" != yes && test "$ac_cv_type_u_int64_t" != yes; then case "$ac_cv_sizeof_long" in 8) acx_cv_type_int64_t=long ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for type equivalent to int64_t" >&5 $as_echo_n "checking for type equivalent to int64_t... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${acx_cv_type_int64_t-'using preprocessor symbols'}" >&5 $as_echo "${acx_cv_type_int64_t-'using preprocessor symbols'}" >&6; } fi # Now we can use the above types if test "$ac_cv_type_uintptr_t" != yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for type equivalent to intptr_t" >&5 $as_echo_n "checking for type equivalent to intptr_t... " >&6; } case $ac_cv_sizeof_void_p in 2) acx_cv_type_intptr_t=int16_t ;; 4) acx_cv_type_intptr_t=int32_t ;; 8) acx_cv_type_intptr_t=int64_t ;; *) as_fn_error "no equivalent for intptr_t, please report a bug" "$LINENO" 5 esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_cv_type_intptr_t" >&5 $as_echo "$acx_cv_type_intptr_t" >&6; } fi # ----------------- done all checks, emit header ------------- ac_config_commands="$ac_config_commands gstdint.h" 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 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 #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 _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 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 # 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 { $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 "${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" CXX="$CXX" GFORTRAN="$GFORTRAN" # 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 "$macro_version" | $SED "$delay_single_quote_subst"`' macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec_ld='`$ECHO "$hardcode_libdir_flag_spec_ld" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' fix_srcfile_path='`$ECHO "$fix_srcfile_path" | $SED "$delay_single_quote_subst"`' always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`' hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } # Quote evaled strings. for var in SHELL \ ECHO \ SED \ GREP \ EGREP \ FGREP \ LD \ NM \ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ OBJDUMP \ 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 \ 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 \ install_override_mode \ finish_eval \ old_striplib \ striplib; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$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 \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done 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' GCC="$GCC" CC="$CC" acx_cv_header_stdint="$acx_cv_header_stdint" acx_cv_type_int8_t="$acx_cv_type_int8_t" acx_cv_type_int16_t="$acx_cv_type_int16_t" acx_cv_type_int32_t="$acx_cv_type_int32_t" acx_cv_type_int64_t="$acx_cv_type_int64_t" acx_cv_type_intptr_t="$acx_cv_type_intptr_t" ac_cv_type_uintmax_t="$ac_cv_type_uintmax_t" ac_cv_type_uintptr_t="$ac_cv_type_uintptr_t" ac_cv_type_uint64_t="$ac_cv_type_uint64_t" ac_cv_type_u_int64_t="$ac_cv_type_u_int64_t" ac_cv_type_u_int32_t="$ac_cv_type_u_int32_t" ac_cv_type_int_least32_t="$ac_cv_type_int_least32_t" ac_cv_type_int_fast32_t="$ac_cv_type_int_fast32_t" ac_cv_sizeof_void_p="$ac_cv_sizeof_void_p" # 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" ;; "gstdint.h") CONFIG_COMMANDS="$CONFIG_COMMANDS gstdint.h" ;; "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` 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 ' >$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 ' >$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, 2009 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 # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # An echo program that protects backslashes. ECHO=$lt_ECHO # 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 # An object symbol dumper. OBJDUMP=$lt_OBJDUMP # 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 # Whether to use a lock for old archive extraction. lock_old_archive_extraction=$lock_old_archive_extraction # 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 # 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 # Permission mode override for installation of shared libraries. install_override_mode=$lt_install_override_mode # 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 # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # 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 "${1}" | $SED "$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 "${1}" | $SED "$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 "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; 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 "${1}" | $SED "$my_sed_long_opt"` func_opt_split_arg=`$ECHO "${1}" | $SED "$my_sed_long_arg"` } # func_lo2o object func_lo2o () { func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` } # func_xform libobj-or-source func_xform () { func_xform_result=`$ECHO "${1}" | $SED '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" ;; "gstdint.h":C) if test "$GCC" = yes; then echo "/* generated for " `$CC --version | sed 1q` "*/" > tmp-stdint.h else echo "/* generated for $CC */" > tmp-stdint.h fi sed 's/^ *//' >> tmp-stdint.h < EOF if test "$acx_cv_header_stdint" != stdint.h; then echo "#include " >> tmp-stdint.h fi if test "$acx_cv_header_stdint" != stddef.h; then echo "#include <$acx_cv_header_stdint>" >> tmp-stdint.h fi sed 's/^ *//' >> tmp-stdint.h <> tmp-stdint.h <> tmp-stdint.h <> tmp-stdint.h <> tmp-stdint.h <> tmp-stdint.h <> tmp-stdint.h <> tmp-stdint.h <= 199901L #ifndef _INT64_T #define _INT64_T #ifndef __int64_t_defined #ifndef int64_t typedef long long int64_t; #endif #endif #endif #ifndef _UINT64_T #define _UINT64_T #ifndef uint64_t typedef unsigned long long uint64_t; #endif #endif #elif defined __GNUC__ && defined (__STDC__) && __STDC__-0 /* NextStep 2.0 cc is really gcc 1.93 but it defines __GNUC__ = 2 and does not implement __extension__. But that compiler doesn't define __GNUC_MINOR__. */ # if __GNUC__ < 2 || (__NeXT__ && !__GNUC_MINOR__) # define __extension__ # endif # ifndef _INT64_T # define _INT64_T # ifndef int64_t __extension__ typedef long long int64_t; # endif # endif # ifndef _UINT64_T # define _UINT64_T # ifndef uint64_t __extension__ typedef unsigned long long uint64_t; # endif # endif #elif !defined __STRICT_ANSI__ # if defined _MSC_VER || defined __WATCOMC__ || defined __BORLANDC__ # ifndef _INT64_T # define _INT64_T # ifndef int64_t typedef __int64 int64_t; # endif # endif # ifndef _UINT64_T # define _UINT64_T # ifndef uint64_t typedef unsigned __int64 uint64_t; # endif # endif # endif /* compiler */ #endif /* ANSI version */ EOF fi # ------------- done int64_t types, emit intptr types ------------ if test "$ac_cv_type_uintptr_t" != yes; then sed 's/^ *//' >> tmp-stdint.h <> tmp-stdint.h <> tmp-stdint.h <> tmp-stdint.h <> tmp-stdint.h < # 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 vendor/backtrace-sys-0.1.16/src/libbacktrace/configure.ac0000664000000000000000000003070113264166600022017 0ustar rootroot# configure.ac -- Backtrace configure script. # 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. AC_PREREQ(2.64) AC_INIT(package-unused, version-unused,, libbacktrace) AC_CONFIG_SRCDIR(backtrace.h) AC_CONFIG_HEADER(config.h) 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_RANLIB AC_PROG_AWK case "$AWK" in "") AC_MSG_ERROR([can't build without awk]) ;; esac LT_INIT AM_PROG_LIBTOOL 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 ;; *) 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]) 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) GCC_HEADER_STDINT(gstdint.h) 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 if test "$have_mmap" = "no"; then VIEW_FILE=read.lo ALLOC_FILE=alloc.lo else VIEW_FILE=mmapio.lo AC_PREPROC_IFELSE([ #include #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 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) # 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 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 vendor/backtrace-sys-0.1.16/src/libbacktrace/dwarf.c0000664000000000000000000023163413264166600021010 0ustar rootroot/* dwarf.c -- Get file/line information from DWARF for backtraces. 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. */ #include "config.h" #include #include #include #include #include "dwarf2.h" #include "filenames.h" #include "backtrace.h" #include "internal.h" #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. If FREE_FILENAMES is true we free the file names themselves, otherwise we leave them, as there may be line structures pointing to them. */ static void free_line_header (struct backtrace_state *state, struct line_header *hdr, backtrace_error_callback error_callback, void *data) { 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 = ((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; } vendor/backtrace-sys-0.1.16/src/libbacktrace/dwarf2.def0000664000000000000000000006407713264166600021413 0ustar rootroot/* -*- c -*- Declarations and definitions of codes relating to the DWARF2 and DWARF3 symbolic debugging information formats. Copyright (C) 1992-2015 Free Software Foundation, Inc. Written by Gary Funck (gary@intrepid.com) The Ada Joint Program Office (AJPO), Florida State University and Silicon Graphics Inc. provided support for this effort -- June 21, 1995. Derived from the DWARF 1 implementation written by Ron Guilmette (rfg@netcom.com), November 1990. This file is part of GCC. GCC 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, or (at your option) any later version. GCC 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. Under Section 7 of GPL version 3, you are granted additional permissions described in the GCC Runtime Library Exception, version 3.1, as published by the Free Software Foundation. You should have received a copy of the GNU General Public License and a copy of the GCC Runtime Library Exception along with this program; see the files COPYING3 and COPYING.RUNTIME respectively. If not, see . */ /* This file is derived from the DWARF specification (a public document) Revision 2.0.0 (July 27, 1993) developed by the UNIX International Programming Languages Special Interest Group (UI/PLSIG) and distributed by UNIX International. Copies of this specification are available from UNIX International, 20 Waterview Boulevard, Parsippany, NJ, 07054. This file also now contains definitions from the DWARF 3 specification published Dec 20, 2005, available from: http://dwarf.freestandards.org. This file also now contains definitions from the DWARF 4 specification, available from: http://dwarfstd.org/ */ /* This file declares various DWARF-related constants using a set of macros which can be redefined by the including file. The macros are in sections. Each section corresponds to a single set of DWARF constants and has a corresponding key. The key is used in all the macro names. The sections are TAG (for DW_TAG_ constants), FORM (DW_FORM_), AT (DW_AT_), OP (DW_OP_), ATE (DW_ATE_), and CFA (DW_CFA_). Using TAG as an example, the following macros may be used for each key: DW_FIRST_TAG(name, value) - Introduce the first DW_TAG constant. DW_TAG(name, value) - Define a subsequent constant. DW_TAG_DUP(name, value) - Define a subsequent constant whose value is a duplicate of some other constant. Not all keys use the _DUP macro form. If more than one name shares a value, then the base (DW_TAG) form will be the preferred name and DW_TAG_DUP will hold any alternate names. DW_END_TAG - Invoked at the end of the DW_TAG constants. */ DW_FIRST_TAG (DW_TAG_padding, 0x00) DW_TAG (DW_TAG_array_type, 0x01) DW_TAG (DW_TAG_class_type, 0x02) DW_TAG (DW_TAG_entry_point, 0x03) DW_TAG (DW_TAG_enumeration_type, 0x04) DW_TAG (DW_TAG_formal_parameter, 0x05) DW_TAG (DW_TAG_imported_declaration, 0x08) DW_TAG (DW_TAG_label, 0x0a) DW_TAG (DW_TAG_lexical_block, 0x0b) DW_TAG (DW_TAG_member, 0x0d) DW_TAG (DW_TAG_pointer_type, 0x0f) DW_TAG (DW_TAG_reference_type, 0x10) DW_TAG (DW_TAG_compile_unit, 0x11) DW_TAG (DW_TAG_string_type, 0x12) DW_TAG (DW_TAG_structure_type, 0x13) DW_TAG (DW_TAG_subroutine_type, 0x15) DW_TAG (DW_TAG_typedef, 0x16) DW_TAG (DW_TAG_union_type, 0x17) DW_TAG (DW_TAG_unspecified_parameters, 0x18) DW_TAG (DW_TAG_variant, 0x19) DW_TAG (DW_TAG_common_block, 0x1a) DW_TAG (DW_TAG_common_inclusion, 0x1b) DW_TAG (DW_TAG_inheritance, 0x1c) DW_TAG (DW_TAG_inlined_subroutine, 0x1d) DW_TAG (DW_TAG_module, 0x1e) DW_TAG (DW_TAG_ptr_to_member_type, 0x1f) DW_TAG (DW_TAG_set_type, 0x20) DW_TAG (DW_TAG_subrange_type, 0x21) DW_TAG (DW_TAG_with_stmt, 0x22) DW_TAG (DW_TAG_access_declaration, 0x23) DW_TAG (DW_TAG_base_type, 0x24) DW_TAG (DW_TAG_catch_block, 0x25) DW_TAG (DW_TAG_const_type, 0x26) DW_TAG (DW_TAG_constant, 0x27) DW_TAG (DW_TAG_enumerator, 0x28) DW_TAG (DW_TAG_file_type, 0x29) DW_TAG (DW_TAG_friend, 0x2a) DW_TAG (DW_TAG_namelist, 0x2b) DW_TAG (DW_TAG_namelist_item, 0x2c) DW_TAG (DW_TAG_packed_type, 0x2d) DW_TAG (DW_TAG_subprogram, 0x2e) DW_TAG (DW_TAG_template_type_param, 0x2f) DW_TAG (DW_TAG_template_value_param, 0x30) DW_TAG (DW_TAG_thrown_type, 0x31) DW_TAG (DW_TAG_try_block, 0x32) DW_TAG (DW_TAG_variant_part, 0x33) DW_TAG (DW_TAG_variable, 0x34) DW_TAG (DW_TAG_volatile_type, 0x35) /* DWARF 3. */ DW_TAG (DW_TAG_dwarf_procedure, 0x36) DW_TAG (DW_TAG_restrict_type, 0x37) DW_TAG (DW_TAG_interface_type, 0x38) DW_TAG (DW_TAG_namespace, 0x39) DW_TAG (DW_TAG_imported_module, 0x3a) DW_TAG (DW_TAG_unspecified_type, 0x3b) DW_TAG (DW_TAG_partial_unit, 0x3c) DW_TAG (DW_TAG_imported_unit, 0x3d) DW_TAG (DW_TAG_condition, 0x3f) DW_TAG (DW_TAG_shared_type, 0x40) /* DWARF 4. */ DW_TAG (DW_TAG_type_unit, 0x41) DW_TAG (DW_TAG_rvalue_reference_type, 0x42) DW_TAG (DW_TAG_template_alias, 0x43) /* DWARF 5. */ DW_TAG (DW_TAG_coarray_type, 0x44) DW_TAG (DW_TAG_generic_subrange, 0x45) DW_TAG (DW_TAG_dynamic_type, 0x46) DW_TAG (DW_TAG_atomic_type, 0x47) DW_TAG (DW_TAG_call_site, 0x48) DW_TAG (DW_TAG_call_site_parameter, 0x49) DW_TAG (DW_TAG_skeleton_unit, 0x4a) DW_TAG (DW_TAG_immutable_type, 0x4b) DW_TAG_DUP (DW_TAG_lo_user, 0x4080) DW_TAG_DUP (DW_TAG_hi_user, 0xffff) /* SGI/MIPS Extensions. */ DW_TAG (DW_TAG_MIPS_loop, 0x4081) /* HP extensions. See: ftp://ftp.hp.com/pub/lang/tools/WDB/wdb-4.0.tar.gz . */ DW_TAG (DW_TAG_HP_array_descriptor, 0x4090) DW_TAG (DW_TAG_HP_Bliss_field, 0x4091) DW_TAG (DW_TAG_HP_Bliss_field_set, 0x4092) /* GNU extensions. */ DW_TAG (DW_TAG_format_label, 0x4101) /* For FORTRAN 77 and Fortran 90. */ DW_TAG (DW_TAG_function_template, 0x4102) /* For C++. */ DW_TAG (DW_TAG_class_template, 0x4103) /* For C++. */ DW_TAG (DW_TAG_GNU_BINCL, 0x4104) DW_TAG (DW_TAG_GNU_EINCL, 0x4105) /* Template template parameter. See http://gcc.gnu.org/wiki/TemplateParmsDwarf . */ DW_TAG (DW_TAG_GNU_template_template_param, 0x4106) /* Template parameter pack extension, specified at http://wiki.dwarfstd.org/index.php?title=C%2B%2B0x:_Variadic_templates The values of these two TAGS are in the DW_TAG_GNU_* space until the tags are properly part of DWARF 5. */ DW_TAG (DW_TAG_GNU_template_parameter_pack, 0x4107) DW_TAG (DW_TAG_GNU_formal_parameter_pack, 0x4108) /* The GNU call site extension, specified at http://www.dwarfstd.org/ShowIssue.php?issue=100909.2&type=open . The values of these two TAGS are in the DW_TAG_GNU_* space until the tags are properly part of DWARF 5. */ DW_TAG (DW_TAG_GNU_call_site, 0x4109) DW_TAG (DW_TAG_GNU_call_site_parameter, 0x410a) /* Extensions for UPC. See: http://dwarfstd.org/doc/DWARF4.pdf. */ DW_TAG (DW_TAG_upc_shared_type, 0x8765) DW_TAG (DW_TAG_upc_strict_type, 0x8766) DW_TAG (DW_TAG_upc_relaxed_type, 0x8767) /* PGI (STMicroelectronics) extensions. No documentation available. */ DW_TAG (DW_TAG_PGI_kanji_type, 0xA000) DW_TAG (DW_TAG_PGI_interface_block, 0xA020) DW_END_TAG DW_FIRST_FORM (DW_FORM_addr, 0x01) DW_FORM (DW_FORM_block2, 0x03) DW_FORM (DW_FORM_block4, 0x04) DW_FORM (DW_FORM_data2, 0x05) DW_FORM (DW_FORM_data4, 0x06) DW_FORM (DW_FORM_data8, 0x07) DW_FORM (DW_FORM_string, 0x08) DW_FORM (DW_FORM_block, 0x09) DW_FORM (DW_FORM_block1, 0x0a) DW_FORM (DW_FORM_data1, 0x0b) DW_FORM (DW_FORM_flag, 0x0c) DW_FORM (DW_FORM_sdata, 0x0d) DW_FORM (DW_FORM_strp, 0x0e) DW_FORM (DW_FORM_udata, 0x0f) DW_FORM (DW_FORM_ref_addr, 0x10) DW_FORM (DW_FORM_ref1, 0x11) DW_FORM (DW_FORM_ref2, 0x12) DW_FORM (DW_FORM_ref4, 0x13) DW_FORM (DW_FORM_ref8, 0x14) DW_FORM (DW_FORM_ref_udata, 0x15) DW_FORM (DW_FORM_indirect, 0x16) /* DWARF 4. */ DW_FORM (DW_FORM_sec_offset, 0x17) DW_FORM (DW_FORM_exprloc, 0x18) DW_FORM (DW_FORM_flag_present, 0x19) DW_FORM (DW_FORM_ref_sig8, 0x20) /* DWARF 5. */ DW_FORM (DW_FORM_strx, 0x1a) DW_FORM (DW_FORM_addrx, 0x1b) DW_FORM (DW_FORM_ref_sup, 0x1c) DW_FORM (DW_FORM_strp_sup, 0x1d) DW_FORM (DW_FORM_data16, 0x1e) DW_FORM (DW_FORM_line_strp, 0x1f) DW_FORM (DW_FORM_implicit_const, 0x21) DW_FORM (DW_FORM_loclistx, 0x22) DW_FORM (DW_FORM_rnglistx, 0x23) /* Extensions for Fission. See http://gcc.gnu.org/wiki/DebugFission. */ DW_FORM (DW_FORM_GNU_addr_index, 0x1f01) DW_FORM (DW_FORM_GNU_str_index, 0x1f02) /* Extensions for DWZ multifile. See http://www.dwarfstd.org/ShowIssue.php?issue=120604.1&type=open . */ DW_FORM (DW_FORM_GNU_ref_alt, 0x1f20) DW_FORM (DW_FORM_GNU_strp_alt, 0x1f21) DW_END_FORM DW_FIRST_AT (DW_AT_sibling, 0x01) DW_AT (DW_AT_location, 0x02) DW_AT (DW_AT_name, 0x03) DW_AT (DW_AT_ordering, 0x09) DW_AT (DW_AT_subscr_data, 0x0a) DW_AT (DW_AT_byte_size, 0x0b) DW_AT (DW_AT_bit_offset, 0x0c) DW_AT (DW_AT_bit_size, 0x0d) DW_AT (DW_AT_element_list, 0x0f) DW_AT (DW_AT_stmt_list, 0x10) DW_AT (DW_AT_low_pc, 0x11) DW_AT (DW_AT_high_pc, 0x12) DW_AT (DW_AT_language, 0x13) DW_AT (DW_AT_member, 0x14) DW_AT (DW_AT_discr, 0x15) DW_AT (DW_AT_discr_value, 0x16) DW_AT (DW_AT_visibility, 0x17) DW_AT (DW_AT_import, 0x18) DW_AT (DW_AT_string_length, 0x19) DW_AT (DW_AT_common_reference, 0x1a) DW_AT (DW_AT_comp_dir, 0x1b) DW_AT (DW_AT_const_value, 0x1c) DW_AT (DW_AT_containing_type, 0x1d) DW_AT (DW_AT_default_value, 0x1e) DW_AT (DW_AT_inline, 0x20) DW_AT (DW_AT_is_optional, 0x21) DW_AT (DW_AT_lower_bound, 0x22) DW_AT (DW_AT_producer, 0x25) DW_AT (DW_AT_prototyped, 0x27) DW_AT (DW_AT_return_addr, 0x2a) DW_AT (DW_AT_start_scope, 0x2c) DW_AT (DW_AT_bit_stride, 0x2e) DW_AT (DW_AT_upper_bound, 0x2f) DW_AT (DW_AT_abstract_origin, 0x31) DW_AT (DW_AT_accessibility, 0x32) DW_AT (DW_AT_address_class, 0x33) DW_AT (DW_AT_artificial, 0x34) DW_AT (DW_AT_base_types, 0x35) DW_AT (DW_AT_calling_convention, 0x36) DW_AT (DW_AT_count, 0x37) DW_AT (DW_AT_data_member_location, 0x38) DW_AT (DW_AT_decl_column, 0x39) DW_AT (DW_AT_decl_file, 0x3a) DW_AT (DW_AT_decl_line, 0x3b) DW_AT (DW_AT_declaration, 0x3c) DW_AT (DW_AT_discr_list, 0x3d) DW_AT (DW_AT_encoding, 0x3e) DW_AT (DW_AT_external, 0x3f) DW_AT (DW_AT_frame_base, 0x40) DW_AT (DW_AT_friend, 0x41) DW_AT (DW_AT_identifier_case, 0x42) DW_AT (DW_AT_macro_info, 0x43) DW_AT (DW_AT_namelist_items, 0x44) DW_AT (DW_AT_priority, 0x45) DW_AT (DW_AT_segment, 0x46) DW_AT (DW_AT_specification, 0x47) DW_AT (DW_AT_static_link, 0x48) DW_AT (DW_AT_type, 0x49) DW_AT (DW_AT_use_location, 0x4a) DW_AT (DW_AT_variable_parameter, 0x4b) DW_AT (DW_AT_virtuality, 0x4c) DW_AT (DW_AT_vtable_elem_location, 0x4d) /* DWARF 3 values. */ DW_AT (DW_AT_allocated, 0x4e) DW_AT (DW_AT_associated, 0x4f) DW_AT (DW_AT_data_location, 0x50) DW_AT (DW_AT_byte_stride, 0x51) DW_AT (DW_AT_entry_pc, 0x52) DW_AT (DW_AT_use_UTF8, 0x53) DW_AT (DW_AT_extension, 0x54) DW_AT (DW_AT_ranges, 0x55) DW_AT (DW_AT_trampoline, 0x56) DW_AT (DW_AT_call_column, 0x57) DW_AT (DW_AT_call_file, 0x58) DW_AT (DW_AT_call_line, 0x59) DW_AT (DW_AT_description, 0x5a) DW_AT (DW_AT_binary_scale, 0x5b) DW_AT (DW_AT_decimal_scale, 0x5c) DW_AT (DW_AT_small, 0x5d) DW_AT (DW_AT_decimal_sign, 0x5e) DW_AT (DW_AT_digit_count, 0x5f) DW_AT (DW_AT_picture_string, 0x60) DW_AT (DW_AT_mutable, 0x61) DW_AT (DW_AT_threads_scaled, 0x62) DW_AT (DW_AT_explicit, 0x63) DW_AT (DW_AT_object_pointer, 0x64) DW_AT (DW_AT_endianity, 0x65) DW_AT (DW_AT_elemental, 0x66) DW_AT (DW_AT_pure, 0x67) DW_AT (DW_AT_recursive, 0x68) /* DWARF 4. */ DW_AT (DW_AT_signature, 0x69) DW_AT (DW_AT_main_subprogram, 0x6a) DW_AT (DW_AT_data_bit_offset, 0x6b) DW_AT (DW_AT_const_expr, 0x6c) DW_AT (DW_AT_enum_class, 0x6d) DW_AT (DW_AT_linkage_name, 0x6e) /* DWARF 5. */ DW_AT (DW_AT_string_length_bit_size, 0x6f) DW_AT (DW_AT_string_length_byte_size, 0x70) DW_AT (DW_AT_rank, 0x71) DW_AT (DW_AT_str_offsets_base, 0x72) DW_AT (DW_AT_addr_base, 0x73) DW_AT (DW_AT_rnglists_base, 0x74) DW_AT (DW_AT_dwo_name, 0x76) DW_AT (DW_AT_reference, 0x77) DW_AT (DW_AT_rvalue_reference, 0x78) DW_AT (DW_AT_macros, 0x79) DW_AT (DW_AT_call_all_calls, 0x7a) DW_AT (DW_AT_call_all_source_calls, 0x7b) DW_AT (DW_AT_call_all_tail_calls, 0x7c) DW_AT (DW_AT_call_return_pc, 0x7d) DW_AT (DW_AT_call_value, 0x7e) DW_AT (DW_AT_call_origin, 0x7f) DW_AT (DW_AT_call_parameter, 0x80) DW_AT (DW_AT_call_pc, 0x81) DW_AT (DW_AT_call_tail_call, 0x82) DW_AT (DW_AT_call_target, 0x83) DW_AT (DW_AT_call_target_clobbered, 0x84) DW_AT (DW_AT_call_data_location, 0x85) DW_AT (DW_AT_call_data_value, 0x86) DW_AT (DW_AT_noreturn, 0x87) DW_AT (DW_AT_alignment, 0x88) DW_AT (DW_AT_export_symbols, 0x89) DW_AT (DW_AT_deleted, 0x8a) DW_AT (DW_AT_defaulted, 0x8b) DW_AT (DW_AT_loclists_base, 0x8c) DW_AT_DUP (DW_AT_lo_user, 0x2000) /* Implementation-defined range start. */ DW_AT_DUP (DW_AT_hi_user, 0x3fff) /* Implementation-defined range end. */ /* SGI/MIPS extensions. */ DW_AT (DW_AT_MIPS_fde, 0x2001) DW_AT (DW_AT_MIPS_loop_begin, 0x2002) DW_AT (DW_AT_MIPS_tail_loop_begin, 0x2003) DW_AT (DW_AT_MIPS_epilog_begin, 0x2004) DW_AT (DW_AT_MIPS_loop_unroll_factor, 0x2005) DW_AT (DW_AT_MIPS_software_pipeline_depth, 0x2006) DW_AT (DW_AT_MIPS_linkage_name, 0x2007) DW_AT (DW_AT_MIPS_stride, 0x2008) DW_AT (DW_AT_MIPS_abstract_name, 0x2009) DW_AT (DW_AT_MIPS_clone_origin, 0x200a) DW_AT (DW_AT_MIPS_has_inlines, 0x200b) /* HP extensions. */ DW_AT (DW_AT_HP_block_index, 0x2000) DW_AT_DUP (DW_AT_HP_unmodifiable, 0x2001) /* Same as DW_AT_MIPS_fde. */ DW_AT_DUP (DW_AT_HP_prologue, 0x2005) /* Same as DW_AT_MIPS_loop_unroll. */ DW_AT_DUP (DW_AT_HP_epilogue, 0x2008) /* Same as DW_AT_MIPS_stride. */ DW_AT (DW_AT_HP_actuals_stmt_list, 0x2010) DW_AT (DW_AT_HP_proc_per_section, 0x2011) DW_AT (DW_AT_HP_raw_data_ptr, 0x2012) DW_AT (DW_AT_HP_pass_by_reference, 0x2013) DW_AT (DW_AT_HP_opt_level, 0x2014) DW_AT (DW_AT_HP_prof_version_id, 0x2015) DW_AT (DW_AT_HP_opt_flags, 0x2016) DW_AT (DW_AT_HP_cold_region_low_pc, 0x2017) DW_AT (DW_AT_HP_cold_region_high_pc, 0x2018) DW_AT (DW_AT_HP_all_variables_modifiable, 0x2019) DW_AT (DW_AT_HP_linkage_name, 0x201a) DW_AT (DW_AT_HP_prof_flags, 0x201b) /* In comp unit of procs_info for -g. */ DW_AT (DW_AT_HP_unit_name, 0x201f) DW_AT (DW_AT_HP_unit_size, 0x2020) DW_AT (DW_AT_HP_widened_byte_size, 0x2021) DW_AT (DW_AT_HP_definition_points, 0x2022) DW_AT (DW_AT_HP_default_location, 0x2023) DW_AT (DW_AT_HP_is_result_param, 0x2029) /* GNU extensions. */ DW_AT (DW_AT_sf_names, 0x2101) DW_AT (DW_AT_src_info, 0x2102) DW_AT (DW_AT_mac_info, 0x2103) DW_AT (DW_AT_src_coords, 0x2104) DW_AT (DW_AT_body_begin, 0x2105) DW_AT (DW_AT_body_end, 0x2106) DW_AT (DW_AT_GNU_vector, 0x2107) /* Thread-safety annotations. See http://gcc.gnu.org/wiki/ThreadSafetyAnnotation . */ DW_AT (DW_AT_GNU_guarded_by, 0x2108) DW_AT (DW_AT_GNU_pt_guarded_by, 0x2109) DW_AT (DW_AT_GNU_guarded, 0x210a) DW_AT (DW_AT_GNU_pt_guarded, 0x210b) DW_AT (DW_AT_GNU_locks_excluded, 0x210c) DW_AT (DW_AT_GNU_exclusive_locks_required, 0x210d) DW_AT (DW_AT_GNU_shared_locks_required, 0x210e) /* One-definition rule violation detection. See http://gcc.gnu.org/wiki/DwarfSeparateTypeInfo . */ DW_AT (DW_AT_GNU_odr_signature, 0x210f) /* Template template argument name. See http://gcc.gnu.org/wiki/TemplateParmsDwarf . */ DW_AT (DW_AT_GNU_template_name, 0x2110) /* The GNU call site extension. See http://www.dwarfstd.org/ShowIssue.php?issue=100909.2&type=open . */ DW_AT (DW_AT_GNU_call_site_value, 0x2111) DW_AT (DW_AT_GNU_call_site_data_value, 0x2112) DW_AT (DW_AT_GNU_call_site_target, 0x2113) DW_AT (DW_AT_GNU_call_site_target_clobbered, 0x2114) DW_AT (DW_AT_GNU_tail_call, 0x2115) DW_AT (DW_AT_GNU_all_tail_call_sites, 0x2116) DW_AT (DW_AT_GNU_all_call_sites, 0x2117) DW_AT (DW_AT_GNU_all_source_call_sites, 0x2118) /* Section offset into .debug_macro section. */ DW_AT (DW_AT_GNU_macros, 0x2119) /* Attribute for C++ deleted special member functions (= delete;). */ DW_AT (DW_AT_GNU_deleted, 0x211a) /* Extensions for Fission. See http://gcc.gnu.org/wiki/DebugFission. */ DW_AT (DW_AT_GNU_dwo_name, 0x2130) DW_AT (DW_AT_GNU_dwo_id, 0x2131) DW_AT (DW_AT_GNU_ranges_base, 0x2132) DW_AT (DW_AT_GNU_addr_base, 0x2133) DW_AT (DW_AT_GNU_pubnames, 0x2134) DW_AT (DW_AT_GNU_pubtypes, 0x2135) /* Attribute for discriminator. See http://gcc.gnu.org/wiki/Discriminator */ DW_AT (DW_AT_GNU_discriminator, 0x2136) /* VMS extensions. */ DW_AT (DW_AT_VMS_rtnbeg_pd_address, 0x2201) /* GNAT extensions. */ /* GNAT descriptive type. See http://gcc.gnu.org/wiki/DW_AT_GNAT_descriptive_type . */ DW_AT (DW_AT_use_GNAT_descriptive_type, 0x2301) DW_AT (DW_AT_GNAT_descriptive_type, 0x2302) /* Rational constant extension. See https://gcc.gnu.org/wiki/DW_AT_GNU_numerator_denominator . */ DW_TAG (DW_AT_GNU_numerator, 0x2303) DW_TAG (DW_AT_GNU_denominator, 0x2304) /* Biased integer extension. See https://gcc.gnu.org/wiki/DW_AT_GNU_bias . */ DW_TAG (DW_AT_GNU_bias, 0x2305) /* UPC extension. */ DW_AT (DW_AT_upc_threads_scaled, 0x3210) /* PGI (STMicroelectronics) extensions. */ DW_AT (DW_AT_PGI_lbase, 0x3a00) DW_AT (DW_AT_PGI_soffset, 0x3a01) DW_AT (DW_AT_PGI_lstride, 0x3a02) /* Apple extensions. */ DW_AT (DW_AT_APPLE_optimized, 0x3fe1) DW_AT (DW_AT_APPLE_flags, 0x3fe2) DW_AT (DW_AT_APPLE_isa, 0x3fe3) DW_AT (DW_AT_APPLE_block, 0x3fe4) DW_AT (DW_AT_APPLE_major_runtime_vers, 0x3fe5) DW_AT (DW_AT_APPLE_runtime_class, 0x3fe6) DW_AT (DW_AT_APPLE_omit_frame_ptr, 0x3fe7) DW_AT (DW_AT_APPLE_property_name, 0x3fe8) DW_AT (DW_AT_APPLE_property_getter, 0x3fe9) DW_AT (DW_AT_APPLE_property_setter, 0x3fea) DW_AT (DW_AT_APPLE_property_attribute, 0x3feb) DW_AT (DW_AT_APPLE_objc_complete_type, 0x3fec) DW_AT (DW_AT_APPLE_property, 0x3fed) DW_END_AT DW_FIRST_OP (DW_OP_addr, 0x03) DW_OP (DW_OP_deref, 0x06) DW_OP (DW_OP_const1u, 0x08) DW_OP (DW_OP_const1s, 0x09) DW_OP (DW_OP_const2u, 0x0a) DW_OP (DW_OP_const2s, 0x0b) DW_OP (DW_OP_const4u, 0x0c) DW_OP (DW_OP_const4s, 0x0d) DW_OP (DW_OP_const8u, 0x0e) DW_OP (DW_OP_const8s, 0x0f) DW_OP (DW_OP_constu, 0x10) DW_OP (DW_OP_consts, 0x11) DW_OP (DW_OP_dup, 0x12) DW_OP (DW_OP_drop, 0x13) DW_OP (DW_OP_over, 0x14) DW_OP (DW_OP_pick, 0x15) DW_OP (DW_OP_swap, 0x16) DW_OP (DW_OP_rot, 0x17) DW_OP (DW_OP_xderef, 0x18) DW_OP (DW_OP_abs, 0x19) DW_OP (DW_OP_and, 0x1a) DW_OP (DW_OP_div, 0x1b) DW_OP (DW_OP_minus, 0x1c) DW_OP (DW_OP_mod, 0x1d) DW_OP (DW_OP_mul, 0x1e) DW_OP (DW_OP_neg, 0x1f) DW_OP (DW_OP_not, 0x20) DW_OP (DW_OP_or, 0x21) DW_OP (DW_OP_plus, 0x22) DW_OP (DW_OP_plus_uconst, 0x23) DW_OP (DW_OP_shl, 0x24) DW_OP (DW_OP_shr, 0x25) DW_OP (DW_OP_shra, 0x26) DW_OP (DW_OP_xor, 0x27) DW_OP (DW_OP_bra, 0x28) DW_OP (DW_OP_eq, 0x29) DW_OP (DW_OP_ge, 0x2a) DW_OP (DW_OP_gt, 0x2b) DW_OP (DW_OP_le, 0x2c) DW_OP (DW_OP_lt, 0x2d) DW_OP (DW_OP_ne, 0x2e) DW_OP (DW_OP_skip, 0x2f) DW_OP (DW_OP_lit0, 0x30) DW_OP (DW_OP_lit1, 0x31) DW_OP (DW_OP_lit2, 0x32) DW_OP (DW_OP_lit3, 0x33) DW_OP (DW_OP_lit4, 0x34) DW_OP (DW_OP_lit5, 0x35) DW_OP (DW_OP_lit6, 0x36) DW_OP (DW_OP_lit7, 0x37) DW_OP (DW_OP_lit8, 0x38) DW_OP (DW_OP_lit9, 0x39) DW_OP (DW_OP_lit10, 0x3a) DW_OP (DW_OP_lit11, 0x3b) DW_OP (DW_OP_lit12, 0x3c) DW_OP (DW_OP_lit13, 0x3d) DW_OP (DW_OP_lit14, 0x3e) DW_OP (DW_OP_lit15, 0x3f) DW_OP (DW_OP_lit16, 0x40) DW_OP (DW_OP_lit17, 0x41) DW_OP (DW_OP_lit18, 0x42) DW_OP (DW_OP_lit19, 0x43) DW_OP (DW_OP_lit20, 0x44) DW_OP (DW_OP_lit21, 0x45) DW_OP (DW_OP_lit22, 0x46) DW_OP (DW_OP_lit23, 0x47) DW_OP (DW_OP_lit24, 0x48) DW_OP (DW_OP_lit25, 0x49) DW_OP (DW_OP_lit26, 0x4a) DW_OP (DW_OP_lit27, 0x4b) DW_OP (DW_OP_lit28, 0x4c) DW_OP (DW_OP_lit29, 0x4d) DW_OP (DW_OP_lit30, 0x4e) DW_OP (DW_OP_lit31, 0x4f) DW_OP (DW_OP_reg0, 0x50) DW_OP (DW_OP_reg1, 0x51) DW_OP (DW_OP_reg2, 0x52) DW_OP (DW_OP_reg3, 0x53) DW_OP (DW_OP_reg4, 0x54) DW_OP (DW_OP_reg5, 0x55) DW_OP (DW_OP_reg6, 0x56) DW_OP (DW_OP_reg7, 0x57) DW_OP (DW_OP_reg8, 0x58) DW_OP (DW_OP_reg9, 0x59) DW_OP (DW_OP_reg10, 0x5a) DW_OP (DW_OP_reg11, 0x5b) DW_OP (DW_OP_reg12, 0x5c) DW_OP (DW_OP_reg13, 0x5d) DW_OP (DW_OP_reg14, 0x5e) DW_OP (DW_OP_reg15, 0x5f) DW_OP (DW_OP_reg16, 0x60) DW_OP (DW_OP_reg17, 0x61) DW_OP (DW_OP_reg18, 0x62) DW_OP (DW_OP_reg19, 0x63) DW_OP (DW_OP_reg20, 0x64) DW_OP (DW_OP_reg21, 0x65) DW_OP (DW_OP_reg22, 0x66) DW_OP (DW_OP_reg23, 0x67) DW_OP (DW_OP_reg24, 0x68) DW_OP (DW_OP_reg25, 0x69) DW_OP (DW_OP_reg26, 0x6a) DW_OP (DW_OP_reg27, 0x6b) DW_OP (DW_OP_reg28, 0x6c) DW_OP (DW_OP_reg29, 0x6d) DW_OP (DW_OP_reg30, 0x6e) DW_OP (DW_OP_reg31, 0x6f) DW_OP (DW_OP_breg0, 0x70) DW_OP (DW_OP_breg1, 0x71) DW_OP (DW_OP_breg2, 0x72) DW_OP (DW_OP_breg3, 0x73) DW_OP (DW_OP_breg4, 0x74) DW_OP (DW_OP_breg5, 0x75) DW_OP (DW_OP_breg6, 0x76) DW_OP (DW_OP_breg7, 0x77) DW_OP (DW_OP_breg8, 0x78) DW_OP (DW_OP_breg9, 0x79) DW_OP (DW_OP_breg10, 0x7a) DW_OP (DW_OP_breg11, 0x7b) DW_OP (DW_OP_breg12, 0x7c) DW_OP (DW_OP_breg13, 0x7d) DW_OP (DW_OP_breg14, 0x7e) DW_OP (DW_OP_breg15, 0x7f) DW_OP (DW_OP_breg16, 0x80) DW_OP (DW_OP_breg17, 0x81) DW_OP (DW_OP_breg18, 0x82) DW_OP (DW_OP_breg19, 0x83) DW_OP (DW_OP_breg20, 0x84) DW_OP (DW_OP_breg21, 0x85) DW_OP (DW_OP_breg22, 0x86) DW_OP (DW_OP_breg23, 0x87) DW_OP (DW_OP_breg24, 0x88) DW_OP (DW_OP_breg25, 0x89) DW_OP (DW_OP_breg26, 0x8a) DW_OP (DW_OP_breg27, 0x8b) DW_OP (DW_OP_breg28, 0x8c) DW_OP (DW_OP_breg29, 0x8d) DW_OP (DW_OP_breg30, 0x8e) DW_OP (DW_OP_breg31, 0x8f) DW_OP (DW_OP_regx, 0x90) DW_OP (DW_OP_fbreg, 0x91) DW_OP (DW_OP_bregx, 0x92) DW_OP (DW_OP_piece, 0x93) DW_OP (DW_OP_deref_size, 0x94) DW_OP (DW_OP_xderef_size, 0x95) DW_OP (DW_OP_nop, 0x96) /* DWARF 3 extensions. */ DW_OP (DW_OP_push_object_address, 0x97) DW_OP (DW_OP_call2, 0x98) DW_OP (DW_OP_call4, 0x99) DW_OP (DW_OP_call_ref, 0x9a) DW_OP (DW_OP_form_tls_address, 0x9b) DW_OP (DW_OP_call_frame_cfa, 0x9c) DW_OP (DW_OP_bit_piece, 0x9d) /* DWARF 4 extensions. */ DW_OP (DW_OP_implicit_value, 0x9e) DW_OP (DW_OP_stack_value, 0x9f) /* DWARF 5 extensions. */ DW_OP (DW_OP_implicit_pointer, 0xa0) DW_OP (DW_OP_addrx, 0xa1) DW_OP (DW_OP_constx, 0xa2) DW_OP (DW_OP_entry_value, 0xa3) DW_OP (DW_OP_const_type, 0xa4) DW_OP (DW_OP_regval_type, 0xa5) DW_OP (DW_OP_deref_type, 0xa6) DW_OP (DW_OP_xderef_type, 0xa7) DW_OP (DW_OP_convert, 0xa8) DW_OP (DW_OP_reinterpret, 0xa9) DW_OP_DUP (DW_OP_lo_user, 0xe0) /* Implementation-defined range start. */ DW_OP_DUP (DW_OP_hi_user, 0xff) /* Implementation-defined range end. */ /* GNU extensions. */ DW_OP (DW_OP_GNU_push_tls_address, 0xe0) /* The following is for marking variables that are uninitialized. */ DW_OP (DW_OP_GNU_uninit, 0xf0) DW_OP (DW_OP_GNU_encoded_addr, 0xf1) /* The GNU implicit pointer extension. See http://www.dwarfstd.org/ShowIssue.php?issue=100831.1&type=open . */ DW_OP (DW_OP_GNU_implicit_pointer, 0xf2) /* The GNU entry value extension. See http://www.dwarfstd.org/ShowIssue.php?issue=100909.1&type=open . */ DW_OP (DW_OP_GNU_entry_value, 0xf3) /* The GNU typed stack extension. See http://www.dwarfstd.org/doc/040408.1.html . */ DW_OP (DW_OP_GNU_const_type, 0xf4) DW_OP (DW_OP_GNU_regval_type, 0xf5) DW_OP (DW_OP_GNU_deref_type, 0xf6) DW_OP (DW_OP_GNU_convert, 0xf7) DW_OP (DW_OP_GNU_reinterpret, 0xf9) /* The GNU parameter ref extension. */ DW_OP (DW_OP_GNU_parameter_ref, 0xfa) /* Extensions for Fission. See http://gcc.gnu.org/wiki/DebugFission. */ DW_OP (DW_OP_GNU_addr_index, 0xfb) DW_OP (DW_OP_GNU_const_index, 0xfc) /* HP extensions. */ DW_OP_DUP (DW_OP_HP_unknown, 0xe0) /* Ouch, the same as GNU_push_tls_address. */ DW_OP (DW_OP_HP_is_value, 0xe1) DW_OP (DW_OP_HP_fltconst4, 0xe2) DW_OP (DW_OP_HP_fltconst8, 0xe3) DW_OP (DW_OP_HP_mod_range, 0xe4) DW_OP (DW_OP_HP_unmod_range, 0xe5) DW_OP (DW_OP_HP_tls, 0xe6) /* PGI (STMicroelectronics) extensions. */ DW_OP (DW_OP_PGI_omp_thread_num, 0xf8) DW_END_OP DW_FIRST_ATE (DW_ATE_void, 0x0) DW_ATE (DW_ATE_address, 0x1) DW_ATE (DW_ATE_boolean, 0x2) DW_ATE (DW_ATE_complex_float, 0x3) DW_ATE (DW_ATE_float, 0x4) DW_ATE (DW_ATE_signed, 0x5) DW_ATE (DW_ATE_signed_char, 0x6) DW_ATE (DW_ATE_unsigned, 0x7) DW_ATE (DW_ATE_unsigned_char, 0x8) /* DWARF 3. */ DW_ATE (DW_ATE_imaginary_float, 0x9) DW_ATE (DW_ATE_packed_decimal, 0xa) DW_ATE (DW_ATE_numeric_string, 0xb) DW_ATE (DW_ATE_edited, 0xc) DW_ATE (DW_ATE_signed_fixed, 0xd) DW_ATE (DW_ATE_unsigned_fixed, 0xe) DW_ATE (DW_ATE_decimal_float, 0xf) /* DWARF 4. */ DW_ATE (DW_ATE_UTF, 0x10) /* DWARF 5. */ DW_ATE (DW_ATE_UCS, 0x11) DW_ATE (DW_ATE_ASCII, 0x12) DW_ATE_DUP (DW_ATE_lo_user, 0x80) DW_ATE_DUP (DW_ATE_hi_user, 0xff) /* HP extensions. */ DW_ATE (DW_ATE_HP_float80, 0x80) /* Floating-point (80 bit). */ DW_ATE (DW_ATE_HP_complex_float80, 0x81) /* Complex floating-point (80 bit). */ DW_ATE (DW_ATE_HP_float128, 0x82) /* Floating-point (128 bit). */ DW_ATE (DW_ATE_HP_complex_float128, 0x83) /* Complex fp (128 bit). */ DW_ATE (DW_ATE_HP_floathpintel, 0x84) /* Floating-point (82 bit IA64). */ DW_ATE (DW_ATE_HP_imaginary_float80, 0x85) DW_ATE (DW_ATE_HP_imaginary_float128, 0x86) DW_ATE (DW_ATE_HP_VAX_float, 0x88) /* F or G floating. */ DW_ATE (DW_ATE_HP_VAX_float_d, 0x89) /* D floating. */ DW_ATE (DW_ATE_HP_packed_decimal, 0x8a) /* Cobol. */ DW_ATE (DW_ATE_HP_zoned_decimal, 0x8b) /* Cobol. */ DW_ATE (DW_ATE_HP_edited, 0x8c) /* Cobol. */ DW_ATE (DW_ATE_HP_signed_fixed, 0x8d) /* Cobol. */ DW_ATE (DW_ATE_HP_unsigned_fixed, 0x8e) /* Cobol. */ DW_ATE (DW_ATE_HP_VAX_complex_float, 0x8f) /* F or G floating complex. */ DW_ATE (DW_ATE_HP_VAX_complex_float_d, 0x90) /* D floating complex. */ DW_END_ATE DW_FIRST_CFA (DW_CFA_advance_loc, 0x40) DW_CFA (DW_CFA_offset, 0x80) DW_CFA (DW_CFA_restore, 0xc0) DW_CFA (DW_CFA_nop, 0x00) DW_CFA (DW_CFA_set_loc, 0x01) DW_CFA (DW_CFA_advance_loc1, 0x02) DW_CFA (DW_CFA_advance_loc2, 0x03) DW_CFA (DW_CFA_advance_loc4, 0x04) DW_CFA (DW_CFA_offset_extended, 0x05) DW_CFA (DW_CFA_restore_extended, 0x06) DW_CFA (DW_CFA_undefined, 0x07) DW_CFA (DW_CFA_same_value, 0x08) DW_CFA (DW_CFA_register, 0x09) DW_CFA (DW_CFA_remember_state, 0x0a) DW_CFA (DW_CFA_restore_state, 0x0b) DW_CFA (DW_CFA_def_cfa, 0x0c) DW_CFA (DW_CFA_def_cfa_register, 0x0d) DW_CFA (DW_CFA_def_cfa_offset, 0x0e) /* DWARF 3. */ DW_CFA (DW_CFA_def_cfa_expression, 0x0f) DW_CFA (DW_CFA_expression, 0x10) DW_CFA (DW_CFA_offset_extended_sf, 0x11) DW_CFA (DW_CFA_def_cfa_sf, 0x12) DW_CFA (DW_CFA_def_cfa_offset_sf, 0x13) DW_CFA (DW_CFA_val_offset, 0x14) DW_CFA (DW_CFA_val_offset_sf, 0x15) DW_CFA (DW_CFA_val_expression, 0x16) DW_CFA (DW_CFA_lo_user, 0x1c) DW_CFA (DW_CFA_hi_user, 0x3f) /* SGI/MIPS specific. */ DW_CFA (DW_CFA_MIPS_advance_loc8, 0x1d) /* GNU extensions. */ DW_CFA (DW_CFA_GNU_window_save, 0x2d) DW_CFA (DW_CFA_GNU_args_size, 0x2e) DW_CFA (DW_CFA_GNU_negative_offset_extended, 0x2f) DW_END_CFA vendor/backtrace-sys-0.1.16/src/libbacktrace/dwarf2.h0000664000000000000000000003503013264166600021067 0ustar rootroot/* Declarations and definitions of codes relating to the DWARF2 and DWARF3 symbolic debugging information formats. Copyright (C) 1992-2016 Free Software Foundation, Inc. Written by Gary Funck (gary@intrepid.com) The Ada Joint Program Office (AJPO), Florida State University and Silicon Graphics Inc. provided support for this effort -- June 21, 1995. Derived from the DWARF 1 implementation written by Ron Guilmette (rfg@netcom.com), November 1990. This file is part of GCC. GCC 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, or (at your option) any later version. GCC 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. Under Section 7 of GPL version 3, you are granted additional permissions described in the GCC Runtime Library Exception, version 3.1, as published by the Free Software Foundation. You should have received a copy of the GNU General Public License and a copy of the GCC Runtime Library Exception along with this program; see the files COPYING3 and COPYING.RUNTIME respectively. If not, see . */ /* This file is derived from the DWARF specification (a public document) Revision 2.0.0 (July 27, 1993) developed by the UNIX International Programming Languages Special Interest Group (UI/PLSIG) and distributed by UNIX International. Copies of this specification are available from UNIX International, 20 Waterview Boulevard, Parsippany, NJ, 07054. This file also now contains definitions from the DWARF 3 specification published Dec 20, 2005, available from: http://dwarf.freestandards.org. */ #ifndef _DWARF2_H #define _DWARF2_H #define DW_TAG(name, value) , name = value #define DW_TAG_DUP(name, value) , name = value #define DW_FORM(name, value) , name = value #define DW_AT(name, value) , name = value #define DW_AT_DUP(name, value) , name = value #define DW_OP(name, value) , name = value #define DW_OP_DUP(name, value) , name = value #define DW_ATE(name, value) , name = value #define DW_ATE_DUP(name, value) , name = value #define DW_CFA(name, value) , name = value #define DW_FIRST_TAG(name, value) enum dwarf_tag { \ name = value #define DW_END_TAG }; #define DW_FIRST_FORM(name, value) enum dwarf_form { \ name = value #define DW_END_FORM }; #define DW_FIRST_AT(name, value) enum dwarf_attribute { \ name = value #define DW_END_AT }; #define DW_FIRST_OP(name, value) enum dwarf_location_atom { \ name = value #define DW_END_OP }; #define DW_FIRST_ATE(name, value) enum dwarf_type { \ name = value #define DW_END_ATE }; #define DW_FIRST_CFA(name, value) enum dwarf_call_frame_info { \ name = value #define DW_END_CFA }; #include "dwarf2.def" #undef DW_FIRST_TAG #undef DW_END_TAG #undef DW_FIRST_FORM #undef DW_END_FORM #undef DW_FIRST_AT #undef DW_END_AT #undef DW_FIRST_OP #undef DW_END_OP #undef DW_FIRST_ATE #undef DW_END_ATE #undef DW_FIRST_CFA #undef DW_END_CFA #undef DW_TAG #undef DW_TAG_DUP #undef DW_FORM #undef DW_AT #undef DW_AT_DUP #undef DW_OP #undef DW_OP_DUP #undef DW_ATE #undef DW_ATE_DUP #undef DW_CFA /* Flag that tells whether entry has a child or not. */ #define DW_children_no 0 #define DW_children_yes 1 #define DW_AT_stride_size DW_AT_bit_stride /* Note: The use of DW_AT_stride_size is deprecated. */ #define DW_AT_stride DW_AT_byte_stride /* Note: The use of DW_AT_stride is deprecated. */ /* Decimal sign encodings. */ enum dwarf_decimal_sign_encoding { /* DWARF 3. */ DW_DS_unsigned = 0x01, DW_DS_leading_overpunch = 0x02, DW_DS_trailing_overpunch = 0x03, DW_DS_leading_separate = 0x04, DW_DS_trailing_separate = 0x05 }; /* Endianity encodings. */ enum dwarf_endianity_encoding { /* DWARF 3. */ DW_END_default = 0x00, DW_END_big = 0x01, DW_END_little = 0x02, DW_END_lo_user = 0x40, DW_END_hi_user = 0xff }; /* Array ordering names and codes. */ enum dwarf_array_dim_ordering { DW_ORD_row_major = 0, DW_ORD_col_major = 1 }; /* Access attribute. */ enum dwarf_access_attribute { DW_ACCESS_public = 1, DW_ACCESS_protected = 2, DW_ACCESS_private = 3 }; /* Visibility. */ enum dwarf_visibility_attribute { DW_VIS_local = 1, DW_VIS_exported = 2, DW_VIS_qualified = 3 }; /* Virtuality. */ enum dwarf_virtuality_attribute { DW_VIRTUALITY_none = 0, DW_VIRTUALITY_virtual = 1, DW_VIRTUALITY_pure_virtual = 2 }; /* Case sensitivity. */ enum dwarf_id_case { DW_ID_case_sensitive = 0, DW_ID_up_case = 1, DW_ID_down_case = 2, DW_ID_case_insensitive = 3 }; /* Calling convention. */ enum dwarf_calling_convention { DW_CC_normal = 0x1, DW_CC_program = 0x2, DW_CC_nocall = 0x3, /* DWARF 5. */ DW_CC_pass_by_reference = 0x4, DW_CC_pass_by_value = 0x5, DW_CC_lo_user = 0x40, DW_CC_hi_user = 0xff, DW_CC_GNU_renesas_sh = 0x40, DW_CC_GNU_borland_fastcall_i386 = 0x41, /* This DW_CC_ value is not currently generated by any toolchain. It is used internally to GDB to indicate OpenCL C functions that have been compiled with the IBM XL C for OpenCL compiler and use a non-platform calling convention for passing OpenCL C vector types. This value may be changed freely as long as it does not conflict with any other DW_CC_ value defined here. */ DW_CC_GDB_IBM_OpenCL = 0xff }; /* Inline attribute. */ enum dwarf_inline_attribute { DW_INL_not_inlined = 0, DW_INL_inlined = 1, DW_INL_declared_not_inlined = 2, DW_INL_declared_inlined = 3 }; /* Discriminant lists. */ enum dwarf_discrim_list { DW_DSC_label = 0, DW_DSC_range = 1 }; /* Line number opcodes. */ enum dwarf_line_number_ops { DW_LNS_extended_op = 0, DW_LNS_copy = 1, DW_LNS_advance_pc = 2, DW_LNS_advance_line = 3, DW_LNS_set_file = 4, DW_LNS_set_column = 5, DW_LNS_negate_stmt = 6, DW_LNS_set_basic_block = 7, DW_LNS_const_add_pc = 8, DW_LNS_fixed_advance_pc = 9, /* DWARF 3. */ DW_LNS_set_prologue_end = 10, DW_LNS_set_epilogue_begin = 11, DW_LNS_set_isa = 12 }; /* Line number extended opcodes. */ enum dwarf_line_number_x_ops { DW_LNE_end_sequence = 1, DW_LNE_set_address = 2, DW_LNE_define_file = 3, DW_LNE_set_discriminator = 4, /* HP extensions. */ DW_LNE_HP_negate_is_UV_update = 0x11, DW_LNE_HP_push_context = 0x12, DW_LNE_HP_pop_context = 0x13, DW_LNE_HP_set_file_line_column = 0x14, DW_LNE_HP_set_routine_name = 0x15, DW_LNE_HP_set_sequence = 0x16, DW_LNE_HP_negate_post_semantics = 0x17, DW_LNE_HP_negate_function_exit = 0x18, DW_LNE_HP_negate_front_end_logical = 0x19, DW_LNE_HP_define_proc = 0x20, DW_LNE_HP_source_file_correlation = 0x80, DW_LNE_lo_user = 0x80, DW_LNE_hi_user = 0xff }; /* Sub-opcodes for DW_LNE_HP_source_file_correlation. */ enum dwarf_line_number_hp_sfc_ops { DW_LNE_HP_SFC_formfeed = 1, DW_LNE_HP_SFC_set_listing_line = 2, DW_LNE_HP_SFC_associate = 3 }; /* Content type codes in line table directory_entry_format and file_name_entry_format sequences. */ enum dwarf_line_number_content_type { DW_LNCT_path = 0x1, DW_LNCT_directory_index = 0x2, DW_LNCT_timestamp = 0x3, DW_LNCT_size = 0x4, DW_LNCT_MD5 = 0x5, DW_LNCT_lo_user = 0x2000, DW_LNCT_hi_user = 0x3fff }; /* Type codes for location list entries. */ enum dwarf_location_list_entry_type { DW_LLE_end_of_list = 0x00, DW_LLE_base_addressx = 0x01, DW_LLE_startx_endx = 0x02, DW_LLE_startx_length = 0x03, DW_LLE_offset_pair = 0x04, DW_LLE_default_location = 0x05, DW_LLE_base_address = 0x06, DW_LLE_start_end = 0x07, DW_LLE_start_length = 0x08, /* Former extension for Fission. See http://gcc.gnu.org/wiki/DebugFission. */ DW_LLE_GNU_end_of_list_entry = 0x00, DW_LLE_GNU_base_address_selection_entry = 0x01, DW_LLE_GNU_start_end_entry = 0x02, DW_LLE_GNU_start_length_entry = 0x03 }; #define DW_CIE_ID 0xffffffff #define DW64_CIE_ID 0xffffffffffffffffULL #define DW_CIE_VERSION 1 #define DW_CFA_extended 0 #define DW_CHILDREN_no 0x00 #define DW_CHILDREN_yes 0x01 #define DW_ADDR_none 0 /* Source language names and codes. */ enum dwarf_source_language { DW_LANG_C89 = 0x0001, DW_LANG_C = 0x0002, DW_LANG_Ada83 = 0x0003, DW_LANG_C_plus_plus = 0x0004, DW_LANG_Cobol74 = 0x0005, DW_LANG_Cobol85 = 0x0006, DW_LANG_Fortran77 = 0x0007, DW_LANG_Fortran90 = 0x0008, DW_LANG_Pascal83 = 0x0009, DW_LANG_Modula2 = 0x000a, /* DWARF 3. */ DW_LANG_Java = 0x000b, DW_LANG_C99 = 0x000c, DW_LANG_Ada95 = 0x000d, DW_LANG_Fortran95 = 0x000e, DW_LANG_PLI = 0x000f, DW_LANG_ObjC = 0x0010, DW_LANG_ObjC_plus_plus = 0x0011, DW_LANG_UPC = 0x0012, DW_LANG_D = 0x0013, /* DWARF 4. */ DW_LANG_Python = 0x0014, /* DWARF 5. */ DW_LANG_OpenCL = 0x0015, DW_LANG_Go = 0x0016, DW_LANG_Modula3 = 0x0017, DW_LANG_Haskell = 0x0018, DW_LANG_C_plus_plus_03 = 0x0019, DW_LANG_C_plus_plus_11 = 0x001a, DW_LANG_OCaml = 0x001b, DW_LANG_Rust = 0x001c, DW_LANG_C11 = 0x001d, DW_LANG_Swift = 0x001e, DW_LANG_Julia = 0x001f, DW_LANG_Dylan = 0x0020, DW_LANG_C_plus_plus_14 = 0x0021, DW_LANG_Fortran03 = 0x0022, DW_LANG_Fortran08 = 0x0023, DW_LANG_RenderScript = 0x0024, DW_LANG_lo_user = 0x8000, /* Implementation-defined range start. */ DW_LANG_hi_user = 0xffff, /* Implementation-defined range start. */ /* MIPS. */ DW_LANG_Mips_Assembler = 0x8001, /* UPC. */ DW_LANG_Upc = 0x8765, /* HP extensions. */ DW_LANG_HP_Bliss = 0x8003, DW_LANG_HP_Basic91 = 0x8004, DW_LANG_HP_Pascal91 = 0x8005, DW_LANG_HP_IMacro = 0x8006, DW_LANG_HP_Assembler = 0x8007, /* Rust extension, but replaced in DWARF 5. */ DW_LANG_Rust_old = 0x9000 }; /* Names and codes for macro information. */ enum dwarf_macinfo_record_type { DW_MACINFO_define = 1, DW_MACINFO_undef = 2, DW_MACINFO_start_file = 3, DW_MACINFO_end_file = 4, DW_MACINFO_vendor_ext = 255 }; /* DW_TAG_defaulted/DW_TAG_GNU_defaulted attributes. */ enum dwarf_defaulted_attribute { DW_DEFAULTED_no = 0x00, DW_DEFAULTED_in_class = 0x01, DW_DEFAULTED_out_of_class = 0x02 }; /* Names and codes for new style macro information. */ enum dwarf_macro_record_type { DW_MACRO_define = 0x01, DW_MACRO_undef = 0x02, DW_MACRO_start_file = 0x03, DW_MACRO_end_file = 0x04, DW_MACRO_define_strp = 0x05, DW_MACRO_undef_strp = 0x06, DW_MACRO_import = 0x07, DW_MACRO_define_sup = 0x08, DW_MACRO_undef_sup = 0x09, DW_MACRO_import_sup = 0x0a, DW_MACRO_define_strx = 0x0b, DW_MACRO_undef_strx = 0x0c, DW_MACRO_lo_user = 0xe0, DW_MACRO_hi_user = 0xff, /* Compatibility macros for the GNU .debug_macro extension. */ DW_MACRO_GNU_define = 0x01, DW_MACRO_GNU_undef = 0x02, DW_MACRO_GNU_start_file = 0x03, DW_MACRO_GNU_end_file = 0x04, DW_MACRO_GNU_define_indirect = 0x05, DW_MACRO_GNU_undef_indirect = 0x06, DW_MACRO_GNU_transparent_include = 0x07, /* Extensions for DWZ multifile. See http://www.dwarfstd.org/ShowIssue.php?issue=120604.1&type=open . */ DW_MACRO_GNU_define_indirect_alt = 0x08, DW_MACRO_GNU_undef_indirect_alt = 0x09, DW_MACRO_GNU_transparent_include_alt = 0x0a, DW_MACRO_GNU_lo_user = 0xe0, DW_MACRO_GNU_hi_user = 0xff }; /* Index attributes in the Abbreviations Table. */ enum dwarf_name_index_attribute { DW_IDX_compile_unit = 1, DW_IDX_type_unit = 2, DW_IDX_die_offset = 3, DW_IDX_parent = 4, DW_IDX_type_hash = 5, DW_IDX_lo_user = 0x2000, DW_IDX_hi_user = 0x3fff }; /* Range list entry kinds in .debug_rnglists* section. */ enum dwarf_range_list_entry { DW_RLE_end_of_list = 0x00, DW_RLE_base_addressx = 0x01, DW_RLE_startx_endx = 0x02, DW_RLE_startx_length = 0x03, DW_RLE_offset_pair = 0x04, DW_RLE_base_address = 0x05, DW_RLE_start_end = 0x06, DW_RLE_start_length = 0x07 }; /* Unit types in unit_type unit header field. */ enum dwarf_unit_type { DW_UT_compile = 0x01, DW_UT_type = 0x02, DW_UT_partial = 0x03, DW_UT_skeleton = 0x04, DW_UT_split_compile = 0x05, DW_UT_split_type = 0x06, DW_UT_lo_user = 0x80, DW_UT_hi_user = 0xff }; /* @@@ For use with GNU frame unwind information. */ #define DW_EH_PE_absptr 0x00 #define DW_EH_PE_omit 0xff #define DW_EH_PE_uleb128 0x01 #define DW_EH_PE_udata2 0x02 #define DW_EH_PE_udata4 0x03 #define DW_EH_PE_udata8 0x04 #define DW_EH_PE_sleb128 0x09 #define DW_EH_PE_sdata2 0x0A #define DW_EH_PE_sdata4 0x0B #define DW_EH_PE_sdata8 0x0C #define DW_EH_PE_signed 0x08 #define DW_EH_PE_pcrel 0x10 #define DW_EH_PE_textrel 0x20 #define DW_EH_PE_datarel 0x30 #define DW_EH_PE_funcrel 0x40 #define DW_EH_PE_aligned 0x50 #define DW_EH_PE_indirect 0x80 /* Codes for the debug sections in a dwarf package (.dwp) file. Extensions for Fission. See http://gcc.gnu.org/wiki/DebugFissionDWP. */ enum dwarf_sect { DW_SECT_INFO = 1, DW_SECT_TYPES = 2, DW_SECT_ABBREV = 3, DW_SECT_LINE = 4, DW_SECT_LOC = 5, DW_SECT_STR_OFFSETS = 6, DW_SECT_MACINFO = 7, DW_SECT_MACRO = 8, DW_SECT_MAX = 8 }; #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /* Return the name of a DW_TAG_ constant, or NULL if the value is not recognized. */ extern const char *get_DW_TAG_name (unsigned int tag); /* Return the name of a DW_AT_ constant, or NULL if the value is not recognized. */ extern const char *get_DW_AT_name (unsigned int attr); /* Return the name of a DW_FORM_ constant, or NULL if the value is not recognized. */ extern const char *get_DW_FORM_name (unsigned int form); /* Return the name of a DW_OP_ constant, or NULL if the value is not recognized. */ extern const char *get_DW_OP_name (unsigned int op); /* Return the name of a DW_ATE_ constant, or NULL if the value is not recognized. */ extern const char *get_DW_ATE_name (unsigned int enc); /* Return the name of a DW_CFA_ constant, or NULL if the value is not recognized. */ extern const char *get_DW_CFA_name (unsigned int opc); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* _DWARF2_H */ vendor/backtrace-sys-0.1.16/src/libbacktrace/elf.c0000664000000000000000000006350713264166600020455 0ustar rootroot/* elf.c -- Get debug data from an ELF file for backtraces. 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. */ #include "config.h" #include #include #include #ifdef HAVE_DL_ITERATE_PHDR #include #endif #include "backtrace.h" #include "internal.h" #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 mode. */ #if BACKTRACE_ELF_SIZE != 32 && BACKTRACE_ELF_SIZE != 64 #error "Unknown BACKTRACE_ELF_SIZE" #endif /* might #include 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 SHN_LORESERVE #undef SHN_XINDEX #undef SHN_UNDEF #undef SHT_SYMTAB #undef SHT_STRTAB #undef SHT_DYNSYM #undef STT_OBJECT #undef STT_FUNC /* 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 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_SYMTAB 2 #define SHT_STRTAB 3 #define SHT_DYNSYM 11 #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 /* An index of ELF 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 elf_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 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; }; /* 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) { 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; elf_symbols[j].address = sym->st_value + 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); } /* 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, int descriptor, uintptr_t base_address, backtrace_error_callback error_callback, void *data, fileline *fileline_fn, int *found_sym, int *found_dwarf, int exe) { 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; off_t min_offset; off_t max_offset; struct backtrace_view debug_view; int debug_view_valid; *found_sym = 0; *found_dwarf = 0; shdrs_view_valid = 0; names_view_valid = 0; symtab_view_valid = 0; strtab_view_valid = 0; debug_view_valid = 0; 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; break; } } } if (symtab_shndx == 0) symtab_shndx = dynsym_shndx; if (symtab_shndx != 0) { 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)) { 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); *found_sym = 1; elf_add_syminfo_data (state, sdata); } /* FIXME: Need to handle compressed debug sections. */ 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; /* 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; 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, 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 (debug_view_valid) backtrace_release_view (state, &debug_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; 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; 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; 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; } descriptor = backtrace_open (info->dlpi_name, pd->error_callback, pd->data, &does_not_exist); if (descriptor < 0) return 0; } if (elf_add (pd->state, descriptor, info->dlpi_addr, pd->error_callback, pd->data, &elf_fileline_fn, pd->found_sym, &found_dwarf, 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, 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, descriptor, 0, error_callback, data, &elf_fileline_fn, &found_sym, &found_dwarf, 1); 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_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) { if (state->fileline_fn == NULL || state->fileline_fn == elf_nodebug) *fileline_fn = elf_fileline_fn; } else { fileline current_fn; current_fn = backtrace_atomic_load_pointer (&state->fileline_fn); if (current_fn == NULL || current_fn == elf_nodebug) *fileline_fn = elf_fileline_fn; } return 1; } vendor/backtrace-sys-0.1.16/src/libbacktrace/fileline.c0000664000000000000000000001170313264166600021465 0ustar rootroot/* fileline.c -- Get file and line number information in a backtrace. 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. */ #include "config.h" #include #include #include #include #include #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; 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 < 4; ++pass) { const char *filename; 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; 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, 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; } vendor/backtrace-sys-0.1.16/src/libbacktrace/filenames.h0000664000000000000000000000667313264166600021660 0ustar rootroot/* Macros for taking apart, interpreting and processing file names. These are here because some non-Posix (a.k.a. DOSish) systems have drive letter brain-damage at the beginning of an absolute file name, use forward- and back-slash in path names interchangeably, and some of them have case-insensitive file names. Copyright (C) 2000-2015 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. 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 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, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef FILENAMES_H #define FILENAMES_H #include "hashtab.h" /* for hashval_t */ #ifdef __cplusplus extern "C" { #endif #if defined(__MSDOS__) || defined(_WIN32) || defined(__OS2__) || defined (__CYGWIN__) # ifndef HAVE_DOS_BASED_FILE_SYSTEM # define HAVE_DOS_BASED_FILE_SYSTEM 1 # endif # ifndef HAVE_CASE_INSENSITIVE_FILE_SYSTEM # define HAVE_CASE_INSENSITIVE_FILE_SYSTEM 1 # endif # define HAS_DRIVE_SPEC(f) HAS_DOS_DRIVE_SPEC (f) # define IS_DIR_SEPARATOR(c) IS_DOS_DIR_SEPARATOR (c) # define IS_ABSOLUTE_PATH(f) IS_DOS_ABSOLUTE_PATH (f) #else /* not DOSish */ # if defined(__APPLE__) # ifndef HAVE_CASE_INSENSITIVE_FILE_SYSTEM # define HAVE_CASE_INSENSITIVE_FILE_SYSTEM 1 # endif # endif /* __APPLE__ */ # define HAS_DRIVE_SPEC(f) (0) # define IS_DIR_SEPARATOR(c) IS_UNIX_DIR_SEPARATOR (c) # define IS_ABSOLUTE_PATH(f) IS_UNIX_ABSOLUTE_PATH (f) #endif #define IS_DIR_SEPARATOR_1(dos_based, c) \ (((c) == '/') \ || (((c) == '\\') && (dos_based))) #define HAS_DRIVE_SPEC_1(dos_based, f) \ ((f)[0] && ((f)[1] == ':') && (dos_based)) /* Remove the drive spec from F, assuming HAS_DRIVE_SPEC (f). The result is a pointer to the remainder of F. */ #define STRIP_DRIVE_SPEC(f) ((f) + 2) #define IS_DOS_DIR_SEPARATOR(c) IS_DIR_SEPARATOR_1 (1, c) #define IS_DOS_ABSOLUTE_PATH(f) IS_ABSOLUTE_PATH_1 (1, f) #define HAS_DOS_DRIVE_SPEC(f) HAS_DRIVE_SPEC_1 (1, f) #define IS_UNIX_DIR_SEPARATOR(c) IS_DIR_SEPARATOR_1 (0, c) #define IS_UNIX_ABSOLUTE_PATH(f) IS_ABSOLUTE_PATH_1 (0, f) /* Note that when DOS_BASED is true, IS_ABSOLUTE_PATH accepts d:foo as well, although it is only semi-absolute. This is because the users of IS_ABSOLUTE_PATH want to know whether to prepend the current working directory to a file name, which should not be done with a name like d:foo. */ #define IS_ABSOLUTE_PATH_1(dos_based, f) \ (IS_DIR_SEPARATOR_1 (dos_based, (f)[0]) \ || HAS_DRIVE_SPEC_1 (dos_based, f)) extern int filename_cmp (const char *s1, const char *s2); #define FILENAME_CMP(s1, s2) filename_cmp(s1, s2) extern int filename_ncmp (const char *s1, const char *s2, size_t n); extern hashval_t filename_hash (const void *s); extern int filename_eq (const void *s1, const void *s2); extern int canonical_filename_eq (const char *a, const char *b); #ifdef __cplusplus } #endif #endif /* FILENAMES_H */ vendor/backtrace-sys-0.1.16/src/libbacktrace/filetype.awk0000664000000000000000000000041713264166600022057 0ustar rootroot# 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 } } vendor/backtrace-sys-0.1.16/src/libbacktrace/hashtab.h0000664000000000000000000001614613264166600021323 0ustar rootroot/* An expandable hash tables datatype. Copyright (C) 1999-2015 Free Software Foundation, Inc. Contributed by Vladimir Makarov (vmakarov@cygnus.com). 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 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, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ /* This package implements basic hash table functionality. It is possible to search for an entry, create an entry and destroy an entry. Elements in the table are generic pointers. The size of the table is not fixed; if the occupancy of the table grows too high the hash table will be expanded. The abstract data implementation is based on generalized Algorithm D from Knuth's book "The art of computer programming". Hash table is expanded by creation of new hash table and transferring elements from the old table to the new table. */ #ifndef __HASHTAB_H__ #define __HASHTAB_H__ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #include "ansidecl.h" /* The type for a hash code. */ typedef unsigned int hashval_t; /* Callback function pointer types. */ /* Calculate hash of a table entry. */ typedef hashval_t (*htab_hash) (const void *); /* Compare a table entry with a possible entry. The entry already in the table always comes first, so the second element can be of a different type (but in this case htab_find and htab_find_slot cannot be used; instead the variants that accept a hash value must be used). */ typedef int (*htab_eq) (const void *, const void *); /* Cleanup function called whenever a live element is removed from the hash table. */ typedef void (*htab_del) (void *); /* Function called by htab_traverse for each live element. The first arg is the slot of the element (which can be passed to htab_clear_slot if desired), the second arg is the auxiliary pointer handed to htab_traverse. Return 1 to continue scan, 0 to stop. */ typedef int (*htab_trav) (void **, void *); /* Memory-allocation function, with the same functionality as calloc(). Iff it returns NULL, the hash table implementation will pass an error code back to the user, so if your code doesn't handle errors, best if you use xcalloc instead. */ typedef void *(*htab_alloc) (size_t, size_t); /* We also need a free() routine. */ typedef void (*htab_free) (void *); /* Memory allocation and deallocation; variants which take an extra argument. */ typedef void *(*htab_alloc_with_arg) (void *, size_t, size_t); typedef void (*htab_free_with_arg) (void *, void *); /* This macro defines reserved value for empty table entry. */ #define HTAB_EMPTY_ENTRY ((PTR) 0) /* This macro defines reserved value for table entry which contained a deleted element. */ #define HTAB_DELETED_ENTRY ((PTR) 1) /* Hash tables are of the following type. The structure (implementation) of this type is not needed for using the hash tables. All work with hash table should be executed only through functions mentioned below. The size of this structure is subject to change. */ struct htab { /* Pointer to hash function. */ htab_hash hash_f; /* Pointer to comparison function. */ htab_eq eq_f; /* Pointer to cleanup function. */ htab_del del_f; /* Table itself. */ void **entries; /* Current size (in entries) of the hash table. */ size_t size; /* Current number of elements including also deleted elements. */ size_t n_elements; /* Current number of deleted elements in the table. */ size_t n_deleted; /* The following member is used for debugging. Its value is number of all calls of `htab_find_slot' for the hash table. */ unsigned int searches; /* The following member is used for debugging. Its value is number of collisions fixed for time of work with the hash table. */ unsigned int collisions; /* Pointers to allocate/free functions. */ htab_alloc alloc_f; htab_free free_f; /* Alternate allocate/free functions, which take an extra argument. */ void *alloc_arg; htab_alloc_with_arg alloc_with_arg_f; htab_free_with_arg free_with_arg_f; /* Current size (in entries) of the hash table, as an index into the table of primes. */ unsigned int size_prime_index; }; typedef struct htab *htab_t; /* An enum saying whether we insert into the hash table or not. */ enum insert_option {NO_INSERT, INSERT}; /* The prototypes of the package functions. */ extern htab_t htab_create_alloc (size_t, htab_hash, htab_eq, htab_del, htab_alloc, htab_free); extern htab_t htab_create_alloc_ex (size_t, htab_hash, htab_eq, htab_del, void *, htab_alloc_with_arg, htab_free_with_arg); extern htab_t htab_create_typed_alloc (size_t, htab_hash, htab_eq, htab_del, htab_alloc, htab_alloc, htab_free); /* Backward-compatibility functions. */ extern htab_t htab_create (size_t, htab_hash, htab_eq, htab_del); extern htab_t htab_try_create (size_t, htab_hash, htab_eq, htab_del); extern void htab_set_functions_ex (htab_t, htab_hash, htab_eq, htab_del, void *, htab_alloc_with_arg, htab_free_with_arg); extern void htab_delete (htab_t); extern void htab_empty (htab_t); extern void * htab_find (htab_t, const void *); extern void ** htab_find_slot (htab_t, const void *, enum insert_option); extern void * htab_find_with_hash (htab_t, const void *, hashval_t); extern void ** htab_find_slot_with_hash (htab_t, const void *, hashval_t, enum insert_option); extern void htab_clear_slot (htab_t, void **); extern void htab_remove_elt (htab_t, void *); extern void htab_remove_elt_with_hash (htab_t, void *, hashval_t); extern void htab_traverse (htab_t, htab_trav, void *); extern void htab_traverse_noresize (htab_t, htab_trav, void *); extern size_t htab_size (htab_t); extern size_t htab_elements (htab_t); extern double htab_collisions (htab_t); /* A hash function for pointers. */ extern htab_hash htab_hash_pointer; /* An equality function for pointers. */ extern htab_eq htab_eq_pointer; /* A hash function for null-terminated strings. */ extern hashval_t htab_hash_string (const void *); /* An iterative hash function for arbitrary data. */ extern hashval_t iterative_hash (const void *, size_t, hashval_t); /* Shorthand for hashing something with an intrinsic size. */ #define iterative_hash_object(OB,INIT) iterative_hash (&OB, sizeof (OB), INIT) #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* __HASHTAB_H */ vendor/backtrace-sys-0.1.16/src/libbacktrace/install-sh0000775000000000000000000003452313264166600021543 0ustar rootroot#!/bin/sh # install - install a program, script, or datafile scriptversion=2013-12-25.23; # 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. tab=' ' nl=' ' IFS=" $tab$nl" # Set DOITPROG to "echo" to test this script. doit=${DOITPROG-} doit_exec=${doit:-exec} # 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_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 is_target_a_directory=possibly 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 *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) is_target_a_directory=always dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) is_target_a_directory=never;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done # We allow the use of options -d and -T together, by making -d # take the precedence; this is for compatibility with GNU install. if test -n "$dir_arg"; then if test -n "$dst_arg"; then echo "$0: target directory not allowed when installing a directory." >&2 exit 1 fi fi 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 if test $# -gt 1 || test "$is_target_a_directory" = always; then if test ! -d "$dst_arg"; then echo "$0: $dst_arg: Is not a directory." >&2 exit 1 fi fi 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 "$is_target_a_directory" = never; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else dstdir=`dirname "$dst"` 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-writable 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 oIFS=$IFS IFS=/ set -f set fnord $dstdir shift 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` && set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && 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: vendor/backtrace-sys-0.1.16/src/libbacktrace/internal.h0000664000000000000000000002452513264166600021525 0ustar rootroot/* internal.h -- Internal header file for stack backtrace library. 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. */ #ifndef BACKTRACE_INTERNAL_H #define BACKTRACE_INTERNAL_H /* We assume that 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, 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); #endif vendor/backtrace-sys-0.1.16/src/libbacktrace/ltmain.sh0000664000000000000000000074757313264166600021377 0ustar rootroot# Generated from ltmain.m4sh. # libtool (GNU libtool 1.3134 2009-11-29) 2.2.7a # Written by Gordon Matzigkeit , 1996 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, # 2007, 2008, 2009 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 # --no-finish let install mode avoid finish commands # --preserve-dup-deps don't remove duplicate dependency libraries # --quiet, --silent don't print informational messages # --no-quiet, --no-silent # print informational messages (default) # --tag=TAG use configuration variables from tag TAG # -v, --verbose print more informational messages than default # --no-verbose don't print the extra informational messages # --version print version information # -h, --help, --help-all print short, long, or detailed 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. When passed as first option, # `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that. # 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 1.3134 2009-11-29) 2.2.7a # automake: $automake_version # autoconf: $autoconf_version # # Report bugs to . PROGRAM=libtool PACKAGE=libtool VERSION=2.2.7a TIMESTAMP=" 1.3134 2009-11-29" package_revision=1.3134 # 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 # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } # 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 # 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" : ${CP="cp -f"} : ${ECHO=$as_echo} : ${EGREP="/bin/grep -E"} : ${FGREP="/bin/grep -F"} : ${GREP="/bin/grep"} : ${LN_S="ln -s"} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} : ${SED="/mount/endor/wildenhu/local-x86_64/bin/sed"} : ${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 "${1}" | $SED -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 "${1}" | $SED -e "$basename"` } # Generated shell functions inserted here. # These SED scripts presuppose an absolute path with a trailing slash. pathcar='s,^/\([^/]*\).*$,\1,' pathcdr='s,^/[^/]*,,' removedotparts=':dotsl s@/\./@/@g t dotsl s,/\.$,/,' collapseslashes='s@/\{1,\}@/@g' finalslash='s,/*$,/,' # func_normal_abspath PATH # Remove doubled-up and trailing slashes, "." path components, # and cancel out any ".." path components in PATH after making # it an absolute path. # value returned in "$func_normal_abspath_result" func_normal_abspath () { # Start from root dir and reassemble the path. func_normal_abspath_result= func_normal_abspath_tpath=$1 func_normal_abspath_altnamespace= case $func_normal_abspath_tpath in "") # Empty path, that just means $cwd. func_stripname '' '/' "`pwd`" func_normal_abspath_result=$func_stripname_result return ;; # The next three entries are used to spot a run of precisely # two leading slashes without using negated character classes; # we take advantage of case's first-match behaviour. ///*) # Unusual form of absolute path, do nothing. ;; //*) # Not necessarily an ordinary path; POSIX reserves leading '//' # and for example Cygwin uses it to access remote file shares # over CIFS/SMB, so we conserve a leading double slash if found. func_normal_abspath_altnamespace=/ ;; /*) # Absolute path, do nothing. ;; *) # Relative path, prepend $cwd. func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath ;; esac # Cancel out all the simple stuff to save iterations. We also want # the path to end with a slash for ease of parsing, so make sure # there is one (and only one) here. func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"` while :; do # Processed it all yet? if test "$func_normal_abspath_tpath" = / ; then # If we ascended to the root using ".." the result may be empty now. if test -z "$func_normal_abspath_result" ; then func_normal_abspath_result=/ fi break fi func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$pathcar"` func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$pathcdr"` # Figure out what to do with it case $func_normal_abspath_tcomponent in "") # Trailing empty path component, ignore it. ;; ..) # Parent dir; strip last assembled component from result. func_dirname "$func_normal_abspath_result" func_normal_abspath_result=$func_dirname_result ;; *) # Actual path component, append it. func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent ;; esac done # Restore leading double-slash if one was found on entry. func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result } # func_relative_path SRCDIR DSTDIR # generates a relative path from SRCDIR to DSTDIR, with a trailing # slash if non-empty, suitable for immediately appending a filename # without needing to append a separator. # value returned in "$func_relative_path_result" func_relative_path () { func_relative_path_result= func_normal_abspath "$1" func_relative_path_tlibdir=$func_normal_abspath_result func_normal_abspath "$2" func_relative_path_tbindir=$func_normal_abspath_result # Ascend the tree starting from libdir while :; do # check if we have found a prefix of bindir case $func_relative_path_tbindir in $func_relative_path_tlibdir) # found an exact match func_relative_path_tcancelled= break ;; $func_relative_path_tlibdir*) # found a matching prefix func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" func_relative_path_tcancelled=$func_stripname_result if test -z "$func_relative_path_result"; then func_relative_path_result=. fi break ;; *) func_dirname $func_relative_path_tlibdir func_relative_path_tlibdir=${func_dirname_result} if test "x$func_relative_path_tlibdir" = x ; then # Have to descend all the way to the root! func_relative_path_result=../$func_relative_path_result func_relative_path_tcancelled=$func_relative_path_tbindir break fi func_relative_path_result=../$func_relative_path_result ;; esac done # Now calculate path; take care to avoid doubling-up slashes. func_stripname '' '/' "$func_relative_path_result" func_relative_path_result=$func_stripname_result func_stripname '/' '/' "$func_relative_path_tcancelled" if test "x$func_stripname_result" != x ; then func_relative_path_result=${func_relative_path_result}/${func_stripname_result} fi # Normalisation. If bindir is libdir, return empty string, # else relative path ending with a slash; either way, target # file name can be directly appended. if test ! -z "$func_relative_path_result"; then func_stripname './' '' "$func_relative_path_result/" func_relative_path_result=$func_stripname_result fi } # The name of this program: func_dirname_and_basename "$progpath" progname=$func_basename_result # 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_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } # 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 "$my_directory_path" | $SED -e "$dirname"` done my_dir_list=`$ECHO "$my_dir_list" | $SED '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 "$my_tmpdir" } # 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 "$1" | $SED "$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 "$1" | $SED \ -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 '/(C)/!b go :more /\./!{ N s/\n# // b more } :go /^# '$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 [NOEXIT] # Echo long help message to standard output and exit, # unless 'noexit' is passed as argument. 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" ret=$? if test -z "$1"; then exit $ret fi } # 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=: 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_finish=: 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" ;; --no-finish) opt_finish=false ;; --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=: opt_verbose=false ;; --no-quiet|--no-silent) preserve_args="$preserve_args $opt" opt_silent=false ;; --verbose| -v) preserve_args="$preserve_args $opt" opt_silent=false opt_verbose=: ;; --no-verbose) preserve_args="$preserve_args $opt" opt_verbose=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=: ;; --help-all) opt_help=': help-all' ;; --version) func_version ;; -*) func_fatal_help "unrecognized option \`$opt'" ;; *) nonopt="$opt" break ;; esac done case $host in *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* ) # 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 () { test -f "$1" && $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 -f "$1" && 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 CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` 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 "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; # 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 CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case "$@ " in " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) # 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 <?"'"'"' &()|`$[]' \ && 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* | cegcc*) 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 "$srcfile" | $SED 's%^.*/%%; 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 -Wc,FLAG pass FLAG directly to the compiler 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-dir 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 -bindir BINDIR specify path to binaries directory (for systems where libraries must be found in the PATH setting at runtime) -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 -Wc,FLAG -Xcompiler FLAG pass linker-specific FLAG directly to the compiler -Wl,FLAG -Xlinker FLAG pass linker-specific FLAG directly to the linker -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) 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." } # Now that we've collected a possible --mode arg, show help if necessary if $opt_help; then if test "$opt_help" = :; then func_mode_help else { func_help noexit for mode in compile link execute install finish uninstall clean; do func_mode_help done } | sed -n '1p; 2,$s/^Usage:/ or: /p' { func_help noexit for mode in compile link execute install finish uninstall clean; do echo func_mode_help done } | sed '1d /^When reporting/,/^Report/{ H d } $x /information about other modes/d /more detailed .*MODE/d s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' fi exit $? fi # 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 -* | *.la | *.lo ) ;; *) # 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 "----------------------------------------------------------------------" 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 "----------------------------------------------------------------------" 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. case $nonopt in *shtool*) :;; *) false;; esac; 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" install_shared_prog=$install_prog case " $install_prog " in *[\\\ /]cp\ *) install_cp=: ;; *) install_cp=false ;; esac # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=no stripme= no_mode=: for arg do arg2= if test -n "$dest"; then files="$files $dest" dest=$arg continue fi case $arg in -d) isdir=yes ;; -f) if $install_cp; then :; else prev=$arg fi ;; -g | -m | -o) prev=$arg ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then if test "x$prev" = x-m && test -n "$install_override_mode"; then arg2=$install_override_mode no_mode=false fi 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" if test -n "$arg2"; then func_quote_for_eval "$arg2" fi install_shared_prog="$install_shared_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 -n "$install_override_mode" && $no_mode; then if $install_cp; then :; else func_quote_for_eval "$install_override_mode" install_shared_prog="$install_shared_prog -m $func_quote_for_eval_result" fi fi 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 "$destdir" | $SED -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 "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else relink_command=`$ECHO "$relink_command" | $SED "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_shared_prog $dir/$srcname $destdir/$realname" \ 'exit $?' tstripme="$stripme" case $host_os in cygwin* | mingw* | pw32* | cegcc*) 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 "$lib" | $SED '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 "$relink_command" | $SED '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 "$file$stripped_ext" | $SED "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" && $opt_finish; 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 #if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) #pragma GCC diagnostic ignored \"-Wstrict-prototypes\" #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 "$objs$old_deplibs" | $SP2NL | $SED "$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 || { $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $MV "$nlist"T "$nlist" } fi if test -n "$export_symbols_regex"; then $opt_dry_run || { $EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T $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 ${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' < "$nlist" > "$export_symbols" case $host in *cygwin* | *mingw* | *cegcc* ) echo EXPORTS > "$output_objdir/$outputname.def" cat "$export_symbols" >> "$output_objdir/$outputname.def" ;; esac } else $opt_dry_run || { ${SED} -e 's/\([].[*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/' < "$export_symbols" > "$output_objdir/$outputname.exp" $GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T $MV "$nlist"T "$nlist" case $host in *cygwin* | *mingw* | *cegcc* ) echo EXPORTS > "$output_objdir/$outputname.def" 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 || { $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 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* | *cegcc* ) 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* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` else compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` fi ;; *) compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "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 "$compile_command" | $SED "s% @SYMFILE@%%"` finalize_command=`$ECHO "$finalize_command" | $SED "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. # Despite the name, also deal with 64 bit binaries. 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 $OBJDUMP -f "$1" | $SED -e '10q' 2>/dev/null | $EGREP 'file format (pe-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then win32_nmres=`$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" if test "$lock_old_archive_extraction" = yes; then lockfile=$f_ex_an_ar_oldlib.lock until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done fi func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ 'stat=$?; rm -f "$lockfile"; exit $stat' if test "$lock_old_archive_extraction" = yes; then $opt_dry_run || rm -f "$lockfile" fi 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=no] # # 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 variables # 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 $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () { func_emit_wrapper_arg1=${1-no} $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. 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 file=\"\$0\"" qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` $ECHO "\ # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } ECHO=\"$qECHO\" fi\ # Find the directory that this script lives in. thisdir=\`\$ECHO \"\$file\" | $SED '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 \"\$file\" | $SED '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 \"\$file\" | $SED '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 \"\$thisdir\" | $SED '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 \"\$$shlibpath_var\" | $SED '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* | *-cegcc*) $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\ " } # func_to_host_path arg # # Convert paths to host format when used with build tools. # Intended for use with "native" mingw (where libtool itself # is running under the msys shell), or in the following cross- # build environments: # $build $host # mingw (msys) mingw [e.g. native] # cygwin mingw # *nix + wine mingw # where wine is equipped with the `winepath' executable. # In the native mingw case, the (msys) shell automatically # converts paths for any non-msys applications it launches, # but that facility isn't available from inside the cwrapper. # Similar accommodations are necessary for $host mingw and # $build cygwin. Calling this function does no harm for other # $host/$build combinations not listed above. # # ARG is the path (on $build) that should be converted to # the proper representation for $host. The result is stored # in $func_to_host_path_result. func_to_host_path () { func_to_host_path_result="$1" if test -n "$1"; then case $host in *mingw* ) lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' case $build in *mingw* ) # actually, msys # awkward: cmd appends spaces to result func_to_host_path_result=`( cmd //c echo "$1" ) 2>/dev/null | $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` ;; *cygwin* ) func_to_host_path_result=`cygpath -w "$1" | $SED -e "$lt_sed_naive_backslashify"` ;; * ) # Unfortunately, winepath does not exit with a non-zero # error code, so we are forced to check the contents of # stdout. On the other hand, if the command is not # found, the shell will set an exit code of 127 and print # *an error message* to stdout. So we must check for both # error code of zero AND non-empty stdout, which explains # the odd construction: func_to_host_path_tmp1=`winepath -w "$1" 2>/dev/null` if test "$?" -eq 0 && test -n "${func_to_host_path_tmp1}"; then func_to_host_path_result=`$ECHO "$func_to_host_path_tmp1" | $SED -e "$lt_sed_naive_backslashify"` else # Allow warning below. func_to_host_path_result= fi ;; esac if test -z "$func_to_host_path_result" ; then func_error "Could not determine host path corresponding to" func_error " \`$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: func_to_host_path_result="$1" fi ;; esac fi } # end: func_to_host_path # func_to_host_pathlist arg # # Convert pathlists to host format when used with build tools. # See func_to_host_path(), above. This function supports the # following $build/$host combinations (but does no harm for # combinations not listed here): # $build $host # mingw (msys) mingw [e.g. native] # cygwin mingw # *nix + wine mingw # # Path separators are also converted from $build format to # $host format. If ARG begins or ends with a path separator # character, it is preserved (but converted to $host format) # on output. # # ARG is a pathlist (on $build) that should be converted to # the proper representation on $host. The result is stored # in $func_to_host_pathlist_result. func_to_host_pathlist () { func_to_host_pathlist_result="$1" if test -n "$1"; then case $host in *mingw* ) lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them # into '.;' and ';.', and winepath ignores them completely. func_stripname : : "$1" func_to_host_pathlist_tmp1=$func_stripname_result case $build in *mingw* ) # Actually, msys. # Awkward: cmd appends spaces to result. func_to_host_pathlist_result=` ( cmd //c echo "$func_to_host_pathlist_tmp1" ) 2>/dev/null | $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` ;; *cygwin* ) func_to_host_pathlist_result=`cygpath -w -p "$func_to_host_pathlist_tmp1" | $SED -e "$lt_sed_naive_backslashify"` ;; * ) # unfortunately, winepath doesn't convert pathlists func_to_host_pathlist_result="" func_to_host_pathlist_oldIFS=$IFS IFS=: for func_to_host_pathlist_f in $func_to_host_pathlist_tmp1 ; do IFS=$func_to_host_pathlist_oldIFS if test -n "$func_to_host_pathlist_f" ; then func_to_host_path "$func_to_host_pathlist_f" if test -n "$func_to_host_path_result" ; then if test -z "$func_to_host_pathlist_result" ; then func_to_host_pathlist_result="$func_to_host_path_result" else func_append func_to_host_pathlist_result ";$func_to_host_path_result" fi fi fi done IFS=$func_to_host_pathlist_oldIFS ;; esac if test -z "$func_to_host_pathlist_result"; then func_error "Could not determine the host path(s) corresponding to" func_error " \`$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This may break if $1 contains DOS-style drive # specifications. The fix is not to complicate the expression # below, but for the user to provide a working wine installation # with winepath so that path translation in the cross-to-mingw # case works properly. lt_replace_pathsep_nix_to_dos="s|:|;|g" func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp1" |\ $SED -e "$lt_replace_pathsep_nix_to_dos"` fi # Now, add the leading and trailing path separators back case "$1" in :* ) func_to_host_pathlist_result=";$func_to_host_pathlist_result" ;; esac case "$1" in *: ) func_append func_to_host_pathlist_result ";" ;; esac ;; esac fi } # end: func_to_host_pathlist # 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 < #include #ifdef _MSC_VER # include # include # include #else # include # include # ifdef __CYGWIN__ # include # endif #endif #include #include #include #include #include #include #include #include /* declarations of non-ANSI functions */ #if defined(__MINGW32__) # ifdef __STRICT_ANSI__ int _putenv (const char *); # endif #elif defined(__CYGWIN__) # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif /* #elif defined (other platforms) ... */ #endif /* portability defines, excluding path handling macros */ #if defined(_MSC_VER) # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv # define S_IXUSR _S_IEXEC # ifndef _INTPTR_T_DEFINED # define _INTPTR_T_DEFINED # define intptr_t int # endif #elif defined(__MINGW32__) # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv #elif defined(__CYGWIN__) # define HAVE_SETENV # define FOPEN_WB "wb" /* #elif defined (other platforms) ... */ #endif #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 /* path handling portability macros */ #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 */ #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 LT_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, ...); void lt_setenv (const char *name, const char *value); char *lt_extend_str (const char *orig_value, const char *add, int to_end); void lt_update_exe_path (const char *name, const char *value); void lt_update_lib_path (const char *name, const char *value); char **prepare_spawn (char **argv); void lt_dump_script (FILE *f); EOF cat <"))); for (i = 0; i < newargc; i++) { LTWRAPPER_DEBUGPRINTF (("(main) newargz[%d] : %s\n", i, (newargz[i] ? newargz[i] : ""))); } EOF case $host_os in mingw*) cat <<"EOF" /* execv doesn't actually work on mingw as expected on unix */ newargz = prepare_spawn (newargz); rval = _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz); if (rval == -1) { /* failed to start process */ LTWRAPPER_DEBUGPRINTF (("(main) failed to launch target \"%s\": errno = %d\n", lt_argv_zero, errno)); return 127; } return rval; EOF ;; *) cat <<"EOF" execv (lt_argv_zero, 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); } void lt_setenv (const char *name, const char *value) { LTWRAPPER_DEBUGPRINTF (("(lt_setenv) setting '%s' to '%s'\n", (name ? name : ""), (value ? value : ""))); { #ifdef HAVE_SETENV /* always make a copy, for consistency with !HAVE_SETENV */ char *str = xstrdup (value); setenv (name, str, 1); #else int len = strlen (name) + 1 + strlen (value) + 1; char *str = XMALLOC (char, len); sprintf (str, "%s=%s", name, value); if (putenv (str) != EXIT_SUCCESS) { XFREE (str); } #endif } } char * lt_extend_str (const char *orig_value, const char *add, int to_end) { char *new_value; if (orig_value && *orig_value) { int orig_value_len = strlen (orig_value); int add_len = strlen (add); new_value = XMALLOC (char, add_len + orig_value_len + 1); if (to_end) { strcpy (new_value, orig_value); strcpy (new_value + orig_value_len, add); } else { strcpy (new_value, add); strcpy (new_value + add_len, orig_value); } } else { new_value = xstrdup (add); } return new_value; } void lt_update_exe_path (const char *name, const char *value) { LTWRAPPER_DEBUGPRINTF (("(lt_update_exe_path) modifying '%s' by prepending '%s'\n", (name ? name : ""), (value ? value : ""))); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); /* some systems can't cope with a ':'-terminated path #' */ int len = strlen (new_value); while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { new_value[len-1] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); } } void lt_update_lib_path (const char *name, const char *value) { LTWRAPPER_DEBUGPRINTF (("(lt_update_lib_path) modifying '%s' by prepending '%s'\n", (name ? name : ""), (value ? value : ""))); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); } } EOF case $host_os in mingw*) cat <<"EOF" /* Prepares an argument vector before calling spawn(). Note that spawn() does not by itself call the command interpreter (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&v); v.dwPlatformId == VER_PLATFORM_WIN32_NT; }) ? "cmd.exe" : "command.com"). Instead it simply concatenates the arguments, separated by ' ', and calls CreateProcess(). We must quote the arguments since Win32 CreateProcess() interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a special way: - Space and tab are interpreted as delimiters. They are not treated as delimiters if they are surrounded by double quotes: "...". - Unescaped double quotes are removed from the input. Their only effect is that within double quotes, space and tab are treated like normal characters. - Backslashes not followed by double quotes are not special. - But 2*n+1 backslashes followed by a double quote become n backslashes followed by a double quote (n >= 0): \" -> " \\\" -> \" \\\\\" -> \\" */ #define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" #define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" char ** prepare_spawn (char **argv) { size_t argc; char **new_argv; size_t i; /* Count number of arguments. */ for (argc = 0; argv[argc] != NULL; argc++) ; /* Allocate new argument vector. */ new_argv = XMALLOC (char *, argc + 1); /* Put quoted arguments into the new argument vector. */ for (i = 0; i < argc; i++) { const char *string = argv[i]; if (string[0] == '\0') new_argv[i] = xstrdup ("\"\""); else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) { int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); size_t length; unsigned int backslashes; const char *s; char *quoted_string; char *p; length = 0; backslashes = 0; if (quote_around) length++; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') length += backslashes + 1; length++; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) length += backslashes + 1; quoted_string = XMALLOC (char, length + 1); p = quoted_string; backslashes = 0; if (quote_around) *p++ = '"'; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') { unsigned int j; for (j = backslashes + 1; j > 0; j--) *p++ = '\\'; } *p++ = c; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) { unsigned int j; for (j = backslashes; j > 0; j--) *p++ = '\\'; *p++ = '"'; } *p = '\0'; new_argv[i] = quoted_string; } else new_argv[i] = (char *) string; } new_argv[argc] = NULL; return new_argv; } EOF ;; esac cat <<"EOF" void lt_dump_script (FILE* f) { EOF func_emit_wrapper yes | $SED -e 's/\([\\"]\)/\\\1/g' \ -e 's/^/ fputs ("/' -e 's/$/\\n", f);/' cat <<"EOF" } EOF } # end: func_emit_cwrapperexe_src # func_win32_import_lib_p ARG # True if ARG is an import lib, as indicated by $file_magic_cmd func_win32_import_lib_p () { $opt_debug case `eval "$file_magic_cmd \"\$1\" 2>/dev/null" | $SED -e 10q` in *import*) : ;; *) false ;; esac } # func_mode_link arg... func_mode_link () { $opt_debug case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # 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 bindir= 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 bindir) bindir="$arg" prev= continue ;; 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 ;; -bindir) prev=bindir 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 if test -z "$dir"; then if test "$#" -gt 0; then func_fatal_error "require no space between \`-L' and \`$1'" else func_fatal_error "need path for \`-L' option" fi fi # 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* | *-cegcc*) testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; ::) dllsearchpath=$dir;; *) dllsearchpath="$dllsearchpath:$dir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$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* | *-cegcc* | *-*-haiku*) # 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*) # 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 ;; *-*-linux*) 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* | *-cegcc*) # 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 $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 # -tp=* Portland pgcc target processor selection -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*) 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 \"\${$shlibpath_var}\" \| \$SED \'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 func_basename "$deplib" deplib_base=$func_basename_result 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 \"$deplib\"" 2>/dev/null | $SED 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 "$inherited_linker_flags" | $SED '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 " $dependency_libs" | $SED '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* | *cegcc*) # 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 eval "libname=\"$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* | *cegcc*) 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$absdir" # 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 path= 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= 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 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 " $new_inherited_linker_flags" | $SED '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|qnx|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 | *.gcno) ;; $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 "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP` fi # Eliminate all temporary directories. #for path in $notinst_path; do # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` # dependency_libs=`$ECHO "$dependency_libs " | $SED "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* | *-cegcc* | *-*-haiku*) # 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 </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 "$potlib" | $SED '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 eval "libname=\"$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 \"$potent_lib\"" 2>/dev/null | $SED 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 " $deplibs" | $SED 's/ -lc$//; 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 " $tmp_deplibs" | $SED "s,$i,,"` done fi case $tmp_deplibs in *[!\ \ ]*) 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 ;; esac ;; 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 " $newdeplibs" | $SED '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 " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` deplibs=`$ECHO " $deplibs" | $SED '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 "$libobjs" | $SP2NL | $SED "$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* | cegcc*) 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 || $ECHO "$include_expsyms" | $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 || (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 func_basename "$output" output_la=$func_basename_result # 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. reload_objs=$objlist eval "concat_cmds=\"$reload_cmds\"" else # All subsequent reloadable object files will link in # the last one created. reload_objs="$objlist $last_robj" eval "concat_cmds=\"\$concat_cmds~$reload_cmds~\$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~ reload_objs="$objlist $last_robj" eval "concat_cmds=\"\${concat_cmds}$reload_cmds\"" 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 || $ECHO "$include_expsyms" | $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 || (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 "$tmp_whole_archive_flags" | $SED '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 "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $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 || 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 " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED '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 " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED '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* | *-cegcc*) testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; *) dllsearchpath="$dllsearchpath:$libdir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$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 "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$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 *cegcc* | *mingw32ce*) # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. wrappers_required=no ;; *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 "$compile_command" | $SED '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 "$link_command" | $SED '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 "$compile_var$compile_command$compile_rpath" | $SED '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 "$link_command" | $SED '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 "$relink_command" | $SED "$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 # The wrapper executable is built using the $host compiler, # because it contains $host paths and files. If cross- # compiling, it, like the target executable, must be # executed on the $host or under an emulation environment. $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 "$relink_command" | $SED "$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" 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" 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" 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 # In fact, it would be nice if we could use this code for all target # systems that can't hard-code library paths into their executables # and that have no shared library path variable independent of PATH, # but it turns out we can't easily determine that from inspecting # libtool variables, so we have to hard-code the OSs to which it # applies here; at the moment, that means platforms that use the PE # object format with DLL files. See the long comment at the top of # tests/bindir.at for full details. tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) # If a -bindir argument was supplied, place the dll there. if test "x$bindir" != x ; then func_relative_path "$install_libdir" "$bindir" tdlname=$func_relative_path_result$dlname else # Otherwise fall back on heuristic. tdlname=../bin/$dlname fi ;; 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 vendor/backtrace-sys-0.1.16/src/libbacktrace/missing0000775000000000000000000001533013264166600021131 0ustar rootroot#! /bin/sh # Common wrapper for a few potentially missing GNU programs. scriptversion=2013-10-28.13; # UTC # Copyright (C) 1996-2014 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 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 . # 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 case $1 in --is-lightweight) # Used by our autoconf macros to check whether the available missing # script is modern enough. exit 0 ;; --run) # Back-compat with the calling convention used by older automake. shift ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal autoconf autoheader autom4te automake makeinfo bison yacc flex lex help2man Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Send bug reports to ." 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 # Run the given program, remember its exit status. "$@"; st=$? # If it succeeded, we are done. test $st -eq 0 && exit 0 # Also exit now if we it failed (or wasn't found), and '--version' was # passed; such an option is passed most likely to detect whether the # program is present and works. case $2 in --version|--help) exit $st;; esac # Exit code 63 means version mismatch. This often happens when the user # tries to use an ancient version of a tool on a file that requires a # minimum version. if test $st -eq 63; then msg="probably too old" elif test $st -eq 127; then # Program was missing. msg="missing on your system" else # Program was found and executed, but failed. Give up. exit $st fi perl_URL=http://www.perl.org/ flex_URL=http://flex.sourceforge.net/ gnu_software_URL=http://www.gnu.org/software program_details () { case $1 in aclocal|automake) echo "The '$1' program is part of the GNU Automake package:" echo "<$gnu_software_URL/automake>" echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/autoconf>" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; autoconf|autom4te|autoheader) echo "The '$1' program is part of the GNU Autoconf package:" echo "<$gnu_software_URL/autoconf/>" echo "It also requires GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; esac } give_advice () { # Normalize program name to check for. normalized_program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` printf '%s\n' "'$1' is $msg." configure_deps="'configure.ac' or m4 files included by 'configure.ac'" case $normalized_program in autoconf*) echo "You should only need it if you modified 'configure.ac'," echo "or m4 files included by it." program_details 'autoconf' ;; autoheader*) echo "You should only need it if you modified 'acconfig.h' or" echo "$configure_deps." program_details 'autoheader' ;; automake*) echo "You should only need it if you modified 'Makefile.am' or" echo "$configure_deps." program_details 'automake' ;; aclocal*) echo "You should only need it if you modified 'acinclude.m4' or" echo "$configure_deps." program_details 'aclocal' ;; autom4te*) echo "You might have modified some maintainer files that require" echo "the 'autom4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) echo "You should only need it if you modified a '.y' file." echo "You may want to install the GNU Bison package:" echo "<$gnu_software_URL/bison/>" ;; lex*|flex*) echo "You should only need it if you modified a '.l' file." echo "You may want to install the Fast Lexical Analyzer package:" echo "<$flex_URL>" ;; help2man*) echo "You should only need it if you modified a dependency" \ "of a man page." echo "You may want to install the GNU Help2man package:" echo "<$gnu_software_URL/help2man/>" ;; makeinfo*) echo "You should only need it if you modified a '.texi' file, or" echo "any other file indirectly affecting the aspect of the manual." echo "You might want to install the Texinfo package:" echo "<$gnu_software_URL/texinfo/>" echo "The spurious makeinfo call might also be the consequence of" echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" echo "want to install GNU make:" echo "<$gnu_software_URL/make/>" ;; *) echo "You might have modified some files without having the proper" echo "tools for further handling them. Check the 'README' file, it" echo "often tells you about the needed prerequisites for installing" echo "this package. You may also peek at any GNU archive site, in" echo "case some other package contains this missing '$1' program." ;; esac } give_advice "$1" | sed -e '1s/^/WARNING: /' \ -e '2,$s/^/ /' >&2 # Propagate the correct exit status (expected to be 127 for a program # not found, 63 for a program that failed due to version mismatch). exit $st # 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: vendor/backtrace-sys-0.1.16/src/libbacktrace/mmap.c0000664000000000000000000001731213264166600020632 0ustar rootroot/* mmap.c -- Memory allocation with mmap. 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. */ #include "config.h" #include #include #include #include #include #include #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. */ if (size >= sizeof (struct backtrace_freelist_struct)) { struct backtrace_freelist_struct *p; 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; } vendor/backtrace-sys-0.1.16/src/libbacktrace/mmapio.c0000664000000000000000000000565413264166600021170 0ustar rootroot/* mmapio.c -- File views using mmap. 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. */ #include "config.h" #include #include #include #include #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); } vendor/backtrace-sys-0.1.16/src/libbacktrace/nounwind.c0000664000000000000000000000444113264166600021540 0ustar rootroot/* backtrace.c -- Entry point for stack backtrace library. 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. */ #include "config.h" #include #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; } vendor/backtrace-sys-0.1.16/src/libbacktrace/pecoff.c0000664000000000000000000005646313264166600021154 0ustar rootroot/* pecoff.c -- Get debug data from a PE/COFFF file for backtraces. Copyright (C) 2015-2016 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 #include #include #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; size_t str_size; off_t str_off; struct backtrace_view syms_view; 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 char *vptr = (const char *)fhdr_view.data; if (vptr[0] == 'M' && vptr[1] == 'Z') memcpy (&fhdr_off, vptr + 0x3c, 4); 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, §s_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; memcpy (&str_size, syms_view.data + syms_size, 4); 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, §s_view, error_callback, data); sects_view_valid = 0; 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, §s_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, 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; } vendor/backtrace-sys-0.1.16/src/libbacktrace/posix.c0000664000000000000000000000546613264166600021051 0ustar rootroot/* posix.c -- POSIX file I/O routines for the backtrace library. 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. */ #include "config.h" #include #include #include #include #include #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; } vendor/backtrace-sys-0.1.16/src/libbacktrace/print.c0000664000000000000000000000533013264166600021031 0ustar rootroot/* print.c -- Print the current backtrace. 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. */ #include "config.h" #include #include #include #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); } vendor/backtrace-sys-0.1.16/src/libbacktrace/read.c0000664000000000000000000000553313264166600020615 0ustar rootroot/* read.c -- File views without mmap. 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. */ #include "config.h" #include #include #include #include #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; } vendor/backtrace-sys-0.1.16/src/libbacktrace/simple.c0000664000000000000000000000616213264166600021172 0ustar rootroot/* simple.c -- The backtrace_simple function. 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. */ #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; } vendor/backtrace-sys-0.1.16/src/libbacktrace/sort.c0000664000000000000000000000614713264166600020673 0ustar rootroot/* sort.c -- Sort without allocating memory 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. */ #include "config.h" #include #include #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; } } vendor/backtrace-sys-0.1.16/src/libbacktrace/state.c0000664000000000000000000000460113264166600021015 0ustar rootroot/* state.c -- Create the backtrace state. 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. */ #include "config.h" #include #include #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; } vendor/backtrace-sys-0.1.16/src/libbacktrace/stest.c0000664000000000000000000000655213264166600021046 0ustar rootroot/* stest.c -- Test for libbacktrace internal sort function 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. */ #include "config.h" #include #include #include #include #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); } vendor/backtrace-sys-0.1.16/src/libbacktrace/unknown.c0000664000000000000000000000450313264166600021375 0ustar rootroot/* unknown.c -- used when backtrace configury does not know file format. 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. */ #include "config.h" #include #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, 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; } vendor/backtrace-sys-0.1.16/symbol-map0000664000000000000000000000142013264166600016333 0ustar rootrootbacktrace_full __rbt_backtrace_full backtrace_dwarf_add __rbt_backtrace_dwarf_add backtrace_initialize __rbt_backtrace_initialize backtrace_pcinfo __rbt_backtrace_pcinfo backtrace_syminfo __rbt_backtrace_syminfo backtrace_get_view __rbt_backtrace_get_view backtrace_release_view __rbt_backtrace_release_view backtrace_alloc __rbt_backtrace_alloc backtrace_free __rbt_backtrace_free backtrace_vector_finish __rbt_backtrace_vector_finish backtrace_vector_grow __rbt_backtrace_vector_grow backtrace_vector_release __rbt_backtrace_vector_release backtrace_close __rbt_backtrace_close backtrace_open __rbt_backtrace_open backtrace_print __rbt_backtrace_print backtrace_simple __rbt_backtrace_simple backtrace_qsort __rbt_backtrace_qsort backtrace_create_state __rbt_backtrace_create_state vendor/bitflags-0.9.1/0000755000000000000000000000000013264166600013313 5ustar rootrootvendor/bitflags-0.9.1/.cargo-checksum.json0000644000000000000000000000013113264166600017152 0ustar rootroot{"files":{},"package":"4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"}vendor/bitflags-0.9.1/.travis.yml0000664000000000000000000000137213264166600015431 0ustar rootrootos: - linux - osx language: rust rust: - stable - beta - nightly sudo: false before_script: - pip install -v 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH - if [[ -e ~/Library/Python/2.7/bin ]]; then export PATH=~/Library/Python/2.7/bin:$PATH; fi script: - cargo build --verbose - cargo test --verbose - travis-cargo --only nightly test - cargo doc --no-deps after_success: - travis-cargo --only nightly doc-upload env: global: - TRAVIS_CARGO_NIGHTLY_FEATURE=unstable_testing - secure: "DoZ8g8iPs+X3xEEucke0Ae02JbkQ1qd1SSv/L2aQqxULmREtRcbzRauhiT+ToQO5Ft1Lul8uck14nPfs4gMr/O3jFFBhEBVpSlbkJx7eNL3kwUdp95UNroA8I43xPN/nccJaHDN6TMTD3+uajTQTje2SyzOQP+1gvdKg17kguvE=" notifications: email: on_success: never vendor/bitflags-0.9.1/Cargo.toml0000644000000000000000000000213413264166600015243 0ustar rootroot# 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 = "bitflags" version = "0.9.1" authors = ["The Rust Project Developers"] description = "A macro to generate structures which behave like bitflags.\n" homepage = "https://github.com/rust-lang-nursery/bitflags" documentation = "https://docs.rs/bitflags" readme = "README.md" keywords = ["bit", "bitmask", "bitflags"] categories = ["no-std"] license = "MIT/Apache-2.0" repository = "https://github.com/rust-lang-nursery/bitflags" [features] example_generated = [] unstable_testing = [] default = ["example_generated"] [badges.travis-ci] repository = "rust-lang-nursery/bitflags" vendor/bitflags-0.9.1/LICENSE-APACHE0000664000000000000000000002513713264166600015251 0ustar rootroot 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. vendor/bitflags-0.9.1/LICENSE-MIT0000664000000000000000000000205713264166600014755 0ustar rootrootCopyright (c) 2014 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. vendor/bitflags-0.9.1/README.md0000664000000000000000000000066513264166600014603 0ustar rootrootbitflags ======== A Rust macro to generate structures which behave like a set of bitflags [![Build Status](https://travis-ci.org/rust-lang-nursery/bitflags.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/bitflags) [Documentation](https://docs.rs/bitflags) ## Usage Add this to your `Cargo.toml`: ```toml [dependencies] bitflags = "0.9" ``` and this to your crate root: ```rust #[macro_use] extern crate bitflags; ``` vendor/bitflags-0.9.1/src/0000755000000000000000000000000013264166600014102 5ustar rootrootvendor/bitflags-0.9.1/src/example_generated.rs0000664000000000000000000000116513264166600020126 0ustar rootroot//! This module shows an example of code generated by the macro. **IT MUST NOT BE USED OUTSIDE THIS //! CRATE**. bitflags! { /// This is the same `Flags` struct defined in the [crate level example](../index.html#example). /// Note that this struct is just for documentation purposes only, it must not be used outside /// this crate. pub struct Flags: u32 { const FLAG_A = 0b00000001; const FLAG_B = 0b00000010; const FLAG_C = 0b00000100; const FLAG_ABC = FLAG_A.bits | FLAG_B.bits | FLAG_C.bits; } } vendor/bitflags-0.9.1/src/lib.rs0000664000000000000000000007206413264166600015231 0ustar rootroot// Copyright 2014 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! A typesafe bitmask flag generator useful for sets of C-style bitmask flags. //! It can be used for creating typesafe wrappers around C APIs. //! //! The `bitflags!` macro generates a `struct` that manages a set of flags. The //! flags should only be defined for integer types, otherwise unexpected type //! errors may occur at compile time. //! //! # Example //! //! ``` //! #[macro_use] //! extern crate bitflags; //! //! bitflags! { //! struct Flags: u32 { //! const FLAG_A = 0b00000001; //! const FLAG_B = 0b00000010; //! const FLAG_C = 0b00000100; //! const FLAG_ABC = FLAG_A.bits //! | FLAG_B.bits //! | FLAG_C.bits; //! } //! } //! //! fn main() { //! let e1 = FLAG_A | FLAG_C; //! let e2 = FLAG_B | FLAG_C; //! assert_eq!((e1 | e2), FLAG_ABC); // union //! assert_eq!((e1 & e2), FLAG_C); // intersection //! assert_eq!((e1 - e2), FLAG_A); // set difference //! assert_eq!(!e2, FLAG_A); // set complement //! } //! ``` //! //! See [`example_generated::Flags`](./example_generated/struct.Flags.html) for documentation of code //! generated by the above `bitflags!` expansion. //! //! The generated `struct`s can also be extended with type and trait //! implementations: //! //! ``` //! #[macro_use] //! extern crate bitflags; //! //! use std::fmt; //! //! bitflags! { //! struct Flags: u32 { //! const FLAG_A = 0b00000001; //! const FLAG_B = 0b00000010; //! } //! } //! //! impl Flags { //! pub fn clear(&mut self) { //! self.bits = 0; // The `bits` field can be accessed from within the //! // same module where the `bitflags!` macro was invoked. //! } //! } //! //! impl fmt::Display for Flags { //! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { //! write!(f, "hi!") //! } //! } //! //! fn main() { //! let mut flags = FLAG_A | FLAG_B; //! flags.clear(); //! assert!(flags.is_empty()); //! assert_eq!(format!("{}", flags), "hi!"); //! assert_eq!(format!("{:?}", FLAG_A | FLAG_B), "FLAG_A | FLAG_B"); //! assert_eq!(format!("{:?}", FLAG_B), "FLAG_B"); //! } //! ``` //! //! # Visibility //! //! The generated struct and its associated flag constants are not exported //! out of the current module by default. A definition can be exported out of //! the current module by adding `pub` before `flags`: //! //! ```ignore //! #[macro_use] //! extern crate bitflags; //! //! mod example { //! bitflags! { //! pub struct Flags1: u32 { //! const FLAG_A = 0b00000001; //! } //! } //! bitflags! { //! struct Flags2: u32 { //! const FLAG_B = 0b00000010; //! } //! } //! } //! //! fn main() { //! let flag1 = example::FLAG_A; //! let flag2 = example::FLAG_B; // error: const `FLAG_B` is private //! } //! ``` //! //! # Attributes //! //! Attributes can be attached to the generated `struct` by placing them //! before the `flags` keyword. //! //! # Trait implementations //! //! The `Copy`, `Clone`, `PartialEq`, `Eq`, `PartialOrd`, `Ord` and `Hash` //! traits automatically derived for the `struct` using the `derive` attribute. //! Additional traits can be derived by providing an explicit `derive` //! attribute on `flags`. //! //! The `Extend` and `FromIterator` traits are implemented for the `struct`, //! too: `Extend` adds the union of the instances of the `struct` iterated over, //! while `FromIterator` calculates the union. //! //! The `Binary`, `Debug`, `LowerExp`, `Octal` and `UpperExp` trait is also //! implemented by displaying the bits value of the internal struct. //! //! ## Operators //! //! The following operator traits are implemented for the generated `struct`: //! //! - `BitOr` and `BitOrAssign`: union //! - `BitAnd` and `BitAndAssign`: intersection //! - `BitXor` and `BitXorAssign`: toggle //! - `Sub` and `SubAssign`: set difference //! - `Not`: set complement //! //! # Methods //! //! The following methods are defined for the generated `struct`: //! //! - `empty`: an empty set of flags //! - `all`: the set of all flags //! - `bits`: the raw value of the flags currently stored //! - `from_bits`: convert from underlying bit representation, unless that //! representation contains bits that do not correspond to a flag //! - `from_bits_truncate`: convert from underlying bit representation, dropping //! any bits that do not correspond to flags //! - `is_empty`: `true` if no flags are currently stored //! - `is_all`: `true` if all flags are currently set //! - `intersects`: `true` if there are flags common to both `self` and `other` //! - `contains`: `true` all of the flags in `other` are contained within `self` //! - `insert`: inserts the specified flags in-place //! - `remove`: removes the specified flags in-place //! - `toggle`: the specified flags will be inserted if not present, and removed //! if they are. //! //! ## Default //! //! The `Default` trait is not automatically implemented for the generated struct. //! //! If your default value is equal to `0` (which is the same value as calling `empty()` //! on the generated struct), you can simply derive `Default`: //! //! ``` //! #[macro_use] //! extern crate bitflags; //! //! bitflags! { //! // Results in default value with bits: 0 //! #[derive(Default)] //! struct Flags: u32 { //! const FLAG_A = 0b00000001; //! const FLAG_B = 0b00000010; //! const FLAG_C = 0b00000100; //! } //! } //! //! fn main() { //! let derived_default: Flags = Default::default(); //! assert_eq!(derived_default.bits(), 0); //! } //! ``` //! //! If your default value is not equal to `0` you need to implement `Default` yourself: //! //! ``` //! #[macro_use] //! extern crate bitflags; //! //! bitflags! { //! struct Flags: u32 { //! const FLAG_A = 0b00000001; //! const FLAG_B = 0b00000010; //! const FLAG_C = 0b00000100; //! } //! } //! //! // explicit `Default` implementation //! impl Default for Flags { //! fn default() -> Flags { //! FLAG_A | FLAG_C //! } //! } //! //! fn main() { //! let implemented_default: Flags = Default::default(); //! assert_eq!(implemented_default, (FLAG_A | FLAG_C)); //! } //! ``` #![no_std] #![doc(html_root_url = "https://docs.rs/bitflags/0.9.1")] // When compiled for the rustc compiler itself we want to make sure that this is // an unstable crate. #![cfg_attr(rustbuild, feature(staged_api))] #![cfg_attr(rustbuild, unstable(feature = "rustc_private", issue = "27812"))] #[cfg(test)] #[macro_use] extern crate std; // Re-export libstd/libcore using an alias so that the macros can work in no_std // crates while remaining compatible with normal crates. #[doc(hidden)] pub extern crate core as _core; /// The macro used to generate the flag structure. /// /// See the [crate level docs](../bitflags/index.html) for complete documentation. /// /// # Example /// /// ``` /// #[macro_use] /// extern crate bitflags; /// /// bitflags! { /// struct Flags: u32 { /// const FLAG_A = 0b00000001; /// const FLAG_B = 0b00000010; /// const FLAG_C = 0b00000100; /// const FLAG_ABC = FLAG_A.bits /// | FLAG_B.bits /// | FLAG_C.bits; /// } /// } /// /// fn main() { /// let e1 = FLAG_A | FLAG_C; /// let e2 = FLAG_B | FLAG_C; /// assert_eq!((e1 | e2), FLAG_ABC); // union /// assert_eq!((e1 & e2), FLAG_C); // intersection /// assert_eq!((e1 - e2), FLAG_A); // set difference /// assert_eq!(!e2, FLAG_A); // set complement /// } /// ``` /// /// The generated `struct`s can also be extended with type and trait /// implementations: /// /// ``` /// #[macro_use] /// extern crate bitflags; /// /// use std::fmt; /// /// bitflags! { /// struct Flags: u32 { /// const FLAG_A = 0b00000001; /// const FLAG_B = 0b00000010; /// } /// } /// /// impl Flags { /// pub fn clear(&mut self) { /// self.bits = 0; // The `bits` field can be accessed from within the /// // same module where the `bitflags!` macro was invoked. /// } /// } /// /// impl fmt::Display for Flags { /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { /// write!(f, "hi!") /// } /// } /// /// fn main() { /// let mut flags = FLAG_A | FLAG_B; /// flags.clear(); /// assert!(flags.is_empty()); /// assert_eq!(format!("{}", flags), "hi!"); /// assert_eq!(format!("{:?}", FLAG_A | FLAG_B), "FLAG_A | FLAG_B"); /// assert_eq!(format!("{:?}", FLAG_B), "FLAG_B"); /// } /// ``` #[macro_export] macro_rules! bitflags { ($(#[$attr:meta])* pub struct $BitFlags:ident: $T:ty { $($(#[$Flag_attr:meta])* const $Flag:ident = $value:expr;)+ }) => { #[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)] $(#[$attr])* pub struct $BitFlags { bits: $T, } $($(#[$Flag_attr])* pub const $Flag: $BitFlags = $BitFlags { bits: $value };)+ __impl_bitflags! { struct $BitFlags: $T { $($(#[$Flag_attr])* const $Flag = $value;)+ } } }; ($(#[$attr:meta])* struct $BitFlags:ident: $T:ty { $($(#[$Flag_attr:meta])* const $Flag:ident = $value:expr;)+ }) => { #[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)] $(#[$attr])* struct $BitFlags { bits: $T, } $($(#[$Flag_attr])* const $Flag: $BitFlags = $BitFlags { bits: $value };)+ __impl_bitflags! { struct $BitFlags: $T { $($(#[$Flag_attr])* const $Flag = $value;)+ } } }; } #[macro_export] #[doc(hidden)] macro_rules! __impl_bitflags { (struct $BitFlags:ident: $T:ty { $($(#[$Flag_attr:meta])* const $Flag:ident = $value:expr;)+ }) => { impl $crate::_core::fmt::Debug for $BitFlags { fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { // This convoluted approach is to handle #[cfg]-based flag // omission correctly. For example it needs to support: // // #[cfg(unix)] const A: Flag = /* ... */; // #[cfg(windows)] const B: Flag = /* ... */; // Unconditionally define a check for every flag, even disabled // ones. #[allow(non_snake_case)] trait __BitFlags { $( fn $Flag(&self) -> bool { false } )+ } // Conditionally override the check for just those flags that // are not #[cfg]ed away. impl __BitFlags for $BitFlags { $( $(#[$Flag_attr])* fn $Flag(&self) -> bool { self.bits & $Flag.bits == $Flag.bits } )+ } let mut first = true; $( if <$BitFlags as __BitFlags>::$Flag(self) { if !first { try!(f.write_str(" | ")); } first = false; try!(f.write_str(stringify!($Flag))); } )+ if first { try!(f.write_str("(empty)")); } Ok(()) } } impl $crate::_core::fmt::Binary for $BitFlags { fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { $crate::_core::fmt::Binary::fmt(&self.bits, f) } } impl $crate::_core::fmt::Octal for $BitFlags { fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { $crate::_core::fmt::Octal::fmt(&self.bits, f) } } impl $crate::_core::fmt::LowerHex for $BitFlags { fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { $crate::_core::fmt::LowerHex::fmt(&self.bits, f) } } impl $crate::_core::fmt::UpperHex for $BitFlags { fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { $crate::_core::fmt::UpperHex::fmt(&self.bits, f) } } #[allow(dead_code)] impl $BitFlags { /// Returns an empty set of flags. #[inline] pub fn empty() -> $BitFlags { $BitFlags { bits: 0 } } /// Returns the set containing all flags. #[inline] pub fn all() -> $BitFlags { // See `Debug::fmt` for why this approach is taken. #[allow(non_snake_case)] trait __BitFlags { $( fn $Flag() -> $T { 0 } )+ } impl __BitFlags for $BitFlags { $( $(#[$Flag_attr])* fn $Flag() -> $T { $Flag.bits } )+ } $BitFlags { bits: $(<$BitFlags as __BitFlags>::$Flag())|+ } } /// Returns the raw value of the flags currently stored. #[inline] pub fn bits(&self) -> $T { self.bits } /// Convert from underlying bit representation, unless that /// representation contains bits that do not correspond to a flag. #[inline] pub fn from_bits(bits: $T) -> $crate::_core::option::Option<$BitFlags> { if (bits & !$BitFlags::all().bits()) == 0 { $crate::_core::option::Option::Some($BitFlags { bits: bits }) } else { $crate::_core::option::Option::None } } /// Convert from underlying bit representation, dropping any bits /// that do not correspond to flags. #[inline] pub fn from_bits_truncate(bits: $T) -> $BitFlags { $BitFlags { bits: bits } & $BitFlags::all() } /// Returns `true` if no flags are currently stored. #[inline] pub fn is_empty(&self) -> bool { *self == $BitFlags::empty() } /// Returns `true` if all flags are currently set. #[inline] pub fn is_all(&self) -> bool { *self == $BitFlags::all() } /// Returns `true` if there are flags common to both `self` and `other`. #[inline] pub fn intersects(&self, other: $BitFlags) -> bool { !(*self & other).is_empty() } /// Returns `true` all of the flags in `other` are contained within `self`. #[inline] pub fn contains(&self, other: $BitFlags) -> bool { (*self & other) == other } /// Inserts the specified flags in-place. #[inline] pub fn insert(&mut self, other: $BitFlags) { self.bits |= other.bits; } /// Removes the specified flags in-place. #[inline] pub fn remove(&mut self, other: $BitFlags) { self.bits &= !other.bits; } /// Toggles the specified flags in-place. #[inline] pub fn toggle(&mut self, other: $BitFlags) { self.bits ^= other.bits; } /// Inserts or removes the specified flags depending on the passed value. #[inline] pub fn set(&mut self, other: $BitFlags, value: bool) { if value { self.insert(other); } else { self.remove(other); } } } impl $crate::_core::ops::BitOr for $BitFlags { type Output = $BitFlags; /// Returns the union of the two sets of flags. #[inline] fn bitor(self, other: $BitFlags) -> $BitFlags { $BitFlags { bits: self.bits | other.bits } } } impl $crate::_core::ops::BitOrAssign for $BitFlags { /// Adds the set of flags. #[inline] fn bitor_assign(&mut self, other: $BitFlags) { self.bits |= other.bits; } } impl $crate::_core::ops::BitXor for $BitFlags { type Output = $BitFlags; /// Returns the left flags, but with all the right flags toggled. #[inline] fn bitxor(self, other: $BitFlags) -> $BitFlags { $BitFlags { bits: self.bits ^ other.bits } } } impl $crate::_core::ops::BitXorAssign for $BitFlags { /// Toggles the set of flags. #[inline] fn bitxor_assign(&mut self, other: $BitFlags) { self.bits ^= other.bits; } } impl $crate::_core::ops::BitAnd for $BitFlags { type Output = $BitFlags; /// Returns the intersection between the two sets of flags. #[inline] fn bitand(self, other: $BitFlags) -> $BitFlags { $BitFlags { bits: self.bits & other.bits } } } impl $crate::_core::ops::BitAndAssign for $BitFlags { /// Disables all flags disabled in the set. #[inline] fn bitand_assign(&mut self, other: $BitFlags) { self.bits &= other.bits; } } impl $crate::_core::ops::Sub for $BitFlags { type Output = $BitFlags; /// Returns the set difference of the two sets of flags. #[inline] fn sub(self, other: $BitFlags) -> $BitFlags { $BitFlags { bits: self.bits & !other.bits } } } impl $crate::_core::ops::SubAssign for $BitFlags { /// Disables all flags enabled in the set. #[inline] fn sub_assign(&mut self, other: $BitFlags) { self.bits &= !other.bits; } } impl $crate::_core::ops::Not for $BitFlags { type Output = $BitFlags; /// Returns the complement of this set of flags. #[inline] fn not(self) -> $BitFlags { $BitFlags { bits: !self.bits } & $BitFlags::all() } } impl $crate::_core::iter::Extend<$BitFlags> for $BitFlags { fn extend>(&mut self, iterator: T) { for item in iterator { self.insert(item) } } } impl $crate::_core::iter::FromIterator<$BitFlags> for $BitFlags { fn from_iter>(iterator: T) -> $BitFlags { let mut result = Self::empty(); result.extend(iterator); result } } }; } #[cfg(feature = "example_generated")] pub mod example_generated; #[cfg(test)] #[allow(non_upper_case_globals, dead_code)] mod tests { use std::hash::{Hash, Hasher}; use std::collections::hash_map::DefaultHasher; bitflags! { #[doc = "> The first principle is that you must not fool yourself — and"] #[doc = "> you are the easiest person to fool."] #[doc = "> "] #[doc = "> - Richard Feynman"] struct Flags: u32 { const FlagA = 0b00000001; #[doc = " macros are way better at generating code than trans is"] const FlagB = 0b00000010; const FlagC = 0b00000100; #[doc = "* cmr bed"] #[doc = "* strcat table"] #[doc = " wait what?"] const FlagABC = FlagA.bits | FlagB.bits | FlagC.bits; } } bitflags! { struct _CfgFlags: u32 { #[cfg(windows)] const _CfgA = 0b01; #[cfg(unix)] const _CfgB = 0b01; #[cfg(windows)] const _CfgC = _CfgA.bits | 0b10; } } bitflags! { struct AnotherSetOfFlags: i8 { const AnotherFlag = -1_i8; } } bitflags! { struct LongFlags: u32 { const LongFlagA = 0b1111111111111111; } } #[test] fn test_bits(){ assert_eq!(Flags::empty().bits(), 0b00000000); assert_eq!(FlagA.bits(), 0b00000001); assert_eq!(FlagABC.bits(), 0b00000111); assert_eq!(AnotherSetOfFlags::empty().bits(), 0b00); assert_eq!(AnotherFlag.bits(), !0_i8); } #[test] fn test_from_bits() { assert_eq!(Flags::from_bits(0), Some(Flags::empty())); assert_eq!(Flags::from_bits(0b1), Some(FlagA)); assert_eq!(Flags::from_bits(0b10), Some(FlagB)); assert_eq!(Flags::from_bits(0b11), Some(FlagA | FlagB)); assert_eq!(Flags::from_bits(0b1000), None); assert_eq!(AnotherSetOfFlags::from_bits(!0_i8), Some(AnotherFlag)); } #[test] fn test_from_bits_truncate() { assert_eq!(Flags::from_bits_truncate(0), Flags::empty()); assert_eq!(Flags::from_bits_truncate(0b1), FlagA); assert_eq!(Flags::from_bits_truncate(0b10), FlagB); assert_eq!(Flags::from_bits_truncate(0b11), (FlagA | FlagB)); assert_eq!(Flags::from_bits_truncate(0b1000), Flags::empty()); assert_eq!(Flags::from_bits_truncate(0b1001), FlagA); assert_eq!(AnotherSetOfFlags::from_bits_truncate(0_i8), AnotherSetOfFlags::empty()); } #[test] fn test_is_empty(){ assert!(Flags::empty().is_empty()); assert!(!FlagA.is_empty()); assert!(!FlagABC.is_empty()); assert!(!AnotherFlag.is_empty()); } #[test] fn test_is_all() { assert!(Flags::all().is_all()); assert!(!FlagA.is_all()); assert!(FlagABC.is_all()); assert!(AnotherFlag.is_all()); } #[test] fn test_two_empties_do_not_intersect() { let e1 = Flags::empty(); let e2 = Flags::empty(); assert!(!e1.intersects(e2)); assert!(AnotherFlag.intersects(AnotherFlag)); } #[test] fn test_empty_does_not_intersect_with_full() { let e1 = Flags::empty(); let e2 = FlagABC; assert!(!e1.intersects(e2)); } #[test] fn test_disjoint_intersects() { let e1 = FlagA; let e2 = FlagB; assert!(!e1.intersects(e2)); } #[test] fn test_overlapping_intersects() { let e1 = FlagA; let e2 = FlagA | FlagB; assert!(e1.intersects(e2)); } #[test] fn test_contains() { let e1 = FlagA; let e2 = FlagA | FlagB; assert!(!e1.contains(e2)); assert!(e2.contains(e1)); assert!(FlagABC.contains(e2)); assert!(AnotherFlag.contains(AnotherFlag)); } #[test] fn test_insert(){ let mut e1 = FlagA; let e2 = FlagA | FlagB; e1.insert(e2); assert_eq!(e1, e2); let mut e3 = AnotherSetOfFlags::empty(); e3.insert(AnotherFlag); assert_eq!(e3, AnotherFlag); } #[test] fn test_remove(){ let mut e1 = FlagA | FlagB; let e2 = FlagA | FlagC; e1.remove(e2); assert_eq!(e1, FlagB); let mut e3 = AnotherFlag; e3.remove(AnotherFlag); assert_eq!(e3, AnotherSetOfFlags::empty()); } #[test] fn test_operators() { let e1 = FlagA | FlagC; let e2 = FlagB | FlagC; assert_eq!((e1 | e2), FlagABC); // union assert_eq!((e1 & e2), FlagC); // intersection assert_eq!((e1 - e2), FlagA); // set difference assert_eq!(!e2, FlagA); // set complement assert_eq!(e1 ^ e2, FlagA | FlagB); // toggle let mut e3 = e1; e3.toggle(e2); assert_eq!(e3, FlagA | FlagB); let mut m4 = AnotherSetOfFlags::empty(); m4.toggle(AnotherSetOfFlags::empty()); assert_eq!(m4, AnotherSetOfFlags::empty()); } #[test] fn test_set() { let mut e1 = FlagA | FlagC; e1.set(FlagB, true); e1.set(FlagC, false); assert_eq!(e1, FlagA | FlagB); } #[test] fn test_assignment_operators() { let mut m1 = Flags::empty(); let e1 = FlagA | FlagC; // union m1 |= FlagA; assert_eq!(m1, FlagA); // intersection m1 &= e1; assert_eq!(m1, FlagA); // set difference m1 -= m1; assert_eq!(m1, Flags::empty()); // toggle m1 ^= e1; assert_eq!(m1, e1); } #[test] fn test_extend() { let mut flags; flags = Flags::empty(); flags.extend([].iter().cloned()); assert_eq!(flags, Flags::empty()); flags = Flags::empty(); flags.extend([FlagA, FlagB].iter().cloned()); assert_eq!(flags, FlagA | FlagB); flags = FlagA; flags.extend([FlagA, FlagB].iter().cloned()); assert_eq!(flags, FlagA | FlagB); flags = FlagB; flags.extend([FlagA, FlagABC].iter().cloned()); assert_eq!(flags, FlagABC); } #[test] fn test_from_iterator() { assert_eq!([].iter().cloned().collect::(), Flags::empty()); assert_eq!([FlagA, FlagB].iter().cloned().collect::(), FlagA | FlagB); assert_eq!([FlagA, FlagABC].iter().cloned().collect::(), FlagABC); } #[test] fn test_lt() { let mut a = Flags::empty(); let mut b = Flags::empty(); assert!(!(a < b) && !(b < a)); b = FlagB; assert!(a < b); a = FlagC; assert!(!(a < b) && b < a); b = FlagC | FlagB; assert!(a < b); } #[test] fn test_ord() { let mut a = Flags::empty(); let mut b = Flags::empty(); assert!(a <= b && a >= b); a = FlagA; assert!(a > b && a >= b); assert!(b < a && b <= a); b = FlagB; assert!(b > a && b >= a); assert!(a < b && a <= b); } fn hash(t: &T) -> u64 { let mut s = DefaultHasher::new(); t.hash(&mut s); s.finish() } #[test] fn test_hash() { let mut x = Flags::empty(); let mut y = Flags::empty(); assert_eq!(hash(&x), hash(&y)); x = Flags::all(); y = FlagABC; assert_eq!(hash(&x), hash(&y)); } #[test] fn test_debug() { assert_eq!(format!("{:?}", FlagA | FlagB), "FlagA | FlagB"); assert_eq!(format!("{:?}", Flags::empty()), "(empty)"); assert_eq!(format!("{:?}", FlagABC), "FlagA | FlagB | FlagC | FlagABC"); } #[test] fn test_binary() { assert_eq!(format!("{:b}", FlagABC), "111"); assert_eq!(format!("{:#b}", FlagABC), "0b111"); } #[test] fn test_octal() { assert_eq!(format!("{:o}", LongFlagA), "177777"); assert_eq!(format!("{:#o}", LongFlagA), "0o177777"); } #[test] fn test_lowerhex() { assert_eq!(format!("{:x}", LongFlagA), "ffff"); assert_eq!(format!("{:#x}", LongFlagA), "0xffff"); } #[test] fn test_upperhex() { assert_eq!(format!("{:X}", LongFlagA), "FFFF"); assert_eq!(format!("{:#X}", LongFlagA), "0xFFFF"); } mod submodule { bitflags! { pub struct PublicFlags: i8 { const FlagX = 0; } } bitflags! { struct PrivateFlags: i8 { const FlagY = 0; } } #[test] fn test_private() { let _ = FlagY; } } #[test] fn test_public() { let _ = submodule::FlagX; } mod t1 { mod foo { pub type Bar = i32; } bitflags! { /// baz struct Flags: foo::Bar { const A = 0b00000001; #[cfg(foo)] const B = 0b00000010; #[cfg(foo)] const C = 0b00000010; } } } #[test] fn test_in_function() { bitflags! { struct Flags: u8 { const A = 1; #[cfg(any())] // false const B = 2; } } assert_eq!(Flags::all(), A); assert_eq!(format!("{:?}", A), "A"); } } vendor/bitflags-0.9.1/tests/0000755000000000000000000000000013264166600014455 5ustar rootrootvendor/bitflags-0.9.1/tests/conflicting_trait_impls.rs0000664000000000000000000000035413264166600021735 0ustar rootroot#![allow(dead_code)] #![no_std] #[macro_use] extern crate bitflags; #[allow(unused_imports)] use core::fmt::Display; bitflags! { /// baz struct Flags: u32 { const A = 0b00000001; } } #[test] fn main() { } vendor/bitflags-0.9.1/tests/external.rs0000664000000000000000000000056713264166600016657 0ustar rootroot#![allow(dead_code)] #[macro_use] extern crate bitflags; bitflags! { /// baz struct Flags: u32 { const A = 0b00000001; #[doc = "bar"] const B = 0b00000010; const C = 0b00000100; #[doc = "foo"] const ABC = A.bits | B.bits | C.bits; } } #[test] fn smoke() { assert_eq!(ABC, A | B | C); } vendor/bitflags-0.9.1/tests/external_no_std.rs0000664000000000000000000000060213264166600020213 0ustar rootroot#![allow(dead_code)] #![no_std] #[macro_use] extern crate bitflags; bitflags! { /// baz struct Flags: u32 { const A = 0b00000001; #[doc = "bar"] const B = 0b00000010; const C = 0b00000100; #[doc = "foo"] const ABC = A.bits | B.bits | C.bits; } } #[test] fn smoke() { assert_eq!(ABC, A | B | C); } vendor/bitflags-0.9.1/tests/i128_bitflags.rs0000664000000000000000000000170713264166600017370 0ustar rootroot#![cfg(feature = "unstable_testing")] #![allow(dead_code, unused_imports)] #![feature(i128_type)] #[macro_use] extern crate bitflags; bitflags! { /// baz struct Flags128: u128 { const A = 0x0000_0000_0000_0000_0000_0000_0000_0001; const B = 0x0000_0000_0000_1000_0000_0000_0000_0000; const C = 0x8000_0000_0000_0000_0000_0000_0000_0000; const ABC = A.bits | B.bits | C.bits; } } #[test] fn test_i128_bitflags() { assert_eq!(ABC, A | B | C); assert_eq!(A.bits, 0x0000_0000_0000_0000_0000_0000_0000_0001); assert_eq!(B.bits, 0x0000_0000_0000_1000_0000_0000_0000_0000); assert_eq!(C.bits, 0x8000_0000_0000_0000_0000_0000_0000_0000); assert_eq!(ABC.bits, 0x8000_0000_0000_1000_0000_0000_0000_0001); assert_eq!(format!("{:?}", A), "A"); assert_eq!(format!("{:?}", B), "B"); assert_eq!(format!("{:?}", C), "C"); assert_eq!(format!("{:?}", ABC), "A | B | C | ABC"); } vendor/bitflags-1.0.1/0000755000000000000000000000000013264166600013303 5ustar rootrootvendor/bitflags-1.0.1/.cargo-checksum.json0000644000000000000000000000013113264166600017142 0ustar rootroot{"files":{},"package":"b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"}vendor/bitflags-1.0.1/.travis.yml0000664000000000000000000000111413264166600015413 0ustar rootrootos: - linux - osx language: rust cache: cargo rust: # This version is tested to avoid unintentional bumping of the minimum supported Rust version - 1.20.0 - stable - beta - nightly sudo: false script: - cargo test - (cd ./test_suite && cargo test $([ "$TRAVIS_RUST_VERSION" = nightly ] && echo '--features unstable')) env: global: - secure: "DoZ8g8iPs+X3xEEucke0Ae02JbkQ1qd1SSv/L2aQqxULmREtRcbzRauhiT+ToQO5Ft1Lul8uck14nPfs4gMr/O3jFFBhEBVpSlbkJx7eNL3kwUdp95UNroA8I43xPN/nccJaHDN6TMTD3+uajTQTje2SyzOQP+1gvdKg17kguvE=" notifications: email: on_success: never vendor/bitflags-1.0.1/CHANGELOG.md0000664000000000000000000000406613264166600015124 0ustar rootroot# 1.0.0 - **[breaking change]** Macro now generates [associated constants](https://doc.rust-lang.org/reference/items.html#associated-constants) (#24) - **[breaking change]** Minimum supported version is Rust **1.20**, due to usage of associated constants - After being broken in 0.9, the `#[deprecated]` attribute is now supported again (#112) - Other improvements to unit tests and documentation (#106 and #115) ## How to update your code to use associated constants Assuming the following structure definition: ```rust bitflags! { struct Something: u8 { const FOO = 0b01, const BAR = 0b10 } } ``` In 0.9 and older you could do: ```rust let x = FOO.bits | BAR.bits; ``` Now you must use: ```rust let x = Something::FOO.bits | Something::BAR.bits; ``` # 0.9.1 - Fix the implementation of `Formatting` traits when other formatting traits were present in scope (#105) # 0.9.0 - **[breaking change]** Use struct keyword instead of flags to define bitflag types (#84) - **[breaking change]** Terminate const items with semicolons instead of commas (#87) - Implement the `Hex`, `Octal`, and `Binary` formatting traits (#86) - Printing an empty flag value with the `Debug` trait now prints "(empty)" instead of nothing (#85) - The `bitflags!` macro can now be used inside of a fn body, to define a type local to that function (#74) # 0.8.2 - Update feature flag used when building bitflags as a dependency of the Rust toolchain # 0.8.1 - Allow bitflags to be used as a dependency of the Rust toolchain # 0.8.0 - Add support for the experimental `i128` and `u128` integer types (#57) - Add set method: `flags.set(SOME_FLAG, true)` or `flags.set(SOME_FLAG, false)` (#55) This may break code that defines its own set method # 0.7.1 *(yanked)* # 0.7.0 - Implement the Extend trait (#49) - Allow definitions inside the `bitflags!` macro to refer to items imported from other modules (#51) # 0.6.0 - The `no_std` feature was removed as it is now the default - The `assignment_operators` feature was remove as it is now enabled by default - Some clippy suggestions have been applied vendor/bitflags-1.0.1/Cargo.toml0000644000000000000000000000211713264166600015234 0ustar rootroot# 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 = "bitflags" version = "1.0.1" authors = ["The Rust Project Developers"] description = "A macro to generate structures which behave like bitflags.\n" homepage = "https://github.com/rust-lang-nursery/bitflags" documentation = "https://docs.rs/bitflags" readme = "README.md" keywords = ["bit", "bitmask", "bitflags", "flags"] categories = ["no-std"] license = "MIT/Apache-2.0" repository = "https://github.com/rust-lang-nursery/bitflags" [features] default = ["example_generated"] example_generated = [] [badges.travis-ci] repository = "rust-lang-nursery/bitflags" vendor/bitflags-1.0.1/LICENSE-APACHE0000664000000000000000000002513713264166600015241 0ustar rootroot 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. vendor/bitflags-1.0.1/LICENSE-MIT0000664000000000000000000000205713264166600014745 0ustar rootrootCopyright (c) 2014 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. vendor/bitflags-1.0.1/README.md0000664000000000000000000000115213264166600014563 0ustar rootrootbitflags ======== A Rust macro to generate structures which behave like a set of bitflags [![Build Status](https://travis-ci.org/rust-lang-nursery/bitflags.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/bitflags) - [Documentation](https://docs.rs/bitflags) - [Release notes](https://github.com/rust-lang-nursery/bitflags/releases) ## Usage Add this to your `Cargo.toml`: ```toml [dependencies] bitflags = "1.0" ``` and this to your crate root: ```rust #[macro_use] extern crate bitflags; ``` ## Rust Version Support The minimum supported Rust version is 1.20 due to use of associated constants. vendor/bitflags-1.0.1/src/0000755000000000000000000000000013264166600014072 5ustar rootrootvendor/bitflags-1.0.1/src/example_generated.rs0000664000000000000000000000107313264166600020114 0ustar rootroot//! This module shows an example of code generated by the macro. **IT MUST NOT BE USED OUTSIDE THIS //! CRATE**. bitflags! { /// This is the same `Flags` struct defined in the [crate level example](../index.html#example). /// Note that this struct is just for documentation purposes only, it must not be used outside /// this crate. pub struct Flags: u32 { const FLAG_A = 0b00000001; const FLAG_B = 0b00000010; const FLAG_C = 0b00000100; const FLAG_ABC = Self::FLAG_A.bits | Self::FLAG_B.bits | Self::FLAG_C.bits; } } vendor/bitflags-1.0.1/src/lib.rs0000664000000000000000000010261613264166600015216 0ustar rootroot// Copyright 2014 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! A typesafe bitmask flag generator useful for sets of C-style bitmask flags. //! It can be used for creating typesafe wrappers around C APIs. //! //! The `bitflags!` macro generates a `struct` that manages a set of flags. The //! flags should only be defined for integer types, otherwise unexpected type //! errors may occur at compile time. //! //! # Example //! //! ``` //! #[macro_use] //! extern crate bitflags; //! //! bitflags! { //! struct Flags: u32 { //! const A = 0b00000001; //! const B = 0b00000010; //! const C = 0b00000100; //! const ABC = Self::A.bits | Self::B.bits | Self::C.bits; //! } //! } //! //! fn main() { //! let e1 = Flags::A | Flags::C; //! let e2 = Flags::B | Flags::C; //! assert_eq!((e1 | e2), Flags::ABC); // union //! assert_eq!((e1 & e2), Flags::C); // intersection //! assert_eq!((e1 - e2), Flags::A); // set difference //! assert_eq!(!e2, Flags::A); // set complement //! } //! ``` //! //! See [`example_generated::Flags`](./example_generated/struct.Flags.html) for documentation of code //! generated by the above `bitflags!` expansion. //! //! The generated `struct`s can also be extended with type and trait //! implementations: //! //! ``` //! #[macro_use] //! extern crate bitflags; //! //! use std::fmt; //! //! bitflags! { //! struct Flags: u32 { //! const A = 0b00000001; //! const B = 0b00000010; //! } //! } //! //! impl Flags { //! pub fn clear(&mut self) { //! self.bits = 0; // The `bits` field can be accessed from within the //! // same module where the `bitflags!` macro was invoked. //! } //! } //! //! impl fmt::Display for Flags { //! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { //! write!(f, "hi!") //! } //! } //! //! fn main() { //! let mut flags = Flags::A | Flags::B; //! flags.clear(); //! assert!(flags.is_empty()); //! assert_eq!(format!("{}", flags), "hi!"); //! assert_eq!(format!("{:?}", Flags::A | Flags::B), "A | B"); //! assert_eq!(format!("{:?}", Flags::B), "B"); //! } //! ``` //! //! # Visibility //! //! The generated struct and its associated flag constants are not exported //! out of the current module by default. A definition can be exported out of //! the current module by adding `pub` before `flags`: //! //! ``` //! #[macro_use] //! extern crate bitflags; //! //! mod example { //! bitflags! { //! pub struct Flags1: u32 { //! const A = 0b00000001; //! } //! } //! bitflags! { //! # pub //! struct Flags2: u32 { //! const B = 0b00000010; //! } //! } //! } //! //! fn main() { //! let flag1 = example::Flags1::A; //! let flag2 = example::Flags2::B; // error: const `B` is private //! } //! ``` //! //! # Attributes //! //! Attributes can be attached to the generated `struct` by placing them //! before the `flags` keyword. //! //! # Trait implementations //! //! The `Copy`, `Clone`, `PartialEq`, `Eq`, `PartialOrd`, `Ord` and `Hash` //! traits automatically derived for the `struct` using the `derive` attribute. //! Additional traits can be derived by providing an explicit `derive` //! attribute on `flags`. //! //! The `Extend` and `FromIterator` traits are implemented for the `struct`, //! too: `Extend` adds the union of the instances of the `struct` iterated over, //! while `FromIterator` calculates the union. //! //! The `Binary`, `Debug`, `LowerExp`, `Octal` and `UpperExp` trait is also //! implemented by displaying the bits value of the internal struct. //! //! ## Operators //! //! The following operator traits are implemented for the generated `struct`: //! //! - `BitOr` and `BitOrAssign`: union //! - `BitAnd` and `BitAndAssign`: intersection //! - `BitXor` and `BitXorAssign`: toggle //! - `Sub` and `SubAssign`: set difference //! - `Not`: set complement //! //! # Methods //! //! The following methods are defined for the generated `struct`: //! //! - `empty`: an empty set of flags //! - `all`: the set of all flags //! - `bits`: the raw value of the flags currently stored //! - `from_bits`: convert from underlying bit representation, unless that //! representation contains bits that do not correspond to a flag //! - `from_bits_truncate`: convert from underlying bit representation, dropping //! any bits that do not correspond to flags //! - `is_empty`: `true` if no flags are currently stored //! - `is_all`: `true` if all flags are currently set //! - `intersects`: `true` if there are flags common to both `self` and `other` //! - `contains`: `true` all of the flags in `other` are contained within `self` //! - `insert`: inserts the specified flags in-place //! - `remove`: removes the specified flags in-place //! - `toggle`: the specified flags will be inserted if not present, and removed //! if they are. //! - `set`: inserts or removes the specified flags depending on the passed value //! //! ## Default //! //! The `Default` trait is not automatically implemented for the generated struct. //! //! If your default value is equal to `0` (which is the same value as calling `empty()` //! on the generated struct), you can simply derive `Default`: //! //! ``` //! #[macro_use] //! extern crate bitflags; //! //! bitflags! { //! // Results in default value with bits: 0 //! #[derive(Default)] //! struct Flags: u32 { //! const A = 0b00000001; //! const B = 0b00000010; //! const C = 0b00000100; //! } //! } //! //! fn main() { //! let derived_default: Flags = Default::default(); //! assert_eq!(derived_default.bits(), 0); //! } //! ``` //! //! If your default value is not equal to `0` you need to implement `Default` yourself: //! //! ``` //! #[macro_use] //! extern crate bitflags; //! //! bitflags! { //! struct Flags: u32 { //! const A = 0b00000001; //! const B = 0b00000010; //! const C = 0b00000100; //! } //! } //! //! // explicit `Default` implementation //! impl Default for Flags { //! fn default() -> Flags { //! Flags::A | Flags::C //! } //! } //! //! fn main() { //! let implemented_default: Flags = Default::default(); //! assert_eq!(implemented_default, (Flags::A | Flags::C)); //! } //! ``` #![no_std] #![doc(html_root_url = "https://docs.rs/bitflags/1.0.1")] #[cfg(test)] #[macro_use] extern crate std; // Re-export libcore using an alias so that the macros can work without // requiring `extern crate core` downstream. #[doc(hidden)] pub extern crate core as _core; /// The macro used to generate the flag structure. /// /// See the [crate level docs](../bitflags/index.html) for complete documentation. /// /// # Example /// /// ``` /// #[macro_use] /// extern crate bitflags; /// /// bitflags! { /// struct Flags: u32 { /// const A = 0b00000001; /// const B = 0b00000010; /// const C = 0b00000100; /// const ABC = Self::A.bits | Self::B.bits | Self::C.bits; /// } /// } /// /// fn main() { /// let e1 = Flags::A | Flags::C; /// let e2 = Flags::B | Flags::C; /// assert_eq!((e1 | e2), Flags::ABC); // union /// assert_eq!((e1 & e2), Flags::C); // intersection /// assert_eq!((e1 - e2), Flags::A); // set difference /// assert_eq!(!e2, Flags::A); // set complement /// } /// ``` /// /// The generated `struct`s can also be extended with type and trait /// implementations: /// /// ``` /// #[macro_use] /// extern crate bitflags; /// /// use std::fmt; /// /// bitflags! { /// struct Flags: u32 { /// const A = 0b00000001; /// const B = 0b00000010; /// } /// } /// /// impl Flags { /// pub fn clear(&mut self) { /// self.bits = 0; // The `bits` field can be accessed from within the /// // same module where the `bitflags!` macro was invoked. /// } /// } /// /// impl fmt::Display for Flags { /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { /// write!(f, "hi!") /// } /// } /// /// fn main() { /// let mut flags = Flags::A | Flags::B; /// flags.clear(); /// assert!(flags.is_empty()); /// assert_eq!(format!("{}", flags), "hi!"); /// assert_eq!(format!("{:?}", Flags::A | Flags::B), "A | B"); /// assert_eq!(format!("{:?}", Flags::B), "B"); /// } /// ``` #[macro_export] macro_rules! bitflags { ( $(#[$outer:meta])* pub struct $BitFlags:ident: $T:ty { $( $(#[$inner:ident $($args:tt)*])* const $Flag:ident = $value:expr; )+ } ) => { __bitflags! { $(#[$outer])* (pub) $BitFlags: $T { $( $(#[$inner $($args)*])* $Flag = $value; )+ } } }; ( $(#[$outer:meta])* struct $BitFlags:ident: $T:ty { $( $(#[$inner:ident $($args:tt)*])* const $Flag:ident = $value:expr; )+ } ) => { __bitflags! { $(#[$outer])* () $BitFlags: $T { $( $(#[$inner $($args)*])* $Flag = $value; )+ } } }; ( $(#[$outer:meta])* pub ($($vis:tt)+) struct $BitFlags:ident: $T:ty { $( $(#[$inner:ident $($args:tt)*])* const $Flag:ident = $value:expr; )+ } ) => { __bitflags! { $(#[$outer])* (pub ($($vis)+)) $BitFlags: $T { $( $(#[$inner $($args)*])* $Flag = $value; )+ } } }; } #[macro_export] #[doc(hidden)] macro_rules! __bitflags { ( $(#[$outer:meta])* ($($vis:tt)*) $BitFlags:ident: $T:ty { $( $(#[$inner:ident $($args:tt)*])* $Flag:ident = $value:expr; )+ } ) => { #[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)] $(#[$outer])* $($vis)* struct $BitFlags { bits: $T, } __impl_bitflags! { $BitFlags: $T { $( $(#[$inner $($args)*])* $Flag = $value; )+ } } }; } #[macro_export] #[doc(hidden)] macro_rules! __impl_bitflags { ( $BitFlags:ident: $T:ty { $( $(#[$attr:ident $($args:tt)*])* $Flag:ident = $value:expr; )+ } ) => { impl $crate::_core::fmt::Debug for $BitFlags { fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { // This convoluted approach is to handle #[cfg]-based flag // omission correctly. For example it needs to support: // // #[cfg(unix)] const A: Flag = /* ... */; // #[cfg(windows)] const B: Flag = /* ... */; // Unconditionally define a check for every flag, even disabled // ones. #[allow(non_snake_case)] trait __BitFlags { $( #[inline] fn $Flag(&self) -> bool { false } )+ } // Conditionally override the check for just those flags that // are not #[cfg]ed away. impl __BitFlags for $BitFlags { $( __impl_bitflags! { #[allow(deprecated)] #[inline] $(? #[$attr $($args)*])* fn $Flag(&self) -> bool { self.bits & Self::$Flag.bits == Self::$Flag.bits } } )+ } let mut first = true; $( if <$BitFlags as __BitFlags>::$Flag(self) { if !first { try!(f.write_str(" | ")); } first = false; try!(f.write_str(stringify!($Flag))); } )+ if first { try!(f.write_str("(empty)")); } Ok(()) } } impl $crate::_core::fmt::Binary for $BitFlags { fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { $crate::_core::fmt::Binary::fmt(&self.bits, f) } } impl $crate::_core::fmt::Octal for $BitFlags { fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { $crate::_core::fmt::Octal::fmt(&self.bits, f) } } impl $crate::_core::fmt::LowerHex for $BitFlags { fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { $crate::_core::fmt::LowerHex::fmt(&self.bits, f) } } impl $crate::_core::fmt::UpperHex for $BitFlags { fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { $crate::_core::fmt::UpperHex::fmt(&self.bits, f) } } #[allow(dead_code)] impl $BitFlags { $( $(#[$attr $($args)*])* pub const $Flag: $BitFlags = $BitFlags { bits: $value }; )+ /// Returns an empty set of flags. #[inline] pub fn empty() -> $BitFlags { $BitFlags { bits: 0 } } /// Returns the set containing all flags. #[inline] pub fn all() -> $BitFlags { // See `Debug::fmt` for why this approach is taken. #[allow(non_snake_case)] trait __BitFlags { $( #[inline] fn $Flag() -> $T { 0 } )+ } impl __BitFlags for $BitFlags { $( __impl_bitflags! { #[allow(deprecated)] #[inline] $(? #[$attr $($args)*])* fn $Flag() -> $T { Self::$Flag.bits } } )+ } $BitFlags { bits: $(<$BitFlags as __BitFlags>::$Flag())|+ } } /// Returns the raw value of the flags currently stored. #[inline] pub fn bits(&self) -> $T { self.bits } /// Convert from underlying bit representation, unless that /// representation contains bits that do not correspond to a flag. #[inline] pub fn from_bits(bits: $T) -> $crate::_core::option::Option<$BitFlags> { if (bits & !$BitFlags::all().bits()) == 0 { $crate::_core::option::Option::Some($BitFlags { bits: bits }) } else { $crate::_core::option::Option::None } } /// Convert from underlying bit representation, dropping any bits /// that do not correspond to flags. #[inline] pub fn from_bits_truncate(bits: $T) -> $BitFlags { $BitFlags { bits: bits } & $BitFlags::all() } /// Returns `true` if no flags are currently stored. #[inline] pub fn is_empty(&self) -> bool { *self == $BitFlags::empty() } /// Returns `true` if all flags are currently set. #[inline] pub fn is_all(&self) -> bool { *self == $BitFlags::all() } /// Returns `true` if there are flags common to both `self` and `other`. #[inline] pub fn intersects(&self, other: $BitFlags) -> bool { !(*self & other).is_empty() } /// Returns `true` all of the flags in `other` are contained within `self`. #[inline] pub fn contains(&self, other: $BitFlags) -> bool { (*self & other) == other } /// Inserts the specified flags in-place. #[inline] pub fn insert(&mut self, other: $BitFlags) { self.bits |= other.bits; } /// Removes the specified flags in-place. #[inline] pub fn remove(&mut self, other: $BitFlags) { self.bits &= !other.bits; } /// Toggles the specified flags in-place. #[inline] pub fn toggle(&mut self, other: $BitFlags) { self.bits ^= other.bits; } /// Inserts or removes the specified flags depending on the passed value. #[inline] pub fn set(&mut self, other: $BitFlags, value: bool) { if value { self.insert(other); } else { self.remove(other); } } } impl $crate::_core::ops::BitOr for $BitFlags { type Output = $BitFlags; /// Returns the union of the two sets of flags. #[inline] fn bitor(self, other: $BitFlags) -> $BitFlags { $BitFlags { bits: self.bits | other.bits } } } impl $crate::_core::ops::BitOrAssign for $BitFlags { /// Adds the set of flags. #[inline] fn bitor_assign(&mut self, other: $BitFlags) { self.bits |= other.bits; } } impl $crate::_core::ops::BitXor for $BitFlags { type Output = $BitFlags; /// Returns the left flags, but with all the right flags toggled. #[inline] fn bitxor(self, other: $BitFlags) -> $BitFlags { $BitFlags { bits: self.bits ^ other.bits } } } impl $crate::_core::ops::BitXorAssign for $BitFlags { /// Toggles the set of flags. #[inline] fn bitxor_assign(&mut self, other: $BitFlags) { self.bits ^= other.bits; } } impl $crate::_core::ops::BitAnd for $BitFlags { type Output = $BitFlags; /// Returns the intersection between the two sets of flags. #[inline] fn bitand(self, other: $BitFlags) -> $BitFlags { $BitFlags { bits: self.bits & other.bits } } } impl $crate::_core::ops::BitAndAssign for $BitFlags { /// Disables all flags disabled in the set. #[inline] fn bitand_assign(&mut self, other: $BitFlags) { self.bits &= other.bits; } } impl $crate::_core::ops::Sub for $BitFlags { type Output = $BitFlags; /// Returns the set difference of the two sets of flags. #[inline] fn sub(self, other: $BitFlags) -> $BitFlags { $BitFlags { bits: self.bits & !other.bits } } } impl $crate::_core::ops::SubAssign for $BitFlags { /// Disables all flags enabled in the set. #[inline] fn sub_assign(&mut self, other: $BitFlags) { self.bits &= !other.bits; } } impl $crate::_core::ops::Not for $BitFlags { type Output = $BitFlags; /// Returns the complement of this set of flags. #[inline] fn not(self) -> $BitFlags { $BitFlags { bits: !self.bits } & $BitFlags::all() } } impl $crate::_core::iter::Extend<$BitFlags> for $BitFlags { fn extend>(&mut self, iterator: T) { for item in iterator { self.insert(item) } } } impl $crate::_core::iter::FromIterator<$BitFlags> for $BitFlags { fn from_iter>(iterator: T) -> $BitFlags { let mut result = Self::empty(); result.extend(iterator); result } } }; // Every attribute that the user writes on a const is applied to the // corresponding const that we generate, but within the implementation of // Debug and all() we want to ignore everything but #[cfg] attributes. In // particular, including a #[deprecated] attribute on those items would fail // to compile. // https://github.com/rust-lang-nursery/bitflags/issues/109 // // Input: // // ? #[cfg(feature = "advanced")] // ? #[deprecated(note = "Use somthing else.")] // ? #[doc = r"High quality documentation."] // fn f() -> i32 { /* ... */ } // // Output: // // #[cfg(feature = "advanced")] // fn f() -> i32 { /* ... */ } ( $(#[$filtered:meta])* ? #[cfg $($cfgargs:tt)*] $(? #[$rest:ident $($restargs:tt)*])* fn $($item:tt)* ) => { __impl_bitflags! { $(#[$filtered])* #[cfg $($cfgargs)*] $(? #[$rest $($restargs)*])* fn $($item)* } }; ( $(#[$filtered:meta])* // $next != `cfg` ? #[$next:ident $($nextargs:tt)*] $(? #[$rest:ident $($restargs:tt)*])* fn $($item:tt)* ) => { __impl_bitflags! { $(#[$filtered])* // $next filtered out $(? #[$rest $($restargs)*])* fn $($item)* } }; ( $(#[$filtered:meta])* fn $($item:tt)* ) => { $(#[$filtered])* fn $($item)* }; } #[cfg(feature = "example_generated")] pub mod example_generated; #[cfg(test)] mod tests { use std::hash::{Hash, Hasher}; use std::collections::hash_map::DefaultHasher; bitflags! { #[doc = "> The first principle is that you must not fool yourself — and"] #[doc = "> you are the easiest person to fool."] #[doc = "> "] #[doc = "> - Richard Feynman"] struct Flags: u32 { const A = 0b00000001; #[doc = " macros are way better at generating code than trans is"] const B = 0b00000010; const C = 0b00000100; #[doc = "* cmr bed"] #[doc = "* strcat table"] #[doc = " wait what?"] const ABC = Self::A.bits | Self::B.bits | Self::C.bits; } } bitflags! { struct _CfgFlags: u32 { #[cfg(windows)] const _CFG_A = 0b01; #[cfg(unix)] const _CFG_B = 0b01; #[cfg(windows)] const _CFG_C = _CFG_A.bits | 0b10; } } bitflags! { struct AnotherSetOfFlags: i8 { const ANOTHER_FLAG = -1_i8; } } bitflags! { struct LongFlags: u32 { const LONG_A = 0b1111111111111111; } } #[test] fn test_bits(){ assert_eq!(Flags::empty().bits(), 0b00000000); assert_eq!(Flags::A.bits(), 0b00000001); assert_eq!(Flags::ABC.bits(), 0b00000111); assert_eq!(AnotherSetOfFlags::empty().bits(), 0b00); assert_eq!(AnotherSetOfFlags::ANOTHER_FLAG.bits(), !0_i8); } #[test] fn test_from_bits() { assert_eq!(Flags::from_bits(0), Some(Flags::empty())); assert_eq!(Flags::from_bits(0b1), Some(Flags::A)); assert_eq!(Flags::from_bits(0b10), Some(Flags::B)); assert_eq!(Flags::from_bits(0b11), Some(Flags::A | Flags::B)); assert_eq!(Flags::from_bits(0b1000), None); assert_eq!(AnotherSetOfFlags::from_bits(!0_i8), Some(AnotherSetOfFlags::ANOTHER_FLAG)); } #[test] fn test_from_bits_truncate() { assert_eq!(Flags::from_bits_truncate(0), Flags::empty()); assert_eq!(Flags::from_bits_truncate(0b1), Flags::A); assert_eq!(Flags::from_bits_truncate(0b10), Flags::B); assert_eq!(Flags::from_bits_truncate(0b11), (Flags::A | Flags::B)); assert_eq!(Flags::from_bits_truncate(0b1000), Flags::empty()); assert_eq!(Flags::from_bits_truncate(0b1001), Flags::A); assert_eq!(AnotherSetOfFlags::from_bits_truncate(0_i8), AnotherSetOfFlags::empty()); } #[test] fn test_is_empty(){ assert!(Flags::empty().is_empty()); assert!(!Flags::A.is_empty()); assert!(!Flags::ABC.is_empty()); assert!(!AnotherSetOfFlags::ANOTHER_FLAG.is_empty()); } #[test] fn test_is_all() { assert!(Flags::all().is_all()); assert!(!Flags::A.is_all()); assert!(Flags::ABC.is_all()); assert!(AnotherSetOfFlags::ANOTHER_FLAG.is_all()); } #[test] fn test_two_empties_do_not_intersect() { let e1 = Flags::empty(); let e2 = Flags::empty(); assert!(!e1.intersects(e2)); assert!(AnotherSetOfFlags::ANOTHER_FLAG.intersects(AnotherSetOfFlags::ANOTHER_FLAG)); } #[test] fn test_empty_does_not_intersect_with_full() { let e1 = Flags::empty(); let e2 = Flags::ABC; assert!(!e1.intersects(e2)); } #[test] fn test_disjoint_intersects() { let e1 = Flags::A; let e2 = Flags::B; assert!(!e1.intersects(e2)); } #[test] fn test_overlapping_intersects() { let e1 = Flags::A; let e2 = Flags::A | Flags::B; assert!(e1.intersects(e2)); } #[test] fn test_contains() { let e1 = Flags::A; let e2 = Flags::A | Flags::B; assert!(!e1.contains(e2)); assert!(e2.contains(e1)); assert!(Flags::ABC.contains(e2)); assert!(AnotherSetOfFlags::ANOTHER_FLAG.contains(AnotherSetOfFlags::ANOTHER_FLAG)); } #[test] fn test_insert(){ let mut e1 = Flags::A; let e2 = Flags::A | Flags::B; e1.insert(e2); assert_eq!(e1, e2); let mut e3 = AnotherSetOfFlags::empty(); e3.insert(AnotherSetOfFlags::ANOTHER_FLAG); assert_eq!(e3, AnotherSetOfFlags::ANOTHER_FLAG); } #[test] fn test_remove(){ let mut e1 = Flags::A | Flags::B; let e2 = Flags::A | Flags::C; e1.remove(e2); assert_eq!(e1, Flags::B); let mut e3 = AnotherSetOfFlags::ANOTHER_FLAG; e3.remove(AnotherSetOfFlags::ANOTHER_FLAG); assert_eq!(e3, AnotherSetOfFlags::empty()); } #[test] fn test_operators() { let e1 = Flags::A | Flags::C; let e2 = Flags::B | Flags::C; assert_eq!((e1 | e2), Flags::ABC); // union assert_eq!((e1 & e2), Flags::C); // intersection assert_eq!((e1 - e2), Flags::A); // set difference assert_eq!(!e2, Flags::A); // set complement assert_eq!(e1 ^ e2, Flags::A | Flags::B); // toggle let mut e3 = e1; e3.toggle(e2); assert_eq!(e3, Flags::A | Flags::B); let mut m4 = AnotherSetOfFlags::empty(); m4.toggle(AnotherSetOfFlags::empty()); assert_eq!(m4, AnotherSetOfFlags::empty()); } #[test] fn test_set() { let mut e1 = Flags::A | Flags::C; e1.set(Flags::B, true); e1.set(Flags::C, false); assert_eq!(e1, Flags::A | Flags::B); } #[test] fn test_assignment_operators() { let mut m1 = Flags::empty(); let e1 = Flags::A | Flags::C; // union m1 |= Flags::A; assert_eq!(m1, Flags::A); // intersection m1 &= e1; assert_eq!(m1, Flags::A); // set difference m1 -= m1; assert_eq!(m1, Flags::empty()); // toggle m1 ^= e1; assert_eq!(m1, e1); } #[test] fn test_extend() { let mut flags; flags = Flags::empty(); flags.extend([].iter().cloned()); assert_eq!(flags, Flags::empty()); flags = Flags::empty(); flags.extend([Flags::A, Flags::B].iter().cloned()); assert_eq!(flags, Flags::A | Flags::B); flags = Flags::A; flags.extend([Flags::A, Flags::B].iter().cloned()); assert_eq!(flags, Flags::A | Flags::B); flags = Flags::B; flags.extend([Flags::A, Flags::ABC].iter().cloned()); assert_eq!(flags, Flags::ABC); } #[test] fn test_from_iterator() { assert_eq!([].iter().cloned().collect::(), Flags::empty()); assert_eq!([Flags::A, Flags::B].iter().cloned().collect::(), Flags::A | Flags::B); assert_eq!([Flags::A, Flags::ABC].iter().cloned().collect::(), Flags::ABC); } #[test] fn test_lt() { let mut a = Flags::empty(); let mut b = Flags::empty(); assert!(!(a < b) && !(b < a)); b = Flags::B; assert!(a < b); a = Flags::C; assert!(!(a < b) && b < a); b = Flags::C | Flags::B; assert!(a < b); } #[test] fn test_ord() { let mut a = Flags::empty(); let mut b = Flags::empty(); assert!(a <= b && a >= b); a = Flags::A; assert!(a > b && a >= b); assert!(b < a && b <= a); b = Flags::B; assert!(b > a && b >= a); assert!(a < b && a <= b); } fn hash(t: &T) -> u64 { let mut s = DefaultHasher::new(); t.hash(&mut s); s.finish() } #[test] fn test_hash() { let mut x = Flags::empty(); let mut y = Flags::empty(); assert_eq!(hash(&x), hash(&y)); x = Flags::all(); y = Flags::ABC; assert_eq!(hash(&x), hash(&y)); } #[test] fn test_debug() { assert_eq!(format!("{:?}", Flags::A | Flags::B), "A | B"); assert_eq!(format!("{:?}", Flags::empty()), "(empty)"); assert_eq!(format!("{:?}", Flags::ABC), "A | B | C | ABC"); } #[test] fn test_binary() { assert_eq!(format!("{:b}", Flags::ABC), "111"); assert_eq!(format!("{:#b}", Flags::ABC), "0b111"); } #[test] fn test_octal() { assert_eq!(format!("{:o}", LongFlags::LONG_A), "177777"); assert_eq!(format!("{:#o}", LongFlags::LONG_A), "0o177777"); } #[test] fn test_lowerhex() { assert_eq!(format!("{:x}", LongFlags::LONG_A), "ffff"); assert_eq!(format!("{:#x}", LongFlags::LONG_A), "0xffff"); } #[test] fn test_upperhex() { assert_eq!(format!("{:X}", LongFlags::LONG_A), "FFFF"); assert_eq!(format!("{:#X}", LongFlags::LONG_A), "0xFFFF"); } mod submodule { bitflags! { pub struct PublicFlags: i8 { const X = 0; } } bitflags! { struct PrivateFlags: i8 { const Y = 0; } } #[test] fn test_private() { let _ = PrivateFlags::Y; } } #[test] fn test_public() { let _ = submodule::PublicFlags::X; } mod t1 { mod foo { pub type Bar = i32; } bitflags! { /// baz struct Flags: foo::Bar { const A = 0b00000001; #[cfg(foo)] const B = 0b00000010; #[cfg(foo)] const C = 0b00000010; } } } #[test] fn test_in_function() { bitflags! { struct Flags: u8 { const A = 1; #[cfg(any())] // false const B = 2; } } assert_eq!(Flags::all(), Flags::A); assert_eq!(format!("{:?}", Flags::A), "A"); } #[test] fn test_deprecated() { bitflags! { pub struct TestFlags: u32 { #[deprecated(note = "Use something else.")] const ONE = 1; } } } #[test] fn test_pub_crate() { mod module { bitflags! { pub (crate) struct Test: u8 { const FOO = 1; } } } assert_eq!(module::Test::FOO.bits(), 1); } #[test] fn test_pub_in_module() { mod module { mod submodule { bitflags! { // `pub (in super)` means only the module `module` will // be able to access this. pub (in super) struct Test: u8 { const FOO = 1; } } } mod test { // Note: due to `pub (in super)`, // this cannot be accessed directly by the testing code. pub (in super) fn value() -> u8 { super::submodule::Test::FOO.bits() } } pub fn value() -> u8 { test::value() } } assert_eq!(module::value(), 1) } } vendor/bufstream-0.1.3/0000755000000000000000000000000013264166600013502 5ustar rootrootvendor/bufstream-0.1.3/.cargo-checksum.json0000644000000000000000000000013113264166600017341 0ustar rootroot{"files":{},"package":"f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32"}vendor/bufstream-0.1.3/.travis.yml0000664000000000000000000000112213264166600015611 0ustar rootrootlanguage: rust rust: - stable - beta - nightly sudo: false before_script: - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH script: - cargo build --verbose - cargo test --verbose - cargo test --verbose --features tokio - cargo doc --no-deps after_success: - travis-cargo --only nightly doc-upload env: global: secure: "G857gdm63OJ2wcwdEBBeY+53D/zRSSmPfAp/H+8vRy5nnB+4GBq5Xqugq9n4BrvJMoPLMMMAmB46Chk7HHkkk/e4WTQ2orX61c4nNF3b4rdik6fzwVKk4Gy06FlM63cEa9/1iN2BiOg6NA81cmrUrK1ezIdg+8YECsiVu9+7m2g=" notifications: email: on_success: never vendor/bufstream-0.1.3/Cargo.toml0000664000000000000000000000105013264166600015430 0ustar rootroot[package] name = "bufstream" version = "0.1.3" authors = ["The Rust Project Developers"] license = "MIT/Apache-2.0" repository = "https://github.com/alexcrichton/bufstream" homepage = "https://github.com/alexcrichton/bufstream" documentation = "http://alexcrichton.com/bufstream" description = """ Buffered I/O for streams where each read/write half is separately buffered """ [dependencies.futures] optional = true version = "0.1.13" [dependencies.tokio-io] optional = true version = "0.1.1" [features] default = [] tokio = ["futures", "tokio-io"] vendor/bufstream-0.1.3/LICENSE-APACHE0000664000000000000000000002513713264166600015440 0ustar rootroot 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. vendor/bufstream-0.1.3/LICENSE-MIT0000664000000000000000000000205713264166600015144 0ustar rootrootCopyright (c) 2014 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. vendor/bufstream-0.1.3/README.md0000664000000000000000000000114613264166600014765 0ustar rootrootbufstream ========= Buffered I/O streams for reading/writing [![Build Status](https://travis-ci.org/alexcrichton/bufstream.svg?branch=master)](https://travis-ci.org/alexcrichton/bufstream) [Documentation](http://alexcrichton.com/bufstream) ## Usage ```toml [dependencies] bufstream = "0.1" ``` ## Tokio There is support for tokio's `AsyncRead` + `AsyncWrite` traits through the `tokio` feature. When using this crate with asynchronous IO, make sure to properly flush the stream before dropping it since IO during drop may cause panics. For the same reason you should stay away from `BufStream::into_inner`. vendor/bufstream-0.1.3/src/0000755000000000000000000000000013264166600014271 5ustar rootrootvendor/bufstream-0.1.3/src/lib.rs0000664000000000000000000002077613264166600015423 0ustar rootroot// 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! A crate for separately buffered streams. //! //! This crate provides a `BufStream` type which provides buffering of both the //! reading and writing halves of a `Read + Write` type. Each half is completely //! independently buffered of the other, which may not always be desired. For //! example `BufStream` may have surprising semantics. //! //! # Usage //! //! ```toml //! [dependencies] //! bufstream = "0.1" //! ``` //! //! ```no_run //! use std::io::prelude::*; //! use std::net::TcpStream; //! use bufstream::BufStream; //! //! //! let stream = TcpStream::connect("localhost:4000").unwrap(); //! let mut buf = BufStream::new(stream); //! buf.read(&mut [0; 1024]).unwrap(); //! buf.write(&[0; 1024]).unwrap(); //! ``` //! //! # Async I/O //! //! This crate optionally can support async I/O streams with the [Tokio stack] via //! the `tokio` feature of this crate: //! //! [Tokio stack]: https://tokio.rs/ //! //! ```toml //! bufstream = { version = "0.2", features = ["tokio"] } //! ``` //! //! All methods are internally capable of working with streams that may return //! [`ErrorKind::WouldBlock`] when they're not ready to perform the particular //! operation. //! //! [`ErrorKind::WouldBlock`]: https://doc.rust-lang.org/std/io/enum.ErrorKind.html //! //! Note that care needs to be taken when using these objects, however. The //! Tokio runtime, in particular, requires that data is fully flushed before //! dropping streams. For compatibility with blocking streams all streams are //! flushed/written when they are dropped, and this is not always a suitable //! time to perform I/O. If I/O streams are flushed before drop, however, then //! these operations will be a noop. #[cfg(feature = "tokio")] extern crate futures; #[cfg(feature = "tokio")] #[macro_use] extern crate tokio_io; use std::fmt; use std::io::prelude::*; use std::io::{self, BufReader, BufWriter}; use std::error; #[cfg(feature = "tokio")] use futures::Poll; #[cfg(feature = "tokio")] use tokio_io::{AsyncRead, AsyncWrite}; const DEFAULT_BUF_SIZE: usize = 8 * 1024; /// Wraps a Stream and buffers input and output to and from it. /// /// It can be excessively inefficient to work directly with a `Read+Write`. For /// example, every call to `read` or `write` on `TcpStream` results in a system /// call. A `BufStream` keeps in memory buffers of data, making large, /// infrequent calls to `read` and `write` on the underlying `Read+Write`. /// /// The output buffer will be written out when this stream is dropped. #[derive(Debug)] pub struct BufStream { inner: BufReader> } /// An error returned by `into_inner` which combines an error that /// happened while writing out the buffer, and the buffered writer object /// which may be used to recover from the condition. #[derive(Debug)] pub struct IntoInnerError(W, io::Error); impl IntoInnerError { /// Returns the error which caused the call to `into_inner()` to fail. /// /// This error was returned when attempting to write the internal buffer. pub fn error(&self) -> &io::Error { &self.1 } /// Returns the buffered writer instance which generated the error. /// /// The returned object can be used for error recovery, such as /// re-inspecting the buffer. pub fn into_inner(self) -> W { self.0 } } impl From> for io::Error { fn from(iie: IntoInnerError) -> io::Error { iie.1 } } impl error::Error for IntoInnerError { fn description(&self) -> &str { error::Error::description(self.error()) } } impl fmt::Display for IntoInnerError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.error().fmt(f) } } struct InternalBufWriter(Option>); impl InternalBufWriter { fn get_ref(&self) -> &BufWriter { self.0.as_ref().unwrap() } fn get_mut(&mut self) -> &mut BufWriter { self.0.as_mut().unwrap() } } impl Read for InternalBufWriter { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.get_mut().get_mut().read(buf) } } impl fmt::Debug for InternalBufWriter { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.get_ref().fmt(f) } } impl BufStream { /// Creates a new buffered stream with explicitly listed capacities for the /// reader/writer buffer. pub fn with_capacities(reader_cap: usize, writer_cap: usize, inner: S) -> BufStream { let writer = BufWriter::with_capacity(writer_cap, inner); let internal_writer = InternalBufWriter(Some(writer)); let reader = BufReader::with_capacity(reader_cap, internal_writer); BufStream { inner: reader } } /// Creates a new buffered stream with the default reader/writer buffer /// capacities. pub fn new(inner: S) -> BufStream { BufStream::with_capacities(DEFAULT_BUF_SIZE, DEFAULT_BUF_SIZE, inner) } /// Gets a reference to the underlying stream. pub fn get_ref(&self) -> &S { self.inner.get_ref().get_ref().get_ref() } /// Gets a mutable reference to the underlying stream. /// /// # Warning /// /// It is inadvisable to read directly from or write directly to the /// underlying stream. pub fn get_mut(&mut self) -> &mut S { self.inner.get_mut().get_mut().get_mut() } /// Unwraps this `BufStream`, returning the underlying stream. /// /// The internal write buffer is written out before returning the stream. /// Any leftover data in the read buffer is lost. pub fn into_inner(mut self) -> Result>> { let e = { let InternalBufWriter(ref mut w) = *self.inner.get_mut(); let (e, w2) = match w.take().unwrap().into_inner() { Ok(s) => return Ok(s), Err(err) => { (io::Error::new(err.error().kind(), err.error().to_string()), err.into_inner()) } }; *w = Some(w2); e }; Err(IntoInnerError(self, e)) } } impl BufRead for BufStream { fn fill_buf(&mut self) -> io::Result<&[u8]> { self.inner.fill_buf() } fn consume(&mut self, amt: usize) { self.inner.consume(amt) } fn read_until(&mut self, byte: u8, buf: &mut Vec) -> io::Result { self.inner.read_until(byte, buf) } fn read_line(&mut self, string: &mut String) -> io::Result { self.inner.read_line(string) } } impl Read for BufStream { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.read(buf) } } impl Write for BufStream { fn write(&mut self, buf: &[u8]) -> io::Result { self.inner.get_mut().0.as_mut().unwrap().write(buf) } fn flush(&mut self) -> io::Result<()> { self.inner.get_mut().0.as_mut().unwrap().flush() } } #[cfg(feature = "tokio")] impl AsyncRead for BufStream {} #[cfg(feature = "tokio")] impl AsyncWrite for BufStream { fn shutdown(&mut self) -> Poll<(), io::Error> { try_nb!(self.flush()); let mut inner = self.inner.get_mut().0.as_mut().unwrap(); inner.shutdown() } } #[cfg(test)] mod tests { use std::io::prelude::*; use std::io; use super::BufStream; // This is just here to make sure that we don't infinite loop in the // newtype struct autoderef weirdness #[test] fn test_buffered_stream() { struct S; impl Write for S { fn write(&mut self, b: &[u8]) -> io::Result { Ok(b.len()) } fn flush(&mut self) -> io::Result<()> { Ok(()) } } impl Read for S { fn read(&mut self, _: &mut [u8]) -> io::Result { Ok(0) } } let mut stream = BufStream::new(S); assert_eq!(stream.read(&mut [0; 10]).unwrap(), 0); stream.write(&[0; 10]).unwrap(); stream.flush().unwrap(); } } vendor/cc-1.0.10/0000755000000000000000000000000013264166600012155 5ustar rootrootvendor/cc-1.0.10/.cargo-checksum.json0000644000000000000000000000013113264166600016014 0ustar rootroot{"files":{},"package":"8b9d2900f78631a5876dc5d6c9033ede027253efcd33dd36b1309fc6cab97ee0"}vendor/cc-1.0.10/.travis.yml0000664000000000000000000000347513264166600014301 0ustar rootrootlanguage: rust sudo: false matrix: include: - rust: 1.13.0 install: script: cargo build - rust: stable env: TARGET=x86_64-unknown-linux-gnu NO_ADD=1 - rust: stable env: TARGET=i686-unknown-linux-gnu - os: osx env: TARGET=x86_64-apple-darwin NO_ADD=1 - os: osx env: TARGET=aarch64-apple-ios NO_RUN=--no-run TARGET_SYSROOT=$(xcrun -sdk iphoneos --show-sdk-path) - rust: beta env: TARGET=x86_64-unknown-linux-gnu NO_ADD=1 - rust: nightly env: TARGET=x86_64-unknown-linux-gnu NO_ADD=1 - install: rustup component add rustfmt-preview script: - cargo fmt -- --write-mode diff - (cd cc-test && cargo fmt -- --write-mode diff) - rust: nightly before_script: - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH install: script: - cargo doc --no-deps --all-features after_success: - travis-cargo --only nightly doc-upload install: - if [ -z "$NO_ADD" ]; then rustup target add $TARGET; fi script: - cargo build --verbose - cargo test --verbose $NO_RUN - cargo test --verbose --features parallel $NO_RUN - cargo test --manifest-path cc-test/Cargo.toml --target $TARGET $NO_RUN - cargo test --manifest-path cc-test/Cargo.toml --target $TARGET --features parallel $NO_RUN - cargo test --manifest-path cc-test/Cargo.toml --target $TARGET --release $NO_RUN - cargo doc - cargo clean && cargo build - rustdoc --test README.md -L target/debug -L target/debug/deps env: global: secure: "CBtqrudgE0PS8x3kTr44jKbC2D4nfnmdYVecooNm0qnER4B4TSvZpZSQoCgKK6k4BYQuOSyFTOwYx6M79w39ZMOgyCP9ytB+tyMWL0/+ZuUQL04yVg4M5vd3oJMkOaXbvG56ncgPyFrseY+FPDg+mXAzvJk/nily37YXjkQj2D0=" notifications: email: on_success: never addons: apt: packages: - g++-multilib vendor/cc-1.0.10/Cargo.toml0000644000000000000000000000242213264166600014105 0ustar rootroot# 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 = "cc" version = "1.0.10" authors = ["Alex Crichton "] description = "A build-time dependency for Cargo build scripts to assist in invoking the native\nC compiler to compile native C code into a static archive to be linked into Rust\ncode.\n" homepage = "https://github.com/alexcrichton/cc-rs" documentation = "https://docs.rs/cc" readme = "README.md" keywords = ["build-dependencies"] categories = ["development-tools"] license = "MIT/Apache-2.0" repository = "https://github.com/alexcrichton/cc-rs" [dependencies.rayon] version = "1.0" optional = true [dev-dependencies.tempdir] version = "0.3" [features] parallel = ["rayon"] [badges.appveyor] repository = "alexcrichton/cc-rs" [badges.travis-ci] repository = "alexcrichton/cc-rs" vendor/cc-1.0.10/LICENSE-APACHE0000664000000000000000000002513713264166600014113 0ustar rootroot 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. vendor/cc-1.0.10/LICENSE-MIT0000664000000000000000000000204113264166600013610 0ustar rootrootCopyright (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. vendor/cc-1.0.10/README.md0000664000000000000000000001556513264166600013452 0ustar rootroot# cc-rs A library to compile C/C++/assembly into a Rust library/application. [![Build Status](https://travis-ci.org/alexcrichton/cc-rs.svg?branch=master)](https://travis-ci.org/alexcrichton/cc-rs) [![Build status](https://ci.appveyor.com/api/projects/status/onu270iw98h81nwv?svg=true)](https://ci.appveyor.com/project/alexcrichton/cc-rs) [Documentation](https://docs.rs/cc) A simple library meant to be used as a build dependency with Cargo packages in order to build a set of C/C++ files into a static archive. This crate calls out to the most relevant compiler for a platform, for example using `cl` on MSVC. > **Note**: this crate was recently renamed from the `gcc` crate, so if you're > looking for the `gcc` crate you're in the right spot! ## Using cc-rs First, you'll want to both add a build script for your crate (`build.rs`) and also add this crate to your `Cargo.toml` via: ```toml [build-dependencies] cc = "1.0" ``` Next up, you'll want to write a build script like so: ```rust,no_run // build.rs extern crate cc; fn main() { cc::Build::new() .file("foo.c") .file("bar.c") .compile("foo"); } ``` And that's it! Running `cargo build` should take care of the rest and your Rust application will now have the C files `foo.c` and `bar.c` compiled into a file named libfoo.a. You can call the functions in Rust by declaring functions in your Rust code like so: ``` extern { fn foo_function(); fn bar_function(); } pub fn call() { unsafe { foo_function(); bar_function(); } } fn main() { // ... } ``` ## External configuration via environment variables To control the programs and flags used for building, the builder can set a number of different environment variables. * `CFLAGS` - a series of space separated flags passed to compilers. Note that individual flags cannot currently contain spaces, so doing something like: "-L=foo\ bar" is not possible. * `CC` - the actual C compiler used. Note that this is used as an exact executable name, so (for example) no extra flags can be passed inside this variable, and the builder must ensure that there aren't any trailing spaces. This compiler must understand the `-c` flag. For certain `TARGET`s, it also is assumed to know about other flags (most common is `-fPIC`). * `AR` - the `ar` (archiver) executable to use to build the static library. Each of these variables can also be supplied with certain prefixes and suffixes, in the following prioritized order: 1. `_` - for example, `CC_x86_64-unknown-linux-gnu` 2. `_` - for example, `CC_x86_64_unknown_linux_gnu` 3. `_` - for example, `HOST_CC` or `TARGET_CFLAGS` 4. `` - a plain `CC`, `AR` as above. If none of these variables exist, cc-rs uses built-in defaults In addition to the the above optional environment variables, `cc-rs` has some functions with hard requirements on some variables supplied by [cargo's build-script driver][cargo] that it has the `TARGET`, `OUT_DIR`, `OPT_LEVEL`, and `HOST` variables. [cargo]: http://doc.crates.io/build-script.html#inputs-to-the-build-script ## Optional features ### Parallel Currently cc-rs supports parallel compilation (think `make -jN`) but this feature is turned off by default. To enable cc-rs to compile C/C++ in parallel, you can change your dependency to: ```toml [build-dependencies] cc = { version = "1.0", features = ["parallel"] } ``` By default cc-rs will limit parallelism to `$NUM_JOBS`, or if not present it will limit it to the number of cpus on the machine. If you are using cargo, use `-jN` option of `build`, `test` and `run` commands as `$NUM_JOBS` is supplied by cargo. ## Compile-time Requirements To work properly this crate needs access to a C compiler when the build script is being run. This crate does not ship a C compiler with it. The compiler required varies per platform, but there are three broad categories: * Unix platforms require `cc` to be the C compiler. This can be found by installing cc/clang on Linux distributions and Xcode on OSX, for example. * Windows platforms targeting MSVC (e.g. your target triple ends in `-msvc`) require `cl.exe` to be available and in `PATH`. This is typically found in standard Visual Studio installations and the `PATH` can be set up by running the appropriate developer tools shell. * Windows platforms targeting MinGW (e.g. your target triple ends in `-gnu`) require `cc` to be available in `PATH`. We recommend the [MinGW-w64](http://mingw-w64.org) distribution, which is using the [Win-builds](http://win-builds.org) installation system. You may also acquire it via [MSYS2](http://msys2.github.io), as explained [here][msys2-help]. Make sure to install the appropriate architecture corresponding to your installation of rustc. GCC from older [MinGW](http://www.mingw.org) project is compatible only with 32-bit rust compiler. [msys2-help]: http://github.com/rust-lang/rust#building-on-windows ## C++ support `cc-rs` supports C++ libraries compilation by using the `cpp` method on `Build`: ```rust,no_run extern crate cc; fn main() { cc::Build::new() .cpp(true) // Switch to C++ library compilation. .file("foo.cpp") .compile("libfoo.a"); } ``` When using C++ library compilation switch, the `CXX` and `CXXFLAGS` env variables are used instead of `CC` and `CFLAGS` and the C++ standard library is linked to the crate target. ## CUDA C++ support `cc-rs` also supports compiling CUDA C++ libraries by using the `cuda` method on `Build` (currently for GNU/Clang toolchains only): ```rust,no_run extern crate cc; fn main() { cc::Build::new() // Switch to CUDA C++ library compilation using NVCC. .cuda(true) // Generate code for Maxwell (GTX 970, 980, 980 Ti, Titan X). .flag("-gencode").flag("arch=compute_52,code=sm_52") // Generate code for Maxwell (Jetson TX1). .flag("-gencode").flag("arch=compute_53,code=sm_53") // Generate code for Pascal (GTX 1070, 1080, 1080 Ti, Titan Xp). .flag("-gencode").flag("arch=compute_61,code=sm_61") // Generate code for Pascal (Tesla P100). .flag("-gencode").flag("arch=compute_60,code=sm_60") // Generate code for Pascal (Jetson TX2). .flag("-gencode").flag("arch=compute_62,code=sm_62") .file("bar.cu") .compile("libbar.a"); } ``` ## License This project is licensed under either of * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in Serde by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. vendor/cc-1.0.10/appveyor.yml0000664000000000000000000000455013264166600014553 0ustar rootrootenvironment: # At the time this was added AppVeyor was having troubles with checking # revocation of SSL certificates of sites like static.rust-lang.org and what # we think is crates.io. The libcurl HTTP client by default checks for # revocation on Windows and according to a mailing list [1] this can be # disabled. # # The `CARGO_HTTP_CHECK_REVOKE` env var here tells cargo to disable SSL # revocation checking on Windows in libcurl. Note, though, that rustup, which # we're using to download Rust here, also uses libcurl as the default backend. # Unlike Cargo, however, rustup doesn't have a mechanism to disable revocation # checking. To get rustup working we set `RUSTUP_USE_HYPER` which forces it to # use the Hyper instead of libcurl backend. Both Hyper and libcurl use # schannel on Windows but it appears that Hyper configures it slightly # differently such that revocation checking isn't turned on by default. # # [1]: https://curl.haxx.se/mail/lib-2016-03/0202.html RUSTUP_USE_HYPER: 1 CARGO_HTTP_CHECK_REVOKE: false matrix: - TARGET: x86_64-pc-windows-msvc ARCH: amd64 VS: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat - TARGET: x86_64-pc-windows-msvc ARCH: amd64 VS: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat - TARGET: i686-pc-windows-msvc ARCH: x86 VS: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat - TARGET: i686-pc-windows-msvc ARCH: x86 VS: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat - TARGET: x86_64-pc-windows-gnu MSYS_BITS: 64 - TARGET: i686-pc-windows-gnu MSYS_BITS: 32 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" - if defined VS call "%VS%" %ARCH% - 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 test --features parallel --target %TARGET% - cargo test --manifest-path cc-test/Cargo.toml --target %TARGET% - cargo test --manifest-path cc-test/Cargo.toml --features parallel --target %TARGET% - cargo test --manifest-path cc-test/Cargo.toml --release --target %TARGET% vendor/cc-1.0.10/src/0000755000000000000000000000000013264166600012744 5ustar rootrootvendor/cc-1.0.10/src/bin/0000755000000000000000000000000013264166600013514 5ustar rootrootvendor/cc-1.0.10/src/bin/gcc-shim.rs0000664000000000000000000000110413264166600015552 0ustar rootroot#![cfg_attr(test, allow(dead_code))] use std::env; use std::fs::File; use std::io::prelude::*; use std::path::PathBuf; fn main() { let out_dir = PathBuf::from(env::var_os("GCCTEST_OUT_DIR").unwrap()); for i in 0.. { let candidate = out_dir.join(format!("out{}", i)); if candidate.exists() { continue; } let mut f = File::create(candidate).unwrap(); for arg in env::args().skip(1) { writeln!(f, "{}", arg).unwrap(); } File::create(out_dir.join("libfoo.a")).unwrap(); break; } } vendor/cc-1.0.10/src/com.rs0000664000000000000000000000755613264166600014107 0ustar rootroot// Copyright © 2017 winapi-rs developers // Licensed under the Apache License, Version 2.0 // or the MIT license // , at your option. // All files in the project carrying such notice may not be copied, modified, or distributed // except according to those terms. #![allow(unused)] use std::ffi::{OsStr, OsString}; use std::mem::forget; use std::ops::Deref; use std::os::windows::ffi::{OsStrExt, OsStringExt}; use std::ptr::null_mut; use std::slice::from_raw_parts; use winapi::Interface; use winapi::BSTR; use winapi::CoInitializeEx; use winapi::COINIT_MULTITHREADED; use winapi::{SysFreeString, SysStringLen}; use winapi::IUnknown; use winapi::{HRESULT, S_FALSE, S_OK}; pub fn initialize() -> Result<(), HRESULT> { let err = unsafe { CoInitializeEx(null_mut(), COINIT_MULTITHREADED) }; if err != S_OK && err != S_FALSE { // S_FALSE just means COM is already initialized return Err(err); } Ok(()) } pub struct ComPtr(*mut T) where T: Interface; impl ComPtr where T: Interface, { /// Creates a `ComPtr` to wrap a raw pointer. /// It takes ownership over the pointer which means it does __not__ call `AddRef`. /// `T` __must__ be a COM interface that inherits from `IUnknown`. pub unsafe fn from_raw(ptr: *mut T) -> ComPtr { assert!(!ptr.is_null()); ComPtr(ptr) } /// Casts up the inheritance chain pub fn up(self) -> ComPtr where T: Deref, U: Interface, { ComPtr(self.into_raw() as *mut U) } /// Extracts the raw pointer. /// You are now responsible for releasing it yourself. pub fn into_raw(self) -> *mut T { let p = self.0; forget(self); p } /// For internal use only. fn as_unknown(&self) -> &IUnknown { unsafe { &*(self.0 as *mut IUnknown) } } /// Performs QueryInterface fun. pub fn cast(&self) -> Result, i32> where U: Interface, { let mut obj = null_mut(); let err = unsafe { self.as_unknown().QueryInterface(&U::uuidof(), &mut obj) }; if err < 0 { return Err(err); } Ok(unsafe { ComPtr::from_raw(obj as *mut U) }) } } impl Deref for ComPtr where T: Interface, { type Target = T; fn deref(&self) -> &T { unsafe { &*self.0 } } } impl Clone for ComPtr where T: Interface, { fn clone(&self) -> Self { unsafe { self.as_unknown().AddRef(); ComPtr::from_raw(self.0) } } } impl Drop for ComPtr where T: Interface, { fn drop(&mut self) { unsafe { self.as_unknown().Release(); } } } pub struct BStr(BSTR); impl BStr { pub unsafe fn from_raw(s: BSTR) -> BStr { BStr(s) } pub fn to_osstring(&self) -> OsString { let len = unsafe { SysStringLen(self.0) }; let slice = unsafe { from_raw_parts(self.0, len as usize) }; OsStringExt::from_wide(slice) } } impl Drop for BStr { fn drop(&mut self) { unsafe { SysFreeString(self.0) }; } } pub trait ToWide { fn to_wide(&self) -> Vec; fn to_wide_null(&self) -> Vec; } impl ToWide for T where T: AsRef, { fn to_wide(&self) -> Vec { self.as_ref().encode_wide().collect() } fn to_wide_null(&self) -> Vec { self.as_ref().encode_wide().chain(Some(0)).collect() } } pub trait FromWide where Self: Sized, { fn from_wide(wide: &[u16]) -> Self; fn from_wide_null(wide: &[u16]) -> Self { let len = wide.iter().take_while(|&&c| c != 0).count(); Self::from_wide(&wide[..len]) } } impl FromWide for OsString { fn from_wide(wide: &[u16]) -> OsString { OsStringExt::from_wide(wide) } } vendor/cc-1.0.10/src/lib.rs0000664000000000000000000021706313264166600014073 0ustar rootroot//! A library for build scripts to compile custom C code //! //! This library is intended to be used as a `build-dependencies` entry in //! `Cargo.toml`: //! //! ```toml //! [build-dependencies] //! cc = "1.0" //! ``` //! //! The purpose of this crate is to provide the utility functions necessary to //! compile C code into a static archive which is then linked into a Rust crate. //! Configuration is available through the `Build` struct. //! //! This crate will automatically detect situations such as cross compilation or //! other environment variables set by Cargo and will build code appropriately. //! //! The crate is not limited to C code, it can accept any source code that can //! be passed to a C or C++ compiler. As such, assembly files with extensions //! `.s` (gcc/clang) and `.asm` (MSVC) can also be compiled. //! //! [`Build`]: struct.Build.html //! //! # Parallelism //! //! To parallelize computation, enable the `parallel` feature for the crate. //! //! ```toml //! [build-dependencies] //! cc = { version = "1.0", features = ["parallel"] } //! ``` //! To specify the max number of concurrent compilation jobs, set the `NUM_JOBS` //! environment variable to the desired amount. //! //! Cargo will also set this environment variable when executed with the `-jN` flag. //! //! If `NUM_JOBS` is not set, the `RAYON_NUM_THREADS` environment variable can //! also specify the build paralellism. //! //! # Examples //! //! Use the `Build` struct to compile `src/foo.c`: //! //! ```no_run //! extern crate cc; //! //! fn main() { //! cc::Build::new() //! .file("src/foo.c") //! .define("FOO", Some("bar")) //! .include("src") //! .compile("foo"); //! } //! ``` #![doc(html_root_url = "https://docs.rs/cc/1.0")] #![cfg_attr(test, deny(warnings))] #![deny(missing_docs)] #[cfg(feature = "parallel")] extern crate rayon; use std::env; use std::ffi::{OsStr, OsString}; use std::fs; use std::path::{Path, PathBuf}; use std::process::{Child, Command, Stdio}; use std::io::{self, BufRead, BufReader, Read, Write}; use std::thread::{self, JoinHandle}; use std::collections::HashMap; use std::sync::{Arc, Mutex}; // These modules are all glue to support reading the MSVC version from // the registry and from COM interfaces #[cfg(windows)] mod registry; #[cfg(windows)] #[macro_use] mod winapi; #[cfg(windows)] mod com; #[cfg(windows)] mod setup_config; pub mod windows_registry; /// A builder for compilation of a native static library. /// /// A `Build` is the main type of the `cc` crate and is used to control all the /// various configuration options and such of a compile. You'll find more /// documentation on each method itself. #[derive(Clone, Debug)] pub struct Build { include_directories: Vec, definitions: Vec<(String, Option)>, objects: Vec, flags: Vec, flags_supported: Vec, known_flag_support_status: Arc>>, files: Vec, cpp: bool, cpp_link_stdlib: Option>, cpp_set_stdlib: Option, cuda: bool, target: Option, host: Option, out_dir: Option, opt_level: Option, debug: Option, env: Vec<(OsString, OsString)>, compiler: Option, archiver: Option, cargo_metadata: bool, pic: Option, static_crt: Option, shared_flag: Option, static_flag: Option, warnings_into_errors: bool, warnings: bool, } /// Represents the types of errors that may occur while using cc-rs. #[derive(Clone, Debug)] enum ErrorKind { /// Error occurred while performing I/O. IOError, /// Invalid architecture supplied. ArchitectureInvalid, /// Environment variable not found, with the var in question as extra info. EnvVarNotFound, /// Error occurred while using external tools (ie: invocation of compiler). ToolExecError, /// Error occurred due to missing external tools. ToolNotFound, } /// Represents an internal error that occurred, with an explanation. #[derive(Clone, Debug)] pub struct Error { /// Describes the kind of error that occurred. kind: ErrorKind, /// More explanation of error that occurred. message: String, } impl Error { fn new(kind: ErrorKind, message: &str) -> Error { Error { kind: kind, message: message.to_owned(), } } } impl From for Error { fn from(e: io::Error) -> Error { Error::new(ErrorKind::IOError, &format!("{}", e)) } } /// Configuration used to represent an invocation of a C compiler. /// /// This can be used to figure out what compiler is in use, what the arguments /// to it are, and what the environment variables look like for the compiler. /// This can be used to further configure other build systems (e.g. forward /// along CC and/or CFLAGS) or the `to_command` method can be used to run the /// compiler itself. #[derive(Clone, Debug)] pub struct Tool { path: PathBuf, cc_wrapper_path: Option, cc_wrapper_args: Vec, args: Vec, env: Vec<(OsString, OsString)>, family: ToolFamily, cuda: bool, } /// Represents the family of tools this tool belongs to. /// /// Each family of tools differs in how and what arguments they accept. /// /// Detection of a family is done on best-effort basis and may not accurately reflect the tool. #[derive(Copy, Clone, Debug, PartialEq)] enum ToolFamily { /// Tool is GNU Compiler Collection-like. Gnu, /// Tool is Clang-like. It differs from the GCC in a sense that it accepts superset of flags /// and its cross-compilation approach is different. Clang, /// Tool is the MSVC cl.exe. Msvc, } impl ToolFamily { /// What the flag to request debug info for this family of tools look like fn debug_flag(&self) -> &'static str { match *self { ToolFamily::Msvc => "/Z7", ToolFamily::Gnu | ToolFamily::Clang => "-g", } } /// What the flag to include directories into header search path looks like fn include_flag(&self) -> &'static str { match *self { ToolFamily::Msvc => "/I", ToolFamily::Gnu | ToolFamily::Clang => "-I", } } /// What the flag to request macro-expanded source output looks like fn expand_flag(&self) -> &'static str { match *self { ToolFamily::Msvc => "/E", ToolFamily::Gnu | ToolFamily::Clang => "-E", } } /// What the flags to enable all warnings fn warnings_flags(&self) -> &'static [&'static str] { static MSVC_FLAGS: &'static [&'static str] = &["/W4"]; static GNU_CLANG_FLAGS: &'static [&'static str] = &["-Wall", "-Wextra"]; match *self { ToolFamily::Msvc => &MSVC_FLAGS, ToolFamily::Gnu | ToolFamily::Clang => &GNU_CLANG_FLAGS, } } /// What the flag to turn warning into errors fn warnings_to_errors_flag(&self) -> &'static str { match *self { ToolFamily::Msvc => "/WX", ToolFamily::Gnu | ToolFamily::Clang => "-Werror", } } /// NVCC-specific. Device code debug info flag. This is separate from the /// debug info flag passed to the C++ compiler. fn nvcc_debug_flag(&self) -> &'static str { match *self { ToolFamily::Msvc => unimplemented!(), ToolFamily::Gnu | ToolFamily::Clang => "-G", } } /// NVCC-specific. Redirect the following flag to the underlying C++ /// compiler. fn nvcc_redirect_flag(&self) -> &'static str { match *self { ToolFamily::Msvc => unimplemented!(), ToolFamily::Gnu | ToolFamily::Clang => "-Xcompiler", } } } /// Represents an object. /// /// This is a source file -> object file pair. #[derive(Clone, Debug)] struct Object { src: PathBuf, dst: PathBuf, } impl Object { /// Create a new source file -> object file pair. fn new(src: PathBuf, dst: PathBuf) -> Object { Object { src: src, dst: dst } } } impl Build { /// Construct a new instance of a blank set of configuration. /// /// This builder is finished with the [`compile`] function. /// /// [`compile`]: struct.Build.html#method.compile pub fn new() -> Build { Build { include_directories: Vec::new(), definitions: Vec::new(), objects: Vec::new(), flags: Vec::new(), flags_supported: Vec::new(), known_flag_support_status: Arc::new(Mutex::new(HashMap::new())), files: Vec::new(), shared_flag: None, static_flag: None, cpp: false, cpp_link_stdlib: None, cpp_set_stdlib: None, cuda: false, target: None, host: None, out_dir: None, opt_level: None, debug: None, env: Vec::new(), compiler: None, archiver: None, cargo_metadata: true, pic: None, static_crt: None, warnings: true, warnings_into_errors: false, } } /// Add a directory to the `-I` or include path for headers /// /// # Example /// /// ```no_run /// use std::path::Path; /// /// let library_path = Path::new("/path/to/library"); /// /// cc::Build::new() /// .file("src/foo.c") /// .include(library_path) /// .include("src") /// .compile("foo"); /// ``` pub fn include>(&mut self, dir: P) -> &mut Build { self.include_directories.push(dir.as_ref().to_path_buf()); self } /// Specify a `-D` variable with an optional value. /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .define("FOO", "BAR") /// .define("BAZ", None) /// .compile("foo"); /// ``` pub fn define<'a, V: Into>>(&mut self, var: &str, val: V) -> &mut Build { self.definitions .push((var.to_string(), val.into().map(|s| s.to_string()))); self } /// Add an arbitrary object file to link in pub fn object>(&mut self, obj: P) -> &mut Build { self.objects.push(obj.as_ref().to_path_buf()); self } /// Add an arbitrary flag to the invocation of the compiler /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .flag("-ffunction-sections") /// .compile("foo"); /// ``` pub fn flag(&mut self, flag: &str) -> &mut Build { self.flags.push(flag.to_string()); self } fn ensure_check_file(&self) -> Result { let out_dir = self.get_out_dir()?; let src = if self.cuda { assert!(self.cpp); out_dir.join("flag_check.cu") } else if self.cpp { out_dir.join("flag_check.cpp") } else { out_dir.join("flag_check.c") }; if !src.exists() { let mut f = fs::File::create(&src)?; write!(f, "int main(void) {{ return 0; }}")?; } Ok(src) } /// Run the compiler to test if it accepts the given flag. /// /// For a convenience method for setting flags conditionally, /// see `flag_if_supported()`. /// /// It may return error if it's unable to run the compilier with a test file /// (e.g. the compiler is missing or a write to the `out_dir` failed). /// /// Note: Once computed, the result of this call is stored in the /// `known_flag_support` field. If `is_flag_supported(flag)` /// is called again, the result will be read from the hash table. pub fn is_flag_supported(&self, flag: &str) -> Result { let mut known_status = self.known_flag_support_status.lock().unwrap(); if let Some(is_supported) = known_status.get(flag).cloned() { return Ok(is_supported); } let out_dir = self.get_out_dir()?; let src = self.ensure_check_file()?; let obj = out_dir.join("flag_check"); let target = self.get_target()?; let mut cfg = Build::new(); cfg.flag(flag) .target(&target) .opt_level(0) .host(&target) .debug(false) .cpp(self.cpp) .cuda(self.cuda); let compiler = cfg.try_get_compiler()?; let mut cmd = compiler.to_command(); let is_arm = target.contains("aarch64") || target.contains("arm"); command_add_output_file(&mut cmd, &obj, target.contains("msvc"), false, is_arm); // We need to explicitly tell msvc not to link and create an exe // in the root directory of the crate if target.contains("msvc") { cmd.arg("/c"); } cmd.arg(&src); let output = cmd.output()?; let is_supported = output.stderr.is_empty(); known_status.insert(flag.to_owned(), is_supported); Ok(is_supported) } /// Add an arbitrary flag to the invocation of the compiler if it supports it /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .flag_if_supported("-Wlogical-op") // only supported by GCC /// .flag_if_supported("-Wunreachable-code") // only supported by clang /// .compile("foo"); /// ``` pub fn flag_if_supported(&mut self, flag: &str) -> &mut Build { self.flags_supported.push(flag.to_string()); self } /// Set the `-shared` flag. /// /// When enabled, the compiler will produce a shared object which can /// then be linked with other objects to form an executable. /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .shared_flag(true) /// .compile("libfoo.so"); /// ``` pub fn shared_flag(&mut self, shared_flag: bool) -> &mut Build { self.shared_flag = Some(shared_flag); self } /// Set the `-static` flag. /// /// When enabled on systems that support dynamic linking, this prevents /// linking with the shared libraries. /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .shared_flag(true) /// .static_flag(true) /// .compile("foo"); /// ``` pub fn static_flag(&mut self, static_flag: bool) -> &mut Build { self.static_flag = Some(static_flag); self } /// Add a file which will be compiled pub fn file>(&mut self, p: P) -> &mut Build { self.files.push(p.as_ref().to_path_buf()); self } /// Add files which will be compiled pub fn files

(&mut self, p: P) -> &mut Build where P: IntoIterator, P::Item: AsRef, { for file in p.into_iter() { self.file(file); } self } /// Set C++ support. /// /// The other `cpp_*` options will only become active if this is set to /// `true`. pub fn cpp(&mut self, cpp: bool) -> &mut Build { self.cpp = cpp; self } /// Set CUDA C++ support. /// /// Enabling CUDA will pass the detected C/C++ toolchain as an argument to /// the CUDA compiler, NVCC. NVCC itself accepts some limited GNU-like args; /// any other arguments for the C/C++ toolchain will be redirected using /// "-Xcompiler" flags. /// /// If enabled, this also implicitly enables C++ support. pub fn cuda(&mut self, cuda: bool) -> &mut Build { self.cuda = cuda; if cuda { self.cpp = true; } self } /// Set warnings into errors flag. /// /// Disabled by default. /// /// Warning: turning warnings into errors only make sense /// if you are a developer of the crate using cc-rs. /// Some warnings only appear on some architecture or /// specific version of the compiler. Any user of this crate, /// or any other crate depending on it, could fail during /// compile time. /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .warnings_into_errors(true) /// .compile("libfoo.a"); /// ``` pub fn warnings_into_errors(&mut self, warnings_into_errors: bool) -> &mut Build { self.warnings_into_errors = warnings_into_errors; self } /// Set warnings flags. /// /// Adds some flags: /// - "/Wall" for MSVC. /// - "-Wall", "-Wextra" for GNU and Clang. /// /// Enabled by default. /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .warnings(false) /// .compile("libfoo.a"); /// ``` pub fn warnings(&mut self, warnings: bool) -> &mut Build { self.warnings = warnings; self } /// Set the standard library to link against when compiling with C++ /// support. /// /// The default value of this property depends on the current target: On /// OS X `Some("c++")` is used, when compiling for a Visual Studio based /// target `None` is used and for other targets `Some("stdc++")` is used. /// If the `CXXSTDLIB` environment variable is set, its value will /// override the default value. /// /// A value of `None` indicates that no automatic linking should happen, /// otherwise cargo will link against the specified library. /// /// The given library name must not contain the `lib` prefix. /// /// Common values: /// - `stdc++` for GNU /// - `c++` for Clang /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .shared_flag(true) /// .cpp_link_stdlib("stdc++") /// .compile("libfoo.so"); /// ``` pub fn cpp_link_stdlib<'a, V: Into>>( &mut self, cpp_link_stdlib: V, ) -> &mut Build { self.cpp_link_stdlib = Some(cpp_link_stdlib.into().map(|s| s.into())); self } /// Force the C++ compiler to use the specified standard library. /// /// Setting this option will automatically set `cpp_link_stdlib` to the same /// value. /// /// The default value of this option is always `None`. /// /// This option has no effect when compiling for a Visual Studio based /// target. /// /// This option sets the `-stdlib` flag, which is only supported by some /// compilers (clang, icc) but not by others (gcc). The library will not /// detect which compiler is used, as such it is the responsibility of the /// caller to ensure that this option is only used in conjuction with a /// compiler which supports the `-stdlib` flag. /// /// A value of `None` indicates that no specific C++ standard library should /// be used, otherwise `-stdlib` is added to the compile invocation. /// /// The given library name must not contain the `lib` prefix. /// /// Common values: /// - `stdc++` for GNU /// - `c++` for Clang /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .cpp_set_stdlib("c++") /// .compile("libfoo.a"); /// ``` pub fn cpp_set_stdlib<'a, V: Into>>( &mut self, cpp_set_stdlib: V, ) -> &mut Build { let cpp_set_stdlib = cpp_set_stdlib.into(); self.cpp_set_stdlib = cpp_set_stdlib.map(|s| s.into()); self.cpp_link_stdlib(cpp_set_stdlib); self } /// Configures the target this configuration will be compiling for. /// /// This option is automatically scraped from the `TARGET` environment /// variable by build scripts, so it's not required to call this function. /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .target("aarch64-linux-android") /// .compile("foo"); /// ``` pub fn target(&mut self, target: &str) -> &mut Build { self.target = Some(target.to_string()); self } /// Configures the host assumed by this configuration. /// /// This option is automatically scraped from the `HOST` environment /// variable by build scripts, so it's not required to call this function. /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .host("arm-linux-gnueabihf") /// .compile("foo"); /// ``` pub fn host(&mut self, host: &str) -> &mut Build { self.host = Some(host.to_string()); self } /// Configures the optimization level of the generated object files. /// /// This option is automatically scraped from the `OPT_LEVEL` environment /// variable by build scripts, so it's not required to call this function. pub fn opt_level(&mut self, opt_level: u32) -> &mut Build { self.opt_level = Some(opt_level.to_string()); self } /// Configures the optimization level of the generated object files. /// /// This option is automatically scraped from the `OPT_LEVEL` environment /// variable by build scripts, so it's not required to call this function. pub fn opt_level_str(&mut self, opt_level: &str) -> &mut Build { self.opt_level = Some(opt_level.to_string()); self } /// Configures whether the compiler will emit debug information when /// generating object files. /// /// This option is automatically scraped from the `PROFILE` environment /// variable by build scripts (only enabled when the profile is "debug"), so /// it's not required to call this function. pub fn debug(&mut self, debug: bool) -> &mut Build { self.debug = Some(debug); self } /// Configures the output directory where all object files and static /// libraries will be located. /// /// This option is automatically scraped from the `OUT_DIR` environment /// variable by build scripts, so it's not required to call this function. pub fn out_dir>(&mut self, out_dir: P) -> &mut Build { self.out_dir = Some(out_dir.as_ref().to_owned()); self } /// Configures the compiler to be used to produce output. /// /// This option is automatically determined from the target platform or a /// number of environment variables, so it's not required to call this /// function. pub fn compiler>(&mut self, compiler: P) -> &mut Build { self.compiler = Some(compiler.as_ref().to_owned()); self } /// Configures the tool used to assemble archives. /// /// This option is automatically determined from the target platform or a /// number of environment variables, so it's not required to call this /// function. pub fn archiver>(&mut self, archiver: P) -> &mut Build { self.archiver = Some(archiver.as_ref().to_owned()); self } /// Define whether metadata should be emitted for cargo allowing it to /// automatically link the binary. Defaults to `true`. /// /// The emitted metadata is: /// /// - `rustc-link-lib=static=`*compiled lib* /// - `rustc-link-search=native=`*target folder* /// - When target is MSVC, the ATL-MFC libs are added via `rustc-link-search=native=` /// - When C++ is enabled, the C++ stdlib is added via `rustc-link-lib` /// pub fn cargo_metadata(&mut self, cargo_metadata: bool) -> &mut Build { self.cargo_metadata = cargo_metadata; self } /// Configures whether the compiler will emit position independent code. /// /// This option defaults to `false` for `windows-gnu` targets and /// to `true` for all other targets. pub fn pic(&mut self, pic: bool) -> &mut Build { self.pic = Some(pic); self } /// Configures whether the /MT flag or the /MD flag will be passed to msvc build tools. /// /// This option defaults to `false`, and affect only msvc targets. pub fn static_crt(&mut self, static_crt: bool) -> &mut Build { self.static_crt = Some(static_crt); self } #[doc(hidden)] pub fn __set_env(&mut self, a: A, b: B) -> &mut Build where A: AsRef, B: AsRef, { self.env .push((a.as_ref().to_owned(), b.as_ref().to_owned())); self } /// Run the compiler, generating the file `output` /// /// This will return a result instead of panicing; see compile() for the complete description. pub fn try_compile(&self, output: &str) -> Result<(), Error> { let (lib_name, gnu_lib_name) = if output.starts_with("lib") && output.ends_with(".a") { (&output[3..output.len() - 2], output.to_owned()) } else { let mut gnu = String::with_capacity(5 + output.len()); gnu.push_str("lib"); gnu.push_str(&output); gnu.push_str(".a"); (output, gnu) }; let dst = self.get_out_dir()?; let mut objects = Vec::new(); for file in self.files.iter() { let obj = dst.join(file).with_extension("o"); let obj = if !obj.starts_with(&dst) { dst.join(obj.file_name().ok_or_else(|| { Error::new(ErrorKind::IOError, "Getting object file details failed.") })?) } else { obj }; match obj.parent() { Some(s) => fs::create_dir_all(s)?, None => { return Err(Error::new( ErrorKind::IOError, "Getting object file details failed.", )) } }; objects.push(Object::new(file.to_path_buf(), obj)); } self.compile_objects(&objects)?; self.assemble(lib_name, &dst.join(gnu_lib_name), &objects)?; if self.get_target()?.contains("msvc") { let compiler = self.get_base_compiler()?; let atlmfc_lib = compiler .env() .iter() .find(|&&(ref var, _)| var.as_os_str() == OsStr::new("LIB")) .and_then(|&(_, ref lib_paths)| { env::split_paths(lib_paths).find(|path| { let sub = Path::new("atlmfc/lib"); path.ends_with(sub) || path.parent().map_or(false, |p| p.ends_with(sub)) }) }); if let Some(atlmfc_lib) = atlmfc_lib { self.print(&format!( "cargo:rustc-link-search=native={}", atlmfc_lib.display() )); } } self.print(&format!("cargo:rustc-link-lib=static={}", lib_name)); self.print(&format!("cargo:rustc-link-search=native={}", dst.display())); // Add specific C++ libraries, if enabled. if self.cpp { if let Some(stdlib) = self.get_cpp_link_stdlib()? { self.print(&format!("cargo:rustc-link-lib={}", stdlib)); } } Ok(()) } /// Run the compiler, generating the file `output` /// /// The name `output` should be the name of the library. For backwards compatibility, /// the `output` may start with `lib` and end with `.a`. The Rust compilier will create /// the assembly with the lib prefix and .a extension. MSVC will create a file without prefix, /// ending with `.lib`. /// /// # Panics /// /// Panics if `output` is not formatted correctly or if one of the underlying /// compiler commands fails. It can also panic if it fails reading file names /// or creating directories. pub fn compile(&self, output: &str) { if let Err(e) = self.try_compile(output) { fail(&e.message); } } #[cfg(feature = "parallel")] fn compile_objects(&self, objs: &[Object]) -> Result<(), Error> { use self::rayon::prelude::*; if let Ok(amt) = env::var("NUM_JOBS") { if let Ok(amt) = amt.parse() { let _ = rayon::ThreadPoolBuilder::new() .num_threads(amt) .build_global(); } } // Check for any errors and return the first one found. objs.par_iter() .with_max_len(1) .map(|obj| self.compile_object(obj)) .collect() } #[cfg(not(feature = "parallel"))] fn compile_objects(&self, objs: &[Object]) -> Result<(), Error> { for obj in objs { self.compile_object(obj)?; } Ok(()) } fn compile_object(&self, obj: &Object) -> Result<(), Error> { let is_asm = obj.src.extension().and_then(|s| s.to_str()) == Some("asm"); let target = self.get_target()?; let msvc = target.contains("msvc"); let (mut cmd, name) = if msvc && is_asm { self.msvc_macro_assembler()? } else { let compiler = self.try_get_compiler()?; let mut cmd = compiler.to_command(); for &(ref a, ref b) in self.env.iter() { cmd.env(a, b); } ( cmd, compiler .path .file_name() .ok_or_else(|| Error::new(ErrorKind::IOError, "Failed to get compiler path."))? .to_string_lossy() .into_owned(), ) }; let is_arm = target.contains("aarch64") || target.contains("arm"); command_add_output_file(&mut cmd, &obj.dst, msvc, is_asm, is_arm); // armasm and armasm64 don't requrie -c option if !msvc || !is_asm || !is_arm { cmd.arg(if msvc { "/c" } else { "-c" }); } cmd.arg(&obj.src); run(&mut cmd, &name)?; Ok(()) } /// This will return a result instead of panicing; see expand() for the complete description. pub fn try_expand(&self) -> Result, Error> { let compiler = self.try_get_compiler()?; let mut cmd = compiler.to_command(); for &(ref a, ref b) in self.env.iter() { cmd.env(a, b); } cmd.arg(compiler.family.expand_flag()); assert!( self.files.len() <= 1, "Expand may only be called for a single file" ); for file in self.files.iter() { cmd.arg(file); } let name = compiler .path .file_name() .ok_or_else(|| Error::new(ErrorKind::IOError, "Failed to get compiler path."))? .to_string_lossy() .into_owned(); Ok(run_output(&mut cmd, &name)?) } /// Run the compiler, returning the macro-expanded version of the input files. /// /// This is only relevant for C and C++ files. /// /// # Panics /// Panics if more than one file is present in the config, or if compiler /// path has an invalid file name. /// /// # Example /// ```no_run /// let out = cc::Build::new().file("src/foo.c").expand(); /// ``` pub fn expand(&self) -> Vec { match self.try_expand() { Err(e) => fail(&e.message), Ok(v) => v, } } /// Get the compiler that's in use for this configuration. /// /// This function will return a `Tool` which represents the culmination /// of this configuration at a snapshot in time. The returned compiler can /// be inspected (e.g. the path, arguments, environment) to forward along to /// other tools, or the `to_command` method can be used to invoke the /// compiler itself. /// /// This method will take into account all configuration such as debug /// information, optimization level, include directories, defines, etc. /// Additionally, the compiler binary in use follows the standard /// conventions for this path, e.g. looking at the explicitly set compiler, /// environment variables (a number of which are inspected here), and then /// falling back to the default configuration. /// /// # Panics /// /// Panics if an error occurred while determining the architecture. pub fn get_compiler(&self) -> Tool { match self.try_get_compiler() { Ok(tool) => tool, Err(e) => fail(&e.message), } } /// Get the compiler that's in use for this configuration. /// /// This will return a result instead of panicing; see get_compiler() for the complete description. pub fn try_get_compiler(&self) -> Result { let opt_level = self.get_opt_level()?; let target = self.get_target()?; let mut cmd = self.get_base_compiler()?; // Non-target flags // If the flag is not conditioned on target variable, it belongs here :) match cmd.family { ToolFamily::Msvc => { assert!(!self.cuda, "CUDA C++ compilation not supported for MSVC, yet... but you are welcome to implement it :)"); cmd.args.push("/nologo".into()); let crt_flag = match self.static_crt { Some(true) => "/MT", Some(false) => "/MD", None => { let features = env::var("CARGO_CFG_TARGET_FEATURE").unwrap_or(String::new()); if features.contains("crt-static") { "/MT" } else { "/MD" } } }; cmd.args.push(crt_flag.into()); match &opt_level[..] { // Msvc uses /O1 to enable all optimizations that minimize code size. "z" | "s" | "1" => cmd.args.push("/O1".into()), // -O3 is a valid value for gcc and clang compilers, but not msvc. Cap to /O2. "2" | "3" => cmd.args.push("/O2".into()), _ => {} } } ToolFamily::Gnu | ToolFamily::Clang => { // arm-linux-androideabi-gcc 4.8 shipped with Android NDK does // not support '-Oz' if opt_level == "z" && cmd.family != ToolFamily::Clang { cmd.args.push("-Os".into()); } else { cmd.args.push(format!("-O{}", opt_level).into()); } if !target.contains("-ios") { cmd.push_cc_arg("-ffunction-sections".into()); cmd.push_cc_arg("-fdata-sections".into()); } if self.pic.unwrap_or(!target.contains("windows-gnu")) { cmd.push_cc_arg("-fPIC".into()); } } } for arg in self.envflags(if self.cpp { "CXXFLAGS" } else { "CFLAGS" }) { cmd.args.push(arg.into()); } if self.get_debug() { if self.cuda { let nvcc_debug_flag = cmd.family.nvcc_debug_flag().into(); cmd.args.push(nvcc_debug_flag); } let debug_flag = cmd.family.debug_flag().into(); cmd.push_cc_arg(debug_flag); } // Target flags match cmd.family { ToolFamily::Clang => { cmd.args.push(format!("--target={}", target).into()); } ToolFamily::Msvc => { if target.contains("i586") { cmd.args.push("/ARCH:IA32".into()); } } ToolFamily::Gnu => { if target.contains("i686") || target.contains("i586") { cmd.args.push("-m32".into()); } else if target == "x86_64-unknown-linux-gnux32" { cmd.args.push("-mx32".into()); } else if target.contains("x86_64") || target.contains("powerpc64") { cmd.args.push("-m64".into()); } if self.static_flag.is_none() { let features = env::var("CARGO_CFG_TARGET_FEATURE").unwrap_or(String::new()); if features.contains("crt-static") { cmd.args.push("-static".into()); } } // armv7 targets get to use armv7 instructions if target.starts_with("armv7-") && target.contains("-linux-") { cmd.args.push("-march=armv7-a".into()); } // On android we can guarantee some extra float instructions // (specified in the android spec online) if target.starts_with("armv7-linux-androideabi") { cmd.args.push("-march=armv7-a".into()); cmd.args.push("-mthumb".into()); cmd.args.push("-mfpu=vfpv3-d16".into()); cmd.args.push("-mfloat-abi=softfp".into()); } if target.starts_with("armv4t-unknown-linux-") { cmd.args.push("-march=armv4t".into()); cmd.args.push("-marm".into()); cmd.args.push("-mfloat-abi=soft".into()); } if target.starts_with("armv5te-unknown-linux-") { cmd.args.push("-march=armv5te".into()); cmd.args.push("-marm".into()); cmd.args.push("-mfloat-abi=soft".into()); } // For us arm == armv6 by default if target.starts_with("arm-unknown-linux-") { cmd.args.push("-march=armv6".into()); cmd.args.push("-marm".into()); } // We can guarantee some settings for FRC if target.starts_with("arm-frc-") { cmd.args.push("-march=armv7-a".into()); cmd.args.push("-mcpu=cortex-a9".into()); cmd.args.push("-mfpu=vfpv3".into()); cmd.args.push("-mfloat-abi=softfp".into()); cmd.args.push("-marm".into()); } // Turn codegen down on i586 to avoid some instructions. if target.starts_with("i586-unknown-linux-") { cmd.args.push("-march=pentium".into()); } // Set codegen level for i686 correctly if target.starts_with("i686-unknown-linux-") { cmd.args.push("-march=i686".into()); } // Looks like `musl-gcc` makes is hard for `-m32` to make its way // all the way to the linker, so we need to actually instruct the // linker that we're generating 32-bit executables as well. This'll // typically only be used for build scripts which transitively use // these flags that try to compile executables. if target == "i686-unknown-linux-musl" || target == "i586-unknown-linux-musl" { cmd.args.push("-Wl,-melf_i386".into()); } if target.starts_with("thumb") { cmd.args.push("-mthumb".into()); if target.ends_with("eabihf") { cmd.args.push("-mfloat-abi=hard".into()) } } if target.starts_with("thumbv6m") { cmd.args.push("-march=armv6s-m".into()); } if target.starts_with("thumbv7em") { cmd.args.push("-march=armv7e-m".into()); if target.ends_with("eabihf") { cmd.args.push("-mfpu=fpv4-sp-d16".into()) } } if target.starts_with("thumbv7m") { cmd.args.push("-march=armv7-m".into()); } } } if target.contains("-ios") { // FIXME: potential bug. iOS is always compiled with Clang, but Gcc compiler may be // detected instead. self.ios_flags(&mut cmd)?; } if self.static_flag.unwrap_or(false) { cmd.args.push("-static".into()); } if self.shared_flag.unwrap_or(false) { cmd.args.push("-shared".into()); } if self.cpp { match (self.cpp_set_stdlib.as_ref(), cmd.family) { (None, _) => {} (Some(stdlib), ToolFamily::Gnu) | (Some(stdlib), ToolFamily::Clang) => { cmd.push_cc_arg(format!("-stdlib=lib{}", stdlib).into()); } _ => { println!( "cargo:warning=cpp_set_stdlib is specified, but the {:?} compiler \ does not support this option, ignored", cmd.family ); } } } for directory in self.include_directories.iter() { cmd.args.push(cmd.family.include_flag().into()); cmd.args.push(directory.into()); } if self.warnings { for flag in cmd.family.warnings_flags().iter() { cmd.push_cc_arg(flag.into()); } } for flag in self.flags.iter() { cmd.args.push(flag.into()); } for flag in self.flags_supported.iter() { if self.is_flag_supported(flag).unwrap_or(false) { cmd.push_cc_arg(flag.into()); } } for &(ref key, ref value) in self.definitions.iter() { let lead = if let ToolFamily::Msvc = cmd.family { "/" } else { "-" }; if let Some(ref value) = *value { cmd.args.push(format!("{}D{}={}", lead, key, value).into()); } else { cmd.args.push(format!("{}D{}", lead, key).into()); } } if self.warnings_into_errors { let warnings_to_errors_flag = cmd.family.warnings_to_errors_flag().into(); cmd.push_cc_arg(warnings_to_errors_flag); } Ok(cmd) } fn msvc_macro_assembler(&self) -> Result<(Command, String), Error> { let target = self.get_target()?; let tool = if target.contains("x86_64") { "ml64.exe" } else if target.contains("arm") { "armasm.exe" } else if target.contains("aarch64") { "armasm64.exe" } else { "ml.exe" }; let mut cmd = windows_registry::find(&target, tool).unwrap_or_else(|| self.cmd(tool)); for directory in self.include_directories.iter() { cmd.arg("/I").arg(directory); } for &(ref key, ref value) in self.definitions.iter() { if let Some(ref value) = *value { cmd.arg(&format!("/D{}={}", key, value)); } else { cmd.arg(&format!("/D{}", key)); } } if target.contains("i686") || target.contains("i586") { cmd.arg("/safeseh"); } for flag in self.flags.iter() { cmd.arg(flag); } Ok((cmd, tool.to_string())) } fn assemble(&self, lib_name: &str, dst: &Path, objs: &[Object]) -> Result<(), Error> { // Delete the destination if it exists as the `ar` tool at least on Unix // appends to it, which we don't want. let _ = fs::remove_file(&dst); let objects: Vec<_> = objs.iter().map(|obj| obj.dst.clone()).collect(); let target = self.get_target()?; if target.contains("msvc") { let mut cmd = match self.archiver { Some(ref s) => self.cmd(s), None => windows_registry::find(&target, "lib.exe") .unwrap_or_else(|| self.cmd("lib.exe")), }; let mut out = OsString::from("/OUT:"); out.push(dst); cmd.arg(out).arg("/nologo"); // Similar to https://github.com/rust-lang/rust/pull/47507 // and https://github.com/rust-lang/rust/pull/48548 let estimated_command_line_len = objects .iter() .chain(&self.objects) .map(|a| a.as_os_str().len()) .sum::(); if estimated_command_line_len > 1024 * 6 { let mut args = String::from("\u{FEFF}"); // BOM for arg in objects.iter().chain(&self.objects) { args.push('"'); for c in arg.to_str().unwrap().chars() { if c == '"' { args.push('\\') } args.push(c) } args.push('"'); args.push('\n'); } let mut utf16le = Vec::new(); for code_unit in args.encode_utf16() { utf16le.push(code_unit as u8); utf16le.push((code_unit >> 8) as u8); } let mut args_file = OsString::from(dst); args_file.push(".args"); fs::File::create(&args_file) .unwrap() .write_all(&utf16le) .unwrap(); let mut args_file_arg = OsString::from("@"); args_file_arg.push(args_file); cmd.arg(args_file_arg); } else { cmd.args(&objects).args(&self.objects); } run(&mut cmd, "lib.exe")?; // The Rust compiler will look for libfoo.a and foo.lib, but the // MSVC linker will also be passed foo.lib, so be sure that both // exist for now. let lib_dst = dst.with_file_name(format!("{}.lib", lib_name)); let _ = fs::remove_file(&lib_dst); match fs::hard_link(&dst, &lib_dst).or_else(|_| { // if hard-link fails, just copy (ignoring the number of bytes written) fs::copy(&dst, &lib_dst).map(|_| ()) }) { Ok(_) => (), Err(_) => { return Err(Error::new( ErrorKind::IOError, "Could not copy or create a hard-link to the generated lib file.", )) } }; } else { let (mut ar, cmd) = self.get_ar()?; run( ar.arg("crs").arg(dst).args(&objects).args(&self.objects), &cmd, )?; } Ok(()) } fn ios_flags(&self, cmd: &mut Tool) -> Result<(), Error> { enum ArchSpec { Device(&'static str), Simulator(&'static str), } let target = self.get_target()?; let arch = target.split('-').nth(0).ok_or_else(|| { Error::new( ErrorKind::ArchitectureInvalid, "Unknown architecture for iOS target.", ) })?; let arch = match arch { "arm" | "armv7" | "thumbv7" => ArchSpec::Device("armv7"), "armv7s" | "thumbv7s" => ArchSpec::Device("armv7s"), "arm64" | "aarch64" => ArchSpec::Device("arm64"), "i386" | "i686" => ArchSpec::Simulator("-m32"), "x86_64" => ArchSpec::Simulator("-m64"), _ => { return Err(Error::new( ErrorKind::ArchitectureInvalid, "Unknown architecture for iOS target.", )) } }; let sdk = match arch { ArchSpec::Device(arch) => { cmd.args.push("-arch".into()); cmd.args.push(arch.into()); cmd.args.push("-miphoneos-version-min=7.0".into()); "iphoneos" } ArchSpec::Simulator(arch) => { cmd.args.push(arch.into()); cmd.args.push("-mios-simulator-version-min=7.0".into()); "iphonesimulator" } }; self.print(&format!("Detecting iOS SDK path for {}", sdk)); let sdk_path = self.cmd("xcrun") .arg("--show-sdk-path") .arg("--sdk") .arg(sdk) .stderr(Stdio::inherit()) .output()? .stdout; let sdk_path = match String::from_utf8(sdk_path) { Ok(p) => p, Err(_) => { return Err(Error::new( ErrorKind::IOError, "Unable to determine iOS SDK path.", )) } }; cmd.args.push("-isysroot".into()); cmd.args.push(sdk_path.trim().into()); cmd.args.push("-fembed-bitcode".into()); /* * TODO we probably ultimatedly want the -fembed-bitcode-marker flag * but can't have it now because of an issue in LLVM: * https://github.com/alexcrichton/cc-rs/issues/301 * https://github.com/rust-lang/rust/pull/48896#comment-372192660 */ /* if self.get_opt_level()? == "0" { cmd.args.push("-fembed-bitcode-marker".into()); } */ Ok(()) } fn cmd>(&self, prog: P) -> Command { let mut cmd = Command::new(prog); for &(ref a, ref b) in self.env.iter() { cmd.env(a, b); } cmd } fn get_base_compiler(&self) -> Result { if let Some(ref c) = self.compiler { return Ok(Tool::new(c.clone())); } let host = self.get_host()?; let target = self.get_target()?; let (env, msvc, gnu, traditional) = if self.cpp { ("CXX", "cl.exe", "g++", "c++") } else { ("CC", "cl.exe", "gcc", "cc") }; // On Solaris, c++/cc unlikely to exist or be correct. let default = if host.contains("solaris") { gnu } else { traditional }; let tool_opt: Option = self.env_tool(env) .map(|(tool, cc, args)| { // chop off leading/trailing whitespace to work around // semi-buggy build scripts which are shared in // makefiles/configure scripts (where spaces are far more // lenient) let mut t = Tool::new(PathBuf::from(tool.trim())); if let Some(cc) = cc { t.cc_wrapper_path = Some(PathBuf::from(cc)); } for arg in args { t.cc_wrapper_args.push(arg.into()); } t }) .or_else(|| { if target.contains("emscripten") { let tool = if self.cpp { "em++" } else { "emcc" }; // Windows uses bat file so we have to be a bit more specific if cfg!(windows) { let mut t = Tool::new(PathBuf::from("cmd")); t.args.push("/c".into()); t.args.push(format!("{}.bat", tool).into()); Some(t) } else { Some(Tool::new(PathBuf::from(tool))) } } else { None } }) .or_else(|| windows_registry::find_tool(&target, "cl.exe")); let tool = match tool_opt { Some(t) => t, None => { let compiler = if host.contains("windows") && target.contains("windows") { if target.contains("msvc") { msvc.to_string() } else { format!("{}.exe", gnu) } } else if target.contains("android") { format!("{}-{}", target.replace("armv7", "arm"), gnu) } else if target.contains("cloudabi") { format!("{}-{}", target, traditional) } else if self.get_host()? != target { // CROSS_COMPILE is of the form: "arm-linux-gnueabi-" let cc_env = self.getenv("CROSS_COMPILE"); let cross_compile = cc_env.as_ref().map(|s| s.trim_right_matches('-')); let prefix = cross_compile.or(match &target[..] { "aarch64-unknown-linux-gnu" => Some("aarch64-linux-gnu"), "aarch64-unknown-linux-musl" => Some("aarch64-linux-musl"), "arm-unknown-linux-gnueabi" => Some("arm-linux-gnueabi"), "armv4t-unknown-linux-gnueabi" => Some("arm-linux-gnueabi"), "armv5te-unknown-linux-gnueabi" => Some("arm-linux-gnueabi"), "arm-frc-linux-gnueabi" => Some("arm-frc-linux-gnueabi"), "arm-unknown-linux-gnueabihf" => Some("arm-linux-gnueabihf"), "arm-unknown-linux-musleabi" => Some("arm-linux-musleabi"), "arm-unknown-linux-musleabihf" => Some("arm-linux-musleabihf"), "arm-unknown-netbsd-eabi" => Some("arm--netbsdelf-eabi"), "armv6-unknown-netbsd-eabihf" => Some("armv6--netbsdelf-eabihf"), "armv7-unknown-linux-gnueabihf" => Some("arm-linux-gnueabihf"), "armv7-unknown-linux-musleabihf" => Some("arm-linux-musleabihf"), "armv7-unknown-netbsd-eabihf" => Some("armv7--netbsdelf-eabihf"), "i586-unknown-linux-musl" => Some("musl"), "i686-pc-windows-gnu" => Some("i686-w64-mingw32"), "i686-unknown-linux-musl" => Some("musl"), "i686-unknown-netbsd" => Some("i486--netbsdelf"), "mips-unknown-linux-gnu" => Some("mips-linux-gnu"), "mipsel-unknown-linux-gnu" => Some("mipsel-linux-gnu"), "mips64-unknown-linux-gnuabi64" => Some("mips64-linux-gnuabi64"), "mips64el-unknown-linux-gnuabi64" => Some("mips64el-linux-gnuabi64"), "powerpc-unknown-linux-gnu" => Some("powerpc-linux-gnu"), "powerpc-unknown-linux-gnuspe" => Some("powerpc-linux-gnuspe"), "powerpc-unknown-netbsd" => Some("powerpc--netbsd"), "powerpc64-unknown-linux-gnu" => Some("powerpc-linux-gnu"), "powerpc64le-unknown-linux-gnu" => Some("powerpc64le-linux-gnu"), "s390x-unknown-linux-gnu" => Some("s390x-linux-gnu"), "sparc-unknown-linux-gnu" => Some("sparc-linux-gnu"), "sparc64-unknown-linux-gnu" => Some("sparc64-linux-gnu"), "sparc64-unknown-netbsd" => Some("sparc64--netbsd"), "sparcv9-sun-solaris" => Some("sparcv9-sun-solaris"), "thumbv6m-none-eabi" => Some("arm-none-eabi"), "thumbv7em-none-eabi" => Some("arm-none-eabi"), "thumbv7em-none-eabihf" => Some("arm-none-eabi"), "thumbv7m-none-eabi" => Some("arm-none-eabi"), "x86_64-pc-windows-gnu" => Some("x86_64-w64-mingw32"), "x86_64-rumprun-netbsd" => Some("x86_64-rumprun-netbsd"), "x86_64-unknown-linux-musl" => Some("musl"), "x86_64-unknown-netbsd" => Some("x86_64--netbsd"), _ => None, }); match prefix { Some(prefix) => format!("{}-{}", prefix, gnu), None => default.to_string(), } } else { default.to_string() }; Tool::new(PathBuf::from(compiler)) } }; let tool = if self.cuda { assert!( tool.args.is_empty(), "CUDA compilation currently assumes empty pre-existing args" ); let nvcc = match self.get_var("NVCC") { Err(_) => "nvcc".into(), Ok(nvcc) => nvcc, }; let mut nvcc_tool = Tool::with_features(PathBuf::from(nvcc), self.cuda); nvcc_tool .args .push(format!("-ccbin={}", tool.path.display()).into()); nvcc_tool } else { tool }; Ok(tool) } fn get_var(&self, var_base: &str) -> Result { let target = self.get_target()?; let host = self.get_host()?; let kind = if host == target { "HOST" } else { "TARGET" }; let target_u = target.replace("-", "_"); let res = self.getenv(&format!("{}_{}", var_base, target)) .or_else(|| self.getenv(&format!("{}_{}", var_base, target_u))) .or_else(|| self.getenv(&format!("{}_{}", kind, var_base))) .or_else(|| self.getenv(var_base)); match res { Some(res) => Ok(res), None => Err(Error::new( ErrorKind::EnvVarNotFound, &format!("Could not find environment variable {}.", var_base), )), } } fn envflags(&self, name: &str) -> Vec { self.get_var(name) .unwrap_or(String::new()) .split(|c: char| c.is_whitespace()) .filter(|s| !s.is_empty()) .map(|s| s.to_string()) .collect() } /// Returns compiler path, optional modifier name from whitelist, and arguments vec fn env_tool(&self, name: &str) -> Option<(String, Option, Vec)> { let tool = match self.get_var(name) { Ok(tool) => tool, Err(_) => return None, }; // If this is an exact path on the filesystem we don't want to do any // interpretation at all, just pass it on through. This'll hopefully get // us to support spaces-in-paths. if Path::new(&tool).exists() { return Some((tool, None, Vec::new())); } // Ok now we want to handle a couple of scenarios. We'll assume from // here on out that spaces are splitting separate arguments. Two major // features we want to support are: // // CC='sccache cc' // // aka using `sccache` or any other wrapper/caching-like-thing for // compilations. We want to know what the actual compiler is still, // though, because our `Tool` API support introspection of it to see // what compiler is in use. // // additionally we want to support // // CC='cc -flag' // // where the CC env var is used to also pass default flags to the C // compiler. // // It's true that everything here is a bit of a pain, but apparently if // you're not literally make or bash then you get a lot of bug reports. let known_wrappers = ["ccache", "distcc", "sccache", "icecc"]; let mut parts = tool.split_whitespace(); let maybe_wrapper = match parts.next() { Some(s) => s, None => return None, }; let file_stem = Path::new(maybe_wrapper) .file_stem() .unwrap() .to_str() .unwrap(); if known_wrappers.contains(&file_stem) { if let Some(compiler) = parts.next() { return Some(( compiler.to_string(), Some(maybe_wrapper.to_string()), parts.map(|s| s.to_string()).collect(), )); } } Some(( maybe_wrapper.to_string(), None, parts.map(|s| s.to_string()).collect(), )) } /// Returns the default C++ standard library for the current target: `libc++` /// for OS X and `libstdc++` for anything else. fn get_cpp_link_stdlib(&self) -> Result, Error> { match self.cpp_link_stdlib.clone() { Some(s) => Ok(s), None => { if let Ok(stdlib) = self.get_var("CXXSTDLIB") { if stdlib.is_empty() { Ok(None) } else { Ok(Some(stdlib)) } } else { let target = self.get_target()?; if target.contains("msvc") { Ok(None) } else if target.contains("apple") { Ok(Some("c++".to_string())) } else if target.contains("freebsd") { Ok(Some("c++".to_string())) } else if target.contains("openbsd") { Ok(Some("c++".to_string())) } else { Ok(Some("stdc++".to_string())) } } } } } fn get_ar(&self) -> Result<(Command, String), Error> { if let Some(ref p) = self.archiver { let name = p.file_name().and_then(|s| s.to_str()).unwrap_or("ar"); return Ok((self.cmd(p), name.to_string())); } if let Ok(p) = self.get_var("AR") { return Ok((self.cmd(&p), p)); } let program = if self.get_target()?.contains("android") { format!("{}-ar", self.get_target()?.replace("armv7", "arm")) } else if self.get_target()?.contains("emscripten") { // Windows use bat files so we have to be a bit more specific if cfg!(windows) { let mut cmd = self.cmd("cmd"); cmd.arg("/c").arg("emar.bat"); return Ok((cmd, "emar.bat".to_string())); } "emar".to_string() } else { "ar".to_string() }; Ok((self.cmd(&program), program)) } fn get_target(&self) -> Result { match self.target.clone() { Some(t) => Ok(t), None => Ok(self.getenv_unwrap("TARGET")?), } } fn get_host(&self) -> Result { match self.host.clone() { Some(h) => Ok(h), None => Ok(self.getenv_unwrap("HOST")?), } } fn get_opt_level(&self) -> Result { match self.opt_level.as_ref().cloned() { Some(ol) => Ok(ol), None => Ok(self.getenv_unwrap("OPT_LEVEL")?), } } fn get_debug(&self) -> bool { self.debug.unwrap_or_else(|| match self.getenv("DEBUG") { Some(s) => s != "false", None => false, }) } fn get_out_dir(&self) -> Result { match self.out_dir.clone() { Some(p) => Ok(p), None => Ok(env::var_os("OUT_DIR").map(PathBuf::from).ok_or_else(|| { Error::new( ErrorKind::EnvVarNotFound, "Environment variable OUT_DIR not defined.", ) })?), } } fn getenv(&self, v: &str) -> Option { let r = env::var(v).ok(); self.print(&format!("{} = {:?}", v, r)); r } fn getenv_unwrap(&self, v: &str) -> Result { match self.getenv(v) { Some(s) => Ok(s), None => Err(Error::new( ErrorKind::EnvVarNotFound, &format!("Environment variable {} not defined.", v.to_string()), )), } } fn print(&self, s: &str) { if self.cargo_metadata { println!("{}", s); } } } impl Default for Build { fn default() -> Build { Build::new() } } impl Tool { fn new(path: PathBuf) -> Tool { Tool::with_features(path, false) } fn with_features(path: PathBuf, cuda: bool) -> Tool { // Try to detect family of the tool from its name, falling back to Gnu. let family = if let Some(fname) = path.file_name().and_then(|p| p.to_str()) { if fname.contains("clang") { ToolFamily::Clang } else if fname.contains("cl") && !fname.contains("cloudabi") && !fname.contains("uclibc") { ToolFamily::Msvc } else { ToolFamily::Gnu } } else { ToolFamily::Gnu }; Tool { path: path, cc_wrapper_path: None, cc_wrapper_args: Vec::new(), args: Vec::new(), env: Vec::new(), family: family, cuda: cuda, } } /// Add a flag, and optionally prepend the NVCC wrapper flag "-Xcompiler". /// /// Currently this is only used for compiling CUDA sources, since NVCC only /// accepts a limited set of GNU-like flags, and the rest must be prefixed /// with a "-Xcompiler" flag to get passed to the underlying C++ compiler. fn push_cc_arg(&mut self, flag: OsString) { if self.cuda { self.args.push(self.family.nvcc_redirect_flag().into()); } self.args.push(flag); } /// Converts this compiler into a `Command` that's ready to be run. /// /// This is useful for when the compiler needs to be executed and the /// command returned will already have the initial arguments and environment /// variables configured. pub fn to_command(&self) -> Command { let mut cmd = match self.cc_wrapper_path { Some(ref cc_wrapper_path) => { let mut cmd = Command::new(&cc_wrapper_path); cmd.arg(&self.path); cmd.args(&self.cc_wrapper_args); cmd } None => Command::new(&self.path), }; cmd.args(&self.args); for &(ref k, ref v) in self.env.iter() { cmd.env(k, v); } cmd } /// Returns the path for this compiler. /// /// Note that this may not be a path to a file on the filesystem, e.g. "cc", /// but rather something which will be resolved when a process is spawned. pub fn path(&self) -> &Path { &self.path } /// Returns the default set of arguments to the compiler needed to produce /// executables for the target this compiler generates. pub fn args(&self) -> &[OsString] { &self.args } /// Returns the set of environment variables needed for this compiler to /// operate. /// /// This is typically only used for MSVC compilers currently. pub fn env(&self) -> &[(OsString, OsString)] { &self.env } /// Returns the compiler command in format of CC environment variable. /// Or empty string if CC env was not present /// /// This is typically used by configure script pub fn cc_env(&self) -> OsString { match self.cc_wrapper_path { Some(ref cc_wrapper_path) => { let mut cc_env = cc_wrapper_path.as_os_str().to_owned(); cc_env.push(" "); cc_env.push(self.path.to_path_buf().into_os_string()); for arg in self.cc_wrapper_args.iter() { cc_env.push(" "); cc_env.push(arg); } cc_env } None => OsString::from(""), } } /// Returns the compiler flags in format of CFLAGS environment variable. /// Important here - this will not be CFLAGS from env, its internal gcc's flags to use as CFLAGS /// This is typically used by configure script pub fn cflags_env(&self) -> OsString { let mut flags = OsString::new(); for (i, arg) in self.args.iter().enumerate() { if i > 0 { flags.push(" "); } flags.push(arg); } flags } /// Whether the tool is GNU Compiler Collection-like. pub fn is_like_gnu(&self) -> bool { self.family == ToolFamily::Gnu } /// Whether the tool is Clang-like. pub fn is_like_clang(&self) -> bool { self.family == ToolFamily::Clang } /// Whether the tool is MSVC-like. pub fn is_like_msvc(&self) -> bool { self.family == ToolFamily::Msvc } } fn run(cmd: &mut Command, program: &str) -> Result<(), Error> { let (mut child, print) = spawn(cmd, program)?; let status = match child.wait() { Ok(s) => s, Err(_) => { return Err(Error::new( ErrorKind::ToolExecError, &format!( "Failed to wait on spawned child process, command {:?} with args {:?}.", cmd, program ), )) } }; print.join().unwrap(); println!("{}", status); if status.success() { Ok(()) } else { Err(Error::new( ErrorKind::ToolExecError, &format!( "Command {:?} with args {:?} did not execute successfully (status code {}).", cmd, program, status ), )) } } fn run_output(cmd: &mut Command, program: &str) -> Result, Error> { cmd.stdout(Stdio::piped()); let (mut child, print) = spawn(cmd, program)?; let mut stdout = vec![]; child .stdout .take() .unwrap() .read_to_end(&mut stdout) .unwrap(); let status = match child.wait() { Ok(s) => s, Err(_) => { return Err(Error::new( ErrorKind::ToolExecError, &format!( "Failed to wait on spawned child process, command {:?} with args {:?}.", cmd, program ), )) } }; print.join().unwrap(); println!("{}", status); if status.success() { Ok(stdout) } else { Err(Error::new( ErrorKind::ToolExecError, &format!( "Command {:?} with args {:?} did not execute successfully (status code {}).", cmd, program, status ), )) } } fn spawn(cmd: &mut Command, program: &str) -> Result<(Child, JoinHandle<()>), Error> { println!("running: {:?}", cmd); // Capture the standard error coming from these programs, and write it out // with cargo:warning= prefixes. Note that this is a bit wonky to avoid // requiring the output to be UTF-8, we instead just ship bytes from one // location to another. match cmd.stderr(Stdio::piped()).spawn() { Ok(mut child) => { let stderr = BufReader::new(child.stderr.take().unwrap()); let print = thread::spawn(move || { for line in stderr.split(b'\n').filter_map(|l| l.ok()) { print!("cargo:warning="); std::io::stdout().write_all(&line).unwrap(); println!(""); } }); Ok((child, print)) } Err(ref e) if e.kind() == io::ErrorKind::NotFound => { let extra = if cfg!(windows) { " (see https://github.com/alexcrichton/cc-rs#compile-time-requirements \ for help)" } else { "" }; Err(Error::new( ErrorKind::ToolNotFound, &format!("Failed to find tool. Is `{}` installed?{}", program, extra), )) } Err(_) => Err(Error::new( ErrorKind::ToolExecError, &format!("Command {:?} with args {:?} failed to start.", cmd, program), )), } } fn fail(s: &str) -> ! { panic!("\n\nInternal error occurred: {}\n\n", s) } fn command_add_output_file(cmd: &mut Command, dst: &Path, msvc: bool, is_asm: bool, is_arm: bool) { if msvc && is_asm && is_arm { cmd.arg("-o").arg(&dst); } else if msvc && is_asm { cmd.arg("/Fo").arg(dst); } else if msvc { let mut s = OsString::from("/Fo"); s.push(&dst); cmd.arg(s); } else { cmd.arg("-o").arg(&dst); } } vendor/cc-1.0.10/src/registry.rs0000664000000000000000000001310013264166600015157 0ustar rootroot// 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use std::ffi::{OsStr, OsString}; use std::io; use std::ops::RangeFrom; use std::os::raw; use std::os::windows::prelude::*; pub struct RegistryKey(Repr); type HKEY = *mut u8; type DWORD = u32; type LPDWORD = *mut DWORD; type LPCWSTR = *const u16; type LPWSTR = *mut u16; type LONG = raw::c_long; type PHKEY = *mut HKEY; type PFILETIME = *mut u8; type LPBYTE = *mut u8; type REGSAM = u32; const ERROR_SUCCESS: DWORD = 0; const ERROR_NO_MORE_ITEMS: DWORD = 259; const HKEY_LOCAL_MACHINE: HKEY = 0x80000002 as HKEY; const REG_SZ: DWORD = 1; const KEY_READ: DWORD = 0x20019; const KEY_WOW64_32KEY: DWORD = 0x200; #[link(name = "advapi32")] extern "system" { fn RegOpenKeyExW( key: HKEY, lpSubKey: LPCWSTR, ulOptions: DWORD, samDesired: REGSAM, phkResult: PHKEY, ) -> LONG; fn RegEnumKeyExW( key: HKEY, dwIndex: DWORD, lpName: LPWSTR, lpcName: LPDWORD, lpReserved: LPDWORD, lpClass: LPWSTR, lpcClass: LPDWORD, lpftLastWriteTime: PFILETIME, ) -> LONG; fn RegQueryValueExW( hKey: HKEY, lpValueName: LPCWSTR, lpReserved: LPDWORD, lpType: LPDWORD, lpData: LPBYTE, lpcbData: LPDWORD, ) -> LONG; fn RegCloseKey(hKey: HKEY) -> LONG; } struct OwnedKey(HKEY); enum Repr { Const(HKEY), Owned(OwnedKey), } pub struct Iter<'a> { idx: RangeFrom, key: &'a RegistryKey, } unsafe impl Sync for Repr {} unsafe impl Send for Repr {} pub static LOCAL_MACHINE: RegistryKey = RegistryKey(Repr::Const(HKEY_LOCAL_MACHINE)); impl RegistryKey { fn raw(&self) -> HKEY { match self.0 { Repr::Const(val) => val, Repr::Owned(ref val) => val.0, } } pub fn open(&self, key: &OsStr) -> io::Result { let key = key.encode_wide().chain(Some(0)).collect::>(); let mut ret = 0 as *mut _; let err = unsafe { RegOpenKeyExW( self.raw(), key.as_ptr(), 0, KEY_READ | KEY_WOW64_32KEY, &mut ret, ) }; if err == ERROR_SUCCESS as LONG { Ok(RegistryKey(Repr::Owned(OwnedKey(ret)))) } else { Err(io::Error::from_raw_os_error(err as i32)) } } pub fn iter(&self) -> Iter { Iter { idx: 0.., key: self, } } pub fn query_str(&self, name: &str) -> io::Result { let name: &OsStr = name.as_ref(); let name = name.encode_wide().chain(Some(0)).collect::>(); let mut len = 0; let mut kind = 0; unsafe { let err = RegQueryValueExW( self.raw(), name.as_ptr(), 0 as *mut _, &mut kind, 0 as *mut _, &mut len, ); if err != ERROR_SUCCESS as LONG { return Err(io::Error::from_raw_os_error(err as i32)); } if kind != REG_SZ { return Err(io::Error::new( io::ErrorKind::Other, "registry key wasn't a string", )); } // The length here is the length in bytes, but we're using wide // characters so we need to be sure to halve it for the capacity // passed in. let mut v = Vec::with_capacity(len as usize / 2); let err = RegQueryValueExW( self.raw(), name.as_ptr(), 0 as *mut _, 0 as *mut _, v.as_mut_ptr() as *mut _, &mut len, ); if err != ERROR_SUCCESS as LONG { return Err(io::Error::from_raw_os_error(err as i32)); } v.set_len(len as usize / 2); // Some registry keys may have a terminating nul character, but // we're not interested in that, so chop it off if it's there. if v[v.len() - 1] == 0 { v.pop(); } Ok(OsString::from_wide(&v)) } } } impl Drop for OwnedKey { fn drop(&mut self) { unsafe { RegCloseKey(self.0); } } } impl<'a> Iterator for Iter<'a> { type Item = io::Result; fn next(&mut self) -> Option> { self.idx.next().and_then(|i| unsafe { let mut v = Vec::with_capacity(256); let mut len = v.capacity() as DWORD; let ret = RegEnumKeyExW( self.key.raw(), i, v.as_mut_ptr(), &mut len, 0 as *mut _, 0 as *mut _, 0 as *mut _, 0 as *mut _, ); if ret == ERROR_NO_MORE_ITEMS as LONG { None } else if ret != ERROR_SUCCESS as LONG { Some(Err(io::Error::from_raw_os_error(ret as i32))) } else { v.set_len(len as usize); Some(Ok(OsString::from_wide(&v))) } }) } } vendor/cc-1.0.10/src/setup_config.rs0000664000000000000000000002135213264166600016004 0ustar rootroot// Copyright © 2017 winapi-rs developers // Licensed under the Apache License, Version 2.0 // or the MIT license // , at your option. // All files in the project carrying such notice may not be copied, modified, or distributed // except according to those terms. #![allow(bad_style)] #![allow(unused)] use std::ffi::OsString; use std::ptr::null_mut; use winapi::Interface; use winapi::{LPFILETIME, ULONG}; use winapi::S_FALSE; use winapi::BSTR; use winapi::LPCOLESTR; use winapi::{CoCreateInstance, CLSCTX_ALL}; use winapi::LPSAFEARRAY; use winapi::{IUnknown, IUnknownVtbl}; use winapi::{HRESULT, LCID, LPCWSTR, PULONGLONG}; use com::{BStr, ComPtr}; // Bindings to the Setup.Configuration stuff pub type InstanceState = u32; pub const eNone: InstanceState = 0; pub const eLocal: InstanceState = 1; pub const eRegistered: InstanceState = 2; pub const eNoRebootRequired: InstanceState = 4; pub const eComplete: InstanceState = -1i32 as u32; RIDL!{#[uuid(0xb41463c3, 0x8866, 0x43b5, 0xbc, 0x33, 0x2b, 0x06, 0x76, 0xf7, 0xf4, 0x2e)] interface ISetupInstance(ISetupInstanceVtbl): IUnknown(IUnknownVtbl) { fn GetInstanceId( pbstrInstanceId: *mut BSTR, ) -> HRESULT, fn GetInstallDate( pInstallDate: LPFILETIME, ) -> HRESULT, fn GetInstallationName( pbstrInstallationName: *mut BSTR, ) -> HRESULT, fn GetInstallationPath( pbstrInstallationPath: *mut BSTR, ) -> HRESULT, fn GetInstallationVersion( pbstrInstallationVersion: *mut BSTR, ) -> HRESULT, fn GetDisplayName( lcid: LCID, pbstrDisplayName: *mut BSTR, ) -> HRESULT, fn GetDescription( lcid: LCID, pbstrDescription: *mut BSTR, ) -> HRESULT, fn ResolvePath( pwszRelativePath: LPCOLESTR, pbstrAbsolutePath: *mut BSTR, ) -> HRESULT, }} RIDL!{#[uuid(0x89143c9a, 0x05af, 0x49b0, 0xb7, 0x17, 0x72, 0xe2, 0x18, 0xa2, 0x18, 0x5c)] interface ISetupInstance2(ISetupInstance2Vtbl): ISetupInstance(ISetupInstanceVtbl) { fn GetState( pState: *mut InstanceState, ) -> HRESULT, fn GetPackages( ppsaPackages: *mut LPSAFEARRAY, ) -> HRESULT, fn GetProduct( ppPackage: *mut *mut ISetupPackageReference, ) -> HRESULT, fn GetProductPath( pbstrProductPath: *mut BSTR, ) -> HRESULT, }} RIDL!{#[uuid(0x6380bcff, 0x41d3, 0x4b2e, 0x8b, 0x2e, 0xbf, 0x8a, 0x68, 0x10, 0xc8, 0x48)] interface IEnumSetupInstances(IEnumSetupInstancesVtbl): IUnknown(IUnknownVtbl) { fn Next( celt: ULONG, rgelt: *mut *mut ISetupInstance, pceltFetched: *mut ULONG, ) -> HRESULT, fn Skip( celt: ULONG, ) -> HRESULT, fn Reset() -> HRESULT, fn Clone( ppenum: *mut *mut IEnumSetupInstances, ) -> HRESULT, }} RIDL!{#[uuid(0x42843719, 0xdb4c, 0x46c2, 0x8e, 0x7c, 0x64, 0xf1, 0x81, 0x6e, 0xfd, 0x5b)] interface ISetupConfiguration(ISetupConfigurationVtbl): IUnknown(IUnknownVtbl) { fn EnumInstances( ppEnumInstances: *mut *mut IEnumSetupInstances, ) -> HRESULT, fn GetInstanceForCurrentProcess( ppInstance: *mut *mut ISetupInstance, ) -> HRESULT, fn GetInstanceForPath( wzPath: LPCWSTR, ppInstance: *mut *mut ISetupInstance, ) -> HRESULT, }} RIDL!{#[uuid(0x26aab78c, 0x4a60, 0x49d6, 0xaf, 0x3b, 0x3c, 0x35, 0xbc, 0x93, 0x36, 0x5d)] interface ISetupConfiguration2(ISetupConfiguration2Vtbl): ISetupConfiguration(ISetupConfigurationVtbl) { fn EnumAllInstances( ppEnumInstances: *mut *mut IEnumSetupInstances, ) -> HRESULT, }} RIDL!{#[uuid(0xda8d8a16, 0xb2b6, 0x4487, 0xa2, 0xf1, 0x59, 0x4c, 0xcc, 0xcd, 0x6b, 0xf5)] interface ISetupPackageReference(ISetupPackageReferenceVtbl): IUnknown(IUnknownVtbl) { fn GetId( pbstrId: *mut BSTR, ) -> HRESULT, fn GetVersion( pbstrVersion: *mut BSTR, ) -> HRESULT, fn GetChip( pbstrChip: *mut BSTR, ) -> HRESULT, fn GetLanguage( pbstrLanguage: *mut BSTR, ) -> HRESULT, fn GetBranch( pbstrBranch: *mut BSTR, ) -> HRESULT, fn GetType( pbstrType: *mut BSTR, ) -> HRESULT, fn GetUniqueId( pbstrUniqueId: *mut BSTR, ) -> HRESULT, }} RIDL!{#[uuid(0x42b21b78, 0x6192, 0x463e, 0x87, 0xbf, 0xd5, 0x77, 0x83, 0x8f, 0x1d, 0x5c)] interface ISetupHelper(ISetupHelperVtbl): IUnknown(IUnknownVtbl) { fn ParseVersion( pwszVersion: LPCOLESTR, pullVersion: PULONGLONG, ) -> HRESULT, fn ParseVersionRange( pwszVersionRange: LPCOLESTR, pullMinVersion: PULONGLONG, pullMaxVersion: PULONGLONG, ) -> HRESULT, }} DEFINE_GUID!{CLSID_SetupConfiguration, 0x177f0c4a, 0x1cd3, 0x4de7, 0xa3, 0x2c, 0x71, 0xdb, 0xbb, 0x9f, 0xa3, 0x6d} // Safe wrapper around the COM interfaces pub struct SetupConfiguration(ComPtr); impl SetupConfiguration { pub fn new() -> Result { let mut obj = null_mut(); let err = unsafe { CoCreateInstance( &CLSID_SetupConfiguration, null_mut(), CLSCTX_ALL, &ISetupConfiguration::uuidof(), &mut obj, ) }; if err < 0 { return Err(err); } let obj = unsafe { ComPtr::from_raw(obj as *mut ISetupConfiguration) }; Ok(SetupConfiguration(obj)) } pub fn get_instance_for_current_process(&self) -> Result { let mut obj = null_mut(); let err = unsafe { self.0.GetInstanceForCurrentProcess(&mut obj) }; if err < 0 { return Err(err); } Ok(unsafe { SetupInstance::from_raw(obj) }) } pub fn enum_instances(&self) -> Result { let mut obj = null_mut(); let err = unsafe { self.0.EnumInstances(&mut obj) }; if err < 0 { return Err(err); } Ok(unsafe { EnumSetupInstances::from_raw(obj) }) } pub fn enum_all_instances(&self) -> Result { let mut obj = null_mut(); let this = try!(self.0.cast::()); let err = unsafe { this.EnumAllInstances(&mut obj) }; if err < 0 { return Err(err); } Ok(unsafe { EnumSetupInstances::from_raw(obj) }) } } pub struct SetupInstance(ComPtr); impl SetupInstance { pub unsafe fn from_raw(obj: *mut ISetupInstance) -> SetupInstance { SetupInstance(ComPtr::from_raw(obj)) } pub fn instance_id(&self) -> Result { let mut s = null_mut(); let err = unsafe { self.0.GetInstanceId(&mut s) }; let bstr = unsafe { BStr::from_raw(s) }; if err < 0 { return Err(err); } Ok(bstr.to_osstring()) } pub fn installation_name(&self) -> Result { let mut s = null_mut(); let err = unsafe { self.0.GetInstallationName(&mut s) }; let bstr = unsafe { BStr::from_raw(s) }; if err < 0 { return Err(err); } Ok(bstr.to_osstring()) } pub fn installation_path(&self) -> Result { let mut s = null_mut(); let err = unsafe { self.0.GetInstallationPath(&mut s) }; let bstr = unsafe { BStr::from_raw(s) }; if err < 0 { return Err(err); } Ok(bstr.to_osstring()) } pub fn installation_version(&self) -> Result { let mut s = null_mut(); let err = unsafe { self.0.GetInstallationVersion(&mut s) }; let bstr = unsafe { BStr::from_raw(s) }; if err < 0 { return Err(err); } Ok(bstr.to_osstring()) } pub fn product_path(&self) -> Result { let mut s = null_mut(); let this = try!(self.0.cast::()); let err = unsafe { this.GetProductPath(&mut s) }; let bstr = unsafe { BStr::from_raw(s) }; if err < 0 { return Err(err); } Ok(bstr.to_osstring()) } } pub struct EnumSetupInstances(ComPtr); impl EnumSetupInstances { pub unsafe fn from_raw(obj: *mut IEnumSetupInstances) -> EnumSetupInstances { EnumSetupInstances(ComPtr::from_raw(obj)) } } impl Iterator for EnumSetupInstances { type Item = Result; fn next(&mut self) -> Option> { let mut obj = null_mut(); let err = unsafe { self.0.Next(1, &mut obj, null_mut()) }; if err < 0 { return Some(Err(err)); } if err == S_FALSE { return None; } Some(Ok(unsafe { SetupInstance::from_raw(obj) })) } } vendor/cc-1.0.10/src/winapi.rs0000664000000000000000000001415513264166600014611 0ustar rootroot// Copyright © 2015-2017 winapi-rs developers // Licensed under the Apache License, Version 2.0 // or the MIT license // , at your option. // All files in the project carrying such notice may not be copied, modified, or distributed // except according to those terms. #![allow(bad_style)] use std::os::raw; pub type wchar_t = u16; pub type UINT = raw::c_uint; pub type LPUNKNOWN = *mut IUnknown; pub type REFIID = *const IID; pub type IID = GUID; pub type REFCLSID = *const IID; pub type PVOID = *mut raw::c_void; pub type USHORT = raw::c_ushort; pub type ULONG = raw::c_ulong; pub type LONG = raw::c_long; pub type DWORD = u32; pub type LPVOID = *mut raw::c_void; pub type HRESULT = raw::c_long; pub type LPFILETIME = *mut FILETIME; pub type BSTR = *mut OLECHAR; pub type OLECHAR = WCHAR; pub type WCHAR = wchar_t; pub type LPCOLESTR = *const OLECHAR; pub type LCID = DWORD; pub type LPCWSTR = *const WCHAR; pub type PULONGLONG = *mut ULONGLONG; pub type ULONGLONG = u64; pub const S_OK: HRESULT = 0; pub const S_FALSE: HRESULT = 1; pub const COINIT_MULTITHREADED: u32 = 0x0; pub type CLSCTX = u32; pub const CLSCTX_INPROC_SERVER: CLSCTX = 0x1; pub const CLSCTX_INPROC_HANDLER: CLSCTX = 0x2; pub const CLSCTX_LOCAL_SERVER: CLSCTX = 0x4; pub const CLSCTX_REMOTE_SERVER: CLSCTX = 0x10; pub const CLSCTX_ALL: CLSCTX = CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER; #[repr(C)] #[derive(Copy, Clone)] pub struct GUID { pub Data1: raw::c_ulong, pub Data2: raw::c_ushort, pub Data3: raw::c_ushort, pub Data4: [raw::c_uchar; 8], } #[repr(C)] #[derive(Copy, Clone)] pub struct FILETIME { pub dwLowDateTime: DWORD, pub dwHighDateTime: DWORD, } pub trait Interface { fn uuidof() -> GUID; } #[link(name = "ole32")] #[link(name = "oleaut32")] extern "C" {} extern "system" { pub fn CoInitializeEx(pvReserved: LPVOID, dwCoInit: DWORD) -> HRESULT; pub fn CoCreateInstance( rclsid: REFCLSID, pUnkOuter: LPUNKNOWN, dwClsContext: DWORD, riid: REFIID, ppv: *mut LPVOID, ) -> HRESULT; pub fn SysFreeString(bstrString: BSTR); pub fn SysStringLen(pbstr: BSTR) -> UINT; } #[repr(C)] #[derive(Copy, Clone)] pub struct SAFEARRAYBOUND { pub cElements: ULONG, pub lLbound: LONG, } #[repr(C)] #[derive(Copy, Clone)] pub struct SAFEARRAY { pub cDims: USHORT, pub fFeatures: USHORT, pub cbElements: ULONG, pub cLocks: ULONG, pub pvData: PVOID, pub rgsabound: [SAFEARRAYBOUND; 1], } pub type LPSAFEARRAY = *mut SAFEARRAY; macro_rules! DEFINE_GUID { ( $name:ident, $l:expr, $w1:expr, $w2:expr, $b1:expr, $b2:expr, $b3:expr, $b4:expr, $b5:expr, $b6:expr, $b7:expr, $b8:expr ) => { pub const $name: $crate::winapi::GUID = $crate::winapi::GUID { Data1: $l, Data2: $w1, Data3: $w2, Data4: [$b1, $b2, $b3, $b4, $b5, $b6, $b7, $b8], }; } } macro_rules! RIDL { (#[uuid($($uuid:expr),+)] interface $interface:ident ($vtbl:ident) {$( fn $method:ident($($p:ident : $t:ty,)*) -> $rtr:ty, )+}) => ( #[repr(C)] pub struct $vtbl { $(pub $method: unsafe extern "system" fn( This: *mut $interface, $($p: $t),* ) -> $rtr,)+ } #[repr(C)] pub struct $interface { pub lpVtbl: *const $vtbl, } RIDL!{@impl $interface {$(fn $method($($p: $t,)*) -> $rtr,)+}} RIDL!{@uuid $interface $($uuid),+} ); (#[uuid($($uuid:expr),+)] interface $interface:ident ($vtbl:ident) : $pinterface:ident ($pvtbl:ident) { }) => ( #[repr(C)] pub struct $vtbl { pub parent: $pvtbl, } #[repr(C)] pub struct $interface { pub lpVtbl: *const $vtbl, } RIDL!{@deref $interface $pinterface} RIDL!{@uuid $interface $($uuid),+} ); (#[uuid($($uuid:expr),+)] interface $interface:ident ($vtbl:ident) : $pinterface:ident ($pvtbl:ident) {$( fn $method:ident($($p:ident : $t:ty,)*) -> $rtr:ty, )+}) => ( #[repr(C)] pub struct $vtbl { pub parent: $pvtbl, $(pub $method: unsafe extern "system" fn( This: *mut $interface, $($p: $t,)* ) -> $rtr,)+ } #[repr(C)] pub struct $interface { pub lpVtbl: *const $vtbl, } RIDL!{@impl $interface {$(fn $method($($p: $t,)*) -> $rtr,)+}} RIDL!{@deref $interface $pinterface} RIDL!{@uuid $interface $($uuid),+} ); (@deref $interface:ident $pinterface:ident) => ( impl ::std::ops::Deref for $interface { type Target = $pinterface; #[inline] fn deref(&self) -> &$pinterface { unsafe { &*(self as *const $interface as *const $pinterface) } } } ); (@impl $interface:ident {$( fn $method:ident($($p:ident : $t:ty,)*) -> $rtr:ty, )+}) => ( impl $interface { $(#[inline] pub unsafe fn $method(&self, $($p: $t,)*) -> $rtr { ((*self.lpVtbl).$method)(self as *const _ as *mut _, $($p,)*) })+ } ); (@uuid $interface:ident $l:expr, $w1:expr, $w2:expr, $b1:expr, $b2:expr, $b3:expr, $b4:expr, $b5:expr, $b6:expr, $b7:expr, $b8:expr ) => ( impl $crate::winapi::Interface for $interface { #[inline] fn uuidof() -> $crate::winapi::GUID { $crate::winapi::GUID { Data1: $l, Data2: $w1, Data3: $w2, Data4: [$b1, $b2, $b3, $b4, $b5, $b6, $b7, $b8], } } } ); } RIDL!{#[uuid(0x00000000, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46)] interface IUnknown(IUnknownVtbl) { fn QueryInterface( riid: REFIID, ppvObject: *mut *mut raw::c_void, ) -> HRESULT, fn AddRef() -> ULONG, fn Release() -> ULONG, }} vendor/cc-1.0.10/src/windows_registry.rs0000664000000000000000000006173713264166600016754 0ustar rootroot// 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! A helper module to probe the Windows Registry when looking for //! windows-specific tools. use std::process::Command; use Tool; #[cfg(windows)] macro_rules! otry { ($expr:expr) => (match $expr { Some(val) => val, None => return None, }) } /// Attempts to find a tool within an MSVC installation using the Windows /// registry as a point to search from. /// /// The `target` argument is the target that the tool should work for (e.g. /// compile or link for) and the `tool` argument is the tool to find (e.g. /// `cl.exe` or `link.exe`). /// /// This function will return `None` if the tool could not be found, or it will /// return `Some(cmd)` which represents a command that's ready to execute the /// tool with the appropriate environment variables set. /// /// Note that this function always returns `None` for non-MSVC targets. pub fn find(target: &str, tool: &str) -> Option { find_tool(target, tool).map(|c| c.to_command()) } /// Similar to the `find` function above, this function will attempt the same /// operation (finding a MSVC tool in a local install) but instead returns a /// `Tool` which may be introspected. #[cfg(not(windows))] pub fn find_tool(_target: &str, _tool: &str) -> Option { None } /// Documented above. #[cfg(windows)] pub fn find_tool(target: &str, tool: &str) -> Option { use std::env; // This logic is all tailored for MSVC, if we're not that then bail out // early. if !target.contains("msvc") { return None; } // Looks like msbuild isn't located in the same location as other tools like // cl.exe and lib.exe. To handle this we probe for it manually with // dedicated registry keys. if tool.contains("msbuild") { return impl_::find_msbuild(target); } // If VCINSTALLDIR is set, then someone's probably already run vcvars and we // should just find whatever that indicates. if env::var_os("VCINSTALLDIR").is_some() { return env::var_os("PATH") .and_then(|path| { env::split_paths(&path) .map(|p| p.join(tool)) .find(|p| p.exists()) }) .map(|path| Tool::new(path.into())); } // Ok, if we're here, now comes the fun part of the probing. Default shells // or shells like MSYS aren't really configured to execute `cl.exe` and the // various compiler tools shipped as part of Visual Studio. Here we try to // first find the relevant tool, then we also have to be sure to fill in // environment variables like `LIB`, `INCLUDE`, and `PATH` to ensure that // the tool is actually usable. return impl_::find_msvc_15(tool, target) .or_else(|| impl_::find_msvc_14(tool, target)) .or_else(|| impl_::find_msvc_12(tool, target)) .or_else(|| impl_::find_msvc_11(tool, target)); } /// A version of Visual Studio #[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum VsVers { /// Visual Studio 12 (2013) Vs12, /// Visual Studio 14 (2015) Vs14, /// Visual Studio 15 (2017) Vs15, /// Hidden variant that should not be matched on. Callers that want to /// handle an enumeration of `VsVers` instances should always have a default /// case meaning that it's a VS version they don't understand. #[doc(hidden)] #[allow(bad_style)] __Nonexhaustive_do_not_match_this_or_your_code_will_break, } /// Find the most recent installed version of Visual Studio /// /// This is used by the cmake crate to figure out the correct /// generator. #[cfg(not(windows))] pub fn find_vs_version() -> Result { Err(format!("not windows")) } /// Documented above #[cfg(windows)] pub fn find_vs_version() -> Result { use std::env; match env::var("VisualStudioVersion") { Ok(version) => match &version[..] { "15.0" => Ok(VsVers::Vs15), "14.0" => Ok(VsVers::Vs14), "12.0" => Ok(VsVers::Vs12), vers => Err(format!( "\n\n\ unsupported or unknown VisualStudio version: {}\n\ if another version is installed consider running \ the appropriate vcvars script before building this \ crate\n\ ", vers )), }, _ => { // Check for the presense of a specific registry key // that indicates visual studio is installed. if impl_::has_msbuild_version("15.0") { Ok(VsVers::Vs15) } else if impl_::has_msbuild_version("14.0") { Ok(VsVers::Vs14) } else if impl_::has_msbuild_version("12.0") { Ok(VsVers::Vs12) } else { Err(format!( "\n\n\ couldn't determine visual studio generator\n\ if VisualStudio is installed, however, consider \ running the appropriate vcvars script before building \ this crate\n\ " )) } } } } #[cfg(windows)] mod impl_ { use std::env; use std::ffi::OsString; use std::mem; use std::path::{Path, PathBuf}; use std::fs::File; use std::io::Read; use registry::{RegistryKey, LOCAL_MACHINE}; use com; use setup_config::{SetupConfiguration, SetupInstance}; use Tool; struct MsvcTool { tool: PathBuf, libs: Vec, path: Vec, include: Vec, } impl MsvcTool { fn new(tool: PathBuf) -> MsvcTool { MsvcTool { tool: tool, libs: Vec::new(), path: Vec::new(), include: Vec::new(), } } fn into_tool(self) -> Tool { let MsvcTool { tool, libs, path, include, } = self; let mut tool = Tool::new(tool.into()); add_env(&mut tool, "LIB", libs); add_env(&mut tool, "PATH", path); add_env(&mut tool, "INCLUDE", include); tool } } // In MSVC 15 (2017) MS once again changed the scheme for locating // the tooling. Now we must go through some COM interfaces, which // is super fun for Rust. // // Note that much of this logic can be found [online] wrt paths, COM, etc. // // [online]: https://blogs.msdn.microsoft.com/vcblog/2017/03/06/finding-the-visual-c-compiler-tools-in-visual-studio-2017/ pub fn find_msvc_15(tool: &str, target: &str) -> Option { otry!(com::initialize().ok()); let config = otry!(SetupConfiguration::new().ok()); let iter = otry!(config.enum_all_instances().ok()); for instance in iter { let instance = otry!(instance.ok()); let tool = tool_from_vs15_instance(tool, target, &instance); if tool.is_some() { return tool; } } None } fn tool_from_vs15_instance(tool: &str, target: &str, instance: &SetupInstance) -> Option { let (bin_path, host_dylib_path, lib_path, include_path) = otry!(vs15_vc_paths(target, instance)); let tool_path = bin_path.join(tool); if !tool_path.exists() { return None; }; let mut tool = MsvcTool::new(tool_path); tool.path.push(host_dylib_path); tool.libs.push(lib_path); tool.include.push(include_path); if let Some((atl_lib_path, atl_include_path)) = atl_paths(target, &bin_path) { tool.libs.push(atl_lib_path); tool.include.push(atl_include_path); } otry!(add_sdks(&mut tool, target)); Some(tool.into_tool()) } fn vs15_vc_paths( target: &str, instance: &SetupInstance, ) -> Option<(PathBuf, PathBuf, PathBuf, PathBuf)> { let instance_path: PathBuf = otry!(instance.installation_path().ok()).into(); let version_path = instance_path.join(r"VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt"); let mut version_file = otry!(File::open(version_path).ok()); let mut version = String::new(); otry!(version_file.read_to_string(&mut version).ok()); let version = version.trim(); let host = match host_arch() { X86 => "X86", X86_64 => "X64", _ => return None, }; let target = otry!(lib_subdir(target)); // The directory layout here is MSVC/bin/Host$host/$target/ let path = instance_path.join(r"VC\Tools\MSVC").join(version); // This is the path to the toolchain for a particular target, running // on a given host let bin_path = path.join("bin") .join(&format!("Host{}", host)) .join(&target); // But! we also need PATH to contain the target directory for the host // architecture, because it contains dlls like mspdb140.dll compiled for // the host architecture. let host_dylib_path = path.join("bin") .join(&format!("Host{}", host)) .join(&host.to_lowercase()); let lib_path = path.join("lib").join(&target); let include_path = path.join("include"); Some((bin_path, host_dylib_path, lib_path, include_path)) } fn atl_paths(target: &str, path: &Path) -> Option<(PathBuf, PathBuf)> { let atl_path = path.join("atlfmc"); let sub = otry!(lib_subdir(target)); if atl_path.exists() { Some((atl_path.join("lib").join(sub), atl_path.join("include"))) } else { None } } // For MSVC 14 we need to find the Universal CRT as well as either // the Windows 10 SDK or Windows 8.1 SDK. pub fn find_msvc_14(tool: &str, target: &str) -> Option { let vcdir = otry!(get_vc_dir("14.0")); let mut tool = otry!(get_tool(tool, &vcdir, target)); otry!(add_sdks(&mut tool, target)); Some(tool.into_tool()) } fn add_sdks(tool: &mut MsvcTool, target: &str) -> Option<()> { let sub = otry!(lib_subdir(target)); let (ucrt, ucrt_version) = otry!(get_ucrt_dir()); tool.path .push(ucrt.join("bin").join(&ucrt_version).join(sub)); let ucrt_include = ucrt.join("include").join(&ucrt_version); tool.include.push(ucrt_include.join("ucrt")); let ucrt_lib = ucrt.join("lib").join(&ucrt_version); tool.libs.push(ucrt_lib.join("ucrt").join(sub)); if let Some((sdk, version)) = get_sdk10_dir() { tool.path.push(sdk.join("bin").join(sub)); let sdk_lib = sdk.join("lib").join(&version); tool.libs.push(sdk_lib.join("um").join(sub)); let sdk_include = sdk.join("include").join(&version); tool.include.push(sdk_include.join("um")); tool.include.push(sdk_include.join("winrt")); tool.include.push(sdk_include.join("shared")); } else if let Some(sdk) = get_sdk81_dir() { tool.path.push(sdk.join("bin").join(sub)); let sdk_lib = sdk.join("lib").join("winv6.3"); tool.libs.push(sdk_lib.join("um").join(sub)); let sdk_include = sdk.join("include"); tool.include.push(sdk_include.join("um")); tool.include.push(sdk_include.join("winrt")); tool.include.push(sdk_include.join("shared")); } Some(()) } // For MSVC 12 we need to find the Windows 8.1 SDK. pub fn find_msvc_12(tool: &str, target: &str) -> Option { let vcdir = otry!(get_vc_dir("12.0")); let mut tool = otry!(get_tool(tool, &vcdir, target)); let sub = otry!(lib_subdir(target)); let sdk81 = otry!(get_sdk81_dir()); tool.path.push(sdk81.join("bin").join(sub)); let sdk_lib = sdk81.join("lib").join("winv6.3"); tool.libs.push(sdk_lib.join("um").join(sub)); let sdk_include = sdk81.join("include"); tool.include.push(sdk_include.join("shared")); tool.include.push(sdk_include.join("um")); tool.include.push(sdk_include.join("winrt")); Some(tool.into_tool()) } // For MSVC 11 we need to find the Windows 8 SDK. pub fn find_msvc_11(tool: &str, target: &str) -> Option { let vcdir = otry!(get_vc_dir("11.0")); let mut tool = otry!(get_tool(tool, &vcdir, target)); let sub = otry!(lib_subdir(target)); let sdk8 = otry!(get_sdk8_dir()); tool.path.push(sdk8.join("bin").join(sub)); let sdk_lib = sdk8.join("lib").join("win8"); tool.libs.push(sdk_lib.join("um").join(sub)); let sdk_include = sdk8.join("include"); tool.include.push(sdk_include.join("shared")); tool.include.push(sdk_include.join("um")); tool.include.push(sdk_include.join("winrt")); Some(tool.into_tool()) } fn add_env(tool: &mut Tool, env: &str, paths: Vec) { let prev = env::var_os(env).unwrap_or(OsString::new()); let prev = env::split_paths(&prev); let new = paths.into_iter().chain(prev); tool.env .push((env.to_string().into(), env::join_paths(new).unwrap())); } // Given a possible MSVC installation directory, we look for the linker and // then add the MSVC library path. fn get_tool(tool: &str, path: &Path, target: &str) -> Option { bin_subdir(target) .into_iter() .map(|(sub, host)| { ( path.join("bin").join(sub).join(tool), path.join("bin").join(host), ) }) .filter(|&(ref path, _)| path.is_file()) .map(|(path, host)| { let mut tool = MsvcTool::new(path); tool.path.push(host); tool }) .filter_map(|mut tool| { let sub = otry!(vc_lib_subdir(target)); tool.libs.push(path.join("lib").join(sub)); tool.include.push(path.join("include")); let atlmfc_path = path.join("atlmfc"); if atlmfc_path.exists() { tool.libs.push(atlmfc_path.join("lib").join(sub)); tool.include.push(atlmfc_path.join("include")); } Some(tool) }) .next() } // To find MSVC we look in a specific registry key for the version we are // trying to find. fn get_vc_dir(ver: &str) -> Option { let key = r"SOFTWARE\Microsoft\VisualStudio\SxS\VC7"; let key = otry!(LOCAL_MACHINE.open(key.as_ref()).ok()); let path = otry!(key.query_str(ver).ok()); Some(path.into()) } // To find the Universal CRT we look in a specific registry key for where // all the Universal CRTs are located and then sort them asciibetically to // find the newest version. While this sort of sorting isn't ideal, it is // what vcvars does so that's good enough for us. // // Returns a pair of (root, version) for the ucrt dir if found fn get_ucrt_dir() -> Option<(PathBuf, String)> { let key = r"SOFTWARE\Microsoft\Windows Kits\Installed Roots"; let key = otry!(LOCAL_MACHINE.open(key.as_ref()).ok()); let root = otry!(key.query_str("KitsRoot10").ok()); let readdir = otry!(Path::new(&root).join("lib").read_dir().ok()); let max_libdir = otry!( readdir .filter_map(|dir| dir.ok()) .map(|dir| dir.path()) .filter(|dir| dir.components() .last() .and_then(|c| c.as_os_str().to_str()) .map(|c| c.starts_with("10.") && dir.join("ucrt").is_dir()) .unwrap_or(false)) .max() ); let version = max_libdir.components().last().unwrap(); let version = version.as_os_str().to_str().unwrap().to_string(); Some((root.into(), version)) } // Vcvars finds the correct version of the Windows 10 SDK by looking // for the include `um\Windows.h` because sometimes a given version will // only have UCRT bits without the rest of the SDK. Since we only care about // libraries and not includes, we instead look for `um\x64\kernel32.lib`. // Since the 32-bit and 64-bit libraries are always installed together we // only need to bother checking x64, making this code a tiny bit simpler. // Like we do for the Universal CRT, we sort the possibilities // asciibetically to find the newest one as that is what vcvars does. fn get_sdk10_dir() -> Option<(PathBuf, String)> { let key = r"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0"; let key = otry!(LOCAL_MACHINE.open(key.as_ref()).ok()); let root = otry!(key.query_str("InstallationFolder").ok()); let readdir = otry!(Path::new(&root).join("lib").read_dir().ok()); let mut dirs = readdir .filter_map(|dir| dir.ok()) .map(|dir| dir.path()) .collect::>(); dirs.sort(); let dir = otry!( dirs.into_iter() .rev() .filter(|dir| dir.join("um").join("x64").join("kernel32.lib").is_file()) .next() ); let version = dir.components().last().unwrap(); let version = version.as_os_str().to_str().unwrap().to_string(); Some((root.into(), version)) } // Interestingly there are several subdirectories, `win7` `win8` and // `winv6.3`. Vcvars seems to only care about `winv6.3` though, so the same // applies to us. Note that if we were targetting kernel mode drivers // instead of user mode applications, we would care. fn get_sdk81_dir() -> Option { let key = r"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v8.1"; let key = otry!(LOCAL_MACHINE.open(key.as_ref()).ok()); let root = otry!(key.query_str("InstallationFolder").ok()); Some(root.into()) } fn get_sdk8_dir() -> Option { let key = r"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v8.0"; let key = otry!(LOCAL_MACHINE.open(key.as_ref()).ok()); let root = otry!(key.query_str("InstallationFolder").ok()); Some(root.into()) } const PROCESSOR_ARCHITECTURE_INTEL: u16 = 0; const PROCESSOR_ARCHITECTURE_AMD64: u16 = 9; const X86: u16 = PROCESSOR_ARCHITECTURE_INTEL; const X86_64: u16 = PROCESSOR_ARCHITECTURE_AMD64; // When choosing the tool to use, we have to choose the one which matches // the target architecture. Otherwise we end up in situations where someone // on 32-bit Windows is trying to cross compile to 64-bit and it tries to // invoke the native 64-bit compiler which won't work. // // For the return value of this function, the first member of the tuple is // the folder of the tool we will be invoking, while the second member is // the folder of the host toolchain for that tool which is essential when // using a cross linker. We return a Vec since on x64 there are often two // linkers that can target the architecture we desire. The 64-bit host // linker is preferred, and hence first, due to 64-bit allowing it more // address space to work with and potentially being faster. fn bin_subdir(target: &str) -> Vec<(&'static str, &'static str)> { let arch = target.split('-').next().unwrap(); match (arch, host_arch()) { ("i586", X86) | ("i686", X86) => vec![("", "")], ("i586", X86_64) | ("i686", X86_64) => vec![("amd64_x86", "amd64"), ("", "")], ("x86_64", X86) => vec![("x86_amd64", "")], ("x86_64", X86_64) => vec![("amd64", "amd64"), ("x86_amd64", "")], ("arm", X86) => vec![("x86_arm", "")], ("arm", X86_64) => vec![("amd64_arm", "amd64"), ("x86_arm", "")], _ => vec![], } } fn lib_subdir(target: &str) -> Option<&'static str> { let arch = target.split('-').next().unwrap(); match arch { "i586" | "i686" => Some("x86"), "x86_64" => Some("x64"), "arm" => Some("arm"), "aarch64" => Some("arm64"), _ => None, } } // MSVC's x86 libraries are not in a subfolder fn vc_lib_subdir(target: &str) -> Option<&'static str> { let arch = target.split('-').next().unwrap(); match arch { "i586" | "i686" => Some(""), "x86_64" => Some("amd64"), "arm" => Some("arm"), "aarch64" => Some("arm64"), _ => None, } } #[allow(bad_style)] fn host_arch() -> u16 { type DWORD = u32; type WORD = u16; type LPVOID = *mut u8; type DWORD_PTR = usize; #[repr(C)] struct SYSTEM_INFO { wProcessorArchitecture: WORD, _wReserved: WORD, _dwPageSize: DWORD, _lpMinimumApplicationAddress: LPVOID, _lpMaximumApplicationAddress: LPVOID, _dwActiveProcessorMask: DWORD_PTR, _dwNumberOfProcessors: DWORD, _dwProcessorType: DWORD, _dwAllocationGranularity: DWORD, _wProcessorLevel: WORD, _wProcessorRevision: WORD, } extern "system" { fn GetNativeSystemInfo(lpSystemInfo: *mut SYSTEM_INFO); } unsafe { let mut info = mem::zeroed(); GetNativeSystemInfo(&mut info); info.wProcessorArchitecture } } // Given a registry key, look at all the sub keys and find the one which has // the maximal numeric value. // // Returns the name of the maximal key as well as the opened maximal key. fn max_version(key: &RegistryKey) -> Option<(OsString, RegistryKey)> { let mut max_vers = 0; let mut max_key = None; for subkey in key.iter().filter_map(|k| k.ok()) { let val = subkey .to_str() .and_then(|s| s.trim_left_matches("v").replace(".", "").parse().ok()); let val = match val { Some(s) => s, None => continue, }; if val > max_vers { if let Ok(k) = key.open(&subkey) { max_vers = val; max_key = Some((subkey, k)); } } } max_key } pub fn has_msbuild_version(version: &str) -> bool { match version { "15.0" => { find_msbuild_vs15("x86_64-pc-windows-msvc").is_some() || find_msbuild_vs15("i686-pc-windows-msvc").is_some() } "12.0" | "14.0" => LOCAL_MACHINE .open(&OsString::from(format!( "SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\{}", version ))) .is_ok(), _ => false, } } // see http://stackoverflow.com/questions/328017/path-to-msbuild pub fn find_msbuild(target: &str) -> Option { // VS 15 (2017) changed how to locate msbuild if let Some(r) = find_msbuild_vs15(target) { return Some(r); } else { find_old_msbuild(target) } } fn find_msbuild_vs15(target: &str) -> Option { // Seems like this could also go through SetupConfiguration, // or that find_msvc_15 could just use this registry key // instead of the COM interface. let key = r"SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\VS7"; LOCAL_MACHINE .open(key.as_ref()) .ok() .and_then(|key| key.query_str("15.0").ok()) .map(|path| { let path = PathBuf::from(path).join(r"MSBuild\15.0\Bin\MSBuild.exe"); let mut tool = Tool::new(path); if target.contains("x86_64") { tool.env.push(("Platform".into(), "X64".into())); } tool }) } fn find_old_msbuild(target: &str) -> Option { let key = r"SOFTWARE\Microsoft\MSBuild\ToolsVersions"; LOCAL_MACHINE .open(key.as_ref()) .ok() .and_then(|key| { max_version(&key).and_then(|(_vers, key)| key.query_str("MSBuildToolsPath").ok()) }) .map(|path| { let mut path = PathBuf::from(path); path.push("MSBuild.exe"); let mut tool = Tool::new(path); if target.contains("x86_64") { tool.env.push(("Platform".into(), "X64".into())); } tool }) } } vendor/cc-1.0.10/tests/0000755000000000000000000000000013264166600013317 5ustar rootrootvendor/cc-1.0.10/tests/cc_env.rs0000664000000000000000000000527413264166600015134 0ustar rootrootextern crate cc; extern crate tempdir; use std::env; use std::path::Path; use std::ffi::OsString; mod support; use support::Test; #[test] fn main() { ccache(); distcc(); ccache_spaces(); ccache_env_flags(); leading_spaces(); extra_flags(); path_to_ccache(); more_spaces(); } fn ccache() { let test = Test::gnu(); env::set_var("CC", "ccache cc"); let compiler = test.gcc().file("foo.c").get_compiler(); assert_eq!(compiler.path(), Path::new("cc")); } fn ccache_spaces() { let test = Test::gnu(); test.shim("ccache"); env::set_var("CC", "ccache cc"); let compiler = test.gcc().file("foo.c").get_compiler(); assert_eq!(compiler.path(), Path::new("cc")); } fn distcc() { let test = Test::gnu(); test.shim("distcc"); env::set_var("CC", "distcc cc"); let compiler = test.gcc().file("foo.c").get_compiler(); assert_eq!(compiler.path(), Path::new("cc")); } fn ccache_env_flags() { let test = Test::gnu(); test.shim("ccache"); env::set_var("CC", "ccache lol-this-is-not-a-compiler"); let compiler = test.gcc().file("foo.c").get_compiler(); assert_eq!(compiler.path(), Path::new("lol-this-is-not-a-compiler")); assert_eq!( compiler.cc_env(), OsString::from("ccache lol-this-is-not-a-compiler") ); assert!( compiler .cflags_env() .into_string() .unwrap() .contains("ccache") == false ); assert!( compiler .cflags_env() .into_string() .unwrap() .contains(" lol-this-is-not-a-compiler") == false ); env::set_var("CC", ""); } fn leading_spaces() { let test = Test::gnu(); test.shim("ccache"); env::set_var("CC", " test "); let compiler = test.gcc().file("foo.c").get_compiler(); assert_eq!(compiler.path(), Path::new("test")); env::set_var("CC", ""); } fn extra_flags() { let test = Test::gnu(); test.shim("ccache"); env::set_var("CC", "ccache cc -m32"); let compiler = test.gcc().file("foo.c").get_compiler(); assert_eq!(compiler.path(), Path::new("cc")); } fn path_to_ccache() { let test = Test::gnu(); test.shim("ccache"); env::set_var("CC", "/path/to/ccache.exe cc -m32"); let compiler = test.gcc().file("foo.c").get_compiler(); assert_eq!(compiler.path(), Path::new("cc")); assert_eq!( compiler.cc_env(), OsString::from("/path/to/ccache.exe cc -m32"), ); } fn more_spaces() { let test = Test::gnu(); test.shim("ccache"); env::set_var("CC", "cc -m32"); let compiler = test.gcc().file("foo.c").get_compiler(); assert_eq!(compiler.path(), Path::new("cc")); } vendor/cc-1.0.10/tests/support/0000755000000000000000000000000013264166600015033 5ustar rootrootvendor/cc-1.0.10/tests/support/mod.rs0000664000000000000000000000672613264166600016175 0ustar rootroot#![allow(dead_code)] use std::env; use std::ffi::OsStr; use std::fs::{self, File}; use std::io::prelude::*; use std::path::PathBuf; use cc; use tempdir::TempDir; pub struct Test { pub td: TempDir, pub gcc: PathBuf, pub msvc: bool, } pub struct Execution { args: Vec, } impl Test { pub fn new() -> Test { let mut gcc = PathBuf::from(env::current_exe().unwrap()); gcc.pop(); if gcc.ends_with("deps") { gcc.pop(); } gcc.push(format!("gcc-shim{}", env::consts::EXE_SUFFIX)); Test { td: TempDir::new("gcc-test").unwrap(), gcc: gcc, msvc: false, } } pub fn gnu() -> Test { let t = Test::new(); t.shim("cc").shim("c++").shim("ar"); t } pub fn msvc() -> Test { let mut t = Test::new(); t.shim("cl").shim("lib.exe"); t.msvc = true; t } pub fn shim(&self, name: &str) -> &Test { let fname = format!("{}{}", name, env::consts::EXE_SUFFIX); fs::hard_link(&self.gcc, self.td.path().join(&fname)) .or_else(|_| fs::copy(&self.gcc, self.td.path().join(&fname)).map(|_| ())) .unwrap(); self } pub fn gcc(&self) -> cc::Build { let mut cfg = cc::Build::new(); let mut path = env::split_paths(&env::var_os("PATH").unwrap()).collect::>(); path.insert(0, self.td.path().to_owned()); let target = if self.msvc { "x86_64-pc-windows-msvc" } else { "x86_64-unknown-linux-gnu" }; cfg.target(target) .host(target) .opt_level(2) .debug(false) .out_dir(self.td.path()) .__set_env("PATH", env::join_paths(path).unwrap()) .__set_env("GCCTEST_OUT_DIR", self.td.path()); if self.msvc { cfg.compiler(self.td.path().join("cl")); cfg.archiver(self.td.path().join("lib.exe")); } cfg } pub fn cmd(&self, i: u32) -> Execution { let mut s = String::new(); File::open(self.td.path().join(format!("out{}", i))) .unwrap() .read_to_string(&mut s) .unwrap(); Execution { args: s.lines().map(|s| s.to_string()).collect(), } } } impl Execution { pub fn must_have>(&self, p: P) -> &Execution { if !self.has(p.as_ref()) { panic!("didn't find {:?} in {:?}", p.as_ref(), self.args); } else { self } } pub fn must_not_have>(&self, p: P) -> &Execution { if self.has(p.as_ref()) { panic!("found {:?}", p.as_ref()); } else { self } } pub fn has(&self, p: &OsStr) -> bool { self.args.iter().any(|arg| OsStr::new(arg) == p) } pub fn must_have_in_order(&self, before: &str, after: &str) -> &Execution { let before_position = self.args .iter() .rposition(|x| OsStr::new(x) == OsStr::new(before)); let after_position = self.args .iter() .rposition(|x| OsStr::new(x) == OsStr::new(after)); match (before_position, after_position) { (Some(b), Some(a)) if b < a => {} (b, a) => panic!( "{:?} (last position: {:?}) did not appear before {:?} (last position: {:?})", before, b, after, a ), }; self } } vendor/cc-1.0.10/tests/test.rs0000664000000000000000000001472413264166600014656 0ustar rootrootextern crate cc; extern crate tempdir; use support::Test; mod support; #[test] fn gnu_smoke() { let test = Test::gnu(); test.gcc().file("foo.c").compile("foo"); test.cmd(0) .must_have("-O2") .must_have("foo.c") .must_not_have("-g") .must_have("-c") .must_have("-ffunction-sections") .must_have("-fdata-sections"); test.cmd(1).must_have(test.td.path().join("foo.o")); } #[test] fn gnu_opt_level_1() { let test = Test::gnu(); test.gcc().opt_level(1).file("foo.c").compile("foo"); test.cmd(0).must_have("-O1").must_not_have("-O2"); } #[test] fn gnu_opt_level_s() { let test = Test::gnu(); test.gcc().opt_level_str("s").file("foo.c").compile("foo"); test.cmd(0) .must_have("-Os") .must_not_have("-O1") .must_not_have("-O2") .must_not_have("-O3") .must_not_have("-Oz"); } #[test] fn gnu_debug() { let test = Test::gnu(); test.gcc().debug(true).file("foo.c").compile("foo"); test.cmd(0).must_have("-g"); } #[test] fn gnu_warnings_into_errors() { let test = Test::gnu(); test.gcc() .warnings_into_errors(true) .file("foo.c") .compile("foo"); test.cmd(0).must_have("-Werror"); } #[test] fn gnu_warnings() { let test = Test::gnu(); test.gcc() .warnings(true) .flag("-Wno-missing-field-initializers") .file("foo.c") .compile("foo"); test.cmd(0).must_have("-Wall").must_have("-Wextra"); } #[test] fn gnu_warnings_overridable() { let test = Test::gnu(); test.gcc() .warnings(true) .flag("-Wno-missing-field-initializers") .file("foo.c") .compile("foo"); test.cmd(0) .must_have_in_order("-Wall", "-Wno-missing-field-initializers"); } #[test] fn gnu_x86_64() { for vendor in &["unknown-linux-gnu", "apple-darwin"] { let target = format!("x86_64-{}", vendor); let test = Test::gnu(); test.gcc() .target(&target) .host(&target) .file("foo.c") .compile("foo"); test.cmd(0).must_have("-fPIC").must_have("-m64"); } } #[test] fn gnu_x86_64_no_pic() { for vendor in &["unknown-linux-gnu", "apple-darwin"] { let target = format!("x86_64-{}", vendor); let test = Test::gnu(); test.gcc() .pic(false) .target(&target) .host(&target) .file("foo.c") .compile("foo"); test.cmd(0).must_not_have("-fPIC"); } } #[test] fn gnu_i686() { for vendor in &["unknown-linux-gnu", "apple-darwin"] { let target = format!("i686-{}", vendor); let test = Test::gnu(); test.gcc() .target(&target) .host(&target) .file("foo.c") .compile("foo"); test.cmd(0).must_have("-m32"); } } #[test] fn gnu_i686_pic() { for vendor in &["unknown-linux-gnu", "apple-darwin"] { let target = format!("i686-{}", vendor); let test = Test::gnu(); test.gcc() .pic(true) .target(&target) .host(&target) .file("foo.c") .compile("foo"); test.cmd(0).must_have("-fPIC"); } } #[test] fn gnu_set_stdlib() { let test = Test::gnu(); test.gcc() .cpp_set_stdlib(Some("foo")) .file("foo.c") .compile("foo"); test.cmd(0).must_not_have("-stdlib=foo"); } #[test] fn gnu_include() { let test = Test::gnu(); test.gcc().include("foo/bar").file("foo.c").compile("foo"); test.cmd(0).must_have("-I").must_have("foo/bar"); } #[test] fn gnu_define() { let test = Test::gnu(); test.gcc() .define("FOO", "bar") .define("BAR", None) .file("foo.c") .compile("foo"); test.cmd(0).must_have("-DFOO=bar").must_have("-DBAR"); } #[test] fn gnu_compile_assembly() { let test = Test::gnu(); test.gcc().file("foo.S").compile("foo"); test.cmd(0).must_have("foo.S"); } #[test] fn gnu_shared() { let test = Test::gnu(); test.gcc() .file("foo.c") .shared_flag(true) .static_flag(false) .compile("foo"); test.cmd(0).must_have("-shared").must_not_have("-static"); } #[test] fn gnu_flag_if_supported() { if cfg!(windows) { return; } let test = Test::gnu(); test.gcc() .file("foo.c") .flag_if_supported("-Wall") .flag_if_supported("-Wflag-does-not-exist") .flag_if_supported("-std=c++11") .compile("foo"); test.cmd(0) .must_have("-Wall") .must_not_have("-Wflag-does-not-exist") .must_not_have("-std=c++11"); } #[test] fn gnu_flag_if_supported_cpp() { if cfg!(windows) { return; } let test = Test::gnu(); test.gcc() .cpp(true) .file("foo.cpp") .flag_if_supported("-std=c++11") .compile("foo"); test.cmd(0).must_have("-std=c++11"); } #[test] fn gnu_static() { let test = Test::gnu(); test.gcc() .file("foo.c") .shared_flag(false) .static_flag(true) .compile("foo"); test.cmd(0).must_have("-static").must_not_have("-shared"); } #[test] fn msvc_smoke() { let test = Test::msvc(); test.gcc().file("foo.c").compile("foo"); test.cmd(0) .must_have("/O2") .must_have("foo.c") .must_not_have("/Z7") .must_have("/c") .must_have("/MD"); test.cmd(1).must_have(test.td.path().join("foo.o")); } #[test] fn msvc_opt_level_0() { let test = Test::msvc(); test.gcc().opt_level(0).file("foo.c").compile("foo"); test.cmd(0).must_not_have("/O2"); } #[test] fn msvc_debug() { let test = Test::msvc(); test.gcc().debug(true).file("foo.c").compile("foo"); test.cmd(0).must_have("/Z7"); } #[test] fn msvc_include() { let test = Test::msvc(); test.gcc().include("foo/bar").file("foo.c").compile("foo"); test.cmd(0).must_have("/I").must_have("foo/bar"); } #[test] fn msvc_define() { let test = Test::msvc(); test.gcc() .define("FOO", "bar") .define("BAR", None) .file("foo.c") .compile("foo"); test.cmd(0).must_have("/DFOO=bar").must_have("/DBAR"); } #[test] fn msvc_static_crt() { let test = Test::msvc(); test.gcc().static_crt(true).file("foo.c").compile("foo"); test.cmd(0).must_have("/MT"); } #[test] fn msvc_no_static_crt() { let test = Test::msvc(); test.gcc().static_crt(false).file("foo.c").compile("foo"); test.cmd(0).must_have("/MD"); } vendor/cfg-if-0.1.2/0000755000000000000000000000000013264166600012644 5ustar rootrootvendor/cfg-if-0.1.2/.cargo-checksum.json0000644000000000000000000000013113264166600016503 0ustar rootroot{"files":{},"package":"d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"}vendor/cfg-if-0.1.2/.travis.yml0000664000000000000000000000115113264166600014755 0ustar rootrootlanguage: rust rust: - stable - beta - nightly sudo: false before_script: - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH script: - cargo build --verbose - cargo test --verbose - rustdoc --test README.md -L target/debug -L target/debug/deps - cargo doc --no-deps after_success: - travis-cargo --only nightly doc-upload env: global: secure: "TyMGH+sbPmKs9lKCziKShxWr3G6im0owEchVrbUChWnQIQv1WydXftFoEoUsVl6qZspjehWK1b1AsnIgCXK0HtEi4DnqLsxs0s36bOjfg5yHBT/pETTr6kcq7KAL4Be4GmI331k6gT1Oi0TPFp7Sg9xpiWsQqKIHA5Szk2wpFQ8=" notifications: email: on_success: never vendor/cfg-if-0.1.2/Cargo.toml0000664000000000000000000000076613264166600014607 0ustar rootroot[package] name = "cfg-if" version = "0.1.2" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" repository = "https://github.com/alexcrichton/cfg-if" homepage = "https://github.com/alexcrichton/cfg-if" documentation = "http://alexcrichton.com/cfg-if" description = """ A macro to ergonomically define an item depending on a large number of #[cfg] parameters. Structured like an if-else chain, the first matching branch is the item that gets emitted. """ vendor/cfg-if-0.1.2/LICENSE-APACHE0000664000000000000000000002513713264166600014602 0ustar rootroot 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. vendor/cfg-if-0.1.2/LICENSE-MIT0000664000000000000000000000204113264166600014277 0ustar rootrootCopyright (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. vendor/cfg-if-0.1.2/README.md0000664000000000000000000000173413264166600014132 0ustar rootroot# cfg-if [![Build Status](https://travis-ci.org/alexcrichton/cfg-if.svg?branch=master)](https://travis-ci.org/alexcrichton/cfg-if) [Documentation](http://alexcrichton.com/cfg-if) A macro to ergonomically define an item depending on a large number of #[cfg] parameters. Structured like an if-else chain, the first matching branch is the item that gets emitted. ```toml [dependencies] cfg-if = "0.1" ``` ## Example ```rust #[macro_use] extern crate cfg_if; cfg_if! { if #[cfg(unix)] { fn foo() { /* unix specific functionality */ } } else if #[cfg(target_pointer_width = "32")] { fn foo() { /* non-unix, 32-bit functionality */ } } else { fn foo() { /* fallback implementation */ } } } fn main() { foo(); } ``` # License `cfg-if` is primarily distributed under the terms of both the MIT license and the Apache License (Version 2.0), with portions covered by various BSD-like licenses. See LICENSE-APACHE, and LICENSE-MIT for details. vendor/cfg-if-0.1.2/src/0000755000000000000000000000000013264166600013433 5ustar rootrootvendor/cfg-if-0.1.2/src/lib.rs0000664000000000000000000000614613264166600014560 0ustar rootroot//! A macro for defining #[cfg] if-else statements. //! //! The macro provided by this crate, `cfg_if`, is similar to the `if/elif` C //! preprocessor macro by allowing definition of a cascade of `#[cfg]` cases, //! emitting the implementation which matches first. //! //! This allows you to conveniently provide a long list #[cfg]'d blocks of code //! without having to rewrite each clause multiple times. //! //! # Example //! //! ``` //! #[macro_use] //! extern crate cfg_if; //! //! cfg_if! { //! if #[cfg(unix)] { //! fn foo() { /* unix specific functionality */ } //! } else if #[cfg(target_pointer_width = "32")] { //! fn foo() { /* non-unix, 32-bit functionality */ } //! } else { //! fn foo() { /* fallback implementation */ } //! } //! } //! //! # fn main() {} //! ``` #![no_std] #![doc(html_root_url = "http://alexcrichton.com/cfg-if")] #![deny(missing_docs)] #![cfg_attr(test, deny(warnings))] #[macro_export] macro_rules! cfg_if { ($( if #[cfg($($meta:meta),*)] { $($it:item)* } ) else * else { $($it2:item)* }) => { __cfg_if_items! { () ; $( ( ($($meta),*) ($($it)*) ), )* ( () ($($it2)*) ), } }; ( if #[cfg($($i_met:meta),*)] { $($i_it:item)* } $( else if #[cfg($($e_met:meta),*)] { $($e_it:item)* } )* ) => { __cfg_if_items! { () ; ( ($($i_met),*) ($($i_it)*) ), $( ( ($($e_met),*) ($($e_it)*) ), )* ( () () ), } } } #[macro_export] #[doc(hidden)] macro_rules! __cfg_if_items { (($($not:meta,)*) ; ) => {}; (($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => { __cfg_if_apply! { cfg(all($($m,)* not(any($($not),*)))), $($it)* } __cfg_if_items! { ($($not,)* $($m,)*) ; $($rest)* } } } #[macro_export] #[doc(hidden)] macro_rules! __cfg_if_apply { ($m:meta, $($it:item)*) => { $(#[$m] $it)* } } #[cfg(test)] mod tests { cfg_if! { if #[cfg(test)] { use core::option::Option as Option2; fn works1() -> Option2 { Some(1) } } else { fn works1() -> Option { None } } } cfg_if! { if #[cfg(foo)] { fn works2() -> bool { false } } else if #[cfg(test)] { fn works2() -> bool { true } } else { fn works2() -> bool { false } } } cfg_if! { if #[cfg(foo)] { fn works3() -> bool { false } } else { fn works3() -> bool { true } } } cfg_if! { if #[cfg(test)] { use core::option::Option as Option3; fn works4() -> Option3 { Some(1) } } } cfg_if! { if #[cfg(foo)] { fn works5() -> bool { false } } else if #[cfg(test)] { fn works5() -> bool { true } } } #[test] fn it_works() { assert!(works1().is_some()); assert!(works2()); assert!(works3()); assert!(works4().is_some()); assert!(works5()); } } vendor/cfg-if-0.1.2/tests/0000755000000000000000000000000013264166600014006 5ustar rootrootvendor/cfg-if-0.1.2/tests/xcrate.rs0000664000000000000000000000042013264166600015640 0ustar rootroot#[macro_use] extern crate cfg_if; cfg_if! { if #[cfg(foo)] { fn works() -> bool { false } } else if #[cfg(test)] { fn works() -> bool { true } } else { fn works() -> bool { false } } } #[test] fn smoke() { assert!(works()); } vendor/cmake-0.1.30/0000755000000000000000000000000013264166600012652 5ustar rootrootvendor/cmake-0.1.30/.cargo-checksum.json0000644000000000000000000000013113264166600016511 0ustar rootroot{"files":{},"package":"5cf678ceebedde428000cb3a34465cf3606d1a48da17014948a916deac39da7c"}vendor/cmake-0.1.30/.travis.yml0000664000000000000000000000101413264166600014761 0ustar rootrootlanguage: rust rust: - stable - beta - nightly sudo: false before_script: - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH script: - cargo test --verbose - cargo doc --no-deps after_success: - travis-cargo --only nightly doc-upload env: global: secure: "IA467qqr1j0BpyTqG6hO8Kpt+EUDEjO1pBVhu4+L76/dygkQIwROgqdT7uXZqBPMjU6Rbi0wzGXXHJjbCWVTCjh7U/Q0bK2svtR8DKtM0o1Un/YftSUFt2p/WoiJ9PrkUjKh1rHuoyijpUqAls0JfIz8OdC45egT2SWDufljo+s=" notifications: email: on_success: never vendor/cmake-0.1.30/Cargo.toml0000644000000000000000000000172413264166600014606 0ustar rootroot# 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 = "cmake" version = "0.1.30" authors = ["Alex Crichton "] description = "A build dependency for running `cmake` to build a native library\n" homepage = "https://github.com/alexcrichton/cmake-rs" documentation = "http://alexcrichton.com/cmake-rs" readme = "README.md" keywords = ["build-dependencies"] license = "MIT/Apache-2.0" repository = "https://github.com/alexcrichton/cmake-rs" [dependencies.cc] version = "1.0" vendor/cmake-0.1.30/LICENSE-APACHE0000664000000000000000000002513713264166600014610 0ustar rootroot 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. vendor/cmake-0.1.30/LICENSE-MIT0000664000000000000000000000204113264166600014305 0ustar rootrootCopyright (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. vendor/cmake-0.1.30/README.md0000664000000000000000000000166113264166600014137 0ustar rootroot# cmake [![Build Status](https://travis-ci.org/alexcrichton/cmake-rs.svg?branch=master)](https://travis-ci.org/alexcrichton/cmake-rs) [Documentation](http://alexcrichton.com/cmake-rs) A build dependency for running the `cmake` build tool to compile a native library. ```toml # Cargo.toml [build-dependencies] cmake = "0.2" ``` The CMake executable is assumed to be `cmake` unless the `CMAKE` environmental variable is set. # License This project is licensed under either of * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in Serde by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. vendor/cmake-0.1.30/src/0000755000000000000000000000000013264166600013441 5ustar rootrootvendor/cmake-0.1.30/src/lib.rs0000664000000000000000000006012213264166600014560 0ustar rootroot//! A build dependency for running `cmake` to build a native library //! //! This crate provides some necessary boilerplate and shim support for running //! the system `cmake` command to build a native library. It will add //! appropriate cflags for building code to link into Rust, handle cross //! compilation, and use the necessary generator for the platform being //! targeted. //! //! The builder-style configuration allows for various variables and such to be //! passed down into the build as well. //! //! ## Installation //! //! Add this to your `Cargo.toml`: //! //! ```toml //! [build-dependencies] //! cmake = "0.1" //! ``` //! //! ## Examples //! //! ```no_run //! use cmake; //! //! // Builds the project in the directory located in `libfoo`, installing it //! // into $OUT_DIR //! let dst = cmake::build("libfoo"); //! //! println!("cargo:rustc-link-search=native={}", dst.display()); //! println!("cargo:rustc-link-lib=static=foo"); //! ``` //! //! ```no_run //! use cmake::Config; //! //! let dst = Config::new("libfoo") //! .define("FOO", "BAR") //! .cflag("-foo") //! .build(); //! println!("cargo:rustc-link-search=native={}", dst.display()); //! println!("cargo:rustc-link-lib=static=foo"); //! ``` #![deny(missing_docs)] extern crate cc; use std::env; use std::ffi::{OsString, OsStr}; use std::fs::{self, File}; use std::io::ErrorKind; use std::io::prelude::*; use std::path::{Path, PathBuf}; use std::process::Command; /// Builder style configuration for a pending CMake build. pub struct Config { path: PathBuf, generator: Option, cflags: OsString, cxxflags: OsString, defines: Vec<(OsString, OsString)>, deps: Vec, target: Option, host: Option, out_dir: Option, profile: Option, build_args: Vec, cmake_target: Option, env: Vec<(OsString, OsString)>, static_crt: Option, uses_cxx11: bool, } /// Builds the native library rooted at `path` with the default cmake options. /// This will return the directory in which the library was installed. /// /// # Examples /// /// ```no_run /// use cmake; /// /// // Builds the project in the directory located in `libfoo`, installing it /// // into $OUT_DIR /// let dst = cmake::build("libfoo"); /// /// println!("cargo:rustc-link-search=native={}", dst.display()); /// println!("cargo:rustc-link-lib=static=foo"); /// ``` /// pub fn build>(path: P) -> PathBuf { Config::new(path.as_ref()).build() } impl Config { /// Creates a new blank set of configuration to build the project specified /// at the path `path`. pub fn new>(path: P) -> Config { Config { path: env::current_dir().unwrap().join(path), generator: None, cflags: OsString::new(), cxxflags: OsString::new(), defines: Vec::new(), deps: Vec::new(), profile: None, out_dir: None, target: None, host: None, build_args: Vec::new(), cmake_target: None, env: Vec::new(), static_crt: None, uses_cxx11: false } } /// Sets the build-tool generator (`-G`) for this compilation. pub fn generator>(&mut self, generator: T) -> &mut Config { self.generator = Some(generator.as_ref().to_owned()); self } /// Adds a custom flag to pass down to the C compiler, supplementing those /// that this library already passes. pub fn cflag>(&mut self, flag: P) -> &mut Config { self.cflags.push(" "); self.cflags.push(flag.as_ref()); self } /// Adds a custom flag to pass down to the C++ compiler, supplementing those /// that this library already passes. pub fn cxxflag>(&mut self, flag: P) -> &mut Config { self.cxxflags.push(" "); self.cxxflags.push(flag.as_ref()); self } /// Adds a new `-D` flag to pass to cmake during the generation step. pub fn define(&mut self, k: K, v: V) -> &mut Config where K: AsRef, V: AsRef { self.defines.push((k.as_ref().to_owned(), v.as_ref().to_owned())); self } /// Registers a dependency for this compilation on the native library built /// by Cargo previously. /// /// This registration will modify the `CMAKE_PREFIX_PATH` environment /// variable for the build system generation step. pub fn register_dep(&mut self, dep: &str) -> &mut Config { self.deps.push(dep.to_string()); self } /// Sets the target triple for this compilation. /// /// This is automatically scraped from `$TARGET` which is set for Cargo /// build scripts so it's not necessary to call this from a build script. pub fn target(&mut self, target: &str) -> &mut Config { self.target = Some(target.to_string()); self } /// Sets the host triple for this compilation. /// /// This is automatically scraped from `$HOST` which is set for Cargo /// build scripts so it's not necessary to call this from a build script. pub fn host(&mut self, host: &str) -> &mut Config { self.host = Some(host.to_string()); self } /// Sets the output directory for this compilation. /// /// This is automatically scraped from `$OUT_DIR` which is set for Cargo /// build scripts so it's not necessary to call this from a build script. pub fn out_dir>(&mut self, out: P) -> &mut Config { self.out_dir = Some(out.as_ref().to_path_buf()); self } /// Sets the profile for this compilation. /// /// This is automatically scraped from `$PROFILE` which is set for Cargo /// build scripts so it's not necessary to call this from a build script. pub fn profile(&mut self, profile: &str) -> &mut Config { self.profile = Some(profile.to_string()); self } /// Configures whether the /MT flag or the /MD flag will be passed to msvc build tools. /// /// This option defaults to `false`, and affect only msvc targets. pub fn static_crt(&mut self, static_crt: bool) -> &mut Config { self.static_crt = Some(static_crt); self } /// Add an argument to the final `cmake` build step pub fn build_arg>(&mut self, arg: A) -> &mut Config { self.build_args.push(arg.as_ref().to_owned()); self } /// Configure an environment variable for the `cmake` processes spawned by /// this crate in the `build` step. pub fn env(&mut self, key: K, value: V) -> &mut Config where K: AsRef, V: AsRef, { self.env.push((key.as_ref().to_owned(), value.as_ref().to_owned())); self } /// Sets the build target for the final `cmake` build step, this will /// default to "install" if not specified. pub fn build_target(&mut self, target: &str) -> &mut Config { self.cmake_target = Some(target.to_string()); self } /// Alters the default target triple on OSX to ensure that c++11 is /// available. Does not change the target triple if it is explicitly /// specified. /// /// This does not otherwise affect any CXX flags, i.e. it does not set /// -std=c++11 or -stdlib=libc++. pub fn uses_cxx11(&mut self) -> &mut Config { self.uses_cxx11 = true; self } /// Run this configuration, compiling the library with all the configured /// options. /// /// This will run both the build system generator command as well as the /// command to build the library. pub fn build(&mut self) -> PathBuf { let target = match self.target.clone() { Some(t) => t, None => { let mut t = getenv_unwrap("TARGET"); if t.ends_with("-darwin") && self.uses_cxx11 { t = t + "11" } t } }; let host = self.host.clone().unwrap_or_else(|| { getenv_unwrap("HOST") }); let msvc = target.contains("msvc"); let mut c_cfg = cc::Build::new(); c_cfg.cargo_metadata(false) .opt_level(0) .debug(false) .target(&target) .warnings(false) .host(&host); let mut cxx_cfg = cc::Build::new(); cxx_cfg.cargo_metadata(false) .cpp(true) .opt_level(0) .debug(false) .target(&target) .warnings(false) .host(&host); if let Some(static_crt) = self.static_crt { c_cfg.static_crt(static_crt); cxx_cfg.static_crt(static_crt); } let c_compiler = c_cfg.get_compiler(); let cxx_compiler = cxx_cfg.get_compiler(); let dst = self.out_dir.clone().unwrap_or_else(|| { PathBuf::from(getenv_unwrap("OUT_DIR")) }); let build = dst.join("build"); self.maybe_clear(&build); let _ = fs::create_dir(&build); // Add all our dependencies to our cmake paths let mut cmake_prefix_path = Vec::new(); for dep in &self.deps { if let Some(root) = env::var_os(&format!("DEP_{}_ROOT", dep)) { cmake_prefix_path.push(PathBuf::from(root)); } } let system_prefix = env::var_os("CMAKE_PREFIX_PATH") .unwrap_or(OsString::new()); cmake_prefix_path.extend(env::split_paths(&system_prefix) .map(|s| s.to_owned())); let cmake_prefix_path = env::join_paths(&cmake_prefix_path).unwrap(); // Build up the first cmake command to build the build system. let executable = env::var("CMAKE").unwrap_or("cmake".to_owned()); let mut cmd = Command::new(executable); cmd.arg(&self.path) .current_dir(&build); if target.contains("windows-gnu") { if host.contains("windows") { // On MinGW we need to coerce cmake to not generate a visual // studio build system but instead use makefiles that MinGW can // use to build. if self.generator.is_none() { cmd.arg("-G").arg("MSYS Makefiles"); } } else { // If we're cross compiling onto windows, then set some // variables which will hopefully get things to succeed. Some // systems may need the `windres` or `dlltool` variables set, so // set them if possible. if !self.defined("CMAKE_SYSTEM_NAME") { cmd.arg("-DCMAKE_SYSTEM_NAME=Windows"); } if !self.defined("CMAKE_RC_COMPILER") { let exe = find_exe(c_compiler.path()); if let Some(name) = exe.file_name().unwrap().to_str() { let name = name.replace("gcc", "windres"); let windres = exe.with_file_name(name); if windres.is_file() { let mut arg = OsString::from("-DCMAKE_RC_COMPILER="); arg.push(&windres); cmd.arg(arg); } } } } } else if msvc { // If we're on MSVC we need to be sure to use the right generator or // otherwise we won't get 32/64 bit correct automatically. // This also guarantees that NMake generator isn't chosen implicitly. if self.generator.is_none() { cmd.arg("-G").arg(self.visual_studio_generator(&target)); } } else if target.contains("redox") { if !self.defined("CMAKE_SYSTEM_NAME") { cmd.arg("-DCMAKE_SYSTEM_NAME=Generic"); } } else if target.contains("solaris") { if !self.defined("CMAKE_SYSTEM_NAME") { cmd.arg("-DCMAKE_SYSTEM_NAME=SunOS"); } } let mut is_ninja = false; if let Some(ref generator) = self.generator { cmd.arg("-G").arg(generator); is_ninja = generator.to_string_lossy().contains("Ninja"); } let profile = self.profile.clone().unwrap_or_else(|| { match &getenv_unwrap("PROFILE")[..] { "bench" | "release" => "Release", _ => "Debug", }.to_string() }); for &(ref k, ref v) in &self.defines { let mut os = OsString::from("-D"); os.push(k); os.push("="); os.push(v); cmd.arg(os); } if !self.defined("CMAKE_INSTALL_PREFIX") { let mut dstflag = OsString::from("-DCMAKE_INSTALL_PREFIX="); dstflag.push(&dst); cmd.arg(dstflag); } let build_type = self.defines.iter().find(|&&(ref a, _)| { a == "CMAKE_BUILD_TYPE" }).map(|x| x.1.to_str().unwrap()).unwrap_or(&profile); let build_type_upcase = build_type.chars() .flat_map(|c| c.to_uppercase()) .collect::(); { // let cmake deal with optimization/debuginfo let skip_arg = |arg: &OsStr| { match arg.to_str() { Some(s) => { s.starts_with("-O") || s.starts_with("/O") || s == "-g" } None => false, } }; let mut set_compiler = |kind: &str, compiler: &cc::Tool, extra: &OsString| { let flag_var = format!("CMAKE_{}_FLAGS", kind); let tool_var = format!("CMAKE_{}_COMPILER", kind); if !self.defined(&flag_var) { let mut flagsflag = OsString::from("-D"); flagsflag.push(&flag_var); flagsflag.push("="); flagsflag.push(extra); for arg in compiler.args() { if skip_arg(arg) { continue } flagsflag.push(" "); flagsflag.push(arg); } cmd.arg(flagsflag); } // The visual studio generator apparently doesn't respect // `CMAKE_C_FLAGS` but does respect `CMAKE_C_FLAGS_RELEASE` and // such. We need to communicate /MD vs /MT, so set those vars // here. // // Note that for other generators, though, this *overrides* // things like the optimization flags, which is bad. if self.generator.is_none() && msvc { let flag_var_alt = format!("CMAKE_{}_FLAGS_{}", kind, build_type_upcase); if !self.defined(&flag_var_alt) { let mut flagsflag = OsString::from("-D"); flagsflag.push(&flag_var_alt); flagsflag.push("="); flagsflag.push(extra); for arg in compiler.args() { if skip_arg(arg) { continue } flagsflag.push(" "); flagsflag.push(arg); } cmd.arg(flagsflag); } } // Apparently cmake likes to have an absolute path to the // compiler as otherwise it sometimes thinks that this variable // changed as it thinks the found compiler, /usr/bin/cc, // differs from the specified compiler, cc. Not entirely sure // what's up, but at least this means cmake doesn't get // confused? // // Also specify this on Windows only if we use MSVC with Ninja, // as it's not needed for MSVC with Visual Studio generators and // for MinGW it doesn't really vary. if !self.defined("CMAKE_TOOLCHAIN_FILE") && !self.defined(&tool_var) && (env::consts::FAMILY != "windows" || (msvc && is_ninja)) { let mut ccompiler = OsString::from("-D"); ccompiler.push(&tool_var); ccompiler.push("="); ccompiler.push(find_exe(compiler.path())); #[cfg(windows)] { // CMake doesn't like unescaped `\`s in compiler paths // so we either have to escape them or replace with `/`s. use std::os::windows::ffi::{OsStrExt, OsStringExt}; let wchars = ccompiler.encode_wide().map(|wchar| { if wchar == b'\\' as u16 { '/' as u16 } else { wchar } }).collect::>(); ccompiler = OsString::from_wide(&wchars); } cmd.arg(ccompiler); } }; set_compiler("C", &c_compiler, &self.cflags); set_compiler("CXX", &cxx_compiler, &self.cxxflags); } if !self.defined("CMAKE_BUILD_TYPE") { cmd.arg(&format!("-DCMAKE_BUILD_TYPE={}", profile)); } if !self.defined("CMAKE_TOOLCHAIN_FILE") { if let Ok(s) = env::var("CMAKE_TOOLCHAIN_FILE") { cmd.arg(&format!("-DCMAKE_TOOLCHAIN_FILE={}", s)); } } for &(ref k, ref v) in c_compiler.env().iter().chain(&self.env) { cmd.env(k, v); } run(cmd.env("CMAKE_PREFIX_PATH", cmake_prefix_path), "cmake"); let mut makeflags = None; let mut parallel_args = Vec::new(); if let Ok(s) = env::var("NUM_JOBS") { match self.generator.as_ref().map(|g| g.to_string_lossy()) { Some(ref g) if g.contains("Ninja") => { parallel_args.push(format!("-j{}", s)); } Some(ref g) if g.contains("Visual Studio") => { parallel_args.push(format!("/m:{}", s)); } Some(ref g) if g.contains("NMake") => { // NMake creates `Makefile`s, but doesn't understand `-jN`. } _ if fs::metadata(&dst.join("build/Makefile")).is_ok() => { match env::var_os("CARGO_MAKEFLAGS") { // Only do this on non-windows and non-bsd // On Windows, we could be invoking make instead of // mingw32-make which doesn't work with our jobserver // bsdmake also does not work with our job server Some(ref s) if !(cfg!(windows) || cfg!(target_os = "openbsd") || cfg!(target_os = "netbsd") || cfg!(target_os = "freebsd") || cfg!(target_os = "bitrig") || cfg!(target_os = "dragonflybsd") ) => makeflags = Some(s.clone()), // This looks like `make`, let's hope it understands `-jN`. _ => parallel_args.push(format!("-j{}", s)), } } _ => {} } } // And build! let target = self.cmake_target.clone().unwrap_or("install".to_string()); let mut cmd = Command::new("cmake"); for &(ref k, ref v) in c_compiler.env().iter().chain(&self.env) { cmd.env(k, v); } if let Some(flags) = makeflags { cmd.env("MAKEFLAGS", flags); } run(cmd.arg("--build").arg(".") .arg("--target").arg(target) .arg("--config").arg(&profile) .arg("--").args(&self.build_args) .args(¶llel_args) .current_dir(&build), "cmake"); println!("cargo:root={}", dst.display()); return dst } fn visual_studio_generator(&self, target: &str) -> String { use cc::windows_registry::{find_vs_version, VsVers}; let base = match find_vs_version() { Ok(VsVers::Vs15) => "Visual Studio 15 2017", Ok(VsVers::Vs14) => "Visual Studio 14 2015", Ok(VsVers::Vs12) => "Visual Studio 12 2013", Ok(_) => panic!("Visual studio version detected but this crate \ doesn't know how to generate cmake files for it, \ can the `cmake` crate be updated?"), Err(msg) => panic!(msg), }; if target.contains("i686") { base.to_string() } else if target.contains("x86_64") { format!("{} Win64", base) } else { panic!("unsupported msvc target: {}", target); } } fn defined(&self, var: &str) -> bool { self.defines.iter().any(|&(ref a, _)| a == var) } // If a cmake project has previously been built (e.g. CMakeCache.txt already // exists), then cmake will choke if the source directory for the original // project being built has changed. Detect this situation through the // `CMAKE_HOME_DIRECTORY` variable that cmake emits and if it doesn't match // we blow away the build directory and start from scratch (the recommended // solution apparently [1]). // // [1]: https://cmake.org/pipermail/cmake/2012-August/051545.html fn maybe_clear(&self, dir: &Path) { // CMake will apparently store canonicalized paths which normally // isn't relevant to us but we canonicalize it here to ensure // we're both checking the same thing. let path = fs::canonicalize(&self.path).unwrap_or(self.path.clone()); let mut f = match File::open(dir.join("CMakeCache.txt")) { Ok(f) => f, Err(..) => return, }; let mut u8contents = Vec::new(); match f.read_to_end(&mut u8contents) { Ok(f) => f, Err(..) => return, }; let contents = String::from_utf8_lossy(&u8contents); drop(f); for line in contents.lines() { if line.starts_with("CMAKE_HOME_DIRECTORY") { let needs_cleanup = match line.split('=').next_back() { Some(cmake_home) => { fs::canonicalize(cmake_home) .ok() .map(|cmake_home| cmake_home != path) .unwrap_or(true) }, None => true }; if needs_cleanup { println!("detected home dir change, cleaning out entire build \ directory"); fs::remove_dir_all(dir).unwrap(); } break } } } } fn run(cmd: &mut Command, program: &str) { println!("running: {:?}", cmd); let status = match cmd.status() { Ok(status) => status, Err(ref e) if e.kind() == ErrorKind::NotFound => { fail(&format!("failed to execute command: {}\nis `{}` not installed?", e, program)); } Err(e) => fail(&format!("failed to execute command: {}", e)), }; if !status.success() { fail(&format!("command did not execute successfully, got: {}", status)); } } fn find_exe(path: &Path) -> PathBuf { env::split_paths(&env::var_os("PATH").unwrap_or(OsString::new())) .map(|p| p.join(path)) .find(|p| fs::metadata(p).is_ok()) .unwrap_or(path.to_owned()) } fn getenv_unwrap(v: &str) -> String { match env::var(v) { Ok(s) => s, Err(..) => fail(&format!("environment variable `{}` not defined", v)), } } fn fail(s: &str) -> ! { panic!("\n{}\n\nbuild script failed, must exit now", s) } vendor/commoncrypto-0.2.0/0000755000000000000000000000000013264166600014241 5ustar rootrootvendor/commoncrypto-0.2.0/.cargo-checksum.json0000644000000000000000000000013113264166600020100 0ustar rootroot{"files":{},"package":"d056a8586ba25a1e4d61cb090900e495952c7886786fc55f909ab2f819b69007"}vendor/commoncrypto-0.2.0/Cargo.toml0000644000000000000000000000102213264166600016164 0ustar rootroot[package] name = "commoncrypto" version = "0.2.0" authors = ["Mark Lee"] description = "Idiomatic Rust wrappers for Mac OS X's CommonCrypto library" documentation = "https://docs.rs/commoncrypto" repository = "https://github.com/malept/rust-commoncrypto" keywords = ["crypto", "hash", "digest", "osx", "commoncrypto"] license = "MIT" [features] lint = ["clippy"] [dependencies] commoncrypto-sys = { version = "0.2.0", path = "../commoncrypto-sys" } clippy = { version = "0.0", optional = true } [dev-dependencies] hex = "0.2" vendor/commoncrypto-0.2.0/src/0000755000000000000000000000000013264166600015030 5ustar rootrootvendor/commoncrypto-0.2.0/src/hash.rs0000644000000000000000000000766113264166600016333 0ustar rootroot// Copyright (c) 2016 Mark Lee // // 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. //! Idiomatic Rust wrapper for `CommonCrypto`'s `CCDigestCtx` struct. use commoncrypto_sys::{CCDigestCreate, CCDigestCtx, CCDigestDestroy, CCDigestFinal, CCDigestGetOutputSizeFromRef, CCDigestReset, CCDigestUpdate}; use std::io; pub use commoncrypto_sys::CCDigestAlgorithm; const MAX_DIGEST_SIZE: usize = 64; macro_rules! err_from_ccdigest_retval{ ($func_name: expr, $val: expr) => { Err(io::Error::new(io::ErrorKind::Other, format!("{} returned nonzero: {}", $func_name, $val))) } } #[derive(PartialEq, Copy, Clone, Debug)] enum State { Reset, Updated, Finalized, } /// Generates cryptographic hashes. #[derive(Debug)] pub struct Hasher { ctx: *mut CCDigestCtx, state: State, } impl Hasher { /// Creates a new `Hasher` which will use the given cryptographic `algorithm`. pub fn new(algorithm: CCDigestAlgorithm) -> Hasher { let ctx: *mut CCDigestCtx; unsafe { ctx = CCDigestCreate(algorithm); } Hasher { ctx: ctx, state: State::Reset, } } fn init(&mut self) { match self.state { State::Reset => return, State::Updated => { let _ = self.finish(); } State::Finalized => (), } unsafe { CCDigestReset(self.ctx) }; self.state = State::Reset; } /// Feeds data into the hasher. pub fn update(&mut self, data: &[u8]) -> io::Result { if self.state == State::Finalized { self.init(); } let result = unsafe { CCDigestUpdate(self.ctx, data.as_ptr() as *mut _, data.len()) }; if result == 0 { self.state = State::Updated; Ok(data.len()) } else { err_from_ccdigest_retval!("CCDigestCreate", result) } } /// Finalizes digest operations and produces the digest output. pub fn finish(&mut self) -> io::Result> { if self.state == State::Finalized { self.init(); } let expected_len = unsafe { CCDigestGetOutputSizeFromRef(self.ctx) }; let mut md = vec![0; MAX_DIGEST_SIZE]; let result = unsafe { CCDigestFinal(self.ctx, md.as_mut_ptr()) }; if result == 0 { self.state = State::Finalized; md.truncate(expected_len); Ok(md) } else { err_from_ccdigest_retval!("CCDigestFinal", result) } } } impl io::Write for Hasher { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { self.update(buf) } fn flush(&mut self) -> io::Result<()> { Ok(()) } } impl Drop for Hasher { fn drop(&mut self) { if self.state != State::Finalized { let _ = self.finish(); } unsafe { CCDigestDestroy(self.ctx) } } } vendor/commoncrypto-0.2.0/src/lib.rs0000644000000000000000000000241713264166600016150 0ustar rootroot// Copyright (c) 2016 Mark Lee // // 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. //! Idiomatic Rust wrappers for `CommonCrypto` structs. #![warn(missing_docs)] extern crate commoncrypto_sys; #[warn(missing_docs)] pub mod hash; #[warn(missing_docs)] pub mod pbkdf2; vendor/commoncrypto-0.2.0/src/pbkdf2.rs0000644000000000000000000000504613264166600016553 0ustar rootroot// Copyright (c) 2016 // // 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. //! Idiomatic Rust wrapper for `CommonCrypto`'s `CCKeyDerivationPBKDF` function. use commoncrypto_sys::{CCKeyDerivationPBKDF, CCPBKDFAlgorithm}; use std::io; pub use commoncrypto_sys::CCPseudoRandomAlgorithm; macro_rules! err_from_cckeyderivationpbkdf_retval { ($func_name: expr, $val: expr) => {{ let kind = match $val { // kCCParamError is the only one that's specifically noted -43000 => io::ErrorKind::InvalidInput, _ => io::ErrorKind::Other, }; Err(io::Error::new(kind, format!("{} returned nonzero: {}", $func_name, $val))) }} } /// Derive a key from a password or passphrase and a salt pub fn pbkdf2(password: &[u8], salt: &[u8], prf: CCPseudoRandomAlgorithm, rounds: u32, key_len: usize) -> io::Result> { let mut pw_derived = vec![0u8; key_len]; let result = unsafe { CCKeyDerivationPBKDF(CCPBKDFAlgorithm::kCCPBKDF2, password.as_ptr(), password.len(), salt.as_ptr(), salt.len(), prf, rounds, pw_derived.as_mut_ptr(), pw_derived.len()) }; if result == 0 { Ok(pw_derived) } else { err_from_cckeyderivationpbkdf_retval!("CCKeyDerivationPBKDF", result) } } vendor/commoncrypto-0.2.0/tests/0000755000000000000000000000000013264166600015403 5ustar rootrootvendor/commoncrypto-0.2.0/tests/hash.rs0000644000000000000000000000107013264166600016672 0ustar rootrootextern crate commoncrypto; extern crate hex; use commoncrypto::hash::{CCDigestAlgorithm, Hasher}; use hex::ToHex; use std::io::Write; const TO_HASH: &'static str = "The quick brown fox jumps over the lazy dog"; const TO_HASH_MD5: &'static str = "9e107d9d372bb6826bd81d3542a419d6"; #[test] fn md5_hasher() { let mut hasher = Hasher::new(CCDigestAlgorithm::kCCDigestMD5); assert!(hasher.write_all(TO_HASH.as_bytes()).is_ok()); let result = hasher.finish(); assert!(result.is_ok()); assert_eq!(result.expect("Hash failed").to_hex(), TO_HASH_MD5) } vendor/commoncrypto-0.2.0/tests/pbkdf2.rs0000644000000000000000000000070213264166600017120 0ustar rootrootextern crate commoncrypto; extern crate hex; use commoncrypto::pbkdf2::{pbkdf2, CCPseudoRandomAlgorithm}; use hex::ToHex; #[test] fn derive_pbkdf2() { let derived = pbkdf2(b"password", b"salt", CCPseudoRandomAlgorithm::kCCPRFHmacAlgSHA1, 1, 20) .unwrap(); assert_eq!("0c60c80f961f0e71f3a9b524af6012062fe037a6", derived.to_hex()); } vendor/commoncrypto-sys-0.2.0/0000755000000000000000000000000013264166600015055 5ustar rootrootvendor/commoncrypto-sys-0.2.0/.cargo-checksum.json0000644000000000000000000000013113264166600020714 0ustar rootroot{"files":{},"package":"1fed34f46747aa73dfaa578069fd8279d2818ade2b55f38f22a9401c7f4083e2"}vendor/commoncrypto-sys-0.2.0/Cargo.toml0000644000000000000000000000072413264166600017010 0ustar rootroot[package] name = "commoncrypto-sys" version = "0.2.0" authors = ["Mark Lee"] description = "FFI bindings to Mac OS X's CommonCrypto library" documentation = "https://docs.rs/commoncrypto-sys" repository = "https://github.com/malept/rust-commoncrypto" keywords = ["crypto", "hash", "digest", "osx", "commoncrypto"] license = "MIT" [features] lint = ["clippy"] [dependencies] libc = "0.2" clippy = { version = "0.0", optional = true } [dev-dependencies] hex = "0.2" vendor/commoncrypto-sys-0.2.0/src/0000755000000000000000000000000013264166600015644 5ustar rootrootvendor/commoncrypto-sys-0.2.0/src/lib.rs0000644000000000000000000002175713264166600016774 0ustar rootroot// Copyright (c) 2016 Mark Lee // // 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. //! Low-level bindings to OSX/macOS/iOS's `CommonCrypto` library. #![warn(missing_docs)] extern crate libc; use libc::{c_int, c_uint}; /// Total number of operations. const MD5_CBLOCK: usize = 64; /// Number of operations per round. const MD5_LBLOCK: usize = MD5_CBLOCK / 4; /// Number of bytes for an MD5 hash. pub const MD5_DIGEST_LENGTH: usize = 16; const SHA_LBLOCK: usize = 16; /// Number of bytes for an SHA1 hash. pub const SHA1_DIGEST_LENGTH: usize = 20; /// Number of bytes for an SHA256 hash. pub const SHA256_DIGEST_LENGTH: usize = 32; /// Number of bytes for an SHA384 hash. pub const SHA384_DIGEST_LENGTH: usize = 48; /// Number of bytes for an SHA512 hash. pub const SHA512_DIGEST_LENGTH: usize = 64; /// Struct used to generate MD5 hashes. #[allow(non_camel_case_types, non_snake_case)] #[derive(Clone, Debug, Default, PartialEq)] #[repr(C)] pub struct CC_MD5_CTX { A: c_uint, B: c_uint, C: c_uint, D: c_uint, Nl: c_uint, Nh: c_uint, data: [c_uint; MD5_LBLOCK], num: c_uint, } /// Struct used to generate SHA1 hashes. #[allow(non_camel_case_types, non_snake_case)] #[derive(Clone, Debug, Default, PartialEq)] #[repr(C)] pub struct CC_SHA_CTX { h0: c_uint, h1: c_uint, h2: c_uint, h3: c_uint, h4: c_uint, Nl: c_uint, Nh: c_uint, data: [c_uint; SHA_LBLOCK], num: c_uint, } macro_rules! cc_sha2_struct { ($ctx_name: ident, $ty: ty) => { /// Struct used to generate SHA2 hashes with the given bits. #[allow(non_camel_case_types, non_snake_case)] #[derive(Clone, Debug, Default, PartialEq)] #[repr(C)] pub struct $ctx_name { count: [$ty; 2], hash: [$ty; 8], wbuf: [$ty; 16], } } } cc_sha2_struct!(CC_SHA256_CTX, u32); cc_sha2_struct!(CC_SHA512_CTX, u64); /// Digest algorithm used in `CCDigest*()` functions. #[repr(C)] pub enum CCDigestAlgorithm { /// No digest algorithm kCCDigestNone = 0, /// MD2 kCCDigestMD2 = 1, /// MD4 kCCDigestMD4 = 2, /// MD5 kCCDigestMD5 = 3, /// RIPEMD-128 kCCDigestRMD128 = 4, /// RIPEMD-160 kCCDigestRMD160 = 5, /// RIPEMD-256 kCCDigestRMD256 = 6, /// RIPEMD-320 kCCDigestRMD320 = 7, /// SHA1 kCCDigestSHA1 = 8, /// SHA224 kCCDigestSHA224 = 9, /// SHA256 kCCDigestSHA256 = 10, /// SHA384 kCCDigestSHA384 = 11, /// SHA512 kCCDigestSHA512 = 12, /// Skein, 128 bit (Deprecated in iPhoneOS 6.0 and MacOSX10.9) kCCDigestSkein128 = 13, /// Skein, 160 bit (Deprecated in iPhoneOS 6.0 and MacOSX10.9) kCCDigestSkein160 = 14, /// Skein, 224 bit (Deprecated in iPhoneOS 6.0 and MacOSX10.9) kCCDigestSkein224 = 16, /// Skein, 256 bit (Deprecated in iPhoneOS 6.0 and MacOSX10.9) kCCDigestSkein256 = 17, /// Skein, 384 bit (Deprecated in iPhoneOS 6.0 and MacOSX10.9) kCCDigestSkein384 = 18, /// Skein, 512 bit (Deprecated in iPhoneOS 6.0 and MacOSX10.9) kCCDigestSkein512 = 19, } const CC_DIGEST_SIZE: usize = 1032; /// Context used in `CCDigest*()` functions. #[allow(non_camel_case_types, non_snake_case)] #[repr(C)] pub struct CCDigestCtx { context: [u8; CC_DIGEST_SIZE], } /// Algorithm for use with `CCKeyDerivationPBKDF()`. #[repr(C)] pub enum CCPBKDFAlgorithm { /// PBKDF2 kCCPBKDF2 = 2, } /// Pseudo-random algorithm to use with `CCKeyDerivationPBKDF()`. #[repr(C)] pub enum CCPseudoRandomAlgorithm { /// SHA-1 kCCPRFHmacAlgSHA1 = 1, /// SHA-224 kCCPRFHmacAlgSHA224 = 2, /// SHA-256 kCCPRFHmacAlgSHA256 = 3, /// SHA-384 kCCPRFHmacAlgSHA384 = 4, /// SHA-512 kCCPRFHmacAlgSHA512 = 5, } extern "C" { /// Initializes MD5 hasher. See `man 3cc CC_MD5` for details. pub fn CC_MD5_Init(ctx: *mut CC_MD5_CTX) -> c_int; /// Appends data to be hashed. See `man 3cc CC_MD5` for details. pub fn CC_MD5_Update(ctx: *mut CC_MD5_CTX, data: *const u8, n: usize) -> c_int; /// Generates MD5 hash. See `man 3cc CC_MD5` for details. pub fn CC_MD5_Final(md: *mut u8, ctx: *mut CC_MD5_CTX) -> c_int; /// Initializes SHA1 hasher. See `man 3cc CC_SHA` for details. pub fn CC_SHA1_Init(ctx: *mut CC_SHA_CTX) -> c_int; /// Appends data to be hashed. See `man 3cc CC_SHA` for details. pub fn CC_SHA1_Update(ctx: *mut CC_SHA_CTX, data: *const u8, n: usize) -> c_int; /// Generates SHA1 hash. See `man 3cc CC_SHA` for details. pub fn CC_SHA1_Final(md: *mut u8, ctx: *mut CC_SHA_CTX) -> c_int; /// Initializes SHA256 hasher. See `man 3cc CC_SHA` for details. pub fn CC_SHA256_Init(ctx: *mut CC_SHA256_CTX) -> c_int; /// Appends data to be hashed. See `man 3cc CC_SHA` for details. pub fn CC_SHA256_Update(ctx: *mut CC_SHA256_CTX, data: *const u8, n: usize) -> c_int; /// Generates SHA256 hash. See `man 3cc CC_SHA` for details. pub fn CC_SHA256_Final(md: *mut u8, ctx: *mut CC_SHA256_CTX) -> c_int; /// Initializes SHA384 hasher. See `man 3cc CC_SHA` for details. pub fn CC_SHA384_Init(ctx: *mut CC_SHA512_CTX) -> c_int; /// Appends data to be hashed. See `man 3cc CC_SHA` for details. pub fn CC_SHA384_Update(ctx: *mut CC_SHA512_CTX, data: *const u8, n: usize) -> c_int; /// Generates SHA384 hash. See `man 3cc CC_SHA` for details. pub fn CC_SHA384_Final(md: *mut u8, ctx: *mut CC_SHA512_CTX) -> c_int; /// Initializes SHA512 hasher. See `man 3cc CC_SHA` for details. pub fn CC_SHA512_Init(ctx: *mut CC_SHA512_CTX) -> c_int; /// Appends data to be hashed. See `man 3cc CC_SHA` for details. pub fn CC_SHA512_Update(ctx: *mut CC_SHA512_CTX, data: *const u8, n: usize) -> c_int; /// Generates SHA512 hash. See `man 3cc CC_SHA` for details. pub fn CC_SHA512_Final(md: *mut u8, ctx: *mut CC_SHA512_CTX) -> c_int; /// Generic digest hasher. pub fn CCDigest(algorithm: CCDigestAlgorithm, data: *const u8, length: usize, output: *mut u8) -> c_int; /// Allocate and initialize a `CCDigestCtx` for a digest. pub fn CCDigestCreate(algorithm: CCDigestAlgorithm) -> *mut CCDigestCtx; /// Continue to digest data. Returns `0` on success. pub fn CCDigestUpdate(ctx: *mut CCDigestCtx, data: *const u8, length: usize) -> c_int; /// Conclude digest operations and produce the digest output. Returns `0` on success. pub fn CCDigestFinal(ctx: *mut CCDigestCtx, output: *mut u8) -> c_int; /// Clear and free a `CCDigestCtx`. pub fn CCDigestDestroy(ctx: *mut CCDigestCtx); /// Clear and re-initialize a `CCDigestCtx` for the same algorithm. pub fn CCDigestReset(ctx: *mut CCDigestCtx); /// Produce the digest output result for the bytes currently processed. Returns `0` on success. pub fn CCDigestGetDigest(ctx: *mut CCDigestCtx, output: *mut u8) -> c_int; /// Provides the block size of the digest algorithm. Returns `0` on failure. pub fn CCDigestGetBlockSize(algorithm: CCDigestAlgorithm) -> usize; /// Provides the digest output size of the digest algorithm. Returns `0` on failure. pub fn CCDigestGetOutputSize(algorithm: CCDigestAlgorithm) -> usize; /// Provides the block size of the digest algorithm. Returns `0` on failure. pub fn CCDigestGetBlockSizeFromRef(ctx: *mut CCDigestCtx) -> usize; /// Provides the digest output size of the digest algorithm. Returns `0` on failure. pub fn CCDigestGetOutputSizeFromRef(ctx: *mut CCDigestCtx) -> usize; /// Derive a key from a user-supplied password via PBKDF2. pub fn CCKeyDerivationPBKDF(algorithm: CCPBKDFAlgorithm, password: *const u8, passwordLen: usize, salt: *const u8, saltLen: usize, prf: CCPseudoRandomAlgorithm, rounds: u32, derivedKey: *mut u8, derivedKeyLen: usize) -> c_int; } vendor/commoncrypto-sys-0.2.0/tests/0000755000000000000000000000000013264166600016217 5ustar rootrootvendor/commoncrypto-sys-0.2.0/tests/hash.rs0000644000000000000000000001137713264166600017521 0ustar rootrootextern crate commoncrypto_sys; extern crate hex; use hex::ToHex; const TO_HASH: &'static str = "The quick brown fox jumps over the lazy dog"; const TO_HASH_MD5: &'static str = "9e107d9d372bb6826bd81d3542a419d6"; const TO_HASH_SHA1: &'static str = "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12"; const TO_HASH_SHA256: &'static str = "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592"; const TO_HASH_SHA384: &'static str = "ca737f1014a48f4c0b6dd43cb177b0afd9e5169367544c494011e3317dbf9a509cb1e5dc1e85a941bbee3d7f2afbc9b1"; const TO_HASH_SHA512: &'static str = "07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6"; macro_rules! test_cc_hash { ( $test_name: ident, $ctx_ty: ident, $digest_len: ident, $init_func: ident, $update_func: ident, $final_func: ident, $expected_hash: ident ) => { #[test] fn $test_name() { let mut ctx = commoncrypto_sys::$ctx_ty::default(); let mut md = [0u8; commoncrypto_sys::$digest_len]; unsafe { assert_eq!(commoncrypto_sys::$init_func(&mut ctx), 1); assert_eq!(commoncrypto_sys::$update_func(&mut ctx, TO_HASH.as_ptr(), TO_HASH.len()), 1); assert_eq!(commoncrypto_sys::$final_func(md.as_mut_ptr(), &mut ctx), 1); } assert_eq!(md.to_vec().to_hex(), $expected_hash); } } } macro_rules! test_ccdigest { ( $test_name: ident, $algorithm: ident, $digest_len: ident, $expected_hash: ident ) => { #[test] fn $test_name() { let mut md = [0u8; commoncrypto_sys::$digest_len]; unsafe { assert_eq!(commoncrypto_sys::CCDigest(commoncrypto_sys::CCDigestAlgorithm::$algorithm, TO_HASH.as_ptr(), TO_HASH.len(), md.as_mut_ptr()), 0) } assert_eq!(md.to_vec().to_hex(), $expected_hash); } } } macro_rules! test_ccdigestgetoutputsize { ( $test_name: ident, $algorithm: ident, $expected_digest_len: ident ) => { #[test] fn $test_name() { unsafe { assert_eq!(commoncrypto_sys::CCDigestGetOutputSize(commoncrypto_sys::CCDigestAlgorithm::$algorithm), commoncrypto_sys::$expected_digest_len); } } } } test_cc_hash!(md5_hash, CC_MD5_CTX, MD5_DIGEST_LENGTH, CC_MD5_Init, CC_MD5_Update, CC_MD5_Final, TO_HASH_MD5); test_cc_hash!(sha1_hash, CC_SHA_CTX, SHA1_DIGEST_LENGTH, CC_SHA1_Init, CC_SHA1_Update, CC_SHA1_Final, TO_HASH_SHA1); test_cc_hash!(sha256_hash, CC_SHA256_CTX, SHA256_DIGEST_LENGTH, CC_SHA256_Init, CC_SHA256_Update, CC_SHA256_Final, TO_HASH_SHA256); test_cc_hash!(sha384_hash, CC_SHA512_CTX, SHA384_DIGEST_LENGTH, CC_SHA384_Init, CC_SHA384_Update, CC_SHA384_Final, TO_HASH_SHA384); test_cc_hash!(sha512_hash, CC_SHA512_CTX, SHA512_DIGEST_LENGTH, CC_SHA512_Init, CC_SHA512_Update, CC_SHA512_Final, TO_HASH_SHA512); test_ccdigest!(md5_ccdigest, kCCDigestMD5, MD5_DIGEST_LENGTH, TO_HASH_MD5); test_ccdigest!(sha1_ccdigest, kCCDigestSHA1, SHA1_DIGEST_LENGTH, TO_HASH_SHA1); test_ccdigest!(sha256_ccdigest, kCCDigestSHA256, SHA256_DIGEST_LENGTH, TO_HASH_SHA256); test_ccdigest!(sha384_ccdigest, kCCDigestSHA384, SHA384_DIGEST_LENGTH, TO_HASH_SHA384); test_ccdigest!(sha512_ccdigest, kCCDigestSHA512, SHA512_DIGEST_LENGTH, TO_HASH_SHA512); test_ccdigestgetoutputsize!(md5_ccdigestoutputsize, kCCDigestMD5, MD5_DIGEST_LENGTH); test_ccdigestgetoutputsize!(sha1_ccdigestoutputsize, kCCDigestSHA1, SHA1_DIGEST_LENGTH); test_ccdigestgetoutputsize!(sha256_ccdigestoutputsize, kCCDigestSHA256, SHA256_DIGEST_LENGTH); test_ccdigestgetoutputsize!(sha384_ccdigestoutputsize, kCCDigestSHA384, SHA384_DIGEST_LENGTH); test_ccdigestgetoutputsize!(sha512_ccdigestoutputsize, kCCDigestSHA512, SHA512_DIGEST_LENGTH); vendor/commoncrypto-sys-0.2.0/tests/pbkdf2.rs0000644000000000000000000000303313264166600017734 0ustar rootrootextern crate commoncrypto_sys; extern crate hex; use hex::{ToHex, FromHex}; // These password, salts, rounds and derived key values come from the test // vectors stated in RFC 6070 const PASSWORD: &'static str = "password"; const SALT: &'static str = "salt"; const DERIVED1: &'static str = "0c60c80f961f0e71f3a9b524af6012062fe037a6"; const DERIVED4096: &'static str = "4b007901b765489abead49d926f721d065a429c1"; macro_rules! test_pbkdf2 { ( $test_name: ident, $prf_algorithm: ident, $pw: ident, $salt: ident, $rounds: expr, $expected_dkey: ident ) => { #[test] fn $test_name() { let derived_len = Vec::::from_hex($expected_dkey).expect("dkey from hex").len(); let mut pw_derived = vec![0u8; derived_len]; unsafe { assert_eq!(0, commoncrypto_sys::CCKeyDerivationPBKDF( commoncrypto_sys::CCPBKDFAlgorithm::kCCPBKDF2, $pw.as_ptr(), $pw.len(), $salt.as_ptr(), $salt.len(), commoncrypto_sys::CCPseudoRandomAlgorithm::$prf_algorithm, $rounds, pw_derived.as_mut_ptr(), pw_derived.len() )); } assert_eq!($expected_dkey, pw_derived.to_hex()); } } } test_pbkdf2!(pbkdf2_1, kCCPRFHmacAlgSHA1, PASSWORD, SALT, 1, DERIVED1); test_pbkdf2!(pbkdf2_4096, kCCPRFHmacAlgSHA1, PASSWORD, SALT, 4096, DERIVED4096); vendor/core-foundation-0.5.1/0000755000000000000000000000000013264166600014610 5ustar rootrootvendor/core-foundation-0.5.1/.cargo-checksum.json0000644000000000000000000000013113264166600020447 0ustar rootroot{"files":{},"package":"286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980"}vendor/core-foundation-0.5.1/Cargo.toml0000644000000000000000000000227013264166600016541 0ustar rootroot# 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 = "core-foundation" version = "0.5.1" authors = ["The Servo Project Developers"] description = "Bindings to Core Foundation for OS X" homepage = "https://github.com/servo/core-foundation-rs" license = "MIT / Apache-2.0" repository = "https://github.com/servo/core-foundation-rs" [dependencies.chrono] version = "0.4" optional = true [dependencies.core-foundation-sys] version = "0.5.1" [dependencies.libc] version = "0.2" [dependencies.uuid] version = "0.5" optional = true [features] mac_os_10_7_support = ["core-foundation-sys/mac_os_10_7_support"] mac_os_10_8_features = ["core-foundation-sys/mac_os_10_8_features"] with-chrono = ["chrono"] with-uuid = ["uuid"] vendor/core-foundation-0.5.1/LICENSE-APACHE0000644000000000000000000002513713264166600016544 0ustar rootroot 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. vendor/core-foundation-0.5.1/LICENSE-MIT0000644000000000000000000000205313264166600016244 0ustar rootrootCopyright (c) 2012-2013 Mozilla Foundation 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. vendor/core-foundation-0.5.1/src/0000755000000000000000000000000013264166600015377 5ustar rootrootvendor/core-foundation-0.5.1/src/array.rs0000644000000000000000000002064413264166600017071 0ustar rootroot// Copyright 2013 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Heterogeneous immutable arrays. pub use core_foundation_sys::array::*; pub use core_foundation_sys::base::CFIndex; use core_foundation_sys::base::{CFTypeRef, CFRelease, kCFAllocatorDefault}; use libc::c_void; use std::mem; use std::mem::ManuallyDrop; use std::marker::PhantomData; use std; use std::ops::Deref; use std::fmt::{Debug, Formatter}; use base::{CFIndexConvertible, TCFType, TCFTypeRef, CFRange}; /// A heterogeneous immutable array. pub struct CFArray(CFArrayRef, PhantomData); /// A reference to an element inside the array pub struct ItemRef<'a, T: 'a>(ManuallyDrop, PhantomData<&'a T>); impl<'a, T> Deref for ItemRef<'a, T> { type Target = T; fn deref(&self) -> &T { &self.0 } } impl<'a, T: Debug> Debug for ItemRef<'a, T> { fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> { self.0.fmt(f) } } /// A trait describing how to convert from the stored *const c_void to the desired T pub unsafe trait FromVoid { unsafe fn from_void<'a>(x: *const c_void) -> ItemRef<'a, Self> where Self: std::marker::Sized; } unsafe impl FromVoid for u32 { unsafe fn from_void<'a>(x: *const c_void) -> ItemRef<'a, Self> { // Functions like CGFontCopyTableTags treat the void*'s as u32's // so we convert by casting directly ItemRef(ManuallyDrop::new(x as u32), PhantomData) } } unsafe impl FromVoid for T { unsafe fn from_void<'a>(x: *const c_void) -> ItemRef<'a, Self> { ItemRef(ManuallyDrop::new(TCFType::wrap_under_create_rule(T::Ref::from_void_ptr(x))), PhantomData) } } impl Drop for CFArray { fn drop(&mut self) { unsafe { CFRelease(self.as_CFTypeRef()) } } } pub struct CFArrayIterator<'a, T: 'a> { array: &'a CFArray, index: CFIndex, len: CFIndex, } impl<'a, T: FromVoid> Iterator for CFArrayIterator<'a, T> { type Item = ItemRef<'a, T>; fn next(&mut self) -> Option> { if self.index >= self.len { None } else { let value = unsafe { self.array.get_unchecked(self.index) }; self.index += 1; Some(value) } } } impl<'a, T: FromVoid> ExactSizeIterator for CFArrayIterator<'a, T> { fn len(&self) -> usize { (self.array.len() - self.index) as usize } } impl_TCFTypeGeneric!(CFArray, CFArrayRef, CFArrayGetTypeID); impl_CFTypeDescriptionGeneric!(CFArray); impl CFArray { /// Creates a new `CFArray` with the given elements, which must be `CFType` objects. pub fn from_CFTypes(elems: &[T]) -> CFArray where T: TCFType { unsafe { let elems: Vec = elems.iter().map(|elem| elem.as_CFTypeRef()).collect(); let array_ref = CFArrayCreate(kCFAllocatorDefault, mem::transmute(elems.as_ptr()), elems.len().to_CFIndex(), &kCFTypeArrayCallBacks); TCFType::wrap_under_create_rule(array_ref) } } #[inline] pub fn to_untyped(&self) -> CFArray { unsafe { CFArray::wrap_under_get_rule(self.0) } } /// Returns the same array, but with the type reset to void pointers. /// Equal to `to_untyped`, but is faster since it does not increment the retain count. #[inline] pub fn into_untyped(self) -> CFArray { let reference = self.0; mem::forget(self); unsafe { CFArray::wrap_under_create_rule(reference) } } /// Iterates over the elements of this `CFArray`. /// /// Careful; the loop body must wrap the reference properly. Generally, when array elements are /// Core Foundation objects (not always true), they need to be wrapped with /// `TCFType::wrap_under_get_rule()`. #[inline] pub fn iter<'a>(&'a self) -> CFArrayIterator<'a, T> { CFArrayIterator { array: self, index: 0, len: self.len(), } } #[inline] pub fn len(&self) -> CFIndex { unsafe { CFArrayGetCount(self.0) } } #[inline] pub unsafe fn get_unchecked<'a>(&'a self, index: CFIndex) -> ItemRef<'a, T> where T: FromVoid { T::from_void(CFArrayGetValueAtIndex(self.0, index)) } #[inline] pub fn get<'a>(&'a self, index: CFIndex) -> Option> where T: FromVoid { if index < self.len() { Some(unsafe { T::from_void(CFArrayGetValueAtIndex(self.0, index)) } ) } else { None } } pub fn get_values(&self, range: CFRange) -> Vec<*const c_void> { let mut vec = Vec::with_capacity(range.length as usize); unsafe { CFArrayGetValues(self.0, range, vec.as_mut_ptr()); vec.set_len(range.length as usize); vec } } pub fn get_all_values(&self) -> Vec<*const c_void> { self.get_values(CFRange { location: 0, length: self.len() }) } } impl<'a, T: FromVoid> IntoIterator for &'a CFArray { type Item = ItemRef<'a, T>; type IntoIter = CFArrayIterator<'a, T>; fn into_iter(self) -> CFArrayIterator<'a, T> { self.iter() } } #[cfg(test)] mod tests { use super::*; use std::mem; use base::CFType; #[test] fn to_untyped_correct_retain_count() { let array = CFArray::::from_CFTypes(&[]); assert_eq!(array.retain_count(), 1); let untyped_array = array.to_untyped(); assert_eq!(array.retain_count(), 2); assert_eq!(untyped_array.retain_count(), 2); mem::drop(array); assert_eq!(untyped_array.retain_count(), 1); } #[test] fn into_untyped() { let array = CFArray::::from_CFTypes(&[]); let array2 = array.to_untyped(); assert_eq!(array.retain_count(), 2); let untyped_array = array.into_untyped(); assert_eq!(untyped_array.retain_count(), 2); mem::drop(array2); assert_eq!(untyped_array.retain_count(), 1); } #[test] fn borrow() { use string::CFString; let string = CFString::from_static_string("bar"); assert_eq!(string.retain_count(), 1); let x; { let arr: CFArray = CFArray::from_CFTypes(&[string]); { let p = arr.get(0).unwrap(); assert_eq!(p.retain_count(), 1); } { x = arr.get(0).unwrap().clone(); assert_eq!(x.retain_count(), 2); assert_eq!(x.to_string(), "bar"); } } assert_eq!(x.retain_count(), 1); } #[test] fn should_box_and_unbox() { use number::CFNumber; let n0 = CFNumber::from(0); let n1 = CFNumber::from(1); let n2 = CFNumber::from(2); let n3 = CFNumber::from(3); let n4 = CFNumber::from(4); let n5 = CFNumber::from(5); let arr = CFArray::from_CFTypes(&[ n0.as_CFType(), n1.as_CFType(), n2.as_CFType(), n3.as_CFType(), n4.as_CFType(), n5.as_CFType(), ]); assert!(arr.get_all_values() == &[n0.as_CFTypeRef(), n1.as_CFTypeRef(), n2.as_CFTypeRef(), n3.as_CFTypeRef(), n4.as_CFTypeRef(), n5.as_CFTypeRef()]); let mut sum = 0; let mut iter = arr.iter(); assert_eq!(iter.len(), 6); assert!(iter.next().is_some()); assert_eq!(iter.len(), 5); for elem in iter { let number: CFNumber = elem.downcast::().unwrap(); sum += number.to_i64().unwrap() } assert!(sum == 15); for elem in arr.iter() { let number: CFNumber = elem.downcast::().unwrap(); sum += number.to_i64().unwrap() } assert!(sum == 30); } } vendor/core-foundation-0.5.1/src/base.rs0000644000000000000000000002111013264166600016652 0ustar rootroot// Copyright 2013 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use std::fmt; use std::mem; pub use core_foundation_sys::base::*; use string::CFString; pub trait CFIndexConvertible { /// Always use this method to construct a `CFIndex` value. It performs bounds checking to /// ensure the value is in range. fn to_CFIndex(self) -> CFIndex; } impl CFIndexConvertible for usize { #[inline] fn to_CFIndex(self) -> CFIndex { let max_CFIndex = CFIndex::max_value(); if self > (max_CFIndex as usize) { panic!("value out of range") } self as CFIndex } } declare_TCFType!{ /// Superclass of all Core Foundation objects. CFType, CFTypeRef } impl CFType { /// Try to downcast the `CFType` to a subclass. Checking if the instance is the /// correct subclass happens at runtime and `None` is returned if it is not the correct type. /// Works similar to [`Box::downcast`] and [`CFPropertyList::downcast`]. /// /// # Examples /// /// ``` /// # use core_foundation::string::CFString; /// # use core_foundation::boolean::CFBoolean; /// # use core_foundation::base::{CFType, TCFType}; /// # /// // Create a string. /// let string: CFString = CFString::from_static_string("FooBar"); /// // Cast it up to a CFType. /// let cf_type: CFType = string.as_CFType(); /// // Cast it down again. /// assert!(cf_type.downcast::().unwrap().to_string() == "FooBar"); /// // Casting it to some other type will yield `None` /// assert!(cf_type.downcast::().is_none()); /// ``` /// /// [`Box::downcast`]: https://doc.rust-lang.org/std/boxed/struct.Box.html#method.downcast /// [`CFPropertyList::downcast`]: ../propertylist/struct.CFPropertyList.html#method.downcast #[inline] pub fn downcast(&self) -> Option { if self.instance_of::() { unsafe { let reference = T::Ref::from_void_ptr(self.0); Some(T::wrap_under_get_rule(reference)) } } else { None } } /// Similar to [`downcast`], but consumes self and can thus avoid touching the retain count. /// /// [`downcast`]: #method.downcast #[inline] pub fn downcast_into(self) -> Option { if self.instance_of::() { unsafe { let reference = T::Ref::from_void_ptr(self.0); mem::forget(self); Some(T::wrap_under_create_rule(reference)) } } else { None } } } impl fmt::Debug for CFType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let desc = unsafe { CFString::wrap_under_create_rule(CFCopyDescription(self.0)) }; desc.fmt(f) } } impl Clone for CFType { #[inline] fn clone(&self) -> CFType { unsafe { TCFType::wrap_under_get_rule(self.0) } } } impl PartialEq for CFType { #[inline] fn eq(&self, other: &CFType) -> bool { unsafe { CFEqual(self.as_CFTypeRef(), other.as_CFTypeRef()) != 0 } } } declare_TCFType!(CFAllocator, CFAllocatorRef); impl_TCFType!(CFAllocator, CFAllocatorRef, CFAllocatorGetTypeID); impl CFAllocator { #[inline] pub fn new(mut context: CFAllocatorContext) -> CFAllocator { unsafe { let allocator_ref = CFAllocatorCreate(kCFAllocatorDefault, &mut context); TCFType::wrap_under_create_rule(allocator_ref) } } } /// All Core Foundation types implement this trait. The associated type `Ref` specifies the /// associated Core Foundation type: e.g. for `CFType` this is `CFTypeRef`; for `CFArray` this is /// `CFArrayRef`. pub trait TCFType { /// The reference type wrapped inside this type. type Ref: TCFTypeRef; /// Returns the object as its concrete TypeRef. fn as_concrete_TypeRef(&self) -> Self::Ref; /// Returns an instance of the object, wrapping the underlying `CFTypeRef` subclass. Use this /// when following Core Foundation's "Create Rule". The reference count is *not* bumped. unsafe fn wrap_under_create_rule(obj: Self::Ref) -> Self; /// Returns the type ID for this class. fn type_id() -> CFTypeID; /// Returns the object as a wrapped `CFType`. The reference count is incremented by one. #[inline] fn as_CFType(&self) -> CFType { unsafe { TCFType::wrap_under_get_rule(self.as_CFTypeRef()) } } /// Returns the object as a wrapped `CFType`. Consumes self and avoids changing the reference /// count. #[inline] fn into_CFType(self) -> CFType where Self: Sized, { let reference = self.as_CFTypeRef(); mem::forget(self); unsafe { TCFType::wrap_under_create_rule(reference) } } /// Returns the object as a raw `CFTypeRef`. The reference count is not adjusted. fn as_CFTypeRef(&self) -> CFTypeRef; /// Returns an instance of the object, wrapping the underlying `CFTypeRef` subclass. Use this /// when following Core Foundation's "Get Rule". The reference count *is* bumped. unsafe fn wrap_under_get_rule(reference: Self::Ref) -> Self; /// Returns the reference count of the object. It is unwise to do anything other than test /// whether the return value of this method is greater than zero. #[inline] fn retain_count(&self) -> CFIndex { unsafe { CFGetRetainCount(self.as_CFTypeRef()) } } /// Returns the type ID of this object. #[inline] fn type_of(&self) -> CFTypeID { unsafe { CFGetTypeID(self.as_CFTypeRef()) } } /// Writes a debugging version of this object on standard error. fn show(&self) { unsafe { CFShow(self.as_CFTypeRef()) } } /// Returns true if this value is an instance of another type. #[inline] fn instance_of(&self) -> bool { self.type_of() == OtherCFType::type_id() } } impl TCFType for CFType { type Ref = CFTypeRef; #[inline] fn as_concrete_TypeRef(&self) -> CFTypeRef { self.0 } #[inline] unsafe fn wrap_under_get_rule(reference: CFTypeRef) -> CFType { let reference: CFTypeRef = CFRetain(reference); TCFType::wrap_under_create_rule(reference) } #[inline] fn as_CFTypeRef(&self) -> CFTypeRef { self.as_concrete_TypeRef() } #[inline] unsafe fn wrap_under_create_rule(obj: CFTypeRef) -> CFType { CFType(obj) } #[inline] fn type_id() -> CFTypeID { // FIXME(pcwalton): Is this right? 0 } } #[cfg(test)] mod tests { use super::*; use std::mem; use boolean::CFBoolean; #[test] fn cftype_instance_of() { let string = CFString::from_static_string("foo"); let cftype = string.as_CFType(); assert!(cftype.instance_of::()); assert!(!cftype.instance_of::()); } #[test] fn as_cftype_retain_count() { let string = CFString::from_static_string("bar"); assert_eq!(string.retain_count(), 1); let cftype = string.as_CFType(); assert_eq!(cftype.retain_count(), 2); mem::drop(string); assert_eq!(cftype.retain_count(), 1); } #[test] fn into_cftype_retain_count() { let string = CFString::from_static_string("bar"); assert_eq!(string.retain_count(), 1); let cftype = string.into_CFType(); assert_eq!(cftype.retain_count(), 1); } #[test] fn as_cftype_and_downcast() { let string = CFString::from_static_string("bar"); let cftype = string.as_CFType(); let string2 = cftype.downcast::().unwrap(); assert_eq!(string2.to_string(), "bar"); assert_eq!(string.retain_count(), 3); assert_eq!(cftype.retain_count(), 3); assert_eq!(string2.retain_count(), 3); } #[test] fn into_cftype_and_downcast_into() { let string = CFString::from_static_string("bar"); let cftype = string.into_CFType(); let string2 = cftype.downcast_into::().unwrap(); assert_eq!(string2.to_string(), "bar"); assert_eq!(string2.retain_count(), 1); } } vendor/core-foundation-0.5.1/src/boolean.rs0000644000000000000000000000350313264166600017365 0ustar rootroot// Copyright 2013 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! A Boolean type. pub use core_foundation_sys::number::{CFBooleanRef, CFBooleanGetTypeID, kCFBooleanTrue, kCFBooleanFalse}; use base::TCFType; declare_TCFType!{ /// A Boolean type. /// /// FIXME(pcwalton): Should be a newtype struct, but that fails due to a Rust compiler bug. CFBoolean, CFBooleanRef } impl_TCFType!(CFBoolean, CFBooleanRef, CFBooleanGetTypeID); impl_CFTypeDescription!(CFBoolean); impl CFBoolean { pub fn true_value() -> CFBoolean { unsafe { TCFType::wrap_under_get_rule(kCFBooleanTrue) } } pub fn false_value() -> CFBoolean { unsafe { TCFType::wrap_under_get_rule(kCFBooleanFalse) } } } impl From for CFBoolean { fn from(value: bool) -> CFBoolean { if value { CFBoolean::true_value() } else { CFBoolean::false_value() } } } impl From for bool { fn from(value: CFBoolean) -> bool { value.0 == unsafe { kCFBooleanTrue } } } #[cfg(test)] mod tests { use super::*; #[test] fn to_and_from_bool() { let b_false = CFBoolean::from(false); let b_true = CFBoolean::from(true); assert_ne!(b_false, b_true); assert_eq!(b_false, CFBoolean::false_value()); assert_eq!(b_true, CFBoolean::true_value()); assert!(!bool::from(b_false)); assert!(bool::from(b_true)); } } vendor/core-foundation-0.5.1/src/bundle.rs0000644000000000000000000000740113264166600017220 0ustar rootroot// Copyright 2013 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Core Foundation Bundle Type pub use core_foundation_sys::bundle::*; use core_foundation_sys::base::kCFAllocatorDefault; use base::TCFType; use url::CFURL; use dictionary::CFDictionary; declare_TCFType!{ /// A Bundle type. CFBundle, CFBundleRef } impl_TCFType!(CFBundle, CFBundleRef, CFBundleGetTypeID); impl CFBundle { pub fn new(bundleURL: CFURL) -> Option { unsafe { let bundle_ref = CFBundleCreate(kCFAllocatorDefault, bundleURL.as_concrete_TypeRef()); if bundle_ref.is_null() { None } else { Some(TCFType::wrap_under_create_rule(bundle_ref)) } } } pub fn main_bundle() -> CFBundle { unsafe { let bundle_ref = CFBundleGetMainBundle(); TCFType::wrap_under_get_rule(bundle_ref) } } pub fn info_dictionary(&self) -> CFDictionary { unsafe { let info_dictionary = CFBundleGetInfoDictionary(self.0); TCFType::wrap_under_get_rule(info_dictionary) } } pub fn executable_url(&self) -> Option { unsafe { let exe_url = CFBundleCopyExecutableURL(self.0); if exe_url.is_null() { None } else { Some(TCFType::wrap_under_create_rule(exe_url)) } } } pub fn private_frameworks_url(&self) -> Option { unsafe { let fw_url = CFBundleCopyPrivateFrameworksURL(self.0); if fw_url.is_null() { None } else { Some(TCFType::wrap_under_create_rule(fw_url)) } } } } #[test] fn safari_executable_url() { use string::CFString; use url::{CFURL, kCFURLPOSIXPathStyle}; let cfstr_path = CFString::from_static_string("/Applications/Safari.app"); let cfurl_path = CFURL::from_file_system_path(cfstr_path, kCFURLPOSIXPathStyle, true); let cfurl_executable = CFBundle::new(cfurl_path) .expect("Safari not present") .executable_url(); assert!(cfurl_executable.is_some()); assert_eq!(cfurl_executable .unwrap() .absolute() .get_file_system_path(kCFURLPOSIXPathStyle) .to_string(), "/Applications/Safari.app/Contents/MacOS/Safari"); } #[test] fn safari_private_frameworks_url() { use string::CFString; use url::{CFURL, kCFURLPOSIXPathStyle}; let cfstr_path = CFString::from_static_string("/Applications/Safari.app"); let cfurl_path = CFURL::from_file_system_path(cfstr_path, kCFURLPOSIXPathStyle, true); let cfurl_executable = CFBundle::new(cfurl_path) .expect("Safari not present") .private_frameworks_url(); assert!(cfurl_executable.is_some()); assert_eq!(cfurl_executable .unwrap() .absolute() .get_file_system_path(kCFURLPOSIXPathStyle) .to_string(), "/Applications/Safari.app/Contents/Frameworks"); } #[test] fn non_existant_bundle() { use string::CFString; use url::{CFURL, kCFURLPOSIXPathStyle}; let cfstr_path = CFString::from_static_string("/usr/local/foo"); let cfurl_path = CFURL::from_file_system_path(cfstr_path, kCFURLPOSIXPathStyle, true); assert!(CFBundle::new(cfurl_path).is_none()); } vendor/core-foundation-0.5.1/src/data.rs0000644000000000000000000000331613264166600016661 0ustar rootroot// Copyright 2013 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Core Foundation byte buffers. pub use core_foundation_sys::data::*; use core_foundation_sys::base::CFIndex; use core_foundation_sys::base::{kCFAllocatorDefault}; use std::ops::Deref; use std::slice; use base::{CFIndexConvertible, TCFType}; declare_TCFType!{ /// A byte buffer. CFData, CFDataRef } impl_TCFType!(CFData, CFDataRef, CFDataGetTypeID); impl_CFTypeDescription!(CFData); impl CFData { pub fn from_buffer(buffer: &[u8]) -> CFData { unsafe { let data_ref = CFDataCreate(kCFAllocatorDefault, buffer.as_ptr(), buffer.len().to_CFIndex()); TCFType::wrap_under_create_rule(data_ref) } } /// Returns a pointer to the underlying bytes in this data. Note that this byte buffer is /// read-only. #[inline] pub fn bytes<'a>(&'a self) -> &'a [u8] { unsafe { slice::from_raw_parts(CFDataGetBytePtr(self.0), self.len() as usize) } } /// Returns the length of this byte buffer. #[inline] pub fn len(&self) -> CFIndex { unsafe { CFDataGetLength(self.0) } } } impl Deref for CFData { type Target = [u8]; #[inline] fn deref(&self) -> &[u8] { self.bytes() } } vendor/core-foundation-0.5.1/src/date.rs0000644000000000000000000000733713264166600016674 0ustar rootroot// Copyright 2013 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Core Foundation date objects. pub use core_foundation_sys::date::*; use core_foundation_sys::base::kCFAllocatorDefault; use base::TCFType; #[cfg(feature = "with-chrono")] use chrono::NaiveDateTime; declare_TCFType!{ /// A date. CFDate, CFDateRef } impl_TCFType!(CFDate, CFDateRef, CFDateGetTypeID); impl_CFTypeDescription!(CFDate); impl_CFComparison!(CFDate, CFDateCompare); impl CFDate { #[inline] pub fn new(time: CFAbsoluteTime) -> CFDate { unsafe { let date_ref = CFDateCreate(kCFAllocatorDefault, time); TCFType::wrap_under_create_rule(date_ref) } } #[inline] pub fn now() -> CFDate { CFDate::new(unsafe { CFAbsoluteTimeGetCurrent() }) } #[inline] pub fn abs_time(&self) -> CFAbsoluteTime { unsafe { CFDateGetAbsoluteTime(self.0) } } #[cfg(feature = "with-chrono")] pub fn naive_utc(&self) -> NaiveDateTime { let ts = unsafe { self.abs_time() + kCFAbsoluteTimeIntervalSince1970 }; let (secs, nanos) = if ts.is_sign_positive() { (ts.trunc() as i64, ts.fract()) } else { // nanoseconds can't be negative in NaiveDateTime (ts.trunc() as i64 - 1, 1.0 - ts.fract().abs()) }; NaiveDateTime::from_timestamp(secs, (nanos * 1e9).floor() as u32) } #[cfg(feature = "with-chrono")] pub fn from_naive_utc(time: NaiveDateTime) -> CFDate { let secs = time.timestamp(); let nanos = time.timestamp_subsec_nanos(); let ts = unsafe { secs as f64 + (nanos as f64 / 1e9) - kCFAbsoluteTimeIntervalSince1970 }; CFDate::new(ts) } } #[cfg(test)] mod test { use super::CFDate; use std::cmp::Ordering; #[cfg(feature = "with-chrono")] use chrono::NaiveDateTime; #[cfg(feature = "with-chrono")] fn approx_eq(a: f64, b: f64) -> bool { use std::f64; let same_sign = a.is_sign_positive() == b.is_sign_positive(); let equal = ((a - b).abs() / f64::min(a.abs() + b.abs(), f64::MAX)) < f64::EPSILON; (same_sign && equal) } #[test] fn date_comparison() { let now = CFDate::now(); let past = CFDate::new(now.abs_time() - 1.0); assert_eq!(now.cmp(&past), Ordering::Greater); assert_eq!(now.cmp(&now), Ordering::Equal); assert_eq!(past.cmp(&now), Ordering::Less); } #[test] fn date_equality() { let now = CFDate::now(); let same_time = CFDate::new(now.abs_time()); assert_eq!(now, same_time); } #[test] #[cfg(feature = "with-chrono")] fn date_chrono_conversion_positive() { let date = CFDate::now(); let datetime = date.naive_utc(); let converted = CFDate::from_naive_utc(datetime); assert!(approx_eq(date.abs_time(), converted.abs_time())); } #[test] #[cfg(feature = "with-chrono")] fn date_chrono_conversion_negative() { use super::kCFAbsoluteTimeIntervalSince1970; let ts = unsafe { kCFAbsoluteTimeIntervalSince1970 - 420.0 }; let date = CFDate::new(ts); let datetime: NaiveDateTime = date.naive_utc(); let converted = CFDate::from_naive_utc(datetime); assert!(approx_eq(date.abs_time(), converted.abs_time())); } } vendor/core-foundation-0.5.1/src/dictionary.rs0000644000000000000000000003133413264166600020116 0ustar rootroot// Copyright 2013 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Dictionaries of key-value pairs. pub use core_foundation_sys::dictionary::*; use core_foundation_sys::base::{CFTypeRef, kCFAllocatorDefault}; use libc::c_void; use std::mem; use std::ptr; use base::{CFType, CFIndexConvertible, TCFType, TCFTypeRef}; declare_TCFType!{ /// An immutable dictionary of key-value pairs. CFDictionary, CFDictionaryRef } impl_TCFType!(CFDictionary, CFDictionaryRef, CFDictionaryGetTypeID); impl_CFTypeDescription!(CFDictionary); impl CFDictionary { pub fn from_CFType_pairs(pairs: &[(K, V)]) -> CFDictionary { let (keys, values): (Vec, Vec) = pairs .iter() .map(|&(ref key, ref value)| (key.as_CFTypeRef(), value.as_CFTypeRef())) .unzip(); unsafe { let dictionary_ref = CFDictionaryCreate(kCFAllocatorDefault, mem::transmute(keys.as_ptr()), mem::transmute(values.as_ptr()), keys.len().to_CFIndex(), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); TCFType::wrap_under_create_rule(dictionary_ref) } } #[inline] pub fn len(&self) -> usize { unsafe { CFDictionaryGetCount(self.0) as usize } } #[inline] pub fn is_empty(&self) -> bool { self.len() == 0 } #[inline] pub fn contains_key(&self, key: *const c_void) -> bool { unsafe { CFDictionaryContainsKey(self.0, key) != 0 } } /// Similar to `contains_key` but acts on a higher level, automatically converting from any /// `TCFType` to the raw pointer of its concrete TypeRef. #[inline] pub fn contains_key2(&self, key: &K) -> bool { self.contains_key(key.as_concrete_TypeRef().as_void_ptr()) } #[inline] pub fn find(&self, key: *const c_void) -> Option<*const c_void> { unsafe { let mut value: *const c_void = ptr::null(); if CFDictionaryGetValueIfPresent(self.0, key, &mut value) != 0 { Some(value) } else { None } } } /// Similar to `find` but acts on a higher level, automatically converting from any `TCFType` /// to the raw pointer of its concrete TypeRef. #[inline] pub fn find2(&self, key: &K) -> Option<*const c_void> { self.find(key.as_concrete_TypeRef().as_void_ptr()) } /// # Panics /// /// Panics if the key is not present in the dictionary. Use `find` to get an `Option` instead /// of panicking. #[inline] pub fn get(&self, key: *const c_void) -> *const c_void { self.find(key).expect(&format!("No entry found for key {:p}", key)) } /// A convenience function to retrieve `CFType` instances. #[inline] pub unsafe fn get_CFType(&self, key: *const c_void) -> CFType { let value: CFTypeRef = mem::transmute(self.get(key)); TCFType::wrap_under_get_rule(value) } pub fn get_keys_and_values(&self) -> (Vec<*const c_void>, Vec<*const c_void>) { let length = self.len(); let mut keys = Vec::with_capacity(length); let mut values = Vec::with_capacity(length); unsafe { CFDictionaryGetKeysAndValues(self.0, keys.as_mut_ptr(), values.as_mut_ptr()); keys.set_len(length); values.set_len(length); } (keys, values) } } declare_TCFType!{ /// An mutable dictionary of key-value pairs. CFMutableDictionary, CFMutableDictionaryRef } impl_TCFType!(CFMutableDictionary, CFMutableDictionaryRef, CFDictionaryGetTypeID); impl_CFTypeDescription!(CFMutableDictionary); impl CFMutableDictionary { pub fn new() -> Self { Self::with_capacity(0) } pub fn with_capacity(capacity: isize) -> Self { unsafe { let dictionary_ref = CFDictionaryCreateMutable(kCFAllocatorDefault, capacity as _, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); TCFType::wrap_under_create_rule(dictionary_ref) } } pub fn copy_with_capacity(&self, capacity: isize) -> Self { unsafe { let dictionary_ref = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, capacity as _, self.0); TCFType::wrap_under_get_rule(dictionary_ref) } } pub fn from_CFType_pairs(pairs: &[(K, V)]) -> CFMutableDictionary { let result = Self::with_capacity(pairs.len() as _); unsafe { for &(ref key, ref value) in pairs { result.add(key.as_CFTypeRef(), value.as_CFTypeRef()); } } result } // Immutable interface #[inline] pub fn len(&self) -> usize { unsafe { CFDictionaryGetCount(self.0) as usize } } #[inline] pub fn is_empty(&self) -> bool { self.len() == 0 } #[inline] pub fn contains_key(&self, key: *const c_void) -> bool { unsafe { CFDictionaryContainsKey(self.0, key) != 0 } } /// Similar to `contains_key` but acts on a higher level, automatically converting from any /// `TCFType` to the raw pointer of its concrete TypeRef. #[inline] pub fn contains_key2(&self, key: &K) -> bool { self.contains_key(key.as_concrete_TypeRef().as_void_ptr()) } #[inline] pub fn find(&self, key: *const c_void) -> Option<*const c_void> { unsafe { let mut value: *const c_void = ptr::null(); if CFDictionaryGetValueIfPresent(self.0, key, &mut value) != 0 { Some(value) } else { None } } } /// Similar to `find` but acts on a higher level, automatically converting from any `TCFType` /// to the raw pointer of its concrete TypeRef. #[inline] pub fn find2(&self, key: &K) -> Option<*const c_void> { self.find(key.as_concrete_TypeRef().as_void_ptr()) } /// # Panics /// /// Panics if the key is not present in the dictionary. Use `find` to get an `Option` instead /// of panicking. #[inline] pub fn get(&self, key: *const c_void) -> *const c_void { self.find(key).expect(&format!("No entry found for key {:p}", key)) } /// A convenience function to retrieve `CFType` instances. #[inline] pub unsafe fn get_CFType(&self, key: *const c_void) -> CFType { let value: CFTypeRef = mem::transmute(self.get(key)); TCFType::wrap_under_get_rule(value) } pub fn get_keys_and_values(&self) -> (Vec<*const c_void>, Vec<*const c_void>) { let length = self.len(); let mut keys = Vec::with_capacity(length); let mut values = Vec::with_capacity(length); unsafe { CFDictionaryGetKeysAndValues(self.0, keys.as_mut_ptr(), values.as_mut_ptr()); keys.set_len(length); values.set_len(length); } (keys, values) } // Mutable interface /// Adds the key-value pair to the dictionary if no such key already exist. #[inline] pub unsafe fn add(&self, key: *const c_void, value: *const c_void) { CFDictionaryAddValue(self.0, key, value) } /// Similar to `add` but acts on a higher level, automatically converting from any `TCFType` /// to the raw pointer of its concrete TypeRef. #[inline] pub fn add2(&self, key: &K, value: &V) { unsafe { self.add( key.as_concrete_TypeRef().as_void_ptr(), value.as_concrete_TypeRef().as_void_ptr(), ) } } /// Sets the value of the key in the dictionary. #[inline] pub unsafe fn set(&self, key: *const c_void, value: *const c_void) { CFDictionarySetValue(self.0, key, value) } /// Similar to `set` but acts on a higher level, automatically converting from any `TCFType` /// to the raw pointer of its concrete TypeRef. #[inline] pub fn set2(&self, key: &K, value: &V) { unsafe { self.set( key.as_concrete_TypeRef().as_void_ptr(), value.as_concrete_TypeRef().as_void_ptr(), ) } } /// Replaces the value of the key in the dictionary. #[inline] pub unsafe fn replace(&self, key: *const c_void, value: *const c_void) { CFDictionaryReplaceValue(self.0, key, value) } /// Similar to `replace` but acts on a higher level, automatically converting from any `TCFType` /// to the raw pointer of its concrete TypeRef. #[inline] pub fn replace2(&self, key: &K, value: &V) { unsafe { self.replace( key.as_concrete_TypeRef().as_void_ptr(), value.as_concrete_TypeRef().as_void_ptr(), ) } } /// Removes the value of the key from the dictionary. #[inline] pub unsafe fn remove(&self, key: *const c_void) { CFDictionaryRemoveValue(self.0, key); } /// Similar to `remove` but acts on a higher level, automatically converting from any `TCFType` /// to the raw pointer of its concrete TypeRef. #[inline] pub fn remove2(&self, key: &K) { unsafe { self.remove(key.as_concrete_TypeRef().as_void_ptr()) } } #[inline] pub fn remove_all(&self) { unsafe { CFDictionaryRemoveAllValues(self.0) } } } #[cfg(test)] pub mod test { use super::*; use base::TCFType; use boolean::{CFBoolean, CFBooleanRef}; use number::CFNumber; use string::CFString; #[test] fn dictionary() { let bar = CFString::from_static_string("Bar"); let baz = CFString::from_static_string("Baz"); let boo = CFString::from_static_string("Boo"); let foo = CFString::from_static_string("Foo"); let tru = CFBoolean::true_value(); let n42 = CFNumber::from(42); let d = CFDictionary::from_CFType_pairs(&[ (bar.as_CFType(), boo.as_CFType()), (baz.as_CFType(), tru.as_CFType()), (foo.as_CFType(), n42.as_CFType()), ]); let (v1, v2) = d.get_keys_and_values(); assert!(v1 == &[bar.as_CFTypeRef(), baz.as_CFTypeRef(), foo.as_CFTypeRef()]); assert!(v2 == &[boo.as_CFTypeRef(), tru.as_CFTypeRef(), n42.as_CFTypeRef()]); } #[test] fn mutable_dictionary() { let bar = CFString::from_static_string("Bar"); let baz = CFString::from_static_string("Baz"); let boo = CFString::from_static_string("Boo"); let foo = CFString::from_static_string("Foo"); let tru = CFBoolean::true_value(); let n42 = CFNumber::from(42); let d = CFMutableDictionary::new(); d.add2(&bar, &boo); d.add2(&baz, &tru); d.add2(&foo, &n42); assert_eq!(d.len(), 3); let (v1, v2) = d.get_keys_and_values(); assert!(v1 == &[bar.as_CFTypeRef(), baz.as_CFTypeRef(), foo.as_CFTypeRef()]); assert!(v2 == &[boo.as_CFTypeRef(), tru.as_CFTypeRef(), n42.as_CFTypeRef()]); d.remove2(&baz); assert_eq!(d.len(), 2); let (v1, v2) = d.get_keys_and_values(); assert!(v1 == &[bar.as_CFTypeRef(), foo.as_CFTypeRef()]); assert!(v2 == &[boo.as_CFTypeRef(), n42.as_CFTypeRef()]); d.remove_all(); assert_eq!(d.len(), 0) } #[test] fn dict_find2_and_contains_key2() { let dict = CFDictionary::from_CFType_pairs(&[ ( CFString::from_static_string("hello"), CFBoolean::true_value(), ), ]); let key = CFString::from_static_string("hello"); let invalid_key = CFString::from_static_string("foobar"); assert!(dict.contains_key2(&key)); assert!(!dict.contains_key2(&invalid_key)); let value = unsafe { CFBoolean::wrap_under_get_rule(dict.find2(&key).unwrap() as CFBooleanRef) }; assert_eq!(value, CFBoolean::true_value()); assert_eq!(dict.find2(&invalid_key), None); } } vendor/core-foundation-0.5.1/src/error.rs0000644000000000000000000000357113264166600017104 0ustar rootroot// Copyright 2016 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Core Foundation errors. pub use core_foundation_sys::error::*; use std::error::Error; use std::fmt; use base::{CFIndex, TCFType}; use string::CFString; declare_TCFType!{ /// An error value. CFError, CFErrorRef } impl_TCFType!(CFError, CFErrorRef, CFErrorGetTypeID); impl fmt::Debug for CFError { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.debug_struct("CFError") .field("domain", &self.domain()) .field("code", &self.code()) .field("description", &self.description()) .finish() } } impl fmt::Display for CFError { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "{}", self.description()) } } impl Error for CFError { fn description(&self) -> &str { "a Core Foundation error" } } impl CFError { /// Returns a string identifying the domain with which this error is /// associated. pub fn domain(&self) -> CFString { unsafe { let s = CFErrorGetDomain(self.0); CFString::wrap_under_get_rule(s) } } /// Returns the code identifying this type of error. pub fn code(&self) -> CFIndex { unsafe { CFErrorGetCode(self.0) } } /// Returns a human-presentable description of the error. pub fn description(&self) -> CFString { unsafe { let s = CFErrorCopyDescription(self.0); CFString::wrap_under_create_rule(s) } } } vendor/core-foundation-0.5.1/src/filedescriptor.rs0000644000000000000000000001350113264166600020763 0ustar rootrootpub use core_foundation_sys::filedescriptor::*; use core_foundation_sys::base::{Boolean, CFIndex}; use core_foundation_sys::base::{kCFAllocatorDefault, CFOptionFlags}; use base::TCFType; use runloop::CFRunLoopSource; use std::mem; use std::os::unix::io::{AsRawFd, RawFd}; use std::ptr; declare_TCFType!{ CFFileDescriptor, CFFileDescriptorRef } impl_TCFType!(CFFileDescriptor, CFFileDescriptorRef, CFFileDescriptorGetTypeID); impl CFFileDescriptor { pub fn new(fd: RawFd, closeOnInvalidate: bool, callout: CFFileDescriptorCallBack, context: Option<&CFFileDescriptorContext>) -> Option { let context = context.map_or(ptr::null(), |c| c as *const _); unsafe { let fd_ref = CFFileDescriptorCreate(kCFAllocatorDefault, fd, closeOnInvalidate as Boolean, callout, context); if fd_ref.is_null() { None } else { Some(TCFType::wrap_under_create_rule(fd_ref)) } } } pub fn context(&self) -> CFFileDescriptorContext { unsafe { let mut context: CFFileDescriptorContext = mem::uninitialized(); CFFileDescriptorGetContext(self.0, &mut context); context } } pub fn enable_callbacks(&self, callback_types: CFOptionFlags) { unsafe { CFFileDescriptorEnableCallBacks(self.0, callback_types) } } pub fn disable_callbacks(&self, callback_types: CFOptionFlags) { unsafe { CFFileDescriptorDisableCallBacks(self.0, callback_types) } } pub fn valid(&self) -> bool { unsafe { CFFileDescriptorIsValid(self.0) != 0 } } pub fn invalidate(&self) { unsafe { CFFileDescriptorInvalidate(self.0) } } pub fn to_run_loop_source(&self, order: CFIndex) -> Option { unsafe { let source_ref = CFFileDescriptorCreateRunLoopSource( kCFAllocatorDefault, self.0, order ); if source_ref.is_null() { None } else { Some(TCFType::wrap_under_create_rule(source_ref)) } } } } impl AsRawFd for CFFileDescriptor { fn as_raw_fd(&self) -> RawFd { unsafe { CFFileDescriptorGetNativeDescriptor(self.0) } } } #[cfg(test)] mod test { extern crate libc; use super::*; use std::ffi::CString; use libc::{c_void, O_RDWR}; use core_foundation_sys::base::{CFOptionFlags}; use core_foundation_sys::runloop::{kCFRunLoopDefaultMode}; use runloop::{CFRunLoop}; #[test] fn test_consumed() { let path = CString::new("/dev/null").unwrap(); let raw_fd = unsafe { libc::open(path.as_ptr(), O_RDWR, 0) }; let cf_fd = CFFileDescriptor::new(raw_fd, true, never_callback, None); assert!(cf_fd.is_some()); let cf_fd = cf_fd.unwrap(); assert!(cf_fd.valid()); cf_fd.invalidate(); assert!(!cf_fd.valid()); // close() should fail assert_eq!(unsafe { libc::close(raw_fd) }, -1); } #[test] fn test_unconsumed() { let path = CString::new("/dev/null").unwrap(); let raw_fd = unsafe { libc::open(path.as_ptr(), O_RDWR, 0) }; let cf_fd = CFFileDescriptor::new(raw_fd, false, never_callback, None); assert!(cf_fd.is_some()); let cf_fd = cf_fd.unwrap(); assert!(cf_fd.valid()); cf_fd.invalidate(); assert!(!cf_fd.valid()); // close() should succeed assert_eq!(unsafe { libc::close(raw_fd) }, 0); } extern "C" fn never_callback(_f: CFFileDescriptorRef, _callback_types: CFOptionFlags, _info_ptr: *mut c_void) { unreachable!(); } struct TestInfo { value: CFOptionFlags } #[test] fn test_callback() { let mut info = TestInfo { value: 0 }; let context = CFFileDescriptorContext { version: 0, info: &mut info as *mut _ as *mut c_void, retain: None, release: None, copyDescription: None }; let path = CString::new("/dev/null").unwrap(); let raw_fd = unsafe { libc::open(path.as_ptr(), O_RDWR, 0) }; let cf_fd = CFFileDescriptor::new(raw_fd, true, callback, Some(&context)); assert!(cf_fd.is_some()); let cf_fd = cf_fd.unwrap(); assert!(cf_fd.valid()); let run_loop = CFRunLoop::get_current(); let source = CFRunLoopSource::from_file_descriptor(&cf_fd, 0); assert!(source.is_some()); unsafe { run_loop.add_source(&source.unwrap(), kCFRunLoopDefaultMode); } info.value = 0; cf_fd.enable_callbacks(kCFFileDescriptorReadCallBack); CFRunLoop::run_current(); assert_eq!(info.value, kCFFileDescriptorReadCallBack); info.value = 0; cf_fd.enable_callbacks(kCFFileDescriptorWriteCallBack); CFRunLoop::run_current(); assert_eq!(info.value, kCFFileDescriptorWriteCallBack); info.value = 0; cf_fd.disable_callbacks(kCFFileDescriptorReadCallBack | kCFFileDescriptorWriteCallBack); cf_fd.invalidate(); assert!(!cf_fd.valid()); } extern "C" fn callback(_f: CFFileDescriptorRef, callback_types: CFOptionFlags, info_ptr: *mut c_void) { assert!(!info_ptr.is_null()); let info: *mut TestInfo = info_ptr as *mut TestInfo; unsafe { (*info).value = callback_types }; CFRunLoop::get_current().stop(); } } vendor/core-foundation-0.5.1/src/lib.rs0000644000000000000000000001310613264166600016514 0ustar rootroot// Copyright 2013 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![allow(non_snake_case)] extern crate core_foundation_sys; extern crate libc; #[cfg(feature = "with-chrono")] extern crate chrono; #[macro_export] macro_rules! declare_TCFType { ( $(#[$doc:meta])* $ty:ident, $raw:ident ) => { $(#[$doc])* pub struct $ty($raw); impl Drop for $ty { fn drop(&mut self) { unsafe { $crate::base::CFRelease(self.as_CFTypeRef()) } } } } } #[macro_export] macro_rules! impl_TCFType { ($ty:ident, $ty_ref:ident, $ty_id:ident) => { impl $crate::base::TCFType for $ty { type Ref = $ty_ref; #[inline] fn as_concrete_TypeRef(&self) -> $ty_ref { self.0 } #[inline] unsafe fn wrap_under_get_rule(reference: $ty_ref) -> $ty { use std::mem; let reference = mem::transmute($crate::base::CFRetain(mem::transmute(reference))); $crate::base::TCFType::wrap_under_create_rule(reference) } #[inline] fn as_CFTypeRef(&self) -> $crate::base::CFTypeRef { unsafe { ::std::mem::transmute(self.as_concrete_TypeRef()) } } #[inline] unsafe fn wrap_under_create_rule(reference: $ty_ref) -> $ty { $ty(reference) } #[inline] fn type_id() -> $crate::base::CFTypeID { unsafe { $ty_id() } } } impl Clone for $ty { #[inline] fn clone(&self) -> $ty { unsafe { $ty::wrap_under_get_rule(self.0) } } } impl PartialEq for $ty { #[inline] fn eq(&self, other: &$ty) -> bool { self.as_CFType().eq(&other.as_CFType()) } } impl Eq for $ty { } } } // This is basically identical to the implementation above. I can't // think of a clean way to have them share code #[macro_export] macro_rules! impl_TCFTypeGeneric { ($ty:ident, $ty_ref:ident, $ty_id:ident) => { impl $crate::base::TCFType for $ty { type Ref = $ty_ref; #[inline] fn as_concrete_TypeRef(&self) -> $ty_ref { self.0 } #[inline] unsafe fn wrap_under_get_rule(reference: $ty_ref) -> $ty { use std::mem; let reference = mem::transmute($crate::base::CFRetain(mem::transmute(reference))); $crate::base::TCFType::wrap_under_create_rule(reference) } #[inline] fn as_CFTypeRef(&self) -> ::core_foundation_sys::base::CFTypeRef { unsafe { ::std::mem::transmute(self.as_concrete_TypeRef()) } } #[inline] unsafe fn wrap_under_create_rule(obj: $ty_ref) -> $ty { $ty(obj, PhantomData) } #[inline] fn type_id() -> ::core_foundation_sys::base::CFTypeID { unsafe { $ty_id() } } } impl Clone for $ty { #[inline] fn clone(&self) -> $ty { unsafe { $ty::wrap_under_get_rule(self.0) } } } impl PartialEq for $ty { #[inline] fn eq(&self, other: &$ty) -> bool { self.as_CFType().eq(&other.as_CFType()) } } impl Eq for $ty { } } } #[macro_export] macro_rules! impl_CFTypeDescription { ($ty:ident) => { impl ::std::fmt::Debug for $ty { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { self.as_CFType().fmt(f) } } } } // The same as impl_CFTypeDescription but with a type parameter #[macro_export] macro_rules! impl_CFTypeDescriptionGeneric { ($ty:ident) => { impl ::std::fmt::Debug for $ty { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { self.as_CFType().fmt(f) } } } } #[macro_export] macro_rules! impl_CFComparison { ($ty:ident, $compare:ident) => { impl PartialOrd for $ty { #[inline] fn partial_cmp(&self, other: &$ty) -> Option<::std::cmp::Ordering> { unsafe { Some($compare(self.as_concrete_TypeRef(), other.as_concrete_TypeRef(), ::std::ptr::null_mut()).into()) } } } impl Ord for $ty { #[inline] fn cmp(&self, other: &$ty) -> ::std::cmp::Ordering { self.partial_cmp(other).unwrap() } } } } pub mod array; pub mod base; pub mod boolean; pub mod data; pub mod date; pub mod dictionary; pub mod error; pub mod filedescriptor; pub mod number; pub mod set; pub mod string; pub mod url; pub mod bundle; pub mod propertylist; pub mod runloop; pub mod timezone; pub mod uuid; vendor/core-foundation-0.5.1/src/number.rs0000644000000000000000000000570413264166600017243 0ustar rootroot// Copyright 2013 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Immutable numbers. use core_foundation_sys::base::kCFAllocatorDefault; pub use core_foundation_sys::number::*; use std::mem; use base::TCFType; declare_TCFType!{ /// An immutable numeric value. CFNumber, CFNumberRef } impl_TCFType!(CFNumber, CFNumberRef, CFNumberGetTypeID); impl_CFTypeDescription!(CFNumber); impl_CFComparison!(CFNumber, CFNumberCompare); impl CFNumber { #[inline] pub fn to_i64(&self) -> Option { unsafe { let mut value: i64 = 0; let ok = CFNumberGetValue(self.0, kCFNumberSInt64Type, mem::transmute(&mut value)); if ok { Some(value) } else { None } } } #[inline] pub fn to_f32(&self) -> Option { unsafe { let mut value: f32 = 0.0; let ok = CFNumberGetValue(self.0, kCFNumberFloat32Type, mem::transmute(&mut value)); if ok { Some(value) } else { None } } } #[inline] pub fn to_f64(&self) -> Option { unsafe { let mut value: f64 = 0.0; let ok = CFNumberGetValue(self.0, kCFNumberFloat64Type, mem::transmute(&mut value)); if ok { Some(value) } else { None } } } } impl From for CFNumber { #[inline] fn from(value: i32) -> Self { unsafe { let number_ref = CFNumberCreate( kCFAllocatorDefault, kCFNumberSInt32Type, mem::transmute(&value), ); TCFType::wrap_under_create_rule(number_ref) } } } impl From for CFNumber { #[inline] fn from(value: i64) -> Self { unsafe { let number_ref = CFNumberCreate( kCFAllocatorDefault, kCFNumberSInt64Type, mem::transmute(&value), ); TCFType::wrap_under_create_rule(number_ref) } } } impl From for CFNumber { #[inline] fn from(value: f32) -> Self { unsafe { let number_ref = CFNumberCreate( kCFAllocatorDefault, kCFNumberFloat32Type, mem::transmute(&value), ); TCFType::wrap_under_create_rule(number_ref) } } } impl From for CFNumber { #[inline] fn from(value: f64) -> Self { unsafe { let number_ref = CFNumberCreate( kCFAllocatorDefault, kCFNumberFloat64Type, mem::transmute(&value), ); TCFType::wrap_under_create_rule(number_ref) } } } vendor/core-foundation-0.5.1/src/propertylist.rs0000644000000000000000000002633613264166600020537 0ustar rootroot// Copyright 2013 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Core Foundation property lists use std::ptr; use std::mem; use libc::c_void; use error::CFError; use data::CFData; use base::{CFType, TCFType, TCFTypeRef}; pub use core_foundation_sys::propertylist::*; use core_foundation_sys::error::CFErrorRef; use core_foundation_sys::base::{CFGetRetainCount, CFGetTypeID, CFIndex, CFRetain, CFShow, CFTypeID, kCFAllocatorDefault}; pub fn create_with_data(data: CFData, options: CFPropertyListMutabilityOptions) -> Result<(*const c_void, CFPropertyListFormat), CFError> { unsafe { let mut error: CFErrorRef = ptr::null_mut(); let mut format: CFPropertyListFormat = 0; let property_list = CFPropertyListCreateWithData(kCFAllocatorDefault, data.as_concrete_TypeRef(), options, &mut format, &mut error); if property_list.is_null() { Err(TCFType::wrap_under_create_rule(error)) } else { Ok((property_list, format)) } } } pub fn create_data(property_list: *const c_void, format: CFPropertyListFormat) -> Result { unsafe { let mut error: CFErrorRef = ptr::null_mut(); let data_ref = CFPropertyListCreateData(kCFAllocatorDefault, property_list, format, 0, &mut error); if data_ref.is_null() { Err(TCFType::wrap_under_create_rule(error)) } else { Ok(TCFType::wrap_under_create_rule(data_ref)) } } } /// Trait for all subclasses of [`CFPropertyList`]. /// /// [`CFPropertyList`]: struct.CFPropertyList.html pub trait CFPropertyListSubClass: TCFType { /// Create an instance of the superclass type [`CFPropertyList`] for this instance. /// /// [`CFPropertyList`]: struct.CFPropertyList.html #[inline] fn to_CFPropertyList(&self) -> CFPropertyList { unsafe { CFPropertyList::wrap_under_get_rule(self.as_concrete_TypeRef().as_void_ptr()) } } /// Equal to [`to_CFPropertyList`], but consumes self and avoids changing the reference count. /// /// [`to_CFPropertyList`]: #method.to_CFPropertyList #[inline] fn into_CFPropertyList(self) -> CFPropertyList where Self: Sized, { let reference = self.as_concrete_TypeRef().as_void_ptr(); mem::forget(self); unsafe { CFPropertyList::wrap_under_create_rule(reference) } } } impl CFPropertyListSubClass for ::data::CFData {} impl CFPropertyListSubClass for ::string::CFString {} impl CFPropertyListSubClass for ::array::CFArray {} impl CFPropertyListSubClass for ::dictionary::CFDictionary {} impl CFPropertyListSubClass for ::date::CFDate {} impl CFPropertyListSubClass for ::boolean::CFBoolean {} impl CFPropertyListSubClass for ::number::CFNumber {} declare_TCFType!{ /// A CFPropertyList struct. This is superclass to [`CFData`], [`CFString`], [`CFArray`], /// [`CFDictionary`], [`CFDate`], [`CFBoolean`], and [`CFNumber`]. /// /// This superclass type does not have its own `CFTypeID`, instead each instance has the `CFTypeID` /// of the subclass it is an instance of. Thus, this type cannot implement the [`TCFType`] trait, /// since it cannot implement the static [`TCFType::type_id()`] method. /// /// [`CFData`]: ../data/struct.CFData.html /// [`CFString`]: ../string/struct.CFString.html /// [`CFArray`]: ../array/struct.CFArray.html /// [`CFDictionary`]: ../dictionary/struct.CFDictionary.html /// [`CFDate`]: ../date/struct.CFDate.html /// [`CFBoolean`]: ../boolean/struct.CFBoolean.html /// [`CFNumber`]: ../number/struct.CFNumber.html /// [`TCFType`]: ../base/trait.TCFType.html /// [`TCFType::type_id()`]: ../base/trait.TCFType.html#method.type_of CFPropertyList, CFPropertyListRef } impl CFPropertyList { #[inline] pub fn as_concrete_TypeRef(&self) -> CFPropertyListRef { self.0 } #[inline] pub unsafe fn wrap_under_get_rule(reference: CFPropertyListRef) -> CFPropertyList { let reference = mem::transmute(CFRetain(mem::transmute(reference))); CFPropertyList(reference) } #[inline] pub fn as_CFType(&self) -> CFType { unsafe { CFType::wrap_under_get_rule(self.as_CFTypeRef()) } } #[inline] pub fn into_CFType(self) -> CFType where Self: Sized, { let reference = self.as_CFTypeRef(); mem::forget(self); unsafe { TCFType::wrap_under_create_rule(reference) } } #[inline] pub fn as_CFTypeRef(&self) -> ::core_foundation_sys::base::CFTypeRef { unsafe { mem::transmute(self.as_concrete_TypeRef()) } } #[inline] pub unsafe fn wrap_under_create_rule(obj: CFPropertyListRef) -> CFPropertyList { CFPropertyList(obj) } /// Returns the reference count of the object. It is unwise to do anything other than test /// whether the return value of this method is greater than zero. #[inline] pub fn retain_count(&self) -> CFIndex { unsafe { CFGetRetainCount(self.as_CFTypeRef()) } } /// Returns the type ID of this object. Will be one of CFData, CFString, CFArray, CFDictionary, /// CFDate, CFBoolean, or CFNumber. #[inline] pub fn type_of(&self) -> CFTypeID { unsafe { CFGetTypeID(self.as_CFTypeRef()) } } /// Writes a debugging version of this object on standard error. pub fn show(&self) { unsafe { CFShow(self.as_CFTypeRef()) } } /// Returns true if this value is an instance of another type. #[inline] pub fn instance_of(&self) -> bool { self.type_of() == OtherCFType::type_id() } } impl Clone for CFPropertyList { #[inline] fn clone(&self) -> CFPropertyList { unsafe { CFPropertyList::wrap_under_get_rule(self.0) } } } impl PartialEq for CFPropertyList { #[inline] fn eq(&self, other: &CFPropertyList) -> bool { self.as_CFType().eq(&other.as_CFType()) } } impl Eq for CFPropertyList {} impl CFPropertyList { /// Try to downcast the [`CFPropertyList`] to a subclass. Checking if the instance is the /// correct subclass happens at runtime and `None` is returned if it is not the correct type. /// Works similar to [`Box::downcast`] and [`CFType::downcast`]. /// /// # Examples /// /// ``` /// # use core_foundation::string::CFString; /// # use core_foundation::propertylist::{CFPropertyList, CFPropertyListSubClass}; /// # /// // Create a string. /// let string: CFString = CFString::from_static_string("FooBar"); /// // Cast it up to a property list. /// let propertylist: CFPropertyList = string.to_CFPropertyList(); /// // Cast it down again. /// assert!(propertylist.downcast::().unwrap().to_string() == "FooBar"); /// ``` /// /// [`CFPropertyList`]: struct.CFPropertyList.html /// [`Box::downcast`]: https://doc.rust-lang.org/std/boxed/struct.Box.html#method.downcast pub fn downcast(&self) -> Option { if self.instance_of::() { unsafe { let subclass_ref = T::Ref::from_void_ptr(self.0); Some(T::wrap_under_get_rule(subclass_ref)) } } else { None } } /// Similar to [`downcast`], but consumes self and can thus avoid touching the retain count. /// /// [`downcast`]: #method.downcast pub fn downcast_into(self) -> Option { if self.instance_of::() { unsafe { let subclass_ref = T::Ref::from_void_ptr(self.0); mem::forget(self); Some(T::wrap_under_create_rule(subclass_ref)) } } else { None } } } #[cfg(test)] pub mod test { use super::*; use string::CFString; use boolean::CFBoolean; #[test] fn test_property_list_serialization() { use base::{TCFType, CFEqual}; use boolean::CFBoolean; use number::CFNumber; use dictionary::CFDictionary; use string::CFString; use super::*; let bar = CFString::from_static_string("Bar"); let baz = CFString::from_static_string("Baz"); let boo = CFString::from_static_string("Boo"); let foo = CFString::from_static_string("Foo"); let tru = CFBoolean::true_value(); let n42 = CFNumber::from(42); let dict1 = CFDictionary::from_CFType_pairs(&[(bar.as_CFType(), boo.as_CFType()), (baz.as_CFType(), tru.as_CFType()), (foo.as_CFType(), n42.as_CFType())]); let data = create_data(dict1.as_CFTypeRef(), kCFPropertyListXMLFormat_v1_0).unwrap(); let (dict2, _) = create_with_data(data, kCFPropertyListImmutable).unwrap(); unsafe { assert!(CFEqual(dict1.as_CFTypeRef(), dict2) == 1); } } #[test] fn to_propertylist_retain_count() { let string = CFString::from_static_string("Bar"); assert_eq!(string.retain_count(), 1); let propertylist = string.to_CFPropertyList(); assert_eq!(string.retain_count(), 2); assert_eq!(propertylist.retain_count(), 2); mem::drop(string); assert_eq!(propertylist.retain_count(), 1); } #[test] fn downcast_string() { let propertylist = CFString::from_static_string("Bar").to_CFPropertyList(); assert!(propertylist.downcast::().unwrap().to_string() == "Bar"); assert!(propertylist.downcast::().is_none()); } #[test] fn downcast_boolean() { let propertylist = CFBoolean::true_value().to_CFPropertyList(); assert!(propertylist.downcast::().is_some()); assert!(propertylist.downcast::().is_none()); } #[test] fn downcast_into_fail() { let string = CFString::from_static_string("Bar"); let propertylist = string.to_CFPropertyList(); assert_eq!(string.retain_count(), 2); assert!(propertylist.downcast_into::().is_none()); assert_eq!(string.retain_count(), 1); } #[test] fn downcast_into() { let string = CFString::from_static_string("Bar"); let propertylist = string.to_CFPropertyList(); assert_eq!(string.retain_count(), 2); let string2 = propertylist.downcast_into::().unwrap(); assert!(string2.to_string() == "Bar"); assert_eq!(string2.retain_count(), 2); } } vendor/core-foundation-0.5.1/src/runloop.rs0000644000000000000000000001370513264166600017451 0ustar rootroot// Copyright 2013 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![allow(non_upper_case_globals)] pub use core_foundation_sys::runloop::*; use core_foundation_sys::base::CFIndex; use core_foundation_sys::base::{kCFAllocatorDefault, CFOptionFlags}; use core_foundation_sys::string::CFStringRef; use base::{TCFType}; use date::{CFAbsoluteTime, CFTimeInterval}; use filedescriptor::CFFileDescriptor; use string::{CFString}; pub type CFRunLoopMode = CFStringRef; declare_TCFType!(CFRunLoop, CFRunLoopRef); impl_TCFType!(CFRunLoop, CFRunLoopRef, CFRunLoopGetTypeID); impl_CFTypeDescription!(CFRunLoop); impl CFRunLoop { pub fn get_current() -> CFRunLoop { unsafe { let run_loop_ref = CFRunLoopGetCurrent(); TCFType::wrap_under_get_rule(run_loop_ref) } } pub fn get_main() -> CFRunLoop { unsafe { let run_loop_ref = CFRunLoopGetMain(); TCFType::wrap_under_get_rule(run_loop_ref) } } pub fn run_current() { unsafe { CFRunLoopRun(); } } pub fn stop(&self) { unsafe { CFRunLoopStop(self.0); } } pub fn current_mode(&self) -> Option { unsafe { let string_ref = CFRunLoopCopyCurrentMode(self.0); if string_ref.is_null() { return None; } let cf_string: CFString = TCFType::wrap_under_create_rule(string_ref); Some(cf_string.to_string()) } } pub fn contains_timer(&self, timer: &CFRunLoopTimer, mode: CFRunLoopMode) -> bool { unsafe { CFRunLoopContainsTimer(self.0, timer.0, mode) != 0 } } pub fn add_timer(&self, timer: &CFRunLoopTimer, mode: CFRunLoopMode) { unsafe { CFRunLoopAddTimer(self.0, timer.0, mode); } } pub fn remove_timer(&self, timer: &CFRunLoopTimer, mode: CFRunLoopMode) { unsafe { CFRunLoopRemoveTimer(self.0, timer.0, mode); } } pub fn contains_source(&self, source: &CFRunLoopSource, mode: CFRunLoopMode) -> bool { unsafe { CFRunLoopContainsSource(self.0, source.0, mode) != 0 } } pub fn add_source(&self, source: &CFRunLoopSource, mode: CFRunLoopMode) { unsafe { CFRunLoopAddSource(self.0, source.0, mode); } } pub fn remove_source(&self, source: &CFRunLoopSource, mode: CFRunLoopMode) { unsafe { CFRunLoopRemoveSource(self.0, source.0, mode); } } pub fn contains_observer(&self, observer: &CFRunLoopObserver, mode: CFRunLoopMode) -> bool { unsafe { CFRunLoopContainsObserver(self.0, observer.0, mode) != 0 } } pub fn add_observer(&self, observer: &CFRunLoopObserver, mode: CFRunLoopMode) { unsafe { CFRunLoopAddObserver(self.0, observer.0, mode); } } pub fn remove_observer(&self, observer: &CFRunLoopObserver, mode: CFRunLoopMode) { unsafe { CFRunLoopRemoveObserver(self.0, observer.0, mode); } } } declare_TCFType!(CFRunLoopTimer, CFRunLoopTimerRef); impl_TCFType!(CFRunLoopTimer, CFRunLoopTimerRef, CFRunLoopTimerGetTypeID); impl CFRunLoopTimer { pub fn new(fireDate: CFAbsoluteTime, interval: CFTimeInterval, flags: CFOptionFlags, order: CFIndex, callout: CFRunLoopTimerCallBack, context: *mut CFRunLoopTimerContext) -> CFRunLoopTimer { unsafe { let timer_ref = CFRunLoopTimerCreate(kCFAllocatorDefault, fireDate, interval, flags, order, callout, context); TCFType::wrap_under_create_rule(timer_ref) } } } declare_TCFType!(CFRunLoopSource, CFRunLoopSourceRef); impl_TCFType!(CFRunLoopSource, CFRunLoopSourceRef, CFRunLoopSourceGetTypeID); impl CFRunLoopSource { pub fn from_file_descriptor(fd: &CFFileDescriptor, order: CFIndex) -> Option { fd.to_run_loop_source(order) } } declare_TCFType!(CFRunLoopObserver, CFRunLoopObserverRef); impl_TCFType!(CFRunLoopObserver, CFRunLoopObserverRef, CFRunLoopObserverGetTypeID); #[cfg(test)] mod test { use super::*; use date::{CFDate, CFAbsoluteTime}; use std::mem; use libc::c_void; use std::sync::mpsc; #[test] fn wait_200_milliseconds() { let run_loop = CFRunLoop::get_current(); let now = CFDate::now().abs_time(); let (elapsed_tx, elapsed_rx) = mpsc::channel(); let mut info = Info { start_time: now, elapsed_tx, }; let mut context = unsafe { CFRunLoopTimerContext { version: 0, info: &mut info as *mut _ as *mut c_void, retain: mem::zeroed(), release: mem::zeroed(), copyDescription: mem::zeroed(), } }; let run_loop_timer = CFRunLoopTimer::new(now + 0.20f64, 0f64, 0, 0, timer_popped, &mut context); unsafe { run_loop.add_timer(&run_loop_timer, kCFRunLoopDefaultMode); } CFRunLoop::run_current(); let elapsed = elapsed_rx.try_recv().unwrap(); println!("wait_200_milliseconds, elapsed: {}", elapsed); assert!(elapsed > 0.19 && elapsed < 0.30); } struct Info { start_time: CFAbsoluteTime, elapsed_tx: mpsc::Sender, } extern "C" fn timer_popped(_timer: CFRunLoopTimerRef, raw_info: *mut c_void) { let info: *mut Info = unsafe { mem::transmute(raw_info) }; let now = CFDate::now().abs_time(); let elapsed = now - unsafe { (*info).start_time }; let _ = unsafe { (*info).elapsed_tx.send(elapsed) }; CFRunLoop::get_current().stop(); } } vendor/core-foundation-0.5.1/src/set.rs0000644000000000000000000000252013264166600016537 0ustar rootroot// Copyright 2013 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! An immutable bag of elements. pub use core_foundation_sys::set::*; use core_foundation_sys::base::{CFTypeRef, kCFAllocatorDefault}; use base::{CFIndexConvertible, TCFType}; use std::mem; declare_TCFType!{ /// An immutable bag of elements. CFSet, CFSetRef } impl_TCFType!(CFSet, CFSetRef, CFSetGetTypeID); impl_CFTypeDescription!(CFSet); impl CFSet { /// Creates a new set from a list of `CFType` instances. pub fn from_slice(elems: &[T]) -> CFSet where T: TCFType { unsafe { let elems: Vec = elems.iter().map(|elem| elem.as_CFTypeRef()).collect(); let set_ref = CFSetCreate(kCFAllocatorDefault, mem::transmute(elems.as_ptr()), elems.len().to_CFIndex(), &kCFTypeSetCallBacks); TCFType::wrap_under_create_rule(set_ref) } } } vendor/core-foundation-0.5.1/src/string.rs0000644000000000000000000001241613264166600017257 0ustar rootroot// Copyright 2013 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Immutable strings. pub use core_foundation_sys::string::*; use base::{CFIndexConvertible, TCFType}; use core_foundation_sys::base::{Boolean, CFIndex, CFRange}; use core_foundation_sys::base::{kCFAllocatorDefault, kCFAllocatorNull}; use std::fmt; use std::str::{self, FromStr}; use std::ptr; use std::ffi::CStr; declare_TCFType!{ /// An immutable string in one of a variety of encodings. CFString, CFStringRef } impl_TCFType!(CFString, CFStringRef, CFStringGetTypeID); impl FromStr for CFString { type Err = (); /// See also CFString::new for a variant of this which does not return a Result #[inline] fn from_str(string: &str) -> Result { Ok(CFString::new(string)) } } impl<'a> From<&'a str> for CFString { #[inline] fn from(string: &'a str) -> CFString { CFString::new(string) } } impl fmt::Display for CFString { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { unsafe { // Do this without allocating if we can get away with it let c_string = CFStringGetCStringPtr(self.0, kCFStringEncodingUTF8); if c_string != ptr::null() { let c_str = CStr::from_ptr(c_string); fmt.write_str(str::from_utf8_unchecked(c_str.to_bytes())) } else { let char_len = self.char_len(); // First, ask how big the buffer ought to be. let mut bytes_required: CFIndex = 0; CFStringGetBytes(self.0, CFRange { location: 0, length: char_len }, kCFStringEncodingUTF8, 0, false as Boolean, ptr::null_mut(), 0, &mut bytes_required); // Then, allocate the buffer and actually copy. let mut buffer = vec![b'\x00'; bytes_required as usize]; let mut bytes_used: CFIndex = 0; let chars_written = CFStringGetBytes(self.0, CFRange { location: 0, length: char_len }, kCFStringEncodingUTF8, 0, false as Boolean, buffer.as_mut_ptr(), buffer.len().to_CFIndex(), &mut bytes_used) as usize; assert!(chars_written.to_CFIndex() == char_len); // This is dangerous; we over-allocate and null-terminate the string (during // initialization). assert!(bytes_used == buffer.len().to_CFIndex()); fmt.write_str(str::from_utf8_unchecked(&buffer)) } } } } impl fmt::Debug for CFString { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "\"{}\"", self) } } impl CFString { /// Creates a new `CFString` instance from a Rust string. #[inline] pub fn new(string: &str) -> CFString { unsafe { let string_ref = CFStringCreateWithBytes(kCFAllocatorDefault, string.as_ptr(), string.len().to_CFIndex(), kCFStringEncodingUTF8, false as Boolean); CFString::wrap_under_create_rule(string_ref) } } /// Like `CFString::new`, but references a string that can be used as a backing store /// by virtue of being statically allocated. #[inline] pub fn from_static_string(string: &'static str) -> CFString { unsafe { let string_ref = CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, string.as_ptr(), string.len().to_CFIndex(), kCFStringEncodingUTF8, false as Boolean, kCFAllocatorNull); TCFType::wrap_under_create_rule(string_ref) } } /// Returns the number of characters in the string. #[inline] pub fn char_len(&self) -> CFIndex { unsafe { CFStringGetLength(self.0) } } } #[test] fn string_and_back() { let original = "The quick brown fox jumped over the slow lazy dog."; let cfstr = CFString::from_static_string(original); let converted = cfstr.to_string(); assert!(converted == original); } vendor/core-foundation-0.5.1/src/timezone.rs0000644000000000000000000000521313264166600017600 0ustar rootroot// Copyright 2013 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Core Foundation time zone objects. pub use core_foundation_sys::timezone::*; use core_foundation_sys::base::kCFAllocatorDefault; use base::TCFType; use date::{CFDate, CFTimeInterval}; #[cfg(feature = "with-chrono")] use chrono::{FixedOffset, NaiveDateTime}; declare_TCFType!{ /// A time zone. CFTimeZone, CFTimeZoneRef } impl_TCFType!(CFTimeZone, CFTimeZoneRef, CFTimeZoneGetTypeID); impl_CFTypeDescription!(CFTimeZone); impl Default for CFTimeZone { fn default() -> CFTimeZone { unsafe { let tz_ref = CFTimeZoneCopyDefault(); TCFType::wrap_under_create_rule(tz_ref) } } } impl CFTimeZone { #[inline] pub fn new(interval: CFTimeInterval) -> CFTimeZone { unsafe { let tz_ref = CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorDefault, interval); TCFType::wrap_under_create_rule(tz_ref) } } #[inline] pub fn system() -> CFTimeZone { unsafe { let tz_ref = CFTimeZoneCopySystem(); TCFType::wrap_under_create_rule(tz_ref) } } pub fn seconds_from_gmt(&self, date: CFDate) -> CFTimeInterval { unsafe { CFTimeZoneGetSecondsFromGMT(self.0, date.abs_time()) } } #[cfg(feature = "with-chrono")] pub fn offset_at_date(&self, date: NaiveDateTime) -> FixedOffset { let date = CFDate::from_naive_utc(date); FixedOffset::east(self.seconds_from_gmt(date) as i32) } #[cfg(feature = "with-chrono")] pub fn from_offset(offset: FixedOffset) -> CFTimeZone { CFTimeZone::new(offset.local_minus_utc() as f64) } } #[cfg(test)] mod test { use super::CFTimeZone; #[cfg(feature = "with-chrono")] use chrono::{NaiveDateTime, FixedOffset}; #[test] fn timezone_comparison() { let system = CFTimeZone::system(); let default = CFTimeZone::default(); assert_eq!(system, default); } #[test] #[cfg(feature = "with-chrono")] fn timezone_chrono_conversion() { let offset = FixedOffset::west(28800); let tz = CFTimeZone::from_offset(offset); let converted = tz.offset_at_date(NaiveDateTime::from_timestamp(0, 0)); assert_eq!(offset, converted); } } vendor/core-foundation-0.5.1/src/url.rs0000644000000000000000000001222313264166600016547 0ustar rootroot// Copyright 2013 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! A URL type for Core Foundation. pub use core_foundation_sys::url::*; use base::{TCFType, CFIndex}; use string::{CFString}; use core_foundation_sys::base::{kCFAllocatorDefault, Boolean}; use std::fmt; use std::ptr; use std::path::{Path, PathBuf}; use std::mem; use libc::{strlen, PATH_MAX}; #[cfg(unix)] use std::os::unix::ffi::OsStrExt; #[cfg(unix)] use std::ffi::OsStr; declare_TCFType!(CFURL, CFURLRef); impl_TCFType!(CFURL, CFURLRef, CFURLGetTypeID); impl fmt::Debug for CFURL { #[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { unsafe { let string: CFString = TCFType::wrap_under_get_rule(CFURLGetString(self.0)); write!(f, "{}", string.to_string()) } } } impl CFURL { pub fn from_path>(path: P, isDirectory: bool) -> Option { let path_bytes; #[cfg(unix)] { path_bytes = path.as_ref().as_os_str().as_bytes() } #[cfg(not(unix))] { // XXX: Getting non-valid UTF8 paths into CoreFoundation on Windows is going to be unpleasant // CFURLGetWideFileSystemRepresentation might help path_bytes = match path.as_ref().to_str() { Some(path) => path, None => return None, } } unsafe { let url_ref = CFURLCreateFromFileSystemRepresentation(ptr::null_mut(), path_bytes.as_ptr(), path_bytes.len() as CFIndex, isDirectory as u8); if url_ref.is_null() { return None; } Some(TCFType::wrap_under_create_rule(url_ref)) } } pub fn from_file_system_path(filePath: CFString, pathStyle: CFURLPathStyle, isDirectory: bool) -> CFURL { unsafe { let url_ref = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, filePath.as_concrete_TypeRef(), pathStyle, isDirectory as u8); TCFType::wrap_under_create_rule(url_ref) } } #[cfg(unix)] pub fn to_path(&self) -> Option { // implementing this on Windows is more complicated because of the different OsStr representation unsafe { let mut buf: [u8; PATH_MAX as usize] = mem::uninitialized(); let result = CFURLGetFileSystemRepresentation(self.0, true as Boolean, buf.as_mut_ptr(), buf.len() as CFIndex); if result == false as Boolean { return None; } let len = strlen(buf.as_ptr() as *const i8); let path = OsStr::from_bytes(&buf[0..len]); Some(PathBuf::from(path)) } } pub fn get_string(&self) -> CFString { unsafe { TCFType::wrap_under_get_rule(CFURLGetString(self.0)) } } pub fn get_file_system_path(&self, pathStyle: CFURLPathStyle) -> CFString { unsafe { TCFType::wrap_under_create_rule(CFURLCopyFileSystemPath(self.as_concrete_TypeRef(), pathStyle)) } } pub fn absolute(&self) -> CFURL { unsafe { TCFType::wrap_under_create_rule(CFURLCopyAbsoluteURL(self.as_concrete_TypeRef())) } } } #[test] fn file_url_from_path() { let path = "/usr/local/foo/"; let cfstr_path = CFString::from_static_string(path); let cfurl = CFURL::from_file_system_path(cfstr_path, kCFURLPOSIXPathStyle, true); assert_eq!(cfurl.get_string().to_string(), "file:///usr/local/foo/"); } #[cfg(unix)] #[test] fn non_utf8() { use std::ffi::OsStr; let path = Path::new(OsStr::from_bytes(b"/\xC0/blame")); let cfurl = CFURL::from_path(path, false).unwrap(); assert_eq!(cfurl.to_path().unwrap(), path); let len = unsafe { CFURLGetBytes(cfurl.as_concrete_TypeRef(), ptr::null_mut(), 0) }; assert_eq!(len, 17); } #[test] fn absolute_file_url() { use core_foundation_sys::url::CFURLCreateWithFileSystemPathRelativeToBase; use std::path::PathBuf; let path = "/usr/local/foo"; let file = "bar"; let cfstr_path = CFString::from_static_string(path); let cfstr_file = CFString::from_static_string(file); let cfurl_base = CFURL::from_file_system_path(cfstr_path, kCFURLPOSIXPathStyle, true); let cfurl_relative: CFURL = unsafe { let url_ref = CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorDefault, cfstr_file.as_concrete_TypeRef(), kCFURLPOSIXPathStyle, false as u8, cfurl_base.as_concrete_TypeRef()); TCFType::wrap_under_create_rule(url_ref) }; let mut absolute_path = PathBuf::from(path); absolute_path.push(file); assert_eq!(cfurl_relative.get_file_system_path(kCFURLPOSIXPathStyle).to_string(), file); assert_eq!(cfurl_relative.absolute().get_file_system_path(kCFURLPOSIXPathStyle).to_string(), absolute_path.to_str().unwrap()); } vendor/core-foundation-0.5.1/src/uuid.rs0000644000000000000000000000520213264166600016712 0ustar rootroot// Copyright 2013 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Core Foundation UUID objects. #[cfg(feature = "with-uuid")] extern crate uuid; pub use core_foundation_sys::uuid::*; use core_foundation_sys::base::kCFAllocatorDefault; use base::TCFType; #[cfg(feature = "with-uuid")] use self::uuid::Uuid; declare_TCFType! { /// A UUID. CFUUID, CFUUIDRef } impl_TCFType!(CFUUID, CFUUIDRef, CFUUIDGetTypeID); impl_CFTypeDescription!(CFUUID); impl CFUUID { #[inline] pub fn new() -> CFUUID { unsafe { let uuid_ref = CFUUIDCreate(kCFAllocatorDefault); TCFType::wrap_under_create_rule(uuid_ref) } } } #[cfg(feature = "with-uuid")] impl Into for CFUUID { fn into(self) -> Uuid { let b = unsafe { CFUUIDGetUUIDBytes(self.0) }; let bytes = [ b.byte0, b.byte1, b.byte2, b.byte3, b.byte4, b.byte5, b.byte6, b.byte7, b.byte8, b.byte9, b.byte10, b.byte11, b.byte12, b.byte13, b.byte14, b.byte15, ]; Uuid::from_bytes(&bytes).unwrap() } } #[cfg(feature = "with-uuid")] impl From for CFUUID { fn from(uuid: Uuid) -> CFUUID { let b = uuid.as_bytes(); let bytes = CFUUIDBytes { byte0: b[0], byte1: b[1], byte2: b[2], byte3: b[3], byte4: b[4], byte5: b[5], byte6: b[6], byte7: b[7], byte8: b[8], byte9: b[9], byte10: b[10], byte11: b[11], byte12: b[12], byte13: b[13], byte14: b[14], byte15: b[15], }; unsafe { let uuid_ref = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, bytes); TCFType::wrap_under_create_rule(uuid_ref) } } } #[cfg(test)] #[cfg(feature = "with-uuid")] mod test { use super::CFUUID; use uuid::Uuid; #[test] fn uuid_conversion() { let cf_uuid = CFUUID::new(); let uuid: Uuid = cf_uuid.clone().into(); let converted = CFUUID::from(uuid); assert!(cf_uuid == converted); } } vendor/core-foundation-0.5.1/tests/0000755000000000000000000000000013264166600015752 5ustar rootrootvendor/core-foundation-0.5.1/tests/use_macro_outside_crate.rs0000644000000000000000000000131713264166600023211 0ustar rootroot#[macro_use] extern crate core_foundation; extern crate libc; use core_foundation::base::{CFComparisonResult, TCFType}; use libc::c_void; // sys equivalent stuff that must be declared #[repr(C)] pub struct __CFFooBar(c_void); pub type CFFooBarRef = *const __CFFooBar; extern "C" { pub fn CFFooBarGetTypeID() -> core_foundation::base::CFTypeID; pub fn fake_compare( this: CFFooBarRef, other: CFFooBarRef, context: *mut c_void, ) -> CFComparisonResult; } // Try to use the macros outside of the crate declare_TCFType!(CFFooBar, CFFooBarRef); impl_TCFType!(CFFooBar, CFFooBarRef, CFFooBarGetTypeID); impl_CFTypeDescription!(CFFooBar); impl_CFComparison!(CFFooBar, fake_compare); vendor/core-foundation-sys-0.5.1/0000755000000000000000000000000013264166600015424 5ustar rootrootvendor/core-foundation-sys-0.5.1/.cargo-checksum.json0000644000000000000000000000013113264166600021263 0ustar rootroot{"files":{},"package":"716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa"}vendor/core-foundation-sys-0.5.1/Cargo.toml0000644000000000000000000000165413264166600017362 0ustar rootroot# 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 = "core-foundation-sys" version = "0.5.1" authors = ["The Servo Project Developers"] build = "build.rs" description = "Bindings to Core Foundation for OS X" homepage = "https://github.com/servo/core-foundation-rs" license = "MIT / Apache-2.0" repository = "https://github.com/servo/core-foundation-rs" [dependencies.libc] version = "0.2" [features] mac_os_10_7_support = [] mac_os_10_8_features = [] vendor/core-foundation-sys-0.5.1/LICENSE-APACHE0000644000000000000000000002513713264166600017360 0ustar rootroot 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. vendor/core-foundation-sys-0.5.1/LICENSE-MIT0000644000000000000000000000205313264166600017060 0ustar rootrootCopyright (c) 2012-2013 Mozilla Foundation 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. vendor/core-foundation-sys-0.5.1/build.rs0000644000000000000000000000110413264166600017065 0ustar rootroot// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. fn main() { if std::env::var("TARGET").unwrap().contains("-apple") { println!("cargo:rustc-link-lib=framework=CoreFoundation"); } } vendor/core-foundation-sys-0.5.1/src/0000755000000000000000000000000013264166600016213 5ustar rootrootvendor/core-foundation-sys-0.5.1/src/array.rs0000644000000000000000000000414213264166600017700 0ustar rootroot// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use libc::c_void; use base::{CFRange, CFIndex, CFAllocatorRef, CFTypeID, Boolean}; use string::CFStringRef; pub type CFArrayRetainCallBack = extern "C" fn(allocator: CFAllocatorRef, value: *const c_void) -> *const c_void; pub type CFArrayReleaseCallBack = extern "C" fn(allocator: CFAllocatorRef, value: *const c_void); pub type CFArrayCopyDescriptionCallBack = extern "C" fn(value: *const c_void) -> CFStringRef; pub type CFArrayEqualCallBack = extern "C" fn(value1: *const c_void, value2: *const c_void) -> Boolean; #[repr(C)] #[derive(Clone, Copy)] pub struct CFArrayCallBacks { pub version: CFIndex, pub retain: CFArrayRetainCallBack, pub release: CFArrayReleaseCallBack, pub copyDescription: CFArrayCopyDescriptionCallBack, pub equal: CFArrayEqualCallBack, } #[repr(C)] pub struct __CFArray(c_void); pub type CFArrayRef = *const __CFArray; extern { /* * CFArray.h */ pub static kCFTypeArrayCallBacks: CFArrayCallBacks; pub fn CFArrayCreate(allocator: CFAllocatorRef, values: *const *const c_void, numValues: CFIndex, callBacks: *const CFArrayCallBacks) -> CFArrayRef; pub fn CFArrayCreateCopy(allocator: CFAllocatorRef , theArray: CFArrayRef) -> CFArrayRef; // CFArrayBSearchValues // CFArrayContainsValue pub fn CFArrayGetCount(theArray: CFArrayRef) -> CFIndex; // CFArrayGetCountOfValue // CFArrayGetFirstIndexOfValue // CFArrayGetLastIndexOfValue pub fn CFArrayGetValues(theArray: CFArrayRef, range: CFRange, values: *mut *const c_void); pub fn CFArrayGetValueAtIndex(theArray: CFArrayRef, idx: CFIndex) -> *const c_void; // CFArrayApplyFunction pub fn CFArrayGetTypeID() -> CFTypeID; } vendor/core-foundation-sys-0.5.1/src/base.rs0000644000000000000000000001230413264166600017473 0ustar rootroot// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use std::cmp::Ordering; use libc::{c_uint, c_long, c_ulong, c_void, c_int}; use string::CFStringRef; pub type Boolean = u8; pub type CFIndex = c_long; pub type mach_port_t = c_uint; pub type CFAllocatorRef = *const c_void; pub type CFNullRef = *const c_void; pub type CFHashCode = c_ulong; pub type CFTypeID = c_ulong; pub type CFTypeRef = *const c_void; pub type CFOptionFlags = u32; pub type OSStatus = i32; pub type SInt32 = c_int; #[repr(i64)] #[derive(Clone, Copy)] pub enum CFComparisonResult { LessThan = -1, EqualTo = 0, GreaterThan = 1, } impl Into for CFComparisonResult { fn into(self) -> Ordering { match self { CFComparisonResult::LessThan => Ordering::Less, CFComparisonResult::EqualTo => Ordering::Equal, CFComparisonResult::GreaterThan => Ordering::Greater } } } #[repr(C)] #[derive(Clone, Copy)] pub struct CFRange { pub location: CFIndex, pub length: CFIndex } // for back-compat impl CFRange { pub fn init(location: CFIndex, length: CFIndex) -> CFRange { CFRange { location: location, length: length, } } } pub type CFAllocatorRetainCallBack = extern "C" fn(info: *mut c_void) -> *mut c_void; pub type CFAllocatorReleaseCallBack = extern "C" fn(info: *mut c_void); pub type CFAllocatorCopyDescriptionCallBack = extern "C" fn(info: *mut c_void) -> CFStringRef; pub type CFAllocatorAllocateCallBack = extern "C" fn(allocSize: CFIndex, hint: CFOptionFlags, info: *mut c_void) -> *mut c_void; pub type CFAllocatorReallocateCallBack = extern "C" fn(ptr: *mut c_void, newsize: CFIndex, hint: CFOptionFlags, info: *mut c_void) -> *mut c_void; pub type CFAllocatorDeallocateCallBack = extern "C" fn(ptr: *mut c_void, info: *mut c_void); pub type CFAllocatorPreferredSizeCallBack = extern "C" fn(size: CFIndex, hint: CFOptionFlags, info: *mut c_void) -> CFIndex; #[repr(C)] #[derive(Clone, Copy)] pub struct CFAllocatorContext { pub version: CFIndex, pub info: *mut c_void, pub retain: CFAllocatorRetainCallBack, pub release: CFAllocatorReleaseCallBack, pub copyDescription: CFAllocatorCopyDescriptionCallBack, pub allocate: CFAllocatorAllocateCallBack, pub reallocate: CFAllocatorReallocateCallBack, pub deallocate: CFAllocatorDeallocateCallBack, pub preferredSize: CFAllocatorPreferredSizeCallBack } /// Trait for all types which are Core Foundation reference types. pub trait TCFTypeRef { fn as_void_ptr(&self) -> *const c_void; unsafe fn from_void_ptr(ptr: *const c_void) -> Self; } impl TCFTypeRef for *const T { fn as_void_ptr(&self) -> *const c_void { (*self) as *const c_void } unsafe fn from_void_ptr(ptr: *const c_void) -> Self { ptr as *const T } } impl TCFTypeRef for *mut T { fn as_void_ptr(&self) -> *const c_void { (*self) as *const T as *const c_void } unsafe fn from_void_ptr(ptr: *const c_void) -> Self { ptr as *const T as *mut T } } extern { /* * CFBase.h */ /* CFAllocator Reference */ pub static kCFAllocatorDefault: CFAllocatorRef; pub static kCFAllocatorSystemDefault: CFAllocatorRef; pub static kCFAllocatorMalloc: CFAllocatorRef; pub static kCFAllocatorMallocZone: CFAllocatorRef; pub static kCFAllocatorNull: CFAllocatorRef; pub static kCFAllocatorUseContext: CFAllocatorRef; pub fn CFAllocatorCreate(allocator: CFAllocatorRef, context: *mut CFAllocatorContext) -> CFAllocatorRef; pub fn CFAllocatorAllocate(allocator: CFAllocatorRef, size: CFIndex, hint: CFOptionFlags) -> *mut c_void; pub fn CFAllocatorDeallocate(allocator: CFAllocatorRef, ptr: *mut c_void); pub fn CFAllocatorGetPreferredSizeForSize(allocator: CFAllocatorRef, size: CFIndex, hint: CFOptionFlags) -> CFIndex; pub fn CFAllocatorReallocate(allocator: CFAllocatorRef, ptr: *mut c_void, newsize: CFIndex, hint: CFOptionFlags) -> *mut c_void; pub fn CFAllocatorGetDefault() -> CFAllocatorRef; pub fn CFAllocatorSetDefault(allocator: CFAllocatorRef); pub fn CFAllocatorGetContext(allocator: CFAllocatorRef, context: *mut CFAllocatorContext); pub fn CFAllocatorGetTypeID() -> CFTypeID; /* CFNull Reference */ pub static kCFNull: CFNullRef; /* CFType Reference */ //fn CFCopyTypeIDDescription //fn CFGetAllocator pub fn CFCopyDescription(cf: CFTypeRef) -> CFStringRef; pub fn CFEqual(cf1: CFTypeRef, cf2: CFTypeRef) -> Boolean; pub fn CFGetRetainCount(cf: CFTypeRef) -> CFIndex; pub fn CFGetTypeID(cf: CFTypeRef) -> CFTypeID; pub fn CFHash(cf: CFTypeRef) -> CFHashCode; //fn CFMakeCollectable pub fn CFRelease(cf: CFTypeRef); pub fn CFRetain(cf: CFTypeRef) -> CFTypeRef; pub fn CFShow(obj: CFTypeRef); /* Base Utilities Reference */ // N.B. Some things missing here. } vendor/core-foundation-sys-0.5.1/src/bundle.rs0000644000000000000000000000242713264166600020037 0ustar rootroot// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use libc::c_void; use base::{CFTypeID, CFAllocatorRef}; use url::CFURLRef; use dictionary::CFDictionaryRef; use string::CFStringRef; #[repr(C)] pub struct __CFBundle(c_void); pub type CFBundleRef = *mut __CFBundle; extern { /* * CFBundle.h */ pub fn CFBundleCreate(allocator: CFAllocatorRef, bundleURL: CFURLRef) -> CFBundleRef; pub fn CFBundleGetBundleWithIdentifier(bundleID: CFStringRef) -> CFBundleRef; pub fn CFBundleGetFunctionPointerForName(bundle: CFBundleRef, function_name: CFStringRef) -> *const c_void; pub fn CFBundleGetMainBundle() -> CFBundleRef; pub fn CFBundleGetInfoDictionary(bundle: CFBundleRef) -> CFDictionaryRef; pub fn CFBundleGetTypeID() -> CFTypeID; pub fn CFBundleCopyExecutableURL(bundle: CFBundleRef) -> CFURLRef; pub fn CFBundleCopyPrivateFrameworksURL(bundle: CFBundleRef) -> CFURLRef; } vendor/core-foundation-sys-0.5.1/src/data.rs0000644000000000000000000000076213264166600017477 0ustar rootrootuse libc::c_void; use base::{CFAllocatorRef, CFTypeID, CFIndex}; #[repr(C)] pub struct __CFData(c_void); pub type CFDataRef = *const __CFData; extern { /* * CFData.h */ pub fn CFDataCreate(allocator: CFAllocatorRef, bytes: *const u8, length: CFIndex) -> CFDataRef; //fn CFDataFind pub fn CFDataGetBytePtr(theData: CFDataRef) -> *const u8; pub fn CFDataGetLength(theData: CFDataRef) -> CFIndex; pub fn CFDataGetTypeID() -> CFTypeID; } vendor/core-foundation-sys-0.5.1/src/date.rs0000644000000000000000000000235613264166600017504 0ustar rootroot// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use libc::c_void; use base::{CFAllocatorRef, CFComparisonResult, CFTypeID}; #[repr(C)] pub struct __CFDate(c_void); pub type CFDateRef = *const __CFDate; pub type CFTimeInterval = f64; pub type CFAbsoluteTime = CFTimeInterval; extern { pub static kCFAbsoluteTimeIntervalSince1904: CFTimeInterval; pub static kCFAbsoluteTimeIntervalSince1970: CFTimeInterval; pub fn CFAbsoluteTimeGetCurrent() -> CFAbsoluteTime; pub fn CFDateCreate(allocator: CFAllocatorRef, at: CFAbsoluteTime) -> CFDateRef; pub fn CFDateGetAbsoluteTime(date: CFDateRef) -> CFAbsoluteTime; pub fn CFDateGetTimeIntervalSinceDate(date: CFDateRef, other: CFDateRef) -> CFTimeInterval; pub fn CFDateCompare(date: CFDateRef, other: CFDateRef, context: *mut c_void) -> CFComparisonResult; pub fn CFDateGetTypeID() -> CFTypeID; } vendor/core-foundation-sys-0.5.1/src/dictionary.rs0000644000000000000000000001057213264166600020733 0ustar rootroot// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use libc::{c_void}; use base::{CFAllocatorRef, CFHashCode, CFIndex, CFTypeID, Boolean}; use string::CFStringRef; pub type CFDictionaryApplierFunction = extern "C" fn(key: *const c_void, value: *const c_void, context: *mut c_void); pub type CFDictionaryRetainCallBack = extern "C" fn(allocator: CFAllocatorRef, value: *const c_void) -> *const c_void; pub type CFDictionaryReleaseCallBack = extern "C" fn(allocator: CFAllocatorRef, value: *const c_void); pub type CFDictionaryCopyDescriptionCallBack = extern "C" fn(value: *const c_void) -> CFStringRef; pub type CFDictionaryEqualCallBack = extern "C" fn(value1: *const c_void, value2: *const c_void) -> Boolean; pub type CFDictionaryHashCallBack = extern "C" fn(value: *const c_void) -> CFHashCode; #[repr(C)] #[derive(Clone, Copy)] pub struct CFDictionaryKeyCallBacks { pub version: CFIndex, pub retain: CFDictionaryRetainCallBack, pub release: CFDictionaryReleaseCallBack, pub copyDescription: CFDictionaryCopyDescriptionCallBack, pub equal: CFDictionaryEqualCallBack, pub hash: CFDictionaryHashCallBack } #[repr(C)] #[derive(Clone, Copy)] pub struct CFDictionaryValueCallBacks { pub version: CFIndex, pub retain: CFDictionaryRetainCallBack, pub release: CFDictionaryReleaseCallBack, pub copyDescription: CFDictionaryCopyDescriptionCallBack, pub equal: CFDictionaryEqualCallBack } #[repr(C)] pub struct __CFDictionary(c_void); pub type CFDictionaryRef = *const __CFDictionary; pub type CFMutableDictionaryRef = *mut __CFDictionary; extern { /* * CFDictionary.h */ pub static kCFTypeDictionaryKeyCallBacks: CFDictionaryKeyCallBacks; pub static kCFTypeDictionaryValueCallBacks: CFDictionaryValueCallBacks; pub fn CFDictionaryContainsKey(theDict: CFDictionaryRef, key: *const c_void) -> Boolean; pub fn CFDictionaryCreate(allocator: CFAllocatorRef, keys: *const *const c_void, values: *const *const c_void, numValues: CFIndex, keyCallBacks: *const CFDictionaryKeyCallBacks, valueCallBacks: *const CFDictionaryValueCallBacks) -> CFDictionaryRef; pub fn CFDictionaryGetCount(theDict: CFDictionaryRef) -> CFIndex; pub fn CFDictionaryGetTypeID() -> CFTypeID; pub fn CFDictionaryGetValueIfPresent(theDict: CFDictionaryRef, key: *const c_void, value: *mut *const c_void) -> Boolean; pub fn CFDictionaryApplyFunction(theDict: CFDictionaryRef, applier: CFDictionaryApplierFunction, context: *mut c_void); pub fn CFDictionaryGetKeysAndValues(theDict: CFDictionaryRef, keys: *mut *const c_void, values: *mut *const c_void); pub fn CFDictionaryCreateMutable(allocator: CFAllocatorRef, capacity: CFIndex, keyCallbacks: *const CFDictionaryKeyCallBacks, valueCallbacks: *const CFDictionaryValueCallBacks) -> CFMutableDictionaryRef; pub fn CFDictionaryCreateMutableCopy(allocator: CFAllocatorRef, capacity: CFIndex, theDict: CFDictionaryRef) -> CFMutableDictionaryRef; pub fn CFDictionaryAddValue(theDict: CFMutableDictionaryRef, key: *const c_void, value: *const c_void); pub fn CFDictionarySetValue(theDict: CFMutableDictionaryRef, key: *const c_void, value: *const c_void); pub fn CFDictionaryReplaceValue(theDict: CFMutableDictionaryRef, key: *const c_void, value: *const c_void); pub fn CFDictionaryRemoveValue(theDict: CFMutableDictionaryRef, key: *const c_void); pub fn CFDictionaryRemoveAllValues(theDict: CFMutableDictionaryRef); } vendor/core-foundation-sys-0.5.1/src/error.rs0000644000000000000000000000200213264166600017704 0ustar rootroot// Copyright 2016 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use libc::c_void; use base::{CFTypeID, CFIndex}; use string::CFStringRef; #[repr(C)] pub struct __CFError(c_void); pub type CFErrorRef = *mut __CFError; extern "C" { pub fn CFErrorGetTypeID() -> CFTypeID; pub static kCFErrorDomainPOSIX: CFStringRef; pub static kCFErrorDomainOSStatus: CFStringRef; pub static kCFErrorDomainMach: CFStringRef; pub static kCFErrorDomainCocoa: CFStringRef; pub fn CFErrorGetDomain(err: CFErrorRef) -> CFStringRef; pub fn CFErrorGetCode(err: CFErrorRef) -> CFIndex; pub fn CFErrorCopyDescription(err: CFErrorRef) -> CFStringRef; } vendor/core-foundation-sys-0.5.1/src/filedescriptor.rs0000644000000000000000000000366313264166600021607 0ustar rootrootuse libc::{c_void, c_int}; use base::{Boolean, CFIndex, CFTypeID, CFOptionFlags, CFAllocatorRef}; use string::CFStringRef; use runloop::CFRunLoopSourceRef; pub type CFFileDescriptorNativeDescriptor = c_int; #[repr(C)] pub struct __CFFileDescriptor(c_void); pub type CFFileDescriptorRef = *mut __CFFileDescriptor; /* Callback Reason Types */ pub const kCFFileDescriptorReadCallBack: CFOptionFlags = 1 << 0; pub const kCFFileDescriptorWriteCallBack: CFOptionFlags = 1 << 1; pub type CFFileDescriptorCallBack = extern "C" fn (f: CFFileDescriptorRef, callBackTypes: CFOptionFlags, info: *mut c_void); #[repr(C)] #[derive(Clone, Copy)] pub struct CFFileDescriptorContext { pub version: CFIndex, pub info: *mut c_void, pub retain: Option *const c_void>, pub release: Option, pub copyDescription: Option CFStringRef>, } extern { /* * CFFileDescriptor.h */ pub fn CFFileDescriptorGetTypeID() -> CFTypeID; pub fn CFFileDescriptorCreate(allocator: CFAllocatorRef, fd: CFFileDescriptorNativeDescriptor, closeOnInvalidate: Boolean, callout: CFFileDescriptorCallBack, context: *const CFFileDescriptorContext) -> CFFileDescriptorRef; pub fn CFFileDescriptorGetNativeDescriptor(f: CFFileDescriptorRef) -> CFFileDescriptorNativeDescriptor; pub fn CFFileDescriptorGetContext(f: CFFileDescriptorRef, context: *mut CFFileDescriptorContext); pub fn CFFileDescriptorEnableCallBacks(f: CFFileDescriptorRef, callBackTypes: CFOptionFlags); pub fn CFFileDescriptorDisableCallBacks(f: CFFileDescriptorRef, callBackTypes: CFOptionFlags); pub fn CFFileDescriptorInvalidate(f: CFFileDescriptorRef); pub fn CFFileDescriptorIsValid(f: CFFileDescriptorRef) -> Boolean; pub fn CFFileDescriptorCreateRunLoopSource(allocator: CFAllocatorRef, f: CFFileDescriptorRef, order: CFIndex) -> CFRunLoopSourceRef; } vendor/core-foundation-sys-0.5.1/src/lib.rs0000644000000000000000000000170013264166600017325 0ustar rootroot// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![allow(non_snake_case, non_camel_case_types, non_upper_case_globals, improper_ctypes)] #![cfg_attr(all(feature="mac_os_10_7_support", feature="mac_os_10_8_features"), feature(linkage))] // back-compat requires weak linkage extern crate libc; pub mod array; pub mod base; pub mod bundle; pub mod data; pub mod date; pub mod dictionary; pub mod error; pub mod filedescriptor; pub mod messageport; pub mod number; pub mod propertylist; pub mod runloop; pub mod set; pub mod string; pub mod timezone; pub mod url; pub mod uuid; vendor/core-foundation-sys-0.5.1/src/messageport.rs0000644000000000000000000000656213264166600021123 0ustar rootroot// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use libc::c_void; use base::{CFAllocatorRef, CFIndex, CFTypeID, Boolean}; use data::CFDataRef; use date::CFTimeInterval; use runloop::CFRunLoopSourceRef; use string::CFStringRef; #[repr(C)] #[derive(Copy, Clone)] #[derive(Debug)] pub struct CFMessagePortContext { pub version: CFIndex, pub info: *mut c_void, pub retain: Option *const c_void>, pub release: Option, pub copyDescription: Option CFStringRef>, } pub type CFMessagePortCallBack = Option< unsafe extern fn(local: CFMessagePortRef, msgid: i32, data: CFDataRef, info: *mut c_void) -> CFDataRef>; pub type CFMessagePortInvalidationCallBack = Option< unsafe extern "C" fn(ms: CFMessagePortRef, info: *mut c_void)>; #[repr(C)] pub struct __CFMessagePort(c_void); pub type CFMessagePortRef = *mut __CFMessagePort; extern { /* * CFMessagePort.h */ pub fn CFMessagePortGetTypeID() -> CFTypeID; pub fn CFMessagePortCreateLocal(allocator: CFAllocatorRef, name: CFStringRef, callout: CFMessagePortCallBack, context: *const CFMessagePortContext, shouldFreeInfo: *mut Boolean) -> CFMessagePortRef; pub fn CFMessagePortCreateRemote(allocator: CFAllocatorRef, name: CFStringRef) -> CFMessagePortRef; pub fn CFMessagePortIsRemote(ms: CFMessagePortRef) -> Boolean; pub fn CFMessagePortGetName(ms: CFMessagePortRef) -> CFStringRef; pub fn CFMessagePortSetName(ms: CFMessagePortRef, newName: CFStringRef) -> Boolean; pub fn CFMessagePortGetContext(ms: CFMessagePortRef, context: *mut CFMessagePortContext); pub fn CFMessagePortInvalidate(ms: CFMessagePortRef); pub fn CFMessagePortIsValid(ms: CFMessagePortRef) -> Boolean; pub fn CFMessagePortGetInvalidationCallBack(ms: CFMessagePortRef) -> CFMessagePortInvalidationCallBack; pub fn CFMessagePortSetInvalidationCallBack(ms: CFMessagePortRef, callout: CFMessagePortInvalidationCallBack); pub fn CFMessagePortSendRequest(remote: CFMessagePortRef, msgid: i32, data: CFDataRef, sendTimeout: CFTimeInterval, rcvTimeout: CFTimeInterval, replyMode: CFStringRef, returnData: *mut CFDataRef) -> i32; pub fn CFMessagePortCreateRunLoopSource(allocator: CFAllocatorRef, local: CFMessagePortRef, order: CFIndex) -> CFRunLoopSourceRef; // CFMessagePortSetDispatchQueue } vendor/core-foundation-sys-0.5.1/src/number.rs0000644000000000000000000000447113264166600020057 0ustar rootroot// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use libc::c_void; use base::{CFAllocatorRef, CFTypeID, CFComparisonResult}; #[repr(C)] pub struct __CFBoolean(c_void); pub type CFBooleanRef = *const __CFBoolean; pub type CFNumberType = u32; // members of enum CFNumberType // static kCFNumberSInt8Type: CFNumberType = 1; // static kCFNumberSInt16Type: CFNumberType = 2; pub static kCFNumberSInt32Type: CFNumberType = 3; pub static kCFNumberSInt64Type: CFNumberType = 4; pub static kCFNumberFloat32Type: CFNumberType = 5; pub static kCFNumberFloat64Type: CFNumberType = 6; // static kCFNumberCharType: CFNumberType = 7; // static kCFNumberShortType: CFNumberType = 8; // static kCFNumberIntType: CFNumberType = 9; // static kCFNumberLongType: CFNumberType = 10; // static kCFNumberLongLongType: CFNumberType = 11; // static kCFNumberFloatType: CFNumberType = 12; // static kCFNumberDoubleType: CFNumberType = 13; // static kCFNumberCFIndexType: CFNumberType = 14; // static kCFNumberNSIntegerType: CFNumberType = 15; // static kCFNumberCGFloatType: CFNumberType = 16; // static kCFNumberMaxType: CFNumberType = 16; // This is an enum due to zero-sized types warnings. // For more details see https://github.com/rust-lang/rust/issues/27303 pub enum __CFNumber {} pub type CFNumberRef = *const __CFNumber; extern { /* * CFNumber.h */ pub static kCFBooleanTrue: CFBooleanRef; pub static kCFBooleanFalse: CFBooleanRef; pub fn CFBooleanGetTypeID() -> CFTypeID; pub fn CFNumberCreate(allocator: CFAllocatorRef, theType: CFNumberType, valuePtr: *const c_void) -> CFNumberRef; //fn CFNumberGetByteSize pub fn CFNumberGetValue(number: CFNumberRef, theType: CFNumberType, valuePtr: *mut c_void) -> bool; pub fn CFNumberCompare(date: CFNumberRef, other: CFNumberRef, context: *mut c_void) -> CFComparisonResult; pub fn CFNumberGetTypeID() -> CFTypeID; } vendor/core-foundation-sys-0.5.1/src/propertylist.rs0000644000000000000000000000320213264166600021336 0ustar rootrootuse base::{CFAllocatorRef, CFIndex, CFOptionFlags, CFTypeRef}; use data::CFDataRef; use error::CFErrorRef; pub type CFPropertyListRef = CFTypeRef; pub type CFPropertyListFormat = CFIndex; pub const kCFPropertyListOpenStepFormat: CFPropertyListFormat = 1; pub const kCFPropertyListXMLFormat_v1_0: CFPropertyListFormat = 100; pub const kCFPropertyListBinaryFormat_v1_0: CFPropertyListFormat = 200; pub type CFPropertyListMutabilityOptions = CFOptionFlags; pub const kCFPropertyListImmutable: CFPropertyListMutabilityOptions = 0; pub const kCFPropertyListMutableContainers: CFPropertyListMutabilityOptions = 1; pub const kCFPropertyListMutableContainersAndLeaves: CFPropertyListMutabilityOptions = 2; extern "C" { // CFPropertyList.h // // fn CFPropertyListCreateDeepCopy // fn CFPropertyListIsValid pub fn CFPropertyListCreateWithData(allocator: CFAllocatorRef, data: CFDataRef, options: CFPropertyListMutabilityOptions, format: *mut CFPropertyListFormat, error: *mut CFErrorRef) -> CFPropertyListRef; // fn CFPropertyListCreateWithStream // fn CFPropertyListWrite pub fn CFPropertyListCreateData(allocator: CFAllocatorRef, propertyList: CFPropertyListRef, format: CFPropertyListFormat, options: CFOptionFlags, error: *mut CFErrorRef) -> CFDataRef; } vendor/core-foundation-sys-0.5.1/src/runloop.rs0000644000000000000000000002137513264166600020267 0ustar rootroot// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use libc::c_void; use array::CFArrayRef; use base::{Boolean, CFIndex, CFTypeID, CFAllocatorRef, CFOptionFlags, CFHashCode, mach_port_t}; use date::{CFAbsoluteTime, CFTimeInterval}; use string::CFStringRef; #[repr(C)] pub struct __CFRunLoop(c_void); pub type CFRunLoopRef = *mut __CFRunLoop; #[repr(C)] pub struct __CFRunLoopSource(c_void); pub type CFRunLoopSourceRef = *mut __CFRunLoopSource; #[repr(C)] pub struct __CFRunLoopObserver(c_void); pub type CFRunLoopObserverRef = *mut __CFRunLoopObserver; // Reasons for CFRunLoopRunInMode() to Return pub const kCFRunLoopRunFinished: i32 = 1; pub const kCFRunLoopRunStopped: i32 = 2; pub const kCFRunLoopRunTimedOut: i32 = 3; pub const kCFRunLoopRunHandledSource: i32 = 4; // Run Loop Observer Activities //typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) { pub type CFRunLoopActivity = CFOptionFlags; pub const kCFRunLoopEntry: CFOptionFlags = 1 << 0; pub const kCFRunLoopBeforeTimers: CFOptionFlags = 1 << 1; pub const kCFRunLoopBeforeSources: CFOptionFlags = 1 << 2; pub const kCFRunLoopBeforeWaiting: CFOptionFlags = 1 << 5; pub const kCFRunLoopAfterWaiting: CFOptionFlags = 1 << 6; pub const kCFRunLoopExit: CFOptionFlags = 1 << 7; pub const kCFRunLoopAllActivities: CFOptionFlags = 0x0FFFFFFF; #[repr(C)] pub struct CFRunLoopSourceContext { pub version: CFIndex, pub info: *mut c_void, pub retain: extern "C" fn (info: *const c_void) -> *const c_void, pub release: extern "C" fn (info: *const c_void), pub copyDescription: extern "C" fn (info: *const c_void) -> CFStringRef, pub equal: extern "C" fn (info1: *const c_void, info2: *const c_void) -> Boolean, pub hash: extern "C" fn (info: *const c_void) -> CFHashCode, pub schedule: extern "C" fn (info: *const c_void, rl: CFRunLoopRef, mode: CFStringRef), pub cancel: extern "C" fn (info: *const c_void, rl: CFRunLoopRef, mode: CFStringRef), pub perform: extern "C" fn (info: *const c_void), } #[repr(C)] pub struct CFRunLoopSourceContext1 { pub version: CFIndex, pub info: *mut c_void, pub retain: extern "C" fn (info: *const c_void) -> *const c_void, pub release: extern "C" fn (info: *const c_void), pub copyDescription: extern "C" fn (info: *const c_void) -> CFStringRef, pub equal: extern "C" fn (info1: *const c_void, info2: *const c_void) -> Boolean, pub hash: extern "C" fn (info: *const c_void) -> CFHashCode, // note that the following two fields are platform dependent in the C header, the ones here are for OS X pub getPort: extern "C" fn (info: *mut c_void) -> mach_port_t, pub perform: extern "C" fn (msg: *mut c_void, size: CFIndex, allocator: CFAllocatorRef, info: *mut c_void) -> *mut c_void, } #[repr(C)] pub struct CFRunLoopObserverContext { pub version: CFIndex, pub info: *mut c_void, pub retain: extern "C" fn (info: *const c_void) -> *const c_void, pub release: extern "C" fn (info: *const c_void), pub copyDescription: extern "C" fn (info: *const c_void) -> CFStringRef, } pub type CFRunLoopObserverCallBack = extern "C" fn (observer: CFRunLoopObserverRef, activity: CFRunLoopActivity, info: *mut c_void); #[repr(C)] pub struct CFRunLoopTimerContext { pub version: CFIndex, pub info: *mut c_void, pub retain: extern "C" fn (info: *const c_void) -> *const c_void, pub release: extern "C" fn (info: *const c_void), pub copyDescription: extern "C" fn (info: *const c_void) -> CFStringRef, } pub type CFRunLoopTimerCallBack = extern "C" fn (timer: CFRunLoopTimerRef, info: *mut c_void); #[repr(C)] pub struct __CFRunLoopTimer; pub type CFRunLoopTimerRef = *mut __CFRunLoopTimer; extern { /* * CFRunLoop.h */ pub static kCFRunLoopDefaultMode: CFStringRef; pub static kCFRunLoopCommonModes: CFStringRef; pub fn CFRunLoopGetTypeID() -> CFTypeID; pub fn CFRunLoopGetCurrent() -> CFRunLoopRef; pub fn CFRunLoopGetMain() -> CFRunLoopRef; pub fn CFRunLoopCopyCurrentMode(rl: CFRunLoopRef) -> CFStringRef; pub fn CFRunLoopCopyAllModes(rl: CFRunLoopRef) -> CFArrayRef; pub fn CFRunLoopAddCommonMode(rl: CFRunLoopRef, mode: CFStringRef); pub fn CFRunLoopGetNextTimerFireDate(rl: CFRunLoopRef, mode: CFStringRef) -> CFAbsoluteTime; pub fn CFRunLoopRun(); pub fn CFRunLoopRunInMode(mode: CFStringRef, seconds: CFTimeInterval, returnAfterSourceHandled: Boolean) -> i32; pub fn CFRunLoopIsWaiting(rl: CFRunLoopRef) -> Boolean; pub fn CFRunLoopWakeUp(rl: CFRunLoopRef); pub fn CFRunLoopStop(rl: CFRunLoopRef); // fn CFRunLoopPerformBlock(rl: CFRunLoopRef, mode: CFTypeRef, block: void (^)(void)); pub fn CFRunLoopContainsSource(rl: CFRunLoopRef, source: CFRunLoopSourceRef, mode: CFStringRef) -> Boolean; pub fn CFRunLoopAddSource(rl: CFRunLoopRef, source: CFRunLoopSourceRef, mode: CFStringRef); pub fn CFRunLoopRemoveSource(rl: CFRunLoopRef, source: CFRunLoopSourceRef, mode: CFStringRef); pub fn CFRunLoopContainsObserver(rl: CFRunLoopRef, observer: CFRunLoopObserverRef, mode: CFStringRef) -> Boolean; pub fn CFRunLoopAddObserver(rl: CFRunLoopRef, observer: CFRunLoopObserverRef, mode: CFStringRef); pub fn CFRunLoopRemoveObserver(rl: CFRunLoopRef, observer: CFRunLoopObserverRef, mode: CFStringRef); pub fn CFRunLoopContainsTimer(rl: CFRunLoopRef, timer: CFRunLoopTimerRef, mode: CFStringRef) -> Boolean; pub fn CFRunLoopAddTimer(rl: CFRunLoopRef, timer: CFRunLoopTimerRef, mode: CFStringRef); pub fn CFRunLoopRemoveTimer(rl: CFRunLoopRef, timer: CFRunLoopTimerRef, mode: CFStringRef); pub fn CFRunLoopSourceGetTypeID() -> CFTypeID; pub fn CFRunLoopSourceCreate(allocator: CFAllocatorRef, order: CFIndex, context: *mut CFRunLoopSourceContext) -> CFRunLoopSourceRef; pub fn CFRunLoopSourceGetOrder(source: CFRunLoopSourceRef) -> CFIndex; pub fn CFRunLoopSourceInvalidate(source: CFRunLoopSourceRef); pub fn CFRunLoopSourceIsValid(source: CFRunLoopSourceRef) -> Boolean; pub fn CFRunLoopSourceGetContext(source: CFRunLoopSourceRef, context: *mut CFRunLoopSourceContext); pub fn CFRunLoopSourceSignal(source: CFRunLoopSourceRef); pub fn CFRunLoopObserverGetTypeID() -> CFTypeID; pub fn CFRunLoopObserverCreate(allocator: CFAllocatorRef, activities: CFOptionFlags, repeats: Boolean, order: CFIndex, callout: CFRunLoopObserverCallBack, context: *mut CFRunLoopObserverContext) -> CFRunLoopObserverRef; // fn CFRunLoopObserverCreateWithHandler(allocator: CFAllocatorRef, activities: CFOptionFlags, repeats: Boolean, order: CFIndex, block: void (^) (CFRunLoopObserverRef observer, CFRunLoopActivity activity)) -> CFRunLoopObserverRef; pub fn CFRunLoopObserverGetActivities(observer: CFRunLoopObserverRef) -> CFOptionFlags; pub fn CFRunLoopObserverDoesRepeat(observer: CFRunLoopObserverRef) -> Boolean; pub fn CFRunLoopObserverGetOrder(observer: CFRunLoopObserverRef) -> CFIndex; pub fn CFRunLoopObserverInvalidate(observer: CFRunLoopObserverRef); pub fn CFRunLoopObserverIsValid(observer: CFRunLoopObserverRef) -> Boolean; pub fn CFRunLoopObserverGetContext(observer: CFRunLoopObserverRef, context: *mut CFRunLoopObserverContext); pub fn CFRunLoopTimerGetTypeID() -> CFTypeID; pub fn CFRunLoopTimerCreate(allocator: CFAllocatorRef, fireDate: CFAbsoluteTime, interval: CFTimeInterval, flags: CFOptionFlags, order: CFIndex, callout: CFRunLoopTimerCallBack, context: *mut CFRunLoopTimerContext) -> CFRunLoopTimerRef; // fn CFRunLoopTimerCreateWithHandler(allocator: CFAllocatorRef, fireDate: CFAbsoluteTime, interval: CFTimeInterval, flags: CFOptionFlags, order: CFIndex, block: void (^) (CFRunLoopTimerRef timer)) -> CFRunLoopTimerRef; pub fn CFRunLoopTimerGetNextFireDate(timer: CFRunLoopTimerRef) -> CFAbsoluteTime; pub fn CFRunLoopTimerSetNextFireDate(timer: CFRunLoopTimerRef, fireDate: CFAbsoluteTime); pub fn CFRunLoopTimerGetInterval(timer: CFRunLoopTimerRef) -> CFTimeInterval; pub fn CFRunLoopTimerDoesRepeat(timer: CFRunLoopTimerRef) -> Boolean; pub fn CFRunLoopTimerGetOrder(timer: CFRunLoopTimerRef) -> CFIndex; pub fn CFRunLoopTimerInvalidate(timer: CFRunLoopTimerRef); pub fn CFRunLoopTimerIsValid(timer: CFRunLoopTimerRef) -> Boolean; pub fn CFRunLoopTimerGetContext(timer: CFRunLoopTimerRef, context: *mut CFRunLoopTimerContext); pub fn CFRunLoopTimerGetTolerance(timer: CFRunLoopTimerRef) -> CFTimeInterval; pub fn CFRunLoopTimerSetTolerance(timer: CFRunLoopTimerRef, tolerance: CFTimeInterval); } vendor/core-foundation-sys-0.5.1/src/set.rs0000644000000000000000000000343713264166600017363 0ustar rootroot// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use libc::c_void; use base::{CFAllocatorRef, CFIndex, CFTypeID}; pub type CFSetApplierFunction = extern "C" fn (value: *const c_void, context: *const c_void); pub type CFSetRetainCallBack = *const u8; pub type CFSetReleaseCallBack = *const u8; pub type CFSetCopyDescriptionCallBack = *const u8; pub type CFSetEqualCallBack = *const u8; pub type CFSetHashCallBack = *const u8; #[repr(C)] #[derive(Clone, Copy)] pub struct CFSetCallBacks { pub version: CFIndex, pub retain: CFSetRetainCallBack, pub release: CFSetReleaseCallBack, pub copyDescription: CFSetCopyDescriptionCallBack, pub equal: CFSetEqualCallBack, pub hash: CFSetHashCallBack, } #[repr(C)] pub struct __CFSet(c_void); pub type CFSetRef = *const __CFSet; extern { /* * CFSet.h */ pub static kCFTypeSetCallBacks: CFSetCallBacks; /* Creating Sets */ pub fn CFSetCreate(allocator: CFAllocatorRef, values: *const *const c_void, numValues: CFIndex, callBacks: *const CFSetCallBacks) -> CFSetRef; /* Applying a Function to Set Members */ pub fn CFSetApplyFunction(theSet: CFSetRef, applier: CFSetApplierFunction, context: *const c_void); pub fn CFSetGetCount(theSet: CFSetRef) -> CFIndex; pub fn CFSetGetTypeID() -> CFTypeID; } vendor/core-foundation-sys-0.5.1/src/string.rs0000644000000000000000000003702713264166600020100 0ustar rootroot// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use libc::{c_char, c_ushort, c_void}; use base::{Boolean, CFOptionFlags, CFIndex, CFAllocatorRef, CFRange, CFTypeID}; pub type UniChar = c_ushort; // CFString.h pub type CFStringCompareFlags = CFOptionFlags; //static kCFCompareCaseInsensitive: CFStringCompareFlags = 1; //static kCFCompareBackwards: CFStringCompareFlags = 4; //static kCFCompareAnchored: CFStringCompareFlags = 8; //static kCFCompareNonliteral: CFStringCompareFlags = 16; //static kCFCompareLocalized: CFStringCompareFlags = 32; //static kCFCompareNumerically: CFStringCompareFlags = 64; //static kCFCompareDiacriticInsensitive: CFStringCompareFlags = 128; //static kCFCompareWidthInsensitive: CFStringCompareFlags = 256; //static kCFCompareForcedOrdering: CFStringCompareFlags = 512; pub type CFStringEncoding = u32; // OS X built-in encodings. //static kCFStringEncodingMacRoman: CFStringEncoding = 0; //static kCFStringEncodingWindowsLatin1: CFStringEncoding = 0x0500; //static kCFStringEncodingISOLatin1: CFStringEncoding = 0x0201; //static kCFStringEncodingNextStepLatin: CFStringEncoding = 0x0B01; //static kCFStringEncodingASCII: CFStringEncoding = 0x0600; //static kCFStringEncodingUnicode: CFStringEncoding = 0x0100; pub static kCFStringEncodingUTF8: CFStringEncoding = 0x08000100; //static kCFStringEncodingNonLossyASCII: CFStringEncoding = 0x0BFF; //static kCFStringEncodingUTF16: CFStringEncoding = 0x0100; //static kCFStringEncodingUTF16BE: CFStringEncoding = 0x10000100; //static kCFStringEncodingUTF16LE: CFStringEncoding = 0x14000100; //static kCFStringEncodingUTF32: CFStringEncoding = 0x0c000100; //static kCFStringEncodingUTF32BE: CFStringEncoding = 0x18000100; //static kCFStringEncodingUTF32LE: CFStringEncoding = 0x1c000100; // CFStringEncodingExt.h pub type CFStringEncodings = CFIndex; // External encodings, except those defined above. // Defined above: kCFStringEncodingMacRoman = 0 //static kCFStringEncodingMacJapanese: CFStringEncoding = 1; //static kCFStringEncodingMacChineseTrad: CFStringEncoding = 2; //static kCFStringEncodingMacKorean: CFStringEncoding = 3; //static kCFStringEncodingMacArabic: CFStringEncoding = 4; //static kCFStringEncodingMacHebrew: CFStringEncoding = 5; //static kCFStringEncodingMacGreek: CFStringEncoding = 6; //static kCFStringEncodingMacCyrillic: CFStringEncoding = 7; //static kCFStringEncodingMacDevanagari: CFStringEncoding = 9; //static kCFStringEncodingMacGurmukhi: CFStringEncoding = 10; //static kCFStringEncodingMacGujarati: CFStringEncoding = 11; //static kCFStringEncodingMacOriya: CFStringEncoding = 12; //static kCFStringEncodingMacBengali: CFStringEncoding = 13; //static kCFStringEncodingMacTamil: CFStringEncoding = 14; //static kCFStringEncodingMacTelugu: CFStringEncoding = 15; //static kCFStringEncodingMacKannada: CFStringEncoding = 16; //static kCFStringEncodingMacMalayalam: CFStringEncoding = 17; //static kCFStringEncodingMacSinhalese: CFStringEncoding = 18; //static kCFStringEncodingMacBurmese: CFStringEncoding = 19; //static kCFStringEncodingMacKhmer: CFStringEncoding = 20; //static kCFStringEncodingMacThai: CFStringEncoding = 21; //static kCFStringEncodingMacLaotian: CFStringEncoding = 22; //static kCFStringEncodingMacGeorgian: CFStringEncoding = 23; //static kCFStringEncodingMacArmenian: CFStringEncoding = 24; //static kCFStringEncodingMacChineseSimp: CFStringEncoding = 25; //static kCFStringEncodingMacTibetan: CFStringEncoding = 26; //static kCFStringEncodingMacMongolian: CFStringEncoding = 27; //static kCFStringEncodingMacEthiopic: CFStringEncoding = 28; //static kCFStringEncodingMacCentralEurRoman: CFStringEncoding = 29; //static kCFStringEncodingMacVietnamese: CFStringEncoding = 30; //static kCFStringEncodingMacExtArabic: CFStringEncoding = 31; //static kCFStringEncodingMacSymbol: CFStringEncoding = 33; //static kCFStringEncodingMacDingbats: CFStringEncoding = 34; //static kCFStringEncodingMacTurkish: CFStringEncoding = 35; //static kCFStringEncodingMacCroatian: CFStringEncoding = 36; //static kCFStringEncodingMacIcelandic: CFStringEncoding = 37; //static kCFStringEncodingMacRomanian: CFStringEncoding = 38; //static kCFStringEncodingMacCeltic: CFStringEncoding = 39; //static kCFStringEncodingMacGaelic: CFStringEncoding = 40; //static kCFStringEncodingMacFarsi: CFStringEncoding = 0x8C; //static kCFStringEncodingMacUkrainian: CFStringEncoding = 0x98; //static kCFStringEncodingMacInuit: CFStringEncoding = 0xEC; //static kCFStringEncodingMacVT100: CFStringEncoding = 0xFC; //static kCFStringEncodingMacHFS: CFStringEncoding = 0xFF; // Defined above: kCFStringEncodingISOLatin1 = 0x0201 //static kCFStringEncodingISOLatin2: CFStringEncoding = 0x0202; //static kCFStringEncodingISOLatin3: CFStringEncoding = 0x0203; //static kCFStringEncodingISOLatin4: CFStringEncoding = 0x0204; //static kCFStringEncodingISOLatinCyrillic: CFStringEncoding = 0x0205; //static kCFStringEncodingISOLatinArabic: CFStringEncoding = 0x0206; //static kCFStringEncodingISOLatinGreek: CFStringEncoding = 0x0207; //static kCFStringEncodingISOLatinHebrew: CFStringEncoding = 0x0208; //static kCFStringEncodingISOLatin5: CFStringEncoding = 0x0209; //static kCFStringEncodingISOLatin6: CFStringEncoding = 0x020A; //static kCFStringEncodingISOLatinThai: CFStringEncoding = 0x020B; //static kCFStringEncodingISOLatin7: CFStringEncoding = 0x020D; //static kCFStringEncodingISOLatin8: CFStringEncoding = 0x020E; //static kCFStringEncodingISOLatin9: CFStringEncoding = 0x020F; //static kCFStringEncodingISOLatin10: CFStringEncoding = 0x0210; //static kCFStringEncodingDOSLatinUS: CFStringEncoding = 0x0400; //static kCFStringEncodingDOSGreek: CFStringEncoding = 0x0405; //static kCFStringEncodingDOSBalticRim: CFStringEncoding = 0x0406; //static kCFStringEncodingDOSLatin1: CFStringEncoding = 0x0410; //static kCFStringEncodingDOSGreek1: CFStringEncoding = 0x0411; //static kCFStringEncodingDOSLatin2: CFStringEncoding = 0x0412; //static kCFStringEncodingDOSCyrillic: CFStringEncoding = 0x0413; //static kCFStringEncodingDOSTurkish: CFStringEncoding = 0x0414; //static kCFStringEncodingDOSPortuguese: CFStringEncoding = 0x0415; //static kCFStringEncodingDOSIcelandic: CFStringEncoding = 0x0416; //static kCFStringEncodingDOSHebrew: CFStringEncoding = 0x0417; //static kCFStringEncodingDOSCanadianFrench: CFStringEncoding = 0x0418; //static kCFStringEncodingDOSArabic: CFStringEncoding = 0x0419; //static kCFStringEncodingDOSNordic: CFStringEncoding = 0x041A; //static kCFStringEncodingDOSRussian: CFStringEncoding = 0x041B; //static kCFStringEncodingDOSGreek2: CFStringEncoding = 0x041C; //static kCFStringEncodingDOSThai: CFStringEncoding = 0x041D; //static kCFStringEncodingDOSJapanese: CFStringEncoding = 0x0420; //static kCFStringEncodingDOSChineseSimplif: CFStringEncoding = 0x0421; //static kCFStringEncodingDOSKorean: CFStringEncoding = 0x0422; //static kCFStringEncodingDOSChineseTrad: CFStringEncoding = 0x0423; // Defined above: kCFStringEncodingWindowsLatin1 = 0x0500 //static kCFStringEncodingWindowsLatin2: CFStringEncoding = 0x0501; //static kCFStringEncodingWindowsCyrillic: CFStringEncoding = 0x0502; //static kCFStringEncodingWindowsGreek: CFStringEncoding = 0x0503; //static kCFStringEncodingWindowsLatin5: CFStringEncoding = 0x0504; //static kCFStringEncodingWindowsHebrew: CFStringEncoding = 0x0505; //static kCFStringEncodingWindowsArabic: CFStringEncoding = 0x0506; //static kCFStringEncodingWindowsBalticRim: CFStringEncoding = 0x0507; //static kCFStringEncodingWindowsVietnamese: CFStringEncoding = 0x0508; //static kCFStringEncodingWindowsKoreanJohab: CFStringEncoding = 0x0510; // Defined above: kCFStringEncodingASCII = 0x0600 //static kCFStringEncodingANSEL: CFStringEncoding = 0x0601; //static kCFStringEncodingJIS_X0201_76: CFStringEncoding = 0x0620; //static kCFStringEncodingJIS_X0208_83: CFStringEncoding = 0x0621; //static kCFStringEncodingJIS_X0208_90: CFStringEncoding = 0x0622; //static kCFStringEncodingJIS_X0212_90: CFStringEncoding = 0x0623; //static kCFStringEncodingJIS_C6226_78: CFStringEncoding = 0x0624; //static kCFStringEncodingShiftJIS_X0213: CFStringEncoding = 0x0628; //static kCFStringEncodingShiftJIS_X0213_MenKuTen: CFStringEncoding = 0x0629; //static kCFStringEncodingGB_2312_80: CFStringEncoding = 0x0630; //static kCFStringEncodingGBK_95: CFStringEncoding = 0x0631; //static kCFStringEncodingGB_18030_2000: CFStringEncoding = 0x0632; //static kCFStringEncodingKSC_5601_87: CFStringEncoding = 0x0640; //static kCFStringEncodingKSC_5601_92_Johab: CFStringEncoding = 0x0641; //static kCFStringEncodingCNS_11643_92_P1: CFStringEncoding = 0x0651; //static kCFStringEncodingCNS_11643_92_P2: CFStringEncoding = 0x0652; //static kCFStringEncodingCNS_11643_92_P3: CFStringEncoding = 0x0653; //static kCFStringEncodingISO_2022_JP: CFStringEncoding = 0x0820; //static kCFStringEncodingISO_2022_JP_2: CFStringEncoding = 0x0821; //static kCFStringEncodingISO_2022_JP_1: CFStringEncoding = 0x0822; //static kCFStringEncodingISO_2022_JP_3: CFStringEncoding = 0x0823; //static kCFStringEncodingISO_2022_CN: CFStringEncoding = 0x0830; //static kCFStringEncodingISO_2022_CN_EXT: CFStringEncoding = 0x0831; //static kCFStringEncodingISO_2022_KR: CFStringEncoding = 0x0840; //static kCFStringEncodingEUC_JP: CFStringEncoding = 0x0920; //static kCFStringEncodingEUC_CN: CFStringEncoding = 0x0930; //static kCFStringEncodingEUC_TW: CFStringEncoding = 0x0931; //static kCFStringEncodingEUC_KR: CFStringEncoding = 0x0940; //static kCFStringEncodingShiftJIS: CFStringEncoding = 0x0A01; //static kCFStringEncodingKOI8_R: CFStringEncoding = 0x0A02; //static kCFStringEncodingBig5: CFStringEncoding = 0x0A03; //static kCFStringEncodingMacRomanLatin1: CFStringEncoding = 0x0A04; //static kCFStringEncodingHZ_GB_2312: CFStringEncoding = 0x0A05; //static kCFStringEncodingBig5_HKSCS_1999: CFStringEncoding = 0x0A06; //static kCFStringEncodingVISCII: CFStringEncoding = 0x0A07; //static kCFStringEncodingKOI8_U: CFStringEncoding = 0x0A08; //static kCFStringEncodingBig5_E: CFStringEncoding = 0x0A09; // Defined above: kCFStringEncodingNextStepLatin = 0x0B01 //static kCFStringEncodingNextStepJapanese: CFStringEncoding = 0x0B02; //static kCFStringEncodingEBCDIC_US: CFStringEncoding = 0x0C01; //static kCFStringEncodingEBCDIC_CP037: CFStringEncoding = 0x0C02; //static kCFStringEncodingUTF7: CFStringEncoding = 0x04000100; //static kCFStringEncodingUTF7_IMAP: CFStringEncoding = 0x0A10; //static kCFStringEncodingShiftJIS_X0213_00: CFStringEncoding = 0x0628; /* Deprecated */ #[repr(C)] pub struct __CFString(c_void); pub type CFStringRef = *const __CFString; extern { /* * CFString.h */ // N.B. organized according to "Functions by task" in docs /* Creating a CFString */ //fn CFSTR //fn CFStringCreateArrayBySeparatingStrings //fn CFStringCreateByCombiningStrings //fn CFStringCreateCopy //fn CFStringCreateFromExternalRepresentation pub fn CFStringCreateWithBytes(alloc: CFAllocatorRef, bytes: *const u8, numBytes: CFIndex, encoding: CFStringEncoding, isExternalRepresentation: Boolean) -> CFStringRef; pub fn CFStringCreateWithBytesNoCopy(alloc: CFAllocatorRef, bytes: *const u8, numBytes: CFIndex, encoding: CFStringEncoding, isExternalRepresentation: Boolean, contentsDeallocator: CFAllocatorRef) -> CFStringRef; //fn CFStringCreateWithCharacters //fn CFStringCreateWithCharactersNoCopy pub fn CFStringCreateWithCString(alloc: CFAllocatorRef, cStr: *const c_char, encoding: CFStringEncoding) -> CFStringRef; //fn CFStringCreateWithCStringNoCopy //fn CFStringCreateWithFormat //fn CFStringCreateWithFormatAndArguments //fn CFStringCreateWithPascalString //fn CFStringCreateWithPascalStringNoCopy //fn CFStringCreateWithSubstring /* Searching Strings */ //fn CFStringCreateArrayWithFindResults //fn CFStringFind //fn CFStringFindCharacterFromSet //fn CFStringFindWithOptions //fn CFStringFindWithOptionsAndLocale //fn CFStringGetLineBounds /* Comparing Strings */ //fn CFStringCompare //fn CFStringCompareWithOptions //fn CFStringCompareWithOptionsAndLocale //fn CFStringHasPrefix //fn CFStringHasSuffix /* Accessing Characters */ //fn CFStringCreateExternalRepresentation pub fn CFStringGetBytes(theString: CFStringRef, range: CFRange, encoding: CFStringEncoding, lossByte: u8, isExternalRepresentation: Boolean, buffer: *mut u8, maxBufLen: CFIndex, usedBufLen: *mut CFIndex) -> CFIndex; //fn CFStringGetCharacterAtIndex //fn CFStringGetCharacters //fn CFStringGetCharactersPtr //fn CFStringGetCharacterFromInlineBuffer pub fn CFStringGetCString(theString: CFStringRef, buffer: *mut c_char, bufferSize: CFIndex, encoding: CFStringEncoding) -> Boolean; pub fn CFStringGetCStringPtr(theString: CFStringRef, encoding: CFStringEncoding) -> *const c_char; pub fn CFStringGetLength(theString: CFStringRef) -> CFIndex; //fn CFStringGetPascalString //fn CFStringGetPascalStringPtr //fn CFStringGetRangeOfComposedCharactersAtIndex //fn CFStringInitInlineBuffer /* Working With Hyphenation */ //fn CFStringGetHyphenationLocationBeforeIndex //fn CFStringIsHyphenationAvailableForLocale /* Working With Encodings */ //fn CFStringConvertEncodingToIANACharSetName //fn CFStringConvertEncodingToNSStringEncoding //fn CFStringConvertEncodingToWindowsCodepage //fn CFStringConvertIANACharSetNameToEncoding //fn CFStringConvertNSStringEncodingToEncoding //fn CFStringConvertWindowsCodepageToEncoding //fn CFStringGetFastestEncoding //fn CFStringGetListOfAvailableEncodings //fn CFStringGetMaximumSizeForEncoding //fn CFStringGetMostCompatibleMacStringEncoding //fn CFStringGetNameOfEncoding //fn CFStringGetSmallestEncoding //fn CFStringGetSystemEncoding //fn CFStringIsEncodingAvailable /* Getting Numeric Values */ //fn CFStringGetDoubleValue //fn CFStringGetIntValue /* Getting String Properties */ //fn CFShowStr pub fn CFStringGetTypeID() -> CFTypeID; /* String File System Representations */ //fn CFStringCreateWithFileSystemRepresentation //fn CFStringGetFileSystemRepresentation //fn CFStringGetMaximumSizeOfFileSystemRepresentation /* Getting Paragraph Bounds */ //fn CFStringGetParagraphBounds /* Managing Surrogates */ //fn CFStringGetLongCharacterForSurrogatePair //fn CFStringGetSurrogatePairForLongCharacter //fn CFStringIsSurrogateHighCharacter //fn CFStringIsSurrogateLowCharacter } vendor/core-foundation-sys-0.5.1/src/timezone.rs0000644000000000000000000000176213264166600020421 0ustar rootroot// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use libc::c_void; use base::{CFAllocatorRef, CFTypeID}; use date::{CFTimeInterval, CFAbsoluteTime}; #[repr(C)] pub struct __CFTimeZone(c_void); pub type CFTimeZoneRef = *const __CFTimeZone; extern { pub fn CFTimeZoneCopySystem() -> CFTimeZoneRef; pub fn CFTimeZoneCopyDefault() -> CFTimeZoneRef; pub fn CFTimeZoneCreateWithTimeIntervalFromGMT(allocator: CFAllocatorRef, interval: CFTimeInterval) -> CFTimeZoneRef; pub fn CFTimeZoneGetSecondsFromGMT(tz: CFTimeZoneRef, time: CFAbsoluteTime) -> CFTimeInterval; pub fn CFTimeZoneGetTypeID() -> CFTypeID; } vendor/core-foundation-sys-0.5.1/src/url.rs0000644000000000000000000001770313264166600017373 0ustar rootroot// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use libc::c_void; use base::{CFOptionFlags, CFIndex, CFAllocatorRef, Boolean, CFTypeID, CFTypeRef, SInt32}; use string::{CFStringRef, CFStringEncoding}; use error::CFErrorRef; #[repr(C)] pub struct __CFURL(c_void); pub type CFURLRef = *const __CFURL; pub type CFURLBookmarkCreationOptions = CFOptionFlags; pub type CFURLPathStyle = CFIndex; /* typedef CF_ENUM(CFIndex, CFURLPathStyle) */ pub const kCFURLPOSIXPathStyle: CFURLPathStyle = 0; pub const kCFURLHFSPathStyle: CFURLPathStyle = 1; pub const kCFURLWindowsPathStyle: CFURLPathStyle = 2; // static kCFURLBookmarkCreationPreferFileIDResolutionMask: CFURLBookmarkCreationOptions = // (1 << 8) as u32; // static kCFURLBookmarkCreationMinimalBookmarkMask: CFURLBookmarkCreationOptions = // (1 << 9) as u32; // static kCFURLBookmarkCreationSuitableForBookmarkFile: CFURLBookmarkCreationOptions = // (1 << 10) as u32; // static kCFURLBookmarkCreationWithSecurityScope: CFURLBookmarkCreationOptions = // (1 << 11) as u32; // static kCFURLBookmarkCreationSecurityScopeAllowOnlyReadAccess: CFURLBookmarkCreationOptions = // (1 << 12) as u32; // TODO: there are a lot of missing keys and constants. Add if you are bored or need them. extern { /* * CFURL.h */ /* Common File System Resource Keys */ pub static kCFURLAttributeModificationDateKey: CFStringRef; pub static kCFURLContentAccessDateKey: CFStringRef; pub static kCFURLContentModificationDateKey: CFStringRef; pub static kCFURLCreationDateKey: CFStringRef; pub static kCFURLFileResourceIdentifierKey: CFStringRef; pub static kCFURLFileSecurityKey: CFStringRef; pub static kCFURLHasHiddenExtensionKey: CFStringRef; pub static kCFURLIsDirectoryKey: CFStringRef; pub static kCFURLIsExecutableKey: CFStringRef; pub static kCFURLIsHiddenKey: CFStringRef; pub static kCFURLIsPackageKey: CFStringRef; pub static kCFURLIsReadableKey: CFStringRef; pub static kCFURLIsRegularFileKey: CFStringRef; pub static kCFURLIsSymbolicLinkKey: CFStringRef; pub static kCFURLIsSystemImmutableKey: CFStringRef; pub static kCFURLIsUserImmutableKey: CFStringRef; pub static kCFURLIsVolumeKey: CFStringRef; pub static kCFURLIsWritableKey: CFStringRef; pub static kCFURLLabelNumberKey: CFStringRef; pub static kCFURLLinkCountKey: CFStringRef; pub static kCFURLLocalizedLabelKey: CFStringRef; pub static kCFURLLocalizedNameKey: CFStringRef; pub static kCFURLLocalizedTypeDescriptionKey: CFStringRef; pub static kCFURLNameKey: CFStringRef; pub static kCFURLParentDirectoryURLKey: CFStringRef; pub static kCFURLPreferredIOBlockSizeKey: CFStringRef; pub static kCFURLTypeIdentifierKey: CFStringRef; pub static kCFURLVolumeIdentifierKey: CFStringRef; pub static kCFURLVolumeURLKey: CFStringRef; #[cfg(feature="mac_os_10_8_features")] #[cfg_attr(feature = "mac_os_10_7_support", linkage = "extern_weak")] pub static kCFURLIsExcludedFromBackupKey: CFStringRef; pub static kCFURLFileResourceTypeKey: CFStringRef; /* Creating a CFURL */ pub fn CFURLCopyAbsoluteURL(anURL: CFURLRef) -> CFURLRef; //fn CFURLCreateAbsoluteURLWithBytes //fn CFURLCreateByResolvingBookmarkData //fn CFURLCreateCopyAppendingPathComponent //fn CFURLCreateCopyAppendingPathExtension //fn CFURLCreateCopyDeletingLastPathComponent //fn CFURLCreateCopyDeletingPathExtension pub fn CFURLCreateFilePathURL(allocator: CFAllocatorRef, url: CFURLRef, error: *mut CFErrorRef) -> CFURLRef; //fn CFURLCreateFileReferenceURL pub fn CFURLCreateFromFileSystemRepresentation(allocator: CFAllocatorRef, buffer: *const u8, bufLen: CFIndex, isDirectory: Boolean) -> CFURLRef; //fn CFURLCreateFromFileSystemRepresentationRelativeToBase //fn CFURLCreateFromFSRef pub fn CFURLCreateWithBytes(allocator: CFAllocatorRef, URLBytes: *const u8, length: CFIndex, encoding: CFStringEncoding, baseURL: CFURLRef) -> CFURLRef; pub fn CFURLCreateWithFileSystemPath(allocator: CFAllocatorRef, filePath: CFStringRef, pathStyle: CFURLPathStyle, isDirectory: Boolean) -> CFURLRef; pub fn CFURLCreateWithFileSystemPathRelativeToBase(allocator: CFAllocatorRef, filePath: CFStringRef, pathStyle: CFURLPathStyle, isDirectory: Boolean, baseURL: CFURLRef) -> CFURLRef; //fn CFURLCreateWithString(allocator: CFAllocatorRef, urlString: CFStringRef, // baseURL: CFURLRef) -> CFURLRef; /* Accessing the Parts of a URL */ pub fn CFURLCanBeDecomposed(anURL: CFURLRef) -> Boolean; pub fn CFURLCopyFileSystemPath(anURL: CFURLRef, pathStyle: CFURLPathStyle) -> CFStringRef; pub fn CFURLCopyFragment(anURL: CFURLRef, charactersToLeaveEscaped: CFStringRef) -> CFStringRef; pub fn CFURLCopyHostName(anURL: CFURLRef) -> CFStringRef; pub fn CFURLCopyLastPathComponent(anURL: CFURLRef) -> CFStringRef; pub fn CFURLCopyNetLocation(anURL: CFURLRef) -> CFStringRef; pub fn CFURLCopyParameterString(anURL: CFURLRef, charactersToLeaveEscaped: CFStringRef) -> CFStringRef; pub fn CFURLCopyPassword(anURL: CFURLRef) -> CFStringRef; pub fn CFURLCopyPath(anURL: CFURLRef) -> CFStringRef; pub fn CFURLCopyPathExtension(anURL: CFURLRef) -> CFStringRef; pub fn CFURLCopyQueryString(anURL: CFURLRef, charactersToLeaveEscaped: CFStringRef) -> CFStringRef; pub fn CFURLCopyResourceSpecifier(anURL: CFURLRef) -> CFStringRef; pub fn CFURLCopyScheme(anURL: CFURLRef) -> CFStringRef; pub fn CFURLCopyStrictPath(anURL: CFURLRef, isAbsolute: *mut Boolean) -> CFStringRef; pub fn CFURLCopyUserName(anURL: CFURLRef) -> CFStringRef; pub fn CFURLGetPortNumber(anURL: CFURLRef) -> SInt32; pub fn CFURLHasDirectoryPath(anURL: CFURLRef) -> Boolean; /* Converting URLs to Other Representations */ //fn CFURLCreateData(allocator: CFAllocatorRef, url: CFURLRef, // encoding: CFStringEncoding, escapeWhitespace: bool) -> CFDataRef; //fn CFURLCreateStringByAddingPercentEscapes //fn CFURLCreateStringByReplacingPercentEscapes //fn CFURLCreateStringByReplacingPercentEscapesUsingEncoding pub fn CFURLGetFileSystemRepresentation(anURL: CFURLRef, resolveAgainstBase: Boolean, buffer: *mut u8, maxBufLen: CFIndex) -> Boolean; //fn CFURLGetFSRef pub fn CFURLGetString(anURL: CFURLRef) -> CFStringRef; /* Getting URL Properties */ //fn CFURLGetBaseURL(anURL: CFURLRef) -> CFURLRef; pub fn CFURLGetBytes(anURL: CFURLRef, buffer: *mut u8, bufferLength: CFIndex) -> CFIndex; //fn CFURLGetByteRangeForComponent pub fn CFURLGetTypeID() -> CFTypeID; //fn CFURLResourceIsReachable /* Getting and Setting File System Resource Properties */ pub fn CFURLClearResourcePropertyCache(url: CFURLRef); //fn CFURLClearResourcePropertyCacheForKey //fn CFURLCopyResourcePropertiesForKeys //fn CFURLCopyResourcePropertyForKey //fn CFURLCreateResourcePropertiesForKeysFromBookmarkData //fn CFURLCreateResourcePropertyForKeyFromBookmarkData //fn CFURLSetResourcePropertiesForKeys pub fn CFURLSetResourcePropertyForKey(url: CFURLRef, key: CFStringRef, value: CFTypeRef, error: *mut CFErrorRef) -> Boolean; //fn CFURLSetTemporaryResourcePropertyForKey /* Working with Bookmark Data */ //fn CFURLCreateBookmarkData //fn CFURLCreateBookmarkDataFromAliasRecord //fn CFURLCreateBookmarkDataFromFile //fn CFURLWriteBookmarkDataToFile //fn CFURLStartAccessingSecurityScopedResource //fn CFURLStopAccessingSecurityScopedResource } #[test] #[cfg(feature="mac_os_10_8_features")] fn can_see_excluded_from_backup_key() { let _ = unsafe { kCFURLIsExcludedFromBackupKey }; } vendor/core-foundation-sys-0.5.1/src/uuid.rs0000644000000000000000000000236613264166600017536 0ustar rootroot// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use libc::c_void; use base::{CFAllocatorRef, CFTypeID}; #[repr(C)] pub struct __CFUUID(c_void); pub type CFUUIDRef = *const __CFUUID; #[repr(C)] #[derive(Clone, Copy, Default)] pub struct CFUUIDBytes { pub byte0: u8, pub byte1: u8, pub byte2: u8, pub byte3: u8, pub byte4: u8, pub byte5: u8, pub byte6: u8, pub byte7: u8, pub byte8: u8, pub byte9: u8, pub byte10: u8, pub byte11: u8, pub byte12: u8, pub byte13: u8, pub byte14: u8, pub byte15: u8 } extern { /* * CFUUID.h */ pub fn CFUUIDCreate(allocator: CFAllocatorRef) -> CFUUIDRef; pub fn CFUUIDCreateFromUUIDBytes(allocator: CFAllocatorRef, bytes: CFUUIDBytes) -> CFUUIDRef; pub fn CFUUIDGetUUIDBytes(uuid: CFUUIDRef) -> CFUUIDBytes; pub fn CFUUIDGetTypeID() -> CFTypeID; } vendor/crossbeam-0.3.2/0000755000000000000000000000000013264166600013471 5ustar rootrootvendor/crossbeam-0.3.2/.cargo-checksum.json0000644000000000000000000000013113264166600017330 0ustar rootroot{"files":{},"package":"24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19"}vendor/crossbeam-0.3.2/.travis.yml0000664000000000000000000000141413264166600015604 0ustar rootrootlanguage: rust # necessary for `travis-cargo coveralls --no-sudo` addons: apt: packages: - libcurl4-openssl-dev - libelf-dev - libdw-dev # run builds for all the trains (and more) rust: - nightly - beta - stable # load travis-cargo before_script: - | pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH # the main build script: - | travis-cargo build && travis-cargo test && travis-cargo test -- --release && travis-cargo run -- --bin bench --release && travis-cargo --only stable doc env: global: # override the default `--features unstable` used for the nightly branch (optional) - TRAVIS_CARGO_NIGHTLY_FEATURE=nightly notifications: email: on_success: never vendor/crossbeam-0.3.2/CHANGELOG.md0000664000000000000000000000136413264166600015310 0ustar rootroot# Version 0.3 - Introduced `ScopedThreadBuilder` with the ability to name threads and set stack size - `Worker` methods in the Chase-Lev deque don't require mutable access anymore - Fixed a bug when unblocking `pop()` in `MsQueue` - Implemented `Drop` for `MsQueue`, `SegQueue`, and `TreiberStack` - Implemented `Default` for `TreiberStack` - Added `is_empty` to `SegQueue` - Renamed `mem::epoch` to `epoch` - Other bug fixes # Version 0.2 - Changed existing non-blocking `pop` methods to `try_pop` - Added blocking `pop` support to Michael-Scott queue - Added Chase-Lev work-stealing deque # Version 0.1 - Added [epoch-based memory management](http://aturon.github.io/blog/2015/08/27/epoch/) - Added Michael-Scott queue - Added Segmented array queue vendor/crossbeam-0.3.2/Cargo.toml0000644000000000000000000000171713264166600015427 0ustar rootroot# 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 = "crossbeam" version = "0.3.2" authors = ["Aaron Turon "] description = "Support for lock-free data structures, synchronizers, and parallel programming" documentation = "https://docs.rs/crossbeam" readme = "README.md" categories = ["concurrency", "data-structures"] license = "Apache-2.0/MIT" repository = "https://github.com/crossbeam-rs/crossbeam" [dev-dependencies.rand] version = "0.3" [features] nightly = [] vendor/crossbeam-0.3.2/LICENSE-APACHE0000664000000000000000000002513713264166600015427 0ustar rootroot 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. vendor/crossbeam-0.3.2/LICENSE-MIT0000664000000000000000000000205713264166600015133 0ustar rootrootCopyright (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. vendor/crossbeam-0.3.2/README.md0000664000000000000000000000336213264166600014756 0ustar rootroot# Notice This crate is outdated. The Crossbeam project is currently in a transition period. We are rewriting the epoch garbage collector, as well as several other utilities and adding new structures. To follow the progress, please take a look at other crates in the project [here](https://github.com/crossbeam-rs). When the transition is complete, this crate will be updated to use the new code. # Crossbeam: support for concurrent and parallel programming [![Build Status](https://travis-ci.org/crossbeam-rs/crossbeam.svg?branch=master)](https://travis-ci.org/crossbeam-rs/crossbeam) This crate is an early work in progress. The focus for the moment is concurrency: - **Non-blocking data structures**. These data structures allow for high performance, highly-concurrent access, much superior to wrapping with a `Mutex`. Ultimately the goal is to include stacks, queues, deques, bags, sets and maps. - **Memory management**. Because non-blocking data structures avoid global synchronization, it is not easy to tell when internal data can be safely freed. The `epoch` module provides generic, easy to use, and high-performance APIs for managing memory in these cases. - **Synchronization**. The standard library provides a few synchronization primitives (locks, barriers, etc) but this crate seeks to expand that set to include more advanced/niche primitives, as well as userspace alternatives. - **Scoped thread API**. Finally, the crate provides a "scoped" thread API, making it possible to spawn threads that share stack data with their parents. # Usage To use Crossbeam, add this to your `Cargo.toml`: ```toml [dependencies] crossbeam = "0.3.0" ``` For examples of what Crossbeam is capable of, see the [documentation][docs]. [docs]: https://docs.rs/crossbeam/ vendor/crossbeam-0.3.2/src/0000755000000000000000000000000013264166600014260 5ustar rootrootvendor/crossbeam-0.3.2/src/bin/0000755000000000000000000000000013264166600015030 5ustar rootrootvendor/crossbeam-0.3.2/src/bin/bench.rs0000664000000000000000000000776113264166600016472 0ustar rootrootextern crate crossbeam; use std::collections::VecDeque; use std::sync::Mutex; use std::sync::mpsc::channel; use std::time::Duration; use crossbeam::scope; use crossbeam::sync::MsQueue; use crossbeam::sync::SegQueue; use extra_impls::mpsc_queue::Queue as MpscQueue; mod extra_impls; const COUNT: u64 = 10000000; const THREADS: u64 = 2; fn time(f: F) -> Duration { let start = ::std::time::Instant::now(); f(); start.elapsed() } fn nanos(d: Duration) -> f64 { d.as_secs() as f64 * 1000000000f64 + (d.subsec_nanos() as f64) } trait Queue { fn push(&self, T); fn try_pop(&self) -> Option; } impl Queue for MsQueue { fn push(&self, t: T) { self.push(t) } fn try_pop(&self) -> Option { self.try_pop() } } impl Queue for SegQueue { fn push(&self, t: T) { self.push(t) } fn try_pop(&self) -> Option { self.try_pop() } } impl Queue for MpscQueue { fn push(&self, t: T) { self.push(t) } fn try_pop(&self) -> Option { use extra_impls::mpsc_queue::*; loop { match self.pop() { Data(t) => return Some(t), Empty => return None, Inconsistent => (), } } } } impl Queue for Mutex> { fn push(&self, t: T) { self.lock().unwrap().push_back(t) } fn try_pop(&self) -> Option { self.lock().unwrap().pop_front() } } fn bench_queue_mpsc + Sync>(q: Q) -> f64 { let d = time(|| { scope(|scope| { for _i in 0..THREADS { let qr = &q; scope.spawn(move || { for x in 0..COUNT { let _ = qr.push(x); } }); } let mut count = 0; while count < COUNT*THREADS { if q.try_pop().is_some() { count += 1; } } }); }); nanos(d) / ((COUNT * THREADS) as f64) } fn bench_queue_mpmc + Sync>(q: Q) -> f64 { use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering::Relaxed; let prod_count = AtomicUsize::new(0); let d = time(|| { scope(|scope| { for _i in 0..THREADS { let qr = &q; let pcr = &prod_count; scope.spawn(move || { for _x in 0..COUNT { qr.push(true); } if pcr.fetch_add(1, Relaxed) == (THREADS as usize) - 1 { for _x in 0..THREADS { qr.push(false) } } }); scope.spawn(move || { loop { if let Some(false) = qr.try_pop() { break } } }); } }); }); nanos(d) / ((COUNT * THREADS) as f64) } fn bench_chan_mpsc() -> f64 { let (tx, rx) = channel(); let d = time(|| { scope(|scope| { for _i in 0..THREADS { let my_tx = tx.clone(); scope.spawn(move || { for x in 0..COUNT { let _ = my_tx.send(x); } }); } for _i in 0..COUNT*THREADS { let _ = rx.recv().unwrap(); } }); }); nanos(d) / ((COUNT * THREADS) as f64) } fn main() { println!("MSQ mpsc: {}", bench_queue_mpsc(MsQueue::new())); println!("chan mpsc: {}", bench_chan_mpsc()); println!("mpsc mpsc: {}", bench_queue_mpsc(MpscQueue::new())); println!("Seg mpsc: {}", bench_queue_mpsc(SegQueue::new())); println!("MSQ mpmc: {}", bench_queue_mpmc(MsQueue::new())); println!("Seg mpmc: {}", bench_queue_mpmc(SegQueue::new())); // println!("queue_mpsc: {}", bench_queue_mpsc()); // println!("queue_mpmc: {}", bench_queue_mpmc()); // println!("mutex_mpmc: {}", bench_mutex_mpmc()); } vendor/crossbeam-0.3.2/src/bin/extra_impls/0000755000000000000000000000000013264166600017357 5ustar rootrootvendor/crossbeam-0.3.2/src/bin/extra_impls/mod.rs0000664000000000000000000000002413264166600020502 0ustar rootrootpub mod mpsc_queue; vendor/crossbeam-0.3.2/src/bin/extra_impls/mpsc_queue.rs0000664000000000000000000001302413264166600022075 0ustar rootroot/* Copyright (c) 2010-2011 Dmitry Vyukov. All rights reserved. * 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. * * THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "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 DMITRY VYUKOV OR CONTRIBUTORS 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 views and conclusions contained in the software and documentation are * those of the authors and should not be interpreted as representing official * policies, either expressed or implied, of Dmitry Vyukov. */ //! A mostly lock-free multi-producer, single consumer queue. //! //! This module contains an implementation of a concurrent MPSC queue. This //! queue can be used to share data between threads, and is also used as the //! building block of channels in rust. //! //! Note that the current implementation of this queue has a caveat of the `pop` //! method, and see the method for more information about it. Due to this //! caveat, this queue may not be appropriate for all use-cases. // http://www.1024cores.net/home/lock-free-algorithms // /queues/non-intrusive-mpsc-node-based-queue pub use self::PopResult::*; use std::fmt; use std::ptr; use std::cell::UnsafeCell; use std::sync::atomic::{AtomicPtr, Ordering}; /// A result of the `pop` function. #[derive(Debug)] pub enum PopResult { /// Some data has been popped Data(T), /// The queue is empty Empty, /// The queue is in an inconsistent state. Popping data should succeed, but /// some pushers have yet to make enough progress in order allow a pop to /// succeed. It is recommended that a pop() occur "in the near future" in /// order to see if the sender has made progress or not Inconsistent, } #[derive(Debug)] struct Node { next: AtomicPtr>, value: Option, } /// The multi-producer single-consumer structure. This is not cloneable, but it /// may be safely shared so long as it is guaranteed that there is only one /// popper at a time (many pushers are allowed). pub struct Queue { head: AtomicPtr>, tail: UnsafeCell<*mut Node>, } impl fmt::Debug for Queue { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Queue {{ ... }}") } } unsafe impl Send for Queue { } unsafe impl Sync for Queue { } impl Node { unsafe fn new(v: Option) -> *mut Node { Box::into_raw(Box::new(Node { next: AtomicPtr::new(ptr::null_mut()), value: v, })) } } impl Queue { /// Creates a new queue that is safe to share among multiple producers and /// one consumer. pub fn new() -> Queue { let stub = unsafe { Node::new(None) }; Queue { head: AtomicPtr::new(stub), tail: UnsafeCell::new(stub), } } /// Pushes a new value onto this queue. pub fn push(&self, t: T) { unsafe { let n = Node::new(Some(t)); let prev = self.head.swap(n, Ordering::AcqRel); (*prev).next.store(n, Ordering::Release); } } /// Pops some data from this queue. /// /// Note that the current implementation means that this function cannot /// return `Option`. It is possible for this queue to be in an /// inconsistent state where many pushes have succeeded and completely /// finished, but pops cannot return `Some(t)`. This inconsistent state /// happens when a pusher is pre-empted at an inopportune moment. /// /// This inconsistent state means that this queue does indeed have data, but /// it does not currently have access to it at this time. pub fn pop(&self) -> PopResult { unsafe { let tail = *self.tail.get(); let next = (*tail).next.load(Ordering::Acquire); if !next.is_null() { *self.tail.get() = next; assert!((*tail).value.is_none()); assert!((*next).value.is_some()); let ret = (*next).value.take().unwrap(); let _ = Box::from_raw(tail); return Data(ret); } if self.head.load(Ordering::Acquire) == tail {Empty} else {Inconsistent} } } } impl Drop for Queue { fn drop(&mut self) { unsafe { let mut cur = *self.tail.get(); while !cur.is_null() { let next = (*cur).next.load(Ordering::Relaxed); let _ = Box::from_raw(cur); cur = next; } } } } vendor/crossbeam-0.3.2/src/bin/stress-msq.rs0000664000000000000000000000150613264166600017523 0ustar rootrootextern crate crossbeam; use crossbeam::sync::MsQueue; use crossbeam::scope; use std::sync::Arc; const DUP: usize = 4; const THREADS: u32 = 2; const COUNT: u64 = 100000; fn main() { scope(|s| { for _i in 0..DUP { let q = Arc::new(MsQueue::new()); let qs = q.clone(); s.spawn(move || { for i in 1..COUNT { qs.push(i) } }); for _i in 0..THREADS { let qr = q.clone(); s.spawn(move || { let mut cur: u64 = 0; for _j in 0..COUNT { if let Some(new) = qr.try_pop() { assert!(new > cur); cur = new; } } }); } } }); } vendor/crossbeam-0.3.2/src/cache_padded.rs0000664000000000000000000001064513264166600017202 0ustar rootrootuse std::marker; use std::cell::UnsafeCell; use std::fmt; use std::mem; use std::ptr; use std::ops::{Deref, DerefMut}; // For now, treat this as an arch-independent constant. const CACHE_LINE: usize = 32; #[cfg_attr(feature = "nightly", repr(simd))] #[derive(Debug)] struct Padding(u64, u64, u64, u64); /// Pad `T` to the length of a cacheline. /// /// Sometimes concurrent programming requires a piece of data to be padded out /// to the size of a cacheline to avoid "false sharing": cachelines being /// invalidated due to unrelated concurrent activity. Use the `CachePadded` type /// when you want to *avoid* cache locality. /// /// At the moment, cache lines are assumed to be 32 * sizeof(usize) on all /// architectures. /// /// **Warning**: the wrapped data is never dropped; move out using `ptr::read` /// if you need to run dtors. pub struct CachePadded { data: UnsafeCell<[usize; CACHE_LINE]>, _marker: ([Padding; 0], marker::PhantomData), } impl fmt::Debug for CachePadded { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "CachePadded {{ ... }}") } } unsafe impl Send for CachePadded {} unsafe impl Sync for CachePadded {} #[cfg(not(feature = "nightly"))] macro_rules! declare_zeros_valid { () => { /// Types for which mem::zeroed() is safe. /// /// If a type `T: ZerosValid`, then a sequence of zeros the size of `T` must be /// a valid member of the type `T`. pub unsafe trait ZerosValid {} } } #[cfg(feature = "nightly")] macro_rules! declare_zeros_valid { () => { /// Types for which mem::zeroed() is safe. /// /// If a type `T: ZerosValid`, then a sequence of zeros the size of `T` must be /// a valid member of the type `T`. pub unsafe auto trait ZerosValid {} } } declare_zeros_valid!(); macro_rules! zeros_valid { ($( $T:ty )*) => ($( unsafe impl ZerosValid for $T {} )*)} zeros_valid!(u8 u16 u32 u64 usize); zeros_valid!(i8 i16 i32 i64 isize); unsafe impl ZerosValid for ::std::sync::atomic::AtomicUsize {} unsafe impl ZerosValid for ::std::sync::atomic::AtomicPtr {} impl CachePadded { /// A const fn equivalent to mem::zeroed(). #[cfg(not(feature = "nightly"))] pub fn zeroed() -> CachePadded { CachePadded { data: UnsafeCell::new(([0; CACHE_LINE])), _marker: ([], marker::PhantomData), } } /// A const fn equivalent to mem::zeroed(). #[cfg(feature = "nightly")] pub const fn zeroed() -> CachePadded { CachePadded { data: UnsafeCell::new(([0; CACHE_LINE])), _marker: ([], marker::PhantomData), } } } #[inline] /// Assert that the size and alignment of `T` are consistent with `CachePadded`. fn assert_valid() { assert!(mem::size_of::() <= mem::size_of::>()); assert!(mem::align_of::() <= mem::align_of::>()); } impl CachePadded { /// Wrap `t` with cacheline padding. /// /// **Warning**: the wrapped data is never dropped; move out using /// `ptr:read` if you need to run dtors. pub fn new(t: T) -> CachePadded { assert_valid::(); let ret = CachePadded { data: UnsafeCell::new(([0; CACHE_LINE])), _marker: ([], marker::PhantomData), }; unsafe { let p: *mut T = mem::transmute(&ret.data); ptr::write(p, t); } ret } } impl Deref for CachePadded { type Target = T; fn deref(&self) -> &T { assert_valid::(); unsafe { mem::transmute(&self.data) } } } impl DerefMut for CachePadded { fn deref_mut(&mut self) -> &mut T { assert_valid::(); unsafe { mem::transmute(&mut self.data) } } } // FIXME: support Drop by pulling out a version usable for statics /* impl Drop for CachePadded { fn drop(&mut self) { assert_valid::(); let p: *mut T = mem::transmute(&self.data); mem::drop(ptr::read(p)); } } */ #[cfg(test)] mod test { use super::*; #[test] fn cache_padded_store_u64() { let x: CachePadded = CachePadded::new(17); assert_eq!(*x, 17); } #[test] fn cache_padded_store_pair() { let x: CachePadded<(u64, u64)> = CachePadded::new((17, 37)); assert_eq!(x.0, 17); assert_eq!(x.1, 37); } } vendor/crossbeam-0.3.2/src/epoch/0000755000000000000000000000000013264166600015356 5ustar rootrootvendor/crossbeam-0.3.2/src/epoch/atomic.rs0000664000000000000000000001441513264166600017207 0ustar rootrootuse std::marker::PhantomData; use std::mem; use std::ptr; use std::sync::atomic::{self, Ordering}; use super::{Owned, Shared, Guard}; /// Like `std::sync::atomic::AtomicPtr`. /// /// Provides atomic access to a (nullable) pointer of type `T`, interfacing with /// the `Owned` and `Shared` types. #[derive(Debug)] pub struct Atomic { ptr: atomic::AtomicPtr, _marker: PhantomData<*const ()>, } unsafe impl Send for Atomic {} unsafe impl Sync for Atomic {} fn opt_shared_into_raw(val: Option>) -> *mut T { val.map(|p| p.as_raw()).unwrap_or(ptr::null_mut()) } fn opt_owned_as_raw(val: &Option>) -> *mut T { val.as_ref().map(Owned::as_raw).unwrap_or(ptr::null_mut()) } fn opt_owned_into_raw(val: Option>) -> *mut T { let ptr = val.as_ref().map(Owned::as_raw).unwrap_or(ptr::null_mut()); mem::forget(val); ptr } impl Atomic { /// Create a new, null atomic pointer. #[cfg(feature = "nightly")] pub const fn null() -> Atomic { Atomic { ptr: atomic::AtomicPtr::new(0 as *mut _), _marker: PhantomData } } #[cfg(not(feature = "nightly"))] pub fn null() -> Atomic { Atomic { ptr: atomic::AtomicPtr::new(0 as *mut _), _marker: PhantomData } } /// Create a new atomic pointer pub fn new(data: T) -> Atomic { Atomic { ptr: atomic::AtomicPtr::new(Box::into_raw(Box::new(data))), _marker: PhantomData } } /// Do an atomic load with the given memory ordering. /// /// In order to perform the load, we must pass in a borrow of a /// `Guard`. This is a way of guaranteeing that the thread has pinned the /// epoch for the entire lifetime `'a`. In return, you get an optional /// `Shared` pointer back (`None` if the `Atomic` is currently null), with /// lifetime tied to the guard. /// /// # Panics /// /// Panics if `ord` is `Release` or `AcqRel`. pub fn load<'a>(&self, ord: Ordering, _: &'a Guard) -> Option> { unsafe { Shared::from_raw(self.ptr.load(ord)) } } /// Do an atomic store with the given memory ordering. /// /// Transfers ownership of the given `Owned` pointer, if any. Since no /// lifetime information is acquired, no `Guard` value is needed. /// /// # Panics /// /// Panics if `ord` is `Acquire` or `AcqRel`. pub fn store(&self, val: Option>, ord: Ordering) { self.ptr.store(opt_owned_into_raw(val), ord) } /// Do an atomic store with the given memory ordering, immediately yielding /// a shared reference to the pointer that was stored. /// /// Transfers ownership of the given `Owned` pointer, yielding a `Shared` /// reference to it. Since the reference is valid only for the curent epoch, /// it's lifetime is tied to a `Guard` value. /// /// # Panics /// /// Panics if `ord` is `Acquire` or `AcqRel`. pub fn store_and_ref<'a>(&self, val: Owned, ord: Ordering, _: &'a Guard) -> Shared<'a, T> { unsafe { let shared = Shared::from_owned(val); self.store_shared(Some(shared), ord); shared } } /// Do an atomic store of a `Shared` pointer with the given memory ordering. /// /// This operation does not require a guard, because it does not yield any /// new information about the lifetime of a pointer. /// /// # Panics /// /// Panics if `ord` is `Acquire` or `AcqRel`. pub fn store_shared(&self, val: Option>, ord: Ordering) { self.ptr.store(opt_shared_into_raw(val), ord) } /// Do a compare-and-set from a `Shared` to an `Owned` pointer with the /// given memory ordering. /// /// As with `store`, this operation does not require a guard; it produces no new /// lifetime information. The `Result` indicates whether the CAS succeeded; if /// not, ownership of the `new` pointer is returned to the caller. pub fn cas(&self, old: Option>, new: Option>, ord: Ordering) -> Result<(), Option>> { if self.ptr.compare_and_swap(opt_shared_into_raw(old), opt_owned_as_raw(&new), ord) == opt_shared_into_raw(old) { mem::forget(new); Ok(()) } else { Err(new) } } /// Do a compare-and-set from a `Shared` to an `Owned` pointer with the /// given memory ordering, immediatley acquiring a new `Shared` reference to /// the previously-owned pointer if successful. /// /// This operation is analogous to `store_and_ref`. pub fn cas_and_ref<'a>(&self, old: Option>, new: Owned, ord: Ordering, _: &'a Guard) -> Result, Owned> { if self.ptr.compare_and_swap(opt_shared_into_raw(old), new.as_raw(), ord) == opt_shared_into_raw(old) { Ok(unsafe { Shared::from_owned(new) }) } else { Err(new) } } /// Do a compare-and-set from a `Shared` to another `Shared` pointer with /// the given memory ordering. /// /// The boolean return value is `true` when the CAS is successful. pub fn cas_shared(&self, old: Option>, new: Option>, ord: Ordering) -> bool { self.ptr.compare_and_swap(opt_shared_into_raw(old), opt_shared_into_raw(new), ord) == opt_shared_into_raw(old) } /// Do an atomic swap with an `Owned` pointer with the given memory ordering. pub fn swap<'a>(&self, new: Option>, ord: Ordering, _: &'a Guard) -> Option> { unsafe { Shared::from_raw(self.ptr.swap(opt_owned_into_raw(new), ord)) } } /// Do an atomic swap with a `Shared` pointer with the given memory ordering. pub fn swap_shared<'a>(&self, new: Option>, ord: Ordering, _: &'a Guard) -> Option> { unsafe { Shared::from_raw(self.ptr.swap(opt_shared_into_raw(new), ord)) } } } vendor/crossbeam-0.3.2/src/epoch/garbage.rs0000664000000000000000000000706213264166600017323 0ustar rootroot// Data structures for storing garbage to be freed later (once the // epochs have sufficiently advanced). // // In general, we try to manage the garbage thread locally whenever // possible. Each thread keep track of three bags of garbage. But if a // thread is exiting, these bags must be moved into the global garbage // bags. use std::ptr; use std::mem; use std::sync::atomic::AtomicPtr; use std::sync::atomic::Ordering::{Relaxed, Release, Acquire}; use ZerosValid; /// One item of garbage. /// /// Stores enough information to do a deallocation. #[derive(Debug)] struct Item { ptr: *mut u8, free: unsafe fn(*mut u8), } /// A single, thread-local bag of garbage. #[derive(Debug)] pub struct Bag(Vec); impl Bag { fn new() -> Bag { Bag(vec![]) } fn insert(&mut self, elem: *mut T) { let size = mem::size_of::(); if size > 0 { self.0.push(Item { ptr: elem as *mut u8, free: free::, }) } unsafe fn free(t: *mut u8) { drop(Vec::from_raw_parts(t as *mut T, 0, 1)); } } fn len(&self) -> usize { self.0.len() } /// Deallocate all garbage in the bag pub unsafe fn collect(&mut self) { let mut data = mem::replace(&mut self.0, Vec::new()); for item in data.iter() { (item.free)(item.ptr); } data.truncate(0); self.0 = data; } } // needed because the bags store raw pointers. unsafe impl Send for Bag {} unsafe impl Sync for Bag {} /// A thread-local set of garbage bags. #[derive(Debug)] pub struct Local { /// Garbage added at least one epoch behind the current local epoch pub old: Bag, /// Garbage added in the current local epoch or earlier pub cur: Bag, /// Garbage added in the current *global* epoch pub new: Bag, } impl Local { pub fn new() -> Local { Local { old: Bag::new(), cur: Bag::new(), new: Bag::new(), } } pub fn insert(&mut self, elem: *mut T) { self.new.insert(elem) } /// Collect one epoch of garbage, rotating the local garbage bags. pub unsafe fn collect(&mut self) { let ret = self.old.collect(); mem::swap(&mut self.old, &mut self.cur); mem::swap(&mut self.cur, &mut self.new); ret } pub fn size(&self) -> usize { self.old.len() + self.cur.len() + self.new.len() } } /// A concurrent garbage bag, currently based on Treiber's stack. /// /// The elements are themselves owned `Bag`s. #[derive(Debug)] pub struct ConcBag { head: AtomicPtr, } unsafe impl ZerosValid for ConcBag {} #[derive(Debug)] struct Node { data: Bag, next: AtomicPtr, } impl ConcBag { pub fn insert(&self, t: Bag){ let n = Box::into_raw(Box::new( Node { data: t, next: AtomicPtr::new(ptr::null_mut()) })); loop { let head = self.head.load(Acquire); unsafe { (*n).next.store(head, Relaxed) }; if self.head.compare_and_swap(head, n, Release) == head { break } } } pub unsafe fn collect(&self) { // check to avoid xchg instruction // when no garbage exists let mut head = self.head.load(Relaxed); if head != ptr::null_mut() { head = self.head.swap(ptr::null_mut(), Acquire); while head != ptr::null_mut() { let mut n = Box::from_raw(head); n.data.collect(); head = n.next.load(Relaxed); } } } } vendor/crossbeam-0.3.2/src/epoch/global.rs0000664000000000000000000000471613264166600017176 0ustar rootroot// Definition of global epoch state. The `get` function is the way to // access this data externally (until const fn is stabilized...). use std::sync::atomic::AtomicUsize; use CachePadded; use epoch::garbage; use epoch::participants::Participants; /// Global epoch state #[derive(Debug)] pub struct EpochState { /// Current global epoch pub epoch: CachePadded, // FIXME: move this into the `garbage` module, rationalize API /// Global garbage bags pub garbage: [CachePadded; 3], /// Participant list pub participants: Participants, } unsafe impl Send for EpochState {} unsafe impl Sync for EpochState {} pub use self::imp::get; #[cfg(not(feature = "nightly"))] mod imp { use std::mem; use std::sync::atomic::{self, AtomicUsize}; use std::sync::atomic::Ordering::Relaxed; use super::EpochState; use CachePadded; use epoch::participants::Participants; impl EpochState { fn new() -> EpochState { EpochState { epoch: CachePadded::zeroed(), garbage: [CachePadded::zeroed(), CachePadded::zeroed(), CachePadded::zeroed()], participants: Participants::new(), } } } static EPOCH: AtomicUsize = atomic::ATOMIC_USIZE_INIT; pub fn get() -> &'static EpochState { let mut addr = EPOCH.load(Relaxed); if addr == 0 { let boxed = Box::new(EpochState::new()); let raw = Box::into_raw(boxed); addr = EPOCH.compare_and_swap(0, raw as usize, Relaxed); if addr != 0 { let boxed = unsafe { Box::from_raw(raw) }; mem::drop(boxed); } else { addr = raw as usize; } } unsafe { &*(addr as *mut EpochState) } } } #[cfg(feature = "nightly")] mod imp { use super::EpochState; use CachePadded; use epoch::participants::Participants; impl EpochState { const fn new() -> EpochState { EpochState { epoch: CachePadded::zeroed(), garbage: [CachePadded::zeroed(), CachePadded::zeroed(), CachePadded::zeroed()], participants: Participants::new(), } } } static EPOCH: EpochState = EpochState::new(); pub fn get() -> &'static EpochState { &EPOCH } } vendor/crossbeam-0.3.2/src/epoch/guard.rs0000664000000000000000000000312413264166600017030 0ustar rootrootuse std::marker; use super::{local, Shared}; /// An RAII-style guard for pinning the current epoch. /// /// A guard must be acquired before most operations on an `Atomic` pointer. On /// destruction, it unpins the epoch. #[must_use] #[derive(Debug)] pub struct Guard { _marker: marker::PhantomData<*mut ()>, // !Send and !Sync } /// Pin the current epoch. /// /// Threads generally pin before interacting with a lock-free data /// structure. Pinning requires a full memory barrier, so is somewhat /// expensive. It is rentrant -- you can safely acquire nested guards, and only /// the first guard requires a barrier. Thus, in cases where you expect to /// perform several lock-free operations in quick succession, you may consider /// pinning around the entire set of operations. pub fn pin() -> Guard { local::with_participant(|p| { let entered = p.enter(); let g = Guard { _marker: marker::PhantomData, }; if entered && p.should_gc() { p.try_collect(&g); } g }) } impl Guard { /// Assert that the value is no longer reachable from a lock-free data /// structure and should be collected when sufficient epochs have passed. pub unsafe fn unlinked(&self, val: Shared) { local::with_participant(|p| p.reclaim(val.as_raw())) } /// Move the thread-local garbage into the global set of garbage. pub fn migrate_garbage(&self) { local::with_participant(|p| p.migrate_garbage()) } } impl Drop for Guard { fn drop(&mut self) { local::with_participant(|p| p.exit()); } } vendor/crossbeam-0.3.2/src/epoch/local.rs0000664000000000000000000000160313264166600017020 0ustar rootroot// Manage the thread-local state, providing access to a `Participant` record. use std::sync::atomic::Ordering::Relaxed; use epoch::participant::Participant; use epoch::global; #[derive(Debug)] struct LocalEpoch { participant: *const Participant, } impl LocalEpoch { fn new() -> LocalEpoch { LocalEpoch { participant: global::get().participants.enroll() } } fn get(&self) -> &Participant { unsafe { &*self.participant } } } // FIXME: avoid leaking when all threads have exited impl Drop for LocalEpoch { fn drop(&mut self) { let p = self.get(); p.enter(); p.migrate_garbage(); p.exit(); p.active.store(false, Relaxed); } } thread_local!(static LOCAL_EPOCH: LocalEpoch = LocalEpoch::new() ); pub fn with_participant(f: F) -> T where F: FnOnce(&Participant) -> T { LOCAL_EPOCH.with(|e| f(e.get())) } vendor/crossbeam-0.3.2/src/epoch/mod.rs0000664000000000000000000001703713264166600016515 0ustar rootroot//! Epoch-based memory management //! //! This module provides fast, easy to use memory management for lock free data //! structures. It's inspired by [Keir Fraser's *epoch-based //! reclamation*](https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-579.pdf). //! //! The basic problem this is solving is the fact that when one thread has //! removed a node from a data structure, other threads may still have pointers //! to that node (in the form of snapshots that will be validated through things //! like compare-and-swap), so the memory cannot be immediately freed. Put differently: //! //! 1. There are two sources of reachability at play -- the data structure, and //! the snapshots in threads accessing it. Before we delete a node, we need to know //! that it cannot be reached in either of these ways. //! //! 2. Once a node has been unlinked from the data structure, no *new* snapshots //! reaching it will be created. //! //! Using the epoch scheme is fairly straightforward, and does not require //! understanding any of the implementation details: //! //! - When operating on a shared data structure, a thread must "pin the current //! epoch", which is done by calling `pin()`. This function returns a `Guard` //! which unpins the epoch when destroyed. //! //! - When the thread subsequently reads from a lock-free data structure, the //! pointers it extracts act like references with lifetime tied to the //! `Guard`. This allows threads to safely read from snapshotted data, being //! guaranteed that the data will remain allocated until they exit the epoch. //! //! To put the `Guard` to use, Crossbeam provides a set of three pointer types meant to work together: //! //! - `Owned`, akin to `Box`, which points to uniquely-owned data that has //! not yet been published in a concurrent data structure. //! //! - `Shared<'a, T>`, akin to `&'a T`, which points to shared data that may or may //! not be reachable from a data structure, but it guaranteed not to be freed //! during lifetime `'a`. //! //! - `Atomic`, akin to `std::sync::atomic::AtomicPtr`, which provides atomic //! updates to a pointer using the `Owned` and `Shared` types, and connects them //! to a `Guard`. //! //! Each of these types provides further documentation on usage. //! //! # Example //! //! ``` //! use std::sync::atomic::Ordering::{Acquire, Release, Relaxed}; //! use std::ptr; //! //! use crossbeam::epoch::{self, Atomic, Owned}; //! //! struct TreiberStack { //! head: Atomic>, //! } //! //! struct Node { //! data: T, //! next: Atomic>, //! } //! //! impl TreiberStack { //! fn new() -> TreiberStack { //! TreiberStack { //! head: Atomic::null() //! } //! } //! //! fn push(&self, t: T) { //! // allocate the node via Owned //! let mut n = Owned::new(Node { //! data: t, //! next: Atomic::null(), //! }); //! //! // become active //! let guard = epoch::pin(); //! //! loop { //! // snapshot current head //! let head = self.head.load(Relaxed, &guard); //! //! // update `next` pointer with snapshot //! n.next.store_shared(head, Relaxed); //! //! // if snapshot is still good, link in the new node //! match self.head.cas_and_ref(head, n, Release, &guard) { //! Ok(_) => return, //! Err(owned) => n = owned, //! } //! } //! } //! //! fn pop(&self) -> Option { //! // become active //! let guard = epoch::pin(); //! //! loop { //! // take a snapshot //! match self.head.load(Acquire, &guard) { //! // the stack is non-empty //! Some(head) => { //! // read through the snapshot, *safely*! //! let next = head.next.load(Relaxed, &guard); //! //! // if snapshot is still good, update from `head` to `next` //! if self.head.cas_shared(Some(head), next, Release) { //! unsafe { //! // mark the node as unlinked //! guard.unlinked(head); //! //! // extract out the data from the now-unlinked node //! return Some(ptr::read(&(*head).data)) //! } //! } //! } //! //! // we observed the stack empty //! None => return None //! } //! } //! } //! } //! ``` // FIXME: document implementation details mod atomic; mod garbage; mod global; mod guard; mod local; mod participant; mod participants; pub use self::atomic::Atomic; pub use self::guard::{pin, Guard}; use std::ops::{Deref, DerefMut}; use std::ptr; use std::mem; /// Like `Box`: an owned, heap-allocated data value of type `T`. #[derive(Debug)] pub struct Owned { data: Box, } impl Owned { /// Move `t` to a new heap allocation. pub fn new(t: T) -> Owned { Owned { data: Box::new(t) } } fn as_raw(&self) -> *mut T { self.deref() as *const _ as *mut _ } /// Move data out of the owned box, deallocating the box. pub fn into_inner(self) -> T { *self.data } } impl Deref for Owned { type Target = T; fn deref(&self) -> &T { &self.data } } impl DerefMut for Owned { fn deref_mut(&mut self) -> &mut T { &mut self.data } } #[derive(PartialEq, Eq)] /// Like `&'a T`: a shared reference valid for lifetime `'a`. #[derive(Debug)] pub struct Shared<'a, T: 'a> { data: &'a T, } impl<'a, T> Copy for Shared<'a, T> {} impl<'a, T> Clone for Shared<'a, T> { fn clone(&self) -> Shared<'a, T> { Shared { data: self.data } } } impl<'a, T> Deref for Shared<'a, T> { type Target = &'a T; fn deref(&self) -> &&'a T { &self.data } } impl<'a, T> Shared<'a, T> { unsafe fn from_raw(raw: *mut T) -> Option> { if raw == ptr::null_mut() { None } else { Some(Shared { data: mem::transmute::<*mut T, &T>(raw) }) } } unsafe fn from_ref(r: &T) -> Shared<'a, T> { Shared { data: mem::transmute(r) } } unsafe fn from_owned(owned: Owned) -> Shared<'a, T> { let ret = Shared::from_ref(owned.deref()); mem::forget(owned); ret } pub fn as_raw(&self) -> *mut T { self.data as *const _ as *mut _ } } #[cfg(test)] mod test { use std::sync::atomic::Ordering; use super::*; use epoch; #[test] fn test_no_drop() { static mut DROPS: i32 = 0; struct Test; impl Drop for Test { fn drop(&mut self) { unsafe { DROPS += 1; } } } let g = pin(); let x = Atomic::null(); x.store(Some(Owned::new(Test)), Ordering::Relaxed); x.store_and_ref(Owned::new(Test), Ordering::Relaxed, &g); let y = x.load(Ordering::Relaxed, &g); let z = x.cas_and_ref(y, Owned::new(Test), Ordering::Relaxed, &g).ok(); let _ = x.cas(z, Some(Owned::new(Test)), Ordering::Relaxed); x.swap(Some(Owned::new(Test)), Ordering::Relaxed, &g); unsafe { assert_eq!(DROPS, 0); } } #[test] fn test_new() { let guard = epoch::pin(); let my_atomic = Atomic::new(42); assert_eq!(**my_atomic.load(Ordering::Relaxed, &guard).unwrap(), 42); } } vendor/crossbeam-0.3.2/src/epoch/participant.rs0000664000000000000000000001036413264166600020250 0ustar rootroot// Manages a single participant in the epoch scheme. This is where all // of the actual epoch management logic happens! use std::mem; use std::cell::UnsafeCell; use std::fmt; use std::sync::atomic::{self, AtomicUsize, AtomicBool}; use std::sync::atomic::Ordering::{Relaxed, Acquire, Release, SeqCst}; use epoch::{Atomic, Guard, garbage, global}; use epoch::participants::ParticipantNode; /// Thread-local data for epoch participation. pub struct Participant { /// The local epoch. epoch: AtomicUsize, /// Number of pending uses of `epoch::pin()`; keeping a count allows for /// reentrant use of epoch management. in_critical: AtomicUsize, /// Thread-local garbage tracking garbage: UnsafeCell, /// Is the thread still active? Becomes `false` when the thread exits. This /// is ultimately used to free `Participant` records. pub active: AtomicBool, /// The participant list is coded intrusively; here's the `next` pointer. pub next: Atomic, } impl fmt::Debug for Participant { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Participant {{ ... }}") } } unsafe impl Sync for Participant {} const GC_THRESH: usize = 32; impl Participant { pub fn new() -> Participant { Participant { epoch: AtomicUsize::new(0), in_critical: AtomicUsize::new(0), active: AtomicBool::new(true), garbage: UnsafeCell::new(garbage::Local::new()), next: Atomic::null(), } } /// Enter a critical section. /// /// This method is reentrant, allowing for nested critical sections. /// /// Returns `true` is this is the first entry on the stack (as opposed to a /// re-entrant call). pub fn enter(&self) -> bool { let new_count = self.in_critical.load(Relaxed) + 1; self.in_critical.store(new_count, Relaxed); if new_count > 1 { return false } atomic::fence(SeqCst); let global_epoch = global::get().epoch.load(Relaxed); if global_epoch != self.epoch.load(Relaxed) { self.epoch.store(global_epoch, Relaxed); unsafe { (*self.garbage.get()).collect(); } } true } /// Exit the current (nested) critical section. pub fn exit(&self) { let new_count = self.in_critical.load(Relaxed) - 1; self.in_critical.store( new_count, if new_count > 0 { Relaxed } else { Release }); } /// Begin the reclamation process for a piece of data. pub unsafe fn reclaim(&self, data: *mut T) { (*self.garbage.get()).insert(data); } /// Attempt to collect garbage by moving the global epoch forward. /// /// Returns `true` on success. pub fn try_collect(&self, guard: &Guard) -> bool { let cur_epoch = global::get().epoch.load(SeqCst); for p in global::get().participants.iter(guard) { if p.in_critical.load(Relaxed) > 0 && p.epoch.load(Relaxed) != cur_epoch { return false } } let new_epoch = cur_epoch.wrapping_add(1); atomic::fence(Acquire); if global::get().epoch.compare_and_swap(cur_epoch, new_epoch, SeqCst) != cur_epoch { return false } unsafe { (*self.garbage.get()).collect(); global::get().garbage[new_epoch.wrapping_add(1) % 3].collect(); } self.epoch.store(new_epoch, Release); true } /// Move the current thread-local garbage into the global garbage bags. pub fn migrate_garbage(&self) { let cur_epoch = self.epoch.load(Relaxed); let local = unsafe { mem::replace(&mut *self.garbage.get(), garbage::Local::new()) }; global::get().garbage[cur_epoch.wrapping_sub(1) % 3].insert(local.old); global::get().garbage[cur_epoch % 3].insert(local.cur); global::get().garbage[global::get().epoch.load(Relaxed) % 3].insert(local.new); } /// How much garbage is this participant currently storing? pub fn garbage_size(&self) -> usize { unsafe { (*self.garbage.get()).size() } } /// Is this participant past its local GC threshhold? pub fn should_gc(&self) -> bool { self.garbage_size() >= GC_THRESH } } vendor/crossbeam-0.3.2/src/epoch/participants.rs0000664000000000000000000000650713264166600020437 0ustar rootroot// Manages the global participant list, which is an intrustive list in // which items are lazily removed on traversal (after being // "logically" deleted by becoming inactive.) use std::mem; use std::ops::{Deref, DerefMut}; use std::sync::atomic::Ordering::{Relaxed, Acquire, Release}; use epoch::{Atomic, Owned, Guard}; use epoch::participant::Participant; use CachePadded; /// Global, threadsafe list of threads participating in epoch management. #[derive(Debug)] pub struct Participants { head: Atomic } #[derive(Debug)] pub struct ParticipantNode(CachePadded); impl ParticipantNode { pub fn new() -> ParticipantNode { ParticipantNode(CachePadded::new(Participant::new())) } } impl Deref for ParticipantNode { type Target = Participant; fn deref(&self) -> &Participant { &self.0 } } impl DerefMut for ParticipantNode { fn deref_mut(&mut self) -> &mut Participant { &mut self.0 } } impl Participants { #[cfg(not(feature = "nightly"))] pub fn new() -> Participants { Participants { head: Atomic::null() } } #[cfg(feature = "nightly")] pub const fn new() -> Participants { Participants { head: Atomic::null() } } /// Enroll a new thread in epoch management by adding a new `Particpant` /// record to the global list. pub fn enroll(&self) -> *const Participant { let mut participant = Owned::new(ParticipantNode::new()); // we ultimately use epoch tracking to free Participant nodes, but we // can't actually enter an epoch here, so fake it; we know the node // can't be removed until marked inactive anyway. let fake_guard = (); let g: &'static Guard = unsafe { mem::transmute(&fake_guard) }; loop { let head = self.head.load(Relaxed, g); participant.next.store_shared(head, Relaxed); match self.head.cas_and_ref(head, participant, Release, g) { Ok(shared) => { let shared: &Participant = &shared; return shared; } Err(owned) => { participant = owned; } } } } pub fn iter<'a>(&'a self, g: &'a Guard) -> Iter<'a> { Iter { guard: g, next: &self.head, needs_acq: true, } } } #[derive(Debug)] pub struct Iter<'a> { // pin to an epoch so that we can free inactive nodes guard: &'a Guard, next: &'a Atomic, // an Acquire read is needed only for the first read, due to release // sequences needs_acq: bool, } impl<'a> Iterator for Iter<'a> { type Item = &'a Participant; fn next(&mut self) -> Option<&'a Participant> { let mut cur = if self.needs_acq { self.needs_acq = false; self.next.load(Acquire, self.guard) } else { self.next.load(Relaxed, self.guard) }; while let Some(n) = cur { // attempt to clean up inactive nodes if !n.active.load(Relaxed) { cur = n.next.load(Relaxed, self.guard); // TODO: actually reclaim inactive participants! } else { self.next = &n.next; return Some(&n) } } None } } vendor/crossbeam-0.3.2/src/lib.rs0000664000000000000000000000451313264166600015401 0ustar rootroot//! Support for concurrent and parallel programming. //! //! This crate is an early work in progress. The focus for the moment is //! concurrency: //! //! - **Non-blocking data structures**. These data structures allow for high //! performance, highly-concurrent access, much superior to wrapping with a //! `Mutex`. Ultimately the goal is to include stacks, queues, deques, bags, //! sets and maps. These live in the `sync` module. //! //! - **Memory management**. Because non-blocking data structures avoid global //! synchronization, it is not easy to tell when internal data can be safely //! freed. The `mem` module provides generic, easy to use, and high-performance //! APIs for managing memory in these cases. These live in the `mem` module. //! //! - **Synchronization**. The standard library provides a few synchronization //! primitives (locks, barriers, etc) but this crate seeks to expand that set //! to include more advanced/niche primitives, as well as userspace //! alternatives. These live in the `sync` module. //! //! - **Scoped thread API**. Finally, the crate provides a "scoped" thread API, //! making it possible to spawn threads that share stack data with their //! parents. This functionality is exported at the top-level. //#![deny(missing_docs)] #![cfg_attr(feature = "nightly", feature(const_fn, repr_simd, optin_builtin_traits))] use std::thread; use std::io; pub use scoped::{scope, Scope, ScopedJoinHandle}; pub mod epoch; pub mod sync; mod scoped; mod cache_padded; pub use self::cache_padded::{CachePadded, ZerosValid}; #[doc(hidden)] trait FnBox { fn call_box(self: Box); } impl FnBox for F { fn call_box(self: Box) { (*self)() } } /// Like `std::thread::spawn`, but without the closure bounds. pub unsafe fn spawn_unsafe<'a, F>(f: F) -> thread::JoinHandle<()> where F: FnOnce() + Send + 'a { let builder = thread::Builder::new(); builder_spawn_unsafe(builder, f).unwrap() } /// Like `std::thread::Builder::spawn`, but without the closure bounds. pub unsafe fn builder_spawn_unsafe<'a, F>(builder: thread::Builder, f: F) -> io::Result> where F: FnOnce() + Send + 'a { use std::mem; let closure: Box = Box::new(f); let closure: Box = mem::transmute(closure); builder.spawn(move || closure.call_box()) } vendor/crossbeam-0.3.2/src/scoped.rs0000664000000000000000000002223013264166600016104 0ustar rootrootuse std::cell::RefCell; use std::fmt; use std::mem; use std::rc::Rc; use std::sync::atomic::Ordering; use std::sync::Arc; use std::thread; use std::io; use {builder_spawn_unsafe, FnBox}; use sync::AtomicOption; pub struct Scope<'a> { dtors: RefCell>> } struct DtorChain<'a> { dtor: Box, next: Option>> } enum JoinState { Running(thread::JoinHandle<()>), Joined, } impl JoinState { fn join(&mut self) { let mut state = JoinState::Joined; mem::swap(self, &mut state); if let JoinState::Running(handle) = state { let res = handle.join(); if !thread::panicking() { res.unwrap(); } } } } /// A handle to a scoped thread pub struct ScopedJoinHandle { inner: Rc>, packet: Arc>, thread: thread::Thread, } /// Create a new `scope`, for deferred destructors. /// /// Scopes, in particular, support [*scoped thread spawning*](struct.Scope.html#method.spawn). /// /// # Examples /// /// Creating and using a scope: /// /// ``` /// crossbeam::scope(|scope| { /// scope.defer(|| println!("Exiting scope")); /// scope.spawn(|| println!("Running child thread in scope")) /// }); /// // Prints messages in the reverse order written /// ``` pub fn scope<'a, F, R>(f: F) -> R where F: FnOnce(&Scope<'a>) -> R { let mut scope = Scope { dtors: RefCell::new(None) }; let ret = f(&scope); scope.drop_all(); ret } impl<'a> fmt::Debug for Scope<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Scope {{ ... }}") } } impl fmt::Debug for ScopedJoinHandle { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "ScopedJoinHandle {{ ... }}") } } impl<'a> Scope<'a> { // This method is carefully written in a transactional style, so // that it can be called directly and, if any dtor panics, can be // resumed in the unwinding this causes. By initially running the // method outside of any destructor, we avoid any leakage problems // due to @rust-lang/rust#14875. fn drop_all(&mut self) { loop { // use a separate scope to ensure that the RefCell borrow // is relinquished before running `dtor` let dtor = { let mut dtors = self.dtors.borrow_mut(); if let Some(mut node) = dtors.take() { *dtors = node.next.take().map(|b| *b); node.dtor } else { return } }; dtor.call_box() } } /// Schedule code to be executed when exiting the scope. /// /// This is akin to having a destructor on the stack, except that it is /// *guaranteed* to be run. pub fn defer(&self, f: F) where F: FnOnce() + 'a { let mut dtors = self.dtors.borrow_mut(); *dtors = Some(DtorChain { dtor: Box::new(f), next: dtors.take().map(Box::new) }); } /// Create a scoped thread. /// /// `spawn` is similar to the [`spawn`][spawn] function in Rust's standard library. The /// difference is that this thread is scoped, meaning that it's guaranteed to terminate /// before the current stack frame goes away, allowing you to reference the parent stack frame /// directly. This is ensured by having the parent thread join on the child thread before the /// scope exits. /// /// [spawn]: http://doc.rust-lang.org/std/thread/fn.spawn.html /// /// # Examples /// /// A basic scoped thread: /// /// ``` /// crossbeam::scope(|scope| { /// scope.spawn(|| { /// println!("Hello from a scoped thread!"); /// }); /// }); /// ``` /// /// When writing concurrent Rust programs, you'll sometimes see a pattern like this, using /// [`std::thread::spawn`][spawn]: /// /// ```ignore /// let array = [1, 2, 3]; /// let mut guards = vec![]; /// /// for i in &array { /// let guard = std::thread::spawn(move || { /// println!("element: {}", i); /// }); /// /// guards.push(guard); /// } /// /// for guard in guards { /// guard.join().unwrap(); /// } /// ``` /// /// The basic pattern is: /// /// 1. Iterate over some collection. /// 2. Spin up a thread to operate on each part of the collection. /// 3. Join all the threads. /// /// However, this code actually gives an error: /// /// ```text /// error: `array` does not live long enough /// for i in &array { /// ^~~~~ /// in expansion of for loop expansion /// note: expansion site /// note: reference must be valid for the static lifetime... /// note: ...but borrowed value is only valid for the block suffix following statement 0 at ... /// let array = [1, 2, 3]; /// let mut guards = vec![]; /// /// for i in &array { /// let guard = std::thread::spawn(move || { /// println!("element: {}", i); /// ... /// error: aborting due to previous error /// ``` /// /// Because [`std::thread::spawn`][spawn] doesn't know about this scope, it requires a /// `'static` lifetime. One way of giving it a proper lifetime is to use an [`Arc`][arc]: /// /// [arc]: http://doc.rust-lang.org/stable/std/sync/struct.Arc.html /// /// ``` /// use std::sync::Arc; /// /// let array = Arc::new([1, 2, 3]); /// let mut guards = vec![]; /// /// for i in 0..array.len() { /// let a = array.clone(); /// /// let guard = std::thread::spawn(move || { /// println!("element: {}", a[i]); /// }); /// /// guards.push(guard); /// } /// /// for guard in guards { /// guard.join().unwrap(); /// } /// ``` /// /// But this introduces unnecessary allocation, as `Arc` puts its data on the heap, and we /// also end up dealing with reference counts. We know that we're joining the threads before /// our function returns, so just taking a reference _should_ be safe. Rust can't know that, /// though. /// /// Enter scoped threads. Here's our original example, using `spawn` from crossbeam rather /// than from `std::thread`: /// /// ``` /// let array = [1, 2, 3]; /// /// crossbeam::scope(|scope| { /// for i in &array { /// scope.spawn(move || { /// println!("element: {}", i); /// }); /// } /// }); /// ``` /// /// Much more straightforward. pub fn spawn(&self, f: F) -> ScopedJoinHandle where F: FnOnce() -> T + Send + 'a, T: Send + 'a { self.builder().spawn(f).unwrap() } /// Generates the base configuration for spawning a scoped thread, from which configuration /// methods can be chained. pub fn builder<'s>(&'s self) -> ScopedThreadBuilder<'s, 'a> { ScopedThreadBuilder { scope: self, builder: thread::Builder::new(), } } } /// Scoped thread configuration. Provides detailed control over the properties and behavior of new /// scoped threads. pub struct ScopedThreadBuilder<'s, 'a: 's> { scope: &'s Scope<'a>, builder: thread::Builder, } impl<'s, 'a: 's> ScopedThreadBuilder<'s, 'a> { /// Names the thread-to-be. Currently the name is used for identification only in panic /// messages. pub fn name(mut self, name: String) -> ScopedThreadBuilder<'s, 'a> { self.builder = self.builder.name(name); self } /// Sets the size of the stack for the new thread. pub fn stack_size(mut self, size: usize) -> ScopedThreadBuilder<'s, 'a> { self.builder = self.builder.stack_size(size); self } /// Spawns a new thread, and returns a join handle for it. pub fn spawn(self, f: F) -> io::Result> where F: FnOnce() -> T + Send + 'a, T: Send + 'a { let their_packet = Arc::new(AtomicOption::new()); let my_packet = their_packet.clone(); let join_handle = try!(unsafe { builder_spawn_unsafe(self.builder, move || { their_packet.swap(f(), Ordering::Relaxed); }) }); let thread = join_handle.thread().clone(); let deferred_handle = Rc::new(RefCell::new(JoinState::Running(join_handle))); let my_handle = deferred_handle.clone(); self.scope.defer(move || { let mut state = deferred_handle.borrow_mut(); state.join(); }); Ok(ScopedJoinHandle { inner: my_handle, packet: my_packet, thread: thread, }) } } impl ScopedJoinHandle { /// Join the scoped thread, returning the result it produced. pub fn join(self) -> T { self.inner.borrow_mut().join(); self.packet.take(Ordering::Relaxed).unwrap() } /// Get the underlying thread handle. pub fn thread(&self) -> &thread::Thread { &self.thread } } impl<'a> Drop for Scope<'a> { fn drop(&mut self) { self.drop_all() } } vendor/crossbeam-0.3.2/src/sync/0000755000000000000000000000000013264166600015234 5ustar rootrootvendor/crossbeam-0.3.2/src/sync/arc_cell.rs0000664000000000000000000000424513264166600017355 0ustar rootrootuse std::marker::PhantomData; use std::mem; use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; /// A type providing atomic storage and retrieval of an `Arc`. #[derive(Debug)] pub struct ArcCell(AtomicUsize, PhantomData>); impl Drop for ArcCell { fn drop(&mut self) { self.take(); } } impl ArcCell { /// Creates a new `ArcCell`. pub fn new(t: Arc) -> ArcCell { ArcCell(AtomicUsize::new(unsafe { mem::transmute(t) }), PhantomData) } fn take(&self) -> Arc { loop { match self.0.swap(0, Ordering::Acquire) { 0 => {} n => return unsafe { mem::transmute(n) } } } } fn put(&self, t: Arc) { debug_assert_eq!(self.0.load(Ordering::SeqCst), 0); self.0.store(unsafe { mem::transmute(t) }, Ordering::Release); } /// Stores a new value in the `ArcCell`, returning the previous /// value. pub fn set(&self, t: Arc) -> Arc { let old = self.take(); self.put(t); old } /// Returns a copy of the value stored by the `ArcCell`. pub fn get(&self) -> Arc { let t = self.take(); // NB: correctness here depends on Arc's clone impl not panicking let out = t.clone(); self.put(t); out } } #[cfg(test)] mod test { use std::sync::Arc; use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering}; use super::*; #[test] fn basic() { let r = ArcCell::new(Arc::new(0)); assert_eq!(*r.get(), 0); assert_eq!(*r.set(Arc::new(1)), 0); assert_eq!(*r.get(), 1); } #[test] fn drop_runs() { static DROPS: AtomicUsize = ATOMIC_USIZE_INIT; struct Foo; impl Drop for Foo { fn drop(&mut self) { DROPS.fetch_add(1, Ordering::SeqCst); } } let r = ArcCell::new(Arc::new(Foo)); let _f = r.get(); r.get(); r.set(Arc::new(Foo)); drop(_f); assert_eq!(DROPS.load(Ordering::SeqCst), 1); drop(r); assert_eq!(DROPS.load(Ordering::SeqCst), 2); } } vendor/crossbeam-0.3.2/src/sync/atomic_option.rs0000664000000000000000000000240013264166600020444 0ustar rootrootuse std::sync::atomic::{AtomicPtr, Ordering}; use std::ptr; unsafe impl Send for AtomicOption {} unsafe impl Sync for AtomicOption {} #[derive(Debug)] pub struct AtomicOption { inner: AtomicPtr, } impl Drop for AtomicOption { fn drop(&mut self) { let inner = self.inner.load(Ordering::Relaxed); if !inner.is_null() { unsafe { drop(Box::from_raw(inner)); } } } } impl AtomicOption { pub fn new() -> AtomicOption { AtomicOption { inner: AtomicPtr::new(ptr::null_mut()) } } fn swap_inner(&self, ptr: *mut T, order: Ordering) -> Option> { let old = self.inner.swap(ptr, order); if old.is_null() { None } else { Some(unsafe { Box::from_raw(old) }) } } // allows re-use of allocation pub fn swap_box(&self, t: Box, order: Ordering) -> Option> { self.swap_inner(Box::into_raw(t), order) } pub fn swap(&self, t: T, order: Ordering) -> Option { self.swap_box(Box::new(t), order).map(|old| *old) } pub fn take(&self, order: Ordering) -> Option { self.swap_inner(ptr::null_mut(), order).map(|old| *old) } } vendor/crossbeam-0.3.2/src/sync/chase_lev.rs0000664000000000000000000004411713264166600017544 0ustar rootroot// 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! A lock-free concurrent work-stealing deque //! //! This module contains a hybrid implementation of the Chase-Lev work stealing deque //! described in ["Dynamic Circular Work-Stealing Deque"][chase_lev] and the improved version //! described in ["Correct and Efficient Work-Stealing for Weak Memory Models"][weak_chase_lev]. //! The implementation is heavily based on the pseudocode found in the papers. //! //! # Example //! //! ``` //! use crossbeam::sync::chase_lev; //! let (worker, stealer) = chase_lev::deque(); //! //! // Only the worker may push/try_pop //! worker.push(1); //! worker.try_pop(); //! //! // Stealers take data from the other end of the deque //! worker.push(1); //! stealer.steal(); //! //! // Stealers can be cloned to have many stealers stealing in parallel //! worker.push(1); //! let stealer2 = stealer.clone(); //! stealer2.steal(); //! ``` //! //! [chase_lev]: http://neteril.org/~jeremie/Dynamic_Circular_Work_Queue.pdf //! [weak_chase_lev]: http://www.di.ens.fr/~zappa/readings/ppopp13.pdf use std::cell::UnsafeCell; use std::fmt; use std::mem; use std::ptr; use std::sync::atomic::Ordering::{Acquire, Relaxed, Release, SeqCst}; use std::sync::atomic::{AtomicIsize, fence}; use std::sync::Arc; use std::marker::PhantomData; use std::cell::Cell; use epoch::{self, Atomic, Shared, Owned}; // Once the queue is less than 1/K full, then it will be downsized. Note that // the deque requires that this number be less than 2. const K: isize = 4; // Minimum number of bits that a buffer size should be. No buffer will resize to // under this value, and all deques will initially contain a buffer of this // size. // // The size in question is 1 << MIN_BITS const MIN_BITS: u32 = 7; #[derive(Debug)] struct Deque { bottom: AtomicIsize, top: AtomicIsize, array: Atomic>, } // FIXME: can these constraints be relaxed? unsafe impl Send for Deque {} unsafe impl Sync for Deque {} /// Worker half of the work-stealing deque. This worker has exclusive access to /// one side of the deque, and uses `push` and `try_pop` method to manipulate it. /// /// There may only be one worker per deque, so `Worker` does not implement /// `Clone` or `Copy`. #[derive(Debug)] pub struct Worker { deque: Arc>, // Marker so that the Worker is Send but not Sync. The worker can only be // accessed from a single thread at once. Ideally we would use a negative // impl here but these are not stable yet. marker: PhantomData>, } /// The stealing half of the work-stealing deque. Stealers have access to the /// opposite end of the deque from the worker, and they only have access to the /// `steal` method. /// /// Stealers can be cloned to have more than one handle active at a time. #[derive(Debug)] pub struct Stealer { deque: Arc>, } /// When stealing some data, this is an enumeration of the possible outcomes. #[derive(PartialEq, Eq, Debug)] pub enum Steal { /// The deque was empty at the time of stealing Empty, /// The stealer lost the race for stealing data, and a retry may return more /// data. Abort, /// The stealer has successfully stolen some data. Data(T), } // An internal buffer used by the chase-lev deque. This structure is actually // implemented as a circular buffer, and is used as the intermediate storage of // the data in the deque. // // This Vec always has a length of 0, the backing buffer is just used by the // code below. struct Buffer { storage: UnsafeCell>, log_size: u32, } impl fmt::Debug for Buffer { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Buffer {{ ... }}") } } impl Worker { /// Pushes data onto the front of this work queue. pub fn push(&self, t: T) { unsafe { self.deque.push(t) } } /// Pops data off the front of the work queue, returning `None` on an empty /// queue. pub fn try_pop(&self) -> Option { unsafe { self.deque.try_pop() } } } impl Stealer { /// Steals work off the end of the queue (opposite of the worker's end) pub fn steal(&self) -> Steal { self.deque.steal() } } impl Clone for Stealer { fn clone(&self) -> Stealer { Stealer { deque: self.deque.clone() } } } /// Creates a new empty deque pub fn deque() -> (Worker, Stealer) { let a = Arc::new(Deque::new()); let b = a.clone(); (Worker { deque: a, marker: PhantomData }, Stealer { deque: b }) } // Almost all of this code can be found directly in the paper so I'm not // personally going to heavily comment what's going on here. impl Deque { fn new() -> Deque { let array = Atomic::null(); array.store(Some(Owned::new(Buffer::new(MIN_BITS))), SeqCst); Deque { bottom: AtomicIsize::new(0), top: AtomicIsize::new(0), array: array, } } unsafe fn push(&self, data: T) { let guard = epoch::pin(); let mut b = self.bottom.load(Relaxed); let t = self.top.load(Acquire); let mut a = self.array.load(Relaxed, &guard).unwrap(); let size = b - t; if size >= (a.size() as isize) - 1 { // You won't find this code in the chase-lev deque paper. This is // alluded to in a small footnote, however. We always free a buffer // when growing in order to prevent leaks. a = self.swap_buffer(a, a.resize(b, t, 1), &guard); // reload the bottom counter, since swap_buffer modifies it. b = self.bottom.load(Relaxed); } a.put(b, data); fence(Release); self.bottom.store(b + 1, Relaxed); } unsafe fn try_pop(&self) -> Option { let guard = epoch::pin(); let b = self.bottom.load(Relaxed); let a = self.array.load(Relaxed, &guard).unwrap(); self.bottom.store(b - 1, Relaxed); fence(SeqCst); // the store to bottom must occur before loading top. let t = self.top.load(Relaxed); let size = b - t; if size <= 0 { // empty queue. revert the decrement of bottom. self.bottom.store(b, Relaxed); None } else if size >= 2 { // non-racy case. return the data let data = a.get(b - 1); self.maybe_shrink(b - 1, t, &guard); Some(data) } else { // racy case. race against steals. let success = self.top.compare_and_swap(t, t + 1, SeqCst) == t; // set the queue to a canonically empty state. self.bottom.store(b, Relaxed); if success { Some(a.get(t)) } else { None } } } fn steal(&self) -> Steal { let guard = epoch::pin(); let t = self.top.load(Relaxed); fence(SeqCst); // top must be loaded before bottom. let b = self.bottom.load(Acquire); let size = b - t; if size <= 0 { return Steal::Empty } unsafe { // while the paper uses a "consume" ordering here, the closest thing we have // available is Acquire, which is strictly stronger. let a = self.array.load(Acquire, &guard).unwrap(); let data = a.get(t); // we may be racing against other steals and a pop. if self.top.compare_and_swap(t, t + 1, SeqCst) == t { Steal::Data(data) } else { mem::forget(data); // someone else stole this value Steal::Abort } } } // potentially shrink the array. This can be called only from the worker. unsafe fn maybe_shrink(&self, b: isize, t: isize, guard: &epoch::Guard) { let a = self.array.load(SeqCst, guard).unwrap(); let size = b - t; if size < (a.size() as isize) / K && size > (1 << MIN_BITS) { self.swap_buffer(a, a.resize(b, t, -1), guard); } } // Helper routine not mentioned in the paper which is used in growing and // shrinking buffers to swap in a new buffer into place. // // As a bit of a recap, stealers can continue using buffers after this // method has called 'unlinked' on it. The continued usage is simply a read // followed by a forget, but we must make sure that the memory can continue // to be read after we flag this buffer for reclamation. All stealers, // however, have their own epoch pinned during this time so the buffer will // just naturally be free'd once all concurrent stealers have exited. // // This method may only be called safely from the workers due to the way it modifies // the array pointer. unsafe fn swap_buffer<'a>(&self, old: Shared<'a, Buffer>, buf: Buffer, guard: &'a epoch::Guard) -> Shared<'a, Buffer> { let newbuf = Owned::new(buf); let newbuf = self.array.store_and_ref(newbuf, Release, &guard); guard.unlinked(old); newbuf } } impl Drop for Deque { fn drop(&mut self) { let guard = epoch::pin(); // Arc enforces that we have truly exclusive access here. let t = self.top.load(Relaxed); let b = self.bottom.load(Relaxed); let a = self.array.swap(None, Relaxed, &guard).unwrap(); // Free whatever is leftover in the dequeue, then free the backing // memory itself unsafe { for i in t..b { drop(a.get(i)); } guard.unlinked(a); } } } impl Buffer { fn new(log_size: u32) -> Buffer { Buffer { storage: UnsafeCell::new(Vec::with_capacity(1 << log_size)), log_size: log_size, } } fn size(&self) -> usize { unsafe { (*self.storage.get()).capacity() } } fn mask(&self) -> isize { unsafe { ((*self.storage.get()).capacity() - 1) as isize } } unsafe fn elem(&self, i: isize) -> *mut T { (*self.storage.get()).as_mut_ptr().offset(i & self.mask()) } // This does not protect against loading duplicate values of the same cell, // nor does this clear out the contents contained within. Hence, this is a // very unsafe method which the caller needs to treat specially in case a // race is lost. unsafe fn get(&self, i: isize) -> T { ptr::read(self.elem(i)) } // Unsafe because this unsafely overwrites possibly uninitialized or // initialized data. unsafe fn put(&self, i: isize, t: T) { ptr::write(self.elem(i), t); } // Again, unsafe because this has incredibly dubious ownership violations. // It is assumed that this buffer is immediately dropped. unsafe fn resize(&self, b: isize, t: isize, delta: i32) -> Buffer { let buf = Buffer::new(((self.log_size as i32) + delta) as u32); for i in t..b { buf.put(i, self.get(i)); } return buf; } } #[cfg(test)] mod tests { extern crate rand; use super::{deque, Worker, Stealer, Steal}; use std::thread; use std::sync::Arc; use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, AtomicUsize, ATOMIC_USIZE_INIT}; use std::sync::atomic::Ordering::SeqCst; use self::rand::Rng; #[test] fn smoke() { let (w, s) = deque(); assert_eq!(w.try_pop(), None); assert_eq!(s.steal(), Steal::Empty); w.push(1); assert_eq!(w.try_pop(), Some(1)); w.push(1); assert_eq!(s.steal(), Steal::Data(1)); w.push(1); assert_eq!(s.clone().steal(), Steal::Data(1)); } #[test] fn stealpush() { static AMT: isize = 100000; let (w, s) = deque(); let t = thread::spawn(move || { let mut left = AMT; while left > 0 { match s.steal() { Steal::Data(i) => { assert_eq!(i, 1); left -= 1; } Steal::Abort | Steal::Empty => {} } } }); for _ in 0..AMT { w.push(1); } t.join().unwrap(); } #[test] fn stealpush_large() { static AMT: isize = 100000; let (w, s) = deque(); let t = thread::spawn(move || { let mut left = AMT; while left > 0 { match s.steal() { Steal::Data((1, 10)) => { left -= 1; } Steal::Data(..) => panic!(), Steal::Abort | Steal::Empty => {} } } }); for _ in 0..AMT { w.push((1, 10)); } t.join().unwrap(); } fn stampede(w: Worker>, s: Stealer>, nthreads: isize, amt: usize) { for _ in 0..amt { w.push(Box::new(20)); } let remaining = Arc::new(AtomicUsize::new(amt)); let threads = (0..nthreads).map(|_| { let remaining = remaining.clone(); let s = s.clone(); thread::spawn(move || { while remaining.load(SeqCst) > 0 { match s.steal() { Steal::Data(val) => { if *val == 20 { remaining.fetch_sub(1, SeqCst); } else { panic!() } } Steal::Abort | Steal::Empty => {} } } }) }).collect::>(); while remaining.load(SeqCst) > 0 { if let Some(val) = w.try_pop() { if *val == 20 { remaining.fetch_sub(1, SeqCst); } else { panic!() } } } for thread in threads.into_iter() { thread.join().unwrap(); } } #[test] fn run_stampede() { let (w, s) = deque(); stampede(w, s, 8, 10000); } #[test] fn many_stampede() { static AMT: usize = 4; let threads = (0..AMT).map(|_| { let (w, s) = deque(); thread::spawn(|| { stampede(w, s, 4, 10000); }) }).collect::>(); for thread in threads.into_iter() { thread.join().unwrap(); } } #[test] fn stress() { static AMT: isize = 100000; static NTHREADS: isize = 8; static DONE: AtomicBool = ATOMIC_BOOL_INIT; static HITS: AtomicUsize = ATOMIC_USIZE_INIT; let (w, s) = deque(); let threads = (0..NTHREADS).map(|_| { let s = s.clone(); thread::spawn(move || { loop { match s.steal() { Steal::Data(2) => { HITS.fetch_add(1, SeqCst); } Steal::Data(..) => panic!(), _ if DONE.load(SeqCst) => break, _ => {} } } }) }).collect::>(); let mut rng = rand::thread_rng(); let mut expected = 0; while expected < AMT { if rng.gen_range(0, 3) == 2 { match w.try_pop() { None => {} Some(2) => { HITS.fetch_add(1, SeqCst); }, Some(_) => panic!(), } } else { expected += 1; w.push(2); } } while HITS.load(SeqCst) < AMT as usize { match w.try_pop() { None => {} Some(2) => { HITS.fetch_add(1, SeqCst); }, Some(_) => panic!(), } } DONE.store(true, SeqCst); for thread in threads.into_iter() { thread.join().unwrap(); } assert_eq!(HITS.load(SeqCst), expected as usize); } #[test] fn no_starvation() { static AMT: isize = 10000; static NTHREADS: isize = 4; static DONE: AtomicBool = ATOMIC_BOOL_INIT; let (w, s) = deque(); let (threads, hits): (Vec<_>, Vec<_>) = (0..NTHREADS).map(|_| { let s = s.clone(); let ctr = Arc::new(AtomicUsize::new(0)); let ctr2 = ctr.clone(); (thread::spawn(move || { loop { match s.steal() { Steal::Data((1, 2)) => { ctr.fetch_add(1, SeqCst); } Steal::Data(..) => panic!(), _ if DONE.load(SeqCst) => break, _ => {} } } }), ctr2) }).unzip(); let mut rng = rand::thread_rng(); let mut myhit = false; 'outer: loop { for _ in 0..rng.gen_range(0, AMT) { if !myhit && rng.gen_range(0, 3) == 2 { match w.try_pop() { None => {} Some((1, 2)) => myhit = true, Some(_) => panic!(), } } else { w.push((1, 2)); } } for slot in hits.iter() { let amt = slot.load(SeqCst); if amt == 0 { continue 'outer; } } if myhit { break } } DONE.store(true, SeqCst); for thread in threads.into_iter() { thread.join().unwrap(); } } } vendor/crossbeam-0.3.2/src/sync/mod.rs0000664000000000000000000000050113264166600016357 0ustar rootroot//! Synchronization primitives. pub use self::ms_queue::MsQueue; pub use self::atomic_option::AtomicOption; pub use self::treiber_stack::TreiberStack; pub use self::seg_queue::SegQueue; pub use self::arc_cell::ArcCell; mod atomic_option; mod ms_queue; mod treiber_stack; mod seg_queue; pub mod chase_lev; mod arc_cell; vendor/crossbeam-0.3.2/src/sync/ms_queue.rs0000664000000000000000000003767513264166600017451 0ustar rootrootuse std::sync::atomic::Ordering::{Acquire, Release, Relaxed}; use std::sync::atomic::AtomicBool; use std::{ptr, mem}; use std::thread::{self, Thread}; use epoch::{self, Atomic, Owned, Shared}; use CachePadded; /// A Michael-Scott lock-free queue, with support for blocking `pop`s. /// /// Usable with any number of producers and consumers. // The representation here is a singly-linked list, with a sentinel // node at the front. In general the `tail` pointer may lag behind the // actual tail. Non-sentinel nodes are either all `Data` or all // `Blocked` (requests for data from blocked threads). #[derive(Debug)] pub struct MsQueue { head: CachePadded>>, tail: CachePadded>>, } #[derive(Debug)] struct Node { payload: Payload, next: Atomic>, } #[derive(Debug)] enum Payload { /// A node with actual data that can be popped. Data(T), /// A node representing a blocked request for data. Blocked(*mut Signal), } /// A blocked request for data, which includes a slot to write the data. #[derive(Debug)] struct Signal { /// Thread to unpark when data is ready. thread: Thread, /// The actual data, when available. data: Option, /// Is the data ready? Needed to cope with spurious wakeups. ready: AtomicBool, } impl Node { fn is_data(&self) -> bool { if let Payload::Data(_) = self.payload { true } else { false } } } // Any particular `T` should never accessed concurrently, so no need // for Sync. unsafe impl Sync for MsQueue {} unsafe impl Send for MsQueue {} impl MsQueue { /// Create a new, empty queue. pub fn new() -> MsQueue { let q = MsQueue { head: CachePadded::new(Atomic::null()), tail: CachePadded::new(Atomic::null()), }; let sentinel = Owned::new(Node { payload: Payload::Data(unsafe { mem::uninitialized() }), next: Atomic::null(), }); let guard = epoch::pin(); let sentinel = q.head.store_and_ref(sentinel, Relaxed, &guard); q.tail.store_shared(Some(sentinel), Relaxed); q } #[inline(always)] /// Attempt to atomically place `n` into the `next` pointer of `onto`. /// /// If unsuccessful, returns ownership of `n`, possibly updating /// the queue's `tail` pointer. fn push_internal(&self, guard: &epoch::Guard, onto: Shared>, n: Owned>) -> Result<(), Owned>> { // is `onto` the actual tail? if let Some(next) = onto.next.load(Acquire, guard) { // if not, try to "help" by moving the tail pointer forward self.tail.cas_shared(Some(onto), Some(next), Release); Err(n) } else { // looks like the actual tail; attempt to link in `n` onto.next.cas_and_ref(None, n, Release, guard).map(|shared| { // try to move the tail pointer forward self.tail.cas_shared(Some(onto), Some(shared), Release); }) } } /// Add `t` to the back of the queue, possibly waking up threads /// blocked on `pop`. pub fn push(&self, t: T) { /// We may or may not need to allocate a node; once we do, /// we cache that allocation. enum Cache { Data(T), Node(Owned>), } impl Cache { /// Extract the node if cached, or allocate if not. fn into_node(self) -> Owned> { match self { Cache::Data(t) => { Owned::new(Node { payload: Payload::Data(t), next: Atomic::null() }) } Cache::Node(n) => n } } /// Extract the data from the cache, deallocating any cached node. fn into_data(self) -> T { match self { Cache::Data(t) => t, Cache::Node(node) => { match node.into_inner().payload { Payload::Data(t) => t, _ => unreachable!(), } } } } } let mut cache = Cache::Data(t); // don't allocate up front let guard = epoch::pin(); loop { // We push onto the tail, so we'll start optimistically by looking // there first. let tail = self.tail.load(Acquire, &guard).unwrap(); // Is the queue in Data mode (empty queues can be viewed as either mode)? if tail.is_data() || self.head.load(Relaxed, &guard).unwrap().as_raw() == tail.as_raw() { // Attempt to push onto the `tail` snapshot; fails if // `tail.next` has changed, which will always be the case if the // queue has transitioned to blocking mode. match self.push_internal(&guard, tail, cache.into_node()) { Ok(_) => return, Err(n) => { // replace the cache, retry whole thing cache = Cache::Node(n) } } } else { // Queue is in blocking mode. Attempt to unblock a thread. let head = self.head.load(Acquire, &guard).unwrap(); // Get a handle on the first blocked node. Racy, so queue might // be empty or in data mode by the time we see it. let request = head.next.load(Acquire, &guard).and_then(|next| { match next.payload { Payload::Blocked(signal) => Some((next, signal)), Payload::Data(_) => None, } }); if let Some((blocked_node, signal)) = request { // race to dequeue the node if self.head.cas_shared(Some(head), Some(blocked_node), Release) { unsafe { // signal the thread (*signal).data = Some(cache.into_data()); let thread = (*signal).thread.clone(); (*signal).ready.store(true, Release); thread.unpark(); guard.unlinked(head); return; } } } } } } #[inline(always)] // Attempt to pop a data node. `Ok(None)` if queue is empty or in blocking // mode; `Err(())` if lost race to pop. fn pop_internal(&self, guard: &epoch::Guard) -> Result, ()> { let head = self.head.load(Acquire, guard).unwrap(); if let Some(next) = head.next.load(Acquire, guard) { if let Payload::Data(ref t) = next.payload { unsafe { if self.head.cas_shared(Some(head), Some(next), Release) { guard.unlinked(head); Ok(Some(ptr::read(t))) } else { Err(()) } } } else { Ok(None) } } else { Ok(None) } } /// Check if this queue is empty. pub fn is_empty(&self) -> bool { let guard = epoch::pin(); let head = self.head.load(Acquire, &guard).unwrap(); if let Some(next) = head.next.load(Acquire, &guard) { if let Payload::Data(_) = next.payload { false } else { true } } else { true } } /// Attempt to dequeue from the front. /// /// Returns `None` if the queue is observed to be empty. pub fn try_pop(&self) -> Option { let guard = epoch::pin(); loop { if let Ok(r) = self.pop_internal(&guard) { return r; } } } /// Dequeue an element from the front of the queue, blocking if the queue is /// empty. pub fn pop(&self) -> T { let guard = epoch::pin(); // Fast path: keep retrying until we observe that the queue has no data, // avoiding the allocation of a blocked node. loop { match self.pop_internal(&guard) { Ok(Some(r)) => { return r; } Ok(None) => { break; } Err(()) => {} } } // The signal gets to live on the stack, since this stack frame will be // blocked until receiving the signal. let mut signal = Signal { thread: thread::current(), data: None, ready: AtomicBool::new(false), }; // Go ahead and allocate the blocked node; chances are, we'll need it. let mut node = Owned::new(Node { payload: Payload::Blocked(&mut signal), next: Atomic::null(), }); loop { // try a normal pop if let Ok(Some(r)) = self.pop_internal(&guard) { return r; } // At this point, we believe the queue is empty/blocked. // Snapshot the tail, onto which we want to push a blocked node. let tail = self.tail.load(Acquire, &guard).unwrap(); // Double-check that we're in blocking mode if tail.is_data() { // The current tail is in data mode, so we probably need to abort. // BUT, it might be the sentinel, so check for that first. let head = self.head.load(Relaxed, &guard).unwrap(); if tail.is_data() && tail.as_raw() != head.as_raw() { continue; } } // At this point, the tail snapshot is either a blocked node deep in // the queue, the sentinel, or no longer accessible from the queue. // In *ALL* of these cases, if we succeed in pushing onto the // snapshot, we know we are maintaining the core invariant: all // reachable, non-sentinel nodes have the same payload mode, in this // case, blocked. match self.push_internal(&guard, tail, node) { Ok(()) => { while !signal.ready.load(Acquire) { thread::park(); } return signal.data.unwrap(); } Err(n) => { node = n; } } } } } impl Drop for MsQueue { fn drop(&mut self) { while self.try_pop().is_some() {} // Destroy the remaining sentinel node. let guard = epoch::pin(); let sentinel = self.head.load(Relaxed, &guard).unwrap().as_raw(); unsafe { drop(Vec::from_raw_parts(sentinel, 0, 1)); } } } #[cfg(test)] mod test { const CONC_COUNT: i64 = 1000000; use scope; use super::*; #[test] fn push_try_pop_1() { let q: MsQueue = MsQueue::new(); assert!(q.is_empty()); q.push(37); assert!(!q.is_empty()); assert_eq!(q.try_pop(), Some(37)); assert!(q.is_empty()); } #[test] fn push_try_pop_2() { let q: MsQueue = MsQueue::new(); assert!(q.is_empty()); q.push(37); q.push(48); assert_eq!(q.try_pop(), Some(37)); assert!(!q.is_empty()); assert_eq!(q.try_pop(), Some(48)); assert!(q.is_empty()); } #[test] fn push_try_pop_many_seq() { let q: MsQueue = MsQueue::new(); assert!(q.is_empty()); for i in 0..200 { q.push(i) } assert!(!q.is_empty()); for i in 0..200 { assert_eq!(q.try_pop(), Some(i)); } assert!(q.is_empty()); } #[test] fn push_pop_1() { let q: MsQueue = MsQueue::new(); assert!(q.is_empty()); q.push(37); assert!(!q.is_empty()); assert_eq!(q.pop(), 37); assert!(q.is_empty()); } #[test] fn push_pop_2() { let q: MsQueue = MsQueue::new(); q.push(37); q.push(48); assert_eq!(q.pop(), 37); assert_eq!(q.pop(), 48); } #[test] fn push_pop_many_seq() { let q: MsQueue = MsQueue::new(); assert!(q.is_empty()); for i in 0..200 { q.push(i) } assert!(!q.is_empty()); for i in 0..200 { assert_eq!(q.pop(), i); } assert!(q.is_empty()); } #[test] fn push_try_pop_many_spsc() { let q: MsQueue = MsQueue::new(); assert!(q.is_empty()); scope(|scope| { scope.spawn(|| { let mut next = 0; while next < CONC_COUNT { if let Some(elem) = q.try_pop() { assert_eq!(elem, next); next += 1; } } }); for i in 0..CONC_COUNT { q.push(i) } }); } #[test] fn push_try_pop_many_spmc() { fn recv(_t: i32, q: &MsQueue) { let mut cur = -1; for _i in 0..CONC_COUNT { if let Some(elem) = q.try_pop() { assert!(elem > cur); cur = elem; if cur == CONC_COUNT - 1 { break } } } } let q: MsQueue = MsQueue::new(); assert!(q.is_empty()); let qr = &q; scope(|scope| { for i in 0..3 { scope.spawn(move || recv(i, qr)); } scope.spawn(|| { for i in 0..CONC_COUNT { q.push(i); } }) }); } #[test] fn push_try_pop_many_mpmc() { enum LR { Left(i64), Right(i64) } let q: MsQueue = MsQueue::new(); assert!(q.is_empty()); scope(|scope| { for _t in 0..2 { scope.spawn(|| { for i in CONC_COUNT-1..CONC_COUNT { q.push(LR::Left(i)) } }); scope.spawn(|| { for i in CONC_COUNT-1..CONC_COUNT { q.push(LR::Right(i)) } }); scope.spawn(|| { let mut vl = vec![]; let mut vr = vec![]; for _i in 0..CONC_COUNT { match q.try_pop() { Some(LR::Left(x)) => vl.push(x), Some(LR::Right(x)) => vr.push(x), _ => {} } } let mut vl2 = vl.clone(); let mut vr2 = vr.clone(); vl2.sort(); vr2.sort(); assert_eq!(vl, vl2); assert_eq!(vr, vr2); }); } }); } #[test] fn push_pop_many_spsc() { let q: MsQueue = MsQueue::new(); scope(|scope| { scope.spawn(|| { let mut next = 0; while next < CONC_COUNT { assert_eq!(q.pop(), next); next += 1; } }); for i in 0..CONC_COUNT { q.push(i) } }); assert!(q.is_empty()); } #[test] fn is_empty_dont_pop() { let q: MsQueue = MsQueue::new(); q.push(20); q.push(20); assert!(!q.is_empty()); assert!(!q.is_empty()); assert!(q.try_pop().is_some()); } } vendor/crossbeam-0.3.2/src/sync/seg_queue.rs0000664000000000000000000001775513264166600017605 0ustar rootrootuse std::sync::atomic::Ordering::{Acquire, Release, Relaxed}; use std::sync::atomic::{AtomicBool, AtomicUsize}; use std::fmt; use std::{ptr, mem}; use std::cmp; use std::cell::UnsafeCell; use epoch::{self, Atomic, Owned}; const SEG_SIZE: usize = 32; /// A Michael-Scott queue that allocates "segments" (arrays of nodes) /// for efficiency. /// /// Usable with any number of producers and consumers. #[derive(Debug)] pub struct SegQueue { head: Atomic>, tail: Atomic>, } struct Segment { low: AtomicUsize, data: [UnsafeCell<(T, AtomicBool)>; SEG_SIZE], high: AtomicUsize, next: Atomic>, } impl fmt::Debug for Segment { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Segment {{ ... }}") } } unsafe impl Sync for Segment {} impl Segment { fn new() -> Segment { let rqueue = Segment { data: unsafe { mem::uninitialized() }, low: AtomicUsize::new(0), high: AtomicUsize::new(0), next: Atomic::null(), }; for val in rqueue.data.iter() { unsafe { (*val.get()).1 = AtomicBool::new(false); } } rqueue } } impl SegQueue { /// Create a new, empty queue. pub fn new() -> SegQueue { let q = SegQueue { head: Atomic::null(), tail: Atomic::null(), }; let sentinel = Owned::new(Segment::new()); let guard = epoch::pin(); let sentinel = q.head.store_and_ref(sentinel, Relaxed, &guard); q.tail.store_shared(Some(sentinel), Relaxed); q } /// Add `t` to the back of the queue. pub fn push(&self, t: T) { let guard = epoch::pin(); loop { let tail = self.tail.load(Acquire, &guard).unwrap(); if tail.high.load(Relaxed) >= SEG_SIZE { continue } let i = tail.high.fetch_add(1, Relaxed); unsafe { if i < SEG_SIZE { let cell = (*tail).data.get_unchecked(i).get(); ptr::write(&mut (*cell).0, t); (*cell).1.store(true, Release); if i + 1 == SEG_SIZE { let tail = tail.next.store_and_ref(Owned::new(Segment::new()), Release, &guard); self.tail.store_shared(Some(tail), Release); } return } } } } /// Judge if the queue is empty. /// /// Returns `true` if the queue is empty. pub fn is_empty(&self) -> bool { let guard = epoch::pin(); let head = self.head.load(Acquire, &guard).unwrap(); let tail = self.tail.load(Acquire, &guard).unwrap(); if head.as_raw() != tail.as_raw() { return false; } let low = head.low.load(Relaxed); low >= cmp::min(head.high.load(Relaxed), SEG_SIZE) } /// Attempt to dequeue from the front. /// /// Returns `None` if the queue is observed to be empty. pub fn try_pop(&self) -> Option { let guard = epoch::pin(); loop { let head = self.head.load(Acquire, &guard).unwrap(); loop { let low = head.low.load(Relaxed); if low >= cmp::min(head.high.load(Relaxed), SEG_SIZE) { break } if head.low.compare_and_swap(low, low+1, Relaxed) == low { unsafe { let cell = (*head).data.get_unchecked(low).get(); loop { if (*cell).1.load(Acquire) { break } } if low + 1 == SEG_SIZE { loop { if let Some(next) = head.next.load(Acquire, &guard) { self.head.store_shared(Some(next), Release); guard.unlinked(head); break } } } return Some(ptr::read(&(*cell).0)) } } } if head.next.load(Relaxed, &guard).is_none() { return None } } } } impl Drop for SegQueue { fn drop(&mut self) { while self.try_pop().is_some() {} // Destroy the remaining sentinel segment. let guard = epoch::pin(); let sentinel = self.head.load(Relaxed, &guard).unwrap().as_raw(); unsafe { drop(Vec::from_raw_parts(sentinel, 0, 1)); } } } #[cfg(test)] mod test { const CONC_COUNT: i64 = 1000000; use scope; use super::*; #[test] fn push_pop_1() { let q: SegQueue = SegQueue::new(); q.push(37); assert_eq!(q.try_pop(), Some(37)); } #[test] fn push_pop_2() { let q: SegQueue = SegQueue::new(); q.push(37); q.push(48); assert_eq!(q.try_pop(), Some(37)); assert_eq!(q.try_pop(), Some(48)); } #[test] fn push_pop_empty_check() { let q: SegQueue = SegQueue::new(); assert_eq!(q.is_empty(), true); q.push(42); assert_eq!(q.is_empty(), false); assert_eq!(q.try_pop(), Some(42)); assert_eq!(q.is_empty(), true); } #[test] fn push_pop_many_seq() { let q: SegQueue = SegQueue::new(); for i in 0..200 { q.push(i) } for i in 0..200 { assert_eq!(q.try_pop(), Some(i)); } } #[test] fn push_pop_many_spsc() { let q: SegQueue = SegQueue::new(); scope(|scope| { scope.spawn(|| { let mut next = 0; while next < CONC_COUNT { if let Some(elem) = q.try_pop() { assert_eq!(elem, next); next += 1; } } }); for i in 0..CONC_COUNT { q.push(i) } }); } #[test] fn push_pop_many_spmc() { fn recv(_t: i32, q: &SegQueue) { let mut cur = -1; for _i in 0..CONC_COUNT { if let Some(elem) = q.try_pop() { assert!(elem > cur); cur = elem; if cur == CONC_COUNT - 1 { break } } } } let q: SegQueue = SegQueue::new(); let qr = &q; scope(|scope| { for i in 0..3 { scope.spawn(move || recv(i, qr)); } scope.spawn(|| { for i in 0..CONC_COUNT { q.push(i); } }) }); } #[test] fn push_pop_many_mpmc() { enum LR { Left(i64), Right(i64) } let q: SegQueue = SegQueue::new(); scope(|scope| { for _t in 0..2 { scope.spawn(|| { for i in CONC_COUNT-1..CONC_COUNT { q.push(LR::Left(i)) } }); scope.spawn(|| { for i in CONC_COUNT-1..CONC_COUNT { q.push(LR::Right(i)) } }); scope.spawn(|| { let mut vl = vec![]; let mut vr = vec![]; for _i in 0..CONC_COUNT { match q.try_pop() { Some(LR::Left(x)) => vl.push(x), Some(LR::Right(x)) => vr.push(x), _ => {} } } let mut vl2 = vl.clone(); let mut vr2 = vr.clone(); vl2.sort(); vr2.sort(); assert_eq!(vl, vl2); assert_eq!(vr, vr2); }); } }); } } vendor/crossbeam-0.3.2/src/sync/treiber_stack.rs0000664000000000000000000000556413264166600020437 0ustar rootrootuse std::sync::atomic::Ordering::{Acquire, Release, Relaxed}; use std::ptr; use epoch::{self, Atomic, Owned}; /// Treiber's lock-free stack. /// /// Usable with any number of producers and consumers. #[derive(Debug)] pub struct TreiberStack { head: Atomic>, } #[derive(Debug)] struct Node { data: T, next: Atomic>, } impl TreiberStack { /// Create a new, empty stack. pub fn new() -> TreiberStack { TreiberStack { head: Atomic::null() } } /// Push `t` on top of the stack. pub fn push(&self, t: T) { let mut n = Owned::new(Node { data: t, next: Atomic::null(), }); let guard = epoch::pin(); loop { let head = self.head.load(Relaxed, &guard); n.next.store_shared(head, Relaxed); match self.head.cas_and_ref(head, n, Release, &guard) { Ok(_) => break, Err(owned) => n = owned, } } } /// Attempt to pop the top element of the stack. /// **Deprecated method**, use try_pop /// /// Returns `None` if the stack is observed to be empty. #[cfg_attr(any(feature="beta", feature="nightly"), deprecated(note="The pop method has been renamed to try_pop for consistency with other collections."))] pub fn pop(&self) -> Option { self.try_pop() } /// Attempt to pop the top element of the stack. /// /// Returns `None` if the stack is observed to be empty. pub fn try_pop(&self) -> Option { let guard = epoch::pin(); loop { match self.head.load(Acquire, &guard) { Some(head) => { let next = head.next.load(Relaxed, &guard); if self.head.cas_shared(Some(head), next, Release) { unsafe { guard.unlinked(head); return Some(ptr::read(&(*head).data)); } } } None => return None, } } } /// Check if this queue is empty. pub fn is_empty(&self) -> bool { let guard = epoch::pin(); self.head.load(Acquire, &guard).is_none() } } impl Drop for TreiberStack { fn drop(&mut self) { while self.try_pop().is_some() {} } } impl Default for TreiberStack { fn default() -> Self { TreiberStack::new() } } #[cfg(test)] mod test { use super::*; #[test] fn is_empty() { let q: TreiberStack = TreiberStack::new(); assert!(q.is_empty()); q.push(20); q.push(20); assert!(!q.is_empty()); assert!(!q.is_empty()); assert!(q.try_pop().is_some()); assert!(q.try_pop().is_some()); assert!(q.is_empty()); q.push(25); assert!(!q.is_empty()); } } vendor/crypto-hash-0.3.1/0000755000000000000000000000000013264166600013753 5ustar rootrootvendor/crypto-hash-0.3.1/.cargo-checksum.json0000644000000000000000000000013113264166600017612 0ustar rootroot{"files":{},"package":"09de9ee0fc255ace04c7fa0763c9395a945c37c8292bb554f8d48361d1dcf1b4"}vendor/crypto-hash-0.3.1/CONTRIBUTING.md0000644000000000000000000000625013264166600016207 0ustar rootroot# Contributing to `crypto-hash` `crypto-hash` is a part of the Rust ecosystem. As such, all contributions to this project follow the [Rust language's code of conduct](https://www.rust-lang.org/conduct.html) where appropriate. This project is hosted at [GitHub](https://github.com/malept/crypto-hash). Both pull requests and issues of many different kinds are accepted. ## Filing Issues Issues include bugs, questions, feedback, and feature requests. Before you file a new issue, please make sure that your issue has not already been filed by someone else. ### Filing Bugs When filing a bug, please include the following information: * Operating system and version. If on Linux, please also include the distribution name. * System architecture. Examples include: x86-64, x86, and ARMv7. * Rust version that compiled `crypto-hash`. * The version (and/or git revision) of `crypto-hash`. * A detailed list of steps to reproduce the bug. A minimal testcase would be very helpful, if possible. * If there any any error messages in the console, copying them in the bug summary will be very helpful. ## Adding a new implementation If you are requesting or adding a new library source for hash algorithms, please make sure that it supports all of the existing algorithms. For example, while the creator of this project supports the efforts of the team writing LibreSSL, it does not support the MD5 algorithm. ## Adding a new hash algorithm If you are requesting or adding a wrapper for a new hash algorithm, please make sure that it is available in all of the supported implementations listed in the README. ## Filing Pull Requests Here are some things to keep in mind as you file a pull request to fix a bug, add a new feature, etc.: * Travis CI (for Linux and OS X) and AppVeyor (for Windows) are used to make sure that the project builds as expected on the supported platforms, using the current stable and beta versions of Rust. Make sure the testsuite passes locally by running `cargo test`. * Unless it's impractical, please write tests for your changes. This will help spot regressions much easier. * If your PR changes the behavior of an existing feature, or adds a new feature, please add/edit the `rustdoc` inline documentation. * Please ensure that your changes follow the [rustfmt](https://github.com/rust-lang-nursery/rustfmt) coding standard, and do not produce any warnings when running the [clippy](https://github.com/Manishearth/rust-clippy) linter. * If you are contributing a nontrivial change, please add an entry to `NEWS.md`. The format is similar to the one described at [Keep a Changelog](http://keepachangelog.com/). * Please make sure your commits are rebased onto the latest commit in the master branch, and that you limit/squash the number of commits created to a "feature"-level. For instance: bad: ``` commit 1: add foo algorithm commit 2: run rustfmt commit 3: add test commit 4: add docs commit 5: add bar commit 6: add test + docs ``` good: ``` commit 1: add foo algorithm commit 2: add bar ``` If you are continuing the work of another person's PR and need to rebase/squash, please retain the attribution of the original author(s) and continue the work in subsequent commits. vendor/crypto-hash-0.3.1/Cargo.toml0000644000000000000000000000244213264166600015705 0ustar rootroot# 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 = "crypto-hash" version = "0.3.1" authors = ["Mark Lee"] exclude = [".*.yml", "ci/*"] description = "A wrapper for OS-level cryptographic hash functions" documentation = "https://docs.rs/crypto-hash" readme = "README.md" keywords = ["crypto", "hash", "digest"] license = "MIT" repository = "https://github.com/malept/crypto-hash" [dependencies.hex] version = "0.3" [target."cfg(not(any(target_os = \"windows\", target_os = \"macos\")))".dependencies.openssl] version = "0.10" [target."cfg(target_os = \"macos\")".dependencies.commoncrypto] version = "0.2" [target."cfg(target_os = \"windows\")".dependencies.winapi] version = "0.3" features = ["minwindef", "wincrypt"] [badges.appveyor] repository = "malept/crypto-hash" [badges.travis-ci] repository = "malept/crypto-hash" vendor/crypto-hash-0.3.1/LICENSE0000644000000000000000000000204313264166600014757 0ustar rootrootCopyright (c) 2015, 2016 Mark Lee 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. vendor/crypto-hash-0.3.1/Makefile0000644000000000000000000000127713264166600015422 0ustar rootrootCARGO ?= cargo CARGO_BUILD_TEST = $(CARGO) test --no-run KCOV ?= kcov TEST_APP = debug/crypto_hash-*.exe WIN_TARGET = x86_64-pc-windows-gnu build-test: $(CARGO_BUILD_TEST) check-i686: PKG_CONFIG_LIBDIR=/usr/lib/i386-linux-gnu/pkgconfig \ PKG_CONFIG_ALLOW_CROSS=1 \ $(CARGO) test --target i686-unknown-linux-gnu --verbose check-wine64: $(CARGO_BUILD_TEST) --target $(WIN_TARGET) WINEPREFIX=$(HOME)/.local/share/wineprefixes/wine64 wine64 target/$(WIN_TARGET)/$(TEST_APP) cov: build-test $(KCOV) --exclude-pattern=/.multirust,test.rs target/cov target/$(TEST_APP) debug: build-test rust-gdb target/$(TEST_APP) fmt: $(CARGO) fmt lint: $(CARGO) +nightly clippy -- --allow clippy-pedantic vendor/crypto-hash-0.3.1/NEWS.md0000644000000000000000000000221613264166600015052 0ustar rootroot# Changes by Version ## Unreleased ## [0.3.1] - 2018-02-14 [0.3.1]: https://github.com/malept/crypto-hash/compare/v0.3.0...v0.3.1 ### Changed * Upgrade to `openssl` 0.10.x (#1) * Upgrade to `winapi` 0.3.x ## [0.3.0] - 2017-06-18 [0.3.0]: https://github.com/malept/crypto-hash/compare/v0.2.1...v0.3.0 ### Changed * Upgrade to `commoncrypto` 0.2.x * Function signatures for `digest` and `hex_digest` changed to use `&[u8]`, per Clippy ## [0.2.1] - 2016-12-12 [0.2.1]: https://github.com/malept/crypto-hash/compare/v0.2.0...v0.2.1 ### Changed * Move CommonCrypto implementation to its own crate ## [0.2.0] - 2016-11-06 [0.2.0]: https://github.com/malept/crypto-hash/compare/v0.1.0...v0.2.0 ### Added * SHA-1 algorithm ### Changed * Upgrade rust-openssl to 0.9 ## [0.1.0] - 2016-06-26 [0.1.0]: https://github.com/malept/crypto-hash/releases/tag/v0.1.0 This release signifies the minimum amount of algorithms and implementations necessary for [HTTP digest authentication](https://tools.ietf.org/html/rfc7616). ### Added Algorithms: * MD5 * SHA256 * SHA512 Implementations: * CommonCrypto (OS X) * CryptoAPI (Windows) * OpenSSL (Linux/BSD/etc.) vendor/crypto-hash-0.3.1/README.md0000644000000000000000000000346213264166600015237 0ustar rootroot# `crypto-hash` [![Linux/OS X Status](https://travis-ci.org/malept/crypto-hash.svg?branch=master)](https://travis-ci.org/malept/crypto-hash) [![Windows status](https://ci.appveyor.com/api/projects/status/xwc9nb4633b5n67r/branch/master?svg=true)](https://ci.appveyor.com/project/malept/crypto-hash) [![Crates.io](https://img.shields.io/crates/v/crypto-hash.svg?maxAge=2592000)](https://crates.io/crates/crypto-hash) `crypto-hash` is a Rust wrapper around OS-level implementations of cryptographic hash functions. The purpose of this crate is to provide access to hash algorithms with as few dependencies as possible. This means that when possible, the library uses the hashing functions that are provided by the given operating system's bundled cryptographic libraries. ## Supported Implementations By operating system: * Windows: CryptoAPI * OS X: [CommonCrypto](https://crates.io/crates/commoncrypto) * Linux/BSD/etc.: [OpenSSL](https://crates.io/crates/openssl) ## Supported Algorithms * MD5 * SHA1 * SHA256 * SHA512 ## Usage Add `crypto-hash` to your project's `Cargo.toml`. For more details, consult the [Cargo guide](http://doc.crates.io/guide.html#adding-dependencies). Example: ```rust use crypto_hash::{Algorithm, hex_digest}; let digest = hex_digest(Algorithm::SHA256, b"crypto-hash"); ``` For more examples, consult the [documentation](https://malept.github.io/crypto-hash/). ## [Release Notes](https://github.com/malept/crypto-hash/blob/master/NEWS.md) ## [Contributing](https://github.com/malept/crypto-hash/blob/master/CONTRIBUTING.md) ## Acknowledgements This crate was inspired by [rust-native-tls](https://github.com/sfackler/rust-native-tls) and [crypto-bench](https://github.com/briansmith/crypto-bench). ## Legal `crypto-hash` is copyrighted under the terms of the MIT license. See LICENSE for details. vendor/crypto-hash-0.3.1/src/0000755000000000000000000000000013264166600014542 5ustar rootrootvendor/crypto-hash-0.3.1/src/imp/0000755000000000000000000000000013264166600015327 5ustar rootrootvendor/crypto-hash-0.3.1/src/imp/commoncrypto.rs0000644000000000000000000000555413264166600020437 0ustar rootroot// Copyright (c) 2016 Mark Lee // // 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. //! A cryptographic hash generator dependent upon OSX's `CommonCrypto`. use commoncrypto::hash; use std::io; use super::Algorithm; /// Generator of digests using a cryptographic hash function. /// /// # Examples /// /// ```rust /// use crypto_hash::{Algorithm, Hasher}; /// use std::io::Write; /// /// let mut hasher = Hasher::new(Algorithm::SHA256); /// hasher.write_all(b"crypto"); /// hasher.write_all(b"-"); /// hasher.write_all(b"hash"); /// let result = hasher.finish(); /// let expected = /// b"\xfd\x1a\xfb`\"\xcdMG\xc8\x90\x96\x1cS9(\xea\xcf\xe8!\x9f\x1b%$\xf7\xfb*a\x84}\xdf\x8c'" /// .to_vec(); /// assert_eq!(expected, result) /// ``` #[derive(Debug)] pub struct Hasher(hash::Hasher); impl Hasher { /// Create a new `Hasher` for the given `Algorithm`. pub fn new(algorithm: Algorithm) -> Hasher { let cc_algorithm = match algorithm { Algorithm::MD5 => hash::CCDigestAlgorithm::kCCDigestMD5, Algorithm::SHA1 => hash::CCDigestAlgorithm::kCCDigestSHA1, Algorithm::SHA256 => hash::CCDigestAlgorithm::kCCDigestSHA256, Algorithm::SHA512 => hash::CCDigestAlgorithm::kCCDigestSHA512, }; Hasher(hash::Hasher::new(cc_algorithm)) } /// Generate a digest from the data written to the `Hasher`. pub fn finish(&mut self) -> Vec { let Hasher(ref mut hasher) = *self; match hasher.finish() { Ok(digest) => digest, Err(error) => panic!("CommonCrypto error: {}", error), } } } impl io::Write for Hasher { fn write(&mut self, buf: &[u8]) -> io::Result { let Hasher(ref mut hasher) = *self; hasher.write(buf) } fn flush(&mut self) -> io::Result<()> { let Hasher(ref mut hasher) = *self; hasher.flush() } } vendor/crypto-hash-0.3.1/src/imp/cryptoapi.rs0000644000000000000000000001215713264166600017715 0ustar rootroot// Copyright (c) 2016 Mark Lee // // 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. //! A cryptographic hash generator dependent upon Windows's `CryptoAPI`. //! //! Originally based on: //! https://github.com/rust-lang/cargo/blob/0.10.0/src/cargo/util/sha256.rs //! which is copyright (c) 2014 The Rust Project Developers under the MIT license. use std::io; use std::ptr; use super::Algorithm; use winapi::shared::minwindef::DWORD; use winapi::um::wincrypt::{CALG_MD5, CALG_SHA1, CALG_SHA_256, CALG_SHA_512, CryptAcquireContextW, CryptCreateHash, CryptDestroyHash, CryptGetHashParam, CryptHashData, CryptReleaseContext, CRYPT_SILENT, CRYPT_VERIFYCONTEXT, HCRYPTHASH, HCRYPTPROV, HP_HASHVAL, PROV_RSA_AES}; macro_rules! call { ($e: expr) => ({ if $e == 0 { panic!("failed {}: {}", stringify!($e), io::Error::last_os_error()) } }) } macro_rules! finish_algorithm { ($func_name: ident, $size: ident) => { fn $func_name(&mut self) -> Vec { let mut len = $size as u32; let mut hash = [0u8; $size]; call!(unsafe { CryptGetHashParam(self.hcrypthash, HP_HASHVAL, hash.as_mut_ptr(), &mut len, 0) }); assert_eq!(len as usize, hash.len()); hash.to_vec() } } } const MD5_LENGTH: usize = 16; const SHA1_LENGTH: usize = 20; const SHA256_LENGTH: usize = 32; const SHA512_LENGTH: usize = 64; /// Generator of digests using a cryptographic hash function. /// /// # Examples /// /// ```rust /// use crypto_hash::{Algorithm, Hasher}; /// use std::io::Write; /// /// let mut hasher = Hasher::new(Algorithm::SHA256); /// hasher.write_all(b"crypto"); /// hasher.write_all(b"-"); /// hasher.write_all(b"hash"); /// let result = hasher.finish(); /// let expected = /// b"\xfd\x1a\xfb`\"\xcdMG\xc8\x90\x96\x1cS9(\xea\xcf\xe8!\x9f\x1b%$\xf7\xfb*a\x84}\xdf\x8c'" /// .to_vec(); /// assert_eq!(expected, result) /// ``` pub struct Hasher { algorithm: Algorithm, hcryptprov: HCRYPTPROV, hcrypthash: HCRYPTHASH, } impl Hasher { /// Create a new `Hasher` for the given `Algorithm`. pub fn new(algorithm: Algorithm) -> Hasher { let mut hcp = 0; call!(unsafe { CryptAcquireContextW( &mut hcp, ptr::null(), ptr::null(), PROV_RSA_AES, CRYPT_VERIFYCONTEXT | CRYPT_SILENT, ) }); let hash_type = match algorithm { Algorithm::MD5 => CALG_MD5, Algorithm::SHA1 => CALG_SHA1, Algorithm::SHA256 => CALG_SHA_256, Algorithm::SHA512 => CALG_SHA_512, }; let mut ret = Hasher { algorithm: algorithm, hcryptprov: hcp, hcrypthash: 0, }; call!(unsafe { CryptCreateHash(ret.hcryptprov, hash_type, 0, 0, &mut ret.hcrypthash) }); ret } /// Generate a digest from the data written to the `Hasher`. pub fn finish(&mut self) -> Vec { match self.algorithm { Algorithm::MD5 => self.finish_md5(), Algorithm::SHA1 => self.finish_sha1(), Algorithm::SHA256 => self.finish_sha256(), Algorithm::SHA512 => self.finish_sha512(), } } finish_algorithm!(finish_md5, MD5_LENGTH); finish_algorithm!(finish_sha1, SHA1_LENGTH); finish_algorithm!(finish_sha256, SHA256_LENGTH); finish_algorithm!(finish_sha512, SHA512_LENGTH); } impl io::Write for Hasher { fn write(&mut self, buf: &[u8]) -> io::Result { call!(unsafe { CryptHashData( self.hcrypthash, buf.as_ptr() as *mut _, buf.len() as DWORD, 0, ) }); Ok(buf.len()) } fn flush(&mut self) -> io::Result<()> { Ok(()) } } impl Drop for Hasher { fn drop(&mut self) { if self.hcrypthash != 0 { call!(unsafe { CryptDestroyHash(self.hcrypthash) }); } call!(unsafe { CryptReleaseContext(self.hcryptprov, 0) }); } } vendor/crypto-hash-0.3.1/src/imp/openssl.rs0000644000000000000000000000572213264166600017366 0ustar rootroot// Copyright (c) 2015, 2016 Mark Lee // // 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. //! A cryptographic hash digest generator dependent upon `OpenSSL`. #![warn(missing_docs)] use openssl::hash; use std::io; use super::Algorithm; /// Generator of digests using a cryptographic hash function. /// /// # Examples /// /// ```rust /// use crypto_hash::{Algorithm, Hasher}; /// use std::io::Write; /// /// let mut hasher = Hasher::new(Algorithm::SHA256); /// hasher.write_all(b"crypto"); /// hasher.write_all(b"-"); /// hasher.write_all(b"hash"); /// let result = hasher.finish(); /// let expected = /// b"\xfd\x1a\xfb`\"\xcdMG\xc8\x90\x96\x1cS9(\xea\xcf\xe8!\x9f\x1b%$\xf7\xfb*a\x84}\xdf\x8c'" /// .to_vec(); /// assert_eq!(expected, result) /// ``` pub struct Hasher(hash::Hasher); impl Hasher { /// Create a new `Hasher` for the given `Algorithm`. pub fn new(algorithm: Algorithm) -> Hasher { let hash_type = match algorithm { Algorithm::MD5 => hash::MessageDigest::md5(), Algorithm::SHA1 => hash::MessageDigest::sha1(), Algorithm::SHA256 => hash::MessageDigest::sha256(), Algorithm::SHA512 => hash::MessageDigest::sha512(), }; match hash::Hasher::new(hash_type) { Ok(hasher) => Hasher(hasher), Err(error_stack) => panic!("OpenSSL error(s): {}", error_stack), } } /// Generate a digest from the data written to the `Hasher`. pub fn finish(&mut self) -> Vec { let Hasher(ref mut hasher) = *self; match hasher.finish() { Ok(digest) => digest.to_vec(), Err(error_stack) => panic!("OpenSSL error(s): {}", error_stack), } } } impl io::Write for Hasher { fn write(&mut self, buf: &[u8]) -> io::Result { let Hasher(ref mut hasher) = *self; hasher.write(buf) } fn flush(&mut self) -> io::Result<()> { let Hasher(ref mut hasher) = *self; hasher.flush() } } vendor/crypto-hash-0.3.1/src/lib.rs0000644000000000000000000000751713264166600015670 0ustar rootroot// Copyright (c) 2015, 2016, 2017 Mark Lee // // 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. //! A set of [cryptographic hash //! functions](https://en.wikipedia.org/wiki/Cryptographic_hash_function) provided by the operating //! system, when available. //! //! The purpose of this crate is to provide access to hash algorithms with as few dependencies as //! possible. This means that when possible, the library uses the hashing functions that are //! provided by the given operating system's bundled cryptographic libraries. //! //! # Supported Implementations //! //! By operating system: //! //! * Windows: `CryptoAPI` //! * Mac OS X: `CommonCrypto` //! * Linux/BSD/etc.: `OpenSSL` //! //! # Supported Algorithms //! //! * MD5 //! * SHA1 //! * SHA256 //! * SHA512 #![warn(missing_docs)] #[cfg(target_os = "macos")] extern crate commoncrypto; extern crate hex; #[cfg(not(any(target_os = "macos", target_os = "windows")))] extern crate openssl; #[cfg(target_os = "windows")] extern crate winapi; use std::io::Write; #[cfg(target_os = "macos")] #[path = "imp/commoncrypto.rs"] mod imp; #[cfg(target_os = "windows")] #[path = "imp/cryptoapi.rs"] mod imp; #[cfg(not(any(target_os = "macos", target_os = "windows")))] #[path = "imp/openssl.rs"] mod imp; mod test; pub use imp::Hasher; /// Available cryptographic hash functions. #[derive(Clone, Debug)] pub enum Algorithm { /// Popular message digest algorithm, only available for backwards compatibility purposes. MD5, /// SHA-1 algorithm from NIST FIPS, only available for backwards compatibility purposes. SHA1, /// SHA-2 family algorithm (256 bits). SHA256, /// SHA-2 family algorithm (512 bits). SHA512, } /// Helper function for `Hasher` which generates a cryptographic digest from the given /// data and algorithm. /// /// # Examples /// /// ```rust /// use crypto_hash::{Algorithm, digest}; /// /// let data = b"crypto-hash"; /// let result = digest(Algorithm::SHA256, data); /// let expected = /// b"\xfd\x1a\xfb`\"\xcdMG\xc8\x90\x96\x1cS9(\xea\xcf\xe8!\x9f\x1b%$\xf7\xfb*a\x84}\xdf\x8c'" /// .to_vec(); /// assert_eq!(expected, result) /// ``` pub fn digest(algorithm: Algorithm, data: &[u8]) -> Vec { let mut hasher = imp::Hasher::new(algorithm); hasher.write_all(data).expect("Could not write hash data"); hasher.finish() } /// Helper function for `Hasher` which generates a cryptographic digest serialized in /// hexadecimal from the given data and algorithm. /// /// # Examples /// /// ```rust /// use crypto_hash::{Algorithm, hex_digest}; /// /// let data = b"crypto-hash"; /// let result = hex_digest(Algorithm::SHA256, data); /// let expected = "fd1afb6022cd4d47c890961c533928eacfe8219f1b2524f7fb2a61847ddf8c27"; /// assert_eq!(expected, result) /// ``` pub fn hex_digest(algorithm: Algorithm, data: &[u8]) -> String { hex::encode(digest(algorithm, data)) } vendor/crypto-hash-0.3.1/src/test.rs0000644000000000000000000000556713264166600016104 0ustar rootroot// Copyright (c) 2016, 2017 Mark Lee // // 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. #![cfg(test)] use hex; use std::io::Write; use super::{hex_digest, Algorithm, Hasher}; // From Wikipedia const MD5_EMPTY_STRING: &'static str = "d41d8cd98f00b204e9800998ecf8427e"; const SHA1_EMPTY_STRING: &'static str = "da39a3ee5e6b4b0d3255bfef95601890afd80709"; const SHA256_EMPTY_STRING: &'static str = concat!( "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649", "b934ca495991b7852b855" ); const SHA512_EMPTY_STRING: &'static str = concat!( "cf83e1357eefb8bdf1542850d66d8007d620e4050b5", "715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318", "d2877eec2f63b931bd47417a81a538327af927da3e" ); const TO_HASH: &'static str = "The quick brown fox jumps over the lazy dog"; const TO_HASH_MD5: &'static str = "9e107d9d372bb6826bd81d3542a419d6"; #[test] fn md5_empty_string() { assert_hex_hashed_empty_string(Algorithm::MD5, MD5_EMPTY_STRING) } #[test] fn sha1_empty_string() { assert_hex_hashed_empty_string(Algorithm::SHA1, SHA1_EMPTY_STRING) } #[test] fn sha256_empty_string() { // From Wikipedia assert_hex_hashed_empty_string(Algorithm::SHA256, SHA256_EMPTY_STRING) } #[test] fn sha512_empty_string() { assert_hex_hashed_empty_string(Algorithm::SHA512, SHA512_EMPTY_STRING) } #[test] fn hasher_sans_write() { let mut hasher = Hasher::new(Algorithm::MD5); let actual = hex::encode(hasher.finish()); assert_eq!(MD5_EMPTY_STRING, actual) } #[test] fn hasher_with_write() { let mut hasher = Hasher::new(Algorithm::MD5); hasher .write_all(TO_HASH.as_bytes()) .expect("Could not write to hasher"); let actual = hex::encode(hasher.finish()); assert_eq!(TO_HASH_MD5, actual) } fn assert_hex_hashed_empty_string(algorithm: Algorithm, expected: &str) { let vec = vec![]; assert_eq!(expected, hex_digest(algorithm, vec.as_slice()).as_str()) } vendor/curl-0.4.11/0000755000000000000000000000000013264166600012541 5ustar rootrootvendor/curl-0.4.11/.cargo-checksum.json0000644000000000000000000000013113264166600016400 0ustar rootroot{"files":{},"package":"b70fd6394677d3c0e239ff4be6f2b3176e171ffd1c23ffdc541e78dea2b8bb5e"}vendor/curl-0.4.11/.gitmodules0000664000000000000000000000013613264166600014720 0ustar rootroot[submodule "curl-sys/curl"] path = curl-sys/curl url = https://github.com/alexcrichton/curl vendor/curl-0.4.11/.travis.yml0000664000000000000000000000371613264166600014663 0ustar rootrootlanguage: rust sudo: required dist: trusty services: - docker matrix: include: - os: linux rust: stable env: TARGET=x86_64-unknown-linux-gnu DOCKER=linux64 NO_ADD=1 - os: linux rust: stable env: TARGET=i686-unknown-linux-gnu DOCKER=linux32 - os: linux rust: stable env: TARGET=x86_64-unknown-linux-musl DOCKER=musl - os: linux rust: stable env: TARGET=x86_64-pc-windows-gnu NO_RUN=1 DOCKER=mingw - os: linux rust: stable env: TARGET=x86_64-unknown-linux-gnu DOCKER=linux64-curl NO_ADD=1 - os: osx rust: stable env: TARGET=x86_64-apple-darwin NO_ADD=1 - os: osx rust: stable env: TARGET=i686-apple-darwin - os: linux rust: beta env: TARGET=x86_64-unknown-linux-gnu DOCKER=linux64 NO_ADD=1 - os: linux rust: nightly env: TARGET=x86_64-unknown-linux-gnu DOCKER=linux64 NO_ADD=1 before_script: - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH after_success: - travis-cargo doc-upload sudo: false install: - if [ -z "$NO_ADD" ]; then rustup target add $TARGET; fi script: - curl --version - cargo generate-lockfile - cargo generate-lockfile --manifest-path systest/Cargo.toml - if [ -z "$DOCKER" ]; then sh ci/run.sh; else mkdir .cargo target; docker build -t rust -f ci/Dockerfile-$DOCKER ci; docker run -w /src -v `pwd`:/src:ro -v `pwd`/target:/src/target -v `pwd`/ci/.cargo:/src/.cargo:ro -v `rustc --print sysroot`:/usr/local:ro -e TARGET=$TARGET -e NO_RUN=$NO_RUN -e CARGO_TARGET_DIR=/src/target -it rust sh ci/run.sh; fi notifications: email: on_success: never env: global: secure: "j4son34/PmqogLMUHgcvOk+XtyUtcd0aAA8Sa/h4pyupw8AEM7+5DMMIrcrRh7ieKqmL2RSSGnYtYbd2b5yYroudypsqmQhK0StzrtPaftl/8zxw8liXzA9rat8MP0vuEAe5w9KLRdFKUCU7TzcYXcKttpbavqdNsJae+OFzHJc=" vendor/curl-0.4.11/Cargo.toml0000644000000000000000000000307413264166600014475 0ustar rootroot# 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 = "curl" version = "0.4.11" authors = ["Alex Crichton "] description = "Rust bindings to libcurl for making HTTP requests" homepage = "https://github.com/alexcrichton/curl-rust" documentation = "https://docs.rs/curl" categories = ["api-bindings", "web-programming::http-client"] license = "MIT" repository = "https://github.com/alexcrichton/curl-rust" [dependencies.curl-sys] version = "0.4.1" [dependencies.libc] version = "0.2" [dependencies.socket2] version = "0.3" [dev-dependencies.mio] version = "0.6" [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies.openssl-probe] version = "0.1" [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies.openssl-sys] version = "0.9.0" [target."cfg(target_env=\"msvc\")".dependencies.kernel32-sys] version = "0.2" [target."cfg(target_env=\"msvc\")".dependencies.schannel] version = "0.1.8" [target."cfg(windows)".dependencies.winapi] version = "0.2" [badges.appveyor] repository = "alexcrichton/curl-rust" [badges.travis-ci] repository = "alexcrichton/curl-rust" vendor/curl-0.4.11/LICENSE0000664000000000000000000000203713264166600013552 0ustar rootrootCopyright (c) 2014 Carl Lerche 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. vendor/curl-0.4.11/README.md0000664000000000000000000000640513264166600014027 0ustar rootroot# curl-rust libcurl bindings for Rust [![Build Status](https://travis-ci.org/alexcrichton/curl-rust.svg?branch=master)](https://travis-ci.org/alexcrichton/curl-rust) [![Build status](https://ci.appveyor.com/api/projects/status/lx98wtbxhhhajpr9?svg=true)](https://ci.appveyor.com/project/alexcrichton/curl-rust) [Documentation](https://docs.rs/curl) ## Quick Start ```rust extern crate curl; use std::io::{stdout, Write}; use curl::easy::Easy; // Print a web page onto stdout fn main() { let mut easy = Easy::new(); easy.url("https://www.rust-lang.org/").unwrap(); easy.write_function(|data| { Ok(stdout().write(data).unwrap()) }).unwrap(); easy.perform().unwrap(); println!("{}", easy.response_code().unwrap()); } ``` ```rust extern crate curl; use curl::easy::Easy; // Capture output into a local `Vec`. fn main() { let mut dst = Vec::new(); let mut easy = Easy::new(); easy.url("https://www.rust-lang.org/").unwrap(); let mut transfer = easy.transfer(); transfer.write_function(|data| { dst.extend_from_slice(data); Ok(data.len()) }).unwrap(); transfer.perform().unwrap(); } ``` ## Post / Put requests The `put` and `post` methods on `Easy` can configure the method of the HTTP request, and then `read_function` can be used to specify how data is filled in. This interface works particularly well with types that implement `Read`. ```rust,no_run extern crate curl; use std::io::Read; use curl::easy::Easy; fn main() { let mut data = "this is the body".as_bytes(); let mut easy = Easy::new(); easy.url("http://www.example.com/upload").unwrap(); easy.post(true).unwrap(); easy.post_field_size(data.len() as u64).unwrap(); let mut transfer = easy.transfer(); transfer.read_function(|buf| { Ok(data.read(buf).unwrap_or(0)) }).unwrap(); transfer.perform().unwrap(); } ``` ## Custom headers Custom headers can be specified as part of the request: ```rust,no_run extern crate curl; use curl::easy::{Easy, List}; fn main() { let mut easy = Easy::new(); easy.url("http://www.example.com").unwrap(); let mut list = List::new(); list.append("Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==").unwrap(); easy.http_headers(list).unwrap(); easy.perform().unwrap(); } ``` ## Keep alive The handle can be re-used across multiple requests. Curl will attempt to keep the connections alive. ```rust,no_run extern crate curl; use curl::easy::Easy; fn main() { let mut handle = Easy::new(); handle.url("http://www.example.com/foo").unwrap(); handle.perform().unwrap(); handle.url("http://www.example.com/bar").unwrap(); handle.perform().unwrap(); } ``` ## Multiple requests The libcurl library provides support for sending multiple requests simultaneously through the "multi" interface. This is currently bound in the `multi` module of this crate and provides the ability to execute multiple transfers simultaneously. For more information, see that module. ## Version Support The bindings have been developed using curl version 7.24.0. They should work with any newer version of curl and possibly with older versions, but this has not been tested. ## License The `curl-rust` crate is licensed under the MIT license, see `LICENSE` for more details. vendor/curl-0.4.11/appveyor.yml0000664000000000000000000000520413264166600015134 0ustar rootrootenvironment: matrix: # Ensure MinGW works, but we need to download the 32-bit MinGW compiler from a # custom location. - TARGET: i686-pc-windows-gnu MINGW_URL: https://s3.amazonaws.com/rust-lang-ci MINGW_ARCHIVE: i686-4.9.2-release-win32-dwarf-rt_v4-rev4.7z MINGW_DIR: mingw32 - TARGET: x86_64-pc-windows-gnu MSYS_BITS: 64 # Ensure vanilla builds work - TARGET: i686-pc-windows-msvc - TARGET: x86_64-pc-windows-msvc # Pin to specific VS versions to ensure the build works - TARGET: x86_64-pc-windows-msvc ARCH: amd64 VS: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat - TARGET: x86_64-pc-windows-msvc ARCH: amd64 VS: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat # Ensure getting libcurl from vcpkg works - TARGET: x86_64-pc-windows-msvc VCPKGRS_DYNAMIC: 1 VCPKG_DEFAULT_TRIPLET: x64-windows install: # Install rust, x86_64-pc-windows-msvc host - appveyor-retry appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe # use nightly if required until -Ctarget-feature=+crt-static is stable (expected in rust 1.19) - if not defined RUSTFLAGS rustup-init.exe -y --default-host x86_64-pc-windows-msvc - if defined RUSTFLAGS rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain nightly - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin # Install the target we're compiling for - if NOT "%TARGET%" == "x86_64-pc-windows-msvc" rustup target add %TARGET% # Use the system msys if we can - if defined MSYS_BITS set PATH=C:\msys64\mingw%MSYS_BITS%\bin;C:\msys64\usr\bin;%PATH% # download a custom compiler otherwise - if defined MINGW_URL appveyor DownloadFile %MINGW_URL%/%MINGW_ARCHIVE% - if defined MINGW_URL 7z x -y %MINGW_ARCHIVE% > nul - if defined MINGW_URL set PATH=C:\Python27;%CD%\%MINGW_DIR%\bin;C:\msys64\usr\bin;%PATH% # If we're pinning to a specific visual studio, do so now - if defined VS call "%VS%" %ARCH% # let's see what we got - where gcc rustc cargo - rustc -vV - cargo -vV - set CARGO_TARGET_DIR=%CD%\target # install vcpkg if required - if defined VCPKG_DEFAULT_TRIPLET git clone https://github.com/Microsoft/vcpkg c:\projects\vcpkg - if defined VCPKG_DEFAULT_TRIPLET c:\projects\vcpkg\bootstrap-vcpkg.bat - if defined VCPKG_DEFAULT_TRIPLET set VCPKG_ROOT=c:\projects\vcpkg - if defined VCPKG_DEFAULT_TRIPLET echo yes > %VCPKG_ROOT%\Downloads\AlwaysAllowDownloads - if defined VCPKG_DEFAULT_TRIPLET %VCPKG_ROOT%\vcpkg.exe install curl build: false test_script: - cargo test --target %TARGET% - cargo run --manifest-path systest/Cargo.toml --target %TARGET% vendor/curl-0.4.11/ci/0000755000000000000000000000000013264166600013134 5ustar rootrootvendor/curl-0.4.11/ci/.cargo/0000755000000000000000000000000013264166600014305 5ustar rootrootvendor/curl-0.4.11/ci/.cargo/config0000664000000000000000000000010113264166600015467 0ustar rootroot[target.x86_64-pc-windows-gnu] linker = "x86_64-w64-mingw32-gcc" vendor/curl-0.4.11/ci/Dockerfile-linux320000664000000000000000000000050013264166600016425 0ustar rootrootFROM ubuntu:16.04 RUN dpkg --add-architecture i386 && \ apt-get update && \ apt-get install -y --no-install-recommends \ gcc-multilib \ ca-certificates \ make \ libc6-dev \ libssl-dev:i386 \ pkg-config ENV PKG_CONFIG=i686-linux-gnu-pkg-config \ PKG_CONFIG_ALLOW_CROSS=1 vendor/curl-0.4.11/ci/Dockerfile-linux640000664000000000000000000000025713264166600016443 0ustar rootrootFROM ubuntu:16.04 RUN apt-get update RUN apt-get install -y --no-install-recommends \ gcc ca-certificates make libc6-dev \ libssl-dev \ pkg-config ENV FEATURES="http2"vendor/curl-0.4.11/ci/Dockerfile-linux64-curl0000664000000000000000000000025313264166600017402 0ustar rootrootFROM ubuntu:14.04 RUN apt-get update RUN apt-get install -y --no-install-recommends \ gcc ca-certificates make libc6-dev \ libssl-dev libcurl4-openssl-dev pkg-config vendor/curl-0.4.11/ci/Dockerfile-mingw0000664000000000000000000000025013264166600016244 0ustar rootrootFROM ubuntu:16.04 RUN apt-get update RUN apt-get install -y --no-install-recommends \ gcc ca-certificates make libc6-dev \ gcc-mingw-w64-x86-64 libz-mingw-w64-dev vendor/curl-0.4.11/ci/Dockerfile-musl0000664000000000000000000000071513264166600016111 0ustar rootrootFROM ubuntu:16.04 RUN apt-get update RUN apt-get install -y --no-install-recommends \ gcc ca-certificates make libc6-dev curl \ musl-tools RUN \ curl https://www.openssl.org/source/old/1.0.2/openssl-1.0.2g.tar.gz | tar xzf - && \ cd openssl-1.0.2g && \ CC=musl-gcc ./Configure --prefix=/openssl no-dso linux-x86_64 -fPIC && \ make -j10 && \ make install && \ cd .. && \ rm -rf openssl-1.0.2g ENV OPENSSL_STATIC=1 \ OPENSSL_DIR=/openssl vendor/curl-0.4.11/ci/run.sh0000664000000000000000000000061613264166600014301 0ustar rootroot#!/bin/sh set -ex cargo test --target $TARGET --no-run if [ -z "$NO_RUN" ]; then cargo test --target $TARGET cargo run --manifest-path systest/Cargo.toml --target $TARGET cargo doc --no-deps --target $TARGET cargo doc --no-deps -p curl-sys --target $TARGET fi if [ -n "$FEATURES" ] then cargo run --manifest-path systest/Cargo.toml --target $TARGET --features "$FEATURES" fi vendor/curl-0.4.11/src/0000755000000000000000000000000013264166600013330 5ustar rootrootvendor/curl-0.4.11/src/easy/0000755000000000000000000000000013264166600014271 5ustar rootrootvendor/curl-0.4.11/src/easy/form.rs0000664000000000000000000002547213264166600015616 0ustar rootrootuse std::ffi::CString; use std::fmt; use std::path::Path; use FormError; use curl_sys; use easy::{list, List}; /// Multipart/formdata for an HTTP POST request. /// /// This structure is built up and then passed to the `Easy::httppost` method to /// be sent off with a request. pub struct Form { head: *mut curl_sys::curl_httppost, tail: *mut curl_sys::curl_httppost, headers: Vec, buffers: Vec>, strings: Vec, } /// One part in a multipart upload, added to a `Form`. pub struct Part<'form, 'data> { form: &'form mut Form, name: &'data str, array: Vec, error: Option, } pub fn raw(form: &Form) -> *mut curl_sys::curl_httppost { form.head } impl Form { /// Creates a new blank form ready for the addition of new data. pub fn new() -> Form { Form { head: 0 as *mut _, tail: 0 as *mut _, headers: Vec::new(), buffers: Vec::new(), strings: Vec::new(), } } /// Prepares adding a new part to this `Form` /// /// Note that the part is not actually added to the form until the `add` /// method is called on `Part`, which may or may not fail. pub fn part<'a, 'data>(&'a mut self, name: &'data str) -> Part<'a, 'data> { Part { error: None, form: self, name: name, array: vec![curl_sys::curl_forms { option: curl_sys::CURLFORM_END, value: 0 as *mut _, }], } } } impl fmt::Debug for Form { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // TODO: fill this out more f.debug_struct("Form") .field("fields", &"...") .finish() } } impl Drop for Form { fn drop(&mut self) { unsafe { curl_sys::curl_formfree(self.head); } } } impl<'form, 'data> Part<'form, 'data> { /// A pointer to the contents of this part, the actual data to send away. pub fn contents(&mut self, contents: &'data [u8]) -> &mut Self { let pos = self.array.len() - 1; // curl has an oddity where if the length if 0 it will call strlen // on the value. This means that if someone wants to add empty form // contents we need to make sure the buffer contains a null byte. let ptr = if contents.is_empty() { b"\x00" } else { contents }.as_ptr(); self.array.insert(pos, curl_sys::curl_forms { option: curl_sys::CURLFORM_COPYCONTENTS, value: ptr as *mut _, }); self.array.insert(pos + 1, curl_sys::curl_forms { option: curl_sys::CURLFORM_CONTENTSLENGTH, value: contents.len() as *mut _, }); self } /// Causes this file to be read and its contents used as data in this part /// /// This part does not automatically become a file upload part simply /// because its data was read from a file. /// /// # Errors /// /// If the filename has any internal nul bytes or if on Windows it does not /// contain a unicode filename then the `add` function will eventually /// return an error. pub fn file_content

(&mut self, file: P) -> &mut Self where P: AsRef { self._file_content(file.as_ref()) } fn _file_content(&mut self, file: &Path) -> &mut Self { if let Some(bytes) = self.path2cstr(file) { let pos = self.array.len() - 1; self.array.insert(pos, curl_sys::curl_forms { option: curl_sys::CURLFORM_FILECONTENT, value: bytes.as_ptr() as *mut _, }); self.form.strings.push(bytes); } self } /// Makes this part a file upload part of the given file. /// /// Sets the filename field to the basename of the provided file name, and /// it reads the contents of the file and passes them as data and sets the /// content type if the given file matches one of the internally known file /// extensions. /// /// The given upload file must exist entirely on the filesystem before the /// upload is started because libcurl needs to read the size of it /// beforehand. /// /// Multiple files can be uploaded by calling this method multiple times and /// content types can also be configured for each file (by calling that /// next). /// /// # Errors /// /// If the filename has any internal nul bytes or if on Windows it does not /// contain a unicode filename then this function will cause `add` to return /// an error when called. pub fn file(&mut self, file: &'data P) -> &mut Self where P: AsRef { self._file(file.as_ref()) } fn _file(&mut self, file: &'data Path) -> &mut Self { if let Some(bytes) = self.path2cstr(file) { let pos = self.array.len() - 1; self.array.insert(pos, curl_sys::curl_forms { option: curl_sys::CURLFORM_FILE, value: bytes.as_ptr() as *mut _, }); self.form.strings.push(bytes); } self } /// Used in combination with `Part::file`, provides the content-type for /// this part, possibly instead of choosing an internal one. /// /// # Panics /// /// This function will panic if `content_type` contains an internal nul /// byte. pub fn content_type(&mut self, content_type: &'data str) -> &mut Self { if let Some(bytes) = self.bytes2cstr(content_type.as_bytes()) { let pos = self.array.len() - 1; self.array.insert(pos, curl_sys::curl_forms { option: curl_sys::CURLFORM_CONTENTTYPE, value: bytes.as_ptr() as *mut _, }); self.form.strings.push(bytes); } self } /// Used in combination with `Part::file`, provides the filename for /// this part instead of the actual one. /// /// # Errors /// /// If `name` contains an internal nul byte, or if on Windows the path is /// not valid unicode then this function will return an error when `add` is /// called. pub fn filename(&mut self, name: &'data P) -> &mut Self where P: AsRef { self._filename(name.as_ref()) } fn _filename(&mut self, name: &'data Path) -> &mut Self { if let Some(bytes) = self.path2cstr(name) { let pos = self.array.len() - 1; self.array.insert(pos, curl_sys::curl_forms { option: curl_sys::CURLFORM_FILENAME, value: bytes.as_ptr() as *mut _, }); self.form.strings.push(bytes); } self } /// This is used to provide a custom file upload part without using the /// `file` method above. /// /// The first parameter is for the filename field and the second is the /// in-memory contents. /// /// # Errors /// /// If `name` contains an internal nul byte, or if on Windows the path is /// not valid unicode then this function will return an error when `add` is /// called. pub fn buffer(&mut self, name: &'data P, data: Vec) -> &mut Self where P: AsRef { self._buffer(name.as_ref(), data) } fn _buffer(&mut self, name: &'data Path, data: Vec) -> &mut Self { if let Some(bytes) = self.path2cstr(name) { let pos = self.array.len() - 1; self.array.insert(pos, curl_sys::curl_forms { option: curl_sys::CURLFORM_BUFFER, value: bytes.as_ptr() as *mut _, }); self.form.strings.push(bytes); self.array.insert(pos + 1, curl_sys::curl_forms { option: curl_sys::CURLFORM_BUFFERPTR, value: data.as_ptr() as *mut _, }); self.array.insert(pos + 2, curl_sys::curl_forms { option: curl_sys::CURLFORM_BUFFERLENGTH, value: data.len() as *mut _, }); self.form.buffers.push(data); } self } /// Specifies extra headers for the form POST section. /// /// Appends the list of headers to those libcurl automatically generates. pub fn content_header(&mut self, headers: List) -> &mut Self { let pos = self.array.len() - 1; self.array.insert(pos, curl_sys::curl_forms { option: curl_sys::CURLFORM_CONTENTHEADER, value: list::raw(&headers) as *mut _, }); self.form.headers.push(headers); self } /// Attempts to add this part to the `Form` that it was created from. /// /// If any error happens while adding, that error is returned, otherwise /// `Ok(())` is returned. pub fn add(&mut self) -> Result<(), FormError> { if let Some(err) = self.error.clone() { return Err(err) } let rc = unsafe { curl_sys::curl_formadd(&mut self.form.head, &mut self.form.tail, curl_sys::CURLFORM_COPYNAME, self.name.as_ptr(), curl_sys::CURLFORM_NAMELENGTH, self.name.len(), curl_sys::CURLFORM_ARRAY, self.array.as_ptr(), curl_sys::CURLFORM_END) }; if rc == curl_sys::CURL_FORMADD_OK { Ok(()) } else { Err(FormError::new(rc)) } } #[cfg(unix)] fn path2cstr(&mut self, p: &Path) -> Option { use std::os::unix::prelude::*; self.bytes2cstr(p.as_os_str().as_bytes()) } #[cfg(windows)] fn path2cstr(&mut self, p: &Path) -> Option { match p.to_str() { Some(bytes) => self.bytes2cstr(bytes.as_bytes()), None if self.error.is_none() => { // TODO: better error code self.error = Some(FormError::new(curl_sys::CURL_FORMADD_INCOMPLETE)); None } None => None, } } fn bytes2cstr(&mut self, bytes: &[u8]) -> Option { match CString::new(bytes) { Ok(c) => Some(c), Err(..) if self.error.is_none() => { // TODO: better error code self.error = Some(FormError::new(curl_sys::CURL_FORMADD_INCOMPLETE)); None } Err(..) => None, } } } impl<'form, 'data> fmt::Debug for Part<'form, 'data> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // TODO: fill this out more f.debug_struct("Part") .field("name", &self.name) .field("form", &self.form) .finish() } } vendor/curl-0.4.11/src/easy/handle.rs0000664000000000000000000015420713264166600016105 0ustar rootrootuse std::cell::Cell; use std::fmt; use std::io::SeekFrom; use std::path::Path; use std::ptr; use std::str; use std::time::Duration; use curl_sys; use libc::c_void; use Error; use easy::{Form, List}; use easy::handler::{self, InfoType, SeekResult, ReadError, WriteError}; use easy::handler::{TimeCondition, IpResolve, HttpVersion, SslVersion}; use easy::handler::{SslOpt, NetRc, Auth, ProxyType}; use easy::{Easy2, Handler}; /// Raw bindings to a libcurl "easy session". /// /// This type is the same as the `Easy2` type in this library except that it /// does not contain a type parameter. Callbacks from curl are all controlled /// via closures on this `Easy` type, and this type namely has a `transfer` /// method as well for ergonomic management of these callbacks. /// /// There's not necessarily a right answer for which type is correct to use, but /// as a general rule of thumb `Easy` is typically a reasonable choice for /// synchronous I/O and `Easy2` is a good choice for asynchronous I/O. /// /// ## Examples /// /// Creating a handle which can be used later /// /// ``` /// use curl::easy::Easy; /// /// let handle = Easy::new(); /// ``` /// /// Send an HTTP request, writing the response to stdout. /// /// ``` /// use std::io::{stdout, Write}; /// /// use curl::easy::Easy; /// /// let mut handle = Easy::new(); /// handle.url("https://www.rust-lang.org/").unwrap(); /// handle.write_function(|data| { /// Ok(stdout().write(data).unwrap()) /// }).unwrap(); /// handle.perform().unwrap(); /// ``` /// /// Collect all output of an HTTP request to a vector. /// /// ``` /// use curl::easy::Easy; /// /// let mut data = Vec::new(); /// let mut handle = Easy::new(); /// handle.url("https://www.rust-lang.org/").unwrap(); /// { /// let mut transfer = handle.transfer(); /// transfer.write_function(|new_data| { /// data.extend_from_slice(new_data); /// Ok(new_data.len()) /// }).unwrap(); /// transfer.perform().unwrap(); /// } /// println!("{:?}", data); /// ``` /// /// More examples of various properties of an HTTP request can be found on the /// specific methods as well. #[derive(Debug)] pub struct Easy { inner: Easy2, } /// A scoped transfer of information which borrows an `Easy` and allows /// referencing stack-local data of the lifetime `'data`. /// /// Usage of `Easy` requires the `'static` and `Send` bounds on all callbacks /// registered, but that's not often wanted if all you need is to collect a /// bunch of data in memory to a vector, for example. The `Transfer` structure, /// created by the `Easy::transfer` method, is used for this sort of request. /// /// The callbacks attached to a `Transfer` are only active for that one transfer /// object, and they allow to elide both the `Send` and `'static` bounds to /// close over stack-local information. pub struct Transfer<'easy, 'data> { easy: &'easy mut Easy, data: Box>, } pub struct EasyData { running: Cell, owned: Callbacks<'static>, borrowed: Cell<*mut Callbacks<'static>>, } unsafe impl Send for EasyData {} #[derive(Default)] struct Callbacks<'a> { write: Option Result + 'a>>, read: Option Result + 'a>>, seek: Option SeekResult + 'a>>, debug: Option>, header: Option bool + 'a>>, progress: Option bool + 'a>>, ssl_ctx: Option Result<(), Error> + 'a>>, } impl Easy { /// Creates a new "easy" handle which is the core of almost all operations /// in libcurl. /// /// To use a handle, applications typically configure a number of options /// followed by a call to `perform`. Options are preserved across calls to /// `perform` and need to be reset manually (or via the `reset` method) if /// this is not desired. pub fn new() -> Easy { Easy { inner: Easy2::new(EasyData { running: Cell::new(false), owned: Callbacks::default(), borrowed: Cell::new(ptr::null_mut()), }), } } // ========================================================================= // Behavior options /// Same as [`Easy2::verbose`](struct.Easy2.html#method.verbose) pub fn verbose(&mut self, verbose: bool) -> Result<(), Error> { self.inner.verbose(verbose) } /// Same as [`Easy2::show_header`](struct.Easy2.html#method.show_header) pub fn show_header(&mut self, show: bool) -> Result<(), Error> { self.inner.show_header(show) } /// Same as [`Easy2::progress`](struct.Easy2.html#method.progress) pub fn progress(&mut self, progress: bool) -> Result<(), Error> { self.inner.progress(progress) } /// Same as [`Easy2::signal`](struct.Easy2.html#method.signal) pub fn signal(&mut self, signal: bool) -> Result<(), Error> { self.inner.signal(signal) } /// Same as [`Easy2::wildcard_match`](struct.Easy2.html#method.wildcard_match) pub fn wildcard_match(&mut self, m: bool) -> Result<(), Error> { self.inner.wildcard_match(m) } /// Same as [`Easy2::unix_socket`](struct.Easy2.html#method.unix_socket) pub fn unix_socket(&mut self, unix_domain_socket: &str) -> Result<(), Error> { self.inner.unix_socket(unix_domain_socket) } // ========================================================================= // Callback options /// Set callback for writing received data. /// /// This callback function gets called by libcurl as soon as there is data /// received that needs to be saved. /// /// The callback function will be passed as much data as possible in all /// invokes, but you must not make any assumptions. It may be one byte, it /// may be thousands. If `show_header` is enabled, which makes header data /// get passed to the write callback, you can get up to /// `CURL_MAX_HTTP_HEADER` bytes of header data passed into it. This /// usually means 100K. /// /// This function may be called with zero bytes data if the transferred file /// is empty. /// /// The callback should return the number of bytes actually taken care of. /// If that amount differs from the amount passed to your callback function, /// it'll signal an error condition to the library. This will cause the /// transfer to get aborted and the libcurl function used will return /// an error with `is_write_error`. /// /// If your callback function returns `Err(WriteError::Pause)` it will cause /// this transfer to become paused. See `unpause_write` for further details. /// /// By default data is sent into the void, and this corresponds to the /// `CURLOPT_WRITEFUNCTION` and `CURLOPT_WRITEDATA` options. /// /// Note that the lifetime bound on this function is `'static`, but that /// is often too restrictive. To use stack data consider calling the /// `transfer` method and then using `write_function` to configure a /// callback that can reference stack-local data. /// /// # Examples /// /// ``` /// use std::io::{stdout, Write}; /// use curl::easy::Easy; /// /// let mut handle = Easy::new(); /// handle.url("https://www.rust-lang.org/").unwrap(); /// handle.write_function(|data| { /// Ok(stdout().write(data).unwrap()) /// }).unwrap(); /// handle.perform().unwrap(); /// ``` /// /// Writing to a stack-local buffer /// /// ``` /// use std::io::{stdout, Write}; /// use curl::easy::Easy; /// /// let mut buf = Vec::new(); /// let mut handle = Easy::new(); /// handle.url("https://www.rust-lang.org/").unwrap(); /// /// let mut transfer = handle.transfer(); /// transfer.write_function(|data| { /// buf.extend_from_slice(data); /// Ok(data.len()) /// }).unwrap(); /// transfer.perform().unwrap(); /// ``` pub fn write_function(&mut self, f: F) -> Result<(), Error> where F: FnMut(&[u8]) -> Result + Send + 'static { self.inner.get_mut().owned.write = Some(Box::new(f)); Ok(()) } /// Read callback for data uploads. /// /// This callback function gets called by libcurl as soon as it needs to /// read data in order to send it to the peer - like if you ask it to upload /// or post data to the server. /// /// Your function must then return the actual number of bytes that it stored /// in that memory area. Returning 0 will signal end-of-file to the library /// and cause it to stop the current transfer. /// /// If you stop the current transfer by returning 0 "pre-maturely" (i.e /// before the server expected it, like when you've said you will upload N /// bytes and you upload less than N bytes), you may experience that the /// server "hangs" waiting for the rest of the data that won't come. /// /// The read callback may return `Err(ReadError::Abort)` to stop the /// current operation immediately, resulting in a `is_aborted_by_callback` /// error code from the transfer. /// /// The callback can return `Err(ReadError::Pause)` to cause reading from /// this connection to pause. See `unpause_read` for further details. /// /// By default data not input, and this corresponds to the /// `CURLOPT_READFUNCTION` and `CURLOPT_READDATA` options. /// /// Note that the lifetime bound on this function is `'static`, but that /// is often too restrictive. To use stack data consider calling the /// `transfer` method and then using `read_function` to configure a /// callback that can reference stack-local data. /// /// # Examples /// /// Read input from stdin /// /// ```no_run /// use std::io::{stdin, Read}; /// use curl::easy::Easy; /// /// let mut handle = Easy::new(); /// handle.url("https://example.com/login").unwrap(); /// handle.read_function(|into| { /// Ok(stdin().read(into).unwrap()) /// }).unwrap(); /// handle.post(true).unwrap(); /// handle.perform().unwrap(); /// ``` /// /// Reading from stack-local data: /// /// ```no_run /// use std::io::{stdin, Read}; /// use curl::easy::Easy; /// /// let mut data_to_upload = &b"foobar"[..]; /// let mut handle = Easy::new(); /// handle.url("https://example.com/login").unwrap(); /// handle.post(true).unwrap(); /// /// let mut transfer = handle.transfer(); /// transfer.read_function(|into| { /// Ok(data_to_upload.read(into).unwrap()) /// }).unwrap(); /// transfer.perform().unwrap(); /// ``` pub fn read_function(&mut self, f: F) -> Result<(), Error> where F: FnMut(&mut [u8]) -> Result + Send + 'static { self.inner.get_mut().owned.read = Some(Box::new(f)); Ok(()) } /// User callback for seeking in input stream. /// /// This function gets called by libcurl to seek to a certain position in /// the input stream and can be used to fast forward a file in a resumed /// upload (instead of reading all uploaded bytes with the normal read /// function/callback). It is also called to rewind a stream when data has /// already been sent to the server and needs to be sent again. This may /// happen when doing a HTTP PUT or POST with a multi-pass authentication /// method, or when an existing HTTP connection is reused too late and the /// server closes the connection. /// /// The callback function must return `SeekResult::Ok` on success, /// `SeekResult::Fail` to cause the upload operation to fail or /// `SeekResult::CantSeek` to indicate that while the seek failed, libcurl /// is free to work around the problem if possible. The latter can sometimes /// be done by instead reading from the input or similar. /// /// By default data this option is not set, and this corresponds to the /// `CURLOPT_SEEKFUNCTION` and `CURLOPT_SEEKDATA` options. /// /// Note that the lifetime bound on this function is `'static`, but that /// is often too restrictive. To use stack data consider calling the /// `transfer` method and then using `seek_function` to configure a /// callback that can reference stack-local data. pub fn seek_function(&mut self, f: F) -> Result<(), Error> where F: FnMut(SeekFrom) -> SeekResult + Send + 'static { self.inner.get_mut().owned.seek = Some(Box::new(f)); Ok(()) } /// Callback to progress meter function /// /// This function gets called by libcurl instead of its internal equivalent /// with a frequent interval. While data is being transferred it will be /// called very frequently, and during slow periods like when nothing is /// being transferred it can slow down to about one call per second. /// /// The callback gets told how much data libcurl will transfer and has /// transferred, in number of bytes. The first argument is the total number /// of bytes libcurl expects to download in this transfer. The second /// argument is the number of bytes downloaded so far. The third argument is /// the total number of bytes libcurl expects to upload in this transfer. /// The fourth argument is the number of bytes uploaded so far. /// /// Unknown/unused argument values passed to the callback will be set to /// zero (like if you only download data, the upload size will remain 0). /// Many times the callback will be called one or more times first, before /// it knows the data sizes so a program must be made to handle that. /// /// Returning `false` from this callback will cause libcurl to abort the /// transfer and return `is_aborted_by_callback`. /// /// If you transfer data with the multi interface, this function will not be /// called during periods of idleness unless you call the appropriate /// libcurl function that performs transfers. /// /// `progress` must be set to `true` to make this function actually get /// called. /// /// By default this function calls an internal method and corresponds to /// `CURLOPT_PROGRESSFUNCTION` and `CURLOPT_PROGRESSDATA`. /// /// Note that the lifetime bound on this function is `'static`, but that /// is often too restrictive. To use stack data consider calling the /// `transfer` method and then using `progress_function` to configure a /// callback that can reference stack-local data. pub fn progress_function(&mut self, f: F) -> Result<(), Error> where F: FnMut(f64, f64, f64, f64) -> bool + Send + 'static { self.inner.get_mut().owned.progress = Some(Box::new(f)); Ok(()) } /// Callback to SSL context /// /// This callback function gets called by libcurl just before the /// initialization of an SSL connection after having processed all /// other SSL related options to give a last chance to an /// application to modify the behaviour of the SSL /// initialization. The `ssl_ctx` parameter is actually a pointer /// to the SSL library's SSL_CTX. If an error is returned from the /// callback no attempt to establish a connection is made and the /// perform operation will return the callback's error code. /// /// This function will get called on all new connections made to a /// server, during the SSL negotiation. The SSL_CTX pointer will /// be a new one every time. /// /// To use this properly, a non-trivial amount of knowledge of /// your SSL library is necessary. For example, you can use this /// function to call library-specific callbacks to add additional /// validation code for certificates, and even to change the /// actual URI of a HTTPS request. /// /// By default this function calls an internal method and /// corresponds to `CURLOPT_SSL_CTX_FUNCTION` and /// `CURLOPT_SSL_CTX_DATA`. /// /// Note that the lifetime bound on this function is `'static`, but that /// is often too restrictive. To use stack data consider calling the /// `transfer` method and then using `progress_function` to configure a /// callback that can reference stack-local data. pub fn ssl_ctx_function(&mut self, f: F) -> Result<(), Error> where F: FnMut(*mut c_void) -> Result<(), Error> + Send + 'static { self.inner.get_mut().owned.ssl_ctx = Some(Box::new(f)); Ok(()) } /// Specify a debug callback /// /// `debug_function` replaces the standard debug function used when /// `verbose` is in effect. This callback receives debug information, /// as specified in the type argument. /// /// By default this option is not set and corresponds to the /// `CURLOPT_DEBUGFUNCTION` and `CURLOPT_DEBUGDATA` options. /// /// Note that the lifetime bound on this function is `'static`, but that /// is often too restrictive. To use stack data consider calling the /// `transfer` method and then using `debug_function` to configure a /// callback that can reference stack-local data. pub fn debug_function(&mut self, f: F) -> Result<(), Error> where F: FnMut(InfoType, &[u8]) + Send + 'static { self.inner.get_mut().owned.debug = Some(Box::new(f)); Ok(()) } /// Callback that receives header data /// /// This function gets called by libcurl as soon as it has received header /// data. The header callback will be called once for each header and only /// complete header lines are passed on to the callback. Parsing headers is /// very easy using this. If this callback returns `false` it'll signal an /// error to the library. This will cause the transfer to get aborted and /// the libcurl function in progress will return `is_write_error`. /// /// A complete HTTP header that is passed to this function can be up to /// CURL_MAX_HTTP_HEADER (100K) bytes. /// /// It's important to note that the callback will be invoked for the headers /// of all responses received after initiating a request and not just the /// final response. This includes all responses which occur during /// authentication negotiation. If you need to operate on only the headers /// from the final response, you will need to collect headers in the /// callback yourself and use HTTP status lines, for example, to delimit /// response boundaries. /// /// When a server sends a chunked encoded transfer, it may contain a /// trailer. That trailer is identical to a HTTP header and if such a /// trailer is received it is passed to the application using this callback /// as well. There are several ways to detect it being a trailer and not an /// ordinary header: 1) it comes after the response-body. 2) it comes after /// the final header line (CR LF) 3) a Trailer: header among the regular /// response-headers mention what header(s) to expect in the trailer. /// /// For non-HTTP protocols like FTP, POP3, IMAP and SMTP this function will /// get called with the server responses to the commands that libcurl sends. /// /// By default this option is not set and corresponds to the /// `CURLOPT_HEADERFUNCTION` and `CURLOPT_HEADERDATA` options. /// /// Note that the lifetime bound on this function is `'static`, but that /// is often too restrictive. To use stack data consider calling the /// `transfer` method and then using `header_function` to configure a /// callback that can reference stack-local data. /// /// # Examples /// /// ``` /// use std::str; /// /// use curl::easy::Easy; /// /// let mut handle = Easy::new(); /// handle.url("https://www.rust-lang.org/").unwrap(); /// handle.header_function(|header| { /// print!("header: {}", str::from_utf8(header).unwrap()); /// true /// }).unwrap(); /// handle.perform().unwrap(); /// ``` /// /// Collecting headers to a stack local vector /// /// ``` /// use std::str; /// /// use curl::easy::Easy; /// /// let mut headers = Vec::new(); /// let mut handle = Easy::new(); /// handle.url("https://www.rust-lang.org/").unwrap(); /// /// { /// let mut transfer = handle.transfer(); /// transfer.header_function(|header| { /// headers.push(str::from_utf8(header).unwrap().to_string()); /// true /// }).unwrap(); /// transfer.perform().unwrap(); /// } /// /// println!("{:?}", headers); /// ``` pub fn header_function(&mut self, f: F) -> Result<(), Error> where F: FnMut(&[u8]) -> bool + Send + 'static { self.inner.get_mut().owned.header = Some(Box::new(f)); Ok(()) } // ========================================================================= // Error options // TODO: error buffer and stderr /// Same as [`Easy2::fail_on_error`](struct.Easy2.html#method.fail_on_error) pub fn fail_on_error(&mut self, fail: bool) -> Result<(), Error> { self.inner.fail_on_error(fail) } // ========================================================================= // Network options /// Same as [`Easy2::url`](struct.Easy2.html#method.url) pub fn url(&mut self, url: &str) -> Result<(), Error> { self.inner.url(url) } /// Same as [`Easy2::port`](struct.Easy2.html#method.port) pub fn port(&mut self, port: u16) -> Result<(), Error> { self.inner.port(port) } /// Same as [`Easy2::proxy`](struct.Easy2.html#method.proxy) pub fn proxy(&mut self, url: &str) -> Result<(), Error> { self.inner.proxy(url) } /// Same as [`Easy2::proxy_port`](struct.Easy2.html#method.proxy_port) pub fn proxy_port(&mut self, port: u16) -> Result<(), Error> { self.inner.proxy_port(port) } /// Same as [`Easy2::proxy_type`](struct.Easy2.html#method.proxy_type) pub fn proxy_type(&mut self, kind: ProxyType) -> Result<(), Error> { self.inner.proxy_type(kind) } /// Same as [`Easy2::noproxy`](struct.Easy2.html#method.noproxy) pub fn noproxy(&mut self, skip: &str) -> Result<(), Error> { self.inner.noproxy(skip) } /// Same as [`Easy2::http_proxy_tunnel`](struct.Easy2.html#method.http_proxy_tunnel) pub fn http_proxy_tunnel(&mut self, tunnel: bool) -> Result<(), Error> { self.inner.http_proxy_tunnel(tunnel) } /// Same as [`Easy2::interface`](struct.Easy2.html#method.interface) pub fn interface(&mut self, interface: &str) -> Result<(), Error> { self.inner.interface(interface) } /// Same as [`Easy2::set_local_port`](struct.Easy2.html#method.set_local_port) pub fn set_local_port(&mut self, port: u16) -> Result<(), Error> { self.inner.set_local_port(port) } /// Same as [`Easy2::local_port_range`](struct.Easy2.html#method.local_port_range) pub fn local_port_range(&mut self, range: u16) -> Result<(), Error> { self.inner.local_port_range(range) } /// Same as [`Easy2::dns_cache_timeout`](struct.Easy2.html#method.dns_cache_timeout) pub fn dns_cache_timeout(&mut self, dur: Duration) -> Result<(), Error> { self.inner.dns_cache_timeout(dur) } /// Same as [`Easy2::buffer_size`](struct.Easy2.html#method.buffer_size) pub fn buffer_size(&mut self, size: usize) -> Result<(), Error> { self.inner.buffer_size(size) } /// Same as [`Easy2::tcp_nodelay`](struct.Easy2.html#method.tcp_nodelay) pub fn tcp_nodelay(&mut self, enable: bool) -> Result<(), Error> { self.inner.tcp_nodelay(enable) } /// Same as [`Easy2::tcp_keepalive`](struct.Easy2.html#method.tcp_keepalive) pub fn tcp_keepalive(&mut self, enable: bool) -> Result<(), Error> { self.inner.tcp_keepalive(enable) } /// Same as [`Easy2::tcp_keepintvl`](struct.Easy2.html#method.tcp_keepalive) pub fn tcp_keepintvl(&mut self, dur: Duration) -> Result<(), Error> { self.inner.tcp_keepintvl(dur) } /// Same as [`Easy2::tcp_keepidle`](struct.Easy2.html#method.tcp_keepidle) pub fn tcp_keepidle(&mut self, dur: Duration) -> Result<(), Error> { self.inner.tcp_keepidle(dur) } /// Same as [`Easy2::address_scope`](struct.Easy2.html#method.address_scope) pub fn address_scope(&mut self, scope: u32) -> Result<(), Error> { self.inner.address_scope(scope) } // ========================================================================= // Names and passwords /// Same as [`Easy2::username`](struct.Easy2.html#method.username) pub fn username(&mut self, user: &str) -> Result<(), Error> { self.inner.username(user) } /// Same as [`Easy2::password`](struct.Easy2.html#method.password) pub fn password(&mut self, pass: &str) -> Result<(), Error> { self.inner.password(pass) } /// Same as [`Easy2::http_auth`](struct.Easy2.html#method.http_auth) pub fn http_auth(&mut self, auth: &Auth) -> Result<(), Error> { self.inner.http_auth(auth) } /// Same as [`Easy2::proxy_username`](struct.Easy2.html#method.proxy_username) pub fn proxy_username(&mut self, user: &str) -> Result<(), Error> { self.inner.proxy_username(user) } /// Same as [`Easy2::proxy_password`](struct.Easy2.html#method.proxy_password) pub fn proxy_password(&mut self, pass: &str) -> Result<(), Error> { self.inner.proxy_password(pass) } /// Same as [`Easy2::proxy_auth`](struct.Easy2.html#method.proxy_auth) pub fn proxy_auth(&mut self, auth: &Auth) -> Result<(), Error> { self.inner.proxy_auth(auth) } /// Same as [`Easy2::netrc`](struct.Easy2.html#method.netrc) pub fn netrc(&mut self, netrc: NetRc) -> Result<(), Error> { self.inner.netrc(netrc) } // ========================================================================= // HTTP Options /// Same as [`Easy2::autoreferer`](struct.Easy2.html#method.autoreferer) pub fn autoreferer(&mut self, enable: bool) -> Result<(), Error> { self.inner.autoreferer(enable) } /// Same as [`Easy2::accept_encoding`](struct.Easy2.html#method.accept_encoding) pub fn accept_encoding(&mut self, encoding: &str) -> Result<(), Error> { self.inner.accept_encoding(encoding) } /// Same as [`Easy2::transfer_encoding`](struct.Easy2.html#method.transfer_encoding) pub fn transfer_encoding(&mut self, enable: bool) -> Result<(), Error> { self.inner.transfer_encoding(enable) } /// Same as [`Easy2::follow_location`](struct.Easy2.html#method.follow_location) pub fn follow_location(&mut self, enable: bool) -> Result<(), Error> { self.inner.follow_location(enable) } /// Same as [`Easy2::unrestricted_auth`](struct.Easy2.html#method.unrestricted_auth) pub fn unrestricted_auth(&mut self, enable: bool) -> Result<(), Error> { self.inner.unrestricted_auth(enable) } /// Same as [`Easy2::max_redirections`](struct.Easy2.html#method.max_redirections) pub fn max_redirections(&mut self, max: u32) -> Result<(), Error> { self.inner.max_redirections(max) } /// Same as [`Easy2::put`](struct.Easy2.html#method.put) pub fn put(&mut self, enable: bool) -> Result<(), Error> { self.inner.put(enable) } /// Same as [`Easy2::post`](struct.Easy2.html#method.post) pub fn post(&mut self, enable: bool) -> Result<(), Error> { self.inner.post(enable) } /// Same as [`Easy2::post_field_copy`](struct.Easy2.html#method.post_field_copy) pub fn post_fields_copy(&mut self, data: &[u8]) -> Result<(), Error> { self.inner.post_fields_copy(data) } /// Same as [`Easy2::post_field_size`](struct.Easy2.html#method.post_field_size) pub fn post_field_size(&mut self, size: u64) -> Result<(), Error> { self.inner.post_field_size(size) } /// Same as [`Easy2::httppost`](struct.Easy2.html#method.httppost) pub fn httppost(&mut self, form: Form) -> Result<(), Error> { self.inner.httppost(form) } /// Same as [`Easy2::referer`](struct.Easy2.html#method.referer) pub fn referer(&mut self, referer: &str) -> Result<(), Error> { self.inner.referer(referer) } /// Same as [`Easy2::useragent`](struct.Easy2.html#method.useragent) pub fn useragent(&mut self, useragent: &str) -> Result<(), Error> { self.inner.useragent(useragent) } /// Same as [`Easy2::http_headers`](struct.Easy2.html#method.http_headers) pub fn http_headers(&mut self, list: List) -> Result<(), Error> { self.inner.http_headers(list) } /// Same as [`Easy2::cookie`](struct.Easy2.html#method.cookie) pub fn cookie(&mut self, cookie: &str) -> Result<(), Error> { self.inner.cookie(cookie) } /// Same as [`Easy2::cookie_file`](struct.Easy2.html#method.cookie_file) pub fn cookie_file>(&mut self, file: P) -> Result<(), Error> { self.inner.cookie_file(file) } /// Same as [`Easy2::cookie_jar`](struct.Easy2.html#method.cookie_jar) pub fn cookie_jar>(&mut self, file: P) -> Result<(), Error> { self.inner.cookie_jar(file) } /// Same as [`Easy2::cookie_session`](struct.Easy2.html#method.cookie_session) pub fn cookie_session(&mut self, session: bool) -> Result<(), Error> { self.inner.cookie_session(session) } /// Same as [`Easy2::cookie_list`](struct.Easy2.html#method.cookie_list) pub fn cookie_list(&mut self, cookie: &str) -> Result<(), Error> { self.inner.cookie_list(cookie) } /// Same as [`Easy2::get`](struct.Easy2.html#method.get) pub fn get(&mut self, enable: bool) -> Result<(), Error> { self.inner.get(enable) } /// Same as [`Easy2::ignore_content_length`](struct.Easy2.html#method.ignore_content_length) pub fn ignore_content_length(&mut self, ignore: bool) -> Result<(), Error> { self.inner.ignore_content_length(ignore) } /// Same as [`Easy2::http_content_decoding`](struct.Easy2.html#method.http_content_decoding) pub fn http_content_decoding(&mut self, enable: bool) -> Result<(), Error> { self.inner.http_content_decoding(enable) } /// Same as [`Easy2::http_transfer_decoding`](struct.Easy2.html#method.http_transfer_decoding) pub fn http_transfer_decoding(&mut self, enable: bool) -> Result<(), Error> { self.inner.http_transfer_decoding(enable) } // ========================================================================= // Protocol Options /// Same as [`Easy2::range`](struct.Easy2.html#method.range) pub fn range(&mut self, range: &str) -> Result<(), Error> { self.inner.range(range) } /// Same as [`Easy2::resume_from`](struct.Easy2.html#method.resume_from) pub fn resume_from(&mut self, from: u64) -> Result<(), Error> { self.inner.resume_from(from) } /// Same as [`Easy2::custom_request`](struct.Easy2.html#method.custom_request) pub fn custom_request(&mut self, request: &str) -> Result<(), Error> { self.inner.custom_request(request) } /// Same as [`Easy2::fetch_filetime`](struct.Easy2.html#method.fetch_filetime) pub fn fetch_filetime(&mut self, fetch: bool) -> Result<(), Error> { self.inner.fetch_filetime(fetch) } /// Same as [`Easy2::nobody`](struct.Easy2.html#method.nobody) pub fn nobody(&mut self, enable: bool) -> Result<(), Error> { self.inner.nobody(enable) } /// Same as [`Easy2::in_filesize`](struct.Easy2.html#method.in_filesize) pub fn in_filesize(&mut self, size: u64) -> Result<(), Error> { self.inner.in_filesize(size) } /// Same as [`Easy2::upload`](struct.Easy2.html#method.upload) pub fn upload(&mut self, enable: bool) -> Result<(), Error> { self.inner.upload(enable) } /// Same as [`Easy2::max_filesize`](struct.Easy2.html#method.max_filesize) pub fn max_filesize(&mut self, size: u64) -> Result<(), Error> { self.inner.max_filesize(size) } /// Same as [`Easy2::time_condition`](struct.Easy2.html#method.time_condition) pub fn time_condition(&mut self, cond: TimeCondition) -> Result<(), Error> { self.inner.time_condition(cond) } /// Same as [`Easy2::time_value`](struct.Easy2.html#method.time_value) pub fn time_value(&mut self, val: i64) -> Result<(), Error> { self.inner.time_value(val) } // ========================================================================= // Connection Options /// Same as [`Easy2::timeout`](struct.Easy2.html#method.timeout) pub fn timeout(&mut self, timeout: Duration) -> Result<(), Error> { self.inner.timeout(timeout) } /// Same as [`Easy2::low_speed_limit`](struct.Easy2.html#method.low_speed_limit) pub fn low_speed_limit(&mut self, limit: u32) -> Result<(), Error> { self.inner.low_speed_limit(limit) } /// Same as [`Easy2::low_speed_time`](struct.Easy2.html#method.low_speed_time) pub fn low_speed_time(&mut self, dur: Duration) -> Result<(), Error> { self.inner.low_speed_time(dur) } /// Same as [`Easy2::max_send_speed`](struct.Easy2.html#method.max_send_speed) pub fn max_send_speed(&mut self, speed: u64) -> Result<(), Error> { self.inner.max_send_speed(speed) } /// Same as [`Easy2::max_recv_speed`](struct.Easy2.html#method.max_recv_speed) pub fn max_recv_speed(&mut self, speed: u64) -> Result<(), Error> { self.inner.max_recv_speed(speed) } /// Same as [`Easy2::max_connects`](struct.Easy2.html#method.max_connects) pub fn max_connects(&mut self, max: u32) -> Result<(), Error> { self.inner.max_connects(max) } /// Same as [`Easy2::fresh_connect`](struct.Easy2.html#method.fresh_connect) pub fn fresh_connect(&mut self, enable: bool) -> Result<(), Error> { self.inner.fresh_connect(enable) } /// Same as [`Easy2::forbid_reuse`](struct.Easy2.html#method.forbid_reuse) pub fn forbid_reuse(&mut self, enable: bool) -> Result<(), Error> { self.inner.forbid_reuse(enable) } /// Same as [`Easy2::connect_timeout`](struct.Easy2.html#method.connect_timeout) pub fn connect_timeout(&mut self, timeout: Duration) -> Result<(), Error> { self.inner.connect_timeout(timeout) } /// Same as [`Easy2::ip_resolve`](struct.Easy2.html#method.ip_resolve) pub fn ip_resolve(&mut self, resolve: IpResolve) -> Result<(), Error> { self.inner.ip_resolve(resolve) } /// Same as [`Easy2::resolve`](struct.Easy2.html#method.resolve) pub fn resolve(&mut self, list: List) -> Result<(), Error> { self.inner.resolve(list) } /// Same as [`Easy2::connect_only`](struct.Easy2.html#method.connect_only) pub fn connect_only(&mut self, enable: bool) -> Result<(), Error> { self.inner.connect_only(enable) } // ========================================================================= // SSL/Security Options /// Same as [`Easy2::ssl_cert`](struct.Easy2.html#method.ssl_cert) pub fn ssl_cert>(&mut self, cert: P) -> Result<(), Error> { self.inner.ssl_cert(cert) } /// Same as [`Easy2::ssl_cert_type`](struct.Easy2.html#method.ssl_cert_type) pub fn ssl_cert_type(&mut self, kind: &str) -> Result<(), Error> { self.inner.ssl_cert_type(kind) } /// Same as [`Easy2::ssl_key`](struct.Easy2.html#method.ssl_key) pub fn ssl_key>(&mut self, key: P) -> Result<(), Error> { self.inner.ssl_key(key) } /// Same as [`Easy2::ssl_key_type`](struct.Easy2.html#method.ssl_key_type) pub fn ssl_key_type(&mut self, kind: &str) -> Result<(), Error> { self.inner.ssl_key_type(kind) } /// Same as [`Easy2::key_password`](struct.Easy2.html#method.key_password) pub fn key_password(&mut self, password: &str) -> Result<(), Error> { self.inner.key_password(password) } /// Same as [`Easy2::ssl_engine`](struct.Easy2.html#method.ssl_engine) pub fn ssl_engine(&mut self, engine: &str) -> Result<(), Error> { self.inner.ssl_engine(engine) } /// Same as [`Easy2::ssl_engine_default`](struct.Easy2.html#method.ssl_engine_default) pub fn ssl_engine_default(&mut self, enable: bool) -> Result<(), Error> { self.inner.ssl_engine_default(enable) } /// Same as [`Easy2::http_version`](struct.Easy2.html#method.http_version) pub fn http_version(&mut self, version: HttpVersion) -> Result<(), Error> { self.inner.http_version(version) } /// Same as [`Easy2::ssl_version`](struct.Easy2.html#method.ssl_version) pub fn ssl_version(&mut self, version: SslVersion) -> Result<(), Error> { self.inner.ssl_version(version) } /// Same as [`Easy2::ssl_verify_host`](struct.Easy2.html#method.ssl_verify_host) pub fn ssl_verify_host(&mut self, verify: bool) -> Result<(), Error> { self.inner.ssl_verify_host(verify) } /// Same as [`Easy2::ssl_verify_peer`](struct.Easy2.html#method.ssl_verify_peer) pub fn ssl_verify_peer(&mut self, verify: bool) -> Result<(), Error> { self.inner.ssl_verify_peer(verify) } /// Same as [`Easy2::cainfo`](struct.Easy2.html#method.cainfo) pub fn cainfo>(&mut self, path: P) -> Result<(), Error> { self.inner.cainfo(path) } /// Same as [`Easy2::issuer_cert`](struct.Easy2.html#method.issuer_cert) pub fn issuer_cert>(&mut self, path: P) -> Result<(), Error> { self.inner.issuer_cert(path) } /// Same as [`Easy2::capath`](struct.Easy2.html#method.capath) pub fn capath>(&mut self, path: P) -> Result<(), Error> { self.inner.capath(path) } /// Same as [`Easy2::crlfile`](struct.Easy2.html#method.crlfile) pub fn crlfile>(&mut self, path: P) -> Result<(), Error> { self.inner.crlfile(path) } /// Same as [`Easy2::certinfo`](struct.Easy2.html#method.certinfo) pub fn certinfo(&mut self, enable: bool) -> Result<(), Error> { self.inner.certinfo(enable) } /// Same as [`Easy2::random_file`](struct.Easy2.html#method.random_file) pub fn random_file>(&mut self, p: P) -> Result<(), Error> { self.inner.random_file(p) } /// Same as [`Easy2::egd_socket`](struct.Easy2.html#method.egd_socket) pub fn egd_socket>(&mut self, p: P) -> Result<(), Error> { self.inner.egd_socket(p) } /// Same as [`Easy2::ssl_cipher_list`](struct.Easy2.html#method.ssl_cipher_list) pub fn ssl_cipher_list(&mut self, ciphers: &str) -> Result<(), Error> { self.inner.ssl_cipher_list(ciphers) } /// Same as [`Easy2::ssl_sessionid_cache`](struct.Easy2.html#method.ssl_sessionid_cache) pub fn ssl_sessionid_cache(&mut self, enable: bool) -> Result<(), Error> { self.inner.ssl_sessionid_cache(enable) } /// Same as [`Easy2::ssl_options`](struct.Easy2.html#method.ssl_options) pub fn ssl_options(&mut self, bits: &SslOpt) -> Result<(), Error> { self.inner.ssl_options(bits) } // ========================================================================= // getters /// Same as [`Easy2::effective_url`](struct.Easy2.html#method.effective_url) pub fn effective_url(&mut self) -> Result, Error> { self.inner.effective_url() } /// Same as [`Easy2::effective_url_bytes`](struct.Easy2.html#method.effective_url_bytes) pub fn effective_url_bytes(&mut self) -> Result, Error> { self.inner.effective_url_bytes() } /// Same as [`Easy2::response_code`](struct.Easy2.html#method.response_code) pub fn response_code(&mut self) -> Result { self.inner.response_code() } /// Same as [`Easy2::http_connectcode`](struct.Easy2.html#method.http_connectcode) pub fn http_connectcode(&mut self) -> Result { self.inner.http_connectcode() } /// Same as [`Easy2::filetime`](struct.Easy2.html#method.filetime) pub fn filetime(&mut self) -> Result, Error> { self.inner.filetime() } /// Same as [`Easy2::total_time`](struct.Easy2.html#method.total_time) pub fn total_time(&mut self) -> Result { self.inner.total_time() } /// Same as [`Easy2::namelookup_time`](struct.Easy2.html#method.namelookup_time) pub fn namelookup_time(&mut self) -> Result { self.inner.namelookup_time() } /// Same as [`Easy2::connect_time`](struct.Easy2.html#method.connect_time) pub fn connect_time(&mut self) -> Result { self.inner.connect_time() } /// Same as [`Easy2::appconnect_time`](struct.Easy2.html#method.appconnect_time) pub fn appconnect_time(&mut self) -> Result { self.inner.appconnect_time() } /// Same as [`Easy2::pretransfer_time`](struct.Easy2.html#method.pretransfer_time) pub fn pretransfer_time(&mut self) -> Result { self.inner.pretransfer_time() } /// Same as [`Easy2::starttransfer_time`](struct.Easy2.html#method.starttransfer_time) pub fn starttransfer_time(&mut self) -> Result { self.inner.starttransfer_time() } /// Same as [`Easy2::redirect_time`](struct.Easy2.html#method.redirect_time) pub fn redirect_time(&mut self) -> Result { self.inner.redirect_time() } /// Same as [`Easy2::redirect_count`](struct.Easy2.html#method.redirect_count) pub fn redirect_count(&mut self) -> Result { self.inner.redirect_count() } /// Same as [`Easy2::redirect_url`](struct.Easy2.html#method.redirect_url) pub fn redirect_url(&mut self) -> Result, Error> { self.inner.redirect_url() } /// Same as [`Easy2::redirect_url_bytes`](struct.Easy2.html#method.redirect_url_bytes) pub fn redirect_url_bytes(&mut self) -> Result, Error> { self.inner.redirect_url_bytes() } /// Same as [`Easy2::header_size`](struct.Easy2.html#method.header_size) pub fn header_size(&mut self) -> Result { self.inner.header_size() } /// Same as [`Easy2::request_size`](struct.Easy2.html#method.request_size) pub fn request_size(&mut self) -> Result { self.inner.request_size() } /// Same as [`Easy2::content_type`](struct.Easy2.html#method.content_type) pub fn content_type(&mut self) -> Result, Error> { self.inner.content_type() } /// Same as [`Easy2::content_type_bytes`](struct.Easy2.html#method.content_type_bytes) pub fn content_type_bytes(&mut self) -> Result, Error> { self.inner.content_type_bytes() } /// Same as [`Easy2::os_errno`](struct.Easy2.html#method.os_errno) pub fn os_errno(&mut self) -> Result { self.inner.os_errno() } /// Same as [`Easy2::primary_ip`](struct.Easy2.html#method.primary_ip) pub fn primary_ip(&mut self) -> Result, Error> { self.inner.primary_ip() } /// Same as [`Easy2::primary_port`](struct.Easy2.html#method.primary_port) pub fn primary_port(&mut self) -> Result { self.inner.primary_port() } /// Same as [`Easy2::local_ip`](struct.Easy2.html#method.local_ip) pub fn local_ip(&mut self) -> Result, Error> { self.inner.local_ip() } /// Same as [`Easy2::local_port`](struct.Easy2.html#method.local_port) pub fn local_port(&mut self) -> Result { self.inner.local_port() } /// Same as [`Easy2::cookies`](struct.Easy2.html#method.cookies) pub fn cookies(&mut self) -> Result { self.inner.cookies() } // ========================================================================= // Other methods /// Same as [`Easy2::perform`](struct.Easy2.html#method.perform) pub fn perform(&self) -> Result<(), Error> { assert!(self.inner.get_ref().borrowed.get().is_null()); self.do_perform() } fn do_perform(&self) -> Result<(), Error> { // We don't allow recursive invocations of `perform` because we're // invoking `FnMut`closures behind a `&self` pointer. This flag acts as // our own `RefCell` borrow flag sorta. if self.inner.get_ref().running.get() { return Err(Error::new(curl_sys::CURLE_FAILED_INIT)) } self.inner.get_ref().running.set(true); struct Reset<'a>(&'a Cell); impl<'a> Drop for Reset<'a> { fn drop(&mut self) { self.0.set(false); } } let _reset = Reset(&self.inner.get_ref().running); self.inner.perform() } /// Creates a new scoped transfer which can be used to set callbacks and /// data which only live for the scope of the returned object. /// /// An `Easy` handle is often reused between different requests to cache /// connections to servers, but often the lifetime of the data as part of /// each transfer is unique. This function serves as an ability to share an /// `Easy` across many transfers while ergonomically using possibly /// stack-local data as part of each transfer. /// /// Configuration can be set on the `Easy` and then a `Transfer` can be /// created to set scoped configuration (like callbacks). Finally, the /// `perform` method on the `Transfer` function can be used. /// /// When the `Transfer` option is dropped then all configuration set on the /// transfer itself will be reset. pub fn transfer<'data, 'easy>(&'easy mut self) -> Transfer<'easy, 'data> { assert!(!self.inner.get_ref().running.get()); Transfer { data: Box::new(Callbacks::default()), easy: self, } } /// Same as [`Easy2::unpause_read`](struct.Easy2.html#method.unpause_read) pub fn unpause_read(&self) -> Result<(), Error> { self.inner.unpause_read() } /// Same as [`Easy2::unpause_write`](struct.Easy2.html#method.unpause_write) pub fn unpause_write(&self) -> Result<(), Error> { self.inner.unpause_write() } /// Same as [`Easy2::url_encode`](struct.Easy2.html#method.url_encode) pub fn url_encode(&mut self, s: &[u8]) -> String { self.inner.url_encode(s) } /// Same as [`Easy2::url_decode`](struct.Easy2.html#method.url_decode) pub fn url_decode(&mut self, s: &str) -> Vec { self.inner.url_decode(s) } /// Same as [`Easy2::reset`](struct.Easy2.html#method.reset) pub fn reset(&mut self) { self.inner.reset() } /// Same as [`Easy2::recv`](struct.Easy2.html#method.recv) pub fn recv(&mut self, data: &mut [u8]) -> Result { self.inner.recv(data) } /// Same as [`Easy2::send`](struct.Easy2.html#method.send) pub fn send(&mut self, data: &[u8]) -> Result { self.inner.send(data) } /// Same as [`Easy2::raw`](struct.Easy2.html#method.raw) pub fn raw(&self) -> *mut curl_sys::CURL { self.inner.raw() } } impl EasyData { /// An unsafe function to get the appropriate callback field. /// /// We can have callbacks configured from one of two different sources. /// We could either have a callback from the `borrowed` field, callbacks on /// an ephemeral `Transfer`, or the `owned` field which are `'static` /// callbacks that live for the lifetime of this `EasyData`. /// /// The first set of callbacks are unsafe to access because they're actually /// owned elsewhere and we're just aliasing. Additionally they don't /// technically live long enough for us to access them, so they're hidden /// behind unsafe pointers and casts. /// /// This function returns `&'a mut T` but that's actually somewhat of a lie. /// The value should **not be stored to** nor should it be used for the full /// lifetime of `'a`, but rather immediately in the local scope. /// /// Basically this is just intended to acquire a callback, invoke it, and /// then stop. Nothing else. Super unsafe. unsafe fn callback<'a, T, F>(&'a mut self, f: F) -> Option<&'a mut T> where F: for<'b> Fn(&'b mut Callbacks<'static>) -> &'b mut Option, { let ptr = self.borrowed.get(); if !ptr.is_null() { let val = f(&mut *ptr); if val.is_some() { return val.as_mut() } } f(&mut self.owned).as_mut() } } impl Handler for EasyData { fn write(&mut self, data: &[u8]) -> Result { unsafe { match self.callback(|s| &mut s.write) { Some(write) => write(data), None => Ok(data.len()), } } } fn read(&mut self, data: &mut [u8]) -> Result { unsafe { match self.callback(|s| &mut s.read) { Some(read) => read(data), None => Ok(0), } } } fn seek(&mut self, whence: SeekFrom) -> SeekResult { unsafe { match self.callback(|s| &mut s.seek) { Some(seek) => seek(whence), None => SeekResult::CantSeek, } } } fn debug(&mut self, kind: InfoType, data: &[u8]) { unsafe { match self.callback(|s| &mut s.debug) { Some(debug) => debug(kind, data), None => handler::debug(kind, data), } } } fn header(&mut self, data: &[u8]) -> bool { unsafe { match self.callback(|s| &mut s.header) { Some(header) => header(data), None => true, } } } fn progress(&mut self, dltotal: f64, dlnow: f64, ultotal: f64, ulnow: f64) -> bool { unsafe { match self.callback(|s| &mut s.progress) { Some(progress) => progress(dltotal, dlnow, ultotal, ulnow), None => true, } } } fn ssl_ctx(&mut self, cx: *mut c_void) -> Result<(), Error> { unsafe { match self.callback(|s| &mut s.ssl_ctx) { Some(ssl_ctx) => ssl_ctx(cx), None => handler::ssl_ctx(cx), } } } } impl fmt::Debug for EasyData { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { "callbacks ...".fmt(f) } } impl<'easy, 'data> Transfer<'easy, 'data> { /// Same as `Easy::write_function`, just takes a non `'static` lifetime /// corresponding to the lifetime of this transfer. pub fn write_function(&mut self, f: F) -> Result<(), Error> where F: FnMut(&[u8]) -> Result + 'data { self.data.write = Some(Box::new(f)); Ok(()) } /// Same as `Easy::read_function`, just takes a non `'static` lifetime /// corresponding to the lifetime of this transfer. pub fn read_function(&mut self, f: F) -> Result<(), Error> where F: FnMut(&mut [u8]) -> Result + 'data { self.data.read = Some(Box::new(f)); Ok(()) } /// Same as `Easy::seek_function`, just takes a non `'static` lifetime /// corresponding to the lifetime of this transfer. pub fn seek_function(&mut self, f: F) -> Result<(), Error> where F: FnMut(SeekFrom) -> SeekResult + 'data { self.data.seek = Some(Box::new(f)); Ok(()) } /// Same as `Easy::progress_function`, just takes a non `'static` lifetime /// corresponding to the lifetime of this transfer. pub fn progress_function(&mut self, f: F) -> Result<(), Error> where F: FnMut(f64, f64, f64, f64) -> bool + 'data { self.data.progress = Some(Box::new(f)); Ok(()) } /// Same as `Easy::ssl_ctx_function`, just takes a non `'static` /// lifetime corresponding to the lifetime of this transfer. pub fn ssl_ctx_function(&mut self, f: F) -> Result<(), Error> where F: FnMut(*mut c_void) -> Result<(), Error> + Send + 'data { self.data.ssl_ctx = Some(Box::new(f)); Ok(()) } /// Same as `Easy::debug_function`, just takes a non `'static` lifetime /// corresponding to the lifetime of this transfer. pub fn debug_function(&mut self, f: F) -> Result<(), Error> where F: FnMut(InfoType, &[u8]) + 'data { self.data.debug = Some(Box::new(f)); Ok(()) } /// Same as `Easy::header_function`, just takes a non `'static` lifetime /// corresponding to the lifetime of this transfer. pub fn header_function(&mut self, f: F) -> Result<(), Error> where F: FnMut(&[u8]) -> bool + 'data { self.data.header = Some(Box::new(f)); Ok(()) } /// Same as `Easy::transfer`. pub fn perform(&self) -> Result<(), Error> { let inner = self.easy.inner.get_ref(); // Note that we're casting a `&self` pointer to a `*mut`, and then // during the invocation of this call we're going to invoke `FnMut` // closures that we ourselves own. // // This should be ok, however, because `do_perform` checks for recursive // invocations of `perform` and disallows them. Our type also isn't // `Sync`. inner.borrowed.set(&*self.data as *const _ as *mut _); // Make sure to reset everything back to the way it was before when // we're done. struct Reset<'a>(&'a Cell<*mut Callbacks<'static>>); impl<'a> Drop for Reset<'a> { fn drop(&mut self) { self.0.set(ptr::null_mut()); } } let _reset = Reset(&inner.borrowed); self.easy.do_perform() } /// Same as `Easy::unpause_read`. pub fn unpause_read(&self) -> Result<(), Error> { self.easy.unpause_read() } /// Same as `Easy::unpause_write` pub fn unpause_write(&self) -> Result<(), Error> { self.easy.unpause_write() } } impl<'easy, 'data> fmt::Debug for Transfer<'easy, 'data> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Transfer") .field("easy", &self.easy) .finish() } } impl<'easy, 'data> Drop for Transfer<'easy, 'data> { fn drop(&mut self) { // Extra double check to make sure we don't leak a pointer to ourselves. assert!(self.easy.inner.get_ref().borrowed.get().is_null()); } } vendor/curl-0.4.11/src/easy/handler.rs0000664000000000000000000037155413264166600016275 0ustar rootrootuse std::cell::RefCell; use std::ffi::{CStr, CString}; use std::fmt; use std::io::{self, SeekFrom, Write}; use std::path::Path; use std::slice; use std::str; use std::time::Duration; use curl_sys; use libc::{self, c_void, c_char, c_long, size_t, c_int, c_double, c_ulong}; use socket2::Socket; use Error; use easy::form; use easy::list; use easy::{List, Form}; use easy::windows; use panic; /// A trait for the various callbacks used by libcurl to invoke user code. /// /// This trait represents all operations that libcurl can possibly invoke a /// client for code during an HTTP transaction. Each callback has a default /// "noop" implementation, the same as in libcurl. Types implementing this trait /// may simply override the relevant functions to learn about the callbacks /// they're interested in. /// /// # Examples /// /// ``` /// use curl::easy::{Easy2, Handler, WriteError}; /// /// struct Collector(Vec); /// /// impl Handler for Collector { /// fn write(&mut self, data: &[u8]) -> Result { /// self.0.extend_from_slice(data); /// Ok(data.len()) /// } /// } /// /// let mut easy = Easy2::new(Collector(Vec::new())); /// easy.get(true).unwrap(); /// easy.url("https://www.rust-lang.org/").unwrap(); /// easy.perform().unwrap(); /// /// assert_eq!(easy.response_code().unwrap(), 200); /// let contents = easy.get_ref(); /// println!("{}", String::from_utf8_lossy(&contents.0)); /// ``` pub trait Handler { /// Callback invoked whenever curl has downloaded data for the application. /// /// This callback function gets called by libcurl as soon as there is data /// received that needs to be saved. /// /// The callback function will be passed as much data as possible in all /// invokes, but you must not make any assumptions. It may be one byte, it /// may be thousands. If `show_header` is enabled, which makes header data /// get passed to the write callback, you can get up to /// `CURL_MAX_HTTP_HEADER` bytes of header data passed into it. This /// usually means 100K. /// /// This function may be called with zero bytes data if the transferred file /// is empty. /// /// The callback should return the number of bytes actually taken care of. /// If that amount differs from the amount passed to your callback function, /// it'll signal an error condition to the library. This will cause the /// transfer to get aborted and the libcurl function used will return /// an error with `is_write_error`. /// /// If your callback function returns `Err(WriteError::Pause)` it will cause /// this transfer to become paused. See `unpause_write` for further details. /// /// By default data is sent into the void, and this corresponds to the /// `CURLOPT_WRITEFUNCTION` and `CURLOPT_WRITEDATA` options. fn write(&mut self, data: &[u8]) -> Result { Ok(data.len()) } /// Read callback for data uploads. /// /// This callback function gets called by libcurl as soon as it needs to /// read data in order to send it to the peer - like if you ask it to upload /// or post data to the server. /// /// Your function must then return the actual number of bytes that it stored /// in that memory area. Returning 0 will signal end-of-file to the library /// and cause it to stop the current transfer. /// /// If you stop the current transfer by returning 0 "pre-maturely" (i.e /// before the server expected it, like when you've said you will upload N /// bytes and you upload less than N bytes), you may experience that the /// server "hangs" waiting for the rest of the data that won't come. /// /// The read callback may return `Err(ReadError::Abort)` to stop the /// current operation immediately, resulting in a `is_aborted_by_callback` /// error code from the transfer. /// /// The callback can return `Err(ReadError::Pause)` to cause reading from /// this connection to pause. See `unpause_read` for further details. /// /// By default data not input, and this corresponds to the /// `CURLOPT_READFUNCTION` and `CURLOPT_READDATA` options. /// /// Note that the lifetime bound on this function is `'static`, but that /// is often too restrictive. To use stack data consider calling the /// `transfer` method and then using `read_function` to configure a /// callback that can reference stack-local data. fn read(&mut self, data: &mut [u8]) -> Result { drop(data); Ok(0) } /// User callback for seeking in input stream. /// /// This function gets called by libcurl to seek to a certain position in /// the input stream and can be used to fast forward a file in a resumed /// upload (instead of reading all uploaded bytes with the normal read /// function/callback). It is also called to rewind a stream when data has /// already been sent to the server and needs to be sent again. This may /// happen when doing a HTTP PUT or POST with a multi-pass authentication /// method, or when an existing HTTP connection is reused too late and the /// server closes the connection. /// /// The callback function must return `SeekResult::Ok` on success, /// `SeekResult::Fail` to cause the upload operation to fail or /// `SeekResult::CantSeek` to indicate that while the seek failed, libcurl /// is free to work around the problem if possible. The latter can sometimes /// be done by instead reading from the input or similar. /// /// By default data this option is not set, and this corresponds to the /// `CURLOPT_SEEKFUNCTION` and `CURLOPT_SEEKDATA` options. fn seek(&mut self, whence: SeekFrom) -> SeekResult { drop(whence); SeekResult::CantSeek } /// Specify a debug callback /// /// `debug_function` replaces the standard debug function used when /// `verbose` is in effect. This callback receives debug information, /// as specified in the type argument. /// /// By default this option is not set and corresponds to the /// `CURLOPT_DEBUGFUNCTION` and `CURLOPT_DEBUGDATA` options. fn debug(&mut self, kind: InfoType, data: &[u8]) { debug(kind, data) } /// Callback that receives header data /// /// This function gets called by libcurl as soon as it has received header /// data. The header callback will be called once for each header and only /// complete header lines are passed on to the callback. Parsing headers is /// very easy using this. If this callback returns `false` it'll signal an /// error to the library. This will cause the transfer to get aborted and /// the libcurl function in progress will return `is_write_error`. /// /// A complete HTTP header that is passed to this function can be up to /// CURL_MAX_HTTP_HEADER (100K) bytes. /// /// It's important to note that the callback will be invoked for the headers /// of all responses received after initiating a request and not just the /// final response. This includes all responses which occur during /// authentication negotiation. If you need to operate on only the headers /// from the final response, you will need to collect headers in the /// callback yourself and use HTTP status lines, for example, to delimit /// response boundaries. /// /// When a server sends a chunked encoded transfer, it may contain a /// trailer. That trailer is identical to a HTTP header and if such a /// trailer is received it is passed to the application using this callback /// as well. There are several ways to detect it being a trailer and not an /// ordinary header: 1) it comes after the response-body. 2) it comes after /// the final header line (CR LF) 3) a Trailer: header among the regular /// response-headers mention what header(s) to expect in the trailer. /// /// For non-HTTP protocols like FTP, POP3, IMAP and SMTP this function will /// get called with the server responses to the commands that libcurl sends. /// /// By default this option is not set and corresponds to the /// `CURLOPT_HEADERFUNCTION` and `CURLOPT_HEADERDATA` options. fn header(&mut self, data: &[u8]) -> bool { drop(data); true } /// Callback to progress meter function /// /// This function gets called by libcurl instead of its internal equivalent /// with a frequent interval. While data is being transferred it will be /// called very frequently, and during slow periods like when nothing is /// being transferred it can slow down to about one call per second. /// /// The callback gets told how much data libcurl will transfer and has /// transferred, in number of bytes. The first argument is the total number /// of bytes libcurl expects to download in this transfer. The second /// argument is the number of bytes downloaded so far. The third argument is /// the total number of bytes libcurl expects to upload in this transfer. /// The fourth argument is the number of bytes uploaded so far. /// /// Unknown/unused argument values passed to the callback will be set to /// zero (like if you only download data, the upload size will remain 0). /// Many times the callback will be called one or more times first, before /// it knows the data sizes so a program must be made to handle that. /// /// Returning `false` from this callback will cause libcurl to abort the /// transfer and return `is_aborted_by_callback`. /// /// If you transfer data with the multi interface, this function will not be /// called during periods of idleness unless you call the appropriate /// libcurl function that performs transfers. /// /// `progress` must be set to `true` to make this function actually get /// called. /// /// By default this function calls an internal method and corresponds to /// `CURLOPT_PROGRESSFUNCTION` and `CURLOPT_PROGRESSDATA`. fn progress(&mut self, dltotal: f64, dlnow: f64, ultotal: f64, ulnow: f64) -> bool { drop((dltotal, dlnow, ultotal, ulnow)); true } /// Callback to SSL context /// /// This callback function gets called by libcurl just before the /// initialization of an SSL connection after having processed all /// other SSL related options to give a last chance to an /// application to modify the behaviour of the SSL /// initialization. The `ssl_ctx` parameter is actually a pointer /// to the SSL library's SSL_CTX. If an error is returned from the /// callback no attempt to establish a connection is made and the /// perform operation will return the callback's error code. /// /// This function will get called on all new connections made to a /// server, during the SSL negotiation. The SSL_CTX pointer will /// be a new one every time. /// /// To use this properly, a non-trivial amount of knowledge of /// your SSL library is necessary. For example, you can use this /// function to call library-specific callbacks to add additional /// validation code for certificates, and even to change the /// actual URI of a HTTPS request. /// /// By default this function calls an internal method and /// corresponds to `CURLOPT_SSL_CTX_FUNCTION` and /// `CURLOPT_SSL_CTX_DATA`. /// /// Note that this callback is not guaranteed to be called, not all versions /// of libcurl support calling this callback. fn ssl_ctx(&mut self, cx: *mut c_void) -> Result<(), Error> { // By default, if we're on an OpenSSL enabled libcurl and we're on // Windows, add the system's certificate store to OpenSSL's certificate // store. ssl_ctx(cx) } /// Callback to open sockets for libcurl. /// /// This callback function gets called by libcurl instead of the socket(2) /// call. The callback function should return the newly created socket /// or `None` in case no connection could be established or another /// error was detected. Any additional `setsockopt(2)` calls can of course /// be done on the socket at the user's discretion. A `None` return /// value from the callback function will signal an unrecoverable error to /// libcurl and it will return `is_couldnt_connect` from the function that /// triggered this callback. /// /// By default this function opens a standard socket and /// corresponds to `CURLOPT_OPENSOCKETFUNCTION `. fn open_socket(&mut self, family: c_int, socktype: c_int, protocol: c_int) -> Option { // Note that we override this to calling a function in `socket2` to // ensure that we open all sockets with CLOEXEC. Otherwise if we rely on // libcurl to open sockets it won't use CLOEXEC. return Socket::new(family.into(), socktype.into(), Some(protocol.into())) .ok() .map(cvt); #[cfg(unix)] fn cvt(socket: Socket) -> curl_sys::curl_socket_t { use std::os::unix::prelude::*; socket.into_raw_fd() } #[cfg(windows)] fn cvt(socket: Socket) -> curl_sys::curl_socket_t { use std::os::windows::prelude::*; socket.into_raw_socket() } } } pub fn debug(kind: InfoType, data: &[u8]) { let out = io::stderr(); let prefix = match kind { InfoType::Text => "*", InfoType::HeaderIn => "<", InfoType::HeaderOut => ">", InfoType::DataIn | InfoType::SslDataIn => "{", InfoType::DataOut | InfoType::SslDataOut => "}", InfoType::__Nonexhaustive => " ", }; let mut out = out.lock(); drop(write!(out, "{} ", prefix)); drop(out.write_all(data)); } pub fn ssl_ctx(cx: *mut c_void) -> Result<(), Error> { windows::add_certs_to_context(cx); Ok(()) } /// Raw bindings to a libcurl "easy session". /// /// This type corresponds to the `CURL` type in libcurl, and is probably what /// you want for just sending off a simple HTTP request and fetching a response. /// Each easy handle can be thought of as a large builder before calling the /// final `perform` function. /// /// There are many many configuration options for each `Easy2` handle, and they /// should all have their own documentation indicating what it affects and how /// it interacts with other options. Some implementations of libcurl can use /// this handle to interact with many different protocols, although by default /// this crate only guarantees the HTTP/HTTPS protocols working. /// /// Note that almost all methods on this structure which configure various /// properties return a `Result`. This is largely used to detect whether the /// underlying implementation of libcurl actually implements the option being /// requested. If you're linked to a version of libcurl which doesn't support /// the option, then an error will be returned. Some options also perform some /// validation when they're set, and the error is returned through this vector. /// /// Note that historically this library contained an `Easy` handle so this one's /// called `Easy2`. The major difference between the `Easy` type is that an /// `Easy2` structure uses a trait instead of closures for all of the callbacks /// that curl can invoke. The `Easy` type is actually built on top of this /// `Easy` type, and this `Easy2` type can be more flexible in some situations /// due to the generic parameter. /// /// There's not necessarily a right answer for which type is correct to use, but /// as a general rule of thumb `Easy` is typically a reasonable choice for /// synchronous I/O and `Easy2` is a good choice for asynchronous I/O. /// /// # Examples /// /// ``` /// use curl::easy::{Easy2, Handler, WriteError}; /// /// struct Collector(Vec); /// /// impl Handler for Collector { /// fn write(&mut self, data: &[u8]) -> Result { /// self.0.extend_from_slice(data); /// Ok(data.len()) /// } /// } /// /// let mut easy = Easy2::new(Collector(Vec::new())); /// easy.get(true).unwrap(); /// easy.url("https://www.rust-lang.org/").unwrap(); /// easy.perform().unwrap(); /// /// assert_eq!(easy.response_code().unwrap(), 200); /// let contents = easy.get_ref(); /// println!("{}", String::from_utf8_lossy(&contents.0)); /// ``` pub struct Easy2 { inner: Box>, } struct Inner { handle: *mut curl_sys::CURL, header_list: Option, resolve_list: Option, form: Option

, error_buf: RefCell>, handler: H, } unsafe impl Send for Inner {} /// Possible proxy types that libcurl currently understands. #[allow(missing_docs)] #[derive(Debug)] pub enum ProxyType { Http = curl_sys::CURLPROXY_HTTP as isize, Http1 = curl_sys::CURLPROXY_HTTP_1_0 as isize, Socks4 = curl_sys::CURLPROXY_SOCKS4 as isize, Socks5 = curl_sys::CURLPROXY_SOCKS5 as isize, Socks4a = curl_sys::CURLPROXY_SOCKS4A as isize, Socks5Hostname = curl_sys::CURLPROXY_SOCKS5_HOSTNAME as isize, /// Hidden variant to indicate that this enum should not be matched on, it /// may grow over time. #[doc(hidden)] __Nonexhaustive, } /// Possible conditions for the `time_condition` method. #[allow(missing_docs)] #[derive(Debug)] pub enum TimeCondition { None = curl_sys::CURL_TIMECOND_NONE as isize, IfModifiedSince = curl_sys::CURL_TIMECOND_IFMODSINCE as isize, IfUnmodifiedSince = curl_sys::CURL_TIMECOND_IFUNMODSINCE as isize, LastModified = curl_sys::CURL_TIMECOND_LASTMOD as isize, /// Hidden variant to indicate that this enum should not be matched on, it /// may grow over time. #[doc(hidden)] __Nonexhaustive, } /// Possible values to pass to the `ip_resolve` method. #[allow(missing_docs)] #[derive(Debug)] pub enum IpResolve { V4 = curl_sys::CURL_IPRESOLVE_V4 as isize, V6 = curl_sys::CURL_IPRESOLVE_V6 as isize, Any = curl_sys::CURL_IPRESOLVE_WHATEVER as isize, /// Hidden variant to indicate that this enum should not be matched on, it /// may grow over time. #[doc(hidden)] __Nonexhaustive = 500, } /// Possible values to pass to the `http_version` method. #[derive(Debug)] pub enum HttpVersion { /// We don't care what http version to use, and we'd like the library to /// choose the best possible for us. Any = curl_sys::CURL_HTTP_VERSION_NONE as isize, /// Please use HTTP 1.0 in the request V10 = curl_sys::CURL_HTTP_VERSION_1_0 as isize, /// Please use HTTP 1.1 in the request V11 = curl_sys::CURL_HTTP_VERSION_1_1 as isize, /// Please use HTTP 2 in the request /// (Added in CURL 7.33.0) V2 = curl_sys::CURL_HTTP_VERSION_2_0 as isize, /// Use version 2 for HTTPS, version 1.1 for HTTP /// (Added in CURL 7.47.0) V2TLS = curl_sys::CURL_HTTP_VERSION_2TLS as isize, /// Please use HTTP 2 without HTTP/1.1 Upgrade /// (Added in CURL 7.49.0) V2PriorKnowledge = curl_sys::CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE as isize, /// Hidden variant to indicate that this enum should not be matched on, it /// may grow over time. #[doc(hidden)] __Nonexhaustive = 500, } /// Possible values to pass to the `ip_resolve` method. #[allow(missing_docs)] #[derive(Debug)] pub enum SslVersion { Default = curl_sys::CURL_SSLVERSION_DEFAULT as isize, Tlsv1 = curl_sys::CURL_SSLVERSION_TLSv1 as isize, Sslv2 = curl_sys::CURL_SSLVERSION_SSLv2 as isize, Sslv3 = curl_sys::CURL_SSLVERSION_SSLv3 as isize, // Tlsv10 = curl_sys::CURL_SSLVERSION_TLSv1_0 as isize, // Tlsv11 = curl_sys::CURL_SSLVERSION_TLSv1_1 as isize, // Tlsv12 = curl_sys::CURL_SSLVERSION_TLSv1_2 as isize, /// Hidden variant to indicate that this enum should not be matched on, it /// may grow over time. #[doc(hidden)] __Nonexhaustive = 500, } /// Possible return values from the `seek_function` callback. #[derive(Debug)] pub enum SeekResult { /// Indicates that the seek operation was a success Ok = curl_sys::CURL_SEEKFUNC_OK as isize, /// Indicates that the seek operation failed, and the entire request should /// fail as a result. Fail = curl_sys::CURL_SEEKFUNC_FAIL as isize, /// Indicates that although the seek failed libcurl should attempt to keep /// working if possible (for example "seek" through reading). CantSeek = curl_sys::CURL_SEEKFUNC_CANTSEEK as isize, /// Hidden variant to indicate that this enum should not be matched on, it /// may grow over time. #[doc(hidden)] __Nonexhaustive = 500, } /// Possible data chunks that can be witnessed as part of the `debug_function` /// callback. #[derive(Debug)] pub enum InfoType { /// The data is informational text. Text, /// The data is header (or header-like) data received from the peer. HeaderIn, /// The data is header (or header-like) data sent to the peer. HeaderOut, /// The data is protocol data received from the peer. DataIn, /// The data is protocol data sent to the peer. DataOut, /// The data is SSL/TLS (binary) data received from the peer. SslDataIn, /// The data is SSL/TLS (binary) data sent to the peer. SslDataOut, /// Hidden variant to indicate that this enum should not be matched on, it /// may grow over time. #[doc(hidden)] __Nonexhaustive, } /// Possible error codes that can be returned from the `read_function` callback. #[derive(Debug)] pub enum ReadError { /// Indicates that the connection should be aborted immediately Abort, /// Indicates that reading should be paused until `unpause` is called. Pause, /// Hidden variant to indicate that this enum should not be matched on, it /// may grow over time. #[doc(hidden)] __Nonexhaustive, } /// Possible error codes that can be returned from the `write_function` callback. #[derive(Debug)] pub enum WriteError { /// Indicates that reading should be paused until `unpause` is called. Pause, /// Hidden variant to indicate that this enum should not be matched on, it /// may grow over time. #[doc(hidden)] __Nonexhaustive, } /// Options for `.netrc` parsing. #[derive(Debug)] pub enum NetRc { /// Ignoring `.netrc` file and use information from url /// /// This option is default Ignored = curl_sys::CURL_NETRC_IGNORED as isize, /// The use of your `~/.netrc` file is optional, and information in the URL is to be /// preferred. The file will be scanned for the host and user name (to find the password only) /// or for the host only, to find the first user name and password after that machine, which /// ever information is not specified in the URL. Optional = curl_sys::CURL_NETRC_OPTIONAL as isize, /// This value tells the library that use of the file is required, to ignore the information in /// the URL, and to search the file for the host only. Required = curl_sys::CURL_NETRC_REQUIRED as isize, } /// Structure which stores possible authentication methods to get passed to /// `http_auth` and `proxy_auth`. #[derive(Clone)] pub struct Auth { bits: c_long, } /// Structure which stores possible ssl options to pass to `ssl_options`. #[derive(Clone)] pub struct SslOpt { bits: c_long, } impl Easy2 { /// Creates a new "easy" handle which is the core of almost all operations /// in libcurl. /// /// To use a handle, applications typically configure a number of options /// followed by a call to `perform`. Options are preserved across calls to /// `perform` and need to be reset manually (or via the `reset` method) if /// this is not desired. pub fn new(handler: H) -> Easy2 { ::init(); unsafe { let handle = curl_sys::curl_easy_init(); assert!(!handle.is_null()); let mut ret = Easy2 { inner: Box::new(Inner { handle: handle, header_list: None, resolve_list: None, form: None, error_buf: RefCell::new(vec![0; curl_sys::CURL_ERROR_SIZE]), handler: handler, }), }; ret.default_configure(); return ret } } /// Re-initializes this handle to the default values. /// /// This puts the handle to the same state as it was in when it was just /// created. This does, however, keep live connections, the session id /// cache, the dns cache, and cookies. pub fn reset(&mut self) { unsafe { curl_sys::curl_easy_reset(self.inner.handle); } self.default_configure(); } fn default_configure(&mut self) { self.setopt_ptr(curl_sys::CURLOPT_ERRORBUFFER, self.inner.error_buf.borrow().as_ptr() as *const _) .expect("failed to set error buffer"); let _ = self.signal(false); self.ssl_configure(); let ptr = &*self.inner as *const _ as *const _; let cb: extern fn(*mut c_char, size_t, size_t, *mut c_void) -> size_t = header_cb::; self.setopt_ptr(curl_sys::CURLOPT_HEADERFUNCTION, cb as *const _) .expect("failed to set header callback"); self.setopt_ptr(curl_sys::CURLOPT_HEADERDATA, ptr) .expect("failed to set header callback"); let cb: curl_sys::curl_write_callback = write_cb::; self.setopt_ptr(curl_sys::CURLOPT_WRITEFUNCTION, cb as *const _) .expect("failed to set write callback"); self.setopt_ptr(curl_sys::CURLOPT_WRITEDATA, ptr) .expect("failed to set write callback"); let cb: curl_sys::curl_read_callback = read_cb::; self.setopt_ptr(curl_sys::CURLOPT_READFUNCTION, cb as *const _) .expect("failed to set read callback"); self.setopt_ptr(curl_sys::CURLOPT_READDATA, ptr) .expect("failed to set read callback"); let cb: curl_sys::curl_seek_callback = seek_cb::; self.setopt_ptr(curl_sys::CURLOPT_SEEKFUNCTION, cb as *const _) .expect("failed to set seek callback"); self.setopt_ptr(curl_sys::CURLOPT_SEEKDATA, ptr) .expect("failed to set seek callback"); let cb: curl_sys::curl_progress_callback = progress_cb::; self.setopt_ptr(curl_sys::CURLOPT_PROGRESSFUNCTION, cb as *const _) .expect("failed to set progress callback"); self.setopt_ptr(curl_sys::CURLOPT_PROGRESSDATA, ptr) .expect("failed to set progress callback"); let cb: curl_sys::curl_debug_callback = debug_cb::; self.setopt_ptr(curl_sys::CURLOPT_DEBUGFUNCTION, cb as *const _) .expect("failed to set debug callback"); self.setopt_ptr(curl_sys::CURLOPT_DEBUGDATA, ptr) .expect("failed to set debug callback"); let cb: curl_sys::curl_ssl_ctx_callback = ssl_ctx_cb::; drop(self.setopt_ptr(curl_sys::CURLOPT_SSL_CTX_FUNCTION, cb as *const _)); drop(self.setopt_ptr(curl_sys::CURLOPT_SSL_CTX_DATA, ptr)); let cb: curl_sys::curl_opensocket_callback = opensocket_cb::; self.setopt_ptr(curl_sys::CURLOPT_OPENSOCKETFUNCTION , cb as *const _) .expect("failed to set open socket callback"); self.setopt_ptr(curl_sys::CURLOPT_OPENSOCKETDATA, ptr) .expect("failed to set open socket callback"); } #[cfg(all(unix, not(target_os = "macos")))] fn ssl_configure(&mut self) { let probe = ::openssl_probe::probe(); if let Some(ref path) = probe.cert_file { let _ = self.cainfo(path); } if let Some(ref path) = probe.cert_dir { let _ = self.capath(path); } } #[cfg(not(all(unix, not(target_os = "macos"))))] fn ssl_configure(&mut self) {} } impl Easy2 { // ========================================================================= // Behavior options /// Configures this handle to have verbose output to help debug protocol /// information. /// /// By default output goes to stderr, but the `stderr` function on this type /// can configure that. You can also use the `debug_function` method to get /// all protocol data sent and received. /// /// By default, this option is `false`. pub fn verbose(&mut self, verbose: bool) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_VERBOSE, verbose as c_long) } /// Indicates whether header information is streamed to the output body of /// this request. /// /// This option is only relevant for protocols which have header metadata /// (like http or ftp). It's not generally possible to extract headers /// from the body if using this method, that use case should be intended for /// the `header_function` method. /// /// To set HTTP headers, use the `http_header` method. /// /// By default, this option is `false` and corresponds to /// `CURLOPT_HEADER`. pub fn show_header(&mut self, show: bool) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_HEADER, show as c_long) } /// Indicates whether a progress meter will be shown for requests done with /// this handle. /// /// This will also prevent the `progress_function` from being called. /// /// By default this option is `false` and corresponds to /// `CURLOPT_NOPROGRESS`. pub fn progress(&mut self, progress: bool) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_NOPROGRESS, (!progress) as c_long) } /// Inform libcurl whether or not it should install signal handlers or /// attempt to use signals to perform library functions. /// /// If this option is disabled then timeouts during name resolution will not /// work unless libcurl is built against c-ares. Note that enabling this /// option, however, may not cause libcurl to work with multiple threads. /// /// By default this option is `false` and corresponds to `CURLOPT_NOSIGNAL`. /// Note that this default is **different than libcurl** as it is intended /// that this library is threadsafe by default. See the [libcurl docs] for /// some more information. /// /// [libcurl docs]: https://curl.haxx.se/libcurl/c/threadsafe.html pub fn signal(&mut self, signal: bool) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_NOSIGNAL, (!signal) as c_long) } /// Indicates whether multiple files will be transferred based on the file /// name pattern. /// /// The last part of a filename uses fnmatch-like pattern matching. /// /// By default this option is `false` and corresponds to /// `CURLOPT_WILDCARDMATCH`. pub fn wildcard_match(&mut self, m: bool) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_WILDCARDMATCH, m as c_long) } /// Provides the unix domain socket which this handle will work with. /// /// The string provided must be unix domain socket -encoded with the format: /// /// ```text /// /path/file.sock /// ``` pub fn unix_socket(&mut self, unix_domain_socket: &str) -> Result<(), Error> { let socket = try!(CString::new(unix_domain_socket)); self.setopt_str(curl_sys::CURLOPT_UNIX_SOCKET_PATH, &socket) } // ========================================================================= // Internal accessors /// Acquires a reference to the underlying handler for events. pub fn get_ref(&self) -> &H { &self.inner.handler } /// Acquires a reference to the underlying handler for events. pub fn get_mut(&mut self) -> &mut H { &mut self.inner.handler } // ========================================================================= // Error options // TODO: error buffer and stderr /// Indicates whether this library will fail on HTTP response codes >= 400. /// /// This method is not fail-safe especially when authentication is involved. /// /// By default this option is `false` and corresponds to /// `CURLOPT_FAILONERROR`. pub fn fail_on_error(&mut self, fail: bool) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_FAILONERROR, fail as c_long) } // ========================================================================= // Network options /// Provides the URL which this handle will work with. /// /// The string provided must be URL-encoded with the format: /// /// ```text /// scheme://host:port/path /// ``` /// /// The syntax is not validated as part of this function and that is /// deferred until later. /// /// By default this option is not set and `perform` will not work until it /// is set. This option corresponds to `CURLOPT_URL`. pub fn url(&mut self, url: &str) -> Result<(), Error> { let url = try!(CString::new(url)); self.setopt_str(curl_sys::CURLOPT_URL, &url) } /// Configures the port number to connect to, instead of the one specified /// in the URL or the default of the protocol. pub fn port(&mut self, port: u16) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_PORT, port as c_long) } // /// Indicates whether sequences of `/../` and `/./` will be squashed or not. // /// // /// By default this option is `false` and corresponds to // /// `CURLOPT_PATH_AS_IS`. // pub fn path_as_is(&mut self, as_is: bool) -> Result<(), Error> { // } /// Provide the URL of a proxy to use. /// /// By default this option is not set and corresponds to `CURLOPT_PROXY`. pub fn proxy(&mut self, url: &str) -> Result<(), Error> { let url = try!(CString::new(url)); self.setopt_str(curl_sys::CURLOPT_PROXY, &url) } /// Provide port number the proxy is listening on. /// /// By default this option is not set (the default port for the proxy /// protocol is used) and corresponds to `CURLOPT_PROXYPORT`. pub fn proxy_port(&mut self, port: u16) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_PROXYPORT, port as c_long) } /// Indicates the type of proxy being used. /// /// By default this option is `ProxyType::Http` and corresponds to /// `CURLOPT_PROXYTYPE`. pub fn proxy_type(&mut self, kind: ProxyType) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_PROXYTYPE, kind as c_long) } /// Provide a list of hosts that should not be proxied to. /// /// This string is a comma-separated list of hosts which should not use the /// proxy specified for connections. A single `*` character is also accepted /// as a wildcard for all hosts. /// /// By default this option is not set and corresponds to /// `CURLOPT_NOPROXY`. pub fn noproxy(&mut self, skip: &str) -> Result<(), Error> { let skip = try!(CString::new(skip)); self.setopt_str(curl_sys::CURLOPT_PROXYTYPE, &skip) } /// Inform curl whether it should tunnel all operations through the proxy. /// /// This essentially means that a `CONNECT` is sent to the proxy for all /// outbound requests. /// /// By default this option is `false` and corresponds to /// `CURLOPT_HTTPPROXYTUNNEL`. pub fn http_proxy_tunnel(&mut self, tunnel: bool) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_HTTPPROXYTUNNEL, tunnel as c_long) } /// Tell curl which interface to bind to for an outgoing network interface. /// /// The interface name, IP address, or host name can be specified here. /// /// By default this option is not set and corresponds to /// `CURLOPT_INTERFACE`. pub fn interface(&mut self, interface: &str) -> Result<(), Error> { let s = try!(CString::new(interface)); self.setopt_str(curl_sys::CURLOPT_INTERFACE, &s) } /// Indicate which port should be bound to locally for this connection. /// /// By default this option is 0 (any port) and corresponds to /// `CURLOPT_LOCALPORT`. pub fn set_local_port(&mut self, port: u16) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_LOCALPORT, port as c_long) } /// Indicates the number of attempts libcurl will perform to find a working /// port number. /// /// By default this option is 1 and corresponds to /// `CURLOPT_LOCALPORTRANGE`. pub fn local_port_range(&mut self, range: u16) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_LOCALPORTRANGE, range as c_long) } /// Sets the timeout of how long name resolves will be kept in memory. /// /// This is distinct from DNS TTL options and is entirely speculative. /// /// By default this option is 60s and corresponds to /// `CURLOPT_DNS_CACHE_TIMEOUT`. pub fn dns_cache_timeout(&mut self, dur: Duration) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_DNS_CACHE_TIMEOUT, dur.as_secs() as c_long) } /// Specify the preferred receive buffer size, in bytes. /// /// This is treated as a request, not an order, and the main point of this /// is that the write callback may get called more often with smaller /// chunks. /// /// By default this option is the maximum write size and corresopnds to /// `CURLOPT_BUFFERSIZE`. pub fn buffer_size(&mut self, size: usize) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_BUFFERSIZE, size as c_long) } // /// Enable or disable TCP Fast Open // /// // /// By default this options defaults to `false` and corresponds to // /// `CURLOPT_TCP_FASTOPEN` // pub fn fast_open(&mut self, enable: bool) -> Result<(), Error> { // } /// Configures whether the TCP_NODELAY option is set, or Nagle's algorithm /// is disabled. /// /// The purpose of Nagle's algorithm is to minimize the number of small /// packet's on the network, and disabling this may be less efficient in /// some situations. /// /// By default this option is `false` and corresponds to /// `CURLOPT_TCP_NODELAY`. pub fn tcp_nodelay(&mut self, enable: bool) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_TCP_NODELAY, enable as c_long) } /// Configures whether TCP keepalive probes will be sent. /// /// The delay and frequency of these probes is controlled by `tcp_keepidle` /// and `tcp_keepintvl`. /// /// By default this option is `false` and corresponds to /// `CURLOPT_TCP_KEEPALIVE`. pub fn tcp_keepalive(&mut self, enable: bool) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_TCP_KEEPALIVE, enable as c_long) } /// Configures the TCP keepalive idle time wait. /// /// This is the delay, after which the connection is idle, keepalive probes /// will be sent. Not all operating systems support this. /// /// By default this corresponds to `CURLOPT_TCP_KEEPIDLE`. pub fn tcp_keepidle(&mut self, amt: Duration) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_TCP_KEEPIDLE, amt.as_secs() as c_long) } /// Configures the delay between keepalive probes. /// /// By default this corresponds to `CURLOPT_TCP_KEEPINTVL`. pub fn tcp_keepintvl(&mut self, amt: Duration) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_TCP_KEEPINTVL, amt.as_secs() as c_long) } /// Configures the scope for local IPv6 addresses. /// /// Sets the scope_id value to use when connecting to IPv6 or link-local /// addresses. /// /// By default this value is 0 and corresponds to `CURLOPT_ADDRESS_SCOPE` pub fn address_scope(&mut self, scope: u32) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_ADDRESS_SCOPE, scope as c_long) } // ========================================================================= // Names and passwords /// Configures the username to pass as authentication for this connection. /// /// By default this value is not set and corresponds to `CURLOPT_USERNAME`. pub fn username(&mut self, user: &str) -> Result<(), Error> { let user = try!(CString::new(user)); self.setopt_str(curl_sys::CURLOPT_USERNAME, &user) } /// Configures the password to pass as authentication for this connection. /// /// By default this value is not set and corresponds to `CURLOPT_PASSWORD`. pub fn password(&mut self, pass: &str) -> Result<(), Error> { let pass = try!(CString::new(pass)); self.setopt_str(curl_sys::CURLOPT_PASSWORD, &pass) } /// Set HTTP server authentication methods to try /// /// If more than one method is set, libcurl will first query the site to see /// which authentication methods it supports and then pick the best one you /// allow it to use. For some methods, this will induce an extra network /// round-trip. Set the actual name and password with the `password` and /// `username` methods. /// /// For authentication with a proxy, see `proxy_auth`. /// /// By default this value is basic and corresponds to `CURLOPT_HTTPAUTH`. pub fn http_auth(&mut self, auth: &Auth) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_HTTPAUTH, auth.bits) } /// Configures the proxy username to pass as authentication for this /// connection. /// /// By default this value is not set and corresponds to /// `CURLOPT_PROXYUSERNAME`. pub fn proxy_username(&mut self, user: &str) -> Result<(), Error> { let user = try!(CString::new(user)); self.setopt_str(curl_sys::CURLOPT_PROXYUSERNAME, &user) } /// Configures the proxy password to pass as authentication for this /// connection. /// /// By default this value is not set and corresponds to /// `CURLOPT_PROXYPASSWORD`. pub fn proxy_password(&mut self, pass: &str) -> Result<(), Error> { let pass = try!(CString::new(pass)); self.setopt_str(curl_sys::CURLOPT_PROXYPASSWORD, &pass) } /// Set HTTP proxy authentication methods to try /// /// If more than one method is set, libcurl will first query the site to see /// which authentication methods it supports and then pick the best one you /// allow it to use. For some methods, this will induce an extra network /// round-trip. Set the actual name and password with the `proxy_password` /// and `proxy_username` methods. /// /// By default this value is basic and corresponds to `CURLOPT_PROXYAUTH`. pub fn proxy_auth(&mut self, auth: &Auth) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_PROXYAUTH, auth.bits) } /// Enable .netrc parsing /// /// By default the .netrc file is ignored and corresponds to `CURL_NETRC_IGNORED`. pub fn netrc(&mut self, netrc: NetRc) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_NETRC, netrc as c_long) } // ========================================================================= // HTTP Options /// Indicates whether the referer header is automatically updated /// /// By default this option is `false` and corresponds to /// `CURLOPT_AUTOREFERER`. pub fn autoreferer(&mut self, enable: bool) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_AUTOREFERER, enable as c_long) } /// Enables automatic decompression of HTTP downloads. /// /// Sets the contents of the Accept-Encoding header sent in an HTTP request. /// This enables decoding of a response with Content-Encoding. /// /// Currently supported encoding are `identity`, `zlib`, and `gzip`. A /// zero-length string passed in will send all accepted encodings. /// /// By default this option is not set and corresponds to /// `CURLOPT_ACCEPT_ENCODING`. pub fn accept_encoding(&mut self, encoding: &str) -> Result<(), Error> { let encoding = try!(CString::new(encoding)); self.setopt_str(curl_sys::CURLOPT_ACCEPT_ENCODING, &encoding) } /// Request the HTTP Transfer Encoding. /// /// By default this option is `false` and corresponds to /// `CURLOPT_TRANSFER_ENCODING`. pub fn transfer_encoding(&mut self, enable: bool) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_TRANSFER_ENCODING, enable as c_long) } /// Follow HTTP 3xx redirects. /// /// Indicates whether any `Location` headers in the response should get /// followed. /// /// By default this option is `false` and corresponds to /// `CURLOPT_FOLLOWLOCATION`. pub fn follow_location(&mut self, enable: bool) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_FOLLOWLOCATION, enable as c_long) } /// Send credentials to hosts other than the first as well. /// /// Sends username/password credentials even when the host changes as part /// of a redirect. /// /// By default this option is `false` and corresponds to /// `CURLOPT_UNRESTRICTED_AUTH`. pub fn unrestricted_auth(&mut self, enable: bool) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_UNRESTRICTED_AUTH, enable as c_long) } /// Set the maximum number of redirects allowed. /// /// A value of 0 will refuse any redirect. /// /// By default this option is `-1` (unlimited) and corresponds to /// `CURLOPT_MAXREDIRS`. pub fn max_redirections(&mut self, max: u32) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_MAXREDIRS, max as c_long) } // TODO: post_redirections /// Make an HTTP PUT request. /// /// By default this option is `false` and corresponds to `CURLOPT_PUT`. pub fn put(&mut self, enable: bool) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_PUT, enable as c_long) } /// Make an HTTP POST request. /// /// This will also make the library use the /// `Content-Type: application/x-www-form-urlencoded` header. /// /// POST data can be specified through `post_fields` or by specifying a read /// function. /// /// By default this option is `false` and corresponds to `CURLOPT_POST`. pub fn post(&mut self, enable: bool) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_POST, enable as c_long) } /// Configures the data that will be uploaded as part of a POST. /// /// Note that the data is copied into this handle and if that's not desired /// then the read callbacks can be used instead. /// /// By default this option is not set and corresponds to /// `CURLOPT_COPYPOSTFIELDS`. pub fn post_fields_copy(&mut self, data: &[u8]) -> Result<(), Error> { // Set the length before the pointer so libcurl knows how much to read try!(self.post_field_size(data.len() as u64)); self.setopt_ptr(curl_sys::CURLOPT_COPYPOSTFIELDS, data.as_ptr() as *const _) } /// Configures the size of data that's going to be uploaded as part of a /// POST operation. /// /// This is called automaticsally as part of `post_fields` and should only /// be called if data is being provided in a read callback (and even then /// it's optional). /// /// By default this option is not set and corresponds to /// `CURLOPT_POSTFIELDSIZE_LARGE`. pub fn post_field_size(&mut self, size: u64) -> Result<(), Error> { // Clear anything previous to ensure we don't read past a buffer try!(self.setopt_ptr(curl_sys::CURLOPT_POSTFIELDS, 0 as *const _)); self.setopt_off_t(curl_sys::CURLOPT_POSTFIELDSIZE_LARGE, size as curl_sys::curl_off_t) } /// Tells libcurl you want a multipart/formdata HTTP POST to be made and you /// instruct what data to pass on to the server in the `form` argument. /// /// By default this option is set to null and corresponds to /// `CURLOPT_HTTPPOST`. pub fn httppost(&mut self, form: Form) -> Result<(), Error> { try!(self.setopt_ptr(curl_sys::CURLOPT_HTTPPOST, form::raw(&form) as *const _)); self.inner.form = Some(form); Ok(()) } /// Sets the HTTP referer header /// /// By default this option is not set and corresponds to `CURLOPT_REFERER`. pub fn referer(&mut self, referer: &str) -> Result<(), Error> { let referer = try!(CString::new(referer)); self.setopt_str(curl_sys::CURLOPT_REFERER, &referer) } /// Sets the HTTP user-agent header /// /// By default this option is not set and corresponds to /// `CURLOPT_USERAGENT`. pub fn useragent(&mut self, useragent: &str) -> Result<(), Error> { let useragent = try!(CString::new(useragent)); self.setopt_str(curl_sys::CURLOPT_USERAGENT, &useragent) } /// Add some headers to this HTTP request. /// /// If you add a header that is otherwise used internally, the value here /// takes precedence. If a header is added with no content (like `Accept:`) /// the internally the header will get disabled. To add a header with no /// content, use the form `MyHeader;` (not the trailing semicolon). /// /// Headers must not be CRLF terminated. Many replaced headers have common /// shortcuts which should be prefered. /// /// By default this option is not set and corresponds to /// `CURLOPT_HTTPHEADER` /// /// # Examples /// /// ``` /// use curl::easy::{Easy, List}; /// /// let mut list = List::new(); /// list.append("Foo: bar").unwrap(); /// list.append("Bar: baz").unwrap(); /// /// let mut handle = Easy::new(); /// handle.url("https://www.rust-lang.org/").unwrap(); /// handle.http_headers(list).unwrap(); /// handle.perform().unwrap(); /// ``` pub fn http_headers(&mut self, list: List) -> Result<(), Error> { let ptr = list::raw(&list); self.inner.header_list = Some(list); self.setopt_ptr(curl_sys::CURLOPT_HTTPHEADER, ptr as *const _) } // /// Add some headers to send to the HTTP proxy. // /// // /// This function is essentially the same as `http_headers`. // /// // /// By default this option is not set and corresponds to // /// `CURLOPT_PROXYHEADER` // pub fn proxy_headers(&mut self, list: &'a List) -> Result<(), Error> { // self.setopt_ptr(curl_sys::CURLOPT_PROXYHEADER, list.raw as *const _) // } /// Set the contents of the HTTP Cookie header. /// /// Pass a string of the form `name=contents` for one cookie value or /// `name1=val1; name2=val2` for multiple values. /// /// Using this option multiple times will only make the latest string /// override the previous ones. This option will not enable the cookie /// engine, use `cookie_file` or `cookie_jar` to do that. /// /// By default this option is not set and corresponds to `CURLOPT_COOKIE`. pub fn cookie(&mut self, cookie: &str) -> Result<(), Error> { let cookie = try!(CString::new(cookie)); self.setopt_str(curl_sys::CURLOPT_COOKIE, &cookie) } /// Set the file name to read cookies from. /// /// The cookie data can be in either the old Netscape / Mozilla cookie data /// format or just regular HTTP headers (Set-Cookie style) dumped to a file. /// /// This also enables the cookie engine, making libcurl parse and send /// cookies on subsequent requests with this handle. /// /// Given an empty or non-existing file or by passing the empty string ("") /// to this option, you can enable the cookie engine without reading any /// initial cookies. /// /// If you use this option multiple times, you just add more files to read. /// Subsequent files will add more cookies. /// /// By default this option is not set and corresponds to /// `CURLOPT_COOKIEFILE`. pub fn cookie_file>(&mut self, file: P) -> Result<(), Error> { self.setopt_path(curl_sys::CURLOPT_COOKIEFILE, file.as_ref()) } /// Set the file name to store cookies to. /// /// This will make libcurl write all internally known cookies to the file /// when this handle is dropped. If no cookies are known, no file will be /// created. Specify "-" as filename to instead have the cookies written to /// stdout. Using this option also enables cookies for this session, so if /// you for example follow a location it will make matching cookies get sent /// accordingly. /// /// Note that libcurl doesn't read any cookies from the cookie jar. If you /// want to read cookies from a file, use `cookie_file`. /// /// By default this option is not set and corresponds to /// `CURLOPT_COOKIEJAR`. pub fn cookie_jar>(&mut self, file: P) -> Result<(), Error> { self.setopt_path(curl_sys::CURLOPT_COOKIEJAR, file.as_ref()) } /// Start a new cookie session /// /// Marks this as a new cookie "session". It will force libcurl to ignore /// all cookies it is about to load that are "session cookies" from the /// previous session. By default, libcurl always stores and loads all /// cookies, independent if they are session cookies or not. Session cookies /// are cookies without expiry date and they are meant to be alive and /// existing for this "session" only. /// /// By default this option is `false` and corresponds to /// `CURLOPT_COOKIESESSION`. pub fn cookie_session(&mut self, session: bool) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_COOKIESESSION, session as c_long) } /// Add to or manipulate cookies held in memory. /// /// Such a cookie can be either a single line in Netscape / Mozilla format /// or just regular HTTP-style header (Set-Cookie: ...) format. This will /// also enable the cookie engine. This adds that single cookie to the /// internal cookie store. /// /// Exercise caution if you are using this option and multiple transfers may /// occur. If you use the Set-Cookie format and don't specify a domain then /// the cookie is sent for any domain (even after redirects are followed) /// and cannot be modified by a server-set cookie. If a server sets a cookie /// of the same name (or maybe you've imported one) then both will be sent /// on a future transfer to that server, likely not what you intended. /// address these issues set a domain in Set-Cookie or use the Netscape /// format. /// /// Additionally, there are commands available that perform actions if you /// pass in these exact strings: /// /// * "ALL" - erases all cookies held in memory /// * "SESS" - erases all session cookies held in memory /// * "FLUSH" - write all known cookies to the specified cookie jar /// * "RELOAD" - reread all cookies from the cookie file /// /// By default this options corresponds to `CURLOPT_COOKIELIST` pub fn cookie_list(&mut self, cookie: &str) -> Result<(), Error> { let cookie = try!(CString::new(cookie)); self.setopt_str(curl_sys::CURLOPT_COOKIELIST, &cookie) } /// Ask for a HTTP GET request. /// /// By default this option is `false` and corresponds to `CURLOPT_HTTPGET`. pub fn get(&mut self, enable: bool) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_HTTPGET, enable as c_long) } // /// Ask for a HTTP GET request. // /// // /// By default this option is `false` and corresponds to `CURLOPT_HTTPGET`. // pub fn http_version(&mut self, vers: &str) -> Result<(), Error> { // self.setopt_long(curl_sys::CURLOPT_HTTPGET, enable as c_long) // } /// Ignore the content-length header. /// /// By default this option is `false` and corresponds to /// `CURLOPT_IGNORE_CONTENT_LENGTH`. pub fn ignore_content_length(&mut self, ignore: bool) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_IGNORE_CONTENT_LENGTH, ignore as c_long) } /// Enable or disable HTTP content decoding. /// /// By default this option is `true` and corresponds to /// `CURLOPT_HTTP_CONTENT_DECODING`. pub fn http_content_decoding(&mut self, enable: bool) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_HTTP_CONTENT_DECODING, enable as c_long) } /// Enable or disable HTTP transfer decoding. /// /// By default this option is `true` and corresponds to /// `CURLOPT_HTTP_TRANSFER_DECODING`. pub fn http_transfer_decoding(&mut self, enable: bool) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_HTTP_TRANSFER_DECODING, enable as c_long) } // /// Timeout for the Expect: 100-continue response // /// // /// By default this option is 1s and corresponds to // /// `CURLOPT_EXPECT_100_TIMEOUT_MS`. // pub fn expect_100_timeout(&mut self, enable: bool) -> Result<(), Error> { // self.setopt_long(curl_sys::CURLOPT_HTTP_TRANSFER_DECODING, // enable as c_long) // } // /// Wait for pipelining/multiplexing. // /// // /// Tells libcurl to prefer to wait for a connection to confirm or deny that // /// it can do pipelining or multiplexing before continuing. // /// // /// When about to perform a new transfer that allows pipelining or // /// multiplexing, libcurl will check for existing connections to re-use and // /// pipeline on. If no such connection exists it will immediately continue // /// and create a fresh new connection to use. // /// // /// By setting this option to `true` - having `pipeline` enabled for the // /// multi handle this transfer is associated with - libcurl will instead // /// wait for the connection to reveal if it is possible to // /// pipeline/multiplex on before it continues. This enables libcurl to much // /// better keep the number of connections to a minimum when using pipelining // /// or multiplexing protocols. // /// // /// The effect thus becomes that with this option set, libcurl prefers to // /// wait and re-use an existing connection for pipelining rather than the // /// opposite: prefer to open a new connection rather than waiting. // /// // /// The waiting time is as long as it takes for the connection to get up and // /// for libcurl to get the necessary response back that informs it about its // /// protocol and support level. // pub fn http_pipewait(&mut self, enable: bool) -> Result<(), Error> { // } // ========================================================================= // Protocol Options /// Indicates the range that this request should retrieve. /// /// The string provided should be of the form `N-M` where either `N` or `M` /// can be left out. For HTTP transfers multiple ranges separated by commas /// are also accepted. /// /// By default this option is not set and corresponds to `CURLOPT_RANGE`. pub fn range(&mut self, range: &str) -> Result<(), Error> { let range = try!(CString::new(range)); self.setopt_str(curl_sys::CURLOPT_RANGE, &range) } /// Set a point to resume transfer from /// /// Specify the offset in bytes you want the transfer to start from. /// /// By default this option is 0 and corresponds to /// `CURLOPT_RESUME_FROM_LARGE`. pub fn resume_from(&mut self, from: u64) -> Result<(), Error> { self.setopt_off_t(curl_sys::CURLOPT_RESUME_FROM_LARGE, from as curl_sys::curl_off_t) } /// Set a custom request string /// /// Specifies that a custom request will be made (e.g. a custom HTTP /// method). This does not change how libcurl performs internally, just /// changes the string sent to the server. /// /// By default this option is not set and corresponds to /// `CURLOPT_CUSTOMREQUEST`. pub fn custom_request(&mut self, request: &str) -> Result<(), Error> { let request = try!(CString::new(request)); self.setopt_str(curl_sys::CURLOPT_CUSTOMREQUEST, &request) } /// Get the modification time of the remote resource /// /// If true, libcurl will attempt to get the modification time of the /// remote document in this operation. This requires that the remote server /// sends the time or replies to a time querying command. The `filetime` /// function can be used after a transfer to extract the received time (if /// any). /// /// By default this option is `false` and corresponds to `CURLOPT_FILETIME` pub fn fetch_filetime(&mut self, fetch: bool) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_FILETIME, fetch as c_long) } /// Indicate whether to download the request without getting the body /// /// This is useful, for example, for doing a HEAD request. /// /// By default this option is `false` and corresponds to `CURLOPT_NOBODY`. pub fn nobody(&mut self, enable: bool) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_NOBODY, enable as c_long) } /// Set the size of the input file to send off. /// /// By default this option is not set and corresponds to /// `CURLOPT_INFILESIZE_LARGE`. pub fn in_filesize(&mut self, size: u64) -> Result<(), Error> { self.setopt_off_t(curl_sys::CURLOPT_INFILESIZE_LARGE, size as curl_sys::curl_off_t) } /// Enable or disable data upload. /// /// This means that a PUT request will be made for HTTP and probably wants /// to be combined with the read callback as well as the `in_filesize` /// method. /// /// By default this option is `false` and corresponds to `CURLOPT_UPLOAD`. pub fn upload(&mut self, enable: bool) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_UPLOAD, enable as c_long) } /// Configure the maximum file size to download. /// /// By default this option is not set and corresponds to /// `CURLOPT_MAXFILESIZE_LARGE`. pub fn max_filesize(&mut self, size: u64) -> Result<(), Error> { self.setopt_off_t(curl_sys::CURLOPT_MAXFILESIZE_LARGE, size as curl_sys::curl_off_t) } /// Selects a condition for a time request. /// /// This value indicates how the `time_value` option is interpreted. /// /// By default this option is not set and corresponds to /// `CURLOPT_TIMECONDITION`. pub fn time_condition(&mut self, cond: TimeCondition) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_TIMECONDITION, cond as c_long) } /// Sets the time value for a conditional request. /// /// The value here should be the number of seconds elapsed since January 1, /// 1970. To pass how to interpret this value, use `time_condition`. /// /// By default this option is not set and corresponds to /// `CURLOPT_TIMEVALUE`. pub fn time_value(&mut self, val: i64) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_TIMEVALUE, val as c_long) } // ========================================================================= // Connection Options /// Set maximum time the request is allowed to take. /// /// Normally, name lookups can take a considerable time and limiting /// operations to less than a few minutes risk aborting perfectly normal /// operations. /// /// If libcurl is built to use the standard system name resolver, that /// portion of the transfer will still use full-second resolution for /// timeouts with a minimum timeout allowed of one second. /// /// In unix-like systems, this might cause signals to be used unless /// `nosignal` is set. /// /// Since this puts a hard limit for how long a request is allowed to /// take, it has limited use in dynamic use cases with varying transfer /// times. You are then advised to explore `low_speed_limit`, /// `low_speed_time` or using `progress_function` to implement your own /// timeout logic. /// /// By default this option is not set and corresponds to /// `CURLOPT_TIMEOUT_MS`. pub fn timeout(&mut self, timeout: Duration) -> Result<(), Error> { // TODO: checked arithmetic and casts // TODO: use CURLOPT_TIMEOUT if the timeout is too great let ms = timeout.as_secs() * 1000 + (timeout.subsec_nanos() / 1_000_000) as u64; self.setopt_long(curl_sys::CURLOPT_TIMEOUT_MS, ms as c_long) } /// Set the low speed limit in bytes per second. /// /// This specifies the average transfer speed in bytes per second that the /// transfer should be below during `low_speed_time` for libcurl to consider /// it to be too slow and abort. /// /// By default this option is not set and corresponds to /// `CURLOPT_LOW_SPEED_LIMIT`. pub fn low_speed_limit(&mut self, limit: u32) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_LOW_SPEED_LIMIT, limit as c_long) } /// Set the low speed time period. /// /// Specifies the window of time for which if the transfer rate is below /// `low_speed_limit` the request will be aborted. /// /// By default this option is not set and corresponds to /// `CURLOPT_LOW_SPEED_TIME`. pub fn low_speed_time(&mut self, dur: Duration) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_LOW_SPEED_TIME, dur.as_secs() as c_long) } /// Rate limit data upload speed /// /// If an upload exceeds this speed (counted in bytes per second) on /// cumulative average during the transfer, the transfer will pause to keep /// the average rate less than or equal to the parameter value. /// /// By default this option is not set (unlimited speed) and corresponds to /// `CURLOPT_MAX_SEND_SPEED_LARGE`. pub fn max_send_speed(&mut self, speed: u64) -> Result<(), Error> { self.setopt_off_t(curl_sys::CURLOPT_MAX_SEND_SPEED_LARGE, speed as curl_sys::curl_off_t) } /// Rate limit data download speed /// /// If a download exceeds this speed (counted in bytes per second) on /// cumulative average during the transfer, the transfer will pause to keep /// the average rate less than or equal to the parameter value. /// /// By default this option is not set (unlimited speed) and corresponds to /// `CURLOPT_MAX_RECV_SPEED_LARGE`. pub fn max_recv_speed(&mut self, speed: u64) -> Result<(), Error> { self.setopt_off_t(curl_sys::CURLOPT_MAX_RECV_SPEED_LARGE, speed as curl_sys::curl_off_t) } /// Set the maximum connection cache size. /// /// The set amount will be the maximum number of simultaneously open /// persistent connections that libcurl may cache in the pool associated /// with this handle. The default is 5, and there isn't much point in /// changing this value unless you are perfectly aware of how this works and /// changes libcurl's behaviour. This concerns connections using any of the /// protocols that support persistent connections. /// /// When reaching the maximum limit, curl closes the oldest one in the cache /// to prevent increasing the number of open connections. /// /// By default this option is set to 5 and corresponds to /// `CURLOPT_MAXCONNECTS` pub fn max_connects(&mut self, max: u32) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_MAXCONNECTS, max as c_long) } /// Force a new connection to be used. /// /// Makes the next transfer use a new (fresh) connection by force instead of /// trying to re-use an existing one. This option should be used with /// caution and only if you understand what it does as it may seriously /// impact performance. /// /// By default this option is `false` and corresponds to /// `CURLOPT_FRESH_CONNECT`. pub fn fresh_connect(&mut self, enable: bool) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_FRESH_CONNECT, enable as c_long) } /// Make connection get closed at once after use. /// /// Makes libcurl explicitly close the connection when done with the /// transfer. Normally, libcurl keeps all connections alive when done with /// one transfer in case a succeeding one follows that can re-use them. /// This option should be used with caution and only if you understand what /// it does as it can seriously impact performance. /// /// By default this option is `false` and corresponds to /// `CURLOPT_FORBID_REUSE`. pub fn forbid_reuse(&mut self, enable: bool) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_FORBID_REUSE, enable as c_long) } /// Timeout for the connect phase /// /// This is the maximum time that you allow the connection phase to the /// server to take. This only limits the connection phase, it has no impact /// once it has connected. /// /// By default this value is 300 seconds and corresponds to /// `CURLOPT_CONNECTTIMEOUT_MS`. pub fn connect_timeout(&mut self, timeout: Duration) -> Result<(), Error> { let ms = timeout.as_secs() * 1000 + (timeout.subsec_nanos() / 1_000_000) as u64; self.setopt_long(curl_sys::CURLOPT_CONNECTTIMEOUT_MS, ms as c_long) } /// Specify which IP protocol version to use /// /// Allows an application to select what kind of IP addresses to use when /// resolving host names. This is only interesting when using host names /// that resolve addresses using more than one version of IP. /// /// By default this value is "any" and corresponds to `CURLOPT_IPRESOLVE`. pub fn ip_resolve(&mut self, resolve: IpResolve) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_IPRESOLVE, resolve as c_long) } /// Specify custom host name to IP address resolves. /// /// Allows specifying hostname to IP mappins to use before trying the /// system resolver. /// /// # Examples /// ``` /// use curl::easy::{Easy, List}; /// /// let mut list = List::new(); /// list.append("www.rust-lang.org:443:13.32.234.49").unwrap(); /// /// let mut handle = Easy::new(); /// handle.url("https://www.rust-lang.org/").unwrap(); /// handle.resolve(list).unwrap(); /// handle.perform().unwrap(); /// ``` pub fn resolve(&mut self, list: List) -> Result<(), Error> { let ptr = list::raw(&list); self.inner.resolve_list = Some(list); self.setopt_ptr(curl_sys::CURLOPT_RESOLVE, ptr as *const _) } /// Configure whether to stop when connected to target server /// /// When enabled it tells the library to perform all the required proxy /// authentication and connection setup, but no data transfer, and then /// return. /// /// The option can be used to simply test a connection to a server. /// /// By default this value is `false` and corresponds to /// `CURLOPT_CONNECT_ONLY`. pub fn connect_only(&mut self, enable: bool) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_CONNECT_ONLY, enable as c_long) } // /// Set interface to speak DNS over. // /// // /// Set the name of the network interface that the DNS resolver should bind // /// to. This must be an interface name (not an address). // /// // /// By default this option is not set and corresponds to // /// `CURLOPT_DNS_INTERFACE`. // pub fn dns_interface(&mut self, interface: &str) -> Result<(), Error> { // let interface = try!(CString::new(interface)); // self.setopt_str(curl_sys::CURLOPT_DNS_INTERFACE, &interface) // } // // /// IPv4 address to bind DNS resolves to // /// // /// Set the local IPv4 address that the resolver should bind to. The // /// argument should be of type char * and contain a single numerical IPv4 // /// address as a string. // /// // /// By default this option is not set and corresponds to // /// `CURLOPT_DNS_LOCAL_IP4`. // pub fn dns_local_ip4(&mut self, ip: &str) -> Result<(), Error> { // let ip = try!(CString::new(ip)); // self.setopt_str(curl_sys::CURLOPT_DNS_LOCAL_IP4, &ip) // } // // /// IPv6 address to bind DNS resolves to // /// // /// Set the local IPv6 address that the resolver should bind to. The // /// argument should be of type char * and contain a single numerical IPv6 // /// address as a string. // /// // /// By default this option is not set and corresponds to // /// `CURLOPT_DNS_LOCAL_IP6`. // pub fn dns_local_ip6(&mut self, ip: &str) -> Result<(), Error> { // let ip = try!(CString::new(ip)); // self.setopt_str(curl_sys::CURLOPT_DNS_LOCAL_IP6, &ip) // } // // /// Set preferred DNS servers. // /// // /// Provides a list of DNS servers to be used instead of the system default. // /// The format of the dns servers option is: // /// // /// ```text // /// host[:port],[host[:port]]... // /// ``` // /// // /// By default this option is not set and corresponds to // /// `CURLOPT_DNS_SERVERS`. // pub fn dns_servers(&mut self, servers: &str) -> Result<(), Error> { // let servers = try!(CString::new(servers)); // self.setopt_str(curl_sys::CURLOPT_DNS_SERVERS, &servers) // } // ========================================================================= // SSL/Security Options /// Sets the SSL client certificate. /// /// The string should be the file name of your client certificate. The /// default format is "P12" on Secure Transport and "PEM" on other engines, /// and can be changed with `ssl_cert_type`. /// /// With NSS or Secure Transport, this can also be the nickname of the /// certificate you wish to authenticate with as it is named in the security /// database. If you want to use a file from the current directory, please /// precede it with "./" prefix, in order to avoid confusion with a /// nickname. /// /// When using a client certificate, you most likely also need to provide a /// private key with `ssl_key`. /// /// By default this option is not set and corresponds to `CURLOPT_SSLCERT`. pub fn ssl_cert>(&mut self, cert: P) -> Result<(), Error> { self.setopt_path(curl_sys::CURLOPT_SSLCERT, cert.as_ref()) } /// Specify type of the client SSL certificate. /// /// The string should be the format of your certificate. Supported formats /// are "PEM" and "DER", except with Secure Transport. OpenSSL (versions /// 0.9.3 and later) and Secure Transport (on iOS 5 or later, or OS X 10.7 /// or later) also support "P12" for PKCS#12-encoded files. /// /// By default this option is "PEM" and corresponds to /// `CURLOPT_SSLCERTTYPE`. pub fn ssl_cert_type(&mut self, kind: &str) -> Result<(), Error> { let kind = try!(CString::new(kind)); self.setopt_str(curl_sys::CURLOPT_SSLCERTTYPE, &kind) } /// Specify private keyfile for TLS and SSL client cert. /// /// The string should be the file name of your private key. The default /// format is "PEM" and can be changed with `ssl_key_type`. /// /// (iOS and Mac OS X only) This option is ignored if curl was built against /// Secure Transport. Secure Transport expects the private key to be already /// present in the keychain or PKCS#12 file containing the certificate. /// /// By default this option is not set and corresponds to `CURLOPT_SSLKEY`. pub fn ssl_key>(&mut self, key: P) -> Result<(), Error> { self.setopt_path(curl_sys::CURLOPT_SSLKEY, key.as_ref()) } /// Set type of the private key file. /// /// The string should be the format of your private key. Supported formats /// are "PEM", "DER" and "ENG". /// /// The format "ENG" enables you to load the private key from a crypto /// engine. In this case `ssl_key` is used as an identifier passed to /// the engine. You have to set the crypto engine with `ssl_engine`. /// "DER" format key file currently does not work because of a bug in /// OpenSSL. /// /// By default this option is "PEM" and corresponds to /// `CURLOPT_SSLKEYTYPE`. pub fn ssl_key_type(&mut self, kind: &str) -> Result<(), Error> { let kind = try!(CString::new(kind)); self.setopt_str(curl_sys::CURLOPT_SSLKEYTYPE, &kind) } /// Set passphrase to private key. /// /// This will be used as the password required to use the `ssl_key`. /// You never needed a pass phrase to load a certificate but you need one to /// load your private key. /// /// By default this option is not set and corresponds to /// `CURLOPT_KEYPASSWD`. pub fn key_password(&mut self, password: &str) -> Result<(), Error> { let password = try!(CString::new(password)); self.setopt_str(curl_sys::CURLOPT_KEYPASSWD, &password) } /// Set the SSL engine identifier. /// /// This will be used as the identifier for the crypto engine you want to /// use for your private key. /// /// By default this option is not set and corresponds to /// `CURLOPT_SSLENGINE`. pub fn ssl_engine(&mut self, engine: &str) -> Result<(), Error> { let engine = try!(CString::new(engine)); self.setopt_str(curl_sys::CURLOPT_SSLENGINE, &engine) } /// Make this handle's SSL engine the default. /// /// By default this option is not set and corresponds to /// `CURLOPT_SSLENGINE_DEFAULT`. pub fn ssl_engine_default(&mut self, enable: bool) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_SSLENGINE_DEFAULT, enable as c_long) } // /// Enable TLS false start. // /// // /// This option determines whether libcurl should use false start during the // /// TLS handshake. False start is a mode where a TLS client will start // /// sending application data before verifying the server's Finished message, // /// thus saving a round trip when performing a full handshake. // /// // /// By default this option is not set and corresponds to // /// `CURLOPT_SSL_FALSESTARTE`. // pub fn ssl_false_start(&mut self, enable: bool) -> Result<(), Error> { // self.setopt_long(curl_sys::CURLOPT_SSLENGINE_DEFAULT, enable as c_long) // } /// Set preferred HTTP version. /// /// By default this option is not set and corresponds to /// `CURLOPT_HTTP_VERSION`. pub fn http_version(&mut self, version: HttpVersion) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_HTTP_VERSION, version as c_long) } /// Set preferred TLS/SSL version. /// /// By default this option is not set and corresponds to /// `CURLOPT_SSLVERSION`. pub fn ssl_version(&mut self, version: SslVersion) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_SSLVERSION, version as c_long) } /// Verify the certificate's name against host. /// /// This should be disabled with great caution! It basically disables the /// security features of SSL if it is disabled. /// /// By default this option is set to `true` and corresponds to /// `CURLOPT_SSL_VERIFYHOST`. pub fn ssl_verify_host(&mut self, verify: bool) -> Result<(), Error> { let val = if verify {2} else {0}; self.setopt_long(curl_sys::CURLOPT_SSL_VERIFYHOST, val) } /// Verify the peer's SSL certificate. /// /// This should be disabled with great caution! It basically disables the /// security features of SSL if it is disabled. /// /// By default this option is set to `true` and corresponds to /// `CURLOPT_SSL_VERIFYPEER`. pub fn ssl_verify_peer(&mut self, verify: bool) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_SSL_VERIFYPEER, verify as c_long) } // /// Verify the certificate's status. // /// // /// This option determines whether libcurl verifies the status of the server // /// cert using the "Certificate Status Request" TLS extension (aka. OCSP // /// stapling). // /// // /// By default this option is set to `false` and corresponds to // /// `CURLOPT_SSL_VERIFYSTATUS`. // pub fn ssl_verify_status(&mut self, verify: bool) -> Result<(), Error> { // self.setopt_long(curl_sys::CURLOPT_SSL_VERIFYSTATUS, verify as c_long) // } /// Specify the path to Certificate Authority (CA) bundle /// /// The file referenced should hold one or more certificates to verify the /// peer with. /// /// This option is by default set to the system path where libcurl's cacert /// bundle is assumed to be stored, as established at build time. /// /// If curl is built against the NSS SSL library, the NSS PEM PKCS#11 module /// (libnsspem.so) needs to be available for this option to work properly. /// /// By default this option is the system defaults, and corresponds to /// `CURLOPT_CAINFO`. pub fn cainfo>(&mut self, path: P) -> Result<(), Error> { self.setopt_path(curl_sys::CURLOPT_CAINFO, path.as_ref()) } /// Set the issuer SSL certificate filename /// /// Specifies a file holding a CA certificate in PEM format. If the option /// is set, an additional check against the peer certificate is performed to /// verify the issuer is indeed the one associated with the certificate /// provided by the option. This additional check is useful in multi-level /// PKI where one needs to enforce that the peer certificate is from a /// specific branch of the tree. /// /// This option makes sense only when used in combination with the /// `ssl_verify_peer` option. Otherwise, the result of the check is not /// considered as failure. /// /// By default this option is not set and corresponds to /// `CURLOPT_ISSUERCERT`. pub fn issuer_cert>(&mut self, path: P) -> Result<(), Error> { self.setopt_path(curl_sys::CURLOPT_ISSUERCERT, path.as_ref()) } /// Specify directory holding CA certificates /// /// Names a directory holding multiple CA certificates to verify the peer /// with. If libcurl is built against OpenSSL, the certificate directory /// must be prepared using the openssl c_rehash utility. This makes sense /// only when used in combination with the `ssl_verify_peer` option. /// /// By default this option is not set and corresponds to `CURLOPT_CAPATH`. pub fn capath>(&mut self, path: P) -> Result<(), Error> { self.setopt_path(curl_sys::CURLOPT_CAPATH, path.as_ref()) } /// Specify a Certificate Revocation List file /// /// Names a file with the concatenation of CRL (in PEM format) to use in the /// certificate validation that occurs during the SSL exchange. /// /// When curl is built to use NSS or GnuTLS, there is no way to influence /// the use of CRL passed to help in the verification process. When libcurl /// is built with OpenSSL support, X509_V_FLAG_CRL_CHECK and /// X509_V_FLAG_CRL_CHECK_ALL are both set, requiring CRL check against all /// the elements of the certificate chain if a CRL file is passed. /// /// This option makes sense only when used in combination with the /// `ssl_verify_peer` option. /// /// A specific error code (`is_ssl_crl_badfile`) is defined with the /// option. It is returned when the SSL exchange fails because the CRL file /// cannot be loaded. A failure in certificate verification due to a /// revocation information found in the CRL does not trigger this specific /// error. /// /// By default this option is not set and corresponds to `CURLOPT_CRLFILE`. pub fn crlfile>(&mut self, path: P) -> Result<(), Error> { self.setopt_path(curl_sys::CURLOPT_CRLFILE, path.as_ref()) } /// Request SSL certificate information /// /// Enable libcurl's certificate chain info gatherer. With this enabled, /// libcurl will extract lots of information and data about the certificates /// in the certificate chain used in the SSL connection. /// /// By default this option is `false` and corresponds to /// `CURLOPT_CERTINFO`. pub fn certinfo(&mut self, enable: bool) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_CERTINFO, enable as c_long) } // /// Set pinned public key. // /// // /// Pass a pointer to a zero terminated string as parameter. The string can // /// be the file name of your pinned public key. The file format expected is // /// "PEM" or "DER". The string can also be any number of base64 encoded // /// sha256 hashes preceded by "sha256//" and separated by ";" // /// // /// When negotiating a TLS or SSL connection, the server sends a certificate // /// indicating its identity. A public key is extracted from this certificate // /// and if it does not exactly match the public key provided to this option, // /// curl will abort the connection before sending or receiving any data. // /// // /// By default this option is not set and corresponds to // /// `CURLOPT_PINNEDPUBLICKEY`. // pub fn pinned_public_key(&mut self, enable: bool) -> Result<(), Error> { // self.setopt_long(curl_sys::CURLOPT_CERTINFO, enable as c_long) // } /// Specify a source for random data /// /// The file will be used to read from to seed the random engine for SSL and /// more. /// /// By default this option is not set and corresponds to /// `CURLOPT_RANDOM_FILE`. pub fn random_file>(&mut self, p: P) -> Result<(), Error> { self.setopt_path(curl_sys::CURLOPT_RANDOM_FILE, p.as_ref()) } /// Specify EGD socket path. /// /// Indicates the path name to the Entropy Gathering Daemon socket. It will /// be used to seed the random engine for SSL. /// /// By default this option is not set and corresponds to /// `CURLOPT_EGDSOCKET`. pub fn egd_socket>(&mut self, p: P) -> Result<(), Error> { self.setopt_path(curl_sys::CURLOPT_EGDSOCKET, p.as_ref()) } /// Specify ciphers to use for TLS. /// /// Holds the list of ciphers to use for the SSL connection. The list must /// be syntactically correct, it consists of one or more cipher strings /// separated by colons. Commas or spaces are also acceptable separators /// but colons are normally used, !, - and + can be used as operators. /// /// For OpenSSL and GnuTLS valid examples of cipher lists include 'RC4-SHA', /// ´SHA1+DES´, 'TLSv1' and 'DEFAULT'. The default list is normally set when /// you compile OpenSSL. /// /// You'll find more details about cipher lists on this URL: /// /// https://www.openssl.org/docs/apps/ciphers.html /// /// For NSS, valid examples of cipher lists include 'rsa_rc4_128_md5', /// ´rsa_aes_128_sha´, etc. With NSS you don't add/remove ciphers. If one /// uses this option then all known ciphers are disabled and only those /// passed in are enabled. /// /// You'll find more details about the NSS cipher lists on this URL: /// /// http://git.fedorahosted.org/cgit/mod_nss.git/plain/docs/mod_nss.html#Directives /// /// By default this option is not set and corresponds to /// `CURLOPT_SSL_CIPHER_LIST`. pub fn ssl_cipher_list(&mut self, ciphers: &str) -> Result<(), Error> { let ciphers = try!(CString::new(ciphers)); self.setopt_str(curl_sys::CURLOPT_SSL_CIPHER_LIST, &ciphers) } /// Enable or disable use of the SSL session-ID cache /// /// By default all transfers are done using the cache enabled. While nothing /// ever should get hurt by attempting to reuse SSL session-IDs, there seem /// to be or have been broken SSL implementations in the wild that may /// require you to disable this in order for you to succeed. /// /// This corresponds to the `CURLOPT_SSL_SESSIONID_CACHE` option. pub fn ssl_sessionid_cache(&mut self, enable: bool) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_SSL_SESSIONID_CACHE, enable as c_long) } /// Set SSL behavior options /// /// Inform libcurl about SSL specific behaviors. /// /// This corresponds to the `CURLOPT_SSL_OPTIONS` option. pub fn ssl_options(&mut self, bits: &SslOpt) -> Result<(), Error> { self.setopt_long(curl_sys::CURLOPT_SSL_OPTIONS, bits.bits) } // /// Set SSL behavior options for proxies // /// // /// Inform libcurl about SSL specific behaviors. // /// // /// This corresponds to the `CURLOPT_PROXY_SSL_OPTIONS` option. // pub fn proxy_ssl_options(&mut self, bits: &SslOpt) -> Result<(), Error> { // self.setopt_long(curl_sys::CURLOPT_PROXY_SSL_OPTIONS, bits.bits) // } // /// Stores a private pointer-sized piece of data. // /// // /// This can be retrieved through the `private` function and otherwise // /// libcurl does not tamper with this value. This corresponds to // /// `CURLOPT_PRIVATE` and defaults to 0. // pub fn set_private(&mut self, private: usize) -> Result<(), Error> { // self.setopt_ptr(curl_sys::CURLOPT_PRIVATE, private as *const _) // } // // /// Fetches this handle's private pointer-sized piece of data. // /// // /// This corresponds to `CURLINFO_PRIVATE` and defaults to 0. // pub fn private(&mut self) -> Result { // self.getopt_ptr(curl_sys::CURLINFO_PRIVATE).map(|p| p as usize) // } // ========================================================================= // getters /// Get the last used URL /// /// In cases when you've asked libcurl to follow redirects, it may /// not be the same value you set with `url`. /// /// This methods corresponds to the `CURLINFO_EFFECTIVE_URL` option. /// /// Returns `Ok(None)` if no effective url is listed or `Err` if an error /// happens or the underlying bytes aren't valid utf-8. pub fn effective_url(&mut self) -> Result, Error> { self.getopt_str(curl_sys::CURLINFO_EFFECTIVE_URL) } /// Get the last used URL, in bytes /// /// In cases when you've asked libcurl to follow redirects, it may /// not be the same value you set with `url`. /// /// This methods corresponds to the `CURLINFO_EFFECTIVE_URL` option. /// /// Returns `Ok(None)` if no effective url is listed or `Err` if an error /// happens or the underlying bytes aren't valid utf-8. pub fn effective_url_bytes(&mut self) -> Result, Error> { self.getopt_bytes(curl_sys::CURLINFO_EFFECTIVE_URL) } /// Get the last response code /// /// The stored value will be zero if no server response code has been /// received. Note that a proxy's CONNECT response should be read with /// `http_connectcode` and not this. /// /// Corresponds to `CURLINFO_RESPONSE_CODE` and returns an error if this /// option is not supported. pub fn response_code(&mut self) -> Result { self.getopt_long(curl_sys::CURLINFO_RESPONSE_CODE).map(|c| c as u32) } /// Get the CONNECT response code /// /// Returns the last received HTTP proxy response code to a CONNECT request. /// The returned value will be zero if no such response code was available. /// /// Corresponds to `CURLINFO_HTTP_CONNECTCODE` and returns an error if this /// option is not supported. pub fn http_connectcode(&mut self) -> Result { self.getopt_long(curl_sys::CURLINFO_HTTP_CONNECTCODE).map(|c| c as u32) } /// Get the remote time of the retrieved document /// /// Returns the remote time of the retrieved document (in number of seconds /// since 1 Jan 1970 in the GMT/UTC time zone). If you get `None`, it can be /// because of many reasons (it might be unknown, the server might hide it /// or the server doesn't support the command that tells document time etc) /// and the time of the document is unknown. /// /// Note that you must tell the server to collect this information before /// the transfer is made, by using the `filetime` method to /// or you will unconditionally get a `None` back. /// /// This corresponds to `CURLINFO_FILETIME` and may return an error if the /// option is not supported pub fn filetime(&mut self) -> Result, Error> { self.getopt_long(curl_sys::CURLINFO_FILETIME).map(|r| { if r == -1 { None } else { Some(r as i64) } }) } /// Get total time of previous transfer /// /// Returns the total time for the previous transfer, /// including name resolving, TCP connect etc. /// /// Corresponds to `CURLINFO_TOTAL_TIME` and may return an error if the /// option isn't supported. pub fn total_time(&mut self) -> Result { self.getopt_double(curl_sys::CURLINFO_TOTAL_TIME) .map(double_seconds_to_duration) } /// Get the name lookup time /// /// Returns the total time from the start /// until the name resolving was completed. /// /// Corresponds to `CURLINFO_NAMELOOKUP_TIME` and may return an error if the /// option isn't supported. pub fn namelookup_time(&mut self) -> Result { self.getopt_double(curl_sys::CURLINFO_NAMELOOKUP_TIME) .map(double_seconds_to_duration) } /// Get the time until connect /// /// Returns the total time from the start /// until the connection to the remote host (or proxy) was completed. /// /// Corresponds to `CURLINFO_CONNECT_TIME` and may return an error if the /// option isn't supported. pub fn connect_time(&mut self) -> Result { self.getopt_double(curl_sys::CURLINFO_CONNECT_TIME) .map(double_seconds_to_duration) } /// Get the time until the SSL/SSH handshake is completed /// /// Returns the total time it took from the start until the SSL/SSH /// connect/handshake to the remote host was completed. This time is most often /// very near to the `pretransfer_time` time, except for cases such as /// HTTP pipelining where the pretransfer time can be delayed due to waits in /// line for the pipeline and more. /// /// Corresponds to `CURLINFO_APPCONNECT_TIME` and may return an error if the /// option isn't supported. pub fn appconnect_time(&mut self) -> Result { self.getopt_double(curl_sys::CURLINFO_APPCONNECT_TIME) .map(double_seconds_to_duration) } /// Get the time until the file transfer start /// /// Returns the total time it took from the start until the file /// transfer is just about to begin. This includes all pre-transfer commands /// and negotiations that are specific to the particular protocol(s) involved. /// It does not involve the sending of the protocol- specific request that /// triggers a transfer. /// /// Corresponds to `CURLINFO_PRETRANSFER_TIME` and may return an error if the /// option isn't supported. pub fn pretransfer_time(&mut self) -> Result { self.getopt_double(curl_sys::CURLINFO_PRETRANSFER_TIME) .map(double_seconds_to_duration) } /// Get the time until the first byte is received /// /// Returns the total time it took from the start until the first /// byte is received by libcurl. This includes `pretransfer_time` and /// also the time the server needs to calculate the result. /// /// Corresponds to `CURLINFO_STARTTRANSFER_TIME` and may return an error if the /// option isn't supported. pub fn starttransfer_time(&mut self) -> Result { self.getopt_double(curl_sys::CURLINFO_STARTTRANSFER_TIME) .map(double_seconds_to_duration) } /// Get the time for all redirection steps /// /// Returns the total time it took for all redirection steps /// include name lookup, connect, pretransfer and transfer before final /// transaction was started. `redirect_time` contains the complete /// execution time for multiple redirections. /// /// Corresponds to `CURLINFO_REDIRECT_TIME` and may return an error if the /// option isn't supported. pub fn redirect_time(&mut self) -> Result { self.getopt_double(curl_sys::CURLINFO_REDIRECT_TIME) .map(double_seconds_to_duration) } /// Get the number of redirects /// /// Corresponds to `CURLINFO_REDIRECT_COUNT` and may return an error if the /// option isn't supported. pub fn redirect_count(&mut self) -> Result { self.getopt_long(curl_sys::CURLINFO_REDIRECT_COUNT).map(|c| c as u32) } /// Get the URL a redirect would go to /// /// Returns the URL a redirect would take you to if you would enable /// `follow_location`. This can come very handy if you think using the /// built-in libcurl redirect logic isn't good enough for you but you would /// still prefer to avoid implementing all the magic of figuring out the new /// URL. /// /// Corresponds to `CURLINFO_REDIRECT_URL` and may return an error if the /// url isn't valid utf-8 or an error happens. pub fn redirect_url(&mut self) -> Result, Error> { self.getopt_str(curl_sys::CURLINFO_REDIRECT_URL) } /// Get the URL a redirect would go to, in bytes /// /// Returns the URL a redirect would take you to if you would enable /// `follow_location`. This can come very handy if you think using the /// built-in libcurl redirect logic isn't good enough for you but you would /// still prefer to avoid implementing all the magic of figuring out the new /// URL. /// /// Corresponds to `CURLINFO_REDIRECT_URL` and may return an error. pub fn redirect_url_bytes(&mut self) -> Result, Error> { self.getopt_bytes(curl_sys::CURLINFO_REDIRECT_URL) } /// Get size of retrieved headers /// /// Corresponds to `CURLINFO_HEADER_SIZE` and may return an error if the /// option isn't supported. pub fn header_size(&mut self) -> Result { self.getopt_long(curl_sys::CURLINFO_HEADER_SIZE).map(|c| c as u64) } /// Get size of sent request. /// /// Corresponds to `CURLINFO_REQUEST_SIZE` and may return an error if the /// option isn't supported. pub fn request_size(&mut self) -> Result { self.getopt_long(curl_sys::CURLINFO_REQUEST_SIZE).map(|c| c as u64) } /// Get Content-Type /// /// Returns the content-type of the downloaded object. This is the value /// read from the Content-Type: field. If you get `None`, it means that the /// server didn't send a valid Content-Type header or that the protocol /// used doesn't support this. /// /// Corresponds to `CURLINFO_CONTENT_TYPE` and may return an error if the /// option isn't supported. pub fn content_type(&mut self) -> Result, Error> { self.getopt_str(curl_sys::CURLINFO_CONTENT_TYPE) } /// Get Content-Type, in bytes /// /// Returns the content-type of the downloaded object. This is the value /// read from the Content-Type: field. If you get `None`, it means that the /// server didn't send a valid Content-Type header or that the protocol /// used doesn't support this. /// /// Corresponds to `CURLINFO_CONTENT_TYPE` and may return an error if the /// option isn't supported. pub fn content_type_bytes(&mut self) -> Result, Error> { self.getopt_bytes(curl_sys::CURLINFO_CONTENT_TYPE) } /// Get errno number from last connect failure. /// /// Note that the value is only set on failure, it is not reset upon a /// successful operation. The number is OS and system specific. /// /// Corresponds to `CURLINFO_OS_ERRNO` and may return an error if the /// option isn't supported. pub fn os_errno(&mut self) -> Result { self.getopt_long(curl_sys::CURLINFO_OS_ERRNO).map(|c| c as i32) } /// Get IP address of last connection. /// /// Returns a string holding the IP address of the most recent connection /// done with this curl handle. This string may be IPv6 when that is /// enabled. /// /// Corresponds to `CURLINFO_PRIMARY_IP` and may return an error if the /// option isn't supported. pub fn primary_ip(&mut self) -> Result, Error> { self.getopt_str(curl_sys::CURLINFO_PRIMARY_IP) } /// Get the latest destination port number /// /// Corresponds to `CURLINFO_PRIMARY_PORT` and may return an error if the /// option isn't supported. pub fn primary_port(&mut self) -> Result { self.getopt_long(curl_sys::CURLINFO_PRIMARY_PORT).map(|c| c as u16) } /// Get local IP address of last connection /// /// Returns a string holding the IP address of the local end of most recent /// connection done with this curl handle. This string may be IPv6 when that /// is enabled. /// /// Corresponds to `CURLINFO_LOCAL_IP` and may return an error if the /// option isn't supported. pub fn local_ip(&mut self) -> Result, Error> { self.getopt_str(curl_sys::CURLINFO_LOCAL_IP) } /// Get the latest local port number /// /// Corresponds to `CURLINFO_LOCAL_PORT` and may return an error if the /// option isn't supported. pub fn local_port(&mut self) -> Result { self.getopt_long(curl_sys::CURLINFO_LOCAL_PORT).map(|c| c as u16) } /// Get all known cookies /// /// Returns a linked-list of all cookies cURL knows (expired ones, too). /// /// Corresponds to the `CURLINFO_COOKIELIST` option and may return an error /// if the option isn't supported. pub fn cookies(&mut self) -> Result { unsafe { let mut list = 0 as *mut _; let rc = curl_sys::curl_easy_getinfo(self.inner.handle, curl_sys::CURLINFO_COOKIELIST, &mut list); try!(self.cvt(rc)); Ok(list::from_raw(list)) } } // ========================================================================= // Other methods /// After options have been set, this will perform the transfer described by /// the options. /// /// This performs the request in a synchronous fashion. This can be used /// multiple times for one easy handle and libcurl will attempt to re-use /// the same connection for all transfers. /// /// This method will preserve all options configured in this handle for the /// next request, and if that is not desired then the options can be /// manually reset or the `reset` method can be called. /// /// Note that this method takes `&self`, which is quite important! This /// allows applications to close over the handle in various callbacks to /// call methods like `unpause_write` and `unpause_read` while a transfer is /// in progress. pub fn perform(&self) -> Result<(), Error> { let ret = unsafe { self.cvt(curl_sys::curl_easy_perform(self.inner.handle)) }; panic::propagate(); return ret } /// Unpause reading on a connection. /// /// Using this function, you can explicitly unpause a connection that was /// previously paused. /// /// A connection can be paused by letting the read or the write callbacks /// return `ReadError::Pause` or `WriteError::Pause`. /// /// To unpause, you may for example call this from the progress callback /// which gets called at least once per second, even if the connection is /// paused. /// /// The chance is high that you will get your write callback called before /// this function returns. pub fn unpause_read(&self) -> Result<(), Error> { unsafe { let rc = curl_sys::curl_easy_pause(self.inner.handle, curl_sys::CURLPAUSE_RECV_CONT); self.cvt(rc) } } /// Unpause writing on a connection. /// /// Using this function, you can explicitly unpause a connection that was /// previously paused. /// /// A connection can be paused by letting the read or the write callbacks /// return `ReadError::Pause` or `WriteError::Pause`. A write callback that /// returns pause signals to the library that it couldn't take care of any /// data at all, and that data will then be delivered again to the callback /// when the writing is later unpaused. /// /// To unpause, you may for example call this from the progress callback /// which gets called at least once per second, even if the connection is /// paused. pub fn unpause_write(&self) -> Result<(), Error> { unsafe { let rc = curl_sys::curl_easy_pause(self.inner.handle, curl_sys::CURLPAUSE_SEND_CONT); self.cvt(rc) } } /// URL encodes a string `s` pub fn url_encode(&mut self, s: &[u8]) -> String { if s.len() == 0 { return String::new() } unsafe { let p = curl_sys::curl_easy_escape(self.inner.handle, s.as_ptr() as *const _, s.len() as c_int); assert!(!p.is_null()); let ret = str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap(); let ret = String::from(ret); curl_sys::curl_free(p as *mut _); return ret } } /// URL decodes a string `s`, returning `None` if it fails pub fn url_decode(&mut self, s: &str) -> Vec { if s.len() == 0 { return Vec::new(); } // Work around https://curl.haxx.se/docs/adv_20130622.html, a bug where // if the last few characters are a bad escape then curl will have a // buffer overrun. let mut iter = s.chars().rev(); let orig_len = s.len(); let mut data; let mut s = s; if iter.next() == Some('%') || iter.next() == Some('%') || iter.next() == Some('%') { data = s.to_string(); data.push(0u8 as char); s = &data[..]; } unsafe { let mut len = 0; let p = curl_sys::curl_easy_unescape(self.inner.handle, s.as_ptr() as *const _, orig_len as c_int, &mut len); assert!(!p.is_null()); let slice = slice::from_raw_parts(p as *const u8, len as usize); let ret = slice.to_vec(); curl_sys::curl_free(p as *mut _); return ret } } // TODO: I don't think this is safe, you can drop this which has all the // callback data and then the next is use-after-free // // /// Attempts to clone this handle, returning a new session handle with the // /// same options set for this handle. // /// // /// Internal state info and things like persistent connections ccannot be // /// transferred. // /// // /// # Errors // /// // /// If a new handle could not be allocated or another error happens, `None` // /// is returned. // pub fn try_clone<'b>(&mut self) -> Option> { // unsafe { // let handle = curl_sys::curl_easy_duphandle(self.handle); // if handle.is_null() { // None // } else { // Some(Easy { // handle: handle, // data: blank_data(), // _marker: marker::PhantomData, // }) // } // } // } /// Receives data from a connected socket. /// /// Only useful after a successful `perform` with the `connect_only` option /// set as well. pub fn recv(&mut self, data: &mut [u8]) -> Result { unsafe { let mut n = 0; let r = curl_sys::curl_easy_recv(self.inner.handle, data.as_mut_ptr() as *mut _, data.len(), &mut n); if r == curl_sys::CURLE_OK { Ok(n) } else { Err(Error::new(r)) } } } /// Sends data over the connected socket. /// /// Only useful after a successful `perform` with the `connect_only` option /// set as well. pub fn send(&mut self, data: &[u8]) -> Result { unsafe { let mut n = 0; let rc = curl_sys::curl_easy_send(self.inner.handle, data.as_ptr() as *const _, data.len(), &mut n); try!(self.cvt(rc)); Ok(n) } } /// Get a pointer to the raw underlying CURL handle. pub fn raw(&self) -> *mut curl_sys::CURL { self.inner.handle } #[cfg(unix)] fn setopt_path(&mut self, opt: curl_sys::CURLoption, val: &Path) -> Result<(), Error> { use std::os::unix::prelude::*; let s = try!(CString::new(val.as_os_str().as_bytes())); self.setopt_str(opt, &s) } #[cfg(windows)] fn setopt_path(&mut self, opt: curl_sys::CURLoption, val: &Path) -> Result<(), Error> { match val.to_str() { Some(s) => self.setopt_str(opt, &try!(CString::new(s))), None => Err(Error::new(curl_sys::CURLE_CONV_FAILED)), } } fn setopt_long(&mut self, opt: curl_sys::CURLoption, val: c_long) -> Result<(), Error> { unsafe { self.cvt(curl_sys::curl_easy_setopt(self.inner.handle, opt, val)) } } fn setopt_str(&mut self, opt: curl_sys::CURLoption, val: &CStr) -> Result<(), Error> { self.setopt_ptr(opt, val.as_ptr()) } fn setopt_ptr(&self, opt: curl_sys::CURLoption, val: *const c_char) -> Result<(), Error> { unsafe { self.cvt(curl_sys::curl_easy_setopt(self.inner.handle, opt, val)) } } fn setopt_off_t(&mut self, opt: curl_sys::CURLoption, val: curl_sys::curl_off_t) -> Result<(), Error> { unsafe { let rc = curl_sys::curl_easy_setopt(self.inner.handle, opt, val); self.cvt(rc) } } fn getopt_bytes(&mut self, opt: curl_sys::CURLINFO) -> Result, Error> { unsafe { let p = try!(self.getopt_ptr(opt)); if p.is_null() { Ok(None) } else { Ok(Some(CStr::from_ptr(p).to_bytes())) } } } fn getopt_ptr(&mut self, opt: curl_sys::CURLINFO) -> Result<*const c_char, Error> { unsafe { let mut p = 0 as *const c_char; let rc = curl_sys::curl_easy_getinfo(self.inner.handle, opt, &mut p); try!(self.cvt(rc)); Ok(p) } } fn getopt_str(&mut self, opt: curl_sys::CURLINFO) -> Result, Error> { match self.getopt_bytes(opt) { Ok(None) => Ok(None), Err(e) => Err(e), Ok(Some(bytes)) => { match str::from_utf8(bytes) { Ok(s) => Ok(Some(s)), Err(_) => Err(Error::new(curl_sys::CURLE_CONV_FAILED)), } } } } fn getopt_long(&mut self, opt: curl_sys::CURLINFO) -> Result { unsafe { let mut p = 0; let rc = curl_sys::curl_easy_getinfo(self.inner.handle, opt, &mut p); try!(self.cvt(rc)); Ok(p) } } fn getopt_double(&mut self, opt: curl_sys::CURLINFO) -> Result { unsafe { let mut p = 0 as c_double; let rc = curl_sys::curl_easy_getinfo(self.inner.handle, opt, &mut p); try!(self.cvt(rc)); Ok(p) } } fn cvt(&self, rc: curl_sys::CURLcode) -> Result<(), Error> { if rc == curl_sys::CURLE_OK { return Ok(()) } let mut buf = self.inner.error_buf.borrow_mut(); if buf[0] == 0 { return Err(Error::new(rc)) } let pos = buf.iter().position(|i| *i == 0).unwrap_or(buf.len()); let msg = String::from_utf8_lossy(&buf[..pos]).into_owned(); buf[0] = 0; Err(::error::error_with_extra(rc, msg.into_boxed_str())) } } impl fmt::Debug for Easy2 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Easy") .field("handle", &self.inner.handle) .field("handler", &self.inner.handle) .finish() } } impl Drop for Easy2 { fn drop(&mut self) { unsafe { curl_sys::curl_easy_cleanup(self.inner.handle); } } } extern fn header_cb(buffer: *mut c_char, size: size_t, nitems: size_t, userptr: *mut c_void) -> size_t { let keep_going = panic::catch(|| unsafe { let data = slice::from_raw_parts(buffer as *const u8, size * nitems); (*(userptr as *mut Inner)).handler.header(data) }).unwrap_or(false); if keep_going { size * nitems } else { !0 } } extern fn write_cb(ptr: *mut c_char, size: size_t, nmemb: size_t, data: *mut c_void) -> size_t { panic::catch(|| unsafe { let input = slice::from_raw_parts(ptr as *const u8, size * nmemb); match (*(data as *mut Inner)).handler.write(input) { Ok(s) => s, Err(WriteError::Pause) | Err(WriteError::__Nonexhaustive) => curl_sys::CURL_WRITEFUNC_PAUSE, } }).unwrap_or(!0) } extern fn read_cb(ptr: *mut c_char, size: size_t, nmemb: size_t, data: *mut c_void) -> size_t { panic::catch(|| unsafe { let input = slice::from_raw_parts_mut(ptr as *mut u8, size * nmemb); match (*(data as *mut Inner)).handler.read(input) { Ok(s) => s, Err(ReadError::Pause) => { curl_sys::CURL_READFUNC_PAUSE } Err(ReadError::__Nonexhaustive) | Err(ReadError::Abort) => { curl_sys::CURL_READFUNC_ABORT } } }).unwrap_or(!0) } extern fn seek_cb(data: *mut c_void, offset: curl_sys::curl_off_t, origin: c_int) -> c_int { panic::catch(|| unsafe { let from = if origin == libc::SEEK_SET { SeekFrom::Start(offset as u64) } else { panic!("unknown origin from libcurl: {}", origin); }; (*(data as *mut Inner)).handler.seek(from) as c_int }).unwrap_or(!0) } extern fn progress_cb(data: *mut c_void, dltotal: c_double, dlnow: c_double, ultotal: c_double, ulnow: c_double) -> c_int { let keep_going = panic::catch(|| unsafe { (*(data as *mut Inner)).handler.progress(dltotal, dlnow, ultotal, ulnow) }).unwrap_or(false); if keep_going { 0 } else { 1 } } // TODO: expose `handle`? is that safe? extern fn debug_cb(_handle: *mut curl_sys::CURL, kind: curl_sys::curl_infotype, data: *mut c_char, size: size_t, userptr: *mut c_void) -> c_int { panic::catch(|| unsafe { let data = slice::from_raw_parts(data as *const u8, size); let kind = match kind { curl_sys::CURLINFO_TEXT => InfoType::Text, curl_sys::CURLINFO_HEADER_IN => InfoType::HeaderIn, curl_sys::CURLINFO_HEADER_OUT => InfoType::HeaderOut, curl_sys::CURLINFO_DATA_IN => InfoType::DataIn, curl_sys::CURLINFO_DATA_OUT => InfoType::DataOut, curl_sys::CURLINFO_SSL_DATA_IN => InfoType::SslDataIn, curl_sys::CURLINFO_SSL_DATA_OUT => InfoType::SslDataOut, _ => return, }; (*(userptr as *mut Inner)).handler.debug(kind, data) }); return 0 } extern fn ssl_ctx_cb(_handle: *mut curl_sys::CURL, ssl_ctx: *mut c_void, data: *mut c_void) -> curl_sys::CURLcode { let res = panic::catch(|| unsafe { match (*(data as *mut Inner)).handler.ssl_ctx(ssl_ctx) { Ok(()) => curl_sys::CURLE_OK, Err(e) => e.code(), } }); // Default to a generic SSL error in case of panic. This // shouldn't really matter since the error should be // propagated later on but better safe than sorry... res.unwrap_or(curl_sys::CURLE_SSL_CONNECT_ERROR) } // TODO: expose `purpose` and `sockaddr` inside of `address` extern fn opensocket_cb(data: *mut c_void, _purpose: curl_sys::curlsocktype, address: *mut curl_sys::curl_sockaddr) -> curl_sys::curl_socket_t { let res = panic::catch(|| unsafe { (*(data as *mut Inner)).handler.open_socket((*address).family, (*address).socktype, (*address).protocol) .unwrap_or(curl_sys::CURL_SOCKET_BAD) }); res.unwrap_or(curl_sys::CURL_SOCKET_BAD) } fn double_seconds_to_duration(seconds: f64) -> Duration { let whole_seconds = seconds.trunc() as u64; let nanos = seconds.fract() * 1_000_000_000f64; Duration::new(whole_seconds, nanos as u32) } #[test] fn double_seconds_to_duration_whole_second() { let dur = double_seconds_to_duration(1.0); assert_eq!(dur.as_secs(), 1); assert_eq!(dur.subsec_nanos(), 0); } #[test] fn double_seconds_to_duration_sub_second1() { let dur = double_seconds_to_duration(0.0); assert_eq!(dur.as_secs(), 0); assert_eq!(dur.subsec_nanos(), 0); } #[test] fn double_seconds_to_duration_sub_second2() { let dur = double_seconds_to_duration(0.5); assert_eq!(dur.as_secs(), 0); assert_eq!(dur.subsec_nanos(), 500_000_000); } impl Auth { /// Creates a new set of authentications with no members. /// /// An `Auth` structure is used to configure which forms of authentication /// are attempted when negotiating connections with servers. pub fn new() -> Auth { Auth { bits: 0 } } /// HTTP Basic authentication. /// /// This is the default choice, and the only method that is in wide-spread /// use and supported virtually everywhere. This sends the user name and /// password over the network in plain text, easily captured by others. pub fn basic(&mut self, on: bool) -> &mut Auth { self.flag(curl_sys::CURLAUTH_BASIC, on) } /// HTTP Digest authentication. /// /// Digest authentication is defined in RFC 2617 and is a more secure way to /// do authentication over public networks than the regular old-fashioned /// Basic method. pub fn digest(&mut self, on: bool) -> &mut Auth { self.flag(curl_sys::CURLAUTH_DIGEST, on) } /// HTTP Digest authentication with an IE flavor. /// /// Digest authentication is defined in RFC 2617 and is a more secure way to /// do authentication over public networks than the regular old-fashioned /// Basic method. The IE flavor is simply that libcurl will use a special /// "quirk" that IE is known to have used before version 7 and that some /// servers require the client to use. pub fn digest_ie(&mut self, on: bool) -> &mut Auth { self.flag(curl_sys::CURLAUTH_DIGEST_IE, on) } /// HTTP Negotiate (SPNEGO) authentication. /// /// Negotiate authentication is defined in RFC 4559 and is the most secure /// way to perform authentication over HTTP. /// /// You need to build libcurl with a suitable GSS-API library or SSPI on /// Windows for this to work. pub fn gssnegotiate(&mut self, on: bool) -> &mut Auth { self.flag(curl_sys::CURLAUTH_GSSNEGOTIATE, on) } /// HTTP NTLM authentication. /// /// A proprietary protocol invented and used by Microsoft. It uses a /// challenge-response and hash concept similar to Digest, to prevent the /// password from being eavesdropped. /// /// You need to build libcurl with either OpenSSL, GnuTLS or NSS support for /// this option to work, or build libcurl on Windows with SSPI support. pub fn ntlm(&mut self, on: bool) -> &mut Auth { self.flag(curl_sys::CURLAUTH_NTLM, on) } /// NTLM delegating to winbind helper. /// /// Authentication is performed by a separate binary application that is /// executed when needed. The name of the application is specified at /// compile time but is typically /usr/bin/ntlm_auth /// /// Note that libcurl will fork when necessary to run the winbind /// application and kill it when complete, calling waitpid() to await its /// exit when done. On POSIX operating systems, killing the process will /// cause a SIGCHLD signal to be raised (regardless of whether /// CURLOPT_NOSIGNAL is set), which must be handled intelligently by the /// application. In particular, the application must not unconditionally /// call wait() in its SIGCHLD signal handler to avoid being subject to a /// race condition. This behavior is subject to change in future versions of /// libcurl. /// /// A proprietary protocol invented and used by Microsoft. It uses a /// challenge-response and hash concept similar to Digest, to prevent the /// password from being eavesdropped. pub fn ntlm_wb(&mut self, on: bool) -> &mut Auth { self.flag(curl_sys::CURLAUTH_NTLM_WB, on) } fn flag(&mut self, bit: c_ulong, on: bool) -> &mut Auth { if on { self.bits |= bit as c_long; } else { self.bits &= !bit as c_long; } self } } impl fmt::Debug for Auth { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let bits = self.bits as c_ulong; f.debug_struct("Auth") .field("basic", &(bits & curl_sys::CURLAUTH_BASIC != 0)) .field("digest", &(bits & curl_sys::CURLAUTH_DIGEST != 0)) .field("digest_ie", &(bits & curl_sys::CURLAUTH_DIGEST_IE != 0)) .field("gssnegotiate", &(bits & curl_sys::CURLAUTH_GSSNEGOTIATE != 0)) .field("ntlm", &(bits & curl_sys::CURLAUTH_NTLM != 0)) .field("ntlm_wb", &(bits & curl_sys::CURLAUTH_NTLM_WB != 0)) .finish() } } impl SslOpt { /// Creates a new set of SSL options. pub fn new() -> SslOpt { SslOpt { bits: 0 } } /// Tells libcurl to disable certificate revocation checks for those SSL /// backends where such behavior is present. /// /// Currently this option is only supported for WinSSL (the native Windows /// SSL library), with an exception in the case of Windows' Untrusted /// Publishers blacklist which it seems can't be bypassed. This option may /// have broader support to accommodate other SSL backends in the future. /// https://curl.haxx.se/docs/ssl-compared.html pub fn no_revoke(&mut self, on: bool) -> &mut SslOpt { self.flag(curl_sys::CURLSSLOPT_NO_REVOKE, on) } /// Tells libcurl to not attempt to use any workarounds for a security flaw /// in the SSL3 and TLS1.0 protocols. /// /// If this option isn't used or this bit is set to 0, the SSL layer libcurl /// uses may use a work-around for this flaw although it might cause /// interoperability problems with some (older) SSL implementations. /// /// > WARNING: avoiding this work-around lessens the security, and by /// > setting this option to 1 you ask for exactly that. This option is only /// > supported for DarwinSSL, NSS and OpenSSL. pub fn allow_beast(&mut self, on: bool) -> &mut SslOpt { self.flag(curl_sys::CURLSSLOPT_ALLOW_BEAST, on) } fn flag(&mut self, bit: c_long, on: bool) -> &mut SslOpt { if on { self.bits |= bit as c_long; } else { self.bits &= !bit as c_long; } self } } impl fmt::Debug for SslOpt { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("SslOpt") .field("no_revoke", &(self.bits & curl_sys::CURLSSLOPT_NO_REVOKE != 0)) .field("allow_beast", &(self.bits & curl_sys::CURLSSLOPT_ALLOW_BEAST != 0)) .finish() } } vendor/curl-0.4.11/src/easy/list.rs0000664000000000000000000000412013264166600015611 0ustar rootrootuse std::ffi::{CStr, CString}; use std::fmt; use curl_sys; use Error; /// A linked list of a strings pub struct List { raw: *mut curl_sys::curl_slist, } /// An iterator over `List` #[derive(Clone)] pub struct Iter<'a> { _me: &'a List, cur: *mut curl_sys::curl_slist, } pub fn raw(list: &List) -> *mut curl_sys::curl_slist { list.raw } pub unsafe fn from_raw(raw: *mut curl_sys::curl_slist) -> List { List { raw: raw } } unsafe impl Send for List {} impl List { /// Creates a new empty list of strings. pub fn new() -> List { List { raw: 0 as *mut _ } } /// Appends some data into this list. pub fn append(&mut self, data: &str) -> Result<(), Error> { let data = try!(CString::new(data)); unsafe { let raw = curl_sys::curl_slist_append(self.raw, data.as_ptr()); assert!(!raw.is_null()); self.raw = raw; Ok(()) } } /// Returns an iterator over the nodes in this list. pub fn iter(&self) -> Iter { Iter { _me: self, cur: self.raw } } } impl fmt::Debug for List { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_list() .entries(self.iter().map(String::from_utf8_lossy)) .finish() } } impl<'a> IntoIterator for &'a List { type IntoIter = Iter<'a>; type Item = &'a [u8]; fn into_iter(self) -> Iter<'a> { self.iter() } } impl Drop for List { fn drop(&mut self) { unsafe { curl_sys::curl_slist_free_all(self.raw) } } } impl<'a> Iterator for Iter<'a> { type Item = &'a [u8]; fn next(&mut self) -> Option<&'a [u8]> { if self.cur.is_null() { return None } unsafe { let ret = Some(CStr::from_ptr((*self.cur).data).to_bytes()); self.cur = (*self.cur).next; return ret } } } impl<'a> fmt::Debug for Iter<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_list() .entries(self.clone().map(String::from_utf8_lossy)) .finish() } } vendor/curl-0.4.11/src/easy/mod.rs0000664000000000000000000000145613264166600015426 0ustar rootroot//! Bindings to the "easy" libcurl API. //! //! This module contains some simple types like `Easy` and `List` which are just //! wrappers around the corresponding libcurl types. There's also a few enums //! scattered about for various options here and there. //! //! Most simple usage of libcurl will likely use the `Easy` structure here, and //! you can find more docs about its usage on that struct. mod list; mod form; mod handle; mod handler; mod windows; pub use self::list::{List, Iter}; pub use self::form::{Form, Part}; pub use self::handle::{Easy, Transfer}; pub use self::handler::{Easy2, Handler}; pub use self::handler::{InfoType, SeekResult, ReadError, WriteError}; pub use self::handler::{TimeCondition, IpResolve, HttpVersion, SslVersion}; pub use self::handler::{SslOpt, NetRc, Auth, ProxyType}; vendor/curl-0.4.11/src/easy/windows.rs0000664000000000000000000001060313264166600016333 0ustar rootroot#![allow(non_camel_case_types, non_snake_case)] use libc::c_void; #[cfg(target_env = "msvc")] mod win { use kernel32; use std::ffi::CString; use std::mem; use std::ptr; use schannel::cert_context::ValidUses; use schannel::cert_store::CertStore; use winapi::{self, c_void, c_uchar, c_long, c_int}; fn lookup(module: &str, symbol: &str) -> Option<*const c_void> { unsafe { let symbol = CString::new(symbol).unwrap(); let mut mod_buf: Vec = module.encode_utf16().collect(); mod_buf.push(0); let handle = kernel32::GetModuleHandleW(mod_buf.as_mut_ptr()); let n = kernel32::GetProcAddress(handle, symbol.as_ptr()); if n == ptr::null() { None } else { Some(n) } } } pub enum X509_STORE {} pub enum X509 {} pub enum SSL_CTX {} type d2i_X509_fn = unsafe extern "C" fn( a: *mut *mut X509, pp: *mut *const c_uchar, length: c_long, ) -> *mut X509; type X509_free_fn = unsafe extern "C" fn(x: *mut X509); type X509_STORE_add_cert_fn = unsafe extern "C" fn(store: *mut X509_STORE, x: *mut X509) -> c_int; type SSL_CTX_get_cert_store_fn = unsafe extern "C" fn(ctx: *const SSL_CTX) -> *mut X509_STORE; struct OpenSSL { d2i_X509: d2i_X509_fn, X509_free: X509_free_fn, X509_STORE_add_cert: X509_STORE_add_cert_fn, SSL_CTX_get_cert_store: SSL_CTX_get_cert_store_fn, } unsafe fn lookup_functions(crypto_module: &str, ssl_module: &str) -> Option { macro_rules! get { ($(let $sym:ident in $module:expr;)*) => ($( let $sym = match lookup($module, stringify!($sym)) { Some(p) => p, None => return None, }; )*) } get! { let d2i_X509 in crypto_module; let X509_free in crypto_module; let X509_STORE_add_cert in crypto_module; let SSL_CTX_get_cert_store in ssl_module; } Some(OpenSSL { d2i_X509: mem::transmute(d2i_X509), X509_free: mem::transmute(X509_free), X509_STORE_add_cert: mem::transmute(X509_STORE_add_cert), SSL_CTX_get_cert_store: mem::transmute(SSL_CTX_get_cert_store), }) } pub unsafe fn add_certs_to_context(ssl_ctx: *mut c_void) { // check the runtime version of OpenSSL let openssl = match ::version::Version::get().ssl_version() { Some(ssl_ver) if ssl_ver.starts_with("OpenSSL/1.1.0") => { lookup_functions("libcrypto", "libssl") } Some(ssl_ver) if ssl_ver.starts_with("OpenSSL/1.0.2") => { lookup_functions("libeay32", "ssleay32") } _ => return, }; let openssl = match openssl { Some(s) => s, None => return, }; let openssl_store = (openssl.SSL_CTX_get_cert_store)(ssl_ctx as *const SSL_CTX); let mut store = match CertStore::open_current_user("ROOT") { Ok(s) => s, Err(_) => return, }; for cert in store.certs() { let valid_uses = match cert.valid_uses() { Ok(v) => v, Err(_) => continue, }; // check the extended key usage for the "Server Authentication" OID match valid_uses { ValidUses::All => {} ValidUses::Oids(ref oids) => { let oid = winapi::wincrypt::szOID_PKIX_KP_SERVER_AUTH.to_owned(); if !oids.contains(&oid) { continue } } } let der = cert.to_der(); let x509 = (openssl.d2i_X509)(ptr::null_mut(), &mut der.as_ptr(), der.len() as c_long); if !x509.is_null() { (openssl.X509_STORE_add_cert)(openssl_store, x509); (openssl.X509_free)(x509); } } } } #[cfg(target_env = "msvc")] pub fn add_certs_to_context(ssl_ctx: *mut c_void) { unsafe { win::add_certs_to_context(ssl_ctx as *mut _); } } #[cfg(not(target_env = "msvc"))] pub fn add_certs_to_context(_: *mut c_void) {} vendor/curl-0.4.11/src/error.rs0000664000000000000000000004557313264166600015047 0ustar rootrootuse std::error; use std::ffi::{self, CStr}; use std::fmt; use std::str; use std::io; use curl_sys; /// An error returned from various "easy" operations. /// /// This structure wraps a `CURLcode`. #[derive(Clone, PartialEq)] pub struct Error { code: curl_sys::CURLcode, extra: Option>, } pub fn error_with_extra(code: curl_sys::CURLcode, extra: Box) -> Error { Error { code: code, extra: Some(extra), } } impl Error { /// Creates a new error from the underlying code returned by libcurl. pub fn new(code: curl_sys::CURLcode) -> Error { Error { code: code, extra: None, } } /// Returns whether this error corresponds to CURLE_UNSUPPORTED_PROTOCOL. pub fn is_unsupported_protocol(&self) -> bool { self.code == curl_sys::CURLE_UNSUPPORTED_PROTOCOL } /// Returns whether this error corresponds to CURLE_FAILED_INIT. pub fn is_failed_init(&self) -> bool { self.code == curl_sys::CURLE_FAILED_INIT } /// Returns whether this error corresponds to CURLE_URL_MALFORMAT. pub fn is_url_malformed(&self) -> bool { self.code == curl_sys::CURLE_URL_MALFORMAT } // /// Returns whether this error corresponds to CURLE_NOT_BUILT_IN. // pub fn is_not_built_in(&self) -> bool { // self.code == curl_sys::CURLE_NOT_BUILT_IN // } /// Returns whether this error corresponds to CURLE_COULDNT_RESOLVE_PROXY. pub fn is_couldnt_resolve_proxy(&self) -> bool { self.code == curl_sys::CURLE_COULDNT_RESOLVE_PROXY } /// Returns whether this error corresponds to CURLE_COULDNT_RESOLVE_HOST. pub fn is_couldnt_resolve_host(&self) -> bool { self.code == curl_sys::CURLE_COULDNT_RESOLVE_HOST } /// Returns whether this error corresponds to CURLE_COULDNT_CONNECT. pub fn is_couldnt_connect(&self) -> bool { self.code == curl_sys::CURLE_COULDNT_CONNECT } /// Returns whether this error corresponds to CURLE_REMOTE_ACCESS_DENIED. pub fn is_remote_access_denied(&self) -> bool { self.code == curl_sys::CURLE_REMOTE_ACCESS_DENIED } /// Returns whether this error corresponds to CURLE_PARTIAL_FILE. pub fn is_partial_file(&self) -> bool { self.code == curl_sys::CURLE_PARTIAL_FILE } /// Returns whether this error corresponds to CURLE_QUOTE_ERROR. pub fn is_quote_error(&self) -> bool { self.code == curl_sys::CURLE_QUOTE_ERROR } /// Returns whether this error corresponds to CURLE_HTTP_RETURNED_ERROR. pub fn is_http_returned_error(&self) -> bool { self.code == curl_sys::CURLE_HTTP_RETURNED_ERROR } /// Returns whether this error corresponds to CURLE_READ_ERROR. pub fn is_read_error(&self) -> bool { self.code == curl_sys::CURLE_READ_ERROR } /// Returns whether this error corresponds to CURLE_WRITE_ERROR. pub fn is_write_error(&self) -> bool { self.code == curl_sys::CURLE_WRITE_ERROR } /// Returns whether this error corresponds to CURLE_UPLOAD_FAILED. pub fn is_upload_failed(&self) -> bool { self.code == curl_sys::CURLE_UPLOAD_FAILED } /// Returns whether this error corresponds to CURLE_OUT_OF_MEMORY. pub fn is_out_of_memory(&self) -> bool { self.code == curl_sys::CURLE_OUT_OF_MEMORY } /// Returns whether this error corresponds to CURLE_OPERATION_TIMEDOUT. pub fn is_operation_timedout(&self) -> bool { self.code == curl_sys::CURLE_OPERATION_TIMEDOUT } /// Returns whether this error corresponds to CURLE_RANGE_ERROR. pub fn is_range_error(&self) -> bool { self.code == curl_sys::CURLE_RANGE_ERROR } /// Returns whether this error corresponds to CURLE_HTTP_POST_ERROR. pub fn is_http_post_error(&self) -> bool { self.code == curl_sys::CURLE_HTTP_POST_ERROR } /// Returns whether this error corresponds to CURLE_SSL_CONNECT_ERROR. pub fn is_ssl_connect_error(&self) -> bool { self.code == curl_sys::CURLE_SSL_CONNECT_ERROR } /// Returns whether this error corresponds to CURLE_BAD_DOWNLOAD_RESUME. pub fn is_bad_download_resume(&self) -> bool { self.code == curl_sys::CURLE_BAD_DOWNLOAD_RESUME } /// Returns whether this error corresponds to CURLE_FILE_COULDNT_READ_FILE. pub fn is_file_couldnt_read_file(&self) -> bool { self.code == curl_sys::CURLE_FILE_COULDNT_READ_FILE } /// Returns whether this error corresponds to CURLE_FUNCTION_NOT_FOUND. pub fn is_function_not_found(&self) -> bool { self.code == curl_sys::CURLE_FUNCTION_NOT_FOUND } /// Returns whether this error corresponds to CURLE_ABORTED_BY_CALLBACK. pub fn is_aborted_by_callback(&self) -> bool { self.code == curl_sys::CURLE_ABORTED_BY_CALLBACK } /// Returns whether this error corresponds to CURLE_BAD_FUNCTION_ARGUMENT. pub fn is_bad_function_argument(&self) -> bool { self.code == curl_sys::CURLE_BAD_FUNCTION_ARGUMENT } /// Returns whether this error corresponds to CURLE_INTERFACE_FAILED. pub fn is_interface_failed(&self) -> bool { self.code == curl_sys::CURLE_INTERFACE_FAILED } /// Returns whether this error corresponds to CURLE_TOO_MANY_REDIRECTS. pub fn is_too_many_redirects(&self) -> bool { self.code == curl_sys::CURLE_TOO_MANY_REDIRECTS } /// Returns whether this error corresponds to CURLE_UNKNOWN_OPTION. pub fn is_unknown_option(&self) -> bool { self.code == curl_sys::CURLE_UNKNOWN_OPTION } /// Returns whether this error corresponds to CURLE_PEER_FAILED_VERIFICATION. pub fn is_peer_failed_verification(&self) -> bool { self.code == curl_sys::CURLE_PEER_FAILED_VERIFICATION } /// Returns whether this error corresponds to CURLE_GOT_NOTHING. pub fn is_got_nothing(&self) -> bool { self.code == curl_sys::CURLE_GOT_NOTHING } /// Returns whether this error corresponds to CURLE_SSL_ENGINE_NOTFOUND. pub fn is_ssl_engine_notfound(&self) -> bool { self.code == curl_sys::CURLE_SSL_ENGINE_NOTFOUND } /// Returns whether this error corresponds to CURLE_SSL_ENGINE_SETFAILED. pub fn is_ssl_engine_setfailed(&self) -> bool { self.code == curl_sys::CURLE_SSL_ENGINE_SETFAILED } /// Returns whether this error corresponds to CURLE_SEND_ERROR. pub fn is_send_error(&self) -> bool { self.code == curl_sys::CURLE_SEND_ERROR } /// Returns whether this error corresponds to CURLE_RECV_ERROR. pub fn is_recv_error(&self) -> bool { self.code == curl_sys::CURLE_RECV_ERROR } /// Returns whether this error corresponds to CURLE_SSL_CERTPROBLEM. pub fn is_ssl_certproblem(&self) -> bool { self.code == curl_sys::CURLE_SSL_CERTPROBLEM } /// Returns whether this error corresponds to CURLE_SSL_CIPHER. pub fn is_ssl_cipher(&self) -> bool { self.code == curl_sys::CURLE_SSL_CIPHER } /// Returns whether this error corresponds to CURLE_SSL_CACERT. pub fn is_ssl_cacert(&self) -> bool { self.code == curl_sys::CURLE_SSL_CACERT } /// Returns whether this error corresponds to CURLE_BAD_CONTENT_ENCODING. pub fn is_bad_content_encoding(&self) -> bool { self.code == curl_sys::CURLE_BAD_CONTENT_ENCODING } /// Returns whether this error corresponds to CURLE_FILESIZE_EXCEEDED. pub fn is_filesize_exceeded(&self) -> bool { self.code == curl_sys::CURLE_FILESIZE_EXCEEDED } /// Returns whether this error corresponds to CURLE_USE_SSL_FAILED. pub fn is_use_ssl_failed(&self) -> bool { self.code == curl_sys::CURLE_USE_SSL_FAILED } /// Returns whether this error corresponds to CURLE_SEND_FAIL_REWIND. pub fn is_send_fail_rewind(&self) -> bool { self.code == curl_sys::CURLE_SEND_FAIL_REWIND } /// Returns whether this error corresponds to CURLE_SSL_ENGINE_INITFAILED. pub fn is_ssl_engine_initfailed(&self) -> bool { self.code == curl_sys::CURLE_SSL_ENGINE_INITFAILED } /// Returns whether this error corresponds to CURLE_LOGIN_DENIED. pub fn is_login_denied(&self) -> bool { self.code == curl_sys::CURLE_LOGIN_DENIED } /// Returns whether this error corresponds to CURLE_CONV_FAILED. pub fn is_conv_failed(&self) -> bool { self.code == curl_sys::CURLE_CONV_FAILED } /// Returns whether this error corresponds to CURLE_CONV_REQD. pub fn is_conv_required(&self) -> bool { self.code == curl_sys::CURLE_CONV_REQD } /// Returns whether this error corresponds to CURLE_SSL_CACERT_BADFILE. pub fn is_ssl_cacert_badfile(&self) -> bool { self.code == curl_sys::CURLE_SSL_CACERT_BADFILE } /// Returns whether this error corresponds to CURLE_SSL_CRL_BADFILE. pub fn is_ssl_crl_badfile(&self) -> bool { self.code == curl_sys::CURLE_SSL_CRL_BADFILE } /// Returns whether this error corresponds to CURLE_SSL_SHUTDOWN_FAILED. pub fn is_ssl_shutdown_failed(&self) -> bool { self.code == curl_sys::CURLE_SSL_SHUTDOWN_FAILED } /// Returns whether this error corresponds to CURLE_AGAIN. pub fn is_again(&self) -> bool { self.code == curl_sys::CURLE_AGAIN } /// Returns whether this error corresponds to CURLE_SSL_ISSUER_ERROR. pub fn is_ssl_issuer_error(&self) -> bool { self.code == curl_sys::CURLE_SSL_ISSUER_ERROR } /// Returns whether this error corresponds to CURLE_CHUNK_FAILED. pub fn is_chunk_failed(&self) -> bool { self.code == curl_sys::CURLE_CHUNK_FAILED } // /// Returns whether this error corresponds to CURLE_NO_CONNECTION_AVAILABLE. // pub fn is_no_connection_available(&self) -> bool { // self.code == curl_sys::CURLE_NO_CONNECTION_AVAILABLE // } /// Returns the value of the underlying error corresponding to libcurl. pub fn code(&self) -> curl_sys::CURLcode { self.code } /// Returns the extra description of this error, if any is available. pub fn extra_description(&self) -> Option<&str> { self.extra.as_ref().map(|s| &**s) } } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let desc = error::Error::description(self); match self.extra { Some(ref s) => write!(f, "[{}] {} ({})", self.code(), desc, s), None => write!(f, "[{}] {}", self.code(), desc), } } } impl fmt::Debug for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Error") .field("description", &error::Error::description(self)) .field("code", &self.code) .field("extra", &self.extra) .finish() } } impl error::Error for Error { fn description(&self) -> &str { unsafe { let s = curl_sys::curl_easy_strerror(self.code); assert!(!s.is_null()); str::from_utf8(CStr::from_ptr(s).to_bytes()).unwrap() } } } /// An error returned from "share" operations. /// /// This structure wraps a `CURLSHcode`. #[derive(Clone, PartialEq)] pub struct ShareError { code: curl_sys::CURLSHcode, } impl ShareError { /// Creates a new error from the underlying code returned by libcurl. pub fn new(code: curl_sys::CURLSHcode) -> ShareError { ShareError { code: code } } /// Returns whether this error corresponds to CURLSHE_BAD_OPTION. pub fn is_bad_option(&self) -> bool { self.code == curl_sys::CURLSHE_BAD_OPTION } /// Returns whether this error corresponds to CURLSHE_IN_USE. pub fn is_in_use(&self) -> bool { self.code == curl_sys::CURLSHE_IN_USE } /// Returns whether this error corresponds to CURLSHE_INVALID. pub fn is_invalid(&self) -> bool { self.code == curl_sys::CURLSHE_INVALID } /// Returns whether this error corresponds to CURLSHE_NOMEM. pub fn is_nomem(&self) -> bool { self.code == curl_sys::CURLSHE_NOMEM } // /// Returns whether this error corresponds to CURLSHE_NOT_BUILT_IN. // pub fn is_not_built_in(&self) -> bool { // self.code == curl_sys::CURLSHE_NOT_BUILT_IN // } /// Returns the value of the underlying error corresponding to libcurl. pub fn code(&self) -> curl_sys::CURLSHcode { self.code } } impl fmt::Display for ShareError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { error::Error::description(self).fmt(f) } } impl fmt::Debug for ShareError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "ShareError {{ description: {:?}, code: {} }}", error::Error::description(self), self.code) } } impl error::Error for ShareError { fn description(&self) -> &str { unsafe { let s = curl_sys::curl_share_strerror(self.code); assert!(!s.is_null()); str::from_utf8(CStr::from_ptr(s).to_bytes()).unwrap() } } } /// An error from "multi" operations. /// /// THis structure wraps a `CURLMcode`. #[derive(Clone, PartialEq)] pub struct MultiError { code: curl_sys::CURLMcode, } impl MultiError { /// Creates a new error from the underlying code returned by libcurl. pub fn new(code: curl_sys::CURLMcode) -> MultiError { MultiError { code: code } } /// Returns whether this error corresponds to CURLM_BAD_HANDLE. pub fn is_bad_handle(&self) -> bool { self.code == curl_sys::CURLM_BAD_HANDLE } /// Returns whether this error corresponds to CURLM_BAD_EASY_HANDLE. pub fn is_bad_easy_handle(&self) -> bool { self.code == curl_sys::CURLM_BAD_EASY_HANDLE } /// Returns whether this error corresponds to CURLM_OUT_OF_MEMORY. pub fn is_out_of_memory(&self) -> bool { self.code == curl_sys::CURLM_OUT_OF_MEMORY } /// Returns whether this error corresponds to CURLM_INTERNAL_ERROR. pub fn is_internal_error(&self) -> bool { self.code == curl_sys::CURLM_INTERNAL_ERROR } /// Returns whether this error corresponds to CURLM_BAD_SOCKET. pub fn is_bad_socket(&self) -> bool { self.code == curl_sys::CURLM_BAD_SOCKET } /// Returns whether this error corresponds to CURLM_UNKNOWN_OPTION. pub fn is_unknown_option(&self) -> bool { self.code == curl_sys::CURLM_UNKNOWN_OPTION } /// Returns whether this error corresponds to CURLM_CALL_MULTI_PERFORM. pub fn is_call_perform(&self) -> bool { self.code == curl_sys::CURLM_CALL_MULTI_PERFORM } // /// Returns whether this error corresponds to CURLM_ADDED_ALREADY. // pub fn is_added_already(&self) -> bool { // self.code == curl_sys::CURLM_ADDED_ALREADY // } /// Returns the value of the underlying error corresponding to libcurl. pub fn code(&self) -> curl_sys::CURLMcode { self.code } } impl fmt::Display for MultiError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { error::Error::description(self).fmt(f) } } impl fmt::Debug for MultiError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "MultiError {{ description: {:?}, code: {} }}", error::Error::description(self), self.code) } } impl error::Error for MultiError { fn description(&self) -> &str { unsafe { let s = curl_sys::curl_multi_strerror(self.code); assert!(!s.is_null()); str::from_utf8(CStr::from_ptr(s).to_bytes()).unwrap() } } } /// An error from "form add" operations. /// /// THis structure wraps a `CURLFORMcode`. #[derive(Clone, PartialEq)] pub struct FormError { code: curl_sys::CURLFORMcode, } impl FormError { /// Creates a new error from the underlying code returned by libcurl. pub fn new(code: curl_sys::CURLFORMcode) -> FormError { FormError { code: code } } /// Returns whether this error corresponds to CURL_FORMADD_MEMORY. pub fn is_memory(&self) -> bool { self.code == curl_sys::CURL_FORMADD_MEMORY } /// Returns whether this error corresponds to CURL_FORMADD_OPTION_TWICE. pub fn is_option_twice(&self) -> bool { self.code == curl_sys::CURL_FORMADD_OPTION_TWICE } /// Returns whether this error corresponds to CURL_FORMADD_NULL. pub fn is_null(&self) -> bool { self.code == curl_sys::CURL_FORMADD_NULL } /// Returns whether this error corresponds to CURL_FORMADD_UNKNOWN_OPTION. pub fn is_unknown_option(&self) -> bool { self.code == curl_sys::CURL_FORMADD_UNKNOWN_OPTION } /// Returns whether this error corresponds to CURL_FORMADD_INCOMPLETE. pub fn is_incomplete(&self) -> bool { self.code == curl_sys::CURL_FORMADD_INCOMPLETE } /// Returns whether this error corresponds to CURL_FORMADD_ILLEGAL_ARRAY. pub fn is_illegal_array(&self) -> bool { self.code == curl_sys::CURL_FORMADD_ILLEGAL_ARRAY } /// Returns whether this error corresponds to CURL_FORMADD_DISABLED. pub fn is_disabled(&self) -> bool { self.code == curl_sys::CURL_FORMADD_DISABLED } /// Returns the value of the underlying error corresponding to libcurl. pub fn code(&self) -> curl_sys::CURLFORMcode { self.code } } impl fmt::Display for FormError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { error::Error::description(self).fmt(f) } } impl fmt::Debug for FormError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "FormError {{ description: {:?}, code: {} }}", error::Error::description(self), self.code) } } impl error::Error for FormError { fn description(&self) -> &str { match self.code { curl_sys::CURL_FORMADD_MEMORY => "allocation failure", curl_sys::CURL_FORMADD_OPTION_TWICE => "one option passed twice", curl_sys::CURL_FORMADD_NULL => "null pointer given for string", curl_sys::CURL_FORMADD_UNKNOWN_OPTION => "unknown option", curl_sys::CURL_FORMADD_INCOMPLETE => "form information not complete", curl_sys::CURL_FORMADD_ILLEGAL_ARRAY => "illegal array in option", curl_sys::CURL_FORMADD_DISABLED => { "libcurl does not have support for this option compiled in" } _ => "unknown form error", } } } impl From for Error { fn from(_: ffi::NulError) -> Error { Error { code: curl_sys::CURLE_CONV_FAILED, extra: None } } } impl From for io::Error { fn from(e: Error) -> io::Error { io::Error::new(io::ErrorKind::Other, e) } } impl From for io::Error { fn from(e: ShareError) -> io::Error { io::Error::new(io::ErrorKind::Other, e) } } impl From for io::Error { fn from(e: MultiError) -> io::Error { io::Error::new(io::ErrorKind::Other, e) } } impl From for io::Error { fn from(e: FormError) -> io::Error { io::Error::new(io::ErrorKind::Other, e) } } vendor/curl-0.4.11/src/lib.rs0000664000000000000000000000767413264166600014464 0ustar rootroot//! Rust bindings to the libcurl C library //! //! This crate contains bindings for an HTTP/HTTPS client which is powered by //! [libcurl], the same library behind the `curl` command line tool. The API //! currently closely matches that of libcurl itself, except that a Rustic layer //! of safety is applied on top. //! //! [libcurl]: https://curl.haxx.se/libcurl/ //! //! # The "Easy" API //! //! The easiest way to send a request is to use the `Easy` api which corresponds //! to `CURL` in libcurl. This handle supports a wide variety of options and can //! be used to make a single blocking request in a thread. Callbacks can be //! specified to deal with data as it arrives and a handle can be reused to //! cache connections and such. //! //! ```rust,no_run //! use std::io::{stdout, Write}; //! //! use curl::easy::Easy; //! //! // Write the contents of rust-lang.org to stdout //! let mut easy = Easy::new(); //! easy.url("https://www.rust-lang.org/").unwrap(); //! easy.write_function(|data| { //! Ok(stdout().write(data).unwrap()) //! }).unwrap(); //! easy.perform().unwrap(); //! ``` //! //! # What about multiple concurrent HTTP requests? //! //! One option you have currently is to send multiple requests in multiple //! threads, but otherwise libcurl has a "multi" interface for doing this //! operation. Initial bindings of this interface can be found in the `multi` //! module, but feedback is welcome! //! //! # Where does libcurl come from? //! //! This crate links to the `curl-sys` crate which is in turn responsible for //! acquiring and linking to the libcurl library. Currently this crate will //! build libcurl from source if one is not already detected on the system. //! //! There is a large number of releases for libcurl, all with different sets of //! capabilities. Robust programs may wish to inspect `Version::get()` to test //! what features are implemented in the linked build of libcurl at runtime. #![deny(missing_docs, missing_debug_implementations)] #![doc(html_root_url = "https://docs.rs/curl/0.4")] extern crate curl_sys; extern crate libc; extern crate socket2; #[cfg(all(unix, not(target_os = "macos")))] extern crate openssl_sys; #[cfg(all(unix, not(target_os = "macos")))] extern crate openssl_probe; #[cfg(windows)] extern crate winapi; #[cfg(target_env = "msvc")] extern crate kernel32; #[cfg(target_env = "msvc")] extern crate schannel; use std::ffi::CStr; use std::str; use std::sync::{Once, ONCE_INIT}; pub use error::{Error, ShareError, MultiError, FormError}; mod error; pub use version::{Version, Protocols}; mod version; mod panic; pub mod easy; pub mod multi; /// Initializes the underlying libcurl library. /// /// It's not required to call this before the library is used, but it's /// recommended to do so as soon as the program starts. pub fn init() { static INIT: Once = ONCE_INIT; INIT.call_once(|| { platform_init(); unsafe { assert_eq!(curl_sys::curl_global_init(curl_sys::CURL_GLOBAL_ALL), 0); } // Note that we explicitly don't schedule a call to // `curl_global_cleanup`. The documentation for that function says // // > You must not call it when any other thread in the program (i.e. a // > thread sharing the same memory) is running. This doesn't just mean // > no other thread that is using libcurl. // // We can't ever be sure of that, so unfortunately we can't call the // function. }); #[cfg(all(unix, not(target_os = "macos")))] fn platform_init() { openssl_sys::init(); } #[cfg(not(all(unix, not(target_os = "macos"))))] fn platform_init() {} } unsafe fn opt_str<'a>(ptr: *const libc::c_char) -> Option<&'a str> { if ptr.is_null() { None } else { Some(str::from_utf8(CStr::from_ptr(ptr).to_bytes()).unwrap()) } } fn cvt(r: curl_sys::CURLcode) -> Result<(), Error> { if r == curl_sys::CURLE_OK { Ok(()) } else { Err(Error::new(r)) } } vendor/curl-0.4.11/src/multi.rs0000664000000000000000000010554213264166600015041 0ustar rootroot//! Multi - initiating multiple requests simultaneously use std::fmt; use std::marker; use std::time::Duration; use libc::{c_int, c_char, c_void, c_long, c_short}; use curl_sys; #[cfg(windows)] use winapi::winsock2::fd_set; #[cfg(unix)] use libc::{fd_set, pollfd, POLLIN, POLLPRI, POLLOUT}; use {MultiError, Error}; use easy::{Easy, Easy2}; use panic; /// A multi handle for initiating multiple connections simultaneously. /// /// This structure corresponds to `CURLM` in libcurl and provides the ability to /// have multiple transfers in flight simultaneously. This handle is then used /// to manage each transfer. The main purpose of a `CURLM` is for the /// *application* to drive the I/O rather than libcurl itself doing all the /// blocking. Methods like `action` allow the application to inform libcurl of /// when events have happened. /// /// Lots more documentation can be found on the libcurl [multi tutorial] where /// the APIs correspond pretty closely with this crate. /// /// [multi tutorial]: https://curl.haxx.se/libcurl/c/libcurl-multi.html pub struct Multi { raw: *mut curl_sys::CURLM, data: Box, } struct MultiData { socket: Box, timer: Box) -> bool + Send>, } /// Message from the `messages` function of a multi handle. /// /// Currently only indicates whether a transfer is done. pub struct Message<'multi> { ptr: *mut curl_sys::CURLMsg, _multi: &'multi Multi, } /// Wrapper around an easy handle while it's owned by a multi handle. /// /// Once an easy handle has been added to a multi handle then it can no longer /// be used via `perform`. This handle is also used to remove the easy handle /// from the multi handle when desired. pub struct EasyHandle { easy: Easy, // This is now effecitvely bound to a `Multi`, so it is no longer sendable. _marker: marker::PhantomData<&'static Multi>, } /// Wrapper around an easy handle while it's owned by a multi handle. /// /// Once an easy handle has been added to a multi handle then it can no longer /// be used via `perform`. This handle is also used to remove the easy handle /// from the multi handle when desired. pub struct Easy2Handle { easy: Easy2, // This is now effecitvely bound to a `Multi`, so it is no longer sendable. _marker: marker::PhantomData<&'static Multi>, } /// Notification of the events that have happened on a socket. /// /// This type is passed as an argument to the `action` method on a multi handle /// to indicate what events have occurred on a socket. pub struct Events { bits: c_int, } /// Notification of events that are requested on a socket. /// /// This type is yielded to the `socket_function` callback to indicate what /// events are requested on a socket. pub struct SocketEvents { bits: c_int, } /// Raw underlying socket type that the multi handles use pub type Socket = curl_sys::curl_socket_t; /// File descriptor to wait on for use with the `wait` method on a multi handle. pub struct WaitFd { inner: curl_sys::curl_waitfd, } impl Multi { /// Creates a new multi session through which multiple HTTP transfers can be /// initiated. pub fn new() -> Multi { unsafe { ::init(); let ptr = curl_sys::curl_multi_init(); assert!(!ptr.is_null()); Multi { raw: ptr, data: Box::new(MultiData { socket: Box::new(|_, _, _| ()), timer: Box::new(|_| true), }), } } } /// Set the callback informed about what to wait for /// /// When the `action` function runs, it informs the application about /// updates in the socket (file descriptor) status by doing none, one, or /// multiple calls to the socket callback. The callback gets status updates /// with changes since the previous time the callback was called. See /// `action` for more details on how the callback is used and should work. /// /// The `SocketEvents` parameter informs the callback on the status of the /// given socket, and the methods on that type can be used to learn about /// what's going on with the socket. /// /// The third `usize` parameter is a custom value set by the `assign` method /// below. pub fn socket_function(&mut self, f: F) -> Result<(), MultiError> where F: FnMut(Socket, SocketEvents, usize) + Send + 'static, { self._socket_function(Box::new(f)) } fn _socket_function(&mut self, f: Box) -> Result<(), MultiError> { self.data.socket = f; let cb: curl_sys::curl_socket_callback = cb; try!(self.setopt_ptr(curl_sys::CURLMOPT_SOCKETFUNCTION, cb as usize as *const c_char)); let ptr = &*self.data as *const _; try!(self.setopt_ptr(curl_sys::CURLMOPT_SOCKETDATA, ptr as *const c_char)); return Ok(()); // TODO: figure out how to expose `_easy` extern fn cb(_easy: *mut curl_sys::CURL, socket: curl_sys::curl_socket_t, what: c_int, userptr: *mut c_void, socketp: *mut c_void) -> c_int { panic::catch(|| unsafe { let f = &mut (*(userptr as *mut MultiData)).socket; f(socket, SocketEvents { bits: what }, socketp as usize) }); 0 } } /// Set data to associate with an internal socket /// /// This function creates an association in the multi handle between the /// given socket and a private token of the application. This is designed /// for `action` uses. /// /// When set, the token will be passed to all future socket callbacks for /// the specified socket. /// /// If the given socket isn't already in use by libcurl, this function will /// return an error. /// /// libcurl only keeps one single token associated with a socket, so /// calling this function several times for the same socket will make the /// last set token get used. /// /// The idea here being that this association (socket to token) is something /// that just about every application that uses this API will need and then /// libcurl can just as well do it since it already has an internal hash /// table lookup for this. /// /// # Typical Usage /// /// In a typical application you allocate a struct or at least use some kind /// of semi-dynamic data for each socket that we must wait for action on /// when using the `action` approach. /// /// When our socket-callback gets called by libcurl and we get to know about /// yet another socket to wait for, we can use `assign` to point out the /// particular data so that when we get updates about this same socket /// again, we don't have to find the struct associated with this socket by /// ourselves. pub fn assign(&self, socket: Socket, token: usize) -> Result<(), MultiError> { unsafe { try!(cvt(curl_sys::curl_multi_assign(self.raw, socket, token as *mut _))); Ok(()) } } /// Set callback to receive timeout values /// /// Certain features, such as timeouts and retries, require you to call /// libcurl even when there is no activity on the file descriptors. /// /// Your callback function should install a non-repeating timer with the /// interval specified. Each time that timer fires, call either `action` or /// `perform`, depending on which interface you use. /// /// A timeout value of `None` means you should delete your timer. /// /// A timeout value of 0 means you should call `action` or `perform` (once) /// as soon as possible. /// /// This callback will only be called when the timeout changes. /// /// The timer callback should return `true` on success, and `false` on /// error. This callback can be used instead of, or in addition to, /// `get_timeout`. pub fn timer_function(&mut self, f: F) -> Result<(), MultiError> where F: FnMut(Option) -> bool + Send + 'static, { self._timer_function(Box::new(f)) } fn _timer_function(&mut self, f: Box) -> bool + Send>) -> Result<(), MultiError> { self.data.timer = f; let cb: curl_sys::curl_multi_timer_callback = cb; try!(self.setopt_ptr(curl_sys::CURLMOPT_TIMERFUNCTION, cb as usize as *const c_char)); let ptr = &*self.data as *const _; try!(self.setopt_ptr(curl_sys::CURLMOPT_TIMERDATA, ptr as *const c_char)); return Ok(()); // TODO: figure out how to expose `_multi` extern fn cb(_multi: *mut curl_sys::CURLM, timeout_ms: c_long, user: *mut c_void) -> c_int { let keep_going = panic::catch(|| unsafe { let f = &mut (*(user as *mut MultiData)).timer; if timeout_ms == -1 { f(None) } else { f(Some(Duration::from_millis(timeout_ms as u64))) } }).unwrap_or(false); if keep_going {0} else {-1} } } fn setopt_ptr(&mut self, opt: curl_sys::CURLMoption, val: *const c_char) -> Result<(), MultiError> { unsafe { cvt(curl_sys::curl_multi_setopt(self.raw, opt, val)) } } /// Add an easy handle to a multi session /// /// Adds a standard easy handle to the multi stack. This function call will /// make this multi handle control the specified easy handle. /// /// When an easy interface is added to a multi handle, it will use a shared /// connection cache owned by the multi handle. Removing and adding new easy /// handles will not affect the pool of connections or the ability to do /// connection re-use. /// /// If you have `timer_function` set in the multi handle (and you really /// should if you're working event-based with `action` and friends), that /// callback will be called from within this function to ask for an updated /// timer so that your main event loop will get the activity on this handle /// to get started. /// /// The easy handle will remain added to the multi handle until you remove /// it again with `remove` on the returned handle - even when a transfer /// with that specific easy handle is completed. pub fn add(&self, mut easy: Easy) -> Result { // Clear any configuration set by previous transfers because we're // moving this into a `Send+'static` situation now basically. easy.transfer(); unsafe { try!(cvt(curl_sys::curl_multi_add_handle(self.raw, easy.raw()))); } Ok(EasyHandle { easy: easy, _marker: marker::PhantomData, }) } /// Same as `add`, but works with the `Easy2` type. pub fn add2(&self, easy: Easy2) -> Result, MultiError> { unsafe { try!(cvt(curl_sys::curl_multi_add_handle(self.raw, easy.raw()))); } Ok(Easy2Handle { easy: easy, _marker: marker::PhantomData, }) } /// Remove an easy handle from this multi session /// /// Removes the easy handle from this multi handle. This will make the /// returned easy handle be removed from this multi handle's control. /// /// When the easy handle has been removed from a multi stack, it is again /// perfectly legal to invoke `perform` on it. /// /// Removing an easy handle while being used is perfectly legal and will /// effectively halt the transfer in progress involving that easy handle. /// All other easy handles and transfers will remain unaffected. pub fn remove(&self, easy: EasyHandle) -> Result { unsafe { try!(cvt(curl_sys::curl_multi_remove_handle(self.raw, easy.easy.raw()))); } Ok(easy.easy) } /// Same as `remove`, but for `Easy2Handle`. pub fn remove2(&self, easy: Easy2Handle) -> Result, MultiError> { unsafe { try!(cvt(curl_sys::curl_multi_remove_handle(self.raw, easy.easy.raw()))); } Ok(easy.easy) } /// Read multi stack informationals /// /// Ask the multi handle if there are any messages/informationals from the /// individual transfers. Messages may include informationals such as an /// error code from the transfer or just the fact that a transfer is /// completed. More details on these should be written down as well. pub fn messages(&self, mut f: F) where F: FnMut(Message) { self._messages(&mut f) } fn _messages(&self, f: &mut FnMut(Message)) { let mut queue = 0; unsafe { loop { let ptr = curl_sys::curl_multi_info_read(self.raw, &mut queue); if ptr.is_null() { break } f(Message { ptr: ptr, _multi: self }) } } } /// Inform of reads/writes available data given an action /// /// When the application has detected action on a socket handled by libcurl, /// it should call this function with the sockfd argument set to /// the socket with the action. When the events on a socket are known, they /// can be passed `events`. When the events on a socket are unknown, pass /// `Events::new()` instead, and libcurl will test the descriptor /// internally. /// /// The returned integer will contain the number of running easy handles /// within the multi handle. When this number reaches zero, all transfers /// are complete/done. When you call `action` on a specific socket and the /// counter decreases by one, it DOES NOT necessarily mean that this exact /// socket/transfer is the one that completed. Use `messages` to figure out /// which easy handle that completed. /// /// The `action` function informs the application about updates in the /// socket (file descriptor) status by doing none, one, or multiple calls to /// the socket callback function set with the `socket_function` method. They /// update the status with changes since the previous time the callback was /// called. pub fn action(&self, socket: Socket, events: &Events) -> Result { let mut remaining = 0; unsafe { try!(cvt(curl_sys::curl_multi_socket_action(self.raw, socket, events.bits, &mut remaining))); Ok(remaining as u32) } } /// Inform libcurl that a timeout has expired and sockets should be tested. /// /// The returned integer will contain the number of running easy handles /// within the multi handle. When this number reaches zero, all transfers /// are complete/done. When you call `action` on a specific socket and the /// counter decreases by one, it DOES NOT necessarily mean that this exact /// socket/transfer is the one that completed. Use `messages` to figure out /// which easy handle that completed. /// /// Get the timeout time by calling the `timer_function` method. Your /// application will then get called with information on how long to wait /// for socket actions at most before doing the timeout action: call the /// `timeout` method. You can also use the `get_timeout` function to /// poll the value at any given time, but for an event-based system using /// the callback is far better than relying on polling the timeout value. pub fn timeout(&self) -> Result { let mut remaining = 0; unsafe { try!(cvt(curl_sys::curl_multi_socket_action(self.raw, curl_sys::CURL_SOCKET_BAD, 0, &mut remaining))); Ok(remaining as u32) } } /// Get how long to wait for action before proceeding /// /// An application using the libcurl multi interface should call /// `get_timeout` to figure out how long it should wait for socket actions - /// at most - before proceeding. /// /// Proceeding means either doing the socket-style timeout action: call the /// `timeout` function, or call `perform` if you're using the simpler and /// older multi interface approach. /// /// The timeout value returned is the duration at this very moment. If 0, it /// means you should proceed immediately without waiting for anything. If it /// returns `None`, there's no timeout at all set. /// /// Note: if libcurl returns a `None` timeout here, it just means that /// libcurl currently has no stored timeout value. You must not wait too /// long (more than a few seconds perhaps) before you call `perform` again. pub fn get_timeout(&self) -> Result, MultiError> { let mut ms = 0; unsafe { try!(cvt(curl_sys::curl_multi_timeout(self.raw, &mut ms))); if ms == -1 { Ok(None) } else { Ok(Some(Duration::from_millis(ms as u64))) } } } /// Block until activity is detected or a timeout passes. /// /// The timeout is used in millisecond-precision. Large durations are /// clamped at the maximum value curl accepts. /// /// The returned integer will contain the number of internal file /// descriptors on which interesting events occured. /// /// This function is a simpler alternative to using `fdset()` and `select()` /// and does not suffer from file descriptor limits. /// /// # Example /// /// ``` /// use curl::multi::Multi; /// use std::time::Duration; /// /// let m = Multi::new(); /// /// // Add some Easy handles... /// /// while m.perform().unwrap() > 0 { /// m.wait(&mut [], Duration::from_secs(1)).unwrap(); /// } /// ``` pub fn wait(&self, waitfds: &mut [WaitFd], timeout: Duration) -> Result { let timeout_ms = { let secs = timeout.as_secs(); if secs > (i32::max_value() / 1000) as u64 { // Duration too large, clamp at maximum value. i32::max_value() } else { secs as i32 * 1000 + timeout.subsec_nanos() as i32 / 1000_000 } }; unsafe { let mut ret = 0; try!(cvt(curl_sys::curl_multi_wait(self.raw, waitfds.as_mut_ptr() as *mut _, waitfds.len() as u32, timeout_ms, &mut ret))); Ok(ret as u32) } } /// Reads/writes available data from each easy handle. /// /// This function handles transfers on all the added handles that need /// attention in an non-blocking fashion. /// /// When an application has found out there's data available for this handle /// or a timeout has elapsed, the application should call this function to /// read/write whatever there is to read or write right now etc. This /// method returns as soon as the reads/writes are done. This function does /// not require that there actually is any data available for reading or /// that data can be written, it can be called just in case. It will return /// the number of handles that still transfer data. /// /// If the amount of running handles is changed from the previous call (or /// is less than the amount of easy handles you've added to the multi /// handle), you know that there is one or more transfers less "running". /// You can then call `info` to get information about each individual /// completed transfer, and that returned info includes `Error` and more. /// If an added handle fails very quickly, it may never be counted as a /// running handle. /// /// When running_handles is set to zero (0) on the return of this function, /// there is no longer any transfers in progress. /// /// # Return /// /// Before libcurl version 7.20.0: If you receive `is_call_perform`, this /// basically means that you should call `perform` again, before you select /// on more actions. You don't have to do it immediately, but the return /// code means that libcurl may have more data available to return or that /// there may be more data to send off before it is "satisfied". Do note /// that `perform` will return `is_call_perform` only when it wants to be /// called again immediately. When things are fine and there is nothing /// immediate it wants done, it'll return `Ok` and you need to wait for /// "action" and then call this function again. /// /// This function only returns errors etc regarding the whole multi stack. /// Problems still might have occurred on individual transfers even when /// this function returns `Ok`. Use `info` to figure out how individual /// transfers did. pub fn perform(&self) -> Result { unsafe { let mut ret = 0; try!(cvt(curl_sys::curl_multi_perform(self.raw, &mut ret))); Ok(ret as u32) } } /// Extracts file descriptor information from a multi handle /// /// This function extracts file descriptor information from a given /// handle, and libcurl returns its `fd_set` sets. The application can use /// these to `select()` on, but be sure to `FD_ZERO` them before calling /// this function as curl_multi_fdset only adds its own descriptors, it /// doesn't zero or otherwise remove any others. The curl_multi_perform /// function should be called as soon as one of them is ready to be read /// from or written to. /// /// If no file descriptors are set by libcurl, this function will return /// `Ok(None)`. Otherwise `Ok(Some(n))` will be returned where `n` the /// highest descriptor number libcurl set. When `Ok(None)` is returned it /// is because libcurl currently does something that isn't possible for /// your application to monitor with a socket and unfortunately you can /// then not know exactly when the current action is completed using /// `select()`. You then need to wait a while before you proceed and call /// `perform` anyway. /// /// When doing `select()`, you should use `get_timeout` to figure out /// how long to wait for action. Call `perform` even if no activity has /// been seen on the `fd_set`s after the timeout expires as otherwise /// internal retries and timeouts may not work as you'd think and want. /// /// If one of the sockets used by libcurl happens to be larger than what /// can be set in an `fd_set`, which on POSIX systems means that the file /// descriptor is larger than `FD_SETSIZE`, then libcurl will try to not /// set it. Setting a too large file descriptor in an `fd_set` implies an out /// of bounds write which can cause crashes, or worse. The effect of NOT /// storing it will possibly save you from the crash, but will make your /// program NOT wait for sockets it should wait for... pub fn fdset2(&self, read: Option<&mut curl_sys::fd_set>, write: Option<&mut curl_sys::fd_set>, except: Option<&mut curl_sys::fd_set>) -> Result, MultiError> { unsafe { let mut ret = 0; let read = read.map(|r| r as *mut _).unwrap_or(0 as *mut _); let write = write.map(|r| r as *mut _).unwrap_or(0 as *mut _); let except = except.map(|r| r as *mut _).unwrap_or(0 as *mut _); try!(cvt(curl_sys::curl_multi_fdset(self.raw, read, write, except, &mut ret))); if ret == -1 { Ok(None) } else { Ok(Some(ret)) } } } #[doc(hidden)] #[deprecated(note = "renamed to fdset2")] pub fn fdset(&self, read: Option<&mut fd_set>, write: Option<&mut fd_set>, except: Option<&mut fd_set>) -> Result, MultiError> { unsafe { let mut ret = 0; let read = read.map(|r| r as *mut _).unwrap_or(0 as *mut _); let write = write.map(|r| r as *mut _).unwrap_or(0 as *mut _); let except = except.map(|r| r as *mut _).unwrap_or(0 as *mut _); try!(cvt(curl_sys::curl_multi_fdset(self.raw, read as *mut _, write as *mut _, except as *mut _, &mut ret))); if ret == -1 { Ok(None) } else { Ok(Some(ret)) } } } /// Attempt to close the multi handle and clean up all associated resources. /// /// Cleans up and removes a whole multi stack. It does not free or touch any /// individual easy handles in any way - they still need to be closed /// individually. pub fn close(&self) -> Result<(), MultiError> { unsafe { cvt(curl_sys::curl_multi_cleanup(self.raw)) } } } fn cvt(code: curl_sys::CURLMcode) -> Result<(), MultiError> { if code == curl_sys::CURLM_OK { Ok(()) } else { Err(MultiError::new(code)) } } impl fmt::Debug for Multi { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Multi") .field("raw", &self.raw) .finish() } } impl Drop for Multi { fn drop(&mut self) { let _ = self.close(); } } impl EasyHandle { /// Sets an internal private token for this `EasyHandle`. /// /// This function will set the `CURLOPT_PRIVATE` field on the underlying /// easy handle. pub fn set_token(&mut self, token: usize) -> Result<(), Error> { unsafe { ::cvt(curl_sys::curl_easy_setopt(self.easy.raw(), curl_sys::CURLOPT_PRIVATE, token)) } } } impl fmt::Debug for EasyHandle { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.easy.fmt(f) } } impl Easy2Handle { /// Acquires a reference to the underlying handler for events. pub fn get_ref(&self) -> &H { self.easy.get_ref() } /// Acquires a reference to the underlying handler for events. pub fn get_mut(&mut self) -> &mut H { self.easy.get_mut() } /// Same as `EasyHandle::set_token` pub fn set_token(&mut self, token: usize) -> Result<(), Error> { unsafe { ::cvt(curl_sys::curl_easy_setopt(self.easy.raw(), curl_sys::CURLOPT_PRIVATE, token)) } } } impl fmt::Debug for Easy2Handle { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.easy.fmt(f) } } impl<'multi> Message<'multi> { /// If this message indicates that a transfer has finished, returns the /// result of the transfer in `Some`. /// /// If the message doesn't indicate that a transfer has finished, then /// `None` is returned. pub fn result(&self) -> Option> { unsafe { if (*self.ptr).msg == curl_sys::CURLMSG_DONE { Some(::cvt((*self.ptr).data as curl_sys::CURLcode)) } else { None } } } /// Returns whether this easy message was for the specified easy handle or /// not. pub fn is_for(&self, handle: &EasyHandle) -> bool { unsafe { (*self.ptr).easy_handle == handle.easy.raw() } } /// Same as `is_for`, but for `Easy2Handle`. pub fn is_for2(&self, handle: &Easy2Handle) -> bool { unsafe { (*self.ptr).easy_handle == handle.easy.raw() } } /// Returns the token associated with the easy handle that this message /// represents a completion for. /// /// This function will return the token assigned with /// `EasyHandle::set_token`. This reads the `CURLINFO_PRIVATE` field of the /// underlying `*mut CURL`. pub fn token(&self) -> Result { unsafe { let mut p = 0usize; try!(::cvt(curl_sys::curl_easy_getinfo((*self.ptr).easy_handle, curl_sys::CURLINFO_PRIVATE, &mut p))); Ok(p) } } } impl<'a> fmt::Debug for Message<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Message") .field("ptr", &self.ptr) .finish() } } impl Events { /// Creates a new blank event bit mask. pub fn new() -> Events { Events { bits: 0 } } /// Set or unset the whether these events indicate that input is ready. pub fn input(&mut self, val: bool) -> &mut Events { self.flag(curl_sys::CURL_CSELECT_IN, val) } /// Set or unset the whether these events indicate that output is ready. pub fn output(&mut self, val: bool) -> &mut Events { self.flag(curl_sys::CURL_CSELECT_OUT, val) } /// Set or unset the whether these events indicate that an error has /// happened. pub fn error(&mut self, val: bool) -> &mut Events { self.flag(curl_sys::CURL_CSELECT_ERR, val) } fn flag(&mut self, flag: c_int, val: bool) -> &mut Events { if val { self.bits |= flag; } else { self.bits &= !flag; } self } } impl fmt::Debug for Events { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Events") .field("input", &(self.bits & curl_sys::CURL_CSELECT_IN != 0)) .field("output", &(self.bits & curl_sys::CURL_CSELECT_IN != 0)) .field("error", &(self.bits & curl_sys::CURL_CSELECT_IN != 0)) .finish() } } impl SocketEvents { /// Wait for incoming data. For the socket to become readable. pub fn input(&self) -> bool { self.bits & curl_sys::CURL_POLL_IN == curl_sys::CURL_POLL_IN } /// Wait for outgoing data. For the socket to become writable. pub fn output(&self) -> bool { self.bits & curl_sys::CURL_POLL_OUT == curl_sys::CURL_POLL_OUT } /// Wait for incoming and outgoing data. For the socket to become readable /// or writable. pub fn input_and_output(&self) -> bool { self.bits & curl_sys::CURL_POLL_INOUT == curl_sys::CURL_POLL_INOUT } /// The specified socket/file descriptor is no longer used by libcurl. pub fn remove(&self) -> bool { self.bits & curl_sys::CURL_POLL_REMOVE == curl_sys::CURL_POLL_REMOVE } } impl fmt::Debug for SocketEvents { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Events") .field("input", &self.input()) .field("output", &self.output()) .field("remove", &self.remove()) .finish() } } impl WaitFd { /// Constructs an empty (invalid) WaitFd. pub fn new() -> WaitFd { WaitFd { inner: curl_sys::curl_waitfd { fd: 0, events: 0, revents: 0, } } } /// Set the file descriptor to wait for. pub fn set_fd(&mut self, fd: Socket) { self.inner.fd = fd; } /// Indicate that the socket should poll on read events such as new data /// received. /// /// Corresponds to `CURL_WAIT_POLLIN`. pub fn poll_on_read(&mut self, val: bool) -> &mut WaitFd { self.flag(curl_sys::CURL_WAIT_POLLIN, val) } /// Indicate that the socket should poll on high priority read events such /// as out of band data. /// /// Corresponds to `CURL_WAIT_POLLPRI`. pub fn poll_on_priority_read(&mut self, val: bool) -> &mut WaitFd { self.flag(curl_sys::CURL_WAIT_POLLPRI, val) } /// Indicate that the socket should poll on write events such as the socket /// being clear to write without blocking. /// /// Corresponds to `CURL_WAIT_POLLOUT`. pub fn poll_on_write(&mut self, val: bool) -> &mut WaitFd { self.flag(curl_sys::CURL_WAIT_POLLOUT, val) } fn flag(&mut self, flag: c_short, val: bool) -> &mut WaitFd { if val { self.inner.events |= flag; } else { self.inner.events &= !flag; } self } /// After a call to `wait`, returns `true` if `poll_on_read` was set and a /// read event occured. pub fn received_read(&self) -> bool { self.inner.revents & curl_sys::CURL_WAIT_POLLIN == curl_sys::CURL_WAIT_POLLIN } /// After a call to `wait`, returns `true` if `poll_on_priority_read` was set and a /// priority read event occured. pub fn received_priority_read(&self) -> bool { self.inner.revents & curl_sys::CURL_WAIT_POLLPRI == curl_sys::CURL_WAIT_POLLPRI } /// After a call to `wait`, returns `true` if `poll_on_write` was set and a /// write event occured. pub fn received_write(&self) -> bool { self.inner.revents & curl_sys::CURL_WAIT_POLLOUT == curl_sys::CURL_WAIT_POLLOUT } } #[cfg(unix)] impl From for WaitFd { fn from(pfd: pollfd) -> WaitFd { let mut events = 0; if pfd.events & POLLIN == POLLIN { events |= curl_sys::CURL_WAIT_POLLIN; } if pfd.events & POLLPRI == POLLPRI { events |= curl_sys::CURL_WAIT_POLLPRI; } if pfd.events & POLLOUT == POLLOUT { events |= curl_sys::CURL_WAIT_POLLOUT; } WaitFd { inner: curl_sys::curl_waitfd { fd: pfd.fd, events: events, revents: 0, } } } } impl fmt::Debug for WaitFd { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("WaitFd") .field("fd", &self.inner.fd) .field("events", &self.inner.fd) .field("revents", &self.inner.fd) .finish() } } vendor/curl-0.4.11/src/panic.rs0000664000000000000000000000154613264166600015000 0ustar rootrootuse std::any::Any; use std::cell::RefCell; use std::panic::{self, AssertUnwindSafe}; thread_local!(static LAST_ERROR: RefCell>> = { RefCell::new(None) }); pub fn catch T>(f: F) -> Option { if LAST_ERROR.with(|slot| slot.borrow().is_some()) { return None } // Note that `AssertUnwindSafe` is used here as we prevent reentering // arbitrary code due to the `LAST_ERROR` check above plus propagation of a // panic after we return back to user code from C. match panic::catch_unwind(AssertUnwindSafe(f)) { Ok(ret) => Some(ret), Err(e) => { LAST_ERROR.with(|slot| *slot.borrow_mut() = Some(e)); None } } } pub fn propagate() { if let Some(t) = LAST_ERROR.with(|slot| slot.borrow_mut().take()) { panic::resume_unwind(t) } } vendor/curl-0.4.11/src/version.rs0000664000000000000000000002207713264166600015375 0ustar rootrootuse std::ffi::CStr; use std::fmt; use std::str; use curl_sys; use libc::{c_int, c_char}; /// Version information about libcurl and the capabilities that it supports. pub struct Version { inner: *mut curl_sys::curl_version_info_data, } unsafe impl Send for Version {} unsafe impl Sync for Version {} /// An iterator over the list of protocols a version supports. #[derive(Clone)] pub struct Protocols<'a> { cur: *const *const c_char, _inner: &'a Version, } impl Version { /// Returns the libcurl version that this library is currently linked against. pub fn num() -> &'static str { unsafe { let s = CStr::from_ptr(curl_sys::curl_version() as *const _); str::from_utf8(s.to_bytes()).unwrap() } } /// Returns the libcurl version that this library is currently linked against. pub fn get() -> Version { unsafe { let ptr = curl_sys::curl_version_info(curl_sys::CURLVERSION_FOURTH); assert!(!ptr.is_null()); Version { inner: ptr } } } /// Returns the human readable version string, pub fn version(&self) -> &str { unsafe { ::opt_str((*self.inner).version).unwrap() } } /// Returns a numeric representation of the version number /// /// This is a 24 bit number made up of the major number, minor, and then /// patch number. For example 7.9.8 will return 0x070908. pub fn version_num(&self) -> u32 { unsafe { (*self.inner).version_num as u32 } } /// Returns a human readable string of the host libcurl is built for. /// /// This is discovered as part of the build environment. pub fn host(&self) -> &str { unsafe { ::opt_str((*self.inner).host).unwrap() } } /// Returns whether libcurl supports IPv6 pub fn feature_ipv6(&self) -> bool { self.flag(curl_sys::CURL_VERSION_IPV6) } /// Returns whether libcurl supports SSL pub fn feature_ssl(&self) -> bool { self.flag(curl_sys::CURL_VERSION_SSL) } /// Returns whether libcurl supports HTTP deflate via libz pub fn feature_libz(&self) -> bool { self.flag(curl_sys::CURL_VERSION_LIBZ) } /// Returns whether libcurl supports HTTP NTLM pub fn feature_ntlm(&self) -> bool { self.flag(curl_sys::CURL_VERSION_NTLM) } /// Returns whether libcurl supports HTTP GSSNEGOTIATE pub fn feature_gss_negotiate(&self) -> bool { self.flag(curl_sys::CURL_VERSION_GSSNEGOTIATE) } /// Returns whether libcurl was built with debug capabilities pub fn feature_debug(&self) -> bool { self.flag(curl_sys::CURL_VERSION_DEBUG) } /// Returns whether libcurl was built with SPNEGO authentication pub fn feature_spnego(&self) -> bool { self.flag(curl_sys::CURL_VERSION_SPNEGO) } /// Returns whether libcurl was built with large file support pub fn feature_largefile(&self) -> bool { self.flag(curl_sys::CURL_VERSION_LARGEFILE) } /// Returns whether libcurl was built with support for IDNA, domain names /// with international letters. pub fn feature_idn(&self) -> bool { self.flag(curl_sys::CURL_VERSION_IDN) } /// Returns whether libcurl was built with support for SSPI. pub fn feature_sspi(&self) -> bool { self.flag(curl_sys::CURL_VERSION_SSPI) } /// Returns whether libcurl was built with asynchronous name lookups. pub fn feature_async_dns(&self) -> bool { self.flag(curl_sys::CURL_VERSION_ASYNCHDNS) } /// Returns whether libcurl was built with support for character /// conversions. pub fn feature_conv(&self) -> bool { self.flag(curl_sys::CURL_VERSION_CONV) } /// Returns whether libcurl was built with support for TLS-SRP. pub fn feature_tlsauth_srp(&self) -> bool { self.flag(curl_sys::CURL_VERSION_TLSAUTH_SRP) } /// Returns whether libcurl was built with support for NTLM delegation to /// winbind helper. pub fn feature_ntlm_wb(&self) -> bool { self.flag(curl_sys::CURL_VERSION_NTLM_WB) } /// Returns whether libcurl was built with support for unix domain socket pub fn feature_unix_domain_socket(&self) -> bool { self.flag(curl_sys::CURL_VERSION_UNIX_SOCKETS) } // /// Returns whether libcurl was built with support for HTTP2. // pub fn feature_http2(&self) -> bool { // self.flag(curl_sys::CURL_VERSION_HTTP2) // } fn flag(&self, flag: c_int) -> bool { unsafe { (*self.inner).features & flag != 0 } } /// Returns the version of OpenSSL that is used, or None if there is no SSL /// support. pub fn ssl_version(&self) -> Option<&str> { unsafe { ::opt_str((*self.inner).ssl_version) } } /// Returns the version of libz that is used, or None if there is no libz /// support. pub fn libz_version(&self) -> Option<&str> { unsafe { ::opt_str((*self.inner).libz_version) } } /// Returns an iterator over the list of protocols that this build of /// libcurl supports. pub fn protocols(&self) -> Protocols { unsafe { Protocols { _inner: self, cur: (*self.inner).protocols } } } /// If available, the human readable version of ares that libcurl is linked /// against. pub fn ares_version(&self) -> Option<&str> { unsafe { if (*self.inner).age >= 1 { ::opt_str((*self.inner).ares) } else { None } } } /// If available, the version of ares that libcurl is linked against. pub fn ares_version_num(&self) -> Option { unsafe { if (*self.inner).age >= 1 { Some((*self.inner).ares_num as u32) } else { None } } } /// If available, the version of libidn that libcurl is linked against. pub fn libidn_version(&self) -> Option<&str> { unsafe { if (*self.inner).age >= 2 { ::opt_str((*self.inner).libidn) } else { None } } } /// If available, the version of iconv libcurl is linked against. pub fn iconv_version_num(&self) -> Option { unsafe { if (*self.inner).age >= 3 { Some((*self.inner).iconv_ver_num as u32) } else { None } } } /// If available, the version of iconv libcurl is linked against. pub fn libssh_version(&self) -> Option<&str> { unsafe { if (*self.inner).age >= 3 { ::opt_str((*self.inner).libssh_version) } else { None } } } } impl fmt::Debug for Version { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut f = f.debug_struct("Version"); f.field("version", &self.version()) .field("host", &self.host()) .field("feature_ipv6", &self.feature_ipv6()) .field("feature_ssl", &self.feature_ssl()) .field("feature_libz", &self.feature_libz()) .field("feature_ntlm", &self.feature_ntlm()) .field("feature_gss_negotiate", &self.feature_gss_negotiate()) .field("feature_debug", &self.feature_debug()) .field("feature_spnego", &self.feature_debug()) .field("feature_largefile", &self.feature_debug()) .field("feature_idn", &self.feature_debug()) .field("feature_sspi", &self.feature_debug()) .field("feature_async_dns", &self.feature_debug()) .field("feature_conv", &self.feature_debug()) .field("feature_tlsauth_srp", &self.feature_debug()) .field("feature_ntlm_wb", &self.feature_debug()) .field("feature_unix_domain_socket", &self.feature_debug()); if let Some(s) = self.ssl_version() { f.field("ssl_version", &s); } if let Some(s) = self.libz_version() { f.field("libz_version", &s); } if let Some(s) = self.ares_version() { f.field("ares_version", &s); } if let Some(s) = self.libidn_version() { f.field("libidn_version", &s); } if let Some(s) = self.iconv_version_num() { f.field("iconv_version_num", &format!("{:x}", s)); } if let Some(s) = self.libssh_version() { f.field("libssh_version", &s); } f.field("protocols", &self.protocols().collect::>()); f.finish() } } impl<'a> Iterator for Protocols<'a> { type Item = &'a str; fn next(&mut self) -> Option<&'a str> { unsafe { if (*self.cur).is_null() { return None } let ret = ::opt_str(*self.cur).unwrap(); self.cur = self.cur.offset(1); Some(ret) } } } impl<'a> fmt::Debug for Protocols<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_list() .entries(self.clone()) .finish() } } vendor/curl-0.4.11/tests/0000755000000000000000000000000013264166600013703 5ustar rootrootvendor/curl-0.4.11/tests/easy.rs0000664000000000000000000003324313264166600015221 0ustar rootrootextern crate curl; use std::cell::{RefCell, Cell}; use std::io::Read; use std::rc::Rc; use std::str; use std::time::Duration; macro_rules! t { ($e:expr) => (match $e { Ok(e) => e, Err(e) => panic!("{} failed with {:?}", stringify!($e), e), }) } use curl::easy::{Easy, List, WriteError, ReadError, Transfer}; use server::Server; mod server; fn handle() -> Easy { let mut e = Easy::new(); t!(e.timeout(Duration::new(20, 0))); return e } fn sink(data: &[u8]) -> Result { Ok(data.len()) } #[test] fn get_smoke() { let s = Server::new(); s.receive("\ GET / HTTP/1.1\r\n\ Host: 127.0.0.1:$PORT\r\n\ Accept: */*\r\n\ \r\n"); s.send("HTTP/1.1 200 OK\r\n\r\n"); let mut handle = handle(); t!(handle.url(&s.url("/"))); t!(handle.perform()); } #[test] fn get_path() { let s = Server::new(); s.receive("\ GET /foo HTTP/1.1\r\n\ Host: 127.0.0.1:$PORT\r\n\ Accept: */*\r\n\ \r\n"); s.send("HTTP/1.1 200 OK\r\n\r\n"); let mut handle = handle(); t!(handle.url(&s.url("/foo"))); t!(handle.perform()); } #[test] fn write_callback() { let s = Server::new(); s.receive("\ GET / HTTP/1.1\r\n\ Host: 127.0.0.1:$PORT\r\n\ Accept: */*\r\n\ \r\n"); s.send("HTTP/1.1 200 OK\r\n\r\nhello!"); let mut all = Vec::::new(); { let mut handle = handle(); t!(handle.url(&s.url("/"))); let mut handle = handle.transfer(); t!(handle.write_function(|data| { all.extend(data); Ok(data.len()) })); t!(handle.perform()); } assert_eq!(all, b"hello!"); } #[test] fn resolve() { let s = Server::new(); s.receive("\ GET / HTTP/1.1\r\n\ Host: example.com:$PORT\r\n\ Accept: */*\r\n\ \r\n"); s.send("HTTP/1.1 200 OK\r\n\r\n"); let mut list = List::new(); t!(list.append(&format!("example.com:{}:127.0.0.1", s.addr().port()))); let mut handle = handle(); t!(handle.url(&format!("http://example.com:{}/", s.addr().port()))); t!(handle.resolve(list)); t!(handle.perform()); } #[test] fn progress() { let s = Server::new(); s.receive("\ GET /foo HTTP/1.1\r\n\ Host: 127.0.0.1:$PORT\r\n\ Accept: */*\r\n\ \r\n"); s.send("HTTP/1.1 200 OK\r\n\r\nHello!"); let mut hits = 0; let mut dl = 0.0; { let mut handle = handle(); t!(handle.url(&s.url("/foo"))); t!(handle.progress(true)); t!(handle.write_function(sink)); let mut handle = handle.transfer(); t!(handle.progress_function(|_, a, _, _| { hits += 1; dl = a; true })); t!(handle.perform()); } assert!(hits > 0); assert_eq!(dl, 6.0); } #[test] fn headers() { let s = Server::new(); s.receive("\ GET / HTTP/1.1\r\n\ Host: 127.0.0.1:$PORT\r\n\ Accept: */*\r\n\ \r\n"); s.send("\ HTTP/1.1 200 OK\r\n\ Foo: bar\r\n\ Bar: baz\r\n\ \r\n Hello!"); let mut headers = Vec::new(); { let mut handle = handle(); t!(handle.url(&s.url("/"))); let mut handle = handle.transfer(); t!(handle.header_function(|h| { headers.push(str::from_utf8(h).unwrap().to_string()); true })); t!(handle.write_function(sink)); t!(handle.perform()); } assert_eq!(headers, vec![ "HTTP/1.1 200 OK\r\n".to_string(), "Foo: bar\r\n".to_string(), "Bar: baz\r\n".to_string(), "\r\n".to_string(), ]); } #[test] fn fail_on_error() { let s = Server::new(); s.receive("\ GET / HTTP/1.1\r\n\ Host: 127.0.0.1:$PORT\r\n\ Accept: */*\r\n\ \r\n"); s.send("\ HTTP/1.1 401 Not so good\r\n\ \r\n"); let mut h = handle(); t!(h.url(&s.url("/"))); t!(h.fail_on_error(true)); assert!(h.perform().is_err()); let s = Server::new(); s.receive("\ GET / HTTP/1.1\r\n\ Host: 127.0.0.1:$PORT\r\n\ Accept: */*\r\n\ \r\n"); s.send("\ HTTP/1.1 401 Not so good\r\n\ \r\n"); let mut h = handle(); t!(h.url(&s.url("/"))); t!(h.fail_on_error(false)); t!(h.perform()); } #[test] fn port() { let s = Server::new(); s.receive("\ GET / HTTP/1.1\r\n\ Host: localhost:$PORT\r\n\ Accept: */*\r\n\ \r\n"); s.send("\ HTTP/1.1 200 OK\r\n\ \r\n"); let mut h = handle(); t!(h.url("http://localhost/")); t!(h.port(s.addr().port())); t!(h.perform()); } #[test] fn proxy() { let s = Server::new(); s.receive("\ GET http://example.com/ HTTP/1.1\r\n\ Host: example.com\r\n\ Accept: */*\r\n\ \r\n"); s.send("\ HTTP/1.1 200 OK\r\n\ \r\n"); let mut h = handle(); t!(h.url("http://example.com/")); t!(h.proxy(&s.url("/"))); t!(h.perform()); } #[test] #[ignore] // fails on newer curl versions? seems benign fn noproxy() { let s = Server::new(); s.receive("\ GET / HTTP/1.1\r\n\ Host: 127.0.0.1:$PORT\r\n\ Accept: */*\r\n\ \r\n"); s.send("\ HTTP/1.1 200 OK\r\n\ \r\n"); let mut h = handle(); t!(h.url(&s.url("/"))); t!(h.proxy(&s.url("/"))); t!(h.noproxy("127.0.0.1")); t!(h.perform()); } #[test] fn misc() { let mut h = handle(); t!(h.tcp_nodelay(true)); // t!(h.tcp_keepalive(true)); // t!(h.tcp_keepidle(Duration::new(3, 0))); // t!(h.tcp_keepintvl(Duration::new(3, 0))); t!(h.buffer_size(10)); t!(h.dns_cache_timeout(Duration::new(1, 0))); } #[test] fn userpass() { let s = Server::new(); s.receive("\ GET / HTTP/1.1\r\n\ Authorization: Basic YmFyOg==\r\n\ Host: 127.0.0.1:$PORT\r\n\ Accept: */*\r\n\ \r\n"); s.send("\ HTTP/1.1 200 OK\r\n\ \r\n"); let mut h = handle(); t!(h.url(&s.url("/"))); t!(h.username("foo")); t!(h.username("bar")); t!(h.perform()); } #[test] fn accept_encoding() { let s = Server::new(); s.receive("\ GET / HTTP/1.1\r\n\ Host: 127.0.0.1:$PORT\r\n\ Accept: */*\r\n\ Accept-Encoding: gzip\r\n\ \r\n"); s.send("\ HTTP/1.1 200 OK\r\n\ \r\n"); let mut h = handle(); t!(h.url(&s.url("/"))); t!(h.accept_encoding("gzip")); t!(h.perform()); } #[test] fn follow_location() { let s1 = Server::new(); let s2 = Server::new(); s1.receive("\ GET / HTTP/1.1\r\n\ Host: 127.0.0.1:$PORT\r\n\ Accept: */*\r\n\ \r\n"); s1.send(&format!("\ HTTP/1.1 301 Moved Permanently\r\n\ Location: http://{}/foo\r\n\ \r\n", s2.addr())); s2.receive("\ GET /foo HTTP/1.1\r\n\ Host: 127.0.0.1:$PORT\r\n\ Accept: */*\r\n\ \r\n"); s2.send("\ HTTP/1.1 200 OK\r\n\ \r\n"); let mut h = handle(); t!(h.url(&s1.url("/"))); t!(h.follow_location(true)); t!(h.perform()); } #[test] fn put() { let s = Server::new(); s.receive("\ PUT / HTTP/1.1\r\n\ Host: 127.0.0.1:$PORT\r\n\ Accept: */*\r\n\ Content-Length: 5\r\n\ \r\n\ data\n"); s.send("\ HTTP/1.1 200 OK\r\n\ \r\n"); let mut data = "data\n".as_bytes(); let mut list = List::new(); t!(list.append("Expect:")); let mut h = handle(); t!(h.url(&s.url("/"))); t!(h.put(true)); t!(h.in_filesize(5)); t!(h.upload(true)); t!(h.http_headers(list)); let mut h = h.transfer(); t!(h.read_function(|buf| { Ok(data.read(buf).unwrap()) })); t!(h.perform()); } #[test] fn post1() { let s = Server::new(); s.receive("\ POST / HTTP/1.1\r\n\ Host: 127.0.0.1:$PORT\r\n\ Accept: */*\r\n\ Content-Length: 5\r\n\ Content-Type: application/x-www-form-urlencoded\r\n\ \r\n\ data\n"); s.send("\ HTTP/1.1 200 OK\r\n\ \r\n"); let mut h = handle(); t!(h.url(&s.url("/"))); t!(h.post(true)); t!(h.post_fields_copy(b"data\n")); t!(h.perform()); } #[test] fn post2() { let s = Server::new(); s.receive("\ POST / HTTP/1.1\r\n\ Host: 127.0.0.1:$PORT\r\n\ Accept: */*\r\n\ Content-Length: 5\r\n\ Content-Type: application/x-www-form-urlencoded\r\n\ \r\n\ data\n"); s.send("\ HTTP/1.1 200 OK\r\n\ \r\n"); let mut h = handle(); t!(h.url(&s.url("/"))); t!(h.post(true)); t!(h.post_fields_copy(b"data\n")); t!(h.write_function(sink)); t!(h.perform()); } #[test] fn post3() { let s = Server::new(); s.receive("\ POST / HTTP/1.1\r\n\ Host: 127.0.0.1:$PORT\r\n\ Accept: */*\r\n\ Content-Length: 5\r\n\ Content-Type: application/x-www-form-urlencoded\r\n\ \r\n\ data\n"); s.send("\ HTTP/1.1 200 OK\r\n\ \r\n"); let mut data = "data\n".as_bytes(); let mut h = handle(); t!(h.url(&s.url("/"))); t!(h.post(true)); t!(h.post_field_size(5)); let mut h = h.transfer(); t!(h.read_function(|buf| { Ok(data.read(buf).unwrap()) })); t!(h.perform()); } #[test] fn referer() { let s = Server::new(); s.receive("\ GET / HTTP/1.1\r\n\ Host: 127.0.0.1:$PORT\r\n\ Accept: */*\r\n\ Referer: foo\r\n\ \r\n"); s.send("\ HTTP/1.1 200 OK\r\n\ \r\n"); let mut h = handle(); t!(h.url(&s.url("/"))); t!(h.referer("foo")); t!(h.perform()); } #[test] fn useragent() { let s = Server::new(); s.receive("\ GET / HTTP/1.1\r\n\ User-Agent: foo\r\n\ Host: 127.0.0.1:$PORT\r\n\ Accept: */*\r\n\ \r\n"); s.send("\ HTTP/1.1 200 OK\r\n\ \r\n"); let mut h = handle(); t!(h.url(&s.url("/"))); t!(h.useragent("foo")); t!(h.perform()); } #[test] fn custom_headers() { let s = Server::new(); s.receive("\ GET / HTTP/1.1\r\n\ Host: 127.0.0.1:$PORT\r\n\ Foo: bar\r\n\ \r\n"); s.send("\ HTTP/1.1 200 OK\r\n\ \r\n"); let mut custom = List::new(); t!(custom.append("Foo: bar")); t!(custom.append("Accept:")); let mut h = handle(); t!(h.url(&s.url("/"))); t!(h.http_headers(custom)); t!(h.perform()); } #[test] fn cookie() { let s = Server::new(); s.receive("\ GET / HTTP/1.1\r\n\ Host: 127.0.0.1:$PORT\r\n\ Accept: */*\r\n\ Cookie: foo\r\n\ \r\n"); s.send("\ HTTP/1.1 200 OK\r\n\ \r\n"); let mut h = handle(); t!(h.url(&s.url("/"))); t!(h.cookie("foo")); t!(h.perform()); } #[test] fn url_encoding() { let mut h = handle(); assert_eq!(h.url_encode(b"foo"), "foo"); assert_eq!(h.url_encode(b"foo bar"), "foo%20bar"); assert_eq!(h.url_encode(b"foo bar\xff"), "foo%20bar%FF"); assert_eq!(h.url_encode(b""), ""); assert_eq!(h.url_decode("foo"), b"foo"); assert_eq!(h.url_decode("foo%20bar"), b"foo bar"); assert_eq!(h.url_decode("foo%2"), b"foo%2"); assert_eq!(h.url_decode("foo%xx"), b"foo%xx"); assert_eq!(h.url_decode("foo%ff"), b"foo\xff"); assert_eq!(h.url_decode(""), b""); } #[test] fn getters() { let s = Server::new(); s.receive("\ GET / HTTP/1.1\r\n\ Host: 127.0.0.1:$PORT\r\n\ Accept: */*\r\n\ \r\n"); s.send("\ HTTP/1.1 200 OK\r\n\ \r\n"); let mut h = handle(); t!(h.url(&s.url("/"))); t!(h.cookie_file("/dev/null")); t!(h.perform()); assert_eq!(t!(h.response_code()), 200); assert_eq!(t!(h.redirect_count()), 0); assert_eq!(t!(h.redirect_url()), None); assert_eq!(t!(h.content_type()), None); let addr = format!("http://{}/", s.addr()); assert_eq!(t!(h.effective_url()), Some(&addr[..])); // TODO: test this // let cookies = t!(h.cookies()).iter() // .map(|s| s.to_vec()) // .collect::>(); // assert_eq!(cookies.len(), 1); } #[test] #[should_panic] fn panic_in_callback() { let s = Server::new(); s.receive("\ GET / HTTP/1.1\r\n\ Host: 127.0.0.1:$PORT\r\n\ Accept: */*\r\n\ \r\n"); s.send("\ HTTP/1.1 200 OK\r\n\ \r\n"); let mut h = handle(); t!(h.url(&s.url("/"))); t!(h.header_function(|_| panic!())); t!(h.perform()); } #[test] fn abort_read() { let s = Server::new(); s.receive("\ PUT / HTTP/1.1\r\n\ Host: 127.0.0.1:$PORT\r\n\ Accept: */*\r\n\ Content-Length: 2\r\n\ \r\n"); s.send("\ HTTP/1.1 200 OK\r\n\ \r\n"); let mut h = handle(); t!(h.url(&s.url("/"))); t!(h.read_function(|_| Err(ReadError::Abort))); t!(h.put(true)); t!(h.in_filesize(2)); let mut list = List::new(); t!(list.append("Expect:")); t!(h.http_headers(list)); let err = h.perform().unwrap_err(); assert!(err.is_aborted_by_callback()); } #[test] fn pause_write_then_resume() { let s = Server::new(); s.receive("\ GET / HTTP/1.1\r\n\ Host: 127.0.0.1:$PORT\r\n\ Accept: */*\r\n\ \r\n"); s.send("\ HTTP/1.1 200 OK\r\n\ \r\n a\n b"); let mut h = handle(); t!(h.url(&s.url("/"))); t!(h.progress(true)); struct State<'a, 'b> { paused: Cell, unpaused: Cell, transfer: RefCell>, } let h = Rc::new(State { paused: Cell::new(false), unpaused: Cell::new(false), transfer: RefCell::new(h.transfer()), }); let h2 = h.clone(); t!(h.transfer.borrow_mut().write_function(move |data| { if h2.unpaused.get() { h2.unpaused.set(false); Ok(data.len()) } else { h2.paused.set(true); Err(WriteError::Pause) } })); let h2 = h.clone(); t!(h.transfer.borrow_mut().progress_function(move |_, _, _, _| { if h2.paused.get() { h2.paused.set(false); h2.unpaused.set(true); t!(h2.transfer.borrow().unpause_write()); } true })); t!(h.transfer.borrow().perform()); } #[test] fn perform_in_perform_is_bad() { let s = Server::new(); s.receive("\ GET / HTTP/1.1\r\n\ Host: 127.0.0.1:$PORT\r\n\ Accept: */*\r\n\ \r\n"); s.send("\ HTTP/1.1 200 OK\r\n\ \r\n a\n b"); let mut h = handle(); t!(h.url(&s.url("/"))); t!(h.progress(true)); let h = Rc::new(RefCell::new(h.transfer())); let h2 = h.clone(); t!(h.borrow_mut().write_function(move |data| { assert!(h2.borrow().perform().is_err()); Ok(data.len()) })); t!(h.borrow().perform()); } // Stupid test to check if unix_socket is callable #[test] fn check_unix_socket() { let mut h = handle(); h.unix_socket("/var/something.socks").is_ok(); } vendor/curl-0.4.11/tests/formdata0000664000000000000000000000000613264166600015421 0ustar rootroothello vendor/curl-0.4.11/tests/multi.rs0000664000000000000000000001542413264166600015413 0ustar rootroot#![cfg(unix)] extern crate curl; extern crate mio; use std::collections::HashMap; use std::io::{Read, Cursor}; use std::time::Duration; use curl::easy::{Easy, List}; use curl::multi::Multi; macro_rules! t { ($e:expr) => (match $e { Ok(e) => e, Err(e) => panic!("{} failed with {:?}", stringify!($e), e), }) } use server::Server; mod server; #[test] fn smoke() { let m = Multi::new(); let mut e = Easy::new(); let s = Server::new(); s.receive("\ GET / HTTP/1.1\r\n\ Host: 127.0.0.1:$PORT\r\n\ Accept: */*\r\n\ \r\n"); s.send("HTTP/1.1 200 OK\r\n\r\n"); t!(e.url(&s.url("/"))); let _e = t!(m.add(e)); while t!(m.perform()) > 0 { t!(m.wait(&mut [], Duration::from_secs(1))); } } #[test] fn smoke2() { let m = Multi::new(); let s1 = Server::new(); s1.receive("\ GET / HTTP/1.1\r\n\ Host: 127.0.0.1:$PORT\r\n\ Accept: */*\r\n\ \r\n"); s1.send("HTTP/1.1 200 OK\r\n\r\n"); let s2 = Server::new(); s2.receive("\ GET / HTTP/1.1\r\n\ Host: 127.0.0.1:$PORT\r\n\ Accept: */*\r\n\ \r\n"); s2.send("HTTP/1.1 200 OK\r\n\r\n"); let mut e1 = Easy::new(); t!(e1.url(&s1.url("/"))); let _e1 = t!(m.add(e1)); let mut e2 = Easy::new(); t!(e2.url(&s2.url("/"))); let _e2 = t!(m.add(e2)); while t!(m.perform()) > 0 { t!(m.wait(&mut [], Duration::from_secs(1))); } let mut done = 0; m.messages(|msg| { msg.result().unwrap().unwrap(); done += 1; }); assert_eq!(done, 2); } #[test] fn upload_lots() { use curl::multi::{Socket, SocketEvents, Events}; #[derive(Debug)] enum Message { Timeout(Option), Wait(Socket, SocketEvents, usize), } let mut m = Multi::new(); let poll = t!(mio::Poll::new()); let (tx, rx) = mio::channel::channel(); let tx2 = tx.clone(); t!(m.socket_function(move |socket, events, token| { t!(tx2.send(Message::Wait(socket, events, token))); })); t!(m.timer_function(move |dur| { t!(tx.send(Message::Timeout(dur))); true })); let s = Server::new(); s.receive(&format!("\ PUT / HTTP/1.1\r\n\ Host: 127.0.0.1:$PORT\r\n\ Accept: */*\r\n\ Content-Length: 131072\r\n\ \r\n\ {}\n", vec!["a"; 128 * 1024 - 1].join(""))); s.send("\ HTTP/1.1 200 OK\r\n\ \r\n"); let mut data = vec![b'a'; 128 * 1024 - 1]; data.push(b'\n'); let mut data = Cursor::new(data); let mut list = List::new(); t!(list.append("Expect:")); let mut h = Easy::new(); t!(h.url(&s.url("/"))); t!(h.put(true)); t!(h.read_function(move |buf| { Ok(data.read(buf).unwrap()) })); t!(h.in_filesize(128 * 1024)); t!(h.upload(true)); t!(h.http_headers(list)); t!(poll.register(&rx, mio::Token(0), mio::Ready::all(), mio::PollOpt::level())); let e = t!(m.add(h)); assert!(t!(m.perform()) > 0); let mut next_token = 1; let mut token_map = HashMap::new(); let mut cur_timeout = None; let mut events = mio::Events::with_capacity(128); let mut running = true; while running { let n = t!(poll.poll(&mut events, cur_timeout)); if n == 0 { if t!(m.timeout()) == 0 { running = false; } } for event in events.iter() { while event.token() == mio::Token(0) { match rx.try_recv() { Ok(Message::Timeout(dur)) => cur_timeout = dur, Ok(Message::Wait(socket, events, token)) => { let evented = mio::unix::EventedFd(&socket); if events.remove() { token_map.remove(&token).unwrap(); } else { let mut e = mio::Ready::none(); if events.input() { e = e | mio::Ready::readable(); } if events.output() { e = e | mio::Ready::writable(); } if token == 0 { let token = next_token; next_token += 1; t!(m.assign(socket, token)); token_map.insert(token, socket); t!(poll.register(&evented, mio::Token(token), e, mio::PollOpt::level())); } else { t!(poll.reregister(&evented, mio::Token(token), e, mio::PollOpt::level())); } } } Err(_) => break, } } if event.token() == mio::Token(0) { continue } let token = event.token(); let socket = token_map[&token.into()]; let mut e = Events::new(); if event.kind().is_readable() { e.input(true); } if event.kind().is_writable() { e.output(true); } if event.kind().is_error() { e.error(true); } let remaining = t!(m.action(socket, &e)); if remaining == 0 { running = false; } } } let mut done = 0; m.messages(|m| { m.result().unwrap().unwrap(); done += 1; }); assert_eq!(done, 1); let mut e = t!(m.remove(e)); assert_eq!(t!(e.response_code()), 200); } // Tests passing raw file descriptors to Multi::wait. The test is limited to Linux only as the // semantics of the underlying poll(2) system call used by curl apparently differ on other // platforms, making the test fail. #[cfg(target_os = "linux")] #[test] fn waitfds() { use std::fs::File; use std::os::unix::io::AsRawFd; use curl::multi::WaitFd; let filenames = ["/dev/null", "/dev/zero", "/dev/urandom"]; let files: Vec = filenames.iter() .map(|filename| File::open(filename).unwrap()) .collect(); let mut waitfds: Vec = files.iter().map(|f| { let mut waitfd = WaitFd::new(); waitfd.set_fd(f.as_raw_fd()); waitfd.poll_on_read(true); waitfd }).collect(); let m = Multi::new(); let events = t!(m.wait(&mut waitfds, Duration::from_secs(1))); assert_eq!(events, 3); for waitfd in waitfds { assert!(waitfd.received_read()); } } vendor/curl-0.4.11/tests/post.rs0000664000000000000000000000457413264166600015252 0ustar rootrootextern crate curl; use std::str; use std::time::Duration; macro_rules! t { ($e:expr) => (match $e { Ok(e) => e, Err(e) => panic!("{} failed with {:?}", stringify!($e), e), }) } use curl::easy::{Easy, Form}; use server::Server; mod server; fn handle() -> Easy { let mut e = Easy::new(); t!(e.timeout(Duration::new(20, 0))); return e } #[test] fn custom() { let s = Server::new(); s.receive("\ POST / HTTP/1.1\r\n\ Host: 127.0.0.1:$PORT\r\n\ Accept: */*\r\n\ Content-Length: 142\r\n\ Expect: 100-continue\r\n\ Content-Type: multipart/form-data; boundary=--[..]\r\n\ \r\n\ --[..]\r\n\ Content-Disposition: form-data; name=\"foo\"\r\n\ \r\n\ 1234\r\n\ --[..]\r\n"); s.send("HTTP/1.1 200 OK\r\n\r\n"); let mut handle = handle(); let mut form = Form::new(); t!(form.part("foo").contents(b"1234").add()); t!(handle.url(&s.url("/"))); t!(handle.httppost(form)); t!(handle.perform()); } #[test] fn buffer() { let s = Server::new(); s.receive("\ POST / HTTP/1.1\r\n\ Host: 127.0.0.1:$PORT\r\n\ Accept: */*\r\n\ Content-Length: 181\r\n\ Expect: 100-continue\r\n\ Content-Type: multipart/form-data; boundary=--[..]\r\n\ \r\n\ --[..]\r\n\ Content-Disposition: form-data; name=\"foo\"; filename=\"bar\"\r\n\ Content-Type: foo/bar\r\n\ \r\n\ 1234\r\n\ --[..]\r\n"); s.send("HTTP/1.1 200 OK\r\n\r\n"); let mut handle = handle(); let mut form = Form::new(); t!(form.part("foo") .buffer("bar", b"1234".to_vec()) .content_type("foo/bar") .add()); t!(handle.url(&s.url("/"))); t!(handle.httppost(form)); t!(handle.perform()); } #[test] fn file() { let s = Server::new(); let formdata = include_str!("formdata"); s.receive(format!("\ POST / HTTP/1.1\r\n\ Host: 127.0.0.1:$PORT\r\n\ Accept: */*\r\n\ Content-Length: {}\r\n\ Expect: 100-continue\r\n\ Content-Type: multipart/form-data; boundary=--[..]\r\n\ \r\n\ --[..]\r\n\ Content-Disposition: form-data; name=\"foo\"; filename=\"formdata\"\r\n\ Content-Type: application/octet-stream\r\n\ \r\n\ {}\ \r\n\ --[..]\r\n", 199 + formdata.len(), formdata).as_str()); s.send("HTTP/1.1 200 OK\r\n\r\n"); let mut handle = handle(); let mut form = Form::new(); t!(form.part("foo") .file("tests/formdata") .add()); t!(handle.url(&s.url("/"))); t!(handle.httppost(form)); t!(handle.perform()); } vendor/curl-0.4.11/tests/server/0000755000000000000000000000000013264166600015211 5ustar rootrootvendor/curl-0.4.11/tests/server/mod.rs0000664000000000000000000001332013264166600016337 0ustar rootroot#![allow(dead_code)] use std::collections::HashSet; use std::net::{TcpListener, SocketAddr, TcpStream}; use std::io::prelude::*; use std::thread; use std::sync::mpsc::{Sender, Receiver, channel}; use std::io::BufReader; pub struct Server { messages: Option>, addr: SocketAddr, thread: Option>, } enum Message { Read(String), Write(String), } fn run(listener: &TcpListener, rx: &Receiver) { let mut socket = BufReader::new(listener.accept().unwrap().0); for msg in rx.iter() { match msg { Message::Read(ref expected) => { let mut expected = &expected[..]; let mut expected_headers = HashSet::new(); while let Some(i) = expected.find("\n") { let line = &expected[..i + 1]; expected = &expected[i + 1..]; expected_headers.insert(line); if line == "\r\n" { break } } let mut expected_len = None; while expected_headers.len() > 0 { let mut actual = String::new(); t!(socket.read_line(&mut actual)); if actual.starts_with("Content-Length") { let len = actual.split(": ").skip(1).next().unwrap(); expected_len = len.trim().parse().ok(); } // various versions of libcurl do different things here if actual == "Proxy-Connection: Keep-Alive\r\n" { continue } if expected_headers.remove(&actual[..]) { continue } let mut found = None; for header in expected_headers.iter() { if lines_match(header, &actual) { found = Some(header.clone()); break } } if let Some(found) = found { expected_headers.remove(&found); continue } panic!("unexpected header: {:?} (remaining headers {:?})", actual, expected_headers); } for header in expected_headers { panic!("expected header but not found: {:?}", header); } let mut line = String::new(); let mut socket = match expected_len { Some(amt) => socket.by_ref().take(amt), None => socket.by_ref().take(expected.len() as u64), }; while socket.limit() > 0 { line.truncate(0); t!(socket.read_line(&mut line)); if line.len() == 0 { break } if expected.len() == 0 { panic!("unexpected line: {:?}", line); } let i = expected.find("\n").unwrap_or(expected.len() - 1); let expected_line = &expected[..i + 1]; expected = &expected[i + 1..]; if lines_match(expected_line, &line) { continue } panic!("lines didn't match:\n\ expected: {:?}\n\ actual: {:?}\n", expected_line, line) } if expected.len() != 0 { println!("didn't get expected data: {:?}", expected); } } Message::Write(ref to_write) => { t!(socket.get_mut().write_all(to_write.as_bytes())); return } } } let mut dst = Vec::new(); t!(socket.read_to_end(&mut dst)); assert!(dst.len() == 0); } fn lines_match(expected: &str, mut actual: &str) -> bool { for (i, part) in expected.split("[..]").enumerate() { match actual.find(part) { Some(j) => { if i == 0 && j != 0 { return false } actual = &actual[j + part.len()..]; } None => { return false } } } actual.is_empty() || expected.ends_with("[..]") } impl Server { pub fn new() -> Server { let listener = t!(TcpListener::bind("127.0.0.1:0")); let addr = t!(listener.local_addr()); let (tx, rx) = channel(); let thread = thread::spawn(move || run(&listener, &rx)); Server { messages: Some(tx), addr: addr, thread: Some(thread), } } pub fn receive(&self, msg: &str) { let msg = msg.replace("$PORT", &self.addr.port().to_string()); self.msg(Message::Read(msg)); } pub fn send(&self, msg: &str) { let msg = msg.replace("$PORT", &self.addr.port().to_string()); self.msg(Message::Write(msg)); } fn msg(&self, msg: Message) { t!(self.messages.as_ref().unwrap().send(msg)); } pub fn addr(&self) -> &SocketAddr { &self.addr } pub fn url(&self, path: &str) -> String { format!("http://{}{}", self.addr, path) } } impl Drop for Server { fn drop(&mut self) { drop(TcpStream::connect(&self.addr)); drop(self.messages.take()); let res = self.thread.take().unwrap().join(); if !thread::panicking() { t!(res); } else if let Err(e) = res { println!("child server thread also failed: {:?}", e); } } } vendor/curl-sys-0.4.1/0000755000000000000000000000000013264166600013274 5ustar rootrootvendor/curl-sys-0.4.1/.cargo-checksum.json0000644000000000000000000000013113264166600017133 0ustar rootroot{"files":{},"package":"f46e49c7125131f5afaded06944d6888b55cbdf8eba05dae73c954019b907961"}vendor/curl-sys-0.4.1/Cargo.toml0000644000000000000000000000272313264166600015230 0ustar rootroot# 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 = "curl-sys" version = "0.4.1" authors = ["Carl Lerche ", "Alex Crichton "] build = "build.rs" links = "curl" description = "Native bindings to the libcurl library" documentation = "https://docs.rs/curl-sys" categories = ["external-ffi-bindings"] license = "MIT" repository = "https://github.com/alexcrichton/curl-rust" [lib] name = "curl_sys" path = "lib.rs" [dependencies.libc] version = "0.2" [dependencies.libz-sys] version = ">= 0" [build-dependencies.cc] version = "1.0" [build-dependencies.pkg-config] version = "0.3" [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies.openssl-sys] version = "0.9" [target."cfg(target_env = \"msvc\")".build-dependencies.vcpkg] version = "0.2" [target."cfg(windows)".dependencies.winapi] version = "0.3" features = ["winsock2", "ws2def"] [badges.appveyor] repository = "alexcrichton/curl-rust" [badges.travis-ci] repository = "alexcrichton/curl-rust" vendor/curl-sys-0.4.1/LICENSE0000664000000000000000000000203713264166600014305 0ustar rootrootCopyright (c) 2014 Carl Lerche 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. vendor/curl-sys-0.4.1/build.rs0000664000000000000000000003374213264166600014754 0ustar rootrootextern crate pkg_config; #[cfg(target_env = "msvc")] extern crate vcpkg; extern crate cc; use std::ascii::AsciiExt; use std::env; use std::ffi::OsString; use std::fs; use std::path::{PathBuf, Path, Component, Prefix}; use std::process::Command; use std::io::ErrorKind; macro_rules! t { ($e:expr) => (match $e { Ok(t) => t, Err(e) => panic!("{} return the error {}", stringify!($e), e), }) } fn main() { let target = env::var("TARGET").unwrap(); let host = env::var("HOST").unwrap(); let src = env::current_dir().unwrap(); let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap()); let windows = target.contains("windows"); // OSX and Haiku ships libcurl by default, so we just use that version // unconditionally. if target.contains("apple") || target.contains("haiku") { return println!("cargo:rustc-flags=-l curl"); } // Illumos/Solaris requires explicit linking with libnsl if target.contains("solaris") { println!("cargo:rustc-flags=-l nsl"); } // Next, fall back and try to use pkg-config if its available. if !target.contains("windows") { match pkg_config::find_library("libcurl") { Ok(lib) => { for path in lib.include_paths.iter() { println!("cargo:include={}", path.display()); } return } Err(e) => println!("Couldn't find libcurl from \ pkgconfig ({:?}), compiling it from source...", e), } } if try_vcpkg() { return; } if !Path::new("curl/.git").exists() { let _ = Command::new("git").args(&["submodule", "update", "--init"]) .status(); } println!("cargo:rustc-link-search=native={}/lib", dst.display()); println!("cargo:rustc-link-lib=static=curl"); println!("cargo:root={}", dst.display()); println!("cargo:include={}/include", dst.display()); if windows { println!("cargo:rustc-link-lib=ws2_32"); println!("cargo:rustc-link-lib=crypt32"); } // MSVC builds are just totally different if target.contains("msvc") { return build_msvc(&target); } let openssl_root = register_dep("OPENSSL"); let zlib_root = register_dep("Z"); let nghttp2_root = register_dep("NGHTTP2"); let cfg = cc::Build::new(); let compiler = cfg.get_compiler(); let _ = fs::create_dir(&dst.join("build")); let mut cmd = Command::new("sh"); let mut cflags = OsString::new(); for arg in compiler.args() { cflags.push(arg); cflags.push(" "); } // Can't run ./configure directly on msys2 b/c we're handing in // Windows-style paths (those starting with C:\), but it chokes on those. // For that reason we build up a shell script with paths converted to // posix versions hopefully... // // Also apparently the buildbots choke unless we manually set LD, who knows // why?! cmd.env("CC", compiler.path()) .env("CFLAGS", cflags) .env("LD", &which("ld").unwrap()) .env("VERBOSE", "1") .current_dir(&dst.join("build")) .arg(msys_compatible(&src.join("curl/configure"))); // For now this build script doesn't support paths with spaces in them. This // is arguably a but in curl's configure script, but we could also try to // paper over it by using a tmp directory which *doesn't* have spaces in it. // As of now though that's not implemented so just give a nicer error for // the time being. let wants_space_error = windows && (dst.to_str().map(|s| s.contains(" ")).unwrap_or(false) || src.to_str().map(|s| s.contains(" ")).unwrap_or(false)); if wants_space_error { panic!("\n\nunfortunately ./configure of libcurl is known to \ fail if there's a space in the path to the current \ directory\n\n\ there's a space in either\n {}\n {}\nand this will cause the \ build to fail\n\n\ the MSVC build should work with a directory that has \ spaces in it, and it would also work to move this to a \ different directory without spaces\n\n", src.display(), dst.display()) } if windows { cmd.arg("--with-winssl"); } else { cmd.arg("--without-ca-bundle"); cmd.arg("--without-ca-path"); } if let Some(root) = openssl_root { cmd.arg(format!("--with-ssl={}", msys_compatible(&root))); } if let Some(root) = zlib_root { cmd.arg(format!("--with-zlib={}", msys_compatible(&root))); } cmd.arg("--enable-static=yes"); cmd.arg("--enable-shared=no"); match &env::var("PROFILE").unwrap()[..] { "bench" | "release" => { cmd.arg("--enable-optimize"); } _ => { cmd.arg("--enable-debug"); cmd.arg("--disable-optimize"); } } cmd.arg(format!("--prefix={}", msys_compatible(&dst))); if target != host && (!target.contains("windows") || !host.contains("windows")) { // NOTE GNU terminology // BUILD = machine where we are (cross) compiling curl // HOST = machine where the compiled curl will be used // TARGET = only relevant when compiling compilers if target.contains("windows") { // curl's configure can't parse `-windows-` triples when used // as `--host`s. In those cases we use this combination of // `host` and `target` that appears to do the right thing. cmd.arg(format!("--host={}", host)); cmd.arg(format!("--target={}", target)); } else { cmd.arg(format!("--build={}", host)); cmd.arg(format!("--host={}", target)); } } if let Some(root) = nghttp2_root { cmd.arg(format!("--with-nghttp2={}", msys_compatible(&root))); } else { cmd.arg("--without-nghttp2"); } cmd.arg("--without-librtmp"); cmd.arg("--without-libidn2"); cmd.arg("--without-libssh2"); cmd.arg("--without-libpsl"); cmd.arg("--disable-ldap"); cmd.arg("--disable-ldaps"); cmd.arg("--disable-ftp"); cmd.arg("--disable-rtsp"); cmd.arg("--disable-dict"); cmd.arg("--disable-telnet"); cmd.arg("--disable-tftp"); cmd.arg("--disable-pop3"); cmd.arg("--disable-imap"); cmd.arg("--disable-smtp"); cmd.arg("--disable-gopher"); cmd.arg("--disable-manual"); cmd.arg("--disable-smb"); cmd.arg("--disable-sspi"); cmd.arg("--disable-manual"); cmd.arg("--disable-unix-sockets"); cmd.arg("--disable-versioned-symbols"); cmd.arg("--enable-hidden-symbols"); cmd.arg("--disable-libcurl-option"); run(&mut cmd, "sh"); run(make() .arg(&format!("-j{}", env::var("NUM_JOBS").unwrap())) .current_dir(&dst.join("build")), "make"); run(make() .arg("install") .current_dir(&dst.join("build")), "make"); } fn run(cmd: &mut Command, program: &str) { println!("running: {:?}", cmd); let status = match cmd.status() { Ok(status) => status, Err(ref e) if e.kind() == ErrorKind::NotFound => { fail(&format!("failed to execute command: {}\nis `{}` not installed?", e, program)); } Err(e) => fail(&format!("failed to execute command: {}", e)), }; if !status.success() { fail(&format!("command did not execute successfully, got: {}", status)); } } fn fail(s: &str) -> ! { panic!("\n{}\n\nbuild script failed, must exit now", s) } fn make() -> Command { let cmd = if cfg!(target_os = "freebsd") {"gmake"} else {"make"}; let mut cmd = Command::new(cmd); // We're using the MSYS make which doesn't work with the mingw32-make-style // MAKEFLAGS, so remove that from the env if present. if cfg!(windows) { cmd.env_remove("MAKEFLAGS").env_remove("MFLAGS"); } return cmd } fn which(cmd: &str) -> Option { let cmd = format!("{}{}", cmd, env::consts::EXE_SUFFIX); let paths = env::var_os("PATH").unwrap(); env::split_paths(&paths).map(|p| p.join(&cmd)).find(|p| { fs::metadata(p).is_ok() }) } fn msys_compatible(path: &Path) -> String { let mut path_string = path.to_str().unwrap().to_string(); if !cfg!(windows) { return path_string; } // Replace e.g. C:\ with /c/ if let Component::Prefix(prefix_component) = path.components().next().unwrap() { if let Prefix::Disk(disk) = prefix_component.kind() { let from = format!("{}:\\", disk as char); let to = format!("/{}/", (disk as char).to_ascii_lowercase()); path_string = path_string.replace(&from, &to); } } path_string.replace("\\", "/") } fn register_dep(dep: &str) -> Option { if let Some(s) = env::var_os(&format!("DEP_{}_ROOT", dep)) { prepend("PKG_CONFIG_PATH", Path::new(&s).join("lib/pkgconfig")); return Some(s.into()) } if let Some(s) = env::var_os(&format!("DEP_{}_INCLUDE", dep)) { let root = Path::new(&s).parent().unwrap(); env::set_var(&format!("DEP_{}_ROOT", dep), root); let path = root.join("lib/pkgconfig"); if path.exists() { prepend("PKG_CONFIG_PATH", path); return Some(root.to_path_buf()) } } return None; fn prepend(var: &str, val: PathBuf) { let prefix = env::var(var).unwrap_or(String::new()); let mut v = vec![val]; v.extend(env::split_paths(&prefix)); env::set_var(var, &env::join_paths(v).unwrap()); } } fn build_msvc(target: &str) { let cmd = cc::windows_registry::find(target, "nmake.exe"); let mut cmd = cmd.unwrap_or(Command::new("nmake.exe")); let src = env::current_dir().unwrap(); let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap()); let machine = if target.starts_with("x86_64") { "x64" } else if target.starts_with("i686") { "x86" } else { panic!("unknown msvc target: {}", target); }; t!(fs::create_dir_all(dst.join("include/curl"))); t!(fs::create_dir_all(dst.join("lib"))); drop(fs::remove_dir_all(&dst.join("build"))); cp_r(&src.join("curl"), &dst.join("build")); cmd.current_dir(dst.join("build/winbuild")); cmd.arg("/f").arg("Makefile.vc") .arg("MODE=static") .arg("ENABLE_IDN=yes") .arg("DEBUG=no") .arg("GEN_PDB=no") .arg("ENABLE_WINSSL=yes") .arg("ENABLE_SSPI=yes") .arg(format!("MACHINE={}", machine)); // These env vars are intended for `make` usually, not nmake, so remove them // unconditionally cmd.env_remove("MAKEFLAGS") .env_remove("MFLAGS"); let features = env::var("CARGO_CFG_TARGET_FEATURE") .unwrap_or(String::new()); if features.contains("crt-static") { cmd.arg("RTLIBCFG=static"); } if let Some(inc) = env::var_os("DEP_Z_ROOT") { let inc = PathBuf::from(inc); let mut s = OsString::from("WITH_DEVEL="); s.push(&inc); cmd.arg("WITH_ZLIB=static").arg(s); // the build system for curl expects this library to be called // zlib_a.lib, so make sure it's named correctly (where libz-sys just // produces zlib.lib) let _ = fs::remove_file(&inc.join("lib/zlib_a.lib")); t!(fs::copy(inc.join("lib/zlib.lib"), inc.join("lib/zlib_a.lib"))); } run(&mut cmd, "nmake"); let name = format!("libcurl-vc-{}-release-static-zlib-static-\ ipv6-sspi-winssl", machine); let libs = dst.join("build/builds").join(name); t!(fs::copy(libs.join("lib/libcurl_a.lib"), dst.join("lib/curl.lib"))); for f in t!(fs::read_dir(libs.join("include/curl"))) { let path = t!(f).path(); let dst = dst.join("include/curl").join(path.file_name().unwrap()); t!(fs::copy(path, dst)); } t!(fs::remove_dir_all(dst.join("build/builds"))); println!("cargo:rustc-link-lib=wldap32"); println!("cargo:rustc-link-lib=advapi32"); println!("cargo:rustc-link-lib=normaliz"); } #[cfg(not(target_env = "msvc"))] fn try_vcpkg() -> bool { false } #[cfg(target_env = "msvc")] fn try_vcpkg() -> bool { // the import library for the dll is called libcurl_imp let mut successful_probe_details = match vcpkg::Config::new().lib_names("libcurl_imp", "libcurl") .emit_includes(true).probe("curl") { Ok(details) => Some(details), Err(e) => { println!("first run of vcpkg did not find libcurl: {}", e); None } }; if successful_probe_details.is_none() { match vcpkg::Config::new().lib_name("libcurl") .emit_includes(true).probe("curl") { Ok(details) => successful_probe_details = Some(details), Err(e) => println!("second run of vcpkg did not find libcurl: {}", e), } } if successful_probe_details.is_some() { // Found libcurl which depends on openssl, libssh2 and zlib // in the a default vcpkg installation. Probe for them // but do not fail if they are not present as we may be working // with a customized vcpkg installation. vcpkg::Config::new() .lib_name("libeay32") .lib_name("ssleay32") .probe("openssl").ok(); vcpkg::probe_package("libssh2").ok(); vcpkg::Config::new() .lib_names("zlib", "zlib1") .probe("zlib").ok(); println!("cargo:rustc-link-lib=crypt32"); println!("cargo:rustc-link-lib=gdi32"); println!("cargo:rustc-link-lib=user32"); println!("cargo:rustc-link-lib=wldap32"); return true; } false } fn cp_r(src: &Path, dst: &Path) { t!(fs::create_dir(dst)); for e in t!(src.read_dir()).map(|e| t!(e)) { let src = e.path(); let dst = dst.join(e.file_name()); if t!(e.file_type()).is_dir() { cp_r(&src, &dst); } else { t!(fs::copy(&src, &dst)); } } } vendor/curl-sys-0.4.1/lib.rs0000664000000000000000000014302513264166600014417 0ustar rootroot#![allow(bad_style)] #![doc(html_root_url = "https://docs.rs/curl-sys/0.3")] extern crate libc; #[cfg(not(target_env = "msvc"))] extern crate libz_sys; #[cfg(all(unix, not(target_os = "macos")))] extern crate openssl_sys; #[cfg(windows)] extern crate winapi; use libc::{c_int, c_char, c_uint, c_short, c_long, c_double, c_void, size_t, time_t}; use libc::c_ulong; #[cfg(unix)] pub use libc::fd_set; #[cfg(windows)] pub use winapi::um::winsock2::fd_set; #[cfg(windows)] use winapi::shared::ws2def::SOCKADDR; #[cfg(target_env = "msvc")] #[doc(hidden)] pub type __enum_ty = libc::c_int; #[cfg(not(target_env = "msvc"))] #[doc(hidden)] pub type __enum_ty = libc::c_uint; pub type CURLINFO = __enum_ty; pub type CURLoption = __enum_ty; pub type CURLcode = __enum_ty; pub type CURLversion = __enum_ty; pub type curl_off_t = i64; pub enum CURL {} #[cfg(unix)] pub type curl_socket_t = libc::c_int; #[cfg(unix)] pub const CURL_SOCKET_BAD: curl_socket_t = -1; #[cfg(all(windows, target_pointer_width = "32"))] pub type curl_socket_t = libc::c_uint; #[cfg(all(windows, target_pointer_width = "64"))] pub type curl_socket_t = u64; #[cfg(windows)] pub const CURL_SOCKET_BAD: curl_socket_t = !0; pub enum curl_httppost { // Note that this changed in some versions of libcurl, so we currently don't // bind the fields as they're apparently not stable. // pub next: *mut curl_httppost, // pub name: *mut c_char, // pub namelength: c_long, // pub contents: *mut c_char, // pub contentslength: c_long, // pub buffer: *mut c_char, // pub bufferlength: c_long, // pub contenttype: *mut c_char, // pub contentheader: *mut curl_slist, // pub more: *mut curl_httppost, // pub flags: c_long, // pub showfilename: *mut c_char, // pub userp: *mut c_void, } // pub const HTTPPOST_FILENAME: c_long = 1 << 0; // pub const HTTPPOST_READFILE: c_long = 1 << 1; // pub const HTTPPOST_PTRNAME: c_long = 1 << 2; // pub const HTTPPOST_PTRCONTENTS: c_long = 1 << 3; // pub const HTTPPOST_BUFFER: c_long = 1 << 4; // pub const HTTPPOST_PTRBUFFER: c_long = 1 << 5; // pub const HTTPPOST_CALLBACK: c_long = 1 << 6; pub type curl_progress_callback = extern fn(*mut c_void, c_double, c_double, c_double, c_double) -> c_int; // pub type curl_xferinfo_callback = extern fn(*mut c_void, // curl_off_t, // curl_off_t, // curl_off_t, // curl_off_t) -> c_int; pub const CURL_WRITEFUNC_PAUSE: size_t = 0x10000001; pub type curl_write_callback = extern fn(*mut c_char, size_t, size_t, *mut c_void) -> size_t; pub type curlfiletype = __enum_ty; pub const CURLFILETYPE_FILE: curlfiletype = 0; pub const CURLFILETYPE_DIRECTORY: curlfiletype = 1; pub const CURLFILETYPE_SYMLINK: curlfiletype = 2; pub const CURLFILETYPE_DEVICE_BLOCK: curlfiletype = 3; pub const CURLFILETYPE_DEVICE_CHAR: curlfiletype = 4; pub const CURLFILETYPE_NAMEDPIPE: curlfiletype = 5; pub const CURLFILETYPE_SOCKET: curlfiletype = 6; pub const CURLFILETYPE_DOOR: curlfiletype = 7; pub const CURLFILETYPE_UNKNOWN: curlfiletype = 8; pub const CURLFINFOFLAG_KNOWN_FILENAME: c_uint = 1 << 0; pub const CURLFINFOFLAG_KNOWN_FILETYPE: c_uint = 1 << 1; pub const CURLFINFOFLAG_KNOWN_TIME: c_uint = 1 << 2; pub const CURLFINFOFLAG_KNOWN_PERM: c_uint = 1 << 3; pub const CURLFINFOFLAG_KNOWN_UID: c_uint = 1 << 4; pub const CURLFINFOFLAG_KNOWN_GID: c_uint = 1 << 5; pub const CURLFINFOFLAG_KNOWN_SIZE: c_uint = 1 << 6; pub const CURLFINFOFLAG_KNOWN_HLINKCOUNT: c_uint = 1 << 7; #[repr(C)] pub struct curl_fileinfo { pub filename: *mut c_char, pub filetype: curlfiletype, pub time: time_t, pub perm: c_uint, pub uid: c_int, pub gid: c_int, pub size: curl_off_t, pub hardlinks: c_long, pub strings_time: *mut c_char, pub strings_perm: *mut c_char, pub strings_user: *mut c_char, pub strings_group: *mut c_char, pub strings_target: *mut c_char, pub flags: c_uint, pub b_data: *mut c_char, pub b_size: size_t, pub b_used: size_t, } pub const CURL_CHUNK_BGN_FUNC_OK: c_long = 0; pub const CURL_CHUNK_BGN_FUNC_FAIL: c_long = 1; pub const CURL_CHUNK_BGN_FUNC_SKIP: c_long = 2; pub type curl_chunk_bgn_callback = extern fn(*const c_void, *mut c_void, c_int) -> c_long; pub const CURL_CHUNK_END_FUNC_OK: c_long = 0; pub const CURL_CHUNK_END_FUNC_FAIL: c_long = 1; pub type curl_chunk_end_callback = extern fn(*mut c_void) -> c_long; pub const CURL_FNMATCHFUNC_MATCH: c_int = 0; pub const CURL_FNMATCHFUNC_NOMATCH: c_int = 1; pub const CURL_FNMATCHFUNC_FAIL: c_int = 2; pub type curl_fnmatch_callback = extern fn(*mut c_void, *const c_char, *const c_char) -> c_int; pub const CURL_SEEKFUNC_OK: c_int = 0; pub const CURL_SEEKFUNC_FAIL: c_int = 1; pub const CURL_SEEKFUNC_CANTSEEK: c_int = 2; pub type curl_seek_callback = extern fn(*mut c_void, curl_off_t, c_int) -> c_int; pub const CURL_READFUNC_ABORT: size_t = 0x10000000; pub const CURL_READFUNC_PAUSE: size_t = 0x10000001; pub type curl_read_callback = extern fn(*mut c_char, size_t, size_t, *mut c_void) -> size_t; // pub const CURL_SOCKOPT_OK: c_int = 0; // pub const CURL_SOCKOPT_ERROR: c_int = 1; // pub const CURL_SOCKOPT_ALREADY_CONNECTED: c_int = 2; // pub type curl_sockopt_callback = extern fn(*mut c_void, // curl_socket_t, // curlsocktype) -> c_int; pub type curlioerr = __enum_ty; pub const CURLIOE_OK: curlioerr = 0; pub const CURLIOE_UNKNOWNCMD: curlioerr = 1; pub const CURLIOE_FAILRESTART: curlioerr = 2; pub type curliocmd = __enum_ty; pub const CURLIOCMD_NOP: curliocmd = 0; pub const CURLIOCMD_RESTARTREAD: curliocmd = 1; pub type curl_ioctl_callback = extern fn(*mut CURL, c_int, *mut c_void) -> curlioerr; pub type curl_malloc_callback = extern fn(size_t) -> *mut c_void; pub type curl_free_callback = extern fn(*mut c_void); pub type curl_realloc_callback = extern fn(*mut c_void, size_t) -> *mut c_void; pub type curl_strdup_callback = extern fn(*const c_char) -> *mut c_char; pub type curl_calloc_callback = extern fn(size_t, size_t) -> *mut c_void; pub type curl_infotype = __enum_ty; pub const CURLINFO_TEXT: curl_infotype = 0; pub const CURLINFO_HEADER_IN: curl_infotype = 1; pub const CURLINFO_HEADER_OUT: curl_infotype = 2; pub const CURLINFO_DATA_IN: curl_infotype = 3; pub const CURLINFO_DATA_OUT: curl_infotype = 4; pub const CURLINFO_SSL_DATA_IN: curl_infotype = 5; pub const CURLINFO_SSL_DATA_OUT: curl_infotype = 6; pub type curl_debug_callback = extern fn(*mut CURL, curl_infotype, *mut c_char, size_t, *mut c_void) -> c_int; pub const CURLE_OK: CURLcode = 0; pub const CURLE_UNSUPPORTED_PROTOCOL: CURLcode = 1; pub const CURLE_FAILED_INIT: CURLcode = 2; pub const CURLE_URL_MALFORMAT: CURLcode = 3; // pub const CURLE_NOT_BUILT_IN: CURLcode = 4; pub const CURLE_COULDNT_RESOLVE_PROXY: CURLcode = 5; pub const CURLE_COULDNT_RESOLVE_HOST: CURLcode = 6; pub const CURLE_COULDNT_CONNECT: CURLcode = 7; pub const CURLE_FTP_WEIRD_SERVER_REPLY: CURLcode = 8; pub const CURLE_REMOTE_ACCESS_DENIED: CURLcode = 9; // pub const CURLE_FTP_ACCEPT_FAILED: CURLcode = 10; pub const CURLE_FTP_WEIRD_PASS_REPLY: CURLcode = 11; // pub const CURLE_FTP_ACCEPT_TIMEOUT: CURLcode = 12; pub const CURLE_FTP_WEIRD_PASV_REPLY: CURLcode = 13; pub const CURLE_FTP_WEIRD_227_FORMAT: CURLcode = 14; pub const CURLE_FTP_CANT_GET_HOST: CURLcode = 15; pub const CURLE_OBSOLETE16: CURLcode = 16; pub const CURLE_FTP_COULDNT_SET_TYPE: CURLcode = 17; pub const CURLE_PARTIAL_FILE: CURLcode = 18; pub const CURLE_FTP_COULDNT_RETR_FILE: CURLcode = 19; pub const CURLE_OBSOLETE20: CURLcode = 20; pub const CURLE_QUOTE_ERROR: CURLcode = 21; pub const CURLE_HTTP_RETURNED_ERROR: CURLcode = 22; pub const CURLE_WRITE_ERROR: CURLcode = 23; pub const CURLE_OBSOLETE24: CURLcode = 24; pub const CURLE_UPLOAD_FAILED: CURLcode = 25; pub const CURLE_READ_ERROR: CURLcode = 26; pub const CURLE_OUT_OF_MEMORY: CURLcode = 27; pub const CURLE_OPERATION_TIMEDOUT: CURLcode = 28; pub const CURLE_OBSOLETE29: CURLcode = 29; pub const CURLE_FTP_PORT_FAILED: CURLcode = 30; pub const CURLE_FTP_COULDNT_USE_REST: CURLcode = 31; pub const CURLE_OBSOLETE32: CURLcode = 32; pub const CURLE_RANGE_ERROR: CURLcode = 33; pub const CURLE_HTTP_POST_ERROR: CURLcode = 34; pub const CURLE_SSL_CONNECT_ERROR: CURLcode = 35; pub const CURLE_BAD_DOWNLOAD_RESUME: CURLcode = 36; pub const CURLE_FILE_COULDNT_READ_FILE: CURLcode = 37; pub const CURLE_LDAP_CANNOT_BIND: CURLcode = 38; pub const CURLE_LDAP_SEARCH_FAILED: CURLcode = 39; pub const CURLE_OBSOLETE40: CURLcode = 40; pub const CURLE_FUNCTION_NOT_FOUND: CURLcode = 41; pub const CURLE_ABORTED_BY_CALLBACK: CURLcode = 42; pub const CURLE_BAD_FUNCTION_ARGUMENT: CURLcode = 43; pub const CURLE_OBSOLETE44: CURLcode = 44; pub const CURLE_INTERFACE_FAILED: CURLcode = 45; pub const CURLE_OBSOLETE46: CURLcode = 46; pub const CURLE_TOO_MANY_REDIRECTS : CURLcode = 47; pub const CURLE_UNKNOWN_OPTION: CURLcode = 48; pub const CURLE_TELNET_OPTION_SYNTAX : CURLcode = 49; pub const CURLE_OBSOLETE50: CURLcode = 50; pub const CURLE_PEER_FAILED_VERIFICATION: CURLcode = 51; pub const CURLE_GOT_NOTHING: CURLcode = 52; pub const CURLE_SSL_ENGINE_NOTFOUND: CURLcode = 53; pub const CURLE_SSL_ENGINE_SETFAILED: CURLcode = 54; pub const CURLE_SEND_ERROR: CURLcode = 55; pub const CURLE_RECV_ERROR: CURLcode = 56; pub const CURLE_OBSOLETE57: CURLcode = 57; pub const CURLE_SSL_CERTPROBLEM: CURLcode = 58; pub const CURLE_SSL_CIPHER: CURLcode = 59; pub const CURLE_SSL_CACERT: CURLcode = 60; pub const CURLE_BAD_CONTENT_ENCODING: CURLcode = 61; pub const CURLE_LDAP_INVALID_URL: CURLcode = 62; pub const CURLE_FILESIZE_EXCEEDED: CURLcode = 63; pub const CURLE_USE_SSL_FAILED: CURLcode = 64; pub const CURLE_SEND_FAIL_REWIND: CURLcode = 65; pub const CURLE_SSL_ENGINE_INITFAILED: CURLcode = 66; pub const CURLE_LOGIN_DENIED: CURLcode = 67; pub const CURLE_TFTP_NOTFOUND: CURLcode = 68; pub const CURLE_TFTP_PERM: CURLcode = 69; pub const CURLE_REMOTE_DISK_FULL: CURLcode = 70; pub const CURLE_TFTP_ILLEGAL: CURLcode = 71; pub const CURLE_TFTP_UNKNOWNID: CURLcode = 72; pub const CURLE_REMOTE_FILE_EXISTS: CURLcode = 73; pub const CURLE_TFTP_NOSUCHUSER: CURLcode = 74; pub const CURLE_CONV_FAILED: CURLcode = 75; pub const CURLE_CONV_REQD: CURLcode = 76; pub const CURLE_SSL_CACERT_BADFILE: CURLcode = 77; pub const CURLE_REMOTE_FILE_NOT_FOUND: CURLcode = 78; pub const CURLE_SSH: CURLcode = 79; pub const CURLE_SSL_SHUTDOWN_FAILED: CURLcode = 80; pub const CURLE_AGAIN: CURLcode = 81; pub const CURLE_SSL_CRL_BADFILE: CURLcode = 82; pub const CURLE_SSL_ISSUER_ERROR: CURLcode = 83; pub const CURLE_FTP_PRET_FAILED: CURLcode = 84; pub const CURLE_RTSP_CSEQ_ERROR: CURLcode = 85; pub const CURLE_RTSP_SESSION_ERROR: CURLcode = 86; pub const CURLE_FTP_BAD_FILE_LIST: CURLcode = 87; pub const CURLE_CHUNK_FAILED: CURLcode = 88; // pub const CURLE_NO_CONNECTION_AVAILABLE: CURLcode = 89; pub type curl_conv_callback = extern fn(*mut c_char, size_t) -> CURLcode; pub type curl_ssl_ctx_callback = extern fn(*mut CURL, *mut c_void, *mut c_void) -> CURLcode; pub type curl_proxytype = __enum_ty; pub const CURLPROXY_HTTP: curl_proxytype = 0; pub const CURLPROXY_HTTP_1_0: curl_proxytype = 1; pub const CURLPROXY_SOCKS4: curl_proxytype = 4; pub const CURLPROXY_SOCKS5: curl_proxytype = 5; pub const CURLPROXY_SOCKS4A: curl_proxytype = 6; pub const CURLPROXY_SOCKS5_HOSTNAME: curl_proxytype = 7; pub const CURLAUTH_NONE: c_ulong = 0; pub const CURLAUTH_BASIC: c_ulong = 1 << 0; pub const CURLAUTH_DIGEST: c_ulong = 1 << 1; pub const CURLAUTH_GSSNEGOTIATE: c_ulong = 1 << 2; pub const CURLAUTH_NTLM: c_ulong = 1 << 3; pub const CURLAUTH_DIGEST_IE: c_ulong = 1 << 4; pub const CURLAUTH_NTLM_WB: c_ulong = 1 << 5; // pub const CURLAUTH_ONLY: c_ulong = 1 << 31; pub const CURLAUTH_ANY: c_ulong = !CURLAUTH_DIGEST_IE; pub const CURLAUTH_ANYSAFE: c_ulong = !(CURLAUTH_BASIC | CURLAUTH_DIGEST_IE); // pub const CURLSSH_AUTH_ANY: c_ulong = !0; // pub const CURLSSH_AUTH_NONE: c_ulong = 0; // pub const CURLSSH_AUTH_PUBLICKEY: c_ulong = 1 << 0; // pub const CURLSSH_AUTH_PASSWORD: c_ulong = 1 << 1; // pub const CURLSSH_AUTH_HOST: c_ulong = 1 << 2; // pub const CURLSSH_AUTH_KEYBOARD: c_ulong = 1 << 3; // pub const CURLSSH_AUTH_AGENT: c_ulong = 1 << 4; // pub const CURLSSH_AUTH_DEFAULT: c_ulong = CURLSSH_AUTH_ANY; pub const CURLGSSAPI_DELEGATION_NONE: c_ulong = 0; pub const CURLGSSAPI_DELEGATION_POLICY_FLAG: c_ulong = 1 << 0; pub const CURLGSSAPI_DELEGATION_FLAG: c_ulong = 1 << 1; // pub type curl_khtype = __enum_ty; // pub const CURLKHTYPE_UNKNOWN: curl_khtype = 0; // pub const CURLKHTYPE_RSA1: curl_khtype = 1; // pub const CURLKHTYPE_RSA: curl_khtype = 2; // pub const CURLKHTYPE_DSS: curl_khtype = 3; // #[repr(C)] // pub struct curl_khkey { // pub key: *const c_char, // pub len: size_t, // pub keytype: curl_khtype, // } // pub type curl_khstat = __enum_ty; // pub const CURLKHSTAT_FINE_ADD_TO_FILE: curl_khstat = 0; // pub const CURLKHSTAT_FINE: curl_khstat = 1; // pub const CURLKHSTAT_REJECT: curl_khstat = 2; // pub const CURLKHSTAT_DEFER: curl_khstat = 3; // // pub type curl_khmatch = __enum_ty; // pub const CURLKHMATCH_OK: curl_khmatch = 0; // pub const CURLKHMATCH_MISMATCH: curl_khmatch = 1; // pub const CURLKHMATCH_MISSING: curl_khmatch = 2; // pub type curl_sshkeycallback = extern fn(*mut CURL, // *const curl_khkey, // *const curl_khkey, // curl_khmatch, // *mut c_void) -> c_int; pub const CURL_NETRC_IGNORED: c_ulong = 0; pub const CURL_NETRC_OPTIONAL: c_ulong = 1; pub const CURL_NETRC_REQUIRED: c_ulong = 2; pub type curl_usessl = __enum_ty; pub const CURLUSESSL_NONE: curl_usessl = 0; pub const CURLUSESSL_TRY: curl_usessl = 1; pub const CURLUSESSL_CONTROL: curl_usessl = 2; pub const CURLUSESSL_ALL: curl_usessl = 3; pub const CURLPROTO_HTTP: c_int = 1 << 0; pub const CURLPROTO_HTTPS: c_int = 1 << 1; pub const CURLPROTO_FILE: c_int = 1 << 10; pub const CURLOPTTYPE_LONG: CURLoption = 0; pub const CURLOPTTYPE_OBJECTPOINT: CURLoption = 10_000; pub const CURLOPTTYPE_FUNCTIONPOINT: CURLoption = 20_000; pub const CURLOPTTYPE_OFF_T: CURLoption = 30_000; pub const CURLOPT_FILE: CURLoption = CURLOPTTYPE_OBJECTPOINT + 1; pub const CURLOPT_URL: CURLoption = CURLOPTTYPE_OBJECTPOINT + 2; pub const CURLOPT_PORT: CURLoption = CURLOPTTYPE_LONG + 3; pub const CURLOPT_PROXY: CURLoption = CURLOPTTYPE_OBJECTPOINT + 4; pub const CURLOPT_USERPWD: CURLoption = CURLOPTTYPE_OBJECTPOINT + 5; pub const CURLOPT_PROXYUSERPWD: CURLoption = CURLOPTTYPE_OBJECTPOINT + 6; pub const CURLOPT_RANGE: CURLoption = CURLOPTTYPE_OBJECTPOINT + 7; pub const CURLOPT_INFILE: CURLoption = CURLOPTTYPE_OBJECTPOINT + 9; pub const CURLOPT_ERRORBUFFER: CURLoption = CURLOPTTYPE_OBJECTPOINT + 10; pub const CURLOPT_WRITEFUNCTION: CURLoption = CURLOPTTYPE_FUNCTIONPOINT + 11; pub const CURLOPT_READFUNCTION: CURLoption = CURLOPTTYPE_FUNCTIONPOINT + 12; pub const CURLOPT_TIMEOUT: CURLoption = CURLOPTTYPE_LONG + 13; pub const CURLOPT_INFILESIZE: CURLoption = CURLOPTTYPE_LONG + 14; pub const CURLOPT_POSTFIELDS: CURLoption = CURLOPTTYPE_OBJECTPOINT + 15; pub const CURLOPT_REFERER: CURLoption = CURLOPTTYPE_OBJECTPOINT + 16; pub const CURLOPT_FTPPORT: CURLoption = CURLOPTTYPE_OBJECTPOINT + 17; pub const CURLOPT_USERAGENT: CURLoption = CURLOPTTYPE_OBJECTPOINT + 18; pub const CURLOPT_LOW_SPEED_LIMIT: CURLoption = CURLOPTTYPE_LONG + 19; pub const CURLOPT_LOW_SPEED_TIME: CURLoption = CURLOPTTYPE_LONG + 20; pub const CURLOPT_RESUME_FROM: CURLoption = CURLOPTTYPE_LONG + 21; pub const CURLOPT_COOKIE: CURLoption = CURLOPTTYPE_OBJECTPOINT + 22; pub const CURLOPT_HTTPHEADER: CURLoption = CURLOPTTYPE_OBJECTPOINT + 23; pub const CURLOPT_HTTPPOST: CURLoption = CURLOPTTYPE_OBJECTPOINT + 24; pub const CURLOPT_SSLCERT: CURLoption = CURLOPTTYPE_OBJECTPOINT + 25; pub const CURLOPT_KEYPASSWD: CURLoption = CURLOPTTYPE_OBJECTPOINT + 26; pub const CURLOPT_CRLF: CURLoption = CURLOPTTYPE_LONG + 27; pub const CURLOPT_QUOTE: CURLoption = CURLOPTTYPE_OBJECTPOINT + 28; pub const CURLOPT_WRITEHEADER: CURLoption = CURLOPTTYPE_OBJECTPOINT + 29; pub const CURLOPT_COOKIEFILE: CURLoption = CURLOPTTYPE_OBJECTPOINT + 31; pub const CURLOPT_SSLVERSION: CURLoption = CURLOPTTYPE_LONG + 32; pub const CURLOPT_TIMECONDITION: CURLoption = CURLOPTTYPE_LONG + 33; pub const CURLOPT_TIMEVALUE: CURLoption = CURLOPTTYPE_LONG + 34; pub const CURLOPT_CUSTOMREQUEST: CURLoption = CURLOPTTYPE_OBJECTPOINT + 36; pub const CURLOPT_STDERR: CURLoption = CURLOPTTYPE_OBJECTPOINT + 37; pub const CURLOPT_POSTQUOTE: CURLoption = CURLOPTTYPE_OBJECTPOINT + 39; pub const CURLOPT_WRITEINFO: CURLoption = CURLOPTTYPE_OBJECTPOINT + 40; pub const CURLOPT_VERBOSE: CURLoption = CURLOPTTYPE_LONG + 41; pub const CURLOPT_HEADER: CURLoption = CURLOPTTYPE_LONG + 42; pub const CURLOPT_NOPROGRESS: CURLoption = CURLOPTTYPE_LONG + 43; pub const CURLOPT_NOBODY: CURLoption = CURLOPTTYPE_LONG + 44; pub const CURLOPT_FAILONERROR: CURLoption = CURLOPTTYPE_LONG + 45; pub const CURLOPT_UPLOAD: CURLoption = CURLOPTTYPE_LONG + 46; pub const CURLOPT_POST: CURLoption = CURLOPTTYPE_LONG + 47; pub const CURLOPT_DIRLISTONLY: CURLoption = CURLOPTTYPE_LONG + 48; pub const CURLOPT_APPEND: CURLoption = CURLOPTTYPE_LONG + 50; pub const CURLOPT_NETRC: CURLoption = CURLOPTTYPE_LONG + 51; pub const CURLOPT_FOLLOWLOCATION: CURLoption = CURLOPTTYPE_LONG + 52; pub const CURLOPT_TRANSFERTEXT: CURLoption = CURLOPTTYPE_LONG + 53; pub const CURLOPT_PUT: CURLoption = CURLOPTTYPE_LONG + 54; pub const CURLOPT_PROGRESSFUNCTION: CURLoption = CURLOPTTYPE_FUNCTIONPOINT + 56; pub const CURLOPT_PROGRESSDATA: CURLoption = CURLOPTTYPE_OBJECTPOINT + 57; pub const CURLOPT_AUTOREFERER: CURLoption = CURLOPTTYPE_LONG + 58; pub const CURLOPT_PROXYPORT: CURLoption = CURLOPTTYPE_LONG + 59; pub const CURLOPT_POSTFIELDSIZE: CURLoption = CURLOPTTYPE_LONG + 60; pub const CURLOPT_HTTPPROXYTUNNEL: CURLoption = CURLOPTTYPE_LONG + 61; pub const CURLOPT_INTERFACE: CURLoption = CURLOPTTYPE_OBJECTPOINT + 62; pub const CURLOPT_KRBLEVEL: CURLoption = CURLOPTTYPE_OBJECTPOINT + 63; pub const CURLOPT_SSL_VERIFYPEER: CURLoption = CURLOPTTYPE_LONG + 64; pub const CURLOPT_CAINFO: CURLoption = CURLOPTTYPE_OBJECTPOINT + 65; pub const CURLOPT_MAXREDIRS: CURLoption = CURLOPTTYPE_LONG + 68; pub const CURLOPT_FILETIME: CURLoption = CURLOPTTYPE_LONG + 69; pub const CURLOPT_TELNETOPTIONS: CURLoption = CURLOPTTYPE_OBJECTPOINT + 70; pub const CURLOPT_MAXCONNECTS: CURLoption = CURLOPTTYPE_LONG + 71; pub const CURLOPT_CLOSEPOLICY: CURLoption = CURLOPTTYPE_LONG + 72; pub const CURLOPT_FRESH_CONNECT: CURLoption = CURLOPTTYPE_LONG + 74; pub const CURLOPT_FORBID_REUSE: CURLoption = CURLOPTTYPE_LONG + 75; pub const CURLOPT_RANDOM_FILE: CURLoption = CURLOPTTYPE_OBJECTPOINT + 76; pub const CURLOPT_EGDSOCKET: CURLoption = CURLOPTTYPE_OBJECTPOINT + 77; pub const CURLOPT_CONNECTTIMEOUT: CURLoption = CURLOPTTYPE_LONG + 78; pub const CURLOPT_HEADERFUNCTION: CURLoption = CURLOPTTYPE_FUNCTIONPOINT + 79; pub const CURLOPT_HTTPGET: CURLoption = CURLOPTTYPE_LONG + 80; pub const CURLOPT_SSL_VERIFYHOST: CURLoption = CURLOPTTYPE_LONG + 81; pub const CURLOPT_COOKIEJAR: CURLoption = CURLOPTTYPE_OBJECTPOINT + 82; pub const CURLOPT_SSL_CIPHER_LIST: CURLoption = CURLOPTTYPE_OBJECTPOINT + 83; pub const CURLOPT_HTTP_VERSION: CURLoption = CURLOPTTYPE_LONG + 84; pub const CURLOPT_FTP_USE_EPSV: CURLoption = CURLOPTTYPE_LONG + 85; pub const CURLOPT_SSLCERTTYPE: CURLoption = CURLOPTTYPE_OBJECTPOINT + 86; pub const CURLOPT_SSLKEY: CURLoption = CURLOPTTYPE_OBJECTPOINT + 87; pub const CURLOPT_SSLKEYTYPE: CURLoption = CURLOPTTYPE_OBJECTPOINT + 88; pub const CURLOPT_SSLENGINE: CURLoption = CURLOPTTYPE_OBJECTPOINT + 89; pub const CURLOPT_SSLENGINE_DEFAULT: CURLoption = CURLOPTTYPE_LONG + 90; pub const CURLOPT_DNS_USE_GLOBAL_CACHE: CURLoption = CURLOPTTYPE_LONG + 91; pub const CURLOPT_DNS_CACHE_TIMEOUT: CURLoption = CURLOPTTYPE_LONG + 92; pub const CURLOPT_PREQUOTE: CURLoption = CURLOPTTYPE_OBJECTPOINT + 93; pub const CURLOPT_DEBUGFUNCTION: CURLoption = CURLOPTTYPE_FUNCTIONPOINT + 94; pub const CURLOPT_DEBUGDATA: CURLoption = CURLOPTTYPE_OBJECTPOINT + 95; pub const CURLOPT_COOKIESESSION: CURLoption = CURLOPTTYPE_LONG + 96; pub const CURLOPT_CAPATH: CURLoption = CURLOPTTYPE_OBJECTPOINT + 97; pub const CURLOPT_BUFFERSIZE: CURLoption = CURLOPTTYPE_LONG + 98; pub const CURLOPT_NOSIGNAL: CURLoption = CURLOPTTYPE_LONG + 99; pub const CURLOPT_SHARE: CURLoption = CURLOPTTYPE_OBJECTPOINT + 100; pub const CURLOPT_PROXYTYPE: CURLoption = CURLOPTTYPE_LONG + 101; pub const CURLOPT_ACCEPT_ENCODING: CURLoption = CURLOPTTYPE_OBJECTPOINT + 102; pub const CURLOPT_PRIVATE: CURLoption = CURLOPTTYPE_OBJECTPOINT + 103; pub const CURLOPT_HTTP200ALIASES: CURLoption = CURLOPTTYPE_OBJECTPOINT + 104; pub const CURLOPT_UNRESTRICTED_AUTH: CURLoption = CURLOPTTYPE_LONG + 105; pub const CURLOPT_FTP_USE_EPRT: CURLoption = CURLOPTTYPE_LONG + 106; pub const CURLOPT_HTTPAUTH: CURLoption = CURLOPTTYPE_LONG + 107; pub const CURLOPT_SSL_CTX_FUNCTION: CURLoption = CURLOPTTYPE_FUNCTIONPOINT + 108; pub const CURLOPT_SSL_CTX_DATA: CURLoption = CURLOPTTYPE_OBJECTPOINT + 109; pub const CURLOPT_FTP_CREATE_MISSING_DIRS: CURLoption = CURLOPTTYPE_LONG + 110; pub const CURLOPT_PROXYAUTH: CURLoption = CURLOPTTYPE_LONG + 111; pub const CURLOPT_FTP_RESPONSE_TIMEOUT: CURLoption = CURLOPTTYPE_LONG + 112; pub const CURLOPT_IPRESOLVE: CURLoption = CURLOPTTYPE_LONG + 113; pub const CURLOPT_MAXFILESIZE: CURLoption = CURLOPTTYPE_LONG + 114; pub const CURLOPT_INFILESIZE_LARGE: CURLoption = CURLOPTTYPE_OFF_T + 115; pub const CURLOPT_RESUME_FROM_LARGE: CURLoption = CURLOPTTYPE_OFF_T + 116; pub const CURLOPT_MAXFILESIZE_LARGE: CURLoption = CURLOPTTYPE_OFF_T + 117; pub const CURLOPT_NETRC_FILE: CURLoption = CURLOPTTYPE_OBJECTPOINT + 118; pub const CURLOPT_USE_SSL: CURLoption = CURLOPTTYPE_LONG + 119; pub const CURLOPT_POSTFIELDSIZE_LARGE: CURLoption = CURLOPTTYPE_OFF_T + 120; pub const CURLOPT_TCP_NODELAY: CURLoption = CURLOPTTYPE_LONG + 121; pub const CURLOPT_FTPSSLAUTH: CURLoption = CURLOPTTYPE_LONG + 129; pub const CURLOPT_IOCTLFUNCTION: CURLoption = CURLOPTTYPE_FUNCTIONPOINT + 130; pub const CURLOPT_IOCTLDATA: CURLoption = CURLOPTTYPE_OBJECTPOINT + 131; pub const CURLOPT_FTP_ACCOUNT: CURLoption = CURLOPTTYPE_OBJECTPOINT + 134; pub const CURLOPT_COOKIELIST: CURLoption = CURLOPTTYPE_OBJECTPOINT + 135; pub const CURLOPT_IGNORE_CONTENT_LENGTH: CURLoption = CURLOPTTYPE_LONG + 136; pub const CURLOPT_FTP_SKIP_PASV_IP: CURLoption = CURLOPTTYPE_LONG + 137; pub const CURLOPT_FTP_FILEMETHOD: CURLoption = CURLOPTTYPE_LONG + 138; pub const CURLOPT_LOCALPORT: CURLoption = CURLOPTTYPE_LONG + 139; pub const CURLOPT_LOCALPORTRANGE: CURLoption = CURLOPTTYPE_LONG + 140; pub const CURLOPT_CONNECT_ONLY: CURLoption = CURLOPTTYPE_LONG + 141; pub const CURLOPT_CONV_FROM_NETWORK_FUNCTION: CURLoption = CURLOPTTYPE_FUNCTIONPOINT + 142; pub const CURLOPT_CONV_TO_NETWORK_FUNCTION: CURLoption = CURLOPTTYPE_FUNCTIONPOINT + 143; pub const CURLOPT_CONV_FROM_UTF8_FUNCTION: CURLoption = CURLOPTTYPE_FUNCTIONPOINT + 144; pub const CURLOPT_MAX_SEND_SPEED_LARGE: CURLoption = CURLOPTTYPE_OFF_T + 145; pub const CURLOPT_MAX_RECV_SPEED_LARGE: CURLoption = CURLOPTTYPE_OFF_T + 146; pub const CURLOPT_FTP_ALTERNATIVE_TO_USER: CURLoption = CURLOPTTYPE_OBJECTPOINT + 147; pub const CURLOPT_SOCKOPTFUNCTION: CURLoption = CURLOPTTYPE_FUNCTIONPOINT + 148; pub const CURLOPT_SOCKOPTDATA: CURLoption = CURLOPTTYPE_OBJECTPOINT + 149; pub const CURLOPT_SSL_SESSIONID_CACHE: CURLoption = CURLOPTTYPE_LONG + 150; pub const CURLOPT_SSH_AUTH_TYPES: CURLoption = CURLOPTTYPE_LONG + 151; pub const CURLOPT_SSH_PUBLIC_KEYFILE: CURLoption = CURLOPTTYPE_OBJECTPOINT + 152; pub const CURLOPT_SSH_PRIVATE_KEYFILE: CURLoption = CURLOPTTYPE_OBJECTPOINT + 153; pub const CURLOPT_FTP_SSL_CCC: CURLoption = CURLOPTTYPE_LONG + 154; pub const CURLOPT_TIMEOUT_MS: CURLoption = CURLOPTTYPE_LONG + 155; pub const CURLOPT_CONNECTTIMEOUT_MS: CURLoption = CURLOPTTYPE_LONG + 156; pub const CURLOPT_HTTP_TRANSFER_DECODING: CURLoption = CURLOPTTYPE_LONG + 157; pub const CURLOPT_HTTP_CONTENT_DECODING: CURLoption = CURLOPTTYPE_LONG + 158; pub const CURLOPT_NEW_FILE_PERMS: CURLoption = CURLOPTTYPE_LONG + 159; pub const CURLOPT_NEW_DIRECTORY_PERMS: CURLoption = CURLOPTTYPE_LONG + 160; pub const CURLOPT_POSTREDIR: CURLoption = CURLOPTTYPE_LONG + 161; pub const CURLOPT_SSH_HOST_PUBLIC_KEY_MD5: CURLoption = CURLOPTTYPE_OBJECTPOINT + 162; pub const CURLOPT_OPENSOCKETFUNCTION: CURLoption = CURLOPTTYPE_FUNCTIONPOINT + 163; pub const CURLOPT_OPENSOCKETDATA: CURLoption = CURLOPTTYPE_OBJECTPOINT + 164; pub const CURLOPT_COPYPOSTFIELDS: CURLoption = CURLOPTTYPE_OBJECTPOINT + 165; pub const CURLOPT_PROXY_TRANSFER_MODE: CURLoption = CURLOPTTYPE_LONG + 166; pub const CURLOPT_SEEKFUNCTION: CURLoption = CURLOPTTYPE_FUNCTIONPOINT + 167; pub const CURLOPT_SEEKDATA: CURLoption = CURLOPTTYPE_OBJECTPOINT + 168; pub const CURLOPT_CRLFILE: CURLoption = CURLOPTTYPE_OBJECTPOINT + 169; pub const CURLOPT_ISSUERCERT: CURLoption = CURLOPTTYPE_OBJECTPOINT + 170; pub const CURLOPT_ADDRESS_SCOPE: CURLoption = CURLOPTTYPE_LONG + 171; pub const CURLOPT_CERTINFO: CURLoption = CURLOPTTYPE_LONG + 172; pub const CURLOPT_USERNAME: CURLoption = CURLOPTTYPE_OBJECTPOINT + 173; pub const CURLOPT_PASSWORD: CURLoption = CURLOPTTYPE_OBJECTPOINT + 174; pub const CURLOPT_PROXYUSERNAME: CURLoption = CURLOPTTYPE_OBJECTPOINT + 175; pub const CURLOPT_PROXYPASSWORD: CURLoption = CURLOPTTYPE_OBJECTPOINT + 176; pub const CURLOPT_NOPROXY: CURLoption = CURLOPTTYPE_OBJECTPOINT + 177; pub const CURLOPT_TFTP_BLKSIZE: CURLoption = CURLOPTTYPE_LONG + 178; pub const CURLOPT_SOCKS5_GSSAPI_SERVICE: CURLoption = CURLOPTTYPE_OBJECTPOINT + 179; pub const CURLOPT_SOCKS5_GSSAPI_NEC: CURLoption = CURLOPTTYPE_LONG + 180; pub const CURLOPT_PROTOCOLS: CURLoption = CURLOPTTYPE_LONG + 181; pub const CURLOPT_REDIR_PROTOCOLS: CURLoption = CURLOPTTYPE_LONG + 182; pub const CURLOPT_SSH_KNOWNHOSTS: CURLoption = CURLOPTTYPE_OBJECTPOINT + 183; pub const CURLOPT_SSH_KEYFUNCTION: CURLoption = CURLOPTTYPE_FUNCTIONPOINT + 184; pub const CURLOPT_SSH_KEYDATA: CURLoption = CURLOPTTYPE_OBJECTPOINT + 185; pub const CURLOPT_MAIL_FROM: CURLoption = CURLOPTTYPE_OBJECTPOINT + 186; pub const CURLOPT_MAIL_RCPT: CURLoption = CURLOPTTYPE_OBJECTPOINT + 187; pub const CURLOPT_FTP_USE_PRET: CURLoption = CURLOPTTYPE_LONG + 188; pub const CURLOPT_RTSP_REQUEST: CURLoption = CURLOPTTYPE_LONG + 189; pub const CURLOPT_RTSP_SESSION_ID: CURLoption = CURLOPTTYPE_OBJECTPOINT + 190; pub const CURLOPT_RTSP_STREAM_URI: CURLoption = CURLOPTTYPE_OBJECTPOINT + 191; pub const CURLOPT_RTSP_TRANSPORT: CURLoption = CURLOPTTYPE_OBJECTPOINT + 192; pub const CURLOPT_RTSP_CLIENT_CSEQ: CURLoption = CURLOPTTYPE_LONG + 193; pub const CURLOPT_RTSP_SERVER_CSEQ: CURLoption = CURLOPTTYPE_LONG + 194; pub const CURLOPT_INTERLEAVEDATA: CURLoption = CURLOPTTYPE_OBJECTPOINT + 195; pub const CURLOPT_INTERLEAVEFUNCTION: CURLoption = CURLOPTTYPE_FUNCTIONPOINT + 196; pub const CURLOPT_WILDCARDMATCH: CURLoption = CURLOPTTYPE_LONG + 197; pub const CURLOPT_CHUNK_BGN_FUNCTION: CURLoption = CURLOPTTYPE_FUNCTIONPOINT + 198; pub const CURLOPT_CHUNK_END_FUNCTION: CURLoption = CURLOPTTYPE_FUNCTIONPOINT + 199; pub const CURLOPT_FNMATCH_FUNCTION: CURLoption = CURLOPTTYPE_FUNCTIONPOINT + 200; pub const CURLOPT_CHUNK_DATA: CURLoption = CURLOPTTYPE_OBJECTPOINT + 201; pub const CURLOPT_FNMATCH_DATA: CURLoption = CURLOPTTYPE_OBJECTPOINT + 202; pub const CURLOPT_RESOLVE: CURLoption = CURLOPTTYPE_OBJECTPOINT + 203; pub const CURLOPT_TLSAUTH_USERNAME: CURLoption = CURLOPTTYPE_OBJECTPOINT + 204; pub const CURLOPT_TLSAUTH_PASSWORD: CURLoption = CURLOPTTYPE_OBJECTPOINT + 205; pub const CURLOPT_TLSAUTH_TYPE: CURLoption = CURLOPTTYPE_OBJECTPOINT + 206; pub const CURLOPT_TRANSFER_ENCODING: CURLoption = CURLOPTTYPE_LONG + 207; pub const CURLOPT_CLOSESOCKETFUNCTION: CURLoption = CURLOPTTYPE_FUNCTIONPOINT + 208; pub const CURLOPT_CLOSESOCKETDATA: CURLoption = CURLOPTTYPE_OBJECTPOINT + 209; pub const CURLOPT_GSSAPI_DELEGATION: CURLoption = CURLOPTTYPE_LONG + 210; // pub const CURLOPT_DNS_SERVERS: CURLoption = CURLOPTTYPE_OBJECTPOINT + 211; // pub const CURLOPT_ACCEPTTIMEOUT_MS: CURLoption = CURLOPTTYPE_LONG + 212; pub const CURLOPT_TCP_KEEPALIVE: CURLoption = CURLOPTTYPE_LONG + 213; pub const CURLOPT_TCP_KEEPIDLE: CURLoption = CURLOPTTYPE_LONG + 214; pub const CURLOPT_TCP_KEEPINTVL: CURLoption = CURLOPTTYPE_LONG + 215; pub const CURLOPT_SSL_OPTIONS: CURLoption = CURLOPTTYPE_LONG + 216; // pub const CURLOPT_MAIL_AUTH: CURLoption = CURLOPTTYPE_OBJECTPOINT + 217; // pub const CURLOPT_SASL_IR: CURLoption = CURLOPTTYPE_LONG + 218; // pub const CURLOPT_XFERINFOFUNCTION: CURLoption = CURLOPTTYPE_FUNCTIONPOINT + 219; // pub const CURLOPT_XOAUTH2_BEARER: CURLoption = CURLOPTTYPE_OBJECTPOINT + 220; // pub const CURLOPT_DNS_INTERFACE: CURLoption = CURLOPTTYPE_OBJECTPOINT + 221; // pub const CURLOPT_DNS_LOCAL_IP4: CURLoption = CURLOPTTYPE_OBJECTPOINT + 222; // pub const CURLOPT_DNS_LOCAL_IP6: CURLoption = CURLOPTTYPE_OBJECTPOINT + 223; // pub const CURLOPT_LOGIN_OPTIONS: CURLoption = CURLOPTTYPE_OBJECTPOINT + 224; pub const CURLOPT_UNIX_SOCKET_PATH: CURLoption = CURLOPTTYPE_OBJECTPOINT + 231; pub const CURL_IPRESOLVE_WHATEVER: c_int = 0; pub const CURL_IPRESOLVE_V4: c_int = 1; pub const CURL_IPRESOLVE_V6: c_int = 2; pub const CURLSSLOPT_ALLOW_BEAST: c_long = 1 << 0; pub const CURLSSLOPT_NO_REVOKE: c_long = 1 << 1; /// These enums are for use with the CURLOPT_HTTP_VERSION option. /// /// Setting this means we don't care, and that we'd like the library to choose /// the best possible for us! pub const CURL_HTTP_VERSION_NONE: c_int = 0; /// Please use HTTP 1.0 in the request pub const CURL_HTTP_VERSION_1_0: c_int = 1; /// Please use HTTP 1.1 in the request pub const CURL_HTTP_VERSION_1_1: c_int = 2; /// Please use HTTP 2 in the request /// (Added in CURL 7.33.0) pub const CURL_HTTP_VERSION_2_0: c_int = 3; /// Use version 2 for HTTPS, version 1.1 for HTTP /// (Added in CURL 7.47.0) pub const CURL_HTTP_VERSION_2TLS: c_int = 4; /// Please use HTTP 2 without HTTP/1.1 Upgrade /// (Added in CURL 7.49.0) pub const CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE: c_int = 5; // Note that the type here is wrong, it's just intended to just be an enum. pub const CURL_SSLVERSION_DEFAULT: CURLoption = 0; pub const CURL_SSLVERSION_TLSv1: CURLoption = 1; pub const CURL_SSLVERSION_SSLv2: CURLoption = 2; pub const CURL_SSLVERSION_SSLv3: CURLoption = 3; // pub const CURL_SSLVERSION_TLSv1_0: CURLoption = 4; // pub const CURL_SSLVERSION_TLSv1_1: CURLoption = 5; // pub const CURL_SSLVERSION_TLSv1_2: CURLoption = 6; pub const CURLOPT_READDATA: CURLoption = CURLOPT_INFILE; pub const CURLOPT_WRITEDATA: CURLoption = CURLOPT_FILE; pub const CURLOPT_HEADERDATA: CURLoption = CURLOPT_WRITEHEADER; pub type curl_TimeCond = __enum_ty; pub const CURL_TIMECOND_NONE: curl_TimeCond = 0; pub const CURL_TIMECOND_IFMODSINCE: curl_TimeCond = 1; pub const CURL_TIMECOND_IFUNMODSINCE: curl_TimeCond = 2; pub const CURL_TIMECOND_LASTMOD: curl_TimeCond = 3; pub type CURLformoption = __enum_ty; pub const CURLFORM_NOTHING: CURLformoption = 0; pub const CURLFORM_COPYNAME: CURLformoption = 1; pub const CURLFORM_PTRNAME: CURLformoption = 2; pub const CURLFORM_NAMELENGTH: CURLformoption = 3; pub const CURLFORM_COPYCONTENTS: CURLformoption = 4; pub const CURLFORM_PTRCONTENTS: CURLformoption = 5; pub const CURLFORM_CONTENTSLENGTH: CURLformoption = 6; pub const CURLFORM_FILECONTENT: CURLformoption = 7; pub const CURLFORM_ARRAY: CURLformoption = 8; pub const CURLFORM_OBSOLETE: CURLformoption = 9; pub const CURLFORM_FILE: CURLformoption = 10; pub const CURLFORM_BUFFER: CURLformoption = 11; pub const CURLFORM_BUFFERPTR: CURLformoption = 12; pub const CURLFORM_BUFFERLENGTH: CURLformoption = 13; pub const CURLFORM_CONTENTTYPE: CURLformoption = 14; pub const CURLFORM_CONTENTHEADER: CURLformoption = 15; pub const CURLFORM_FILENAME: CURLformoption = 16; pub const CURLFORM_END: CURLformoption = 17; pub const CURLFORM_STREAM: CURLformoption = 19; pub type CURLFORMcode = __enum_ty; pub const CURL_FORMADD_OK: CURLFORMcode = 0; pub const CURL_FORMADD_MEMORY: CURLFORMcode = 1; pub const CURL_FORMADD_OPTION_TWICE: CURLFORMcode = 2; pub const CURL_FORMADD_NULL: CURLFORMcode = 3; pub const CURL_FORMADD_UNKNOWN_OPTION: CURLFORMcode = 4; pub const CURL_FORMADD_INCOMPLETE: CURLFORMcode = 5; pub const CURL_FORMADD_ILLEGAL_ARRAY: CURLFORMcode = 6; pub const CURL_FORMADD_DISABLED: CURLFORMcode = 7; #[repr(C)] pub struct curl_forms { pub option: CURLformoption, pub value: *const c_char, } pub type curl_formget_callback = extern fn(*mut c_void, *const c_char, size_t) -> size_t; #[repr(C)] pub struct curl_slist { pub data: *mut c_char, pub next: *mut curl_slist, } #[repr(C)] pub struct curl_certinfo { pub num_of_certs: c_int, pub certinfo: *mut *mut curl_slist, } // pub type curl_sslbackend = __enum_ty; // pub const CURLSSLBACKEND_NONE: curl_sslbackend = 0; // pub const CURLSSLBACKEND_OPENSSL: curl_sslbackend = 1; // pub const CURLSSLBACKEND_GNUTLS: curl_sslbackend = 2; // pub const CURLSSLBACKEND_NSS: curl_sslbackend = 3; // pub const CURLSSLBACKEND_QSOSSL: curl_sslbackend = 4; // pub const CURLSSLBACKEND_GSKIT: curl_sslbackend = 5; // pub const CURLSSLBACKEND_POLARSSL: curl_sslbackend = 6; // pub const CURLSSLBACKEND_CYASSL: curl_sslbackend = 7; // pub const CURLSSLBACKEND_SCHANNEL: curl_sslbackend = 8; // pub const CURLSSLBACKEND_DARWINSSL: curl_sslbackend = 9; // #[repr(C)] // pub struct curl_tlssessioninfo { // pub backend: curl_sslbackend, // pub internals: *mut c_void, // } pub const CURLINFO_STRING: CURLINFO = 0x100000; pub const CURLINFO_LONG: CURLINFO = 0x200000; pub const CURLINFO_DOUBLE: CURLINFO = 0x300000; pub const CURLINFO_SLIST: CURLINFO = 0x400000; pub const CURLINFO_MASK: CURLINFO = 0x0fffff; pub const CURLINFO_TYPEMASK: CURLINFO = 0xf00000; pub const CURLINFO_EFFECTIVE_URL: CURLINFO = CURLINFO_STRING + 1; pub const CURLINFO_RESPONSE_CODE: CURLINFO = CURLINFO_LONG + 2; pub const CURLINFO_TOTAL_TIME: CURLINFO = CURLINFO_DOUBLE + 3; pub const CURLINFO_NAMELOOKUP_TIME: CURLINFO = CURLINFO_DOUBLE + 4; pub const CURLINFO_CONNECT_TIME: CURLINFO = CURLINFO_DOUBLE + 5; pub const CURLINFO_PRETRANSFER_TIME: CURLINFO = CURLINFO_DOUBLE + 6; pub const CURLINFO_SIZE_UPLOAD: CURLINFO = CURLINFO_DOUBLE + 7; pub const CURLINFO_SIZE_DOWNLOAD: CURLINFO = CURLINFO_DOUBLE + 8; pub const CURLINFO_SPEED_DOWNLOAD: CURLINFO = CURLINFO_DOUBLE + 9; pub const CURLINFO_SPEED_UPLOAD: CURLINFO = CURLINFO_DOUBLE + 10; pub const CURLINFO_HEADER_SIZE: CURLINFO = CURLINFO_LONG + 11; pub const CURLINFO_REQUEST_SIZE: CURLINFO = CURLINFO_LONG + 12; pub const CURLINFO_SSL_VERIFYRESULT: CURLINFO = CURLINFO_LONG + 13; pub const CURLINFO_FILETIME: CURLINFO = CURLINFO_LONG + 14; pub const CURLINFO_CONTENT_LENGTH_DOWNLOAD: CURLINFO = CURLINFO_DOUBLE + 15; pub const CURLINFO_CONTENT_LENGTH_UPLOAD: CURLINFO = CURLINFO_DOUBLE + 16; pub const CURLINFO_STARTTRANSFER_TIME: CURLINFO = CURLINFO_DOUBLE + 17; pub const CURLINFO_CONTENT_TYPE: CURLINFO = CURLINFO_STRING + 18; pub const CURLINFO_REDIRECT_TIME: CURLINFO = CURLINFO_DOUBLE + 19; pub const CURLINFO_REDIRECT_COUNT: CURLINFO = CURLINFO_LONG + 20; pub const CURLINFO_PRIVATE: CURLINFO = CURLINFO_STRING + 21; pub const CURLINFO_HTTP_CONNECTCODE: CURLINFO = CURLINFO_LONG + 22; pub const CURLINFO_HTTPAUTH_AVAIL: CURLINFO = CURLINFO_LONG + 23; pub const CURLINFO_PROXYAUTH_AVAIL: CURLINFO = CURLINFO_LONG + 24; pub const CURLINFO_OS_ERRNO: CURLINFO = CURLINFO_LONG + 25; pub const CURLINFO_NUM_CONNECTS: CURLINFO = CURLINFO_LONG + 26; pub const CURLINFO_SSL_ENGINES: CURLINFO = CURLINFO_SLIST + 27; pub const CURLINFO_COOKIELIST: CURLINFO = CURLINFO_SLIST + 28; pub const CURLINFO_LASTSOCKET: CURLINFO = CURLINFO_LONG + 29; pub const CURLINFO_FTP_ENTRY_PATH: CURLINFO = CURLINFO_STRING + 30; pub const CURLINFO_REDIRECT_URL: CURLINFO = CURLINFO_STRING + 31; pub const CURLINFO_PRIMARY_IP: CURLINFO = CURLINFO_STRING + 32; pub const CURLINFO_APPCONNECT_TIME: CURLINFO = CURLINFO_DOUBLE + 33; pub const CURLINFO_CERTINFO: CURLINFO = CURLINFO_SLIST + 34; pub const CURLINFO_CONDITION_UNMET: CURLINFO = CURLINFO_LONG + 35; pub const CURLINFO_RTSP_SESSION_ID: CURLINFO = CURLINFO_STRING + 36; pub const CURLINFO_RTSP_CLIENT_CSEQ: CURLINFO = CURLINFO_LONG + 37; pub const CURLINFO_RTSP_SERVER_CSEQ: CURLINFO = CURLINFO_LONG + 38; pub const CURLINFO_RTSP_CSEQ_RECV: CURLINFO = CURLINFO_LONG + 39; pub const CURLINFO_PRIMARY_PORT: CURLINFO = CURLINFO_LONG + 40; pub const CURLINFO_LOCAL_IP: CURLINFO = CURLINFO_STRING + 41; pub const CURLINFO_LOCAL_PORT: CURLINFO = CURLINFO_LONG + 42; // pub const CURLINFO_TLS_SESSION: CURLINFO = CURLINFO_SLIST + 43; pub type curl_closepolicy = __enum_ty; pub const CURLCLOSEPOLICY_NONE: curl_closepolicy = 0; pub const CURLCLOSEPOLICY_OLDEST: curl_closepolicy = 1; pub const CURLCLOSEPOLICY_LEAST_RECENTLY_USED: curl_closepolicy = 2; pub const CURLCLOSEPOLICY_LEAST_TRAFFIC: curl_closepolicy = 3; pub const CURLCLOSEPOLICY_SLOWEST: curl_closepolicy = 4; pub const CURLCLOSEPOLICY_CALLBACK: curl_closepolicy = 5; pub const CURL_GLOBAL_SSL: c_long = 1 << 0; pub const CURL_GLOBAL_WIN32: c_long = 1 << 1; pub const CURL_GLOBAL_ALL: c_long = CURL_GLOBAL_SSL | CURL_GLOBAL_WIN32; pub const CURL_GLOBAL_NOTHING: c_long = 0; pub const CURL_GLOBAL_DEFAULT: c_long = CURL_GLOBAL_ALL; // pub const CURL_GLOBAL_ACK_EINTR: c_long = 1 << 2; pub type curl_lock_data = __enum_ty; pub const CURL_LOCK_DATA_NONE: curl_lock_data = 0; pub const CURL_LOCK_DATA_SHARE: curl_lock_data = 1; pub const CURL_LOCK_DATA_COOKIE: curl_lock_data = 2; pub const CURL_LOCK_DATA_DNS: curl_lock_data = 3; pub const CURL_LOCK_DATA_SSL_SESSION: curl_lock_data = 4; pub const CURL_LOCK_DATA_CONNECT: curl_lock_data = 5; pub type curl_lock_access = __enum_ty; pub const CURL_LOCK_ACCESS_NONE: curl_lock_access = 0; pub const CURL_LOCK_ACCESS_SHARED: curl_lock_access = 1; pub const CURL_LOCK_ACCESS_SINGLE: curl_lock_access = 2; pub type curl_lock_function = extern fn(*mut CURL, curl_lock_data, curl_lock_access, *mut c_void); pub type curl_unlock_function = extern fn(*mut CURL, curl_lock_data, *mut c_void); pub enum CURLSH {} pub type CURLSHcode = __enum_ty; pub const CURLSHE_OK: CURLSHcode = 0; pub const CURLSHE_BAD_OPTION: CURLSHcode = 1; pub const CURLSHE_IN_USE: CURLSHcode = 2; pub const CURLSHE_INVALID: CURLSHcode = 3; pub const CURLSHE_NOMEM: CURLSHcode = 4; // pub const CURLSHE_NOT_BUILT_IN: CURLSHcode = 5; pub type CURLSHoption = __enum_ty; pub const CURLSHOPT_NONE: CURLSHoption = 0; pub const CURLSHOPT_SHARE: CURLSHoption = 1; pub const CURLSHOPT_UNSHARE: CURLSHoption = 2; pub const CURLSHOPT_LOCKFUNC: CURLSHoption = 3; pub const CURLSHOPT_UNLOCKFUNC: CURLSHoption = 4; pub const CURLSHOPT_USERDATA: CURLSHoption = 5; pub const CURLVERSION_FIRST: CURLversion = 0; pub const CURLVERSION_SECOND: CURLversion = 1; pub const CURLVERSION_THIRD: CURLversion = 2; pub const CURLVERSION_FOURTH: CURLversion = 3; pub const CURLVERSION_NOW: CURLversion = CURLVERSION_FOURTH; #[repr(C)] pub struct curl_version_info_data { pub age: CURLversion, pub version: *const c_char, pub version_num: c_uint, pub host: *const c_char, pub features: c_int, pub ssl_version: *const c_char, pub ssl_version_num: c_long, pub libz_version: *const c_char, pub protocols: *const *const c_char, pub ares: *const c_char, pub ares_num: c_int, pub libidn: *const c_char, pub iconv_ver_num: c_int, pub libssh_version: *const c_char, } pub const CURL_VERSION_IPV6: c_int = 1 << 0; pub const CURL_VERSION_KERBEROS4: c_int = 1 << 1; pub const CURL_VERSION_SSL: c_int = 1 << 2; pub const CURL_VERSION_LIBZ: c_int = 1 << 3; pub const CURL_VERSION_NTLM: c_int = 1 << 4; pub const CURL_VERSION_GSSNEGOTIATE: c_int = 1 << 5; pub const CURL_VERSION_DEBUG: c_int = 1 << 6; pub const CURL_VERSION_ASYNCHDNS: c_int = 1 << 7; pub const CURL_VERSION_SPNEGO: c_int = 1 << 8; pub const CURL_VERSION_LARGEFILE: c_int = 1 << 9; pub const CURL_VERSION_IDN: c_int = 1 << 10; pub const CURL_VERSION_SSPI: c_int = 1 << 11; pub const CURL_VERSION_CONV: c_int = 1 << 12; pub const CURL_VERSION_CURLDEBUG: c_int = 1 << 13; pub const CURL_VERSION_TLSAUTH_SRP: c_int = 1 << 14; pub const CURL_VERSION_NTLM_WB: c_int = 1 << 15; // pub const CURL_VERSION_HTTP2: c_int = 1 << 16; pub const CURL_VERSION_UNIX_SOCKETS: c_int = 1 << 19; pub const CURLPAUSE_RECV: c_int = 1 << 0; pub const CURLPAUSE_RECV_CONT: c_int = 0; pub const CURLPAUSE_SEND: c_int = 1 << 2; pub const CURLPAUSE_SEND_CONT: c_int = 0; pub enum CURLM {} pub type CURLMcode = c_int; pub const CURLM_CALL_MULTI_PERFORM: CURLMcode = -1; pub const CURLM_OK: CURLMcode = 0; pub const CURLM_BAD_HANDLE: CURLMcode = 1; pub const CURLM_BAD_EASY_HANDLE: CURLMcode = 2; pub const CURLM_OUT_OF_MEMORY: CURLMcode = 3; pub const CURLM_INTERNAL_ERROR: CURLMcode = 4; pub const CURLM_BAD_SOCKET: CURLMcode = 5; pub const CURLM_UNKNOWN_OPTION: CURLMcode = 6; // pub const CURLM_ADDED_ALREADY: CURLMcode = 7; pub type CURLMSG = __enum_ty; pub const CURLMSG_NONE: CURLMSG = 0; pub const CURLMSG_DONE: CURLMSG = 1; #[repr(C)] pub struct CURLMsg { pub msg: CURLMSG, pub easy_handle: *mut CURL, pub data: *mut c_void, } pub const CURL_WAIT_POLLIN: c_short = 0x1; pub const CURL_WAIT_POLLPRI: c_short = 0x2; pub const CURL_WAIT_POLLOUT: c_short = 0x4; #[repr(C)] pub struct curl_waitfd { pub fd: curl_socket_t, pub events: c_short, pub revents: c_short, } pub const CURL_POLL_NONE: c_int = 0; pub const CURL_POLL_IN: c_int = 1; pub const CURL_POLL_OUT: c_int = 2; pub const CURL_POLL_INOUT: c_int = 3; pub const CURL_POLL_REMOVE: c_int = 4; pub const CURL_CSELECT_IN: c_int = 1; pub const CURL_CSELECT_OUT: c_int = 2; pub const CURL_CSELECT_ERR: c_int = 4; pub const CURL_SOCKET_TIMEOUT: curl_socket_t = CURL_SOCKET_BAD; pub type curl_socket_callback = extern fn(*mut CURL, curl_socket_t, c_int, *mut c_void, *mut c_void) -> c_int; pub type curl_multi_timer_callback = extern fn(*mut CURLM, c_long, *mut c_void) -> c_int; pub type CURLMoption = __enum_ty; pub const CURLMOPT_SOCKETFUNCTION: CURLMoption = CURLOPTTYPE_FUNCTIONPOINT + 1; pub const CURLMOPT_SOCKETDATA: CURLMoption = CURLOPTTYPE_OBJECTPOINT + 2; pub const CURLMOPT_PIPELINING: CURLMoption = CURLOPTTYPE_LONG + 3; pub const CURLMOPT_TIMERFUNCTION: CURLMoption = CURLOPTTYPE_FUNCTIONPOINT + 4; pub const CURLMOPT_TIMERDATA: CURLMoption = CURLOPTTYPE_OBJECTPOINT + 5; // pub const CURLMOPT_MAXCONNECTS: CURLMoption = CURLOPTTYPE_LONG + 6; // pub const CURLMOPT_MAX_HOST_CONNECTIONS: CURLMoption = CURLOPTTYPE_LONG + 7; // pub const CURLMOPT_MAX_PIPELINE_LENGTH: CURLMoption = CURLOPTTYPE_LONG + 8; // pub const CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE: CURLMoption = CURLOPTTYPE_OFF_T + 9; // pub const CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE: CURLMoption = CURLOPTTYPE_OFF_T + 10; // pub const CURLMOPT_PIPELINING_SITE_BL: CURLMoption = CURLOPTTYPE_OBJECTPOINT + 11; // pub const CURLMOPT_PIPELINING_SERVER_BL: CURLMoption = CURLOPTTYPE_OBJECTPOINT + 12; // pub const CURLMOPT_MAX_TOTAL_CONNECTIONS: CURLMoption = CURLOPTTYPE_LONG + 13; pub const CURL_ERROR_SIZE: usize = 256; pub type curl_opensocket_callback = extern fn(*mut c_void, curlsocktype, *mut curl_sockaddr) -> curl_socket_t; pub type curlsocktype = __enum_ty; pub const CURLSOCKTYPE_IPCXN: curlsocktype = 0; pub const CURLSOCKTYPE_ACCEPT: curlsocktype = 1; pub const CURLSOCKTYPE_LAST: curlsocktype = 2; #[repr(C)] pub struct curl_sockaddr { pub family: c_int, pub socktype: c_int, pub protocol: c_int, pub addrlen: c_uint, #[cfg(unix)] pub addr: libc::sockaddr, #[cfg(windows)] pub addr: SOCKADDR, } extern { pub fn curl_formadd(httppost: *mut *mut curl_httppost, last_post: *mut *mut curl_httppost, ...) -> CURLFORMcode; pub fn curl_formget(form: *mut curl_httppost, arg: *mut c_void, append: curl_formget_callback) -> c_int; pub fn curl_formfree(form: *mut curl_httppost); pub fn curl_version() -> *mut c_char; pub fn curl_easy_escape(handle: *mut CURL, string: *const c_char, length: c_int) -> *mut c_char; pub fn curl_easy_unescape(handle: *mut CURL, string: *const c_char, length: c_int, outlength: *mut c_int) -> *mut c_char; pub fn curl_free(p: *mut c_void); pub fn curl_global_init(flags: c_long) -> CURLcode; pub fn curl_global_init_mem(flags: c_long, m: curl_malloc_callback, f: curl_free_callback, r: curl_realloc_callback, s: curl_strdup_callback, c: curl_calloc_callback) -> CURLcode; pub fn curl_global_cleanup(); pub fn curl_slist_append(list: *mut curl_slist, val: *const c_char) -> *mut curl_slist; pub fn curl_slist_free_all(list: *mut curl_slist); pub fn curl_getdate(p: *const c_char, _: *const time_t) -> time_t; pub fn curl_share_init() -> *mut CURLSH; pub fn curl_share_setopt(sh: *mut CURLSH, opt: CURLSHoption, ...) -> CURLSHcode; pub fn curl_share_cleanup(sh: *mut CURLSH) -> CURLSHcode; pub fn curl_version_info(t: CURLversion) -> *mut curl_version_info_data; pub fn curl_easy_strerror(code: CURLcode) -> *const c_char; pub fn curl_share_strerror(code: CURLSHcode) -> *const c_char; pub fn curl_easy_pause(handle: *mut CURL, bitmask: c_int) -> CURLcode; pub fn curl_easy_init() -> *mut CURL; pub fn curl_easy_setopt(curl: *mut CURL, option: CURLoption, ...) -> CURLcode; pub fn curl_easy_perform(curl: *mut CURL) -> CURLcode; pub fn curl_easy_cleanup(curl: *mut CURL); pub fn curl_easy_getinfo(curl: *mut CURL, info: CURLINFO, ...) -> CURLcode; pub fn curl_easy_duphandle(curl: *mut CURL) -> *mut CURL; pub fn curl_easy_reset(curl: *mut CURL); pub fn curl_easy_recv(curl: *mut CURL, buffer: *mut c_void, buflen: size_t, n: *mut size_t) -> CURLcode; pub fn curl_easy_send(curl: *mut CURL, buffer: *const c_void, buflen: size_t, n: *mut size_t) -> CURLcode; pub fn curl_multi_init() -> *mut CURLM; pub fn curl_multi_add_handle(multi_handle: *mut CURLM, curl_handle: *mut CURL) -> CURLMcode; pub fn curl_multi_remove_handle(multi_handle: *mut CURLM, curl_handle: *mut CURL) -> CURLMcode; pub fn curl_multi_fdset(multi_handle: *mut CURLM, read_fd_set: *mut fd_set, write_fd_set: *mut fd_set, exc_fd_set: *mut fd_set, max_fd: *mut c_int) -> CURLMcode; pub fn curl_multi_wait(multi_handle: *mut CURLM, extra_fds: *mut curl_waitfd, extra_nfds: c_uint, timeout_ms: c_int, ret: *mut c_int) -> CURLMcode; pub fn curl_multi_perform(multi_handle: *mut CURLM, running_handles: *mut c_int) -> CURLMcode; pub fn curl_multi_cleanup(multi_handle: *mut CURLM) -> CURLMcode; pub fn curl_multi_info_read(multi_handle: *mut CURLM, msgs_in_queue: *mut c_int) -> *mut CURLMsg; pub fn curl_multi_strerror(code: CURLMcode) -> *const c_char; pub fn curl_multi_socket(multi_handle: *mut CURLM, s: curl_socket_t, running_handles: *mut c_int) -> CURLMcode; pub fn curl_multi_socket_action(multi_handle: *mut CURLM, s: curl_socket_t, ev_bitmask: c_int, running_handles: *mut c_int) -> CURLMcode; pub fn curl_multi_socket_all(multi_handle: *mut CURLM, running_handles: *mut c_int) -> CURLMcode; pub fn curl_multi_timeout(multi_handle: *mut CURLM, milliseconds: *mut c_long) -> CURLMcode; pub fn curl_multi_setopt(multi_handle: *mut CURLM, option: CURLMoption, ...) -> CURLMcode; pub fn curl_multi_assign(multi_handle: *mut CURLM, sockfd: curl_socket_t, sockp: *mut c_void) -> CURLMcode; } vendor/docopt-0.8.3/0000755000000000000000000000000013264166600013011 5ustar rootrootvendor/docopt-0.8.3/.cargo-checksum.json0000644000000000000000000000013113264166600016650 0ustar rootroot{"files":{},"package":"d8acd393692c503b168471874953a2531df0e9ab77d0b6bbc582395743300a4a"}vendor/docopt-0.8.3/.travis.yml0000644000000000000000000000042513264166600015123 0ustar rootrootlanguage: rust rust: - 1.15.0 - stable - beta - nightly script: - cargo build --verbose - cargo test --verbose - cargo doc - if [ "$TRAVIS_RUST_VERSION" = "nightly" ]; then cd docopt_macros; cargo build --verbose; cargo test --verbose; fi vendor/docopt-0.8.3/COPYING0000644000000000000000000000017613264166600014050 0ustar rootrootThis project is dual-licensed under the Unlicense and MIT licenses. You may use this code under the terms of either license. vendor/docopt-0.8.3/Cargo.toml0000644000000000000000000000236413264166600014746 0ustar rootroot# 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 = "docopt" version = "0.8.3" authors = ["Andrew Gallant "] description = "Command line argument parsing." homepage = "https://github.com/docopt/docopt.rs" documentation = "http://burntsushi.net/rustdoc/docopt/" readme = "README.md" keywords = ["docopt", "argument", "command", "argv"] categories = ["command-line-interface"] license = "Unlicense/MIT" repository = "https://github.com/docopt/docopt.rs" [lib] name = "docopt" [[bin]] name = "docopt-wordlist" path = "src/wordlist.rs" test = false doc = false [dependencies.lazy_static] version = "1" [dependencies.regex] version = "0.2" [dependencies.serde] version = "1.0" [dependencies.serde_derive] version = "1.0" [dependencies.strsim] version = "0.6" vendor/docopt-0.8.3/LICENSE-MIT0000644000000000000000000000207113264166600014445 0ustar rootrootThe MIT License (MIT) Copyright (c) 2015 Andrew Gallant 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. vendor/docopt-0.8.3/Makefile0000644000000000000000000000066613264166600014461 0ustar rootrootall: @echo Nothing to do docs: $(LIB_FILES) cargo doc # WTF is rustdoc doing? in-dir ./target/doc fix-perms rscp ./target/doc/* gopher:~/www/burntsushi.net/rustdoc/ src/test/testcases.rs: src/test/testcases.docopt scripts/mk-testcases ./scripts/mk-testcases ./src/test/testcases.docopt > ./src/test/testcases.rs ctags: ctags --recurse --options=ctags.rust --languages=Rust push: git push github master git push origin master vendor/docopt-0.8.3/README.md0000644000000000000000000002454513264166600014302 0ustar rootrootDocopt for Rust with automatic type based decoding (i.e., data validation). This implementation conforms to the [official description of Docopt](http://docopt.org/) and [passes its test suite](https://github.com/docopt/docopt/pull/201). [![Build status](https://api.travis-ci.org/docopt/docopt.rs.svg)](https://travis-ci.org/docopt/docopt.rs) [![](http://meritbadge.herokuapp.com/docopt)](https://crates.io/crates/docopt) Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org). ### Current status Fully functional but the design of the API is up for debate. **I am seeking feedback**. ### Documentation ### Installation This crate is fully compatible with Cargo. Just add it to your `Cargo.toml`: ```toml [dependencies] docopt = "0.8" serde = "1.0" # if you're using `derive(Deserialize)` serde_derive = "1.0" # if you're using `derive(Deserialize)` ``` If you want to use the macro, then add `docopt_macros = "0.8"` instead. Note that the **`docopt!` macro only works on a nightly Rust compiler** because it is a compiler plugin. ### Quick example Here is a full working example. Notice that you can specify the types of each of the named values in the Docopt usage string. Values will be automatically converted to those types (or an error will be reported). ```rust #[macro_use] extern crate serde_derive; extern crate docopt; use docopt::Docopt; const USAGE: &'static str = " Naval Fate. Usage: naval_fate.py ship new ... naval_fate.py ship move [--speed=] naval_fate.py ship shoot naval_fate.py mine (set|remove) [--moored | --drifting] naval_fate.py (-h | --help) naval_fate.py --version Options: -h --help Show this screen. --version Show version. --speed= Speed in knots [default: 10]. --moored Moored (anchored) mine. --drifting Drifting mine. "; #[derive(Debug, Deserialize)] struct Args { flag_speed: isize, flag_drifting: bool, arg_name: Vec, arg_x: Option, arg_y: Option, cmd_ship: bool, cmd_mine: bool, } fn main() { let args: Args = Docopt::new(USAGE) .and_then(|d| d.deserialize()) .unwrap_or_else(|e| e.exit()); println!("{:?}", args); } ``` Here is the same example, but with the use of the `docopt!` macro, which will *generate a struct for you*. Note that this uses a compiler plugin, so it only works on a **nightly Rust compiler**: ```rust #![feature(plugin)] #![plugin(docopt_macros)] #[macro_use] extern crate serde_derive; extern crate docopt; use docopt::Docopt; docopt!(Args derive Debug, " Naval Fate. Usage: naval_fate.py ship new ... naval_fate.py ship move [--speed=] naval_fate.py ship shoot naval_fate.py mine (set|remove) [--moored | --drifting] naval_fate.py (-h | --help) naval_fate.py --version Options: -h --help Show this screen. --version Show version. --speed= Speed in knots [default: 10]. --moored Moored (anchored) mine. --drifting Drifting mine. "); fn main() { let args: Args = Args::docopt().deserialize().unwrap_or_else(|e| e.exit()); println!("{:?}", args); } ``` The `Args` struct has one static method defined for it: `docopt`. The method returns a normal `Docopt` value, which can be used to set configuration options, `argv` and parse or decode command line arguments. ### Struct field name mapping The field names of the struct map like this: ``` -g => flag_g --group => flag_group --group => flag_group FILE => arg_FILE => arg_file build => cmd_build ``` ### Data validation example Here's another example that shows how to specify the types of your arguments: ```rust #![feature(plugin)] #![plugin(docopt_macros)] #[macro_use] extern crate serde_derive; extern crate docopt; docopt!(Args, "Usage: add ", arg_x: i32, arg_y: i32); fn main() { let args: Args = Args::docopt().deserialize().unwrap_or_else(|e| e.exit()); println!("x: {}, y: {}", args.arg_x, args.arg_y); } ``` In this example, specific type annotations were added. They will be automatically inserted into the generated struct. You can override as many (or as few) fields as you want. If you don't specify a type, then one of `bool`, `u64`, `String` or `Vec` will be chosen depending on the type of argument. In this case, both `arg_x` and `arg_y` would have been `String`. If any value cannot be decoded into a value with the right type, then an error will be shown to the user. And of course, you don't need the macro to do this. You can do the same thing with a manually written struct too. ### Modeling `rustc` Here's a selected subset for some of `rustc`'s options. This also shows how to restrict values to a list of choices via an `enum` type and demonstrates more Docopt features. ```rust #![feature(plugin)] #![plugin(docopt_macros)] #[macro_use] extern crate serde_derive; extern crate serde; extern crate docopt; use serde::de; docopt!(Args derive Debug, " Usage: rustc [options] [--cfg SPEC... -L PATH...] INPUT rustc (--help | --version) Options: -h, --help Show this message. --version Show the version of rustc. --cfg SPEC Configure the compilation environment. -L PATH Add a directory to the library search path. --emit TYPE Configure the output that rustc will produce. Valid values: asm, ir, bc, obj, link. --opt-level LEVEL Optimize with possible levels 0-3. ", flag_opt_level: Option, flag_emit: Option); #[derive(Deserialize, Debug)] enum Emit { Asm, Ir, Bc, Obj, Link } #[derive(Debug)] enum OptLevel { Zero, One, Two, Three } impl<'de> de::Deserialize<'de> for OptLevel { fn deserialize(deserializer: D) -> Result where D: de::Deserializer<'de> { let level = match u8::deserialize(deserializer)? { 0 => OptLevel::Zero, 1 => OptLevel::One, 2 => OptLevel::Two, 3 => OptLevel::Three, n => { let value = de::Unexpected::Unsigned(n as u64); let msg = "expected an integer between 0 and 3"; return Err(de::Error::invalid_value(value, &msg)); } }; Ok(level) } } fn main() { let args: Args = Args::docopt().deserialize().unwrap_or_else(|e| e.exit()); println!("{:?}", args); } ``` ### Viewing the generated struct Generating a struct is pretty magical, but if you want, you can look at it by expanding all macros. Say you wrote the above example for `Usage: add ` into a file called `add.rs`. Then running: ```bash rustc -L path/containing/docopt/lib -Z unstable-options --pretty=expanded add.rs ``` Will show all macros expanded. The `path/containing/docopt/lib` is usually `target/debug/deps` or `target/release/deps` in a cargo project. In the generated code, you should be able to find the generated struct: ```rust struct Args { pub arg_x: int, pub arg_y: int, } ``` ### Traditional Docopt API The reference implementation of Docopt returns a Python dictionary with names like `` or `--flag`. If you prefer this access pattern, then you can use `docopt::ArgvMap`. The disadvantage is that you have to do all of your type conversion manually. Here's the canonical Docopt example with a hash table: ```rust extern crate docopt; use docopt::Docopt; const USAGE: &'static str = " Naval Fate. Usage: naval_fate.py ship new ... naval_fate.py ship move [--speed=] naval_fate.py ship shoot naval_fate.py mine (set|remove) [--moored | --drifting] naval_fate.py (-h | --help) naval_fate.py --version Options: -h --help Show this screen. --version Show version. --speed= Speed in knots [default: 10]. --moored Moored (anchored) mine. --drifting Drifting mine. "; fn main() { let args = Docopt::new(USAGE) .and_then(|dopt| dopt.parse()) .unwrap_or_else(|e| e.exit()); println!("{:?}", args); // You can conveniently access values with `get_{bool,count,str,vec}` // functions. If the key doesn't exist (or if, e.g., you use `get_str` on // a switch), then a sensible default value is returned. println!("\nSome values:"); println!(" Speed: {}", args.get_str("--speed")); println!(" Drifting? {}", args.get_bool("--drifting")); println!(" Names: {:?}", args.get_vec("")); } ``` ### Tab completion support This particular implementation bundles a command called `docopt-wordlist` that can be used to automate tab completion. This repository also collects some basic completion support for various shells (currently only bash) in the `completions` directory. You can use them to setup tab completion on your system. It should work with any program that uses Docopt (or rather, any program that outputs usage messages that look like Docopt). For example, to get tab completion support for Cargo, you'll have to install `docopt-wordlist` and add some voodoo to your `$HOME/.bash_completion` file (this may vary for other shells). Here it is step by step: ```bash # Download and build `docopt-wordlist` (as part of the Docopt package) $ git clone git://github.com/docopt/docopt.rs $ cd docopt.rs $ cargo build --release # Now setup tab completion (for bash) $ echo "DOCOPT_WORDLIST_BIN=\"$(pwd)/target/release/docopt-wordlist\"" >> $HOME/.bash_completion $ echo "source \"$(pwd)/completions/docopt-wordlist.bash\"" >> $HOME/.bash_completion $ echo "complete -F _docopt_wordlist_commands cargo" >> $HOME/.bash_completion ``` My [CSV toolkit](https://github.com/BurntSushi/xsv) is supported too: ```bash # shameless plug... $ echo "complete -F _docopt_wordlist_commands xsv" >> $HOME/.bash_completion ``` Note that this is emphatically a first pass. There are several improvements that I'd like to make: 1. Take context into account when completing. For example, it should be possible to only show completions that can lead to a valid Docopt match. This may be hard. (i.e., It may require restructuring Docopt's internals.) 2. Support more shells. (I'll happily accept pull requests on this one. I doubt I'll venture outside of bash any time soon.) 3. Make tab completion support more seamless. The way it works right now is pretty hacky by intermingling file/directory completion. vendor/docopt-0.8.3/UNLICENSE0000644000000000000000000000227313264166600014265 0ustar rootrootThis is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. 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 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. For more information, please refer to vendor/docopt-0.8.3/completions/0000755000000000000000000000000013264166600015345 5ustar rootrootvendor/docopt-0.8.3/completions/docopt-wordlist.bash0000644000000000000000000000476413264166600021354 0ustar rootroot# This is your basic tab completion that will work well with commands that # have only one usage (i.e., no distinct sub-commands). # # Completion works by simply taking the command name and running `$cmd --help` # to get the usage (which is then parsed for possible completions). function _docopt_wordlist { if [ -z "$DOCOPT_WORDLIST_BIN" ]; then DOCOPT_WORDLIST_BIN=/usr/local/bin/docopt-wordlist fi cword=$(_get_cword) cmd="${COMP_WORDS[0]}" wordlist=$("$cmd" --help 2>&1 | "$DOCOPT_WORDLIST_BIN") gen "$cword" "$wordlist" } # This is a fancier version of the above that supports commands that have # multiple sub-commands (i.e., distinct usages like Cargo). # # This supports sub-command completion only if `$cmd --list` shows a list of # available sub-commands. # # Otherwise, the usage for the command `a b c d` is taken from the first # command that exits successfully: # # a b c d --help # a b c --help # a b --help # a --help # # So for example, if you've typed `cargo test --jo`, then the following # happens: # # cargo test --jo --help # error # cargo test --help # gives 'test' sub-command usage! # # As a special case, if only the initial command has been typed, then the # sub-commands (taken from `$cmd --list`) are added to the wordlist. function _docopt_wordlist_commands { if [ -z "$DOCOPT_WORDLIST_BIN" ]; then DOCOPT_WORDLIST_BIN=/usr/local/bin/docopt-wordlist fi cword=$(_get_cword) if [ "$COMP_CWORD" = 1 ]; then cmd="${COMP_WORDS[0]}" wordlist=$("$cmd" --help 2>&1 | "$DOCOPT_WORDLIST_BIN") wordlist+=" $("$cmd" --list | egrep '^ +\w' | awk '{print $1}')" gen "$cword" "$wordlist" else for ((i="$COMP_CWORD"; i >= 1; i++)); do cmd="${COMP_WORDS[@]::$i}" wordlist=$($cmd --help 2>&1 | "$DOCOPT_WORDLIST_BIN") if [ $? = 0 ]; then gen "$cword" "$wordlist" break fi done fi } # A helper function for running `compgen`, which is responsible for taking # a prefix and presenting possible completions. # # If the current prefix starts with a `.` or a `/`, then file/directory # completion is done. Otherwise, Docopt completion is done. If Docopt # completion is empty, then it falls back to file/directory completion. function gen { cword="$1" wordlist="$2" if [[ "$cword" = .* || "$cword" = /* ]]; then COMPREPLY=($(compgen -A file -- "$cword")) else COMPREPLY=($(compgen -W "$wordlist" -- "$cword")) if [ -z "$COMPREPLY" ]; then COMPREPLY=($(compgen -A file -- "$cword")) fi fi } vendor/docopt-0.8.3/ctags.rust0000644000000000000000000000160613264166600015034 0ustar rootroot--langdef=Rust --langmap=Rust:.rs --regex-Rust=/^[ \t]*(#\[[^\]]\][ \t]*)*(pub[ \t]+)?(extern[ \t]+)?("[^"]+"[ \t]+)?(unsafe[ \t]+)?fn[ \t]+([a-zA-Z0-9_]+)/\6/f,functions,function definitions/ --regex-Rust=/^[ \t]*(pub[ \t]+)?type[ \t]+([a-zA-Z0-9_]+)/\2/T,types,type definitions/ --regex-Rust=/^[ \t]*(pub[ \t]+)?enum[ \t]+([a-zA-Z0-9_]+)/\2/g,enum,enumeration names/ --regex-Rust=/^[ \t]*(pub[ \t]+)?struct[ \t]+([a-zA-Z0-9_]+)/\2/s,structure names/ --regex-Rust=/^[ \t]*(pub[ \t]+)?mod[ \t]+([a-zA-Z0-9_]+)/\2/m,modules,module names/ --regex-Rust=/^[ \t]*(pub[ \t]+)?static[ \t]+([a-zA-Z0-9_]+)/\2/c,consts,static constants/ --regex-Rust=/^[ \t]*(pub[ \t]+)?trait[ \t]+([a-zA-Z0-9_]+)/\2/t,traits,traits/ --regex-Rust=/^[ \t]*(pub[ \t]+)?impl([ \t\n]+<.*>)?[ \t]+([a-zA-Z0-9_]+)/\3/i,impls,trait implementations/ --regex-Rust=/^[ \t]*macro_rules![ \t]+([a-zA-Z0-9_]+)/\1/d,macros,macro definitions/ vendor/docopt-0.8.3/examples/0000755000000000000000000000000013264166600014627 5ustar rootrootvendor/docopt-0.8.3/examples/cargo.rs0000644000000000000000000000252013264166600016267 0ustar rootroot#[macro_use] extern crate serde_derive; extern crate docopt; use docopt::Docopt; // Write the Docopt usage string. const USAGE: &'static str = " Rust's package manager Usage: cargo [...] cargo [options] Options: -h, --help Display this message -V, --version Print version info and exit --list List installed commands -v, --verbose Use verbose output Some common cargo commands are: build Compile the current project clean Remove the target directory doc Build this project's and its dependencies' documentation new Create a new cargo project run Build and execute src/main.rs test Run the tests bench Run the benchmarks update Update dependencies listed in Cargo.lock See 'cargo help ' for more information on a specific command. "; #[derive(Debug, Deserialize)] struct Args { arg_command: Option, arg_args: Vec, flag_list: bool, flag_verbose: bool, } #[derive(Debug, Deserialize)] enum Command { Build, Clean, Doc, New, Run, Test, Bench, Update, } fn main() { let args: Args = Docopt::new(USAGE) .and_then(|d| d.options_first(true).deserialize()) .unwrap_or_else(|e| e.exit()); println!("{:?}", args); } vendor/docopt-0.8.3/examples/cp.rs0000644000000000000000000000106413264166600015600 0ustar rootroot#[macro_use] extern crate serde_derive; extern crate docopt; use docopt::Docopt; // Write the Docopt usage string. const USAGE: &'static str = " Usage: cp [-a] cp [-a] ... Options: -a, --archive Copy everything. "; #[derive(Debug, Deserialize)] struct Args { arg_source: Vec, arg_dest: String, arg_dir: String, flag_archive: bool, } fn main() { let args: Args = Docopt::new(USAGE) .and_then(|d| d.deserialize()) .unwrap_or_else(|e| e.exit()); println!("{:?}", args); } vendor/docopt-0.8.3/examples/decode.rs0000644000000000000000000000224613264166600016424 0ustar rootroot#[macro_use] extern crate serde_derive; extern crate docopt; use docopt::Docopt; const USAGE: &'static str = " Naval Fate. Usage: naval_fate.py ship new ... naval_fate.py ship move [--speed=] naval_fate.py ship shoot naval_fate.py mine (set|remove) [--moored | --drifting] naval_fate.py (-h | --help) naval_fate.py --version Options: -h --help Show this screen. --version Show version. --speed= Speed in knots [default: 10]. --moored Moored (anchored) mine. --drifting Drifting mine. "; #[derive(Debug, Deserialize)] struct Args { flag_speed: isize, flag_drifting: bool, arg_name: Vec, arg_x: Option, arg_y: Option, cmd_ship: bool, cmd_mine: bool, } fn main() { let args: Args = Docopt::new(USAGE) .and_then(|d| d.deserialize()) .unwrap_or_else(|e| e.exit()); println!("{:?}", args); println!("\nSome values:"); println!(" Speed: {}", args.flag_speed); println!(" Drifting? {}", args.flag_drifting); println!(" Names: {:?}", args.arg_name); println!(" Command 'ship' invoked? {:?}", args.cmd_ship); } vendor/docopt-0.8.3/examples/hashmap.rs0000644000000000000000000000236213264166600016621 0ustar rootrootextern crate docopt; use docopt::Docopt; const USAGE: &'static str = " Naval Fate. Usage: naval_fate.py ship new ... naval_fate.py ship move [--speed=] naval_fate.py ship shoot naval_fate.py mine (set|remove) [--moored | --drifting] naval_fate.py (-h | --help) naval_fate.py --version Options: -h --help Show this screen. --version Show version. --speed= Speed in knots [default: 10]. --moored Moored (anchored) mine. --drifting Drifting mine. "; fn main() { let version = "1.2.3".to_owned(); let args = Docopt::new(USAGE) .and_then(|dopt| dopt.version(Some(version)).parse()) .unwrap_or_else(|e| e.exit()); println!("{:?}", args); // You can conveniently access values with `get_{bool,count,str,vec}` // functions. If the key doesn't exist (or if, e.g., you use `get_str` on // a switch), then a sensible default value is returned. println!("\nSome values:"); println!(" Speed: {}", args.get_str("--speed")); println!(" Drifting? {}", args.get_bool("--drifting")); println!(" Names: {:?}", args.get_vec("")); println!(" Command 'ship' invoked? {:?}", args.get_bool("ship")); } vendor/docopt-0.8.3/examples/optional_command.rs0000644000000000000000000000317713264166600020530 0ustar rootroot// This example shows how to implement a command with a "catch all." // // This requires writing your own impl for `Decodable` because docopt's // decoder uses `Option` to mean "T may not be present" rather than // "T may be present but incorrect." #[macro_use] extern crate serde_derive; extern crate serde; extern crate docopt; use docopt::Docopt; use serde::de::{Deserialize, Deserializer, Error, Visitor}; use std::fmt; // Write the Docopt usage string. const USAGE: &'static str = " Rust's package manager Usage: mycli [] Options: -h, --help Display this message "; #[derive(Debug, Deserialize)] struct Args { arg_command: Command, } struct CommandVisitor; impl<'de> Visitor<'de> for CommandVisitor { type Value = Command; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a string A, B or C") } fn visit_str(self, s: &str) -> Result where E: Error { Ok(match s { "" => Command::None, "A" => Command::A, "B" => Command::B, "C" => Command::C, s => Command::Unknown(s.to_string()), }) } } impl<'de> Deserialize<'de> for Command { fn deserialize(d: D) -> Result where D: Deserializer<'de> { d.deserialize_str(CommandVisitor) } } #[derive(Debug)] enum Command { A, B, C, Unknown(String), None, } fn main() { let args: Args = Docopt::new(USAGE) .and_then(|d| d.deserialize()) .unwrap_or_else(|e| e.exit()); println!("{:?}", args); } vendor/docopt-0.8.3/examples/verbose_multiple.rs0000644000000000000000000000157213264166600020562 0ustar rootroot#[macro_use] extern crate serde_derive; extern crate docopt; use docopt::Docopt; // This shows how to implement multiple levels of verbosity. // // When you have multiple patterns, I think the only way to carry the // repeated flag through all of them is to specify it for each pattern // explicitly. // // This is unfortunate. const USAGE: &'static str = " Usage: cp [options] [-v | -vv | -vvv] cp [options] [-v | -vv | -vvv] ... Options: -a, --archive Copy everything. -v, --verbose Show extra log output. "; #[derive(Debug, Deserialize)] struct Args { arg_source: Vec, arg_dest: String, arg_dir: String, flag_archive: bool, flag_verbose: usize, } fn main() { let args: Args = Docopt::new(USAGE) .and_then(|d| d.deserialize()) .unwrap_or_else(|e| e.exit()); println!("{:?}", args); } vendor/docopt-0.8.3/scripts/0000755000000000000000000000000013264166600014500 5ustar rootrootvendor/docopt-0.8.3/scripts/mk-testcases0000755000000000000000000000526513264166600017041 0ustar rootroot#!/usr/bin/env python2 from __future__ import absolute_import, division, print_function import argparse import json import re retests = re.compile('(.*?)"""(.*?)(r"""|\s*$)', re.DOTALL) reinvokes = re.compile('(.+?$)(.+?)\s*(\$|\Z)', re.DOTALL | re.MULTILINE) p = argparse.ArgumentParser( description="Outputs src/test/testcases.rs to stdout") p.add_argument("testcases", metavar="FILE", help="The testcases.docopt language agnostic test suite.") args = p.parse_args() with open(args.testcases) as f: alltests = f.read() alltests = re.sub('^r"""', '', alltests) alltests = re.sub('^\s*#.*$', '', alltests, flags=re.MULTILINE) tests = [] # [{usage, args, expect}] (expect is None ==> user-error) for m in retests.finditer(alltests): usage, invokes = m.group(1).strip(), m.group(2).strip() assert invokes.startswith('$'), 'Bad test: "%s"' % invokes invokes = re.sub('^\$', '', invokes) for mi in reinvokes.finditer(invokes): invoke, expect = mi.group(1).strip(), mi.group(2).strip() err = expect.startswith('"user-error"') tests.append({ 'usage': usage, 'args': invoke.split()[1:], 'expect': None if err else json.loads(expect), }) def show_test(i, t): def show_expect(e): kvs = [] for k, v in e.iteritems(): kvs.append('("%s", %s)' % (k, show_value(v))) return ', '.join(kvs) def show_value(v): if v is None: return 'Plain(None)' elif isinstance(v, basestring): return 'Plain(Some("%s".to_string()))' % v elif isinstance(v, bool): return 'Switch(%s)' % ('true' if v else 'false') elif isinstance(v, int): return 'Counted(%d)' % v elif isinstance(v, list): elms = ', '.join(['"%s".to_string()' % el for el in v]) return 'List(vec!(%s))' % elms else: raise ValueError('Unrecognized value: "%s" (type: %s)' % (v, type(v))) args = ', '.join(['"%s"' % arg for arg in t['args']]) if t['expect'] is None: return 'test_user_error!(test_%d_testcases, "%s", &[%s]);' \ % (i, t['usage'], args) else: expect = show_expect(t['expect']) return 'test_expect!(test_%d_testcases, "%s", &[%s], vec!(%s));' \ % (i, t['usage'], args, expect) print( """// !!! ATTENTION !!! // This file is automatically generated by `scripts/mk-testcases`. // Please do not edit this file directly! use Value::{{Switch, Counted, Plain, List}}; use test::{{get_args, map_from_alist, same_args}}; {tests} """.format(tests='\n\n'.join([show_test(i, t) for i, t in enumerate(tests)]))) vendor/docopt-0.8.3/session.vim0000644000000000000000000000023513264166600015211 0ustar rootrootau BufWritePost *.rs silent!make ctags > /dev/null 2>&1 " let g:syntastic_rust_rustc_fname = "src/lib.rs" " let g:syntastic_rust_rustc_args = "--no-trans" vendor/docopt-0.8.3/src/0000755000000000000000000000000013264166600013600 5ustar rootrootvendor/docopt-0.8.3/src/dopt.rs0000664000000000000000000010047513264166600015125 0ustar rootrootuse std::collections::HashMap; use std::error::Error as StdError; use std::fmt::{self, Debug}; use std::io::{self, Write}; use std::str::FromStr; use std::result; use regex::{Captures, Regex}; use serde::de; use serde::de::IntoDeserializer; use parse::Parser; use synonym::SynonymMap; use self::Value::{Switch, Counted, Plain, List}; use self::Error::{Usage, Argv, NoMatch, Deserialize, WithProgramUsage, Help, Version}; use cap_or_empty; /// Represents the different types of Docopt errors. /// /// This error type has a lot of variants. In the common case, you probably /// don't care why Docopt has failed, and would rather just quit the program /// and show an error message instead. The `exit` method defined on the `Error` /// type will do just that. It will also set the exit code appropriately /// (no error for `--help` or `--version`, but an error code for bad usage, /// bad argv, no match or bad decode). /// /// ### Example /// /// Generally, you want to parse the usage string, try to match the argv /// and then quit the program if there was an error reported at any point /// in that process. This can be achieved like so: /// /// ```no_run /// use docopt::Docopt; /// /// const USAGE: &'static str = " /// Usage: ... /// "; /// /// let args = Docopt::new(USAGE) /// .and_then(|d| d.parse()) /// .unwrap_or_else(|e| e.exit()); /// ``` #[derive(Debug)] pub enum Error { /// Parsing the usage string failed. /// /// This error can only be triggered by the programmer, i.e., the writer /// of the Docopt usage string. This error is usually indicative of a bug /// in your program. Usage(String), /// Parsing the argv specified failed. /// /// The payload is a string describing why the arguments provided could not /// be parsed. /// /// This is distinct from `NoMatch` because it will catch errors like /// using flags that aren't defined in the usage string. Argv(String), /// The given argv parsed successfully, but it did not match any example /// usage of the program. /// /// Regrettably, there is no descriptive message describing *why* the /// given argv didn't match any of the usage strings. NoMatch, /// This indicates a problem deserializing a successful argv match into a /// deserializable value. Deserialize(String), /// Parsing failed, and the program usage should be printed next to the /// failure message. Typically this wraps `Argv` and `NoMatch` errors. WithProgramUsage(Box, String), /// Decoding or parsing failed because the command line specified that the /// help message should be printed. Help, /// Decoding or parsing failed because the command line specified that the /// version should be printed /// /// The version is included as a payload to this variant. Version(String), } impl Error { /// Return whether this was a fatal error or not. /// /// Non-fatal errors include requests to print the help or version /// information of a program, while fatal errors include those such as /// failing to decode or parse. pub fn fatal(&self) -> bool { match *self { Help | Version(..) => false, Usage(..) | Argv(..) | NoMatch | Deserialize(..) => true, WithProgramUsage(ref b, _) => b.fatal(), } } /// Print this error and immediately exit the program. /// /// If the error is non-fatal (e.g., `Help` or `Version`), then the /// error is printed to stdout and the exit status will be `0`. Otherwise, /// when the error is fatal, the error is printed to stderr and the /// exit status will be `1`. pub fn exit(&self) -> ! { if self.fatal() { werr!("{}\n", self); ::std::process::exit(1) } else { let _ = writeln!(&mut io::stdout(), "{}", self); ::std::process::exit(0) } } } type Result = result::Result; impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { WithProgramUsage(ref other, ref usage) => { let other = other.to_string(); if other.is_empty() { write!(f, "{}", usage) } else { write!(f, "{}\n\n{}", other, usage) } } Help => write!(f, ""), NoMatch => write!(f, "Invalid arguments."), Usage(ref s) | Argv(ref s) | Deserialize(ref s) | Version(ref s) => write!(f, "{}", s), } } } impl StdError for Error { fn description(&self) -> &str { match *self { Usage(..) => "invalid usage string", Argv(..) => "failed to parse specified argv", NoMatch => "could not match specified argv", Deserialize(..) => "failed to deserialize", WithProgramUsage(..) => "failed to parse specified argv", Help => "help message requested", Version(..) => "version message requested", } } fn cause(&self) -> Option<&StdError> { match *self { WithProgramUsage(ref cause, _) => Some(&**cause), _ => None, } } } impl de::Error for Error { fn custom(msg: T) -> Self { Error::Deserialize(msg.to_string()) } } /// The main Docopt type, which is constructed with a Docopt usage string. /// /// This can be used to match command line arguments to produce a `ArgvMap`. #[derive(Clone, Debug)] pub struct Docopt { p: Parser, argv: Option>, options_first: bool, help: bool, version: Option, } impl Docopt { /// Parse the Docopt usage string given. /// /// The `Docopt` value returned may be used immediately to parse command /// line arguments with a default configuration. /// /// If there was a problem parsing the usage string, a `Usage` error /// is returned. pub fn new(usage: S) -> Result where S: ::std::ops::Deref { Parser::new(usage.deref()) .map_err(Usage) .map(|p| Docopt { p: p, argv: None, options_first: false, help: true, version: None, }) } /// Parse and deserialize the given argv. /// /// This is a convenience method for /// `parse().and_then(|vals| vals.deserialize())`. /// /// For details on how decoding works, please see the documentation for /// `ArgvMap`. pub fn deserialize<'a, 'de: 'a, D>(&'a self) -> Result where D: de::Deserialize<'de> { self.parse().and_then(|vals| vals.deserialize()) } /// Parse command line arguments and try to match them against a usage /// pattern specified in the Docopt string. /// /// If there is a match, then an `ArgvMap` is returned, which maps /// flags, commands and arguments to values. /// /// If parsing the command line arguments fails, then an `Argv` error is /// returned. If parsing succeeds but there is no match, then a `NoMatch` /// error is returned. Both of these errors are always returned inside a /// `WithProgramUsage` error. /// /// If special handling of `help` or `version` is enabled (the former is /// enabled by default), then `Help` or `Version` errors are returned /// if `--help` or `--version` is present. pub fn parse(&self) -> Result { let argv = self.argv.clone().unwrap_or_else(Docopt::get_argv); let vals = self.p.parse_argv(argv, self.options_first) .map_err(|s| self.err_with_usage(Argv(s))) .and_then(|argv| match self.p.matches(&argv) { Some(m) => Ok(ArgvMap { map: m }), None => Err(self.err_with_usage(NoMatch)), })?; if self.help && vals.get_bool("--help") { return Err(self.err_with_full_doc(Help)); } match self.version { Some(ref v) if vals.get_bool("--version") => { return Err(Version(v.clone())) } _ => {}, } Ok(vals) } /// Set the argv to be used for Docopt parsing. /// /// By default, when no argv is set, and it is automatically taken from /// `std::env::args()`. /// /// The `argv` given *must* be the full set of `argv` passed to the /// program. e.g., `["cp", "src", "dest"]` is right while `["src", "dest"]` /// is wrong. pub fn argv(mut self, argv: I) -> Docopt where I: IntoIterator, S: AsRef { self.argv = Some( argv.into_iter().skip(1).map(|s| s.as_ref().to_owned()).collect() ); self } /// Enables the "options first" Docopt behavior. /// /// The options first behavior means that all flags *must* appear before /// position arguments. That is, after the first position argument is /// seen, all proceeding arguments are interpreted as positional /// arguments unconditionally. pub fn options_first(mut self, yes: bool) -> Docopt { self.options_first = yes; self } /// Enables automatic handling of `--help`. /// /// When this is enabled and `--help` appears anywhere in the arguments, /// then a `Help` error will be returned. You may then use the `exit` /// method on the error value to conveniently quit the program (which will /// print the full usage string to stdout). /// /// Note that for this to work, `--help` must be a valid pattern. /// /// When disabled, there is no special handling of `--help`. pub fn help(mut self, yes: bool) -> Docopt { self.help = yes; self } /// Enables automatic handling of `--version`. /// /// When this is enabled and `--version` appears anywhere in the arguments, /// then a `Version(s)` error will be returned, where `s` is the string /// given here. You may then use the `exit` method on the error value to /// convenient quit the program (which will print the version to stdout). /// /// When disabled (a `None` value), there is no special handling of /// `--version`. pub fn version(mut self, version: Option) -> Docopt { self.version = version; self } #[doc(hidden)] // Exposed for use in `docopt_macros`. pub fn parser(&self) -> &Parser { &self.p } fn err_with_usage(&self, e: Error) -> Error { WithProgramUsage( Box::new(e), self.p.usage.trim().into()) } fn err_with_full_doc(&self, e: Error) -> Error { WithProgramUsage( Box::new(e), self.p.full_doc.trim().into()) } fn get_argv() -> Vec { // Hmm, we should probably handle a Unicode decode error here... ---AG ::std::env::args().skip(1).collect() } } /// A map containing matched values from command line arguments. /// /// The keys are just as specified in Docopt: `--flag` for a long flag or /// `-f` for a short flag. (If `-f` is a synonym for `--flag`, then either /// key will work.) `ARG` or `` specify a positional argument and `cmd` /// specifies a command. #[derive(Clone)] pub struct ArgvMap { #[doc(hidden)] pub map: SynonymMap, } impl ArgvMap { /// Tries to deserialize the map of values into a struct. /// /// This method should always be called to deserialize a `ArgvMap` into /// a struct. All fields of the struct must map to a corresponding key /// in the `ArgvMap`. To this end, each member must have a special prefix /// corresponding to the different kinds of patterns in Docopt. There are /// three prefixes: `flag_`, `arg_` and `cmd_` which respectively /// correspond to short/long flags, positional arguments and commands. /// /// If a Docopt item has a `-` in its name, then it is converted to an `_`. /// /// # Example /// /// ```rust /// # extern crate docopt; /// #[macro_use] /// extern crate serde_derive; /// # extern crate serde; /// # fn main() { /// use docopt::Docopt; /// /// const USAGE: &'static str = " /// Usage: cargo [options] (build | test) /// cargo --help /// /// Options: -v, --verbose /// -h, --help /// "; /// /// #[derive(Deserialize)] /// struct Args { /// cmd_build: bool, /// cmd_test: bool, /// flag_verbose: bool, /// flag_h: bool, /// } /// /// let argv = || vec!["cargo", "build", "-v"].into_iter(); /// let args: Args = Docopt::new(USAGE) /// .and_then(|d| d.argv(argv()).deserialize()) /// .unwrap_or_else(|e| e.exit()); /// assert!(args.cmd_build && !args.cmd_test /// && args.flag_verbose && !args.flag_h); /// # } /// ``` /// /// Note that in the above example, `flag_h` is used but `flag_help` /// could also be used. (In fact, both could be used at the same time.) /// /// In this example, only the `bool` type was used, but any type satisfying /// the `Deserialize` trait is valid. pub fn deserialize<'de, T: de::Deserialize<'de>>(self) -> Result { de::Deserialize::deserialize(&mut Deserializer { vals: self, stack: vec![], }) } /// Finds the value corresponding to `key` and calls `as_bool()` on it. /// If the key does not exist, `false` is returned. pub fn get_bool(&self, key: &str) -> bool { self.find(key).map_or(false, |v| v.as_bool()) } /// Finds the value corresponding to `key` and calls `as_count()` on it. /// If the key does not exist, `0` is returned. pub fn get_count(&self, key: &str) -> u64 { self.find(key).map_or(0, |v| v.as_count()) } /// Finds the value corresponding to `key` and calls `as_str()` on it. /// If the key does not exist, `""` is returned. pub fn get_str(&self, key: &str) -> &str { self.find(key).map_or("", |v| v.as_str()) } /// Finds the value corresponding to `key` and calls `as_vec()` on it. /// If the key does not exist, `vec!()` is returned. pub fn get_vec(&self, key: &str) -> Vec<&str> { self.find(key).map(|v| v.as_vec()).unwrap_or(vec!()) } /// Return the raw value corresponding to some `key`. /// /// `key` should be a string in the traditional Docopt format. e.g., /// `` or `--flag`. pub fn find(&self, key: &str) -> Option<&Value> { self.map.find(&key.into()) } /// Return the number of values, not including synonyms. pub fn len(&self) -> usize { self.map.len() } /// Converts a Docopt key to a struct field name. /// This makes a half-hearted attempt at making the key a valid struct /// field name (like replacing `-` with `_`), but it does not otherwise /// guarantee that the result is a valid struct field name. #[doc(hidden)] pub fn key_to_struct_field(name: &str) -> String { lazy_static! { static ref RE: Regex = regex!( r"^(?:--?(?P\S+)|(?:(?P\p{Lu}+)|<(?P[^>]+)>)|(?P\S+))$" ); } fn sanitize(name: &str) -> String { name.replace("-", "_") } RE.replace(name, |cap: &Captures| { let (flag, cmd) = ( cap_or_empty(cap, "flag"), cap_or_empty(cap, "cmd"), ); let (argu, argb) = ( cap_or_empty(cap, "argu"), cap_or_empty(cap, "argb"), ); let (prefix, name) = if !flag.is_empty() { ("flag_", flag) } else if !argu.is_empty() { ("arg_", argu) } else if !argb.is_empty() { ("arg_", argb) } else if !cmd.is_empty() { ("cmd_", cmd) } else { panic!("Unknown ArgvMap key: '{}'", name) }; let mut prefix = prefix.to_owned(); prefix.push_str(&sanitize(name)); prefix }).into_owned() } /// Converts a struct field name to a Docopt key. #[doc(hidden)] pub fn struct_field_to_key(field: &str) -> String { lazy_static! { static ref FLAG: Regex = regex!(r"^flag_"); static ref ARG: Regex = regex!(r"^arg_"); static ref LETTERS: Regex = regex!(r"^\p{Lu}+$"); static ref CMD: Regex = regex!(r"^cmd_"); } fn desanitize(name: &str) -> String { name.replace("_", "-") } let name = if field.starts_with("flag_") { let name = FLAG.replace(field, ""); let mut pre_name = (if name.len() == 1 { "-" } else { "--" }) .to_owned(); pre_name.push_str(&*name); pre_name } else if field.starts_with("arg_") { let name = ARG.replace(field, "").into_owned(); if LETTERS.is_match(&name) { name } else { let mut pre_name = "<".to_owned(); pre_name.push_str(&*name); pre_name.push('>'); pre_name } } else if field.starts_with("cmd_") { CMD.replace(field, "").into_owned() } else { panic!("Unrecognized struct field: '{}'", field) }; desanitize(&*name) } } impl fmt::Debug for ArgvMap { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if self.len() == 0 { return write!(f, "{{EMPTY}}"); } // This is a little crazy, but we want to group synonyms with // their keys and sort them for predictable output. let reverse: HashMap<&String, &String> = self.map.synonyms().map(|(from, to)| (to, from)).collect(); let mut keys: Vec<&String> = self.map.keys().collect(); keys.sort(); let mut first = true; for &k in &keys { if !first { write!(f, "\n")?; } else { first = false; } match reverse.get(&k) { None => { write!(f, "{} => {:?}", k, self.map.get(k))? } Some(s) => { write!(f, "{}, {} => {:?}", s, k, self.map.get(k))? } } } Ok(()) } } /// A matched command line value. /// /// The value can be a boolean, counted repetition, a plain string or a list /// of strings. /// /// The various `as_{bool,count,str,vec}` methods provide convenient access /// to values without destructuring manually. #[derive(Clone, Debug, PartialEq)] pub enum Value { /// A boolean value from a flag that has no argument. /// /// The presence of a flag means `true` and the absence of a flag /// means `false`. Switch(bool), /// The number of occurrences of a repeated flag. Counted(u64), /// A positional or flag argument. /// /// This is `None` when the positional argument or flag is not present. /// Note that it is possible to have `Some("")` for a present but empty /// argument. Plain(Option), /// A List of positional or flag arguments. /// /// This list may be empty when no arguments or flags are present. List(Vec), } impl Value { /// Returns the value as a bool. /// /// Counted repetitions are `false` if `0` and `true` otherwise. /// Plain strings are `true` if present and `false` otherwise. /// Lists are `true` if non-empty and `false` otherwise. pub fn as_bool(&self) -> bool { match *self { Switch(b) => b, Counted(n) => n > 0, Plain(None) => false, Plain(Some(_)) => true, List(ref vs) => !vs.is_empty(), } } /// Returns the value as a count of the number of times it occurred. /// /// Booleans are `1` if `true` and `0` otherwise. /// Plain strings are `1` if present and `0` otherwise. /// Lists correspond to its length. pub fn as_count(&self) -> u64 { match *self { Switch(b) => if b { 1 } else { 0 }, Counted(n) => n, Plain(None) => 0, Plain(Some(_)) => 1, List(ref vs) => vs.len() as u64, } } /// Returns the value as a string. /// /// All values return an empty string except for a non-empty plain string. pub fn as_str(&self) -> &str { match *self { Switch(_) | Counted(_) | Plain(None) | List(_) => "", Plain(Some(ref s)) => &**s, } } /// Returns the value as a list of strings. /// /// Booleans, repetitions and empty strings correspond to an empty list. /// Plain strings correspond to a list of length `1`. pub fn as_vec(&self) -> Vec<&str> { match *self { Switch(_) | Counted(_) | Plain(None) => vec![], Plain(Some(ref s)) => vec![&**s], List(ref vs) => vs.iter().map(|s| &**s).collect(), } } } /// Deserializer for `ArgvMap` into your own `Deserialize`able types. /// /// In general, you shouldn't have to use this type directly. It is exposed /// in case you want to write a generic function that produces a deserializable /// value. For example, here's a function that takes a usage string, an argv /// and produces a deserializable value: /// /// ```rust /// # extern crate docopt; /// extern crate serde; /// # fn main() { /// use docopt::Docopt; /// use serde::de::Deserialize; /// /// fn deserialize<'de, D: Deserialize<'de>>(usage: &str, argv: &[&str]) /// -> Result { /// Docopt::new(usage) /// .and_then(|d| d.argv(argv.iter()).deserialize()) /// } /// # } pub struct Deserializer<'de> { vals: ArgvMap, stack: Vec>, } #[derive(Debug)] struct DeserializerItem<'de> { key: String, struct_field: &'de str, val: Option, } macro_rules! derr( ($($arg:tt)*) => (return Err(Deserialize(format!($($arg)*)))) ); impl<'de> Deserializer<'de> { fn push(&mut self, struct_field: &'de str) { let key = ArgvMap::struct_field_to_key(struct_field); self.stack .push(DeserializerItem { key: key.clone(), struct_field: struct_field, val: self.vals.find(&*key).cloned(), }); } fn pop(&mut self) -> Result { match self.stack.pop() { None => derr!("Could not deserialize value into unknown key."), Some(it) => Ok(it), } } fn pop_key_val(&mut self) -> Result<(String, Value)> { let it = self.pop()?; match it.val { None => { derr!("Could not find argument '{}' (from struct field '{}'). Note that each struct field must have the right key prefix, which must be one of `cmd_`, `flag_` or `arg_`.", it.key, it.struct_field) } Some(v) => Ok((it.key, v)), } } fn pop_val(&mut self) -> Result { let (_, v) = self.pop_key_val()?; Ok(v) } fn to_number(&mut self, expect: &str) -> Result where T: FromStr + ToString, ::Err: Debug { let (k, v) = self.pop_key_val()?; match v { Counted(n) => Ok(n.to_string().parse().unwrap()), // lol _ => { if v.as_str().trim().is_empty() { Ok("0".parse().unwrap()) // lol } else { match v.as_str().parse() { Err(_) => { derr!("Could not deserialize '{}' to {} for '{}'.", v.as_str(), expect, k) } Ok(v) => Ok(v), } } } } } fn to_float(&mut self, expect: &str) -> Result { let (k, v) = self.pop_key_val()?; match v { Counted(n) => Ok(n as f64), _ => { match v.as_str().parse() { Err(_) => { derr!("Could not deserialize '{}' to {} for '{}'.", v.as_str(), expect, k) } Ok(v) => Ok(v), } } } } } macro_rules! deserialize_num { ($name:ident, $method:ident, $ty:ty) => ( fn $name(self, visitor: V) -> Result where V: de::Visitor<'de> { visitor.$method(self.to_number::<$ty>(stringify!($ty)).map(|n| n as $ty)?) } ); } impl<'a, 'de> ::serde::Deserializer<'de> for &'a mut Deserializer<'de> { type Error = Error; fn deserialize_any(self, _visitor: V) -> Result where V: de::Visitor<'de> { unimplemented!() } fn deserialize_bool(self, visitor: V) -> Result where V: de::Visitor<'de> { visitor.visit_bool(self.pop_val().map(|v| v.as_bool())?) } // wish for stable macro concat_idents! deserialize_num!(deserialize_i8, visit_i8, i8); deserialize_num!(deserialize_i16, visit_i16, i16); deserialize_num!(deserialize_i32, visit_i32, i32); deserialize_num!(deserialize_i64, visit_i64, i64); deserialize_num!(deserialize_u8, visit_u8, u8); deserialize_num!(deserialize_u16, visit_u16, u16); deserialize_num!(deserialize_u32, visit_u32, u32); deserialize_num!(deserialize_u64, visit_u64, u64); fn deserialize_f32(self, visitor: V) -> Result where V: de::Visitor<'de> { visitor.visit_f32(self.to_float("f32").map(|n| n as f32)?) } fn deserialize_f64(self, visitor: V) -> Result where V: de::Visitor<'de> { visitor.visit_f64(self.to_float("f64")?) } fn deserialize_char(self, visitor: V) -> Result where V: de::Visitor<'de> { let (k, v) = self.pop_key_val()?; let vstr = v.as_str(); match vstr.chars().count() { 1 => visitor.visit_char(vstr.chars().next().unwrap()), _ => derr!("Could not deserialize '{}' into char for '{}'.", vstr, k), } } fn deserialize_str(self, visitor: V) -> Result where V: de::Visitor<'de> { let s = self.pop_val()?; visitor.visit_str(s.as_str()) } fn deserialize_string(self, visitor:V) -> Result where V: de::Visitor<'de> { self.deserialize_str(visitor) } fn deserialize_bytes(self, _visitor: V) -> Result where V: de::Visitor<'de> { unimplemented!() } fn deserialize_byte_buf(self, _visitor: V) -> Result where V: de::Visitor<'de> { unimplemented!() } fn deserialize_option(self, visitor: V) -> Result where V: de::Visitor<'de> { let is_some = match self.stack.last() { None => derr!("Could not deserialize value into unknown key."), Some(it) => it.val.as_ref().map_or(false, |v| v.as_bool()), }; if is_some { visitor.visit_some(self) } else { visitor.visit_none() } } fn deserialize_unit(self, _visitor: V) -> Result where V: de::Visitor<'de> { // I don't know what the right thing is here, so just fail for now. panic!("I don't know how to read into a nil value.") } fn deserialize_unit_struct(self, _name: &'static str, visitor: V) -> Result where V: de::Visitor<'de> { visitor.visit_unit() } fn deserialize_newtype_struct(self, _name: &'static str, visitor: V) -> Result where V: de::Visitor<'de> { visitor.visit_newtype_struct(self) } fn deserialize_tuple(self, _len: usize, _visitor: V) -> Result where V: de::Visitor<'de> { unimplemented!() } fn deserialize_tuple_struct(self, _name: &'static str, _len: usize, _visitor: V) -> Result where V: de::Visitor<'de> { unimplemented!() } fn deserialize_map(self, _visitor: V) -> Result where V: de::Visitor<'de> { unimplemented!() } fn deserialize_seq(mut self, visitor: V) -> Result where V: de::Visitor<'de> { let (key, struct_field, val) = match self.stack.pop() { None => derr!("Could not deserialize value into unknown key."), Some(DeserializerItem {key, struct_field, val}) => (key, struct_field, val), }; let list = val.unwrap_or(List(vec![])); let vals = list.as_vec(); for val in vals.iter().rev() { self.stack .push(DeserializerItem { key: key.clone(), struct_field: struct_field, val: Some(Plain(Some((*val).into()))), }); } visitor.visit_seq(SeqDeserializer::new(&mut self, vals.len())) } fn deserialize_struct(mut self, _: &str, fields: &'static [&'static str], visitor: V) -> Result where V: de::Visitor<'de> { visitor.visit_seq(StructDeserializer::new(&mut self, fields)) } fn deserialize_enum(self, _name: &str, variants: &[&str], visitor: V) -> Result where V: de::Visitor<'de> { let v = self.pop_val()?.as_str().to_lowercase(); let s = match variants.iter().find(|&n| n.to_lowercase() == v) { Some(s) => s, None => { derr!("Could not match '{}' with any of \ the allowed variants: {:?}", v, variants) } }; visitor.visit_enum(s.into_deserializer()) } fn deserialize_identifier(self, visitor: V) -> Result where V: de::Visitor<'de> { self.deserialize_str(visitor) } fn deserialize_ignored_any(self, visitor: V) -> Result where V: de::Visitor<'de> { self.deserialize_any(visitor) } } struct SeqDeserializer<'a, 'de: 'a> { de: &'a mut Deserializer<'de>, len: usize, } impl<'a, 'de> SeqDeserializer<'a, 'de> { fn new(de: &'a mut Deserializer<'de>, len: usize) -> Self { SeqDeserializer { de: de, len: len } } } impl<'a, 'de> de::SeqAccess<'de> for SeqDeserializer<'a, 'de> { type Error = Error; fn next_element_seed(&mut self, seed: T) -> Result> where T: de::DeserializeSeed<'de> { if self.len == 0 { return Ok(None); } self.len -= 1; seed.deserialize(&mut *self.de).map(Some) } fn size_hint(&self) -> Option { return Some(self.len); } } struct StructDeserializer<'a, 'de: 'a> { de: &'a mut Deserializer<'de>, fields: &'static [&'static str], } impl<'a, 'de> StructDeserializer<'a, 'de> { fn new(de: &'a mut Deserializer<'de>, fields: &'static [&'static str]) -> Self { StructDeserializer { de: de, fields: fields, } } } impl<'a, 'de> de::SeqAccess<'de> for StructDeserializer<'a, 'de> { type Error = Error; fn next_element_seed(&mut self, seed: T) -> Result> where T: de::DeserializeSeed<'de> { if self.fields.len() == 0 { return Ok(None); } self.de.push(self.fields[0]); self.fields = &self.fields[1..]; seed.deserialize(&mut *self.de).map(Some) } fn size_hint(&self) -> Option { return Some(self.fields.len()); } } vendor/docopt-0.8.3/src/lib.rs0000644000000000000000000002115613264166600014721 0ustar rootroot//! Docopt for Rust. This implementation conforms to the //! [official description of Docopt](http://docopt.org/) and //! [passes its test suite](https://github.com/docopt/docopt/pull/201). //! //! This library is [on GitHub](https://github.com/docopt/docopt.rs). //! //! Fundamentally, Docopt is a command line argument parser. The detail that //! distinguishes it from most parsers is that the parser is derived from the //! usage string. Here's a simple example: //! //! ```rust //! use docopt::Docopt; //! //! // Write the Docopt usage string. //! const USAGE: &'static str = " //! Usage: cp [-a] //! cp [-a] ... //! //! Options: //! -a, --archive Copy everything. //! "; //! //! // The argv. Normally you'd just use `parse` which will automatically //! // use `std::env::args()`. //! let argv = || vec!["cp", "-a", "file1", "file2", "dest/"]; //! //! // Parse argv and exit the program with an error message if it fails. //! let args = Docopt::new(USAGE) //! .and_then(|d| d.argv(argv().into_iter()).parse()) //! .unwrap_or_else(|e| e.exit()); //! //! // Now access your argv values. Synonyms work just fine! //! assert!(args.get_bool("-a") && args.get_bool("--archive")); //! assert_eq!(args.get_vec(""), vec!["file1", "file2"]); //! assert_eq!(args.get_str(""), "dest/"); //! assert_eq!(args.get_str(""), ""); //! ``` //! //! # Type based decoding //! //! Often, command line values aren't just strings or booleans---sometimes //! they are integers, or enums, or something more elaborate. Using the //! standard Docopt interface can be inconvenient for this purpose, because //! you'll need to convert all of the values explicitly. Instead, this crate //! provides a `Decoder` that converts an `ArgvMap` to your custom struct. //! Here is the same example as above using type based decoding: //! //! ```rust //! # extern crate docopt; //! #[macro_use] //! extern crate serde_derive; //! # fn main() { //! use docopt::Docopt; //! //! // Write the Docopt usage string. //! const USAGE: &'static str = " //! Usage: cp [-a] //! cp [-a] ... //! //! Options: //! -a, --archive Copy everything. //! "; //! //! #[derive(Deserialize)] //! struct Args { //! arg_source: Vec, //! arg_dest: String, //! arg_dir: String, //! flag_archive: bool, //! } //! //! let argv = || vec!["cp", "-a", "file1", "file2", "dest/"]; //! let args: Args = Docopt::new(USAGE) //! .and_then(|d| d.argv(argv().into_iter()).deserialize()) //! .unwrap_or_else(|e| e.exit()); //! //! // Now access your argv values. //! fn s(x: &str) -> String { x.to_string() } //! assert!(args.flag_archive); //! assert_eq!(args.arg_source, vec![s("file1"), s("file2")]); //! assert_eq!(args.arg_dir, s("dest/")); //! assert_eq!(args.arg_dest, s("")); //! # } //! ``` //! //! # Command line arguments for `rustc` //! //! Here's an example with a subset of `rustc`'s command line arguments that //! shows more of Docopt and some of the benefits of type based decoding. //! //! ```rust //! # extern crate docopt; //! #[macro_use] //! extern crate serde_derive; //! extern crate serde; //! # fn main() { //! # #![allow(non_snake_case)] //! use docopt::Docopt; //! use std::fmt; //! //! // Write the Docopt usage string. //! const USAGE: &'static str = " //! Usage: rustc [options] [--cfg SPEC... -L PATH...] INPUT //! rustc (--help | --version) //! //! Options: //! -h, --help Show this message. //! --version Show the version of rustc. //! --cfg SPEC Configure the compilation environment. //! -L PATH Add a directory to the library search path. //! --emit TYPE Configure the output that rustc will produce. //! Valid values: asm, ir, bc, obj, link. //! --opt-level LEVEL Optimize with possible levels 0-3. //! "; //! //! #[derive(Deserialize)] //! struct Args { //! arg_INPUT: String, //! flag_emit: Option, //! flag_opt_level: Option, //! flag_cfg: Vec, //! flag_L: Vec, //! flag_help: bool, //! flag_version: bool, //! } //! //! // This is easy. The decoder will automatically restrict values to //! // strings that match one of the enum variants. //! #[derive(Deserialize)] //! # #[derive(Debug, PartialEq)] //! enum Emit { Asm, Ir, Bc, Obj, Link } //! //! // This one is harder because we want the user to specify an integer, //! // but restrict it to a specific range. So we implement `Deserialize` //! // ourselves. //! # #[derive(Debug, PartialEq)] //! enum OptLevel { Zero, One, Two, Three } //! struct OptLevelVisitor; //! //! impl<'de> serde::de::Visitor<'de> for OptLevelVisitor { //! type Value = OptLevel; //! //! fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { //! formatter.write_str("a number from range 0..3") //! } //! //! fn visit_u8(self, n: u8) -> Result //! where E: serde::de::Error //! { //! Ok(match n { //! 0 => OptLevel::Zero, 1 => OptLevel::One, //! 2 => OptLevel::Two, 3 => OptLevel::Three, //! n => { //! let err = format!( //! "Could not deserialize '{}' as opt-level.", n); //! return Err(E::custom(err)); //! } //! }) //! } //! } //! //! impl<'de> serde::de::Deserialize<'de> for OptLevel { //! fn deserialize(d: D) -> Result //! where D: serde::de::Deserializer<'de> //! { //! d.deserialize_u8(OptLevelVisitor) //! } //! } //! //! let argv = || vec!["rustc", "-L", ".", "-L", "..", "--cfg", "a", //! "--opt-level", "2", "--emit=ir", "docopt.rs"]; //! let args: Args = Docopt::new(USAGE) //! .and_then(|d| d.argv(argv().into_iter()).deserialize()) //! .unwrap_or_else(|e| e.exit()); //! //! // Now access your argv values. //! fn s(x: &str) -> String { x.to_string() } //! assert_eq!(args.arg_INPUT, "docopt.rs".to_string()); //! assert_eq!(args.flag_L, vec![s("."), s("..")]); //! assert_eq!(args.flag_cfg, vec![s("a")]); //! assert_eq!(args.flag_opt_level, Some(OptLevel::Two)); //! assert_eq!(args.flag_emit, Some(Emit::Ir)); //! # } //! ``` //! //! # The `docopt!` macro //! //! This package comes bundled with an additional crate, `docopt_macros`, //! which provides a `docopt!` syntax extension. Its purpose is to automate //! the creation of a Rust struct from a Docopt usage string. In particular, //! this provides a single point of truth about the definition of command line //! arguments in your program. //! //! Another advantage of using the macro is that errors in your Docopt usage //! string will be caught at compile time. Stated differently, your program //! will not compile with an invalid Docopt usage string. //! //! The example above using type based decoding can be simplified to this: //! //! ```ignore //! #![feature(plugin)] //! #![plugin(docopt_macros)] //! //! extern crate serde; //! //! extern crate docopt; //! //! // Write the Docopt usage string with the `docopt!` macro. //! docopt!(Args, " //! Usage: cp [-a] //! cp [-a] ... //! //! Options: //! -a, --archive Copy everything. //! ") //! //! fn main() { //! let argv = || vec!["cp", "-a", "file1", "file2", "dest/"]; //! //! // Your `Args` struct has a single static method defined on it, //! // `docopt`, which will return a normal `Docopt` value. //! let args: Args = Args::docopt().deserialize().unwrap_or_else(|e| e.exit()); //! //! // Now access your argv values. //! fn s(x: &str) -> String { x.to_string() } //! assert!(args.flag_archive); //! assert_eq!(args.arg_source, vec![s("file1"), s("file2")]); //! assert_eq!(args.arg_dir, s("dest/")); //! assert_eq!(args.arg_dest, s("")); //! } //! ``` #![crate_name = "docopt"] #![doc(html_root_url = "http://burntsushi.net/rustdoc/docopt")] #![deny(missing_docs)] #[macro_use] extern crate lazy_static; extern crate regex; extern crate strsim; #[allow(unused_imports)] #[macro_use] extern crate serde_derive; extern crate serde; pub use dopt::{ArgvMap, Deserializer, Docopt, Error, Value}; macro_rules! werr( ($($arg:tt)*) => ({ use std::io::{Write, stderr}; write!(&mut stderr(), $($arg)*).unwrap(); }) ); macro_rules! regex( ($s:expr) => (::regex::Regex::new($s).unwrap()); ); fn cap_or_empty<'t>(caps: ®ex::Captures<'t>, name: &str) -> &'t str { caps.name(name).map_or("", |m| m.as_str()) } mod dopt; #[doc(hidden)] pub mod parse; mod synonym; #[cfg(test)] mod test; vendor/docopt-0.8.3/src/parse.rs0000644000000000000000000015036013264166600015265 0ustar rootroot// I am overall pretty displeased with the quality of code in this module. // I wrote it while simultaneously trying to build a mental model of Docopt's // specification (hint: one does not exist in written form). As a result, there // is a lot of coupling and some duplication. // // Some things that I think are good about the following code: // // - The representation of a "usage pattern." I think it is a minimal // representation of a pattern's syntax. (One possible tweak: // `Optional>` -> `Optional>`.) // - Some disciplined use of regexes. I use a pretty basic state machine // for parsing patterns, but for teasing out the patterns and options // from the Docopt string and for picking out flags with arguments, I // think regexes aren't too bad. There may be one or two scary ones though. // - The core matching algorithm is reasonably simple and concise, but I // think writing down some contracts will help me figure out how to make // the code clearer. // // Some bad things: // // - I tried several times to split some of the pieces in this module into // separate modules. I could find no clear separation. This suggests that // there is too much coupling between parsing components. I'm not convinced // that the coupling is necessary. // - The parsers for patterns and argv share some structure. There may be // an easy abstraction waiting there. // - It is not efficient in the slightest. I tried to be conservative with // copying strings, but I think I failed. (It may not be worthwhile to fix // this if it makes the code more awkward. Docopt does not need to be // efficient.) // // Some things to do immediately: // // - Document representation and invariants. // - Less important: write contracts for functions. // // Long term: // // - Write a specification for Docopt. pub use self::Argument::{Zero, One}; pub use self::Atom::{Short, Long, Command, Positional}; use self::Pattern::{Alternates, Sequence, Optional, Repeat, PatAtom}; use std::borrow::ToOwned; use std::collections::{HashMap, HashSet}; use std::collections::hash_map::Entry::{Vacant, Occupied}; use std::cmp::Ordering; use std::fmt; use regex; use regex::Regex; use strsim::levenshtein; use dopt::Value::{self, Switch, Counted, Plain, List}; use synonym::SynonymMap; use cap_or_empty; macro_rules! err( ($($arg:tt)*) => (return Err(format!($($arg)*))) ); #[derive(Clone)] pub struct Parser { pub program: String, pub full_doc: String, pub usage: String, pub descs: SynonymMap, usages: Vec, last_atom_added: Option, // context for [default: ...] } impl Parser { pub fn new(doc: &str) -> Result { let mut d = Parser { program: String::new(), full_doc: doc.into(), usage: String::new(), usages: vec!(), descs: SynonymMap::new(), last_atom_added: None, }; d.parse(doc)?; Ok(d) } pub fn matches(&self, argv: &Argv) -> Option> { for usage in &self.usages { match Matcher::matches(argv, usage) { None => continue, Some(vals) => return Some(vals), } } None } pub fn parse_argv(&self, argv: Vec, options_first: bool) -> Result { Argv::new(self, argv, options_first) } } impl Parser { fn options_atoms(&self) -> Vec { let mut atoms = vec!(); for (atom, _) in self.descs.iter().filter(|&(_, opts)| opts.is_desc) { atoms.push(atom.clone()); } atoms } fn has_arg(&self, atom: &Atom) -> bool { match self.descs.find(atom) { None => false, Some(opts) => opts.arg.has_arg(), } } fn has_repeat(&self, atom: &Atom) -> bool { match self.descs.find(atom) { None => false, Some(opts) => opts.repeats, } } fn parse(&mut self, doc: &str) -> Result<(), String> { lazy_static! { static ref MUSAGE: Regex = Regex::new( r"(?s)(?i:usage):\s*(?P\S+)(?P.*?)(?:$|\n\s*\n)" ).unwrap(); } let caps = match MUSAGE.captures(doc) { None => err!("Could not find usage patterns in doc string."), Some(caps) => caps, }; if cap_or_empty(&caps, "prog").is_empty() { err!("Could not find program name in doc string.") } self.program = cap_or_empty(&caps, "prog").to_string(); self.usage = caps[0].to_string(); // Before we parse the usage patterns, we look for option descriptions. // We do this because the information in option descriptions can be // used to resolve ambiguities in usage patterns (i.e., whether // `--flag ARG` is a flag with an argument or not). // // From the docopt page, "every" line starting with a `-` or a `--` // is considered an option description. Instead, we restrict the lines // to any line *not* in the usage pattern section. // // *sigh* Apparently the above is not true. The official test suite // includes `Options: -a ...`, which means some lines not beginning // with `-` can actually have options. let (pstart, pend) = caps.get(0).map(|m|(m.start(), m.end())).unwrap(); let (before, after) = (&doc[..pstart], &doc[pend..]); // We process every line here (instead of restricting to lines starting // with "-") because we need to check every line for a default value. // The default value always belongs to the most recently defined desc. for line in before.lines().chain(after.lines()) { self.parse_desc(line)?; } let mprog = format!( "^(?:{})?\\s*(.*?)\\s*$", regex::escape(cap_or_empty(&caps, "prog"))); let pats = Regex::new(&*mprog).unwrap(); if cap_or_empty(&caps, "pats").is_empty() { let pattern = PatParser::new(self, "").parse()?; self.usages.push(pattern); } else { for line in cap_or_empty(&caps, "pats").lines() { for pat in pats.captures_iter(line.trim()) { let pattern = PatParser::new(self, &pat[1]).parse()?; self.usages.push(pattern); } } } Ok(()) } fn parse_desc(&mut self, full_desc: &str) -> Result<(), String> { lazy_static! { static ref OPTIONS: Regex = regex!(r"^\s*(?i:options:)\s*"); static ref ISFLAG: Regex = regex!(r"^(-\S|--\S)"); static ref REMOVE_DESC: Regex = regex!(r" .*$"); static ref NORMALIZE_FLAGS: Regex = regex!(r"([^-\s]), -"); static ref FIND_FLAGS: Regex = regex!(r"(?x) (?:(?P--[^\x20\t=]+)|(?P-[^\x20\t=]+)) (?:(?:\x20|=)(?P[^.-]\S*))? (?P\x20\.\.\.)? "); } let desc = OPTIONS.replace(full_desc.trim(), ""); let desc = &*desc; if !ISFLAG.is_match(desc) { self.parse_default(full_desc)?; return Ok(()) } // Get rid of the description, which must be at least two spaces // after the flag or argument. let desc = REMOVE_DESC.replace(desc, ""); // Normalize `-x, --xyz` to `-x --xyz`. let desc = NORMALIZE_FLAGS.replace(&desc, "$1 -"); let desc = desc.trim(); let (mut short, mut long) = <(String, String)>::default(); let mut has_arg = false; let mut last_end = 0; let mut repeated = false; for flags in FIND_FLAGS.captures_iter(desc) { last_end = flags.get(0).unwrap().end(); if !cap_or_empty(&flags, "repeated").is_empty() { // If the "repeated" subcapture is not empty, then we have // a valid repeated option. repeated = true; } let (s, l) = ( cap_or_empty(&flags, "short"), cap_or_empty(&flags, "long"), ); if !s.is_empty() { if !short.is_empty() { err!("Only one short flag is allowed in an option \ description, but found '{}' and '{}'.", short, s) } short = s.into() } if !l.is_empty() { if !long.is_empty() { err!("Only one long flag is allowed in an option \ description, but found '{}' and '{}'.", long, l) } long = l.into() } if let Some(arg) = flags.name("arg").map(|m| m.as_str()) { if !arg.is_empty() { if !Atom::is_arg(arg) { err!("Argument '{}' is not of the form ARG or .", arg) } has_arg = true; // may be changed to default later } } } // Make sure that we consumed everything. If there are leftovers, // then there is some malformed description. Alert the user. assert!(last_end <= desc.len()); if last_end < desc.len() { err!("Extraneous text '{}' in option description '{}'.", &desc[last_end..], desc) } self.add_desc(&short, &long, has_arg, repeated)?; // Looking for default in this line must come after adding the // description, otherwise `parse_default` won't know which option // to assign it to. self.parse_default(full_desc) } fn parse_default(&mut self, desc: &str) -> Result<(), String> { lazy_static! { static ref FIND_DEFAULT: Regex = regex!( r"\[(?i:default):(?P.*)\]" ); } let defval = match FIND_DEFAULT.captures(desc) { None => return Ok(()), Some(c) => cap_or_empty(&c, "val").trim(), }; let last_atom = match self.last_atom_added { None => err!("Found default value '{}' in '{}' before first \ option description.", defval, desc), Some(ref atom) => atom, }; let opts = self.descs .find_mut(last_atom) .expect(&*format!("BUG: last opt desc key ('{:?}') is invalid.", last_atom)); match opts.arg { One(None) => {}, // OK Zero => err!("Cannot assign default value '{}' to flag '{}' \ that has no arguments.", defval, last_atom), One(Some(ref curval)) => err!("Flag '{}' already has a default value \ of '{}' (second default value: '{}').", last_atom, curval, defval), } opts.arg = One(Some(defval.into())); Ok(()) } fn add_desc( &mut self, short: &str, long: &str, has_arg: bool, repeated: bool, ) -> Result<(), String> { assert!(!short.is_empty() || !long.is_empty()); if !short.is_empty() && short.chars().count() != 2 { // It looks like the reference implementation just ignores // these lines. return Ok(()); } let mut opts = Options::new( repeated, if has_arg { One(None) } else { Zero }); opts.is_desc = true; if !short.is_empty() && !long.is_empty() { let (short, long) = (Atom::new(short), Atom::new(long)); self.descs.insert(long.clone(), opts); self.descs.insert_synonym(short, long.clone()); self.last_atom_added = Some(long); } else if !short.is_empty() { let short = Atom::new(short); self.descs.insert(short.clone(), opts); self.last_atom_added = Some(short); } else if !long.is_empty() { let long = Atom::new(long); self.descs.insert(long.clone(), opts); self.last_atom_added = Some(long); } Ok(()) } } impl fmt::Debug for Parser { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { fn sorted(mut xs: Vec) -> Vec { xs.sort(); xs } writeln!(f, "=====")?; writeln!(f, "Program: {}", self.program)?; writeln!(f, "Option descriptions:")?; let keys = sorted(self.descs.keys().collect()); for &k in &keys { writeln!(f, " '{}' => {:?}", k, self.descs.get(k))?; } writeln!(f, "Synonyms:")?; let keys: Vec<(&Atom, &Atom)> = sorted(self.descs.synonyms().collect()); for &(from, to) in &keys { writeln!(f, " {:?} => {:?}", from, to)?; } writeln!(f, "Usages:")?; for pat in &self.usages { writeln!(f, " {:?}", pat)?; } writeln!(f, "=====") } } struct PatParser<'a> { dopt: &'a mut Parser, tokens: Vec, // used while parsing a single usage pattern curi: usize, // ^^ index into pattern chars expecting: Vec, // stack of expected ']' or ')' } impl<'a> PatParser<'a> { fn new(dopt: &'a mut Parser, pat: &str) -> PatParser<'a> { PatParser { dopt: dopt, tokens: pattern_tokens(pat), curi: 0, expecting: vec!(), } } fn parse(&mut self) -> Result { // let mut seen = HashSet::new(); let mut p = self.pattern()?; match self.expecting.pop() { None => {}, Some(c) => err!("Unclosed group. Expected '{}'.", c), } p.add_options_shortcut(self.dopt); p.tag_repeats(&mut self.dopt.descs); Ok(p) } fn pattern(&mut self) -> Result { let mut alts = vec!(); let mut seq = vec!(); while !self.is_eof() { match self.cur() { "..." => { err!("'...' must appear directly after a group, argument, \ flag or command.") } "-" | "--" => { // As per specification, `-` and `--` by themselves are // just commands that should be interpreted conventionally. seq.push(self.command()?); } "|" => { if seq.is_empty() { err!("Unexpected '|'. Not in form 'a | b | c'.") } self.next_noeof("pattern")?; alts.push(Sequence(seq)); seq = vec!(); } "]" | ")" => { if seq.is_empty() { err!("Unexpected '{}'. Empty groups are not allowed.", self.cur()) } match self.expecting.pop() { None => err!("Unexpected '{}'. No open bracket found.", self.cur()), Some(c) => { if c != self.cur().chars().next().unwrap() { err!("Expected '{}' but got '{}'.", c, self.cur()) } } } let mk: fn(Vec) -> Pattern = if self.cur() == "]" { Optional } else { Sequence }; self.next(); return if alts.is_empty() { Ok(mk(seq)) } else { alts.push(Sequence(seq)); Ok(mk(vec!(Alternates(alts)))) } } "[" => { // Check for special '[options]' shortcut. if self.atis(1, "options") && self.atis(2, "]") { self.next(); // cur == options self.next(); // cur == ] self.next(); seq.push(self.maybe_repeat(Optional(vec!()))); continue } self.expecting.push(']'); seq.push(self.group()?); } "(" => { self.expecting.push(')'); seq.push(self.group()?); } _ => { if Atom::is_short(self.cur()) { seq.extend(self.flag_short()?.into_iter()); } else if Atom::is_long(self.cur()) { seq.push(self.flag_long()?); } else if Atom::is_arg(self.cur()) { // These are always positional. // Arguments for -s and --short are picked up // when parsing flags. seq.push(self.positional()?); } else if Atom::is_cmd(self.cur()) { seq.push(self.command()?); } else { err!("Unknown token type '{}'.", self.cur()) } } } } if alts.is_empty() { Ok(Sequence(seq)) } else { alts.push(Sequence(seq)); Ok(Alternates(alts)) } } fn flag_short(&mut self) -> Result, String> { let mut seq = vec!(); let stacked: String = self.cur()[1..].into(); for (i, c) in stacked.chars().enumerate() { let atom = self.dopt.descs.resolve(&Short(c)); let mut pat = PatAtom(atom.clone()); if self.dopt.has_repeat(&atom) { pat = Pattern::repeat(pat); } seq.push(pat); // The only way for a short option to have an argument is if // it's specified in an option description. if !self.dopt.has_arg(&atom) { self.add_atom_ifnotexists(Zero, &atom); } else { // At this point, the flag MUST have an argument. Therefore, // we interpret the "rest" of the characters as the argument. // If the "rest" is empty, then we peek to find and make sure // there is an argument. let rest = &stacked[i+1..]; if rest.is_empty() { self.next_flag_arg(&atom)?; } else { self.errif_invalid_flag_arg(&atom, rest)?; } // We either error'd or consumed the rest of the short stack as // an argument. break } } self.next(); // This is a little weird. We've got to manually look for a repeat // operator right after the stack, and then apply it to each short // flag we generated. // If "sequences" never altered semantics, then we could just use that // here to group a short stack. if self.atis(0, "...") { self.next(); seq = seq.into_iter().map(Pattern::repeat).collect(); } Ok(seq) } fn flag_long(&mut self) -> Result { let (atom, arg) = parse_long_equal(self.cur())?; let atom = self.dopt.descs.resolve(&atom); if self.dopt.descs.contains_key(&atom) { // Options already exist for this atom, so we must check to make // sure things are consistent. let has_arg = self.dopt.has_arg(&atom); if arg.has_arg() && !has_arg { // Found `=` in usage, but previous usage of this flag // didn't specify an argument. err!("Flag '{}' does not take any arguments.", atom) } else if !arg.has_arg() && has_arg { // Didn't find any `=` in usage for this flag, but previous // usage of this flag specifies an argument. // So look for `--flag ARG` self.next_flag_arg(&atom)?; // We don't care about the value of `arg` since options // already exist. (In which case, the argument value can never // change.) } } self.add_atom_ifnotexists(arg, &atom); self.next(); let pat = if self.dopt.has_repeat(&atom) { Pattern::repeat(PatAtom(atom)) } else { PatAtom(atom) }; Ok(self.maybe_repeat(pat)) } fn next_flag_arg(&mut self, atom: &Atom) -> Result<(), String> { self.next_noeof(&*format!("argument for flag '{}'", atom))?; self.errif_invalid_flag_arg(atom, self.cur()) } fn errif_invalid_flag_arg(&self, atom: &Atom, arg: &str) -> Result<(), String> { if !Atom::is_arg(arg) { err!("Expected argument for flag '{}', but found \ malformed argument '{}'.", atom, arg) } Ok(()) } fn command(&mut self) -> Result { let atom = Atom::new(self.cur()); self.add_atom_ifnotexists(Zero, &atom); self.next(); Ok(self.maybe_repeat(PatAtom(atom))) } fn positional(&mut self) -> Result { let atom = Atom::new(self.cur()); self.add_atom_ifnotexists(Zero, &atom); self.next(); Ok(self.maybe_repeat(PatAtom(atom))) } fn add_atom_ifnotexists(&mut self, arg: Argument, atom: &Atom) { if !self.dopt.descs.contains_key(atom) { let opts = Options::new(false, arg); self.dopt.descs.insert(atom.clone(), opts); } } fn group(&mut self) -> Result { self.next_noeof("pattern")?; let pat = self.pattern()?; Ok(self.maybe_repeat(pat)) } fn maybe_repeat(&mut self, pat: Pattern) -> Pattern { if self.atis(0, "...") { self.next(); Pattern::repeat(pat) } else { pat } } fn is_eof(&self) -> bool { self.curi == self.tokens.len() } fn next(&mut self) { if self.curi == self.tokens.len() { return } self.curi += 1; } fn next_noeof(&mut self, expected: &str) -> Result<(), String> { self.next(); if self.curi == self.tokens.len() { err!("Expected {} but reached end of usage pattern.", expected) } Ok(()) } fn cur(&self) -> &str { &*self.tokens[self.curi] } fn atis(&self, offset: usize, is: &str) -> bool { let i = self.curi + offset; i < self.tokens.len() && self.tokens[i] == is } } #[derive(Clone, Debug)] enum Pattern { Alternates(Vec), Sequence(Vec), Optional(Vec), Repeat(Box), PatAtom(Atom), } #[derive(PartialEq, Eq, Ord, Hash, Clone, Debug)] pub enum Atom { Short(char), Long(String), Command(String), Positional(String), } #[derive(Clone, Debug)] pub struct Options { /// Set to true if this atom is ever repeated in any context. /// For positional arguments, non-argument flags and commands, repetition /// means that they become countable. /// For flags with arguments, repetition means multiple distinct values /// can be specified (and are represented as a Vec). pub repeats: bool, /// This specifies whether this atom has any arguments. /// For commands and positional arguments, this is always Zero. /// Flags can have zero or one argument, with an optionally default value. pub arg: Argument, /// Whether it shows up in the "options description" second. pub is_desc: bool, } #[derive(Clone, Debug, PartialEq)] pub enum Argument { Zero, One(Option), // optional default value } impl Pattern { fn add_options_shortcut(&mut self, par: &Parser) { fn add(pat: &mut Pattern, all_atoms: &HashSet, par: &Parser) { match *pat { Alternates(ref mut ps) | Sequence(ref mut ps) => { for p in ps.iter_mut() { add(p, all_atoms, par) } } Repeat(ref mut p) => add(&mut **p, all_atoms, par), PatAtom(_) => {} Optional(ref mut ps) => { if !ps.is_empty() { for p in ps.iter_mut() { add(p, all_atoms, par) } } else { for atom in par.options_atoms().into_iter() { if !all_atoms.contains(&atom) { if par.has_repeat(&atom) { ps.push(Pattern::repeat(PatAtom(atom))); } else { ps.push(PatAtom(atom)); } } } } } } } let all_atoms = self.all_atoms(); add(self, &all_atoms, par); } fn all_atoms(&self) -> HashSet { fn all_atoms(pat: &Pattern, set: &mut HashSet) { match *pat { Alternates(ref ps) | Sequence(ref ps) | Optional(ref ps) => { for p in ps.iter() { all_atoms(p, set) } } Repeat(ref p) => all_atoms(&**p, set), PatAtom(ref a) => { set.insert(a.clone()); } } } let mut set = HashSet::new(); all_atoms(self, &mut set); set } fn tag_repeats(&self, map: &mut SynonymMap) { fn dotag(p: &Pattern, rep: bool, map: &mut SynonymMap, seen: &mut HashSet) { match *p { Alternates(ref ps) => { // This is a bit tricky. Basically, we don't want the // existence of an item in mutually exclusive alternations // to affect whether it repeats or not. // However, we still need to record seeing each item in // each alternation. let fresh = seen.clone(); for p in ps.iter() { let mut isolated = fresh.clone(); dotag(p, rep, map, &mut isolated); for a in isolated.into_iter() { seen.insert(a); } } } Sequence(ref ps) => { for p in ps.iter() { dotag(p, rep, map, seen) } } Optional(ref ps) => { for p in ps.iter() { dotag(p, rep, map, seen) } } Repeat(ref p) => dotag(&**p, true, map, seen), PatAtom(ref atom) => { let opt = map.find_mut(atom).expect("bug: no atom found"); opt.repeats = opt.repeats || rep || seen.contains(atom); seen.insert(atom.clone()); } } } let mut seen = HashSet::new(); dotag(self, false, map, &mut seen); } fn repeat(p: Pattern) -> Pattern { match p { p @ Repeat(_) => p, p => Repeat(Box::new(p)), } } } impl Atom { pub fn new(s: &str) -> Atom { if Atom::is_short(s) { Short(s[1..].chars().next().unwrap()) } else if Atom::is_long(s) { Long(s[2..].into()) } else if Atom::is_arg(s) { if s.starts_with("<") && s.ends_with(">") { Positional(s[1..s.len()-1].into()) } else { Positional(s.into()) } } else if Atom::is_cmd(s) { Command(s.into()) } else { panic!("Unknown atom string: '{}'", s) } } fn is_short(s: &str) -> bool { lazy_static! { static ref RE: Regex = regex!(r"^-[^-]\S*$"); } RE.is_match(s) } fn is_long(s: &str) -> bool { lazy_static! { static ref RE: Regex = regex!(r"^--\S+(?:<[^>]+>)?$"); } RE.is_match(s) } fn is_long_argv(s: &str) -> bool { lazy_static! { static ref RE: Regex = regex!(r"^--\S+(=.+)?$"); } RE.is_match(s) } fn is_arg(s: &str) -> bool { lazy_static! { static ref RE: Regex = regex!(r"^(\p{Lu}+|<[^>]+>)$"); } RE.is_match(s) } fn is_cmd(s: &str) -> bool { lazy_static! { static ref RE: Regex = regex!(r"^(-|--|[^-]\S*)$"); } RE.is_match(s) } // Assigns an integer to each variant of Atom. (For easier sorting.) fn type_as_usize(&self) -> usize { match *self { Short(_) => 0, Long(_) => 1, Command(_) => 2, Positional(_) => 3, } } } impl PartialOrd for Atom { fn partial_cmp(&self, other: &Atom) -> Option { match (self, other) { (&Short(c1), &Short(c2)) => c1.partial_cmp(&c2), (&Long(ref s1), &Long(ref s2)) => s1.partial_cmp(s2), (&Command(ref s1), &Command(ref s2)) => s1.partial_cmp(s2), (&Positional(ref s1), &Positional(ref s2)) => s1.partial_cmp(s2), (a1, a2) => a1.type_as_usize().partial_cmp(&a2.type_as_usize()), } } } impl fmt::Display for Atom { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Short(c) => write!(f, "-{}", c), Long(ref s) => write!(f, "--{}", s), Command(ref s) => write!(f, "{}", s), Positional(ref s) => { if s.chars().all(|c| c.is_uppercase()) { write!(f, "{}", s) } else { write!(f, "<{}>", s) } } } } } impl Options { fn new(rep: bool, arg: Argument) -> Options { Options { repeats: rep, arg: arg, is_desc: false, } } } impl Argument { fn has_arg(&self) -> bool { match *self { Zero => false, One(_) => true, } } } #[doc(hidden)] pub struct Argv<'a> { /// A representation of an argv string as an ordered list of tokens. /// This contains only positional arguments and commands. positional: Vec, /// Same as positional, but contains short and long flags. /// Each flag may have an argument string. flags: Vec, /// Counts the number of times each flag appears. counts: HashMap, // State for parser. dopt: &'a Parser, argv: Vec, curi: usize, options_first: bool, } #[derive(Clone, Debug)] struct ArgvToken { atom: Atom, arg: Option, } impl<'a> Argv<'a> { fn new(dopt: &'a Parser, argv: Vec, options_first: bool) -> Result, String> { let mut a = Argv { positional: vec!(), flags: vec!(), counts: HashMap::new(), dopt: dopt, argv: argv.iter().cloned().collect(), curi: 0, options_first: options_first, }; a.parse()?; for flag in &a.flags { match a.counts.entry(flag.atom.clone()) { Vacant(v) => { v.insert(1); } Occupied(mut v) => { *v.get_mut() += 1; } } } Ok(a) } fn parse(&mut self) -> Result<(), String> { let mut seen_double_dash = false; while self.curi < self.argv.len() { let do_flags = !seen_double_dash && (!self.options_first || self.positional.is_empty()); if do_flags && Atom::is_short(self.cur()) { let stacked: String = self.cur()[1..].into(); for (i, c) in stacked.chars().enumerate() { let mut tok = ArgvToken { atom: self.dopt.descs.resolve(&Short(c)), arg: None, }; if !self.dopt.descs.contains_key(&tok.atom) { err!("Unknown flag: '{}'", &tok.atom); } if !self.dopt.has_arg(&tok.atom) { self.flags.push(tok); } else { let rest = &stacked[i+1..]; tok.arg = Some( if rest.is_empty() { let arg = self.next_arg(&tok.atom)?; arg.into() } else { rest.into() } ); self.flags.push(tok); // We've either produced an error or gobbled up the // rest of these stacked short flags, so stop. break } } } else if do_flags && Atom::is_long_argv(self.cur()) { let (atom, mut arg) = parse_long_equal_argv(self.cur()); let atom = self.dopt.descs.resolve(&atom); if !self.dopt.descs.contains_key(&atom) { return self.err_unknown_flag(&atom) } if arg.is_some() && !self.dopt.has_arg(&atom) { err!("Flag '{}' cannot have an argument, but found '{}'.", &atom, arg.as_ref().unwrap()) } else if arg.is_none() && self.dopt.has_arg(&atom) { self.next_noeof(&*format!("argument for flag '{}'", &atom))?; arg = Some(self.cur().into()); } self.flags.push(ArgvToken { atom: atom, arg: arg }); } else { if !seen_double_dash && self.cur() == "--" { seen_double_dash = true; } else { // Yup, we *always* insert a positional argument, which // means we completely neglect `Command` here. // This is because we can't tell whether something is a // `command` or not until we start pattern matching. let tok = ArgvToken { atom: Positional(self.cur().into()), arg: None, }; self.positional.push(tok); } } self.next() } Ok(()) } fn err_unknown_flag(&self, atom: &Atom) -> Result<(), String> { use std::usize::MAX; let mut best = String::new(); let flag = atom.to_string(); let mut min = MAX; let mut possibles = Vec::new(); for (key, _) in self.dopt.descs.synonyms() { possibles.push(key); } for key in self.dopt.descs.keys() { possibles.push(key); } for key in &possibles { match **key { Long(_) | Command(_) => { let name = key.to_string(); let dist = levenshtein(&flag, &name); if dist < 3 && dist < min { min = dist; best = name; } } _ => {} } } if best.is_empty() { err!("Unknown flag: '{}'", &atom); } else { err!("Unknown flag: '{}'. Did you mean '{}'?", &atom, &best) } } fn cur(&self) -> &str { self.at(0) } fn at(&self, i: usize) -> &str { &*self.argv[self.curi + i] } fn next(&mut self) { if self.curi < self.argv.len() { self.curi += 1 } } fn next_arg(&mut self, atom: &Atom) -> Result<&str, String> { let expected = format!("argument for flag '{}'", atom); self.next_noeof(&*expected)?; Ok(self.cur()) } fn next_noeof(&mut self, expected: &str) -> Result<(), String> { self.next(); if self.curi == self.argv.len() { err!("Expected {} but reached end of arguments.", expected) } Ok(()) } } impl<'a> fmt::Debug for Argv<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { writeln!(f, "Positional: {:?}", self.positional)?; writeln!(f, "Flags: {:?}", self.flags)?; writeln!(f, "Counts: {:?}", self.counts)?; Ok(()) } } struct Matcher<'a, 'b:'a> { argv: &'a Argv<'b>, } #[derive(Clone, Debug, PartialEq)] struct MState { argvi: usize, // index into Argv.positional counts: HashMap, // flags remaining for pattern consumption max_counts: HashMap, // optional flag appearances vals: HashMap, } impl MState { fn fill_value(&mut self, key: Atom, rep: bool, arg: Option) -> bool { match (arg, rep) { (None, false) => { self.vals.insert(key, Switch(true)); } (Some(arg), false) => { self.vals.insert(key, Plain(Some(arg))); } (None, true) => { match self.vals.entry(key) { Vacant(v) => { v.insert(Counted(1)); } Occupied(mut v) => { match *v.get_mut() { Counted(ref mut c) => { *c += 1; } _ => return false, } } } } (Some(arg), true) => { match self.vals.entry(key) { Vacant(v) => { v.insert(List(vec!(arg))); } Occupied(mut v) => { match *v.get_mut() { List(ref mut vs) => vs.push(arg), _ => return false, } } } } } true } fn add_value(&mut self, opts: &Options, spec: &Atom, atom: &Atom, arg: &Option) -> bool { assert!(opts.arg.has_arg() == arg.is_some(), "'{:?}' should have an argument but doesn't", atom); match *atom { Short(_) | Long(_) => { self.fill_value(spec.clone(), opts.repeats, arg.clone()) } Positional(ref v) => { assert!(!opts.arg.has_arg()); self.fill_value(spec.clone(), opts.repeats, Some(v.clone())) } Command(_) => { assert!(!opts.arg.has_arg()); self.fill_value(spec.clone(), opts.repeats, None) } } } fn use_flag(&mut self, flag: &Atom) -> bool { match self.max_counts.entry(flag.clone()) { Vacant(v) => { v.insert(0); } Occupied(_) => {} } match self.counts.entry(flag.clone()) { Vacant(_) => { false } Occupied(mut v) => { let c = v.get_mut(); if *c == 0 { false } else { *c -= 1; true } } } } fn use_optional_flag(&mut self, flag: &Atom) { match self.max_counts.entry(flag.clone()) { Vacant(v) => { v.insert(1); } Occupied(mut v) => { *v.get_mut() += 1; } } } fn match_cmd_or_posarg(&mut self, spec: &Atom, argv: &ArgvToken) -> Option { match (spec, &argv.atom) { (_, &Command(_)) => { // This is impossible because the argv parser doesn't know // how to produce `Command` values. unreachable!() } (&Command(ref n1), &Positional(ref n2)) if n1 == n2 => { // Coerce a positional to a command because the pattern // demands it and the positional argument matches it. self.argvi += 1; Some(ArgvToken { atom: spec.clone(), arg: None }) } (&Positional(_), _) => { self.argvi += 1; Some(argv.clone()) } _ => None, } } } impl<'a, 'b> Matcher<'a, 'b> { fn matches(argv: &'a Argv, pat: &Pattern) -> Option> { let m = Matcher { argv: argv }; let init = MState { argvi: 0, counts: argv.counts.clone(), max_counts: HashMap::new(), vals: HashMap::new(), }; m.states(pat, &init) .into_iter() .filter(|s| m.state_consumed_all_argv(s)) .filter(|s| m.state_has_valid_flags(s)) .filter(|s| m.state_valid_num_flags(s)) .collect::>() .into_iter() .next() .map(|mut s| { m.add_flag_values(&mut s); m.add_default_values(&mut s); // Build a synonym map so that it's easier to look up values. let mut synmap: SynonymMap = s.vals.into_iter() .map(|(k, v)| (k.to_string(), v)) .collect(); for (from, to) in argv.dopt.descs.synonyms() { let (from, to) = (from.to_string(), to.to_string()); if synmap.contains_key(&to) { synmap.insert_synonym(from, to); } } synmap }) } fn token_from(&self, state: &MState) -> Option<&ArgvToken> { self.argv.positional.get(state.argvi) } fn add_value(&self, state: &mut MState, atom_spec: &Atom, atom: &Atom, arg: &Option) -> bool { let opts = self.argv.dopt.descs.get(atom_spec); state.add_value(opts, atom_spec, atom, arg) } fn add_flag_values(&self, state: &mut MState) { for tok in &self.argv.flags { self.add_value(state, &tok.atom, &tok.atom, &tok.arg); } } fn add_default_values(&self, state: &mut MState) { lazy_static! { static ref SPLIT_SPACE: Regex = regex!(r"\s+"); } let vs = &mut state.vals; for (a, opts) in self.argv.dopt.descs.iter() { if vs.contains_key(a) { continue } let atom = a.clone(); match (opts.repeats, &opts.arg) { (false, &Zero) => { match *a { Positional(_) => vs.insert(atom, Plain(None)), _ => vs.insert(atom, Switch(false)), }; } (true, &Zero) => { match *a { Positional(_) => vs.insert(atom, List(vec!())), _ => vs.insert(atom, Counted(0)), }; } (false, &One(None)) => { vs.insert(atom, Plain(None)); } (true, &One(None)) => { vs.insert(atom, List(vec!())); } (false, &One(Some(ref v))) => { vs.insert(atom, Plain(Some(v.clone()))); } (true, &One(Some(ref v))) => { let words = SPLIT_SPACE .split(v) .map(|s| s.to_owned()) .collect(); vs.insert(atom, List(words)); } } } } fn state_consumed_all_argv(&self, state: &MState) -> bool { self.argv.positional.len() == state.argvi } fn state_has_valid_flags(&self, state: &MState) -> bool { self.argv.counts.keys().all(|flag| state.max_counts.contains_key(flag)) } fn state_valid_num_flags(&self, state: &MState) -> bool { state.counts.iter().all( |(flag, count)| count <= &state.max_counts[flag]) } fn states(&self, pat: &Pattern, init: &MState) -> Vec { match *pat { Alternates(ref ps) => { let mut alt_states = vec!(); for p in ps.iter() { alt_states.extend(self.states(p, init).into_iter()); } alt_states } Sequence(ref ps) => { let (mut states, mut next) = (vec!(), vec!()); let mut iter = ps.iter(); match iter.next() { None => return vec!(init.clone()), Some(p) => states.extend(self.states(p, init).into_iter()), } for p in iter { for s in states.into_iter() { next.extend(self.states(p, &s).into_iter()); } states = vec!(); states.extend(next.into_iter()); next = vec!(); } states } Optional(ref ps) => { let mut base = init.clone(); let mut noflags = vec!(); for p in ps.iter() { match p { // Prevent exponential growth in cases like [--flag...] // See https://github.com/docopt/docopt.rs/issues/195 &Repeat(ref b) => match &**b { &PatAtom(ref a @ Short(_)) | &PatAtom(ref a @ Long(_)) => { let argv_count = self.argv.counts.get(a) .map_or(0, |&x| x); let max_count = base.max_counts.get(a) .map_or(0, |&x| x); if argv_count > max_count { for _ in max_count..argv_count { base.use_optional_flag(a); } } } _ => { noflags.push(p); } }, &PatAtom(ref a @ Short(_)) | &PatAtom(ref a @ Long(_)) => { let argv_count = self.argv.counts.get(a) .map_or(0, |&x| x); let max_count = base.max_counts.get(a) .map_or(0, |&x| x); if argv_count > max_count { base.use_optional_flag(a); } } other => { noflags.push(other); } } } let mut states = vec!(); self.all_option_states(&base, &mut states, &*noflags); states } Repeat(ref p) => { match &**p { &PatAtom(ref a @ Short(_)) | &PatAtom(ref a @ Long(_)) => { let mut bases = self.states(&**p, init); for base in &mut bases { let argv_count = self.argv.counts.get(a) .map_or(0, |&x| x); let max_count = base.max_counts.get(a) .map_or(0, |&x| x); if argv_count > max_count { for _ in max_count..argv_count { base.use_optional_flag(a); } } } bases } _ => { let mut grouped_states = vec!(self.states(&**p, init)); loop { let mut nextss = vec!(); for s in grouped_states.last().unwrap().iter() { nextss.extend( self.states(&**p, s) .into_iter() .filter(|snext| snext != s)); } if nextss.is_empty() { break } grouped_states.push(nextss); } grouped_states .into_iter() .flat_map(|ss| ss.into_iter()) .collect::>() } }} PatAtom(ref atom) => { let mut state = init.clone(); match *atom { Short(_) | Long(_) => { if !state.use_flag(atom) { return vec!() } } Command(_) | Positional(_) => { let tok = match self.token_from(init) { None => return vec!(), Some(tok) => tok, }; let tok = match state.match_cmd_or_posarg(atom, tok) { None => return vec!(), Some(tok) => tok, }; if !self.add_value(&mut state, atom, &tok.atom, &tok.arg) { return vec!() } } } vec!(state) } } } fn all_option_states(&self, base: &MState, states: &mut Vec, pats: &[&Pattern]) { if pats.is_empty() { states.push(base.clone()); } else { let (pat, rest) = (*pats.first().unwrap(), &pats[1..]); for s in self.states(pat, base).into_iter() { self.all_option_states(&s, states, rest); } // Order is important here! This must come after the loop above // because we prefer presence over absence. The first state wins. self.all_option_states(base, states, &pats[1..]); } } } // Tries to parse a long flag of the form '--flag[=arg]' and returns a tuple // with the flag atom and whether there is an argument or not. // If '=arg' exists and 'arg' isn't a valid argument, an error is returned. fn parse_long_equal(flag: &str) -> Result<(Atom, Argument), String> { lazy_static! { static ref LONG_EQUAL: Regex = regex!("^(?P[^=]+)=(?P.+)$"); } match LONG_EQUAL.captures(flag) { None => Ok((Atom::new(flag), Zero)), Some(cap) => { let arg = cap_or_empty(&cap, "arg"); if !Atom::is_arg(arg) { err!("Argument '{}' for flag '{}' is not in the \ form ARG or .", flag, arg) } Ok((Atom::new(cap_or_empty(&cap, "name")), One(None))) } } } fn parse_long_equal_argv(flag: &str) -> (Atom, Option) { lazy_static! { static ref LONG_EQUAL: Regex = regex!("^(?P[^=]+)=(?P.*)$"); } match LONG_EQUAL.captures(flag) { None => (Atom::new(flag), None), Some(cap) => ( Atom::new(cap_or_empty(&cap, "name")), Some(cap_or_empty(&cap, "arg").to_string()), ), } } // Tokenizes a usage pattern. // Beware: regex hack ahead. Tokenizes based on whitespace separated words. // It first normalizes `[xyz]` -> `[ xyz ]` so that delimiters are tokens. // Similarly for `...`, `(`, `)` and `|`. // One hitch: `--flag=` is allowed, so we use a regex to pick out // words. fn pattern_tokens(pat: &str) -> Vec { lazy_static! { static ref NORMALIZE: Regex = regex!(r"\.\.\.|\[|\]|\(|\)|\|"); static ref WORDS: Regex = regex!(r"--\S+?=<[^>]+>|<[^>]+>|\S+"); } let pat = NORMALIZE.replace_all(pat.trim(), " $0 "); let mut words = vec!(); for cap in WORDS.captures_iter(&*pat) { words.push(cap[0].to_string()); } words } vendor/docopt-0.8.3/src/synonym.rs0000644000000000000000000000512713264166600015667 0ustar rootrootuse std::collections::HashMap; use std::collections::hash_map::{Iter, Keys}; use std::fmt::Debug; use std::hash::Hash; use std::iter::{FromIterator, IntoIterator}; use std::mem; #[derive(Clone)] pub struct SynonymMap { vals: HashMap, syns: HashMap, } impl SynonymMap { pub fn new() -> SynonymMap { SynonymMap { vals: HashMap::new(), syns: HashMap::new(), } } pub fn insert_synonym(&mut self, from: K, to: K) -> bool { assert!(self.vals.contains_key(&to)); self.syns.insert(from, to).is_none() } pub fn keys(&self) -> Keys { self.vals.keys() } pub fn iter(&self) -> Iter { self.vals.iter() } pub fn synonyms(&self) -> Iter { self.syns.iter() } pub fn find(&self, k: &K) -> Option<&V> { self.with_key(k, |k| self.vals.get(k)) } pub fn contains_key(&self, k: &K) -> bool { self.with_key(k, |k| self.vals.contains_key(k)) } pub fn len(&self) -> usize { self.vals.len() } fn with_key(&self, k: &K, with: F) -> T where F: FnOnce(&K) -> T { if self.syns.contains_key(k) { with(&self.syns[k]) } else { with(k) } } } impl SynonymMap { pub fn resolve(&self, k: &K) -> K { self.with_key(k, |k| k.clone()) } pub fn get<'a>(&'a self, k: &K) -> &'a V { self.find(k).unwrap() } pub fn find_mut<'a>(&'a mut self, k: &K) -> Option<&'a mut V> { if self.syns.contains_key(k) { self.vals.get_mut(&self.syns[k]) } else { self.vals.get_mut(k) } } pub fn swap(&mut self, k: K, mut new: V) -> Option { if self.syns.contains_key(&k) { let old = self.vals.get_mut(&k).unwrap(); mem::swap(old, &mut new); Some(new) } else { self.vals.insert(k, new) } } pub fn insert(&mut self, k: K, v: V) -> bool { self.swap(k, v).is_none() } } impl FromIterator<(K, V)> for SynonymMap { fn from_iter>(iter: T) -> SynonymMap { let mut map = SynonymMap::new(); for (k, v) in iter { map.insert(k, v); } map } } impl Debug for SynonymMap { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { self.vals.fmt(f)?; write!(f, " (synomyns: {:?})", self.syns) } } vendor/docopt-0.8.3/src/test/0000755000000000000000000000000013264166600014557 5ustar rootrootvendor/docopt-0.8.3/src/test/mod.rs0000644000000000000000000000755013264166600015713 0ustar rootrootuse std::collections::HashMap; use {Docopt, ArgvMap, Error}; use Value::{self, Switch, Plain}; fn get_args(doc: &str, argv: &[&'static str]) -> ArgvMap { let dopt = match Docopt::new(doc) { Err(err) => panic!("Invalid usage: {}", err), Ok(dopt) => dopt, }; match dopt.argv(vec!["cmd"].iter().chain(argv.iter())).parse() { Err(err) => panic!("{}", err), Ok(vals) => vals, } } fn map_from_alist(alist: Vec<(&'static str, Value)>) -> HashMap { alist.into_iter().map(|(k, v)| (k.to_string(), v)).collect() } fn same_args(expected: &HashMap, got: &ArgvMap) { for (k, ve) in expected.iter() { match got.map.find(k) { None => panic!("EXPECTED has '{}' but GOT does not.", k), Some(vg) => { assert!(ve == vg, "{}: EXPECTED = '{:?}' != '{:?}' = GOT", k, ve, vg) } } } for (k, vg) in got.map.iter() { match got.map.find(k) { None => panic!("GOT has '{}' but EXPECTED does not.", k), Some(ve) => { assert!(vg == ve, "{}: GOT = '{:?}' != '{:?}' = EXPECTED", k, vg, ve) } } } } macro_rules! test_expect( ($name:ident, $doc:expr, $args:expr, $expected:expr) => ( #[test] fn $name() { let vals = get_args($doc, $args); let expected = map_from_alist($expected); same_args(&expected, &vals); } ); ); macro_rules! test_user_error( ($name:ident, $doc:expr, $args:expr) => ( #[test] #[should_panic] fn $name() { get_args($doc, $args); } ); ); test_expect!(test_issue_13, "Usage: prog file ", &["file", "file"], vec![("file", Switch(true)), ("", Plain(Some("file".to_string())))]); test_expect!(test_issue_129, "Usage: prog [options] Options: --foo ARG Foo foo.", &["--foo=a b"], vec![("--foo", Plain(Some("a b".into())))]); #[test] fn regression_issue_12() { const USAGE: &'static str = " Usage: whisper info whisper update whisper mark "; #[derive(Deserialize, Debug)] struct Args { arg_file: String, cmd_info: bool, cmd_update: bool, arg_timestamp: u64, arg_value: f64, } let dopt: Args = Docopt::new(USAGE) .unwrap() .argv(&["whisper", "mark", "./p/blah", "100"]) .deserialize() .unwrap(); assert_eq!(dopt.arg_timestamp, 0); } #[test] fn regression_issue_195() { const USAGE: &'static str = " Usage: slow [-abcdefghijklmnopqrs...] "; let argv = &["slow", "-abcdefghijklmnopqrs"]; let dopt : Docopt = Docopt::new(USAGE).unwrap().argv(argv); dopt.parse().unwrap(); } #[test] fn regression_issue_219() { #[derive(Deserialize)] struct Args { arg_type: Vec, arg_param: Vec, } const USAGE: &'static str = " Usage: encode [-v ]... "; let argv = &["encode", "-v", "bool", "true", "string", "foo"]; let args: Args = Docopt::new(USAGE).unwrap().argv(argv).deserialize().unwrap(); assert_eq!(args.arg_type, vec!["bool".to_owned(), "string".to_owned()]); assert_eq!(args.arg_param, vec!["true".to_owned(), "foo".to_owned()]); } #[test] fn test_unit_struct() { const USAGE: &'static str = " Usage: cargo version [options] Options: -h, --help Print this message "; #[derive(Deserialize)] struct Options; let argv = &["cargo", "version"]; let dopt: Result= Docopt::new(USAGE) .unwrap() .argv(argv) .deserialize(); assert!(dopt.is_ok()); } mod testcases; mod suggestions; vendor/docopt-0.8.3/src/test/suggestions.rs0000644000000000000000000000410613264166600017500 0ustar rootrootuse {Docopt, Error}; fn get_suggestion(doc: &str, argv: &[&'static str]) -> Error { let dopt = match Docopt::new(doc) { Err(err) => panic!("Invalid usage: {}", err), Ok(dopt) => dopt, }; let mut argv: Vec<_> = argv.iter().map(|x| x.to_string()).collect(); argv.insert(0, "prog".to_string()); match dopt.argv(argv.into_iter()).parse() { Err(err) => err, Ok(_) => panic!("Should have been a user error"), } } macro_rules! test_suggest( ($name:ident, $doc:expr, $args:expr, $expected:expr) => ( #[test] fn $name() { let sg = get_suggestion($doc, $args); println!("{}", sg); match sg { Error::WithProgramUsage(e, _) => { match *e { Error::Argv(msg) => { println!("{:?}",msg); assert_eq!(msg, $expected); } err => panic!("Error other than argv: {:?}", err) } }, _ => panic!("Error without program usage") } } ); ); test_suggest!(test_suggest_1, "Usage: prog [--release]", &["--releas"], "Unknown flag: '--releas'. Did you mean '--release'?"); test_suggest!(test_suggest_2, "Usage: prog [-a] prog [-a] ... prog [-e] Options: -a, --archive Copy everything. ", &["-d"], "Unknown flag: '-d'"); test_suggest!(test_suggest_3, "Usage: prog [-a] prog [-a] ... prog [-e] Options: -a, --archive Copy everything. -e, --export Export all the things. ", &["--expotr"], "Unknown flag: '--expotr'. Did you mean '--export'?"); test_suggest!(test_suggest_4, "Usage: prog [--import] [--complete] ", &["--mport", "--complte"], "Unknown flag: '--mport'. Did you mean '--import'?"); test_suggest!(test_suggest_5, "Usage: prog [--import] [--complete] ", &["--import", "--complte"], "Unknown flag: '--complte'. Did you mean '--complete'?"); vendor/docopt-0.8.3/src/test/testcases.docopt0000644000000000000000000003433313264166600017775 0ustar rootrootr"""Usage: prog """ $ prog {} $ prog --xxx "user-error" r"""Usage: prog [options] Options: -a All. """ $ prog {"-a": false} $ prog -a {"-a": true} $ prog -x "user-error" r"""Usage: prog [options] Options: --all All. """ $ prog {"--all": false} $ prog --all {"--all": true} $ prog --xxx "user-error" r"""Usage: prog [options] Options: -v, --verbose Verbose. """ $ prog --verbose {"--verbose": true} $ prog --ver "user-error" $ prog -v {"--verbose": true} r"""Usage: prog [options] Options: -p PATH """ $ prog -p home/ {"-p": "home/"} $ prog -phome/ {"-p": "home/"} $ prog -p "user-error" r"""Usage: prog [options] Options: --path """ $ prog --path home/ {"--path": "home/"} $ prog --path=home/ {"--path": "home/"} $ prog --pa home/ "user-error" $ prog --pa=home/ "user-error" $ prog --path "user-error" r"""Usage: prog [options] Options: -p PATH, --path= Path to files. """ $ prog -proot {"--path": "root"} r"""Usage: prog [options] Options: -p --path PATH Path to files. """ $ prog -p root {"--path": "root"} $ prog --path root {"--path": "root"} r"""Usage: prog [options] Options: -p PATH Path to files [default: ./] """ $ prog {"-p": "./"} $ prog -phome {"-p": "home"} r"""UsAgE: prog [options] OpTiOnS: --path= Path to files [dEfAuLt: /root] """ $ prog {"--path": "/root"} $ prog --path=home {"--path": "home"} r"""usage: prog [options] options: -a Add -r Remote -m Message """ $ prog -a -r -m Hello {"-a": true, "-r": true, "-m": "Hello"} $ prog -armyourass {"-a": true, "-r": true, "-m": "yourass"} $ prog -a -r {"-a": true, "-r": true, "-m": null} r"""Usage: prog [options] Options: --version --verbose """ $ prog --version {"--version": true, "--verbose": false} $ prog --verbose {"--version": false, "--verbose": true} $ prog --ver "user-error" $ prog --verb "user-error" r"""usage: prog [-a -r -m ] options: -a Add -r Remote -m Message """ $ prog -armyourass {"-a": true, "-r": true, "-m": "yourass"} r"""usage: prog [-armMSG] options: -a Add -r Remote -m Message """ $ prog -a -r -m Hello {"-a": true, "-r": true, "-m": "Hello"} r"""usage: prog -a -b options: -a -b """ $ prog -a -b {"-a": true, "-b": true} $ prog -b -a {"-a": true, "-b": true} $ prog -a "user-error" $ prog "user-error" r"""usage: prog (-a -b) options: -a -b """ $ prog -a -b {"-a": true, "-b": true} $ prog -b -a {"-a": true, "-b": true} $ prog -a "user-error" $ prog "user-error" r"""usage: prog [-a] -b options: -a -b """ $ prog -a -b {"-a": true, "-b": true} $ prog -b -a {"-a": true, "-b": true} $ prog -a "user-error" $ prog -b {"-a": false, "-b": true} $ prog "user-error" r"""usage: prog [(-a -b)] options: -a -b """ $ prog -a -b {"-a": true, "-b": true} $ prog -b -a {"-a": true, "-b": true} $ prog -a "user-error" $ prog -b "user-error" $ prog {"-a": false, "-b": false} r"""usage: prog (-a|-b) options: -a -b """ $ prog -a -b "user-error" $ prog "user-error" $ prog -a {"-a": true, "-b": false} $ prog -b {"-a": false, "-b": true} r"""usage: prog [ -a | -b ] options: -a -b """ $ prog -a -b "user-error" $ prog {"-a": false, "-b": false} $ prog -a {"-a": true, "-b": false} $ prog -b {"-a": false, "-b": true} r"""usage: prog """ $ prog 10 {"": "10"} $ prog 10 20 "user-error" $ prog "user-error" r"""usage: prog []""" $ prog 10 {"": "10"} $ prog 10 20 "user-error" $ prog {"": null} r"""usage: prog """ $ prog 10 20 40 {"": "10", "": "20", "": "40"} $ prog 10 20 "user-error" $ prog "user-error" r"""usage: prog [ ]""" $ prog 10 20 40 {"": "10", "": "20", "": "40"} $ prog 10 20 {"": "10", "": "20", "": null} $ prog "user-error" r"""usage: prog [ | ]""" $ prog 10 20 40 "user-error" $ prog 20 40 {"": null, "": "20", "": "40"} $ prog {"": null, "": null, "": null} r"""usage: prog ( --all | ) options: --all """ $ prog 10 --all {"": "10", "--all": true, "": null} $ prog 10 {"": null, "--all": false, "": "10"} $ prog "user-error" r"""usage: prog [ ]""" $ prog 10 20 {"": ["10", "20"]} $ prog 10 {"": ["10"]} $ prog {"": []} r"""usage: prog [( )]""" $ prog 10 20 {"": ["10", "20"]} $ prog 10 "user-error" $ prog {"": []} r"""usage: prog NAME...""" $ prog 10 20 {"NAME": ["10", "20"]} $ prog 10 {"NAME": ["10"]} $ prog "user-error" r"""usage: prog [NAME]...""" $ prog 10 20 {"NAME": ["10", "20"]} $ prog 10 {"NAME": ["10"]} $ prog {"NAME": []} r"""usage: prog [NAME...]""" $ prog 10 20 {"NAME": ["10", "20"]} $ prog 10 {"NAME": ["10"]} $ prog {"NAME": []} r"""usage: prog [NAME [NAME ...]]""" $ prog 10 20 {"NAME": ["10", "20"]} $ prog 10 {"NAME": ["10"]} $ prog {"NAME": []} r"""usage: prog (NAME | --foo NAME) options: --foo """ $ prog 10 {"NAME": "10", "--foo": false} $ prog --foo 10 {"NAME": "10", "--foo": true} $ prog --foo=10 "user-error" r"""usage: prog (NAME | --foo) [--bar | NAME] options: --foo options: --bar """ $ prog 10 {"NAME": ["10"], "--foo": false, "--bar": false} $ prog 10 20 {"NAME": ["10", "20"], "--foo": false, "--bar": false} $ prog --foo --bar {"NAME": [], "--foo": true, "--bar": true} r"""Naval Fate. Usage: prog ship new ... prog ship [] move [--speed=] prog ship shoot prog mine (set|remove) [--moored|--drifting] prog -h | --help prog --version Options: -h --help Show this screen. --version Show version. --speed= Speed in knots [default: 10]. --moored Mored (anchored) mine. --drifting Drifting mine. """ $ prog ship Guardian move 150 300 --speed=20 {"--drifting": false, "--help": false, "--moored": false, "--speed": "20", "--version": false, "": ["Guardian"], "": "150", "": "300", "mine": false, "move": true, "new": false, "remove": false, "set": false, "ship": true, "shoot": false} r"""usage: prog --hello""" $ prog --hello {"--hello": true} r"""usage: prog [--hello=]""" $ prog {"--hello": null} $ prog --hello wrld {"--hello": "wrld"} r"""usage: prog [-o]""" $ prog {"-o": false} $ prog -o {"-o": true} r"""usage: prog [-opr]""" $ prog -op {"-o": true, "-p": true, "-r": false} r"""usage: prog --aabb | --aa""" $ prog --aa {"--aabb": false, "--aa": true} $ prog --a "user-error" # not a unique prefix # # Counting number of flags # r"""Usage: prog -v""" $ prog -v {"-v": true} r"""Usage: prog [-v -v]""" $ prog {"-v": 0} $ prog -v {"-v": 1} $ prog -vv {"-v": 2} r"""Usage: prog -v ...""" $ prog "user-error" $ prog -v {"-v": 1} $ prog -vv {"-v": 2} $ prog -vvvvvv {"-v": 6} r"""Usage: prog [-v | -vv | -vvv] This one is probably most readable user-friednly variant. """ $ prog {"-v": 0} $ prog -v {"-v": 1} $ prog -vv {"-v": 2} $ prog -vvvv "user-error" r"""usage: prog [--ver --ver]""" $ prog --ver --ver {"--ver": 2} # # Counting commands # r"""usage: prog [go]""" $ prog go {"go": true} r"""usage: prog [go go]""" $ prog {"go": 0} $ prog go {"go": 1} $ prog go go {"go": 2} $ prog go go go "user-error" r"""usage: prog go...""" $ prog go go go go go {"go": 5} # # [options] does not include options from usage-pattern # r"""usage: prog [options] [-a] options: -a -b """ $ prog -a {"-a": true, "-b": false} $ prog -aa "user-error" # # Test [options] shourtcut # r"""Usage: prog [options] A Options: -q Be quiet -v Be verbose. """ $ prog arg {"A": "arg", "-v": false, "-q": false} $ prog -v arg {"A": "arg", "-v": true, "-q": false} $ prog -q arg {"A": "arg", "-v": false, "-q": true} # # Test single dash # r"""usage: prog [-]""" $ prog - {"-": true} $ prog {"-": false} # # If argument is repeated, its value should always be a list # r"""usage: prog [NAME [NAME ...]]""" $ prog a b {"NAME": ["a", "b"]} $ prog {"NAME": []} # # Option's argument defaults to null/None # r"""usage: prog [options] options: -a Add -m Message """ $ prog -a {"-m": null, "-a": true} # # Test options without description # r"""usage: prog --hello""" $ prog --hello {"--hello": true} r"""usage: prog [--hello=]""" $ prog {"--hello": null} $ prog --hello wrld {"--hello": "wrld"} r"""usage: prog [-o]""" $ prog {"-o": false} $ prog -o {"-o": true} r"""usage: prog [-opr]""" $ prog -op {"-o": true, "-p": true, "-r": false} r"""usage: git [-v | --verbose]""" $ prog -v {"-v": true, "--verbose": false} r"""usage: git remote [-v | --verbose]""" $ prog remote -v {"remote": true, "-v": true, "--verbose": false} # # Test empty usage pattern # r"""usage: prog""" $ prog {} r"""usage: prog prog """ $ prog 1 2 {"": "1", "": "2"} $ prog {"": null, "": null} r"""usage: prog prog """ $ prog {"": null, "": null} # # Option's argument should not capture default value from usage pattern # r"""usage: prog [--file=]""" $ prog {"--file": null} r"""usage: prog [--file=] options: --file """ $ prog {"--file": null} r"""Usage: prog [-a ] Options: -a, --address TCP address [default: localhost:6283]. """ $ prog {"--address": "localhost:6283"} # # If option with argument could be repeated, # its arguments should be accumulated into a list # r"""usage: prog --long= ...""" $ prog --long one {"--long": ["one"]} $ prog --long one --long two {"--long": ["one", "two"]} # # Test multiple elements repeated at once # r"""usage: prog (go --speed=)...""" $ prog go left --speed=5 go right --speed=9 {"go": 2, "": ["left", "right"], "--speed": ["5", "9"]} # # Required options should work with option shortcut # r"""usage: prog [options] -a options: -a """ $ prog -a {"-a": true} # # If option could be repeated its defaults should be split into a list # r"""usage: prog [-o ]... options: -o [default: x] """ $ prog -o this -o that {"-o": ["this", "that"]} $ prog {"-o": ["x"]} r"""usage: prog [-o ]... options: -o [default: x y] """ $ prog -o this {"-o": ["this"]} $ prog {"-o": ["x", "y"]} # # Test stacked option's argument # r"""usage: prog -pPATH options: -p PATH """ $ prog -pHOME {"-p": "HOME"} # # Issue 56: Repeated mutually exclusive args give nested lists sometimes # r"""Usage: foo (--xx=X|--yy=Y)...""" $ prog --xx=1 --yy=2 {"--xx": ["1"], "--yy": ["2"]} # # POSIXly correct tokenization # r"""usage: prog []""" $ prog f.txt {"": "f.txt"} r"""usage: prog [--input=]...""" $ prog --input a.txt --input=b.txt {"--input": ["a.txt", "b.txt"]} # # Issue 85: `[options]` shourtcut with multiple subcommands # r"""usage: prog good [options] prog fail [options] options: --loglevel=N """ $ prog fail --loglevel 5 {"--loglevel": "5", "fail": true, "good": false} # # Usage-section syntax # r"""usage:prog --foo""" $ prog --foo {"--foo": true} r"""PROGRAM USAGE: prog --foo""" $ prog --foo {"--foo": true} r"""Usage: prog --foo prog --bar NOT PART OF SECTION""" $ prog --foo {"--foo": true, "--bar": false} r"""Usage: prog --foo prog --bar NOT PART OF SECTION""" $ prog --foo {"--foo": true, "--bar": false} r"""Usage: prog --foo prog --bar NOT PART OF SECTION""" $ prog --foo {"--foo": true, "--bar": false} # # Options-section syntax # r"""Usage: prog [options] global options: --foo local options: --baz --bar other options: --egg --spam -not-an-option- """ $ prog --bar --egg {"--bar": true, "--egg": true, "--spam": false} r"""Usage: prog [-a] [--] [...]""" $ program -a {"-a": true, "": []} r"""Usage: prog [-a] [--] [...]""" $ program -- {"-a": false, "": []} r"""Usage: prog [-a] [--] [...]""" $ program -a -- -b {"-a": true, "": ["-b"]} r"""Usage: prog [-a] [--] [...]""" $ program -a -- -a {"-a": true, "": ["-a"]} r"""Usage: prog [-a] [--] [...]""" $ program -- -a {"-a": false, "": ["-a"]} r"""Usage: prog test [options] [--] [...]""" $ program test a -- -b {"": ["a", "-b"]} r"""Usage: prog test [options] [--] [...]""" $ program test -- -b {"": ["-b"]} r"""Usage: prog test [options] [--] [...]""" $ program test a -b "user-error" r"""Usage: prog test [options] [--] [...]""" $ program test -- -b -- {"": ["-b", "--"]} r"""Usage: prog [options] Options: -a ... Foo """ $ program {"-a": 0} $ program -a {"-a": 1} $ program -a -a {"-a": 2} $ program -aa {"-a": 2} $ program -a -a -a {"-a": 3} $ program -aaa {"-a": 3} r"""Usage: prog [options] Options: -a, --all ... Foo """ $ program {"-a": 0} $ program -a {"-a": 1} $ program -a --all {"-a": 2} $ program -aa --all {"-a": 3} $ program --all {"-a": 1} $ program --all --all {"-a": 2} r"""Usage: prog [options] Options: -a, --all ARG ... Foo """ $ program {"-a": []} $ program -a 1 {"-a": ["1"]} $ program -a 2 --all 3 {"-a": ["2", "3"]} $ program -a4 -a5 --all 6 {"-a": ["4", "5", "6"]} $ program --all 7 {"-a": ["7"]} $ program --all 8 --all 9 {"-a": ["8", "9"]} r"""Usage: prog [options] Options: --all ... Foo """ $ program {"--all": 0} $ program --all {"--all": 1} $ program --all --all {"--all": 2} r"""Usage: prog [options] Options: --all=ARG ... Foo """ $ program {"--all": []} $ program --all 1 {"--all": ["1"]} $ program --all 2 --all 3 {"--all": ["2", "3"]} r"""Usage: prog [options] Options: --all ... Foo """ $ program --all --all "user-error" r"""Usage: prog [options] Options: --all ARG ... Foo """ $ program --all foo --all bar "user-error" r"""Usage: prog --speed=ARG""" $ program --speed 20 {"--speed": "20"} $ program --speed=20 {"--speed": "20"} $ program --speed=-20 {"--speed": "-20"} $ program --speed -20 {"--speed": "-20"} # # Issue 187: Fails to parse a default value containing ']' # r"""usage: prog [--datetime=] options: --datetime= Regex for datetimes [default: ^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}] """ $ prog {"--datetime": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}"} # # Issue 137: -x-y being seen as a positional argument # r"""Usage: prog [options] Options: -x ARG -y""" $ prog -x-y {"-x": "-y"} vendor/docopt-0.8.3/src/test/testcases.rs0000644000000000000000000007357413264166600017143 0ustar rootroot// !!! ATTENTION !!! // This file is automatically generated by `scripts/mk-testcases`. // Please do not edit this file directly! use Value::{Switch, Counted, Plain, List}; use test::{get_args, map_from_alist, same_args}; test_expect!(test_0_testcases, "Usage: prog", &[], vec!()); test_user_error!(test_1_testcases, "Usage: prog", &["--xxx"]); test_expect!(test_2_testcases, "Usage: prog [options] Options: -a All.", &[], vec!(("-a", Switch(false)))); test_expect!(test_3_testcases, "Usage: prog [options] Options: -a All.", &["-a"], vec!(("-a", Switch(true)))); test_user_error!(test_4_testcases, "Usage: prog [options] Options: -a All.", &["-x"]); test_expect!(test_5_testcases, "Usage: prog [options] Options: --all All.", &[], vec!(("--all", Switch(false)))); test_expect!(test_6_testcases, "Usage: prog [options] Options: --all All.", &["--all"], vec!(("--all", Switch(true)))); test_user_error!(test_7_testcases, "Usage: prog [options] Options: --all All.", &["--xxx"]); test_expect!(test_8_testcases, "Usage: prog [options] Options: -v, --verbose Verbose.", &["--verbose"], vec!(("--verbose", Switch(true)))); test_user_error!(test_9_testcases, "Usage: prog [options] Options: -v, --verbose Verbose.", &["--ver"]); test_expect!(test_10_testcases, "Usage: prog [options] Options: -v, --verbose Verbose.", &["-v"], vec!(("--verbose", Switch(true)))); test_expect!(test_11_testcases, "Usage: prog [options] Options: -p PATH", &["-p", "home/"], vec!(("-p", Plain(Some("home/".to_string()))))); test_expect!(test_12_testcases, "Usage: prog [options] Options: -p PATH", &["-phome/"], vec!(("-p", Plain(Some("home/".to_string()))))); test_user_error!(test_13_testcases, "Usage: prog [options] Options: -p PATH", &["-p"]); test_expect!(test_14_testcases, "Usage: prog [options] Options: --path ", &["--path", "home/"], vec!(("--path", Plain(Some("home/".to_string()))))); test_expect!(test_15_testcases, "Usage: prog [options] Options: --path ", &["--path=home/"], vec!(("--path", Plain(Some("home/".to_string()))))); test_user_error!(test_16_testcases, "Usage: prog [options] Options: --path ", &["--pa", "home/"]); test_user_error!(test_17_testcases, "Usage: prog [options] Options: --path ", &["--pa=home/"]); test_user_error!(test_18_testcases, "Usage: prog [options] Options: --path ", &["--path"]); test_expect!(test_19_testcases, "Usage: prog [options] Options: -p PATH, --path= Path to files.", &["-proot"], vec!(("--path", Plain(Some("root".to_string()))))); test_expect!(test_20_testcases, "Usage: prog [options] Options: -p --path PATH Path to files.", &["-p", "root"], vec!(("--path", Plain(Some("root".to_string()))))); test_expect!(test_21_testcases, "Usage: prog [options] Options: -p --path PATH Path to files.", &["--path", "root"], vec!(("--path", Plain(Some("root".to_string()))))); test_expect!(test_22_testcases, "Usage: prog [options] Options: -p PATH Path to files [default: ./]", &[], vec!(("-p", Plain(Some("./".to_string()))))); test_expect!(test_23_testcases, "Usage: prog [options] Options: -p PATH Path to files [default: ./]", &["-phome"], vec!(("-p", Plain(Some("home".to_string()))))); test_expect!(test_24_testcases, "UsAgE: prog [options] OpTiOnS: --path= Path to files [dEfAuLt: /root]", &[], vec!(("--path", Plain(Some("/root".to_string()))))); test_expect!(test_25_testcases, "UsAgE: prog [options] OpTiOnS: --path= Path to files [dEfAuLt: /root]", &["--path=home"], vec!(("--path", Plain(Some("home".to_string()))))); test_expect!(test_26_testcases, "usage: prog [options] options: -a Add -r Remote -m Message", &["-a", "-r", "-m", "Hello"], vec!(("-m", Plain(Some("Hello".to_string()))), ("-a", Switch(true)), ("-r", Switch(true)))); test_expect!(test_27_testcases, "usage: prog [options] options: -a Add -r Remote -m Message", &["-armyourass"], vec!(("-m", Plain(Some("yourass".to_string()))), ("-a", Switch(true)), ("-r", Switch(true)))); test_expect!(test_28_testcases, "usage: prog [options] options: -a Add -r Remote -m Message", &["-a", "-r"], vec!(("-m", Plain(None)), ("-a", Switch(true)), ("-r", Switch(true)))); test_expect!(test_29_testcases, "Usage: prog [options] Options: --version --verbose", &["--version"], vec!(("--verbose", Switch(false)), ("--version", Switch(true)))); test_expect!(test_30_testcases, "Usage: prog [options] Options: --version --verbose", &["--verbose"], vec!(("--verbose", Switch(true)), ("--version", Switch(false)))); test_user_error!(test_31_testcases, "Usage: prog [options] Options: --version --verbose", &["--ver"]); test_user_error!(test_32_testcases, "Usage: prog [options] Options: --version --verbose", &["--verb"]); test_expect!(test_33_testcases, "usage: prog [-a -r -m ] options: -a Add -r Remote -m Message", &["-armyourass"], vec!(("-m", Plain(Some("yourass".to_string()))), ("-a", Switch(true)), ("-r", Switch(true)))); test_expect!(test_34_testcases, "usage: prog [-armMSG] options: -a Add -r Remote -m Message", &["-a", "-r", "-m", "Hello"], vec!(("-m", Plain(Some("Hello".to_string()))), ("-a", Switch(true)), ("-r", Switch(true)))); test_expect!(test_35_testcases, "usage: prog -a -b options: -a -b", &["-a", "-b"], vec!(("-a", Switch(true)), ("-b", Switch(true)))); test_expect!(test_36_testcases, "usage: prog -a -b options: -a -b", &["-b", "-a"], vec!(("-a", Switch(true)), ("-b", Switch(true)))); test_user_error!(test_37_testcases, "usage: prog -a -b options: -a -b", &["-a"]); test_user_error!(test_38_testcases, "usage: prog -a -b options: -a -b", &[]); test_expect!(test_39_testcases, "usage: prog (-a -b) options: -a -b", &["-a", "-b"], vec!(("-a", Switch(true)), ("-b", Switch(true)))); test_expect!(test_40_testcases, "usage: prog (-a -b) options: -a -b", &["-b", "-a"], vec!(("-a", Switch(true)), ("-b", Switch(true)))); test_user_error!(test_41_testcases, "usage: prog (-a -b) options: -a -b", &["-a"]); test_user_error!(test_42_testcases, "usage: prog (-a -b) options: -a -b", &[]); test_expect!(test_43_testcases, "usage: prog [-a] -b options: -a -b", &["-a", "-b"], vec!(("-a", Switch(true)), ("-b", Switch(true)))); test_expect!(test_44_testcases, "usage: prog [-a] -b options: -a -b", &["-b", "-a"], vec!(("-a", Switch(true)), ("-b", Switch(true)))); test_user_error!(test_45_testcases, "usage: prog [-a] -b options: -a -b", &["-a"]); test_expect!(test_46_testcases, "usage: prog [-a] -b options: -a -b", &["-b"], vec!(("-a", Switch(false)), ("-b", Switch(true)))); test_user_error!(test_47_testcases, "usage: prog [-a] -b options: -a -b", &[]); test_expect!(test_48_testcases, "usage: prog [(-a -b)] options: -a -b", &["-a", "-b"], vec!(("-a", Switch(true)), ("-b", Switch(true)))); test_expect!(test_49_testcases, "usage: prog [(-a -b)] options: -a -b", &["-b", "-a"], vec!(("-a", Switch(true)), ("-b", Switch(true)))); test_user_error!(test_50_testcases, "usage: prog [(-a -b)] options: -a -b", &["-a"]); test_user_error!(test_51_testcases, "usage: prog [(-a -b)] options: -a -b", &["-b"]); test_expect!(test_52_testcases, "usage: prog [(-a -b)] options: -a -b", &[], vec!(("-a", Switch(false)), ("-b", Switch(false)))); test_user_error!(test_53_testcases, "usage: prog (-a|-b) options: -a -b", &["-a", "-b"]); test_user_error!(test_54_testcases, "usage: prog (-a|-b) options: -a -b", &[]); test_expect!(test_55_testcases, "usage: prog (-a|-b) options: -a -b", &["-a"], vec!(("-a", Switch(true)), ("-b", Switch(false)))); test_expect!(test_56_testcases, "usage: prog (-a|-b) options: -a -b", &["-b"], vec!(("-a", Switch(false)), ("-b", Switch(true)))); test_user_error!(test_57_testcases, "usage: prog [ -a | -b ] options: -a -b", &["-a", "-b"]); test_expect!(test_58_testcases, "usage: prog [ -a | -b ] options: -a -b", &[], vec!(("-a", Switch(false)), ("-b", Switch(false)))); test_expect!(test_59_testcases, "usage: prog [ -a | -b ] options: -a -b", &["-a"], vec!(("-a", Switch(true)), ("-b", Switch(false)))); test_expect!(test_60_testcases, "usage: prog [ -a | -b ] options: -a -b", &["-b"], vec!(("-a", Switch(false)), ("-b", Switch(true)))); test_expect!(test_61_testcases, "usage: prog ", &["10"], vec!(("", Plain(Some("10".to_string()))))); test_user_error!(test_62_testcases, "usage: prog ", &["10", "20"]); test_user_error!(test_63_testcases, "usage: prog ", &[]); test_expect!(test_64_testcases, "usage: prog []", &["10"], vec!(("", Plain(Some("10".to_string()))))); test_user_error!(test_65_testcases, "usage: prog []", &["10", "20"]); test_expect!(test_66_testcases, "usage: prog []", &[], vec!(("", Plain(None)))); test_expect!(test_67_testcases, "usage: prog ", &["10", "20", "40"], vec!(("", Plain(Some("40".to_string()))), ("", Plain(Some("10".to_string()))), ("", Plain(Some("20".to_string()))))); test_user_error!(test_68_testcases, "usage: prog ", &["10", "20"]); test_user_error!(test_69_testcases, "usage: prog ", &[]); test_expect!(test_70_testcases, "usage: prog [ ]", &["10", "20", "40"], vec!(("", Plain(Some("40".to_string()))), ("", Plain(Some("10".to_string()))), ("", Plain(Some("20".to_string()))))); test_expect!(test_71_testcases, "usage: prog [ ]", &["10", "20"], vec!(("", Plain(None)), ("", Plain(Some("10".to_string()))), ("", Plain(Some("20".to_string()))))); test_user_error!(test_72_testcases, "usage: prog [ ]", &[]); test_user_error!(test_73_testcases, "usage: prog [ | ]", &["10", "20", "40"]); test_expect!(test_74_testcases, "usage: prog [ | ]", &["20", "40"], vec!(("", Plain(Some("40".to_string()))), ("", Plain(None)), ("", Plain(Some("20".to_string()))))); test_expect!(test_75_testcases, "usage: prog [ | ]", &[], vec!(("", Plain(None)), ("", Plain(None)), ("", Plain(None)))); test_expect!(test_76_testcases, "usage: prog ( --all | ) options: --all", &["10", "--all"], vec!(("--all", Switch(true)), ("", Plain(Some("10".to_string()))), ("", Plain(None)))); test_expect!(test_77_testcases, "usage: prog ( --all | ) options: --all", &["10"], vec!(("--all", Switch(false)), ("", Plain(None)), ("", Plain(Some("10".to_string()))))); test_user_error!(test_78_testcases, "usage: prog ( --all | ) options: --all", &[]); test_expect!(test_79_testcases, "usage: prog [ ]", &["10", "20"], vec!(("", List(vec!("10".to_string(), "20".to_string()))))); test_expect!(test_80_testcases, "usage: prog [ ]", &["10"], vec!(("", List(vec!("10".to_string()))))); test_expect!(test_81_testcases, "usage: prog [ ]", &[], vec!(("", List(vec!())))); test_expect!(test_82_testcases, "usage: prog [( )]", &["10", "20"], vec!(("", List(vec!("10".to_string(), "20".to_string()))))); test_user_error!(test_83_testcases, "usage: prog [( )]", &["10"]); test_expect!(test_84_testcases, "usage: prog [( )]", &[], vec!(("", List(vec!())))); test_expect!(test_85_testcases, "usage: prog NAME...", &["10", "20"], vec!(("NAME", List(vec!("10".to_string(), "20".to_string()))))); test_expect!(test_86_testcases, "usage: prog NAME...", &["10"], vec!(("NAME", List(vec!("10".to_string()))))); test_user_error!(test_87_testcases, "usage: prog NAME...", &[]); test_expect!(test_88_testcases, "usage: prog [NAME]...", &["10", "20"], vec!(("NAME", List(vec!("10".to_string(), "20".to_string()))))); test_expect!(test_89_testcases, "usage: prog [NAME]...", &["10"], vec!(("NAME", List(vec!("10".to_string()))))); test_expect!(test_90_testcases, "usage: prog [NAME]...", &[], vec!(("NAME", List(vec!())))); test_expect!(test_91_testcases, "usage: prog [NAME...]", &["10", "20"], vec!(("NAME", List(vec!("10".to_string(), "20".to_string()))))); test_expect!(test_92_testcases, "usage: prog [NAME...]", &["10"], vec!(("NAME", List(vec!("10".to_string()))))); test_expect!(test_93_testcases, "usage: prog [NAME...]", &[], vec!(("NAME", List(vec!())))); test_expect!(test_94_testcases, "usage: prog [NAME [NAME ...]]", &["10", "20"], vec!(("NAME", List(vec!("10".to_string(), "20".to_string()))))); test_expect!(test_95_testcases, "usage: prog [NAME [NAME ...]]", &["10"], vec!(("NAME", List(vec!("10".to_string()))))); test_expect!(test_96_testcases, "usage: prog [NAME [NAME ...]]", &[], vec!(("NAME", List(vec!())))); test_expect!(test_97_testcases, "usage: prog (NAME | --foo NAME) options: --foo", &["10"], vec!(("NAME", Plain(Some("10".to_string()))), ("--foo", Switch(false)))); test_expect!(test_98_testcases, "usage: prog (NAME | --foo NAME) options: --foo", &["--foo", "10"], vec!(("NAME", Plain(Some("10".to_string()))), ("--foo", Switch(true)))); test_user_error!(test_99_testcases, "usage: prog (NAME | --foo NAME) options: --foo", &["--foo=10"]); test_expect!(test_100_testcases, "usage: prog (NAME | --foo) [--bar | NAME] options: --foo options: --bar", &["10"], vec!(("--bar", Switch(false)), ("NAME", List(vec!("10".to_string()))), ("--foo", Switch(false)))); test_expect!(test_101_testcases, "usage: prog (NAME | --foo) [--bar | NAME] options: --foo options: --bar", &["10", "20"], vec!(("--bar", Switch(false)), ("NAME", List(vec!("10".to_string(), "20".to_string()))), ("--foo", Switch(false)))); test_expect!(test_102_testcases, "usage: prog (NAME | --foo) [--bar | NAME] options: --foo options: --bar", &["--foo", "--bar"], vec!(("--bar", Switch(true)), ("NAME", List(vec!())), ("--foo", Switch(true)))); test_expect!(test_103_testcases, "Naval Fate. Usage: prog ship new ... prog ship [] move [--speed=] prog ship shoot prog mine (set|remove) [--moored|--drifting] prog -h | --help prog --version Options: -h --help Show this screen. --version Show version. --speed= Speed in knots [default: 10]. --moored Mored (anchored) mine. --drifting Drifting mine.", &["ship", "Guardian", "move", "150", "300", "--speed=20"], vec!(("shoot", Switch(false)), ("--moored", Switch(false)), ("--drifting", Switch(false)), ("move", Switch(true)), ("--speed", Plain(Some("20".to_string()))), ("mine", Switch(false)), ("new", Switch(false)), ("--version", Switch(false)), ("set", Switch(false)), ("remove", Switch(false)), ("", List(vec!("Guardian".to_string()))), ("ship", Switch(true)), ("", Plain(Some("150".to_string()))), ("", Plain(Some("300".to_string()))), ("--help", Switch(false)))); test_expect!(test_104_testcases, "usage: prog --hello", &["--hello"], vec!(("--hello", Switch(true)))); test_expect!(test_105_testcases, "usage: prog [--hello=]", &[], vec!(("--hello", Plain(None)))); test_expect!(test_106_testcases, "usage: prog [--hello=]", &["--hello", "wrld"], vec!(("--hello", Plain(Some("wrld".to_string()))))); test_expect!(test_107_testcases, "usage: prog [-o]", &[], vec!(("-o", Switch(false)))); test_expect!(test_108_testcases, "usage: prog [-o]", &["-o"], vec!(("-o", Switch(true)))); test_expect!(test_109_testcases, "usage: prog [-opr]", &["-op"], vec!(("-o", Switch(true)), ("-p", Switch(true)), ("-r", Switch(false)))); test_expect!(test_110_testcases, "usage: prog --aabb | --aa", &["--aa"], vec!(("--aa", Switch(true)), ("--aabb", Switch(false)))); test_user_error!(test_111_testcases, "usage: prog --aabb | --aa", &["--a"]); test_expect!(test_112_testcases, "Usage: prog -v", &["-v"], vec!(("-v", Switch(true)))); test_expect!(test_113_testcases, "Usage: prog [-v -v]", &[], vec!(("-v", Counted(0)))); test_expect!(test_114_testcases, "Usage: prog [-v -v]", &["-v"], vec!(("-v", Counted(1)))); test_expect!(test_115_testcases, "Usage: prog [-v -v]", &["-vv"], vec!(("-v", Counted(2)))); test_user_error!(test_116_testcases, "Usage: prog -v ...", &[]); test_expect!(test_117_testcases, "Usage: prog -v ...", &["-v"], vec!(("-v", Counted(1)))); test_expect!(test_118_testcases, "Usage: prog -v ...", &["-vv"], vec!(("-v", Counted(2)))); test_expect!(test_119_testcases, "Usage: prog -v ...", &["-vvvvvv"], vec!(("-v", Counted(6)))); test_expect!(test_120_testcases, "Usage: prog [-v | -vv | -vvv] This one is probably most readable user-friednly variant.", &[], vec!(("-v", Counted(0)))); test_expect!(test_121_testcases, "Usage: prog [-v | -vv | -vvv] This one is probably most readable user-friednly variant.", &["-v"], vec!(("-v", Counted(1)))); test_expect!(test_122_testcases, "Usage: prog [-v | -vv | -vvv] This one is probably most readable user-friednly variant.", &["-vv"], vec!(("-v", Counted(2)))); test_user_error!(test_123_testcases, "Usage: prog [-v | -vv | -vvv] This one is probably most readable user-friednly variant.", &["-vvvv"]); test_expect!(test_124_testcases, "usage: prog [--ver --ver]", &["--ver", "--ver"], vec!(("--ver", Counted(2)))); test_expect!(test_125_testcases, "usage: prog [go]", &["go"], vec!(("go", Switch(true)))); test_expect!(test_126_testcases, "usage: prog [go go]", &[], vec!(("go", Counted(0)))); test_expect!(test_127_testcases, "usage: prog [go go]", &["go"], vec!(("go", Counted(1)))); test_expect!(test_128_testcases, "usage: prog [go go]", &["go", "go"], vec!(("go", Counted(2)))); test_user_error!(test_129_testcases, "usage: prog [go go]", &["go", "go", "go"]); test_expect!(test_130_testcases, "usage: prog go...", &["go", "go", "go", "go", "go"], vec!(("go", Counted(5)))); test_expect!(test_131_testcases, "usage: prog [options] [-a] options: -a -b", &["-a"], vec!(("-a", Switch(true)), ("-b", Switch(false)))); test_user_error!(test_132_testcases, "usage: prog [options] [-a] options: -a -b", &["-aa"]); test_expect!(test_133_testcases, "Usage: prog [options] A Options: -q Be quiet -v Be verbose.", &["arg"], vec!(("A", Plain(Some("arg".to_string()))), ("-v", Switch(false)), ("-q", Switch(false)))); test_expect!(test_134_testcases, "Usage: prog [options] A Options: -q Be quiet -v Be verbose.", &["-v", "arg"], vec!(("A", Plain(Some("arg".to_string()))), ("-v", Switch(true)), ("-q", Switch(false)))); test_expect!(test_135_testcases, "Usage: prog [options] A Options: -q Be quiet -v Be verbose.", &["-q", "arg"], vec!(("A", Plain(Some("arg".to_string()))), ("-v", Switch(false)), ("-q", Switch(true)))); test_expect!(test_136_testcases, "usage: prog [-]", &["-"], vec!(("-", Switch(true)))); test_expect!(test_137_testcases, "usage: prog [-]", &[], vec!(("-", Switch(false)))); test_expect!(test_138_testcases, "usage: prog [NAME [NAME ...]]", &["a", "b"], vec!(("NAME", List(vec!("a".to_string(), "b".to_string()))))); test_expect!(test_139_testcases, "usage: prog [NAME [NAME ...]]", &[], vec!(("NAME", List(vec!())))); test_expect!(test_140_testcases, "usage: prog [options] options: -a Add -m Message", &["-a"], vec!(("-m", Plain(None)), ("-a", Switch(true)))); test_expect!(test_141_testcases, "usage: prog --hello", &["--hello"], vec!(("--hello", Switch(true)))); test_expect!(test_142_testcases, "usage: prog [--hello=]", &[], vec!(("--hello", Plain(None)))); test_expect!(test_143_testcases, "usage: prog [--hello=]", &["--hello", "wrld"], vec!(("--hello", Plain(Some("wrld".to_string()))))); test_expect!(test_144_testcases, "usage: prog [-o]", &[], vec!(("-o", Switch(false)))); test_expect!(test_145_testcases, "usage: prog [-o]", &["-o"], vec!(("-o", Switch(true)))); test_expect!(test_146_testcases, "usage: prog [-opr]", &["-op"], vec!(("-o", Switch(true)), ("-p", Switch(true)), ("-r", Switch(false)))); test_expect!(test_147_testcases, "usage: git [-v | --verbose]", &["-v"], vec!(("-v", Switch(true)), ("--verbose", Switch(false)))); test_expect!(test_148_testcases, "usage: git remote [-v | --verbose]", &["remote", "-v"], vec!(("-v", Switch(true)), ("remote", Switch(true)), ("--verbose", Switch(false)))); test_expect!(test_149_testcases, "usage: prog", &[], vec!()); test_expect!(test_150_testcases, "usage: prog prog ", &["1", "2"], vec!(("", Plain(Some("1".to_string()))), ("", Plain(Some("2".to_string()))))); test_expect!(test_151_testcases, "usage: prog prog ", &[], vec!(("", Plain(None)), ("", Plain(None)))); test_expect!(test_152_testcases, "usage: prog prog", &[], vec!(("", Plain(None)), ("", Plain(None)))); test_expect!(test_153_testcases, "usage: prog [--file=]", &[], vec!(("--file", Plain(None)))); test_expect!(test_154_testcases, "usage: prog [--file=] options: --file ", &[], vec!(("--file", Plain(None)))); test_expect!(test_155_testcases, "Usage: prog [-a ] Options: -a, --address TCP address [default: localhost:6283].", &[], vec!(("--address", Plain(Some("localhost:6283".to_string()))))); test_expect!(test_156_testcases, "usage: prog --long= ...", &["--long", "one"], vec!(("--long", List(vec!("one".to_string()))))); test_expect!(test_157_testcases, "usage: prog --long= ...", &["--long", "one", "--long", "two"], vec!(("--long", List(vec!("one".to_string(), "two".to_string()))))); test_expect!(test_158_testcases, "usage: prog (go --speed=)...", &["go", "left", "--speed=5", "go", "right", "--speed=9"], vec!(("go", Counted(2)), ("", List(vec!("left".to_string(), "right".to_string()))), ("--speed", List(vec!("5".to_string(), "9".to_string()))))); test_expect!(test_159_testcases, "usage: prog [options] -a options: -a", &["-a"], vec!(("-a", Switch(true)))); test_expect!(test_160_testcases, "usage: prog [-o ]... options: -o [default: x]", &["-o", "this", "-o", "that"], vec!(("-o", List(vec!("this".to_string(), "that".to_string()))))); test_expect!(test_161_testcases, "usage: prog [-o ]... options: -o [default: x]", &[], vec!(("-o", List(vec!("x".to_string()))))); test_expect!(test_162_testcases, "usage: prog [-o ]... options: -o [default: x y]", &["-o", "this"], vec!(("-o", List(vec!("this".to_string()))))); test_expect!(test_163_testcases, "usage: prog [-o ]... options: -o [default: x y]", &[], vec!(("-o", List(vec!("x".to_string(), "y".to_string()))))); test_expect!(test_164_testcases, "usage: prog -pPATH options: -p PATH", &["-pHOME"], vec!(("-p", Plain(Some("HOME".to_string()))))); test_expect!(test_165_testcases, "Usage: foo (--xx=X|--yy=Y)...", &["--xx=1", "--yy=2"], vec!(("--yy", List(vec!("2".to_string()))), ("--xx", List(vec!("1".to_string()))))); test_expect!(test_166_testcases, "usage: prog []", &["f.txt"], vec!(("", Plain(Some("f.txt".to_string()))))); test_expect!(test_167_testcases, "usage: prog [--input=]...", &["--input", "a.txt", "--input=b.txt"], vec!(("--input", List(vec!("a.txt".to_string(), "b.txt".to_string()))))); test_expect!(test_168_testcases, "usage: prog good [options] prog fail [options] options: --loglevel=N", &["fail", "--loglevel", "5"], vec!(("fail", Switch(true)), ("good", Switch(false)), ("--loglevel", Plain(Some("5".to_string()))))); test_expect!(test_169_testcases, "usage:prog --foo", &["--foo"], vec!(("--foo", Switch(true)))); test_expect!(test_170_testcases, "PROGRAM USAGE: prog --foo", &["--foo"], vec!(("--foo", Switch(true)))); test_expect!(test_171_testcases, "Usage: prog --foo prog --bar NOT PART OF SECTION", &["--foo"], vec!(("--bar", Switch(false)), ("--foo", Switch(true)))); test_expect!(test_172_testcases, "Usage: prog --foo prog --bar NOT PART OF SECTION", &["--foo"], vec!(("--bar", Switch(false)), ("--foo", Switch(true)))); test_expect!(test_173_testcases, "Usage: prog --foo prog --bar NOT PART OF SECTION", &["--foo"], vec!(("--bar", Switch(false)), ("--foo", Switch(true)))); test_expect!(test_174_testcases, "Usage: prog [options] global options: --foo local options: --baz --bar other options: --egg --spam -not-an-option-", &["--bar", "--egg"], vec!(("--bar", Switch(true)), ("--egg", Switch(true)), ("--spam", Switch(false)))); test_expect!(test_175_testcases, "Usage: prog [-a] [--] [...]", &["-a"], vec!(("", List(vec!())), ("-a", Switch(true)))); test_expect!(test_176_testcases, "Usage: prog [-a] [--] [...]", &["--"], vec!(("", List(vec!())), ("-a", Switch(false)))); test_expect!(test_177_testcases, "Usage: prog [-a] [--] [...]", &["-a", "--", "-b"], vec!(("", List(vec!("-b".to_string()))), ("-a", Switch(true)))); test_expect!(test_178_testcases, "Usage: prog [-a] [--] [...]", &["-a", "--", "-a"], vec!(("", List(vec!("-a".to_string()))), ("-a", Switch(true)))); test_expect!(test_179_testcases, "Usage: prog [-a] [--] [...]", &["--", "-a"], vec!(("", List(vec!("-a".to_string()))), ("-a", Switch(false)))); test_expect!(test_180_testcases, "Usage: prog test [options] [--] [...]", &["test", "a", "--", "-b"], vec!(("", List(vec!("a".to_string(), "-b".to_string()))))); test_expect!(test_181_testcases, "Usage: prog test [options] [--] [...]", &["test", "--", "-b"], vec!(("", List(vec!("-b".to_string()))))); test_user_error!(test_182_testcases, "Usage: prog test [options] [--] [...]", &["test", "a", "-b"]); test_expect!(test_183_testcases, "Usage: prog test [options] [--] [...]", &["test", "--", "-b", "--"], vec!(("", List(vec!("-b".to_string(), "--".to_string()))))); test_expect!(test_184_testcases, "Usage: prog [options] Options: -a ... Foo", &[], vec!(("-a", Counted(0)))); test_expect!(test_185_testcases, "Usage: prog [options] Options: -a ... Foo", &["-a"], vec!(("-a", Counted(1)))); test_expect!(test_186_testcases, "Usage: prog [options] Options: -a ... Foo", &["-a", "-a"], vec!(("-a", Counted(2)))); test_expect!(test_187_testcases, "Usage: prog [options] Options: -a ... Foo", &["-aa"], vec!(("-a", Counted(2)))); test_expect!(test_188_testcases, "Usage: prog [options] Options: -a ... Foo", &["-a", "-a", "-a"], vec!(("-a", Counted(3)))); test_expect!(test_189_testcases, "Usage: prog [options] Options: -a ... Foo", &["-aaa"], vec!(("-a", Counted(3)))); test_expect!(test_190_testcases, "Usage: prog [options] Options: -a, --all ... Foo", &[], vec!(("-a", Counted(0)))); test_expect!(test_191_testcases, "Usage: prog [options] Options: -a, --all ... Foo", &["-a"], vec!(("-a", Counted(1)))); test_expect!(test_192_testcases, "Usage: prog [options] Options: -a, --all ... Foo", &["-a", "--all"], vec!(("-a", Counted(2)))); test_expect!(test_193_testcases, "Usage: prog [options] Options: -a, --all ... Foo", &["-aa", "--all"], vec!(("-a", Counted(3)))); test_expect!(test_194_testcases, "Usage: prog [options] Options: -a, --all ... Foo", &["--all"], vec!(("-a", Counted(1)))); test_expect!(test_195_testcases, "Usage: prog [options] Options: -a, --all ... Foo", &["--all", "--all"], vec!(("-a", Counted(2)))); test_expect!(test_196_testcases, "Usage: prog [options] Options: -a, --all ARG ... Foo", &[], vec!(("-a", List(vec!())))); test_expect!(test_197_testcases, "Usage: prog [options] Options: -a, --all ARG ... Foo", &["-a", "1"], vec!(("-a", List(vec!("1".to_string()))))); test_expect!(test_198_testcases, "Usage: prog [options] Options: -a, --all ARG ... Foo", &["-a", "2", "--all", "3"], vec!(("-a", List(vec!("2".to_string(), "3".to_string()))))); test_expect!(test_199_testcases, "Usage: prog [options] Options: -a, --all ARG ... Foo", &["-a4", "-a5", "--all", "6"], vec!(("-a", List(vec!("4".to_string(), "5".to_string(), "6".to_string()))))); test_expect!(test_200_testcases, "Usage: prog [options] Options: -a, --all ARG ... Foo", &["--all", "7"], vec!(("-a", List(vec!("7".to_string()))))); test_expect!(test_201_testcases, "Usage: prog [options] Options: -a, --all ARG ... Foo", &["--all", "8", "--all", "9"], vec!(("-a", List(vec!("8".to_string(), "9".to_string()))))); test_expect!(test_202_testcases, "Usage: prog [options] Options: --all ... Foo", &[], vec!(("--all", Counted(0)))); test_expect!(test_203_testcases, "Usage: prog [options] Options: --all ... Foo", &["--all"], vec!(("--all", Counted(1)))); test_expect!(test_204_testcases, "Usage: prog [options] Options: --all ... Foo", &["--all", "--all"], vec!(("--all", Counted(2)))); test_expect!(test_205_testcases, "Usage: prog [options] Options: --all=ARG ... Foo", &[], vec!(("--all", List(vec!())))); test_expect!(test_206_testcases, "Usage: prog [options] Options: --all=ARG ... Foo", &["--all", "1"], vec!(("--all", List(vec!("1".to_string()))))); test_expect!(test_207_testcases, "Usage: prog [options] Options: --all=ARG ... Foo", &["--all", "2", "--all", "3"], vec!(("--all", List(vec!("2".to_string(), "3".to_string()))))); test_user_error!(test_208_testcases, "Usage: prog [options] Options: --all ... Foo", &["--all", "--all"]); test_user_error!(test_209_testcases, "Usage: prog [options] Options: --all ARG ... Foo", &["--all", "foo", "--all", "bar"]); test_expect!(test_210_testcases, "Usage: prog --speed=ARG", &["--speed", "20"], vec!(("--speed", Plain(Some("20".to_string()))))); test_expect!(test_211_testcases, "Usage: prog --speed=ARG", &["--speed=20"], vec!(("--speed", Plain(Some("20".to_string()))))); test_expect!(test_212_testcases, "Usage: prog --speed=ARG", &["--speed=-20"], vec!(("--speed", Plain(Some("-20".to_string()))))); test_expect!(test_213_testcases, "Usage: prog --speed=ARG", &["--speed", "-20"], vec!(("--speed", Plain(Some("-20".to_string()))))); test_expect!(test_214_testcases, "usage: prog [--datetime=] options: --datetime= Regex for datetimes [default: ^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}]", &[], vec!(("--datetime", Plain(Some("^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}".to_string()))))); test_expect!(test_215_testcases, "Usage: prog [options] Options: -x ARG -y", &["-x-y"], vec!(("-x", Plain(Some("-y".to_string()))))); vendor/docopt-0.8.3/src/wordlist.rs0000644000000000000000000000634313264166600016023 0ustar rootroot#[macro_use] extern crate lazy_static; #[macro_use] extern crate serde_derive; extern crate regex; extern crate serde; extern crate strsim; use std::collections::HashMap; use std::io::{self, Read, Write}; use dopt::Docopt; use parse::{Atom, Parser}; // cheat until we get syntax extensions back :-( macro_rules! regex( ($s:expr) => (::regex::Regex::new($s).unwrap()); ); macro_rules! werr( ($($arg:tt)*) => ({ use std::io::{Write, stderr}; write!(&mut stderr(), $($arg)*).unwrap(); }) ); fn cap_or_empty<'t>(caps: ®ex::Captures<'t>, name: &str) -> &'t str { caps.name(name).map_or("", |m| m.as_str()) } #[allow(dead_code)] mod dopt; #[allow(dead_code)] mod parse; #[allow(dead_code)] mod synonym; const USAGE: &'static str = " Usage: docopt-wordlist [( )] ... docopt-wordlist prints a list of available flags and commands arguments for the given usage (provided on stdin). Example use: your-command --help | docopt-wordlist This command also supports completing positional arguments when given a list of choices. The choices are included in the word list if and only if the argument name appears in the usage string. For example: your-command --help | docopt-wordlist 'arg' 'a b c' Which will only include 'a', 'b' and 'c' in the wordlist if 'your-command --help' contains a positional argument named 'arg'. "; #[derive(Debug, Deserialize)] struct Args { arg_name: Vec, arg_possibles: Vec, } fn main() { let args: Args = Docopt::new(USAGE) .and_then(|d| d.deserialize()) .unwrap_or_else(|e| e.exit()); match run(args) { Ok(_) => {}, Err(err) => { write!(&mut io::stderr(), "{}", err).unwrap(); ::std::process::exit(1) } } } fn run(args: Args) -> Result<(), String> { let mut usage = String::new(); io::stdin().read_to_string(&mut usage).map_err(|e| e.to_string())?; let parsed = Parser::new(&usage).map_err(|e| e.to_string())?; let arg_possibles: HashMap> = args.arg_name.iter() .zip(args.arg_possibles.iter()) .map(|(name, possibles)| { let choices = regex!(r"[ \t]+").split(&**possibles) .map(|s| s.to_string()) .collect::>(); (name.clone(), choices) }) .collect(); let mut words = vec![]; for k in parsed.descs.keys() { if let Atom::Positional(ref arg_name) = *k { if let Some(choices) = arg_possibles.get(arg_name) { words.extend(choices.iter().map(|s| s.clone())); } // If the user hasn't given choices for this positional argument, // then there's really nothing to complete here. } else { words.push(k.to_string()); } } for (k, _) in parsed.descs.synonyms() { // We don't need to do anything special here since synonyms can // only be flags, which we always include in the wordlist. words.push(k.to_string()); } println!("{}", words.join(" ")); Ok(()) } vendor/dtoa-0.4.2/0000755000000000000000000000000013264166600012443 5ustar rootrootvendor/dtoa-0.4.2/.cargo-checksum.json0000644000000000000000000000013113264166600016302 0ustar rootroot{"files":{},"package":"09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"}vendor/dtoa-0.4.2/.travis.yml0000664000000000000000000000005713264166600014560 0ustar rootrootsudo: false language: rust rust: - nightly vendor/dtoa-0.4.2/Cargo.toml0000644000000000000000000000161413264166600014375 0ustar rootroot# 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 = "dtoa" version = "0.4.2" authors = ["David Tolnay "] exclude = ["performance.png"] description = "Fast functions for printing floating-point primitives to an io::Write" documentation = "https://github.com/dtolnay/dtoa" readme = "README.md" categories = ["value-formatting"] license = "MIT/Apache-2.0" repository = "https://github.com/dtolnay/dtoa" vendor/dtoa-0.4.2/LICENSE-APACHE0000664000000000000000000002513713264166600014401 0ustar rootroot 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. vendor/dtoa-0.4.2/LICENSE-MIT0000664000000000000000000000204313264166600014100 0ustar rootrootCopyright (c) 2016 Itoa 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. vendor/dtoa-0.4.2/README.md0000664000000000000000000000376313264166600013735 0ustar rootrootdtoa ==== [![Build Status](https://api.travis-ci.org/dtolnay/dtoa.svg?branch=master)](https://travis-ci.org/dtolnay/dtoa) [![Latest Version](https://img.shields.io/crates/v/dtoa.svg)](https://crates.io/crates/dtoa) This crate provides fast functions for printing floating-point primitives to an [`io::Write`](https://doc.rust-lang.org/std/io/trait.Write.html). The implementation is a straightforward Rust port of [Milo Yip](https://github.com/miloyip)'s C++ implementation [dtoa.h](https://github.com/miloyip/rapidjson/blob/master/include/rapidjson/internal/dtoa.h). The original C++ code of each function is included in comments. See also [`itoa`](https://github.com/dtolnay/itoa) for printing integer primitives. ## Performance (lower is better) ![performance](https://raw.githubusercontent.com/dtolnay/dtoa/master/performance.png) ## Functions ```rust extern crate dtoa; // write to a vector or other io::Write let mut buf = Vec::new(); dtoa::write(&mut buf, 2.71828f64)?; println!("{:?}", buf); // write to a stack buffer let mut bytes = [b'\0'; 20]; let n = dtoa::write(&mut bytes[..], 2.71828f64)?; println!("{:?}", &bytes[..n]); ``` The function signature is: ```rust fn write(writer: W, value: V) -> io::Result<()> ``` where `dtoa::Floating` is implemented for `f32` and `f64`. The return value gives the number of bytes written. ## Dependency Dtoa is available on [crates.io](https://crates.io/crates/dtoa). Use the following in `Cargo.toml`: ```toml [dependencies] dtoa = "0.4" ``` ## License Licensed under either of * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in dtoa by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. vendor/dtoa-0.4.2/benches/0000755000000000000000000000000013264166600014052 5ustar rootrootvendor/dtoa-0.4.2/benches/bench.rs0000664000000000000000000000245213264166600015504 0ustar rootroot#![feature(test)] extern crate dtoa; extern crate test; macro_rules! benches { ($($name:ident($value:expr),)*) => { mod bench_dtoa { use test::{Bencher, black_box}; $( #[bench] fn $name(b: &mut Bencher) { use dtoa; let mut buf = Vec::with_capacity(20); b.iter(|| { buf.clear(); dtoa::write(&mut buf, black_box($value)).unwrap() }); } )* } mod bench_fmt { use test::{Bencher, black_box}; $( #[bench] fn $name(b: &mut Bencher) { use std::io::Write; let mut buf = Vec::with_capacity(20); b.iter(|| { buf.clear(); write!(&mut buf, "{}", black_box($value)).unwrap() }); } )* } } } benches!( bench_0_f64(0f64), bench_short_f64(0.1234f64), bench_e_f64(2.718281828459045f64), bench_max_f64(::std::f64::MAX), bench_0_f32(0f32), bench_short_f32(0.1234f32), bench_e_f32(2.718281828459045f32), bench_max_f32(::std::f32::MAX), ); vendor/dtoa-0.4.2/src/0000755000000000000000000000000013264166600013232 5ustar rootrootvendor/dtoa-0.4.2/src/diyfp.rs0000664000000000000000000001514013264166600014716 0ustar rootroot// Copyright 2016 Dtoa Developers // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use std::ops; #[derive(Copy, Clone, Debug)] pub struct DiyFp { pub f: F, pub e: E, } impl DiyFp { pub fn new(f: F, e: E) -> Self { DiyFp { f: f, e: e } } } impl ops::Mul for DiyFp { type Output = Self; fn mul(self, rhs: Self) -> Self { let mut tmp = self.f as u64 * rhs.f as u64; tmp += 1u64 << 31; // mult_round DiyFp { f: (tmp >> 32) as u32, e: self.e + rhs.e + 32, } } } impl ops::Mul for DiyFp { type Output = Self; fn mul(self, rhs: Self) -> Self { let m32 = 0xFFFFFFFFu64; let a = self.f >> 32; let b = self.f & m32; let c = rhs.f >> 32; let d = rhs.f & m32; let ac = a * c; let bc = b * c; let ad = a * d; let bd = b * d; let mut tmp = (bd >> 32) + (ad & m32) + (bc & m32); tmp += 1u64 << 31; // mult_round DiyFp { f: ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e: self.e + rhs.e + 64, } } } #[macro_export] macro_rules! diyfp {( floating_type: $fty:ty, significand_type: $sigty:ty, exponent_type: $expty:ty, diy_significand_size: $diy_significand_size:expr, significand_size: $significand_size:expr, exponent_bias: $exponent_bias:expr, mask_type: $mask_type:ty, exponent_mask: $exponent_mask:expr, significand_mask: $significand_mask:expr, hidden_bit: $hidden_bit:expr, cached_powers_f: $cached_powers_f:expr, cached_powers_e: $cached_powers_e:expr, min_power: $min_power:expr, ) => { type DiyFp = diyfp::DiyFp<$sigty, $expty>; impl DiyFp { // Preconditions: // `d` must have a positive sign and must not be infinity or NaN. /* explicit DiyFp(double d) { union { double d; uint64_t u64; } u = { d }; int biased_e = static_cast((u.u64 & kDpExponentMask) >> kDpSignificandSize); uint64_t significand = (u.u64 & kDpSignificandMask); if (biased_e != 0) { f = significand + kDpHiddenBit; e = biased_e - kDpExponentBias; } else { f = significand; e = kDpMinExponent + 1; } } */ unsafe fn from(d: $fty) -> Self { let u: $mask_type = mem::transmute(d); let biased_e = ((u & $exponent_mask) >> $significand_size) as $expty; let significand = u & $significand_mask; if biased_e != 0 { DiyFp { f: significand + $hidden_bit, e: biased_e - $exponent_bias - $significand_size, } } else { DiyFp { f: significand, e: 1 - $exponent_bias - $significand_size, } } } // Normalizes so that the highest bit of the diy significand is 1. /* DiyFp Normalize() const { DiyFp res = *this; while (!(res.f & (static_cast(1) << 63))) { res.f <<= 1; res.e--; } return res; } */ fn normalize(self) -> DiyFp { let mut res = self; while (res.f & (1 << ($diy_significand_size - 1))) == 0 { res.f <<= 1; res.e -= 1; } res } // Normalizes so that the highest bit of the diy significand is 1. // // Precondition: // `self.f` must be no more than 2 bits longer than the f64 significand. /* DiyFp NormalizeBoundary() const { DiyFp res = *this; while (!(res.f & (kDpHiddenBit << 1))) { res.f <<= 1; res.e--; } res.f <<= (kDiySignificandSize - kDpSignificandSize - 2); res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2); return res; } */ fn normalize_boundary(self) -> DiyFp { let mut res = self; while (res.f & $hidden_bit << 1) == 0 { res.f <<= 1; res.e -= 1; } res.f <<= $diy_significand_size - $significand_size - 2; res.e -= $diy_significand_size - $significand_size - 2; res } // Normalizes `self - e` and `self + e` where `e` is half of the least // significant digit of `self`. The plus is normalized so that the highest // bit of the diy significand is 1. The minus is normalized so that it has // the same exponent as the plus. // // Preconditions: // `self` must have been returned directly from `DiyFp::from_f64`. // `self.f` must not be zero. /* void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const { DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary(); DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1); mi.f <<= mi.e - pl.e; mi.e = pl.e; *plus = pl; *minus = mi; } */ fn normalized_boundaries(self) -> (DiyFp, DiyFp) { let pl = DiyFp::new((self.f << 1) + 1, self.e - 1).normalize_boundary(); let mut mi = if self.f == $hidden_bit { DiyFp::new((self.f << 2) - 1, self.e - 2) } else { DiyFp::new((self.f << 1) - 1, self.e - 1) }; mi.f <<= mi.e - pl.e; mi.e = pl.e; (mi, pl) } } impl ops::Sub for DiyFp { type Output = Self; fn sub(self, rhs: Self) -> Self { DiyFp { f: self.f - rhs.f, e: self.e, } } } /* inline DiyFp GetCachedPower(int e, int* K) { //int k = static_cast(ceil((-61 - e) * 0.30102999566398114)) + 374; double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive int k = static_cast(dk); if (dk - k > 0.0) k++; unsigned index = static_cast((k >> 3) + 1); *K = -(-348 + static_cast(index << 3)); // decimal exponent no need lookup table return GetCachedPowerByIndex(index); } */ #[inline] fn get_cached_power(e: $expty) -> (DiyFp, isize) { let dk = (3 - $diy_significand_size - e) as f64 * 0.30102999566398114f64 - ($min_power + 1) as f64; let mut k = dk as isize; if dk - k as f64 > 0.0 { k += 1; } let index = ((k >> 3) + 1) as usize; let k = -($min_power + (index << 3) as isize); (DiyFp::new($cached_powers_f[index], $cached_powers_e[index] as $expty), k) } }} vendor/dtoa-0.4.2/src/dtoa.rs0000664000000000000000000003441313264166600014536 0ustar rootroot// Copyright 2016 Dtoa Developers // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #[macro_export] macro_rules! dtoa {( floating_type: $fty:ty, significand_type: $sigty:ty, exponent_type: $expty:ty, $($diyfp_param:ident: $diyfp_value:tt,)* ) => { diyfp! { floating_type: $fty, significand_type: $sigty, exponent_type: $expty, $($diyfp_param: $diyfp_value,)* }; /* inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) { while (rest < wp_w && delta - rest >= ten_kappa && (rest + ten_kappa < wp_w || /// closer wp_w - rest > rest + ten_kappa - wp_w)) { buffer[len - 1]--; rest += ten_kappa; } } */ #[inline] unsafe fn grisu_round(buffer: *mut u8, len: isize, delta: $sigty, mut rest: $sigty, ten_kappa: $sigty, wp_w: $sigty) { while rest < wp_w && delta - rest >= ten_kappa && (rest + ten_kappa < wp_w || // closer wp_w - rest > rest + ten_kappa - wp_w) { *buffer.offset(len - 1) -= 1; rest += ten_kappa; } } /* inline unsigned CountDecimalDigit32(uint32_t n) { // Simple pure C++ implementation was faster than __builtin_clz version in this situation. if (n < 10) return 1; if (n < 100) return 2; if (n < 1000) return 3; if (n < 10000) return 4; if (n < 100000) return 5; if (n < 1000000) return 6; if (n < 10000000) return 7; if (n < 100000000) return 8; // Will not reach 10 digits in DigitGen() //if (n < 1000000000) return 9; //return 10; return 9; } */ #[inline] fn count_decimal_digit32(n: u32) -> usize { if n < 10 { 1 } else if n < 100 { 2 } else if n < 1000 { 3 } else if n < 10000 { 4 } else if n < 100000 { 5 } else if n < 1000000 { 6 } else if n < 10000000 { 7 } else if n < 100000000 { 8 } // Will not reach 10 digits in digit_gen() else { 9 } } /* inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) { static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; const DiyFp one(uint64_t(1) << -Mp.e, Mp.e); const DiyFp wp_w = Mp - W; uint32_t p1 = static_cast(Mp.f >> -one.e); uint64_t p2 = Mp.f & (one.f - 1); unsigned kappa = CountDecimalDigit32(p1); // kappa in [0, 9] *len = 0; */ // Returns length and k. #[inline] unsafe fn digit_gen(w: DiyFp, mp: DiyFp, mut delta: $sigty, buffer: *mut u8, mut k: isize) -> (isize, isize) { static POW10: [$sigty; 10] = [ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 ]; let one = DiyFp::new(1 << -mp.e, mp.e); let wp_w = mp - w; let mut p1 = (mp.f >> -one.e) as u32; let mut p2 = mp.f & (one.f - 1); let mut kappa = count_decimal_digit32(p1); // kappa in [0, 9] let mut len = 0; /* while (kappa > 0) { uint32_t d = 0; switch (kappa) { case 9: d = p1 / 100000000; p1 %= 100000000; break; case 8: d = p1 / 10000000; p1 %= 10000000; break; case 7: d = p1 / 1000000; p1 %= 1000000; break; case 6: d = p1 / 100000; p1 %= 100000; break; case 5: d = p1 / 10000; p1 %= 10000; break; case 4: d = p1 / 1000; p1 %= 1000; break; case 3: d = p1 / 100; p1 %= 100; break; case 2: d = p1 / 10; p1 %= 10; break; case 1: d = p1; p1 = 0; break; default:; } if (d || *len) buffer[(*len)++] = static_cast('0' + static_cast(d)); kappa--; uint64_t tmp = (static_cast(p1) << -one.e) + p2; if (tmp <= delta) { *K += kappa; GrisuRound(buffer, *len, delta, tmp, static_cast(kPow10[kappa]) << -one.e, wp_w.f); return; } } */ while kappa > 0 { let mut d = 0u32; match kappa { 9 => { d = p1 / 100000000; p1 %= 100000000; } 8 => { d = p1 / 10000000; p1 %= 10000000; } 7 => { d = p1 / 1000000; p1 %= 1000000; } 6 => { d = p1 / 100000; p1 %= 100000; } 5 => { d = p1 / 10000; p1 %= 10000; } 4 => { d = p1 / 1000; p1 %= 1000; } 3 => { d = p1 / 100; p1 %= 100; } 2 => { d = p1 / 10; p1 %= 10; } 1 => { d = p1; p1 = 0; } _ => {} } if d != 0 || len != 0 { *buffer.offset(len) = b'0' + d as u8; len += 1; } kappa -= 1; let tmp = (p1 as $sigty << -one.e) + p2; if tmp <= delta { k += kappa as isize; grisu_round(buffer, len, delta, tmp, POW10[kappa] << -one.e, wp_w.f); return (len, k); } } // kappa = 0 /* for (;;) { p2 *= 10; delta *= 10; char d = static_cast(p2 >> -one.e); if (d || *len) buffer[(*len)++] = static_cast('0' + d); p2 &= one.f - 1; kappa--; if (p2 < delta) { *K += kappa; int index = -static_cast(kappa); GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[-static_cast(kappa)] : 0)); return; } } */ loop { p2 *= 10; delta *= 10; let d = (p2 >> -one.e) as u8; if d != 0 || len != 0 { *buffer.offset(len) = b'0' + d; len += 1; } p2 &= one.f - 1; kappa = kappa.wrapping_sub(1); if p2 < delta { k += kappa as isize; let index = -(kappa as isize); grisu_round(buffer, len, delta, p2, one.f, wp_w.f * if index < 9 { POW10[-(kappa as isize) as usize] } else { 0 }); return (len, k); } } } /* inline void Grisu2(double value, char* buffer, int* length, int* K) { const DiyFp v(value); DiyFp w_m, w_p; v.NormalizedBoundaries(&w_m, &w_p); const DiyFp c_mk = GetCachedPower(w_p.e, K); const DiyFp W = v.Normalize() * c_mk; DiyFp Wp = w_p * c_mk; DiyFp Wm = w_m * c_mk; Wm.f++; Wp.f--; DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K); } */ // Returns length and k. #[inline] unsafe fn grisu2(value: $fty, buffer: *mut u8) -> (isize, isize) { let v = DiyFp::from(value); let (w_m, w_p) = v.normalized_boundaries(); let (c_mk, k) = get_cached_power(w_p.e); let w = v.normalize() * c_mk; let mut wp = w_p * c_mk; let mut wm = w_m * c_mk; wm.f += 1; wp.f -= 1; digit_gen(w, wp, wp.f - wm.f, buffer, k) } /* inline char* WriteExponent(int K, char* buffer) { if (K < 0) { *buffer++ = '-'; K = -K; } if (K >= 100) { *buffer++ = static_cast('0' + static_cast(K / 100)); K %= 100; const char* d = GetDigitsLut() + K * 2; *buffer++ = d[0]; *buffer++ = d[1]; } else if (K >= 10) { const char* d = GetDigitsLut() + K * 2; *buffer++ = d[0]; *buffer++ = d[1]; } else *buffer++ = static_cast('0' + static_cast(K)); return buffer; } */ #[inline] unsafe fn write_exponent(mut k: isize, mut buffer: *mut u8) -> *mut u8 { if k < 0 { *buffer = b'-'; buffer = buffer.offset(1); k = -k; } if k >= 100 { *buffer = b'0' + (k / 100) as u8; k %= 100; let d = DEC_DIGITS_LUT.as_ptr().offset(k * 2); ptr::copy_nonoverlapping(d, buffer.offset(1), 2); buffer.offset(3) } else if k >= 10 { let d = DEC_DIGITS_LUT.as_ptr().offset(k * 2); ptr::copy_nonoverlapping(d, buffer, 2); buffer.offset(2) } else { *buffer = b'0' + k as u8; buffer.offset(1) } } /* inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) { const int kk = length + k; // 10^(kk-1) <= v < 10^kk */ #[inline] unsafe fn prettify(buffer: *mut u8, length: isize, k: isize) -> *mut u8 { let kk = length + k; // 10^(kk-1) <= v < 10^kk /* if (0 <= k && kk <= 21) { // 1234e7 -> 12340000000 for (int i = length; i < kk; i++) buffer[i] = '0'; buffer[kk] = '.'; buffer[kk + 1] = '0'; return &buffer[kk + 2]; } */ if 0 <= k && kk <= 21 { // 1234e7 -> 12340000000 for i in length..kk { *buffer.offset(i) = b'0'; } *buffer.offset(kk) = b'.'; *buffer.offset(kk + 1) = b'0'; buffer.offset(kk + 2) } /* else if (0 < kk && kk <= 21) { // 1234e-2 -> 12.34 std::memmove(&buffer[kk + 1], &buffer[kk], static_cast(length - kk)); buffer[kk] = '.'; if (0 > k + maxDecimalPlaces) { // When maxDecimalPlaces = 2, 1.2345 -> 1.23, 1.102 -> 1.1 // Remove extra trailing zeros (at least one) after truncation. for (int i = kk + maxDecimalPlaces; i > kk + 1; i--) if (buffer[i] != '0') return &buffer[i + 1]; return &buffer[kk + 2]; // Reserve one zero } else return &buffer[length + 1]; } */ else if 0 < kk && kk <= 21 { // 1234e-2 -> 12.34 ptr::copy(buffer.offset(kk), buffer.offset(kk + 1), (length - kk) as usize); *buffer.offset(kk) = b'.'; if 0 > k + MAX_DECIMAL_PLACES { // When MAX_DECIMAL_PLACES = 2, 1.2345 -> 1.23, 1.102 -> 1.1 // Remove extra trailing zeros (at least one) after truncation. for i in (kk + 2 .. kk + MAX_DECIMAL_PLACES + 1).rev() { if *buffer.offset(i) != b'0' { return buffer.offset(i + 1); } } buffer.offset(kk + 2) // Reserve one zero } else { buffer.offset(length + 1) } } /* else if (-6 < kk && kk <= 0) { // 1234e-6 -> 0.001234 const int offset = 2 - kk; std::memmove(&buffer[offset], &buffer[0], static_cast(length)); buffer[0] = '0'; buffer[1] = '.'; for (int i = 2; i < offset; i++) buffer[i] = '0'; if (length - kk > maxDecimalPlaces) { // When maxDecimalPlaces = 2, 0.123 -> 0.12, 0.102 -> 0.1 // Remove extra trailing zeros (at least one) after truncation. for (int i = maxDecimalPlaces + 1; i > 2; i--) if (buffer[i] != '0') return &buffer[i + 1]; return &buffer[3]; // Reserve one zero } else return &buffer[length + offset]; } */ else if -6 < kk && kk <= 0 { // 1234e-6 -> 0.001234 let offset = 2 - kk; ptr::copy(buffer, buffer.offset(offset), length as usize); *buffer = b'0'; *buffer.offset(1) = b'.'; for i in 2..offset { *buffer.offset(i) = b'0'; } if length - kk > MAX_DECIMAL_PLACES { // When MAX_DECIMAL_PLACES = 2, 0.123 -> 0.12, 0.102 -> 0.1 // Remove extra trailing zeros (at least one) after truncation. for i in (3 .. MAX_DECIMAL_PLACES + 2).rev() { if *buffer.offset(i) != b'0' { return buffer.offset(i + 1); } } buffer.offset(3) // Reserve one zero } else { buffer.offset(length + offset) } } /* else if (kk < -maxDecimalPlaces) { // Truncate to zero buffer[0] = '0'; buffer[1] = '.'; buffer[2] = '0'; return &buffer[3]; } */ else if kk < -MAX_DECIMAL_PLACES { *buffer = b'0'; *buffer.offset(1) = b'.'; *buffer.offset(2) = b'0'; buffer.offset(3) } /* else if (length == 1) { // 1e30 buffer[1] = 'e'; return WriteExponent(kk - 1, &buffer[2]); } */ else if length == 1 { // 1e30 *buffer.offset(1) = b'e'; write_exponent(kk - 1, buffer.offset(2)) } /* else { // 1234e30 -> 1.234e33 std::memmove(&buffer[2], &buffer[1], static_cast(length - 1)); buffer[1] = '.'; buffer[length + 1] = 'e'; return WriteExponent(kk - 1, &buffer[0 + length + 2]); } */ else { // 1234e30 -> 1.234e33 ptr::copy(buffer.offset(1), buffer.offset(2), (length - 1) as usize); *buffer.offset(1) = b'.'; *buffer.offset(length + 1) = b'e'; write_exponent(kk - 1, buffer.offset(length + 2)) } } /* inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324) { RAPIDJSON_ASSERT(maxDecimalPlaces >= 1); Double d(value); if (d.IsZero()) { if (d.Sign()) *buffer++ = '-'; // -0.0, Issue #289 buffer[0] = '0'; buffer[1] = '.'; buffer[2] = '0'; return &buffer[3]; } else { if (value < 0) { *buffer++ = '-'; value = -value; } int length, K; Grisu2(value, buffer, &length, &K); return Prettify(buffer, length, K, maxDecimalPlaces); } } */ #[inline] unsafe fn dtoa(mut wr: W, mut value: $fty) -> io::Result { if value == 0.0 { if value.is_sign_negative() { try!(wr.write_all(b"-0.0")); Ok(4) } else { try!(wr.write_all(b"0.0")); Ok(3) } } else { let negative = value < 0.0; if negative { try!(wr.write_all(b"-")); value = -value; } let mut buffer: [u8; 24] = mem::uninitialized(); let buf_ptr = buffer.as_mut_ptr(); let (length, k) = grisu2(value, buf_ptr); let end = prettify(buf_ptr, length, k); let len = end as usize - buf_ptr as usize; try!(wr.write_all(slice::from_raw_parts(buf_ptr, len))); if negative { Ok(len + 1) } else { Ok(len) } } } }} vendor/dtoa-0.4.2/src/lib.rs0000664000000000000000000001242213264166600014351 0ustar rootroot// Copyright 2016 Dtoa Developers // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![doc(html_root_url = "https://docs.rs/dtoa/0.4.2")] #[macro_use] mod diyfp; #[macro_use] mod dtoa; use std::{io, mem, ops, ptr, slice}; #[inline] pub fn write(wr: W, value: V) -> io::Result { value.write(wr) } pub trait Floating { fn write(self, W) -> io::Result; } impl Floating for f32 { fn write(self, wr: W) -> io::Result { dtoa! { floating_type: f32, significand_type: u32, exponent_type: i32, diy_significand_size: 32, significand_size: 23, exponent_bias: 0x7F, mask_type: u32, exponent_mask: 0x7F800000, significand_mask: 0x007FFFFF, hidden_bit: 0x00800000, cached_powers_f: CACHED_POWERS_F_32, cached_powers_e: CACHED_POWERS_E_32, min_power: (-36), }; unsafe { dtoa(wr, self) } } } impl Floating for f64 { fn write(self, wr: W) -> io::Result { dtoa! { floating_type: f64, significand_type: u64, exponent_type: isize, diy_significand_size: 64, significand_size: 52, exponent_bias: 0x3FF, mask_type: u64, exponent_mask: 0x7FF0000000000000, significand_mask: 0x000FFFFFFFFFFFFF, hidden_bit: 0x0010000000000000, cached_powers_f: CACHED_POWERS_F_64, cached_powers_e: CACHED_POWERS_E_64, min_power: (-348), }; unsafe { dtoa(wr, self) } } } //////////////////////////////////////////////////////////////////////////////// const MAX_DECIMAL_PLACES: isize = 324; static DEC_DIGITS_LUT: &'static [u8] = b"0001020304050607080910111213141516171819\ 2021222324252627282930313233343536373839\ 4041424344454647484950515253545556575859\ 6061626364656667686970717273747576777879\ 8081828384858687888990919293949596979899"; // 10^-36, 10^-28, ..., 10^52 static CACHED_POWERS_F_32: [u32; 12] = [ 0xaa242499, 0xfd87b5f3, 0xbce50865, 0x8cbccc09, 0xd1b71759, 0x9c400000, 0xe8d4a510, 0xad78ebc6, 0x813f3979, 0xc097ce7c, 0x8f7e32ce, 0xd5d238a5, ]; static CACHED_POWERS_E_32: [i16; 12] = [ -151, -125, -98, -71, -45, -18, 8, 35, 62, 88, 115, 141, ]; // 10^-348, 10^-340, ..., 10^340 static CACHED_POWERS_F_64: [u64; 87] = [ 0xfa8fd5a0081c0288, 0xbaaee17fa23ebf76, 0x8b16fb203055ac76, 0xcf42894a5dce35ea, 0x9a6bb0aa55653b2d, 0xe61acf033d1a45df, 0xab70fe17c79ac6ca, 0xff77b1fcbebcdc4f, 0xbe5691ef416bd60c, 0x8dd01fad907ffc3c, 0xd3515c2831559a83, 0x9d71ac8fada6c9b5, 0xea9c227723ee8bcb, 0xaecc49914078536d, 0x823c12795db6ce57, 0xc21094364dfb5637, 0x9096ea6f3848984f, 0xd77485cb25823ac7, 0xa086cfcd97bf97f4, 0xef340a98172aace5, 0xb23867fb2a35b28e, 0x84c8d4dfd2c63f3b, 0xc5dd44271ad3cdba, 0x936b9fcebb25c996, 0xdbac6c247d62a584, 0xa3ab66580d5fdaf6, 0xf3e2f893dec3f126, 0xb5b5ada8aaff80b8, 0x87625f056c7c4a8b, 0xc9bcff6034c13053, 0x964e858c91ba2655, 0xdff9772470297ebd, 0xa6dfbd9fb8e5b88f, 0xf8a95fcf88747d94, 0xb94470938fa89bcf, 0x8a08f0f8bf0f156b, 0xcdb02555653131b6, 0x993fe2c6d07b7fac, 0xe45c10c42a2b3b06, 0xaa242499697392d3, 0xfd87b5f28300ca0e, 0xbce5086492111aeb, 0x8cbccc096f5088cc, 0xd1b71758e219652c, 0x9c40000000000000, 0xe8d4a51000000000, 0xad78ebc5ac620000, 0x813f3978f8940984, 0xc097ce7bc90715b3, 0x8f7e32ce7bea5c70, 0xd5d238a4abe98068, 0x9f4f2726179a2245, 0xed63a231d4c4fb27, 0xb0de65388cc8ada8, 0x83c7088e1aab65db, 0xc45d1df942711d9a, 0x924d692ca61be758, 0xda01ee641a708dea, 0xa26da3999aef774a, 0xf209787bb47d6b85, 0xb454e4a179dd1877, 0x865b86925b9bc5c2, 0xc83553c5c8965d3d, 0x952ab45cfa97a0b3, 0xde469fbd99a05fe3, 0xa59bc234db398c25, 0xf6c69a72a3989f5c, 0xb7dcbf5354e9bece, 0x88fcf317f22241e2, 0xcc20ce9bd35c78a5, 0x98165af37b2153df, 0xe2a0b5dc971f303a, 0xa8d9d1535ce3b396, 0xfb9b7cd9a4a7443c, 0xbb764c4ca7a44410, 0x8bab8eefb6409c1a, 0xd01fef10a657842c, 0x9b10a4e5e9913129, 0xe7109bfba19c0c9d, 0xac2820d9623bf429, 0x80444b5e7aa7cf85, 0xbf21e44003acdd2d, 0x8e679c2f5e44ff8f, 0xd433179d9c8cb841, 0x9e19db92b4e31ba9, 0xeb96bf6ebadf77d9, 0xaf87023b9bf0ee6b, ]; static CACHED_POWERS_E_64: [i16; 87] = [ -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, -954, -927, -901, -874, -847, -821, -794, -768, -741, -715, -688, -661, -635, -608, -582, -555, -529, -502, -475, -449, -422, -396, -369, -343, -316, -289, -263, -236, -210, -183, -157, -130, -103, -77, -50, -24, 3, 30, 56, 83, 109, 136, 162, 189, 216, 242, 269, 295, 322, 348, 375, 402, 428, 455, 481, 508, 534, 561, 588, 614, 641, 667, 694, 720, 747, 774, 800, 827, 853, 880, 907, 933, 960, 986, 1013, 1039, 1066, ]; vendor/dtoa-0.4.2/tests/0000755000000000000000000000000013264166600013605 5ustar rootrootvendor/dtoa-0.4.2/tests/test.rs0000664000000000000000000000224113264166600015133 0ustar rootrootextern crate dtoa; use std::str; #[test] fn test_f64() { test_write(1.234e20f64, "123400000000000000000.0"); test_write(1.234e21f64, "1.234e21"); test_write(2.71828f64, "2.71828"); test_write(0.0f64, "0.0"); test_write(-0.0f64, "-0.0"); test_write(1.1e128f64, "1.1e128"); test_write(1.1e-64f64, "1.1e-64"); test_write(2.718281828459045f64, "2.718281828459045"); test_write(5e-324f64, "5e-324"); test_write(::std::f64::MAX, "1.7976931348623157e308"); } #[test] fn test_f32() { test_write(1.234e20f32, "123400000000000000000.0"); test_write(1.234e21f32, "1.234e21"); test_write(2.71828f32, "2.71828"); test_write(0.0f32, "0.0"); test_write(-0.0f32, "-0.0"); test_write(1.1e32f32, "1.1e32"); test_write(1.1e-32f32, "1.1e-32"); test_write(2.7182817f32, "2.7182817"); test_write(1e-45f32, "1e-45"); test_write(::std::f32::MAX, "3.4028235e38"); } fn test_write(value: F, expected: &'static str) { let mut buf = [b'\0'; 30]; let len = dtoa::write(&mut buf[..], value).unwrap(); let result = str::from_utf8(&buf[..len]).unwrap(); assert_eq!(result, expected.to_string()); } vendor/env_logger-0.5.7/0000755000000000000000000000000013264166600013651 5ustar rootrootvendor/env_logger-0.5.7/.cargo-checksum.json0000644000000000000000000000013113264166600017510 0ustar rootroot{"files":{},"package":"0f475037312b91d34dbc3142a1ad3980ef0d070c7a855ce238afdd5e987cfecc"}vendor/env_logger-0.5.7/.travis.yml0000644000000000000000000000065213264166600015765 0ustar rootrootlanguage: rust sudo: false rust: - 1.18.0 - stable - beta - nightly before_script: - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH script: - cargo build --verbose - cargo build --verbose --no-default-features - cargo test --verbose - cargo test --verbose --no-default-features after_success: - travis-cargo --only nightly doc-upload notifications: email: on_success: never vendor/env_logger-0.5.7/Cargo.toml0000644000000000000000000000244113264166600015602 0ustar rootroot# 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 = "env_logger" version = "0.5.7" authors = ["The Rust Project Developers"] description = "A logging implementation for `log` which is configured via an environment\nvariable.\n" documentation = "https://docs.rs/env_logger" readme = "README.md" keywords = ["logging", "log", "logger"] categories = ["development-tools::debugging"] license = "MIT/Apache-2.0" repository = "https://github.com/sebasmagri/env_logger/" [[test]] name = "regexp_filter" harness = false [[test]] name = "log-in-log" harness = false [dependencies.atty] version = "0.2" [dependencies.humantime] version = "1.1.0" [dependencies.log] version = "0.4.0" features = ["std"] [dependencies.regex] version = "0.2" optional = true [dependencies.termcolor] version = "0.3" [features] default = ["regex"] vendor/env_logger-0.5.7/LICENSE-APACHE0000644000000000000000000002513713264166600015605 0ustar rootroot 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. vendor/env_logger-0.5.7/LICENSE-MIT0000644000000000000000000000205713264166600015311 0ustar rootrootCopyright (c) 2014 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. vendor/env_logger-0.5.7/README.md0000644000000000000000000000707613264166600015142 0ustar rootrootenv_logger [![Build Status](https://travis-ci.org/sebasmagri/env_logger.svg?branch=master)](https://travis-ci.org/sebasmagri/env_logger) ========== Implements a logger that can be configured via an environment variable. * [`env_logger` documentation](https://docs.rs/env_logger) ## Usage ### In libraries `env_logger` makes sense when used in executables (binary projects). Libraries should use the [`log`](https://doc.rust-lang.org/log) crate instead. ### In executables It must be added along with `log` to the project dependencies: ```toml [dependencies] log = "0.4.0" env_logger = "0.5.7" ``` `env_logger` must be initialized as early as possible in the project. After it's initialized, you can use the `log` macros to do actual logging. ```rust #[macro_use] extern crate log; extern crate env_logger; fn main() { env_logger::init(); info!("starting up"); // ... } ``` Then when running the executable, specify a value for the `RUST_LOG` environment variable that corresponds with the log messages you want to show. ```bash $ RUST_LOG=info ./main INFO: 2017-11-09T02:12:24Z: main: starting up ``` ### In tests Tests can use the `env_logger` crate to see log messages generated during that test: ```toml [dependencies] log = "0.4.0" [dev-dependencies] env_logger = "0.5.7" ``` ```rust #[macro_use] extern crate log; fn add_one(num: i32) -> i32 { info!("add_one called with {}", num); num + 1 } #[cfg(test)] mod tests { use super::*; extern crate env_logger; #[test] fn it_adds_one() { let _ = env_logger::try_init(); info!("can log from the test too"); assert_eq!(3, add_one(2)); } #[test] fn it_handles_negative_numbers() { let _ = env_logger::try_init(); info!("logging from another test"); assert_eq!(-7, add_one(-8)); } } ``` Assuming the module under test is called `my_lib`, running the tests with the `RUST_LOG` filtering to info messages from this module looks like: ```bash $ RUST_LOG=my_lib=info cargo test Running target/debug/my_lib-... running 2 tests INFO: 2017-11-09T02:12:24Z: my_lib::tests: logging from another test INFO: 2017-11-09T02:12:24Z: my_lib: add_one called with -8 test tests::it_handles_negative_numbers ... ok INFO: 2017-11-09T02:12:24Z: my_lib::tests: can log from the test too INFO: 2017-11-09T02:12:24Z: my_lib: add_one called with 2 test tests::it_adds_one ... ok test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured ``` Note that `env_logger::try_init()` needs to be called in each test in which you want to enable logging. Additionally, the default behavior of tests to run in parallel means that logging output may be interleaved with test output. Either run tests in a single thread by specifying `RUST_TEST_THREADS=1` or by running one test by specifying its name as an argument to the test binaries as directed by the `cargo test` help docs: ```bash $ RUST_LOG=my_lib=info cargo test it_adds_one Running target/debug/my_lib-... running 1 test INFO: 2017-11-09T02:12:24Z: my_lib::tests: can log from the test too INFO: 2017-11-09T02:12:24Z: my_lib: add_one called with 2 test tests::it_adds_one ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured ``` ## Configuring log target By default, `env_logger` logs to stderr. If you want to log to stdout instead, you can use the `Builder` to change the log target: ```rust use std::env; use env_logger::{Builder, Target}; let mut builder = Builder::new(); builder.target(Target::Stdout); if env::var("RUST_LOG").is_ok() { builder.parse(&env::var("RUST_LOG").unwrap()); } builder.init(); ``` vendor/env_logger-0.5.7/examples/0000755000000000000000000000000013264166600015467 5ustar rootrootvendor/env_logger-0.5.7/examples/custom_default_format.rs0000644000000000000000000000156113264166600022426 0ustar rootroot/*! Disabling parts of the default format. Before running this example, try setting the `MY_LOG_LEVEL` environment variable to `info`: ```no_run,shell $ export MY_LOG_LEVEL='info' ``` Also try setting the `MY_LOG_STYLE` environment variable to `never` to disable colors or `auto` to enable them: ```no_run,shell $ export MY_LOG_STYLE=never ``` If you want to control the logging output completely, see the `custom_logger` example. */ #[macro_use] extern crate log; extern crate env_logger; use env_logger::{Env, Builder}; fn init_logger() { let env = Env::default() .filter("MY_LOG_LEVEL") .write_style("MY_LOG_STYLE"); let mut builder = Builder::from_env(env); builder .default_format_level(false) .default_format_timestamp(false); builder.init(); } fn main() { init_logger(); info!("a log from `MyLogger`"); } vendor/env_logger-0.5.7/examples/custom_format.rs0000644000000000000000000000216213264166600020720 0ustar rootroot/*! Changing the default logging format. Before running this example, try setting the `MY_LOG_LEVEL` environment variable to `info`: ```no_run,shell $ export MY_LOG_LEVEL='info' ``` Also try setting the `MY_LOG_STYLE` environment variable to `never` to disable colors or `auto` to enable them: ```no_run,shell $ export MY_LOG_STYLE=never ``` If you want to control the logging output completely, see the `custom_logger` example. */ #[macro_use] extern crate log; extern crate env_logger; use std::io::Write; use env_logger::{Env, Builder, fmt}; fn init_logger() { let env = Env::default() .filter("MY_LOG_LEVEL") .write_style("MY_LOG_STYLE"); let mut builder = Builder::from_env(env); // Use a different format for writing log records builder.format(|buf, record| { let mut style = buf.style(); style.set_bg(fmt::Color::Yellow).set_bold(true); let timestamp = buf.timestamp(); writeln!(buf, "My formatted log ({}): {}", timestamp, style.value(record.args())) }); builder.init(); } fn main() { init_logger(); info!("a log from `MyLogger`"); } vendor/env_logger-0.5.7/examples/custom_logger.rs0000644000000000000000000000246413264166600020714 0ustar rootroot/*! Using `env_logger` to drive a custom logger. Before running this example, try setting the `MY_LOG_LEVEL` environment variable to `info`: ```no_run,shell $ export MY_LOG_LEVEL='info' ``` If you only want to change the way logs are formatted, look at the `custom_format` example. */ #[macro_use] extern crate log; extern crate env_logger; use env_logger::filter::Filter; use log::{Log, Metadata, Record, SetLoggerError}; struct MyLogger { inner: Filter } impl MyLogger { fn new() -> MyLogger { use env_logger::filter::Builder; let mut builder = Builder::from_env("MY_LOG_LEVEL"); MyLogger { inner: builder.build() } } fn init() -> Result<(), SetLoggerError> { let logger = Self::new(); log::set_max_level(logger.inner.filter()); log::set_boxed_logger(Box::new(logger)) } } impl Log for MyLogger { fn enabled(&self, metadata: &Metadata) -> bool { self.inner.enabled(metadata) } fn log(&self, record: &Record) { // Check if the record is matched by the logger before logging if self.inner.matches(record) { println!("{} - {}", record.level(), record.args()); } } fn flush(&self) { } } fn main() { MyLogger::init().unwrap(); info!("a log from `MyLogger`"); } vendor/env_logger-0.5.7/examples/default.rs0000644000000000000000000000131713264166600017463 0ustar rootroot/*! Using `env_logger`. Before running this example, try setting the `MY_LOG_LEVEL` environment variable to `info`: ```no_run,shell $ export MY_LOG_LEVEL='info' ``` Also try setting the `MY_LOG_STYLE` environment variable to `never` to disable colors or `auto` to enable them: ```no_run,shell $ export MY_LOG_STYLE=never ``` */ #[macro_use] extern crate log; extern crate env_logger; use env_logger::Env; fn main() { let env = Env::default() .filter("MY_LOG_LEVEL") .write_style("MY_LOG_STYLE"); env_logger::init_from_env(env); trace!("some trace log"); debug!("some debug log"); info!("some information log"); warn!("some warning log"); error!("some error log"); } vendor/env_logger-0.5.7/examples/direct_logger.rs0000644000000000000000000000201313264166600020642 0ustar rootroot/*! Using `env_logger::Logger` and the `log::Log` trait directly. This example doesn't rely on environment variables, or having a static logger installed. */ extern crate log; extern crate env_logger; fn record() -> log::Record<'static> { let error_metadata = log::MetadataBuilder::new() .target("myApp") .level(log::Level::Error) .build(); log::Record::builder() .metadata(error_metadata) .args(format_args!("Error!")) .line(Some(433)) .file(Some("app.rs")) .module_path(Some("server")) .build() } fn main() { use log::Log; let stylish_logger = env_logger::Builder::new() .filter(None, log::LevelFilter::Error) .write_style(env_logger::WriteStyle::Always) .build(); let unstylish_logger = env_logger::Builder::new() .filter(None, log::LevelFilter::Error) .write_style(env_logger::WriteStyle::Never) .build(); stylish_logger.log(&record()); unstylish_logger.log(&record()); }vendor/env_logger-0.5.7/src/0000755000000000000000000000000013264166600014440 5ustar rootrootvendor/env_logger-0.5.7/src/filter/0000755000000000000000000000000013264166600015725 5ustar rootrootvendor/env_logger-0.5.7/src/filter/mod.rs0000644000000000000000000004316713264166600017065 0ustar rootroot//! Filtering for log records. //! //! This module contains the log filtering used by `env_logger` to match records. //! You can use the `Filter` type in your own logger implementation to use the same //! filter parsing and matching as `env_logger`. For more details about the format //! for directive strings see [Enabling Logging]. //! //! ## Using `env_logger` in your own logger //! //! You can use `env_logger`'s filtering functionality with your own logger. //! Call [`Builder::parse`] to parse directives from a string when constructing //! your logger. Call [`Filter::matches`] to check whether a record should be //! logged based on the parsed filters when log records are received. //! //! ``` //! extern crate log; //! extern crate env_logger; //! use env_logger::filter::Filter; //! use log::{Log, Metadata, Record}; //! //! struct MyLogger { //! filter: Filter //! } //! //! impl MyLogger { //! fn new() -> MyLogger { //! use env_logger::filter::Builder; //! let mut builder = Builder::new(); //! //! // Parse a directives string from an environment variable //! if let Ok(ref filter) = std::env::var("MY_LOG_LEVEL") { //! builder.parse(filter); //! } //! //! MyLogger { //! filter: builder.build() //! } //! } //! } //! //! impl Log for MyLogger { //! fn enabled(&self, metadata: &Metadata) -> bool { //! self.filter.enabled(metadata) //! } //! //! fn log(&self, record: &Record) { //! // Check if the record is matched by the filter //! if self.filter.matches(record) { //! println!("{:?}", record); //! } //! } //! //! fn flush(&self) {} //! } //! # fn main() {} //! ``` //! //! [Enabling Logging]: ../index.html#enabling-logging //! [`Builder::parse`]: struct.Builder.html#method.parse //! [`Filter::matches`]: struct.Filter.html#method.matches use std::env; use std::mem; use std::fmt; use log::{Level, LevelFilter, Record, Metadata}; #[cfg(feature = "regex")] #[path = "regex.rs"] mod inner; #[cfg(not(feature = "regex"))] #[path = "string.rs"] mod inner; /// A log filter. /// /// This struct can be used to determine whether or not a log record /// should be written to the output. /// Use the [`Builder`] type to parse and construct a `Filter`. /// /// [`Builder`]: struct.Builder.html pub struct Filter { directives: Vec, filter: Option, } /// A builder for a log filter. /// /// It can be used to parse a set of directives from a string before building /// a [`Filter`] instance. /// /// ## Example /// /// ``` /// #[macro_use] /// extern crate log; /// extern crate env_logger; /// /// use std::env; /// use std::io; /// use env_logger::filter::Builder; /// /// fn main() { /// let mut builder = Builder::new(); /// /// // Parse a logging filter from an environment variable. /// if let Ok(rust_log) = env::var("RUST_LOG") { /// builder.parse(&rust_log); /// } /// /// let filter = builder.build(); /// } /// ``` /// /// [`Filter`]: struct.Filter.html pub struct Builder { directives: Vec, filter: Option, } #[derive(Debug)] struct Directive { name: Option, level: LevelFilter, } impl Filter { /// Returns the maximum `LevelFilter` that this filter instance is /// configured to output. /// /// # Example /// /// ```rust /// extern crate log; /// extern crate env_logger; /// /// use log::LevelFilter; /// use env_logger::filter::Builder; /// /// fn main() { /// let mut builder = Builder::new(); /// builder.filter(Some("module1"), LevelFilter::Info); /// builder.filter(Some("module2"), LevelFilter::Error); /// /// let filter = builder.build(); /// assert_eq!(filter.filter(), LevelFilter::Info); /// } /// ``` pub fn filter(&self) -> LevelFilter { self.directives.iter() .map(|d| d.level) .max() .unwrap_or(LevelFilter::Off) } /// Checks if this record matches the configured filter. pub fn matches(&self, record: &Record) -> bool { if !self.enabled(record.metadata()) { return false; } if let Some(filter) = self.filter.as_ref() { if !filter.is_match(&*record.args().to_string()) { return false; } } true } /// Determines if a log message with the specified metadata would be logged. pub fn enabled(&self, metadata: &Metadata) -> bool { let level = metadata.level(); let target = metadata.target(); enabled(&self.directives, level, target) } } impl Builder { /// Initializes the filter builder with defaults. pub fn new() -> Builder { Builder { directives: Vec::new(), filter: None, } } /// Initializes the filter builder from an environment. pub fn from_env(env: &str) -> Builder { let mut builder = Builder::new(); if let Ok(s) = env::var(env) { builder.parse(&s); } builder } /// Adds a directive to the filter. /// /// The given module (if any) will log at most the specified level provided. /// If no module is provided then the filter will apply to all log messages. pub fn filter(&mut self, module: Option<&str>, level: LevelFilter) -> &mut Self { self.directives.push(Directive { name: module.map(|s| s.to_string()), level: level, }); self } /// Parses the directives string. /// /// See the [Enabling Logging] section for more details. /// /// [Enabling Logging]: ../index.html#enabling-logging pub fn parse(&mut self, filters: &str) -> &mut Self { let (directives, filter) = parse_spec(filters); self.filter = filter; for directive in directives { self.directives.push(directive); } self } /// Build a log filter. pub fn build(&mut self) -> Filter { if self.directives.is_empty() { // Adds the default filter if none exist self.directives.push(Directive { name: None, level: LevelFilter::Error, }); } else { // Sort the directives by length of their name, this allows a // little more efficient lookup at runtime. self.directives.sort_by(|a, b| { let alen = a.name.as_ref().map(|a| a.len()).unwrap_or(0); let blen = b.name.as_ref().map(|b| b.len()).unwrap_or(0); alen.cmp(&blen) }); } Filter { directives: mem::replace(&mut self.directives, Vec::new()), filter: mem::replace(&mut self.filter, None), } } } impl Default for Builder { fn default() -> Self { Builder::new() } } impl fmt::Debug for Filter { fn fmt(&self, f: &mut fmt::Formatter)->fmt::Result { f.debug_struct("Filter") .field("filter", &self.filter) .field("directives", &self.directives) .finish() } } impl fmt::Debug for Builder { fn fmt(&self, f: &mut fmt::Formatter)->fmt::Result { f.debug_struct("Filter") .field("filter", &self.filter) .field("directives", &self.directives) .finish() } } /// Parse a logging specification string (e.g: "crate1,crate2::mod3,crate3::x=error/foo") /// and return a vector with log directives. fn parse_spec(spec: &str) -> (Vec, Option) { let mut dirs = Vec::new(); let mut parts = spec.split('/'); let mods = parts.next(); let filter = parts.next(); if parts.next().is_some() { println!("warning: invalid logging spec '{}', \ ignoring it (too many '/'s)", spec); return (dirs, None); } mods.map(|m| { for s in m.split(',') { if s.len() == 0 { continue } let mut parts = s.split('='); let (log_level, name) = match (parts.next(), parts.next().map(|s| s.trim()), parts.next()) { (Some(part0), None, None) => { // if the single argument is a log-level string or number, // treat that as a global fallback match part0.parse() { Ok(num) => (num, None), Err(_) => (LevelFilter::max(), Some(part0)), } } (Some(part0), Some(""), None) => (LevelFilter::max(), Some(part0)), (Some(part0), Some(part1), None) => { match part1.parse() { Ok(num) => (num, Some(part0)), _ => { println!("warning: invalid logging spec '{}', \ ignoring it", part1); continue } } }, _ => { println!("warning: invalid logging spec '{}', \ ignoring it", s); continue } }; dirs.push(Directive { name: name.map(|s| s.to_string()), level: log_level, }); }}); let filter = filter.map_or(None, |filter| { match inner::Filter::new(filter) { Ok(re) => Some(re), Err(e) => { println!("warning: invalid regex filter - {}", e); None } } }); return (dirs, filter); } // Check whether a level and target are enabled by the set of directives. fn enabled(directives: &[Directive], level: Level, target: &str) -> bool { // Search for the longest match, the vector is assumed to be pre-sorted. for directive in directives.iter().rev() { match directive.name { Some(ref name) if !target.starts_with(&**name) => {}, Some(..) | None => { return level <= directive.level } } } false } #[cfg(test)] mod tests { use log::{Level, LevelFilter}; use super::{Builder, Filter, Directive, parse_spec, enabled}; fn make_logger_filter(dirs: Vec) -> Filter { let mut logger = Builder::new().build(); logger.directives = dirs; logger } #[test] fn filter_info() { let logger = Builder::new().filter(None, LevelFilter::Info).build(); assert!(enabled(&logger.directives, Level::Info, "crate1")); assert!(!enabled(&logger.directives, Level::Debug, "crate1")); } #[test] fn filter_beginning_longest_match() { let logger = Builder::new() .filter(Some("crate2"), LevelFilter::Info) .filter(Some("crate2::mod"), LevelFilter::Debug) .filter(Some("crate1::mod1"), LevelFilter::Warn) .build(); assert!(enabled(&logger.directives, Level::Debug, "crate2::mod1")); assert!(!enabled(&logger.directives, Level::Debug, "crate2")); } #[test] fn parse_default() { let logger = Builder::new().parse("info,crate1::mod1=warn").build(); assert!(enabled(&logger.directives, Level::Warn, "crate1::mod1")); assert!(enabled(&logger.directives, Level::Info, "crate2::mod2")); } #[test] fn match_full_path() { let logger = make_logger_filter(vec![ Directive { name: Some("crate2".to_string()), level: LevelFilter::Info }, Directive { name: Some("crate1::mod1".to_string()), level: LevelFilter::Warn } ]); assert!(enabled(&logger.directives, Level::Warn, "crate1::mod1")); assert!(!enabled(&logger.directives, Level::Info, "crate1::mod1")); assert!(enabled(&logger.directives, Level::Info, "crate2")); assert!(!enabled(&logger.directives, Level::Debug, "crate2")); } #[test] fn no_match() { let logger = make_logger_filter(vec![ Directive { name: Some("crate2".to_string()), level: LevelFilter::Info }, Directive { name: Some("crate1::mod1".to_string()), level: LevelFilter::Warn } ]); assert!(!enabled(&logger.directives, Level::Warn, "crate3")); } #[test] fn match_beginning() { let logger = make_logger_filter(vec![ Directive { name: Some("crate2".to_string()), level: LevelFilter::Info }, Directive { name: Some("crate1::mod1".to_string()), level: LevelFilter::Warn } ]); assert!(enabled(&logger.directives, Level::Info, "crate2::mod1")); } #[test] fn match_beginning_longest_match() { let logger = make_logger_filter(vec![ Directive { name: Some("crate2".to_string()), level: LevelFilter::Info }, Directive { name: Some("crate2::mod".to_string()), level: LevelFilter::Debug }, Directive { name: Some("crate1::mod1".to_string()), level: LevelFilter::Warn } ]); assert!(enabled(&logger.directives, Level::Debug, "crate2::mod1")); assert!(!enabled(&logger.directives, Level::Debug, "crate2")); } #[test] fn match_default() { let logger = make_logger_filter(vec![ Directive { name: None, level: LevelFilter::Info }, Directive { name: Some("crate1::mod1".to_string()), level: LevelFilter::Warn } ]); assert!(enabled(&logger.directives, Level::Warn, "crate1::mod1")); assert!(enabled(&logger.directives, Level::Info, "crate2::mod2")); } #[test] fn zero_level() { let logger = make_logger_filter(vec![ Directive { name: None, level: LevelFilter::Info }, Directive { name: Some("crate1::mod1".to_string()), level: LevelFilter::Off } ]); assert!(!enabled(&logger.directives, Level::Error, "crate1::mod1")); assert!(enabled(&logger.directives, Level::Info, "crate2::mod2")); } #[test] fn parse_spec_valid() { let (dirs, filter) = parse_spec("crate1::mod1=error,crate1::mod2,crate2=debug"); assert_eq!(dirs.len(), 3); assert_eq!(dirs[0].name, Some("crate1::mod1".to_string())); assert_eq!(dirs[0].level, LevelFilter::Error); assert_eq!(dirs[1].name, Some("crate1::mod2".to_string())); assert_eq!(dirs[1].level, LevelFilter::max()); assert_eq!(dirs[2].name, Some("crate2".to_string())); assert_eq!(dirs[2].level, LevelFilter::Debug); assert!(filter.is_none()); } #[test] fn parse_spec_invalid_crate() { // test parse_spec with multiple = in specification let (dirs, filter) = parse_spec("crate1::mod1=warn=info,crate2=debug"); assert_eq!(dirs.len(), 1); assert_eq!(dirs[0].name, Some("crate2".to_string())); assert_eq!(dirs[0].level, LevelFilter::Debug); assert!(filter.is_none()); } #[test] fn parse_spec_invalid_level() { // test parse_spec with 'noNumber' as log level let (dirs, filter) = parse_spec("crate1::mod1=noNumber,crate2=debug"); assert_eq!(dirs.len(), 1); assert_eq!(dirs[0].name, Some("crate2".to_string())); assert_eq!(dirs[0].level, LevelFilter::Debug); assert!(filter.is_none()); } #[test] fn parse_spec_string_level() { // test parse_spec with 'warn' as log level let (dirs, filter) = parse_spec("crate1::mod1=wrong,crate2=warn"); assert_eq!(dirs.len(), 1); assert_eq!(dirs[0].name, Some("crate2".to_string())); assert_eq!(dirs[0].level, LevelFilter::Warn); assert!(filter.is_none()); } #[test] fn parse_spec_empty_level() { // test parse_spec with '' as log level let (dirs, filter) = parse_spec("crate1::mod1=wrong,crate2="); assert_eq!(dirs.len(), 1); assert_eq!(dirs[0].name, Some("crate2".to_string())); assert_eq!(dirs[0].level, LevelFilter::max()); assert!(filter.is_none()); } #[test] fn parse_spec_global() { // test parse_spec with no crate let (dirs, filter) = parse_spec("warn,crate2=debug"); assert_eq!(dirs.len(), 2); assert_eq!(dirs[0].name, None); assert_eq!(dirs[0].level, LevelFilter::Warn); assert_eq!(dirs[1].name, Some("crate2".to_string())); assert_eq!(dirs[1].level, LevelFilter::Debug); assert!(filter.is_none()); } #[test] fn parse_spec_valid_filter() { let (dirs, filter) = parse_spec("crate1::mod1=error,crate1::mod2,crate2=debug/abc"); assert_eq!(dirs.len(), 3); assert_eq!(dirs[0].name, Some("crate1::mod1".to_string())); assert_eq!(dirs[0].level, LevelFilter::Error); assert_eq!(dirs[1].name, Some("crate1::mod2".to_string())); assert_eq!(dirs[1].level, LevelFilter::max()); assert_eq!(dirs[2].name, Some("crate2".to_string())); assert_eq!(dirs[2].level, LevelFilter::Debug); assert!(filter.is_some() && filter.unwrap().to_string() == "abc"); } #[test] fn parse_spec_invalid_crate_filter() { let (dirs, filter) = parse_spec("crate1::mod1=error=warn,crate2=debug/a.c"); assert_eq!(dirs.len(), 1); assert_eq!(dirs[0].name, Some("crate2".to_string())); assert_eq!(dirs[0].level, LevelFilter::Debug); assert!(filter.is_some() && filter.unwrap().to_string() == "a.c"); } #[test] fn parse_spec_empty_with_filter() { let (dirs, filter) = parse_spec("crate1/a*c"); assert_eq!(dirs.len(), 1); assert_eq!(dirs[0].name, Some("crate1".to_string())); assert_eq!(dirs[0].level, LevelFilter::max()); assert!(filter.is_some() && filter.unwrap().to_string() == "a*c"); } } vendor/env_logger-0.5.7/src/filter/regex.rs0000644000000000000000000000102713264166600017405 0ustar rootrootextern crate regex; use std::fmt; use self::regex::Regex; #[derive(Debug)] pub struct Filter { inner: Regex, } impl Filter { pub fn new(spec: &str) -> Result { match Regex::new(spec){ Ok(r) => Ok(Filter { inner: r }), Err(e) => Err(e.to_string()), } } pub fn is_match(&self, s: &str) -> bool { self.inner.is_match(s) } } impl fmt::Display for Filter { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.inner.fmt(f) } } vendor/env_logger-0.5.7/src/filter/string.rs0000644000000000000000000000063013264166600017600 0ustar rootrootuse std::fmt; #[derive(Debug)] pub struct Filter { inner: String, } impl Filter { pub fn new(spec: &str) -> Result { Ok(Filter { inner: spec.to_string() }) } pub fn is_match(&self, s: &str) -> bool { s.contains(&self.inner) } } impl fmt::Display for Filter { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.inner.fmt(f) } } vendor/env_logger-0.5.7/src/fmt.rs0000644000000000000000000005273413264166600015607 0ustar rootroot//! Formatting for log records. //! //! This module contains a [`Formatter`] that can be used to format log records //! into without needing temporary allocations. Usually you won't need to worry //! about the contents of this module and can use the `Formatter` like an ordinary //! [`Write`]. //! //! # Formatting log records //! //! The format used to print log records can be customised using the [`Builder::format`] //! method. //! Custom formats can apply different color and weight to printed values using //! [`Style`] builders. //! //! ``` //! use std::io::Write; //! use env_logger::fmt::Color; //! //! let mut builder = env_logger::Builder::new(); //! //! builder.format(|buf, record| { //! let mut level_style = buf.style(); //! //! level_style.set_color(Color::Red).set_bold(true); //! //! writeln!(buf, "{}: {}", //! level_style.value(record.level()), //! record.args()) //! }); //! ``` //! //! [`Formatter`]: struct.Formatter.html //! [`Style`]: struct.Style.html //! [`Builder::format`]: ../struct.Builder.html#method.format //! [`Write`]: https://doc.rust-lang.org/stable/std/io/trait.Write.html use std::io::prelude::*; use std::{io, fmt}; use std::rc::Rc; use std::str::FromStr; use std::error::Error; use std::cell::RefCell; use std::time::SystemTime; use termcolor::{self, ColorSpec, ColorChoice, Buffer, BufferWriter, WriteColor}; use atty; use humantime::format_rfc3339_seconds; /// A formatter to write logs into. /// /// `Formatter` implements the standard [`Write`] trait for writing log records. /// It also supports terminal colors, through the [`style`] method. /// /// # Examples /// /// Use the [`writeln`] macro to easily format a log record: /// /// ``` /// use std::io::Write; /// /// let mut builder = env_logger::Builder::new(); /// /// builder.format(|buf, record| writeln!(buf, "{}: {}", record.level(), record.args())); /// ``` /// /// [`Write`]: https://doc.rust-lang.org/stable/std/io/trait.Write.html /// [`writeln`]: https://doc.rust-lang.org/stable/std/macro.writeln.html /// [`style`]: #method.style pub struct Formatter { buf: Rc>, write_style: WriteStyle, } /// A set of styles to apply to the terminal output. /// /// Call [`Formatter::style`] to get a `Style` and use the builder methods to /// set styling properties, like [color] and [weight]. /// To print a value using the style, wrap it in a call to [`value`] when the log /// record is formatted. /// /// # Examples /// /// Create a bold, red colored style and use it to print the log level: /// /// ``` /// use std::io::Write; /// use env_logger::fmt::Color; /// /// let mut builder = env_logger::Builder::new(); /// /// builder.format(|buf, record| { /// let mut level_style = buf.style(); /// /// level_style.set_color(Color::Red).set_bold(true); /// /// writeln!(buf, "{}: {}", /// level_style.value(record.level()), /// record.args()) /// }); /// ``` /// /// Styles can be re-used to output multiple values: /// /// ``` /// use std::io::Write; /// use env_logger::fmt::Color; /// /// let mut builder = env_logger::Builder::new(); /// /// builder.format(|buf, record| { /// let mut bold = buf.style(); /// /// bold.set_bold(true); /// /// writeln!(buf, "{}: {} {}", /// bold.value(record.level()), /// bold.value("some bold text"), /// record.args()) /// }); /// ``` /// /// [`Formatter::style`]: struct.Formatter.html#method.style /// [color]: #method.set_color /// [weight]: #method.set_bold /// [`value`]: #method.value #[derive(Clone)] pub struct Style { buf: Rc>, spec: ColorSpec, } /// A value that can be printed using the given styles. /// /// It is the result of calling [`Style::value`]. /// /// [`Style::value`]: struct.Style.html#method.value pub struct StyledValue<'a, T> { style: &'a Style, value: T, } /// An [RFC3339] formatted timestamp. /// /// The timestamp implements [`Display`] and can be written to a [`Formatter`]. /// /// [RFC3339]: https://www.ietf.org/rfc/rfc3339.txt /// [`Display`]: https://doc.rust-lang.org/stable/std/fmt/trait.Display.html /// [`Formatter`]: struct.Formatter.html pub struct Timestamp(SystemTime); /// Log target, either `stdout` or `stderr`. #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub enum Target { /// Logs will be sent to standard output. Stdout, /// Logs will be sent to standard error. Stderr, } impl Default for Target { fn default() -> Self { Target::Stderr } } /// Whether or not to print styles to the target. #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub enum WriteStyle { /// Try to print styles, but don't force the issue. Auto, /// Try very hard to print styles. Always, /// Never print styles. Never, } impl Default for WriteStyle { fn default() -> Self { WriteStyle::Auto } } /// A terminal target with color awareness. pub(crate) struct Writer { inner: BufferWriter, write_style: WriteStyle, } impl Writer { pub(crate) fn write_style(&self) -> WriteStyle { self.write_style } } /// A builder for a terminal writer. /// /// The target and style choice can be configured before building. pub(crate) struct Builder { target: Target, write_style: WriteStyle, } impl Builder { /// Initialize the writer builder with defaults. pub fn new() -> Self { Builder { target: Default::default(), write_style: Default::default(), } } /// Set the target to write to. pub fn target(&mut self, target: Target) -> &mut Self { self.target = target; self } /// Parses a style choice string. /// /// See the [Disabling colors] section for more details. /// /// [Disabling colors]: ../index.html#disabling-colors pub fn parse(&mut self, write_style: &str) -> &mut Self { self.write_style(parse_write_style(write_style)) } /// Whether or not to print style characters when writing. pub fn write_style(&mut self, write_style: WriteStyle) -> &mut Self { self.write_style = write_style; self } /// Build a terminal writer. pub fn build(&mut self) -> Writer { let color_choice = match self.write_style { WriteStyle::Auto => { if atty::is(match self.target { Target::Stderr => atty::Stream::Stderr, Target::Stdout => atty::Stream::Stdout, }) { ColorChoice::Auto } else { ColorChoice::Never } }, WriteStyle::Always => ColorChoice::Always, WriteStyle::Never => ColorChoice::Never, }; let writer = match self.target { Target::Stderr => BufferWriter::stderr(color_choice), Target::Stdout => BufferWriter::stdout(color_choice), }; Writer { inner: writer, write_style: self.write_style, } } } impl Default for Builder { fn default() -> Self { Builder::new() } } impl Style { /// Set the text color. /// /// # Examples /// /// Create a style with red text: /// /// ``` /// use std::io::Write; /// use env_logger::fmt::Color; /// /// let mut builder = env_logger::Builder::new(); /// /// builder.format(|buf, record| { /// let mut style = buf.style(); /// /// style.set_color(Color::Red); /// /// writeln!(buf, "{}", style.value(record.args())) /// }); /// ``` pub fn set_color(&mut self, color: Color) -> &mut Style { self.spec.set_fg(color.to_termcolor()); self } /// Set the text weight. /// /// If `yes` is true then text will be written in bold. /// If `yes` is false then text will be written in the default weight. /// /// # Examples /// /// Create a style with bold text: /// /// ``` /// use std::io::Write; /// /// let mut builder = env_logger::Builder::new(); /// /// builder.format(|buf, record| { /// let mut style = buf.style(); /// /// style.set_bold(true); /// /// writeln!(buf, "{}", style.value(record.args())) /// }); /// ``` pub fn set_bold(&mut self, yes: bool) -> &mut Style { self.spec.set_bold(yes); self } /// Set the text intensity. /// /// If `yes` is true then text will be written in a brighter color. /// If `yes` is false then text will be written in the default color. /// /// # Examples /// /// Create a style with intense text: /// /// ``` /// use std::io::Write; /// /// let mut builder = env_logger::Builder::new(); /// /// builder.format(|buf, record| { /// let mut style = buf.style(); /// /// style.set_intense(true); /// /// writeln!(buf, "{}", style.value(record.args())) /// }); /// ``` pub fn set_intense(&mut self, yes: bool) -> &mut Style { self.spec.set_intense(yes); self } /// Set the background color. /// /// # Examples /// /// Create a style with a yellow background: /// /// ``` /// use std::io::Write; /// use env_logger::fmt::Color; /// /// let mut builder = env_logger::Builder::new(); /// /// builder.format(|buf, record| { /// let mut style = buf.style(); /// /// style.set_bg(Color::Yellow); /// /// writeln!(buf, "{}", style.value(record.args())) /// }); /// ``` pub fn set_bg(&mut self, color: Color) -> &mut Style { self.spec.set_bg(color.to_termcolor()); self } /// Wrap a value in the style. /// /// The same `Style` can be used to print multiple different values. /// /// # Examples /// /// Create a bold, red colored style and use it to print the log level: /// /// ``` /// use std::io::Write; /// use env_logger::fmt::Color; /// /// let mut builder = env_logger::Builder::new(); /// /// builder.format(|buf, record| { /// let mut style = buf.style(); /// /// style.set_color(Color::Red).set_bold(true); /// /// writeln!(buf, "{}: {}", /// style.value(record.level()), /// record.args()) /// }); /// ``` pub fn value(&self, value: T) -> StyledValue { StyledValue { style: &self, value } } } impl Formatter { pub(crate) fn new(writer: &Writer) -> Self { Formatter { buf: Rc::new(RefCell::new(writer.inner.buffer())), write_style: writer.write_style(), } } pub(crate) fn write_style(&self) -> WriteStyle { self.write_style } /// Begin a new [`Style`]. /// /// # Examples /// /// Create a bold, red colored style and use it to print the log level: /// /// ``` /// use std::io::Write; /// use env_logger::fmt::Color; /// /// let mut builder = env_logger::Builder::new(); /// /// builder.format(|buf, record| { /// let mut level_style = buf.style(); /// /// level_style.set_color(Color::Red).set_bold(true); /// /// writeln!(buf, "{}: {}", /// level_style.value(record.level()), /// record.args()) /// }); /// ``` /// /// [`Style`]: struct.Style.html pub fn style(&self) -> Style { Style { buf: self.buf.clone(), spec: ColorSpec::new(), } } /// Get a [`Timestamp`] for the current date and time in UTC. /// /// # Examples /// /// Include the current timestamp with the log record: /// /// ``` /// use std::io::Write; /// /// let mut builder = env_logger::Builder::new(); /// /// builder.format(|buf, record| { /// let ts = buf.timestamp(); /// /// writeln!(buf, "{}: {}: {}", ts, record.level(), record.args()) /// }); /// ``` /// /// [`Timestamp`]: struct.Timestamp.html pub fn timestamp(&self) -> Timestamp { Timestamp(SystemTime::now()) } pub(crate) fn print(&self, writer: &Writer) -> io::Result<()> { writer.inner.print(&self.buf.borrow()) } pub(crate) fn clear(&mut self) { self.buf.borrow_mut().clear() } } impl Write for Formatter { fn write(&mut self, buf: &[u8]) -> io::Result { self.buf.borrow_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.buf.borrow_mut().flush() } } impl<'a, T> StyledValue<'a, T> { fn write_fmt(&self, f: F) -> fmt::Result where F: FnOnce() -> fmt::Result, { self.style.buf.borrow_mut().set_color(&self.style.spec).map_err(|_| fmt::Error)?; // Always try to reset the terminal style, even if writing failed let write = f(); let reset = self.style.buf.borrow_mut().reset().map_err(|_| fmt::Error); write.and(reset) } } impl fmt::Debug for Timestamp { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { /// A `Debug` wrapper for `Timestamp` that uses the `Display` implementation. struct TimestampValue<'a>(&'a Timestamp); impl<'a> fmt::Debug for TimestampValue<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) } } f.debug_tuple("Timestamp") .field(&TimestampValue(&self)) .finish() } } impl fmt::Debug for Writer { fn fmt(&self, f: &mut fmt::Formatter)->fmt::Result { f.debug_struct("Writer").finish() } } impl fmt::Debug for Formatter { fn fmt(&self, f: &mut fmt::Formatter)->fmt::Result { f.debug_struct("Formatter").finish() } } impl fmt::Debug for Builder { fn fmt(&self, f: &mut fmt::Formatter)->fmt::Result { f.debug_struct("Logger") .field("target", &self.target) .field("write_style", &self.write_style) .finish() } } impl fmt::Debug for Style { fn fmt(&self, f: &mut fmt::Formatter)->fmt::Result { f.debug_struct("Style").field("spec", &self.spec).finish() } } macro_rules! impl_styled_value_fmt { ($($fmt_trait:path),*) => { $( impl<'a, T: $fmt_trait> $fmt_trait for StyledValue<'a, T> { fn fmt(&self, f: &mut fmt::Formatter)->fmt::Result { self.write_fmt(|| T::fmt(&self.value, f)) } } )* }; } impl_styled_value_fmt!( fmt::Debug, fmt::Display, fmt::Pointer, fmt::Octal, fmt::Binary, fmt::UpperHex, fmt::LowerHex, fmt::UpperExp, fmt::LowerExp); impl fmt::Display for Timestamp { fn fmt(&self, f: &mut fmt::Formatter)->fmt::Result { format_rfc3339_seconds(self.0).fmt(f) } } // The `Color` type is copied from https://github.com/BurntSushi/ripgrep/tree/master/termcolor /// The set of available colors for the terminal foreground/background. /// /// The `Ansi256` and `Rgb` colors will only output the correct codes when /// paired with the `Ansi` `WriteColor` implementation. /// /// The `Ansi256` and `Rgb` color types are not supported when writing colors /// on Windows using the console. If they are used on Windows, then they are /// silently ignored and no colors will be emitted. /// /// This set may expand over time. /// /// This type has a `FromStr` impl that can parse colors from their human /// readable form. The format is as follows: /// /// 1. Any of the explicitly listed colors in English. They are matched /// case insensitively. /// 2. A single 8-bit integer, in either decimal or hexadecimal format. /// 3. A triple of 8-bit integers separated by a comma, where each integer is /// in decimal or hexadecimal format. /// /// Hexadecimal numbers are written with a `0x` prefix. #[allow(missing_docs)] #[derive(Clone, Debug, Eq, PartialEq)] pub enum Color { Black, Blue, Green, Red, Cyan, Magenta, Yellow, White, Ansi256(u8), Rgb(u8, u8, u8), #[doc(hidden)] __Nonexhaustive, } /// An error from parsing an invalid color specification. #[derive(Clone, Debug, Eq, PartialEq)] pub struct ParseColorError(ParseColorErrorKind); #[derive(Clone, Debug, Eq, PartialEq)] enum ParseColorErrorKind { /// An error originating from `termcolor`. TermColor(termcolor::ParseColorError), /// An error converting the `termcolor` color to a `env_logger::Color`. /// /// This variant should only get reached if a user uses a new spec that's /// valid for `termcolor`, but not recognised in `env_logger` yet. Unrecognized { given: String, } } impl ParseColorError { fn termcolor(err: termcolor::ParseColorError) -> Self { ParseColorError(ParseColorErrorKind::TermColor(err)) } fn unrecognized(given: String) -> Self { ParseColorError(ParseColorErrorKind::Unrecognized { given }) } /// Return the string that couldn't be parsed as a valid color. pub fn invalid(&self) -> &str { match self.0 { ParseColorErrorKind::TermColor(ref err) => err.invalid(), ParseColorErrorKind::Unrecognized { ref given, .. } => given, } } } impl Error for ParseColorError { fn description(&self) -> &str { match self.0 { ParseColorErrorKind::TermColor(ref err) => err.description(), ParseColorErrorKind::Unrecognized { .. } => "unrecognized color value", } } } impl fmt::Display for ParseColorError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.0 { ParseColorErrorKind::TermColor(ref err) => fmt::Display::fmt(err, f), ParseColorErrorKind::Unrecognized { ref given, .. } => { write!(f, "unrecognized color value '{}'", given) } } } } impl Color { fn to_termcolor(self) -> Option { match self { Color::Black => Some(termcolor::Color::Black), Color::Blue => Some(termcolor::Color::Blue), Color::Green => Some(termcolor::Color::Green), Color::Red => Some(termcolor::Color::Red), Color::Cyan => Some(termcolor::Color::Cyan), Color::Magenta => Some(termcolor::Color::Magenta), Color::Yellow => Some(termcolor::Color::Yellow), Color::White => Some(termcolor::Color::White), Color::Ansi256(value) => Some(termcolor::Color::Ansi256(value)), Color::Rgb(r, g, b) => Some(termcolor::Color::Rgb(r, g, b)), _ => None, } } fn from_termcolor(color: termcolor::Color) -> Option { match color { termcolor::Color::Black => Some(Color::Black), termcolor::Color::Blue => Some(Color::Blue), termcolor::Color::Green => Some(Color::Green), termcolor::Color::Red => Some(Color::Red), termcolor::Color::Cyan => Some(Color::Cyan), termcolor::Color::Magenta => Some(Color::Magenta), termcolor::Color::Yellow => Some(Color::Yellow), termcolor::Color::White => Some(Color::White), termcolor::Color::Ansi256(value) => Some(Color::Ansi256(value)), termcolor::Color::Rgb(r, g, b) => Some(Color::Rgb(r, g, b)), _ => None, } } } impl FromStr for Color { type Err = ParseColorError; fn from_str(s: &str) -> Result { let tc = termcolor::Color::from_str(s).map_err(ParseColorError::termcolor)?; Color::from_termcolor(tc).ok_or(ParseColorError::unrecognized(s.to_owned())) } } fn parse_write_style(spec: &str) -> WriteStyle { match spec { "auto" => WriteStyle::Auto, "always" => WriteStyle::Always, "never" => WriteStyle::Never, _ => Default::default(), } } #[cfg(test)] mod tests { use super::*; #[test] fn parse_write_style_valid() { let inputs = vec![ ("auto", WriteStyle::Auto), ("always", WriteStyle::Always), ("never", WriteStyle::Never), ]; for (input, expected) in inputs { assert_eq!(expected, parse_write_style(input)); } } #[test] fn parse_write_style_invalid() { let inputs = vec![ "", "true", "false", "NEVER!!" ]; for input in inputs { assert_eq!(WriteStyle::Auto, parse_write_style(input)); } } #[test] fn parse_color_name_valid() { let inputs = vec![ "black", "blue", "green", "red", "cyan", "magenta", "yellow", "white", ]; for input in inputs { assert!(Color::from_str(input).is_ok()); } } #[test] fn parse_color_ansi_valid() { let inputs = vec![ "7", "32", "0xFF", ]; for input in inputs { assert!(Color::from_str(input).is_ok()); } } #[test] fn parse_color_rgb_valid() { let inputs = vec![ "0,0,0", "0,128,255", "0x0,0x0,0x0", "0x33,0x66,0xFF", ]; for input in inputs { assert!(Color::from_str(input).is_ok()); } } #[test] fn parse_color_invalid() { let inputs = vec![ "not_a_color", "256", "0,0", "0,0,256", ]; for input in inputs { let err = Color::from_str(input).unwrap_err(); assert_eq!(input, err.invalid()); } } } vendor/env_logger-0.5.7/src/lib.rs0000644000000000000000000007327713264166600015574 0ustar rootroot// 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! A simple logger configured via environment variables which writes //! to stdout or stderr, for use with the logging facade exposed by the //! [`log` crate][log-crate-url]. //! //! ## Example //! //! ``` //! #[macro_use] extern crate log; //! extern crate env_logger; //! //! use log::Level; //! //! fn main() { //! env_logger::init(); //! //! debug!("this is a debug {}", "message"); //! error!("this is printed by default"); //! //! if log_enabled!(Level::Info) { //! let x = 3 * 4; // expensive computation //! info!("the answer was: {}", x); //! } //! } //! ``` //! //! Assumes the binary is `main`: //! //! ```{.bash} //! $ RUST_LOG=error ./main //! ERROR: 2017-11-09T02:12:24Z: main: this is printed by default //! ``` //! //! ```{.bash} //! $ RUST_LOG=info ./main //! ERROR: 2017-11-09T02:12:24Z: main: this is printed by default //! INFO: 2017-11-09T02:12:24Z: main: the answer was: 12 //! ``` //! //! ```{.bash} //! $ RUST_LOG=debug ./main //! DEBUG: 2017-11-09T02:12:24Z: main: this is a debug message //! ERROR: 2017-11-09T02:12:24Z: main: this is printed by default //! INFO: 2017-11-09T02:12:24Z: main: the answer was: 12 //! ``` //! //! You can also set the log level on a per module basis: //! //! ```{.bash} //! $ RUST_LOG=main=info ./main //! ERROR: 2017-11-09T02:12:24Z: main: this is printed by default //! INFO: 2017-11-09T02:12:24Z: main: the answer was: 12 //! ``` //! //! And enable all logging: //! //! ```{.bash} //! $ RUST_LOG=main ./main //! DEBUG: 2017-11-09T02:12:24Z: main: this is a debug message //! ERROR: 2017-11-09T02:12:24Z: main: this is printed by default //! INFO: 2017-11-09T02:12:24Z: main: the answer was: 12 //! ``` //! //! If the binary name contains hyphens, you will need to replace //! them with underscores: //! //! ```{.bash} //! $ RUST_LOG=my_app ./my-app //! DEBUG: 2017-11-09T02:12:24Z: my_app: this is a debug message //! ERROR: 2017-11-09T02:12:24Z: my_app: this is printed by default //! INFO: 2017-11-09T02:12:24Z: my_app: the answer was: 12 //! ``` //! //! This is because Rust modules and crates cannot contain hyphens //! in their name, although `cargo` continues to accept them. //! //! See the documentation for the [`log` crate][log-crate-url] for more //! information about its API. //! //! ## Enabling logging //! //! Log levels are controlled on a per-module basis, and by default all logging //! is disabled except for `error!`. Logging is controlled via the `RUST_LOG` //! environment variable. The value of this environment variable is a //! comma-separated list of logging directives. A logging directive is of the //! form: //! //! ```text //! path::to::module=level //! ``` //! //! The path to the module is rooted in the name of the crate it was compiled //! for, so if your program is contained in a file `hello.rs`, for example, to //! turn on logging for this file you would use a value of `RUST_LOG=hello`. //! Furthermore, this path is a prefix-search, so all modules nested in the //! specified module will also have logging enabled. //! //! The actual `level` is optional to specify. If omitted, all logging will //! be enabled. If specified, it must be one of the strings `debug`, `error`, //! `info`, `warn`, or `trace`. //! //! As the log level for a module is optional, the module to enable logging for //! is also optional. If only a `level` is provided, then the global log //! level for all modules is set to this value. //! //! Some examples of valid values of `RUST_LOG` are: //! //! * `hello` turns on all logging for the 'hello' module //! * `info` turns on all info logging //! * `hello=debug` turns on debug logging for 'hello' //! * `hello,std::option` turns on hello, and std's option logging //! * `error,hello=warn` turn on global error logging and also warn for hello //! //! ## Filtering results //! //! A `RUST_LOG` directive may include a regex filter. The syntax is to append `/` //! followed by a regex. Each message is checked against the regex, and is only //! logged if it matches. Note that the matching is done after formatting the //! log string but before adding any logging meta-data. There is a single filter //! for all modules. //! //! Some examples: //! //! * `hello/foo` turns on all logging for the 'hello' module where the log //! message includes 'foo'. //! * `info/f.o` turns on all info logging where the log message includes 'foo', //! 'f1o', 'fao', etc. //! * `hello=debug/foo*foo` turns on debug logging for 'hello' where the log //! message includes 'foofoo' or 'fofoo' or 'fooooooofoo', etc. //! * `error,hello=warn/[0-9]scopes` turn on global error logging and also //! warn for hello. In both cases the log message must include a single digit //! number followed by 'scopes'. //! //! ## Disabling colors //! //! Colors and other styles can be configured with the `RUST_LOG_STYLE` //! environment variable. It accepts the following values: //! //! * `auto` (default) will attempt to print style characters, but don't force the issue. //! If the console isn't available on Windows, or if TERM=dumb, for example, then don't print colors. //! * `always` will always print style characters even if they aren't supported by the terminal. //! This includes emitting ANSI colors on Windows if the console API is unavailable. //! * `never` will never print style characters. //! //! ## Tweaking the default format //! //! Parts of the default format can be excluded from the log output using the [`Builder`]. //! The following example excluding the timestamp from the log output: //! //! ``` //! #[macro_use] extern crate log; //! extern crate env_logger; //! //! use log::Level; //! //! fn main() { //! env_logger::Builder::from_default_env() //! .default_format_timestamp(false) //! .init(); //! //! debug!("this is a debug {}", "message"); //! error!("this is printed by default"); //! //! if log_enabled!(Level::Info) { //! let x = 3 * 4; // expensive computation //! info!("the answer was: {}", x); //! } //! } //! ``` //! //! [log-crate-url]: https://docs.rs/log/ //! [`Builder`]: struct.Builder.html #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "https://docs.rs/env_logger/0.5.7")] #![cfg_attr(test, deny(warnings))] // When compiled for the rustc compiler itself we want to make sure that this is // an unstable crate #![cfg_attr(rustbuild, feature(staged_api, rustc_private))] #![cfg_attr(rustbuild, unstable(feature = "rustc_private", issue = "27812"))] #![deny(missing_debug_implementations, missing_docs, warnings)] extern crate log; extern crate termcolor; extern crate humantime; extern crate atty; use std::env; use std::borrow::Cow; use std::io::prelude::*; use std::io; use std::mem; use std::cell::RefCell; use log::{Log, LevelFilter, Level, Record, SetLoggerError, Metadata}; pub mod filter; pub mod fmt; pub use self::fmt::{Target, WriteStyle, Color, Formatter}; const DEFAULT_FILTER_ENV: &'static str = "RUST_LOG"; const DEFAULT_WRITE_STYLE_ENV: &'static str = "RUST_LOG_STYLE"; /// Set of environment variables to configure from. /// /// # Default environment variables /// /// By default, the `Env` will read the following environment variables: /// /// - `RUST_LOG`: the level filter /// - `RUST_LOG_STYLE`: whether or not to print styles with records. /// /// These sources can be configured using the builder methods on `Env`. #[derive(Debug)] pub struct Env<'a> { filter: Cow<'a, str>, write_style: Cow<'a, str>, } /// The env logger. /// /// This struct implements the `Log` trait from the [`log` crate][log-crate-url], /// which allows it to act as a logger. /// /// The [`init()`], [`try_init()`], [`Builder::init()`] and [`Builder::try_init()`] /// methods will each construct a `Logger` and immediately initialize it as the /// default global logger. /// /// If you'd instead need access to the constructed `Logger`, you can use /// the associated [`Builder`] and install it with the /// [`log` crate][log-crate-url] directly. /// /// [log-crate-url]: https://docs.rs/log/ /// [`init()`]: fn.init.html /// [`try_init()`]: fn.try_init.html /// [`Builder::init()`]: struct.Builder.html#method.init /// [`Builder::try_init()`]: struct.Builder.html#method.try_init /// [`Builder`]: struct.Builder.html pub struct Logger { writer: fmt::Writer, filter: filter::Filter, format: Box io::Result<()> + Sync + Send>, } struct Format { default_format_timestamp: bool, default_format_module_path: bool, default_format_level: bool, custom_format: Option io::Result<()> + Sync + Send>>, } impl Default for Format { fn default() -> Self { Format { default_format_timestamp: true, default_format_module_path: true, default_format_level: true, custom_format: None, } } } impl Format { /// Convert the format into a callable function. /// /// If the `custom_format` is `Some`, then any `default_format` switches are ignored. /// If the `custom_format` is `None`, then a default format is returned. /// Any `default_format` switches set to `false` won't be written by the format. fn into_boxed_fn(self) -> Box io::Result<()> + Sync + Send> { if let Some(fmt) = self.custom_format { fmt } else { Box::new(move |buf, record| { let write_level = if self.default_format_level { let level = record.level(); let mut level_style = buf.style(); match level { Level::Trace => level_style.set_color(Color::White), Level::Debug => level_style.set_color(Color::Blue), Level::Info => level_style.set_color(Color::Green), Level::Warn => level_style.set_color(Color::Yellow), Level::Error => level_style.set_color(Color::Red).set_bold(true), }; write!(buf, "{:>5} ", level_style.value(level)) } else { Ok(()) }; let write_ts = if self.default_format_timestamp { let ts = buf.timestamp(); write!(buf, "{}: ", ts) } else { Ok(()) }; let default_format_module_path = (self.default_format_module_path, record.module_path()); let write_module_path = if let (true, Some(module_path)) = default_format_module_path { write!(buf, "{}: ", module_path) } else { Ok(()) }; let write_args = writeln!(buf, "{}", record.args()); write_level.and(write_ts).and(write_module_path).and(write_args) }) } } } /// `Builder` acts as builder for initializing a `Logger`. /// /// It can be used to customize the log format, change the environment variable used /// to provide the logging directives and also set the default log level filter. /// /// # Examples /// /// ``` /// #[macro_use] /// extern crate log; /// extern crate env_logger; /// /// use std::env; /// use std::io::Write; /// use log::LevelFilter; /// use env_logger::Builder; /// /// fn main() { /// let mut builder = Builder::from_default_env(); /// /// builder.format(|buf, record| writeln!(buf, "{} - {}", record.level(), record.args())) /// .filter(None, LevelFilter::Info) /// .init(); /// /// error!("error message"); /// info!("info message"); /// } /// ``` #[derive(Default)] pub struct Builder { filter: filter::Builder, writer: fmt::Builder, format: Format, } impl Builder { /// Initializes the log builder with defaults. /// /// **NOTE:** This method won't read from any environment variables. /// Use the [`filter`] and [`write_style`] methods to configure the builder /// or use [`from_env`] or [`from_default_env`] instead. /// /// # Examples /// /// Create a new builder and configure filters and style: /// /// ``` /// # extern crate log; /// # extern crate env_logger; /// # fn main() { /// use log::LevelFilter; /// use env_logger::{Builder, WriteStyle}; /// /// let mut builder = Builder::new(); /// /// builder.filter(None, LevelFilter::Info) /// .write_style(WriteStyle::Always) /// .init(); /// # } /// ``` /// /// [`filter`]: #method.filter /// [`write_style`]: #method.write_style /// [`from_env`]: #method.from_env /// [`from_default_env`]: #method.from_default_env pub fn new() -> Builder { Default::default() } /// Initializes the log builder from the environment. /// /// The variables used to read configuration from can be tweaked before /// passing in. /// /// # Examples /// /// Initialise a logger reading the log filter from an environment variable /// called `MY_LOG`: /// /// ``` /// use env_logger::Builder; /// /// let mut builder = Builder::from_env("MY_LOG"); /// builder.init(); /// ``` /// /// Initialise a logger using the `MY_LOG` variable for filtering and /// `MY_LOG_STYLE` for whether or not to write styles: /// /// ``` /// use env_logger::{Builder, Env}; /// /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE"); /// /// let mut builder = Builder::from_env(env); /// builder.init(); /// ``` pub fn from_env<'a, E>(env: E) -> Self where E: Into> { let mut builder = Builder::new(); let env = env.into(); if let Some(s) = env.get_filter() { builder.parse(&s); } if let Some(s) = env.get_write_style() { builder.parse_write_style(&s); } builder } /// Initializes the log builder from the environment using default variable names. /// /// This method is a convenient way to call `from_env(Env::default())` without /// having to use the `Env` type explicitly. The builder will use the /// [default environment variables]. /// /// # Examples /// /// Initialise a logger using the default environment variables: /// /// ``` /// use env_logger::Builder; /// /// let mut builder = Builder::from_default_env(); /// builder.init(); /// ``` /// /// [default environment variables]: struct.Env.html#default-environment-variables pub fn from_default_env() -> Self { Self::from_env(Env::default()) } /// Sets the format function for formatting the log output. /// /// This function is called on each record logged and should format the /// log record and output it to the given [`Formatter`]. /// /// The format function is expected to output the string directly to the /// `Formatter` so that implementations can use the [`std::fmt`] macros /// to format and output without intermediate heap allocations. The default /// `env_logger` formatter takes advantage of this. /// /// # Examples /// /// Use a custom format to write only the log message: /// /// ``` /// use std::io::Write; /// use env_logger::Builder; /// /// let mut builder = Builder::new(); /// /// builder.format(|buf, record| write!(buf, "{}", record.args())); /// ``` /// /// [`Formatter`]: fmt/struct.Formatter.html /// [`String`]: https://doc.rust-lang.org/stable/std/string/struct.String.html /// [`std::fmt`]: https://doc.rust-lang.org/std/fmt/index.html pub fn format(&mut self, format: F) -> &mut Self where F: Fn(&mut Formatter, &Record) -> io::Result<()> + Sync + Send { self.format.custom_format = Some(Box::new(format)); self } /// Use the default format. /// /// This method will clear any custom format set on the builder. pub fn default_format(&mut self) -> &mut Self { self.format.custom_format = None; self } /// Whether or not to write the level in the default format. pub fn default_format_level(&mut self, write: bool) -> &mut Self { self.format.default_format_level = write; self } /// Whether or not to write the module path in the default format. pub fn default_format_module_path(&mut self, write: bool) -> &mut Self { self.format.default_format_module_path = write; self } /// Whether or not to write the timestamp in the default format. pub fn default_format_timestamp(&mut self, write: bool) -> &mut Self { self.format.default_format_timestamp = write; self } /// Adds filters to the logger. /// /// The given module (if any) will log at most the specified level provided. /// If no module is provided then the filter will apply to all log messages. /// /// # Examples /// /// Only include messages for warning and above for logs in `path::to::module`: /// /// ``` /// # extern crate log; /// # extern crate env_logger; /// # fn main() { /// use log::LevelFilter; /// use env_logger::Builder; /// /// let mut builder = Builder::new(); /// /// builder.filter(Some("path::to::module"), LevelFilter::Info); /// # } /// ``` pub fn filter(&mut self, module: Option<&str>, level: LevelFilter) -> &mut Self { self.filter.filter(module, level); self } /// Parses the directives string in the same form as the `RUST_LOG` /// environment variable. /// /// See the module documentation for more details. pub fn parse(&mut self, filters: &str) -> &mut Self { self.filter.parse(filters); self } /// Sets the target for the log output. /// /// Env logger can log to either stdout or stderr. The default is stderr. /// /// # Examples /// /// Write log message to `stdout`: /// /// ``` /// use env_logger::{Builder, Target}; /// /// let mut builder = Builder::new(); /// /// builder.target(Target::Stdout); /// ``` pub fn target(&mut self, target: fmt::Target) -> &mut Self { self.writer.target(target); self } /// Sets whether or not styles will be written. /// /// This can be useful in environments that don't support control characters /// for setting colors. /// /// # Examples /// /// Never attempt to write styles: /// /// ``` /// use env_logger::{Builder, WriteStyle}; /// /// let mut builder = Builder::new(); /// /// builder.write_style(WriteStyle::Never); /// ``` pub fn write_style(&mut self, write_style: fmt::WriteStyle) -> &mut Self { self.writer.write_style(write_style); self } /// Parses whether or not to write styles in the same form as the `RUST_LOG_STYLE` /// environment variable. /// /// See the module documentation for more details. pub fn parse_write_style(&mut self, write_style: &str) -> &mut Self { self.writer.parse(write_style); self } /// Initializes the global logger with the built env logger. /// /// This should be called early in the execution of a Rust program. Any log /// events that occur before initialization will be ignored. /// /// # Errors /// /// This function will fail if it is called more than once, or if another /// library has already initialized a global logger. pub fn try_init(&mut self) -> Result<(), SetLoggerError> { let logger = self.build(); log::set_max_level(logger.filter()); log::set_boxed_logger(Box::new(logger)) } /// Initializes the global logger with the built env logger. /// /// This should be called early in the execution of a Rust program. Any log /// events that occur before initialization will be ignored. /// /// # Panics /// /// This function will panic if it is called more than once, or if another /// library has already initialized a global logger. pub fn init(&mut self) { self.try_init().expect("Builder::init should not be called after logger initialized"); } /// Build an env logger. /// /// The returned logger implements the `Log` trait and can be installed manually /// or nested within another logger. pub fn build(&mut self) -> Logger { Logger { writer: self.writer.build(), filter: self.filter.build(), format: mem::replace(&mut self.format, Default::default()).into_boxed_fn(), } } } impl Logger { /// Creates the logger from the environment. /// /// The variables used to read configuration from can be tweaked before /// passing in. /// /// # Examples /// /// Create a logger reading the log filter from an environment variable /// called `MY_LOG`: /// /// ``` /// use env_logger::Logger; /// /// let logger = Logger::from_env("MY_LOG"); /// ``` /// /// Create a logger using the `MY_LOG` variable for filtering and /// `MY_LOG_STYLE` for whether or not to write styles: /// /// ``` /// use env_logger::{Logger, Env}; /// /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE"); /// /// let logger = Logger::from_env(env); /// ``` pub fn from_env<'a, E>(env: E) -> Self where E: Into> { Builder::from_env(env).build() } /// Creates the logger from the environment using default variable names. /// /// This method is a convenient way to call `from_env(Env::default())` without /// having to use the `Env` type explicitly. The logger will use the /// [default environment variables]. /// /// # Examples /// /// Creates a logger using the default environment variables: /// /// ``` /// use env_logger::Logger; /// /// let logger = Logger::from_default_env(); /// ``` /// /// [default environment variables]: struct.Env.html#default-environment-variables pub fn from_default_env() -> Self { Builder::from_default_env().build() } /// Returns the maximum `LevelFilter` that this env logger instance is /// configured to output. pub fn filter(&self) -> LevelFilter { self.filter.filter() } /// Checks if this record matches the configured filter. pub fn matches(&self, record: &Record) -> bool { self.filter.matches(record) } } impl Log for Logger { fn enabled(&self, metadata: &Metadata) -> bool { self.filter.enabled(metadata) } fn log(&self, record: &Record) { if self.matches(record) { // Log records are written to a thread-local buffer before being printed // to the terminal. We clear these buffers afterwards, but they aren't shrinked // so will always at least have capacity for the largest log record formatted // on that thread. // // If multiple `Logger`s are used by the same threads then the thread-local // formatter might have different color support. If this is the case the // formatter and its buffer are discarded and recreated. thread_local! { static FORMATTER: RefCell> = RefCell::new(None); } FORMATTER.with(|tl_buf| { // It's possible for implementations to sometimes // log-while-logging (e.g. a `std::fmt` implementation logs // internally) but it's super rare. If this happens make sure we // at least don't panic and ship some output to the screen. let mut a; let mut b = None; let tl_buf = match tl_buf.try_borrow_mut() { Ok(f) => { a = f; &mut *a } Err(_) => &mut b, }; // Check the buffer style. If it's different from the logger's // style then drop the buffer and recreate it. match *tl_buf { Some(ref mut formatter) => { if formatter.write_style() != self.writer.write_style() { *formatter = Formatter::new(&self.writer) } }, ref mut tl_buf => *tl_buf = Some(Formatter::new(&self.writer)) } // The format is guaranteed to be `Some` by this point let mut formatter = tl_buf.as_mut().unwrap(); let _ = (self.format)(&mut formatter, record).and_then(|_| formatter.print(&self.writer)); // Always clear the buffer afterwards formatter.clear(); }); } } fn flush(&self) {} } impl<'a> Env<'a> { /// Get a default set of environment variables. pub fn new() -> Self { Self::default() } /// Specify an environment variable to read the filter from. pub fn filter(mut self, filter_env: E) -> Self where E: Into> { self.filter = filter_env.into(); self } fn get_filter(&self) -> Option { env::var(&*self.filter).ok() } /// Specify an environment variable to read the style from. pub fn write_style(mut self, write_style_env: E) -> Self where E: Into> { self.write_style = write_style_env.into(); self } fn get_write_style(&self) -> Option { env::var(&*self.write_style).ok() } } impl<'a, T> From for Env<'a> where T: Into> { fn from(filter_env: T) -> Self { Env::default().filter(filter_env.into()) } } impl<'a> Default for Env<'a> { fn default() -> Self { Env { filter: DEFAULT_FILTER_ENV.into(), write_style: DEFAULT_WRITE_STYLE_ENV.into() } } } mod std_fmt_impls { use std::fmt; use super::*; impl fmt::Debug for Logger{ fn fmt(&self, f: &mut fmt::Formatter)->fmt::Result { f.debug_struct("Logger") .field("filter", &self.filter) .finish() } } impl fmt::Debug for Builder{ fn fmt(&self, f: &mut fmt::Formatter)->fmt::Result { f.debug_struct("Logger") .field("filter", &self.filter) .field("writer", &self.writer) .finish() } } } /// Attempts to initialize the global logger with an env logger. /// /// This should be called early in the execution of a Rust program. Any log /// events that occur before initialization will be ignored. /// /// # Errors /// /// This function will fail if it is called more than once, or if another /// library has already initialized a global logger. pub fn try_init() -> Result<(), SetLoggerError> { try_init_from_env(Env::default()) } /// Initializes the global logger with an env logger. /// /// This should be called early in the execution of a Rust program. Any log /// events that occur before initialization will be ignored. /// /// # Panics /// /// This function will panic if it is called more than once, or if another /// library has already initialized a global logger. pub fn init() { try_init().expect("env_logger::init should not be called after logger initialized"); } /// Attempts to initialize the global logger with an env logger from the given /// environment variables. /// /// This should be called early in the execution of a Rust program. Any log /// events that occur before initialization will be ignored. /// /// # Examples /// /// Initialise a logger using the `MY_LOG` environment variable for filters /// and `MY_LOG_STYLE` for writing colors: /// /// ``` /// # extern crate env_logger; /// use env_logger::{Builder, Env}; /// /// # fn run() -> Result<(), Box<::std::error::Error>> { /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE"); /// /// env_logger::try_init_from_env(env)?; /// /// Ok(()) /// # } /// # fn main() { run().unwrap(); } /// ``` /// /// # Errors /// /// This function will fail if it is called more than once, or if another /// library has already initialized a global logger. pub fn try_init_from_env<'a, E>(env: E) -> Result<(), SetLoggerError> where E: Into> { let mut builder = Builder::from_env(env); builder.try_init() } /// Initializes the global logger with an env logger from the given environment /// variables. /// /// This should be called early in the execution of a Rust program. Any log /// events that occur before initialization will be ignored. /// /// # Examples /// /// Initialise a logger using the `MY_LOG` environment variable for filters /// and `MY_LOG_STYLE` for writing colors: /// /// ``` /// use env_logger::{Builder, Env}; /// /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE"); /// /// env_logger::init_from_env(env); /// ``` /// /// # Panics /// /// This function will panic if it is called more than once, or if another /// library has already initialized a global logger. pub fn init_from_env<'a, E>(env: E) where E: Into> { try_init_from_env(env).expect("env_logger::init_from_env should not be called after logger initialized"); } vendor/env_logger-0.5.7/tests/0000755000000000000000000000000013264166600015013 5ustar rootrootvendor/env_logger-0.5.7/tests/log-in-log.rs0000644000000000000000000000162513264166600017331 0ustar rootroot#[macro_use] extern crate log; extern crate env_logger; use std::process; use std::fmt; use std::env; use std::str; struct Foo; impl fmt::Display for Foo { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { info!("test"); f.write_str("bar") } } fn main() { env_logger::init(); if env::var("YOU_ARE_TESTING_NOW").is_ok() { return info!("{}", Foo); } let exe = env::current_exe().unwrap(); let out = process::Command::new(exe) .env("YOU_ARE_TESTING_NOW", "1") .env("RUST_LOG", "debug") .output() .unwrap_or_else(|e| panic!("Unable to start child process: {}", e)); if out.status.success() { return } println!("test failed: {}", out.status); println!("--- stdout\n{}", str::from_utf8(&out.stdout).unwrap()); println!("--- stderr\n{}", str::from_utf8(&out.stderr).unwrap()); process::exit(1); } vendor/env_logger-0.5.7/tests/regexp_filter.rs0000644000000000000000000000242213264166600020220 0ustar rootroot#[macro_use] extern crate log; extern crate env_logger; use std::process; use std::env; use std::str; fn main() { if env::var("LOG_REGEXP_TEST").ok() == Some(String::from("1")) { child_main(); } else { parent_main() } } fn child_main() { env_logger::init(); info!("XYZ Message"); } fn run_child(rust_log: String) -> bool { let exe = env::current_exe().unwrap(); let out = process::Command::new(exe) .env("LOG_REGEXP_TEST", "1") .env("RUST_LOG", rust_log) .output() .unwrap_or_else(|e| panic!("Unable to start child process: {}", e)); str::from_utf8(out.stderr.as_ref()).unwrap().contains("XYZ Message") } fn assert_message_printed(rust_log: &str) { if !run_child(rust_log.to_string()) { panic!("RUST_LOG={} should allow the test log message", rust_log) } } fn assert_message_not_printed(rust_log: &str) { if run_child(rust_log.to_string()) { panic!("RUST_LOG={} should not allow the test log message", rust_log) } } fn parent_main() { // test normal log severity levels assert_message_printed("info"); assert_message_not_printed("warn"); // test of regular expression filters assert_message_printed("info/XYZ"); assert_message_not_printed("info/XXX"); } vendor/failure-0.1.1/0000755000000000000000000000000013264166600013137 5ustar rootrootvendor/failure-0.1.1/.cargo-checksum.json0000644000000000000000000000013113264166600016776 0ustar rootroot{"files":{},"package":"934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82"}vendor/failure-0.1.1/.gitlab-ci.yml0000644000000000000000000000017413264166600015575 0ustar rootrootimage: "rust:latest" pages: script: - sh ./build-docs.sh artifacts: paths: - public only: - master vendor/failure-0.1.1/.travis.yml0000644000000000000000000000012513264166600015246 0ustar rootrootlanguage: rust rust: - 1.18.0 - stable - beta - nightly cache: cargo vendor/failure-0.1.1/CODE_OF_CONDUCT.md0000644000000000000000000000621613264166600015743 0ustar rootroot# 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 boats@mozilla.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/ vendor/failure-0.1.1/Cargo.toml0000644000000000000000000000204213264166600015065 0ustar rootroot# 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 = "failure" version = "0.1.1" authors = ["Without Boats "] description = "Experimental error handling abstraction." homepage = "https://boats.gitlab.io/failure" documentation = "https://docs.rs/failure" license = "MIT OR Apache-2.0" repository = "https://github.com/withoutboats/failure" [dependencies.backtrace] version = "0.3.3" optional = true [dependencies.failure_derive] version = "0.1.1" optional = true [features] std = ["backtrace"] derive = ["failure_derive"] default = ["std", "derive"] vendor/failure-0.1.1/LICENSE-APACHE0000644000000000000000000002513713264166600015073 0ustar rootroot 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. vendor/failure-0.1.1/LICENSE-MIT0000644000000000000000000000177713264166600014607 0ustar rootrootPermission 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. vendor/failure-0.1.1/README.md0000644000000000000000000000626513264166600014427 0ustar rootroot# failure - a new error management story [![Build Status](https://travis-ci.org/withoutboats/failure.svg?branch=master)](https://travis-ci.org/withoutboats/failure) [![Latest Version](https://img.shields.io/crates/v/failure.svg)](https://crates.io/crates/failure) [![docs](https://docs.rs/failure/badge.svg)](https://docs.rs/failure) `failure` is designed to make it easier to manage errors in Rust. It is intended to replace error management based on `std::error::Error` with a new system based on lessons learned over the past several years, including those learned from experience with quick-error and error-chain. `failure` provides two core components: * `Fail`: A new trait for custom error types. * `Error`: A struct which any type that implements `Fail` can be cast into. ## Example ```rust extern crate serde; extern crate toml; #[macro_use] extern crate failure; #[macro_use] extern crate serde_derive; use std::collections::HashMap; use std::path::PathBuf; use std::str::FromStr; use failure::Error; // This is a new error type that you've created. It represents the ways a // toolchain could be invalid. // // The custom derive for Fail derives an impl of both Fail and Display. // We don't do any other magic like creating new types. #[derive(Debug, Fail)] enum ToolchainError { #[fail(display = "invalid toolchain name: {}", name)] InvalidToolchainName { name: String, }, #[fail(display = "unknown toolchain version: {}", version)] UnknownToolchainVersion { version: String, } } pub struct ToolchainId { // ... etc } impl FromStr for ToolchainId { type Err = ToolchainError; fn from_str(s: &str) -> Result { // ... etc } } pub type Toolchains = HashMap; // This opens a toml file containing associations between ToolchainIds and // Paths (the roots of those toolchains). // // This could encounter an io Error, a toml parsing error, or a ToolchainError, // all of them will be thrown into the special Error type pub fn read_toolchains(path: PathBuf) -> Result { use std::fs::File; use std::io::Read; let mut string = String::new(); File::open(path)?.read_to_string(&mut string)?; let toml: HashMap = toml::from_str(&string)?; let toolchains = toml.iter().map(|(key, path)| { let toolchain_id = key.parse()?; Ok((toolchain_id, path)) }).collect::>()?; Ok(toolchains) } ``` ## Requirements Both failure and failure_derive are intended to compile on all stable versions of Rust newer than 1.18.0, as well as the latest beta and the latest nightly. If either crate fails to compile on any version newer than 1.18.0, please open an issue. failure is **no_std** compatible, though some aspects of it (primarily the `Error` type) will not be available in no_std mode. ## License failure is licensed under the terms of the MIT License or the Apache License 2.0, at your choosing. ## Code of Conduct Contribution to the failure crate is organized under the terms of the Contributor Covenant, the maintainer of failure, @withoutboats, promises to intervene to uphold that code of conduct. vendor/failure-0.1.1/RELEASES.md0000644000000000000000000000124313264166600014664 0ustar rootroot# Version 0.1.1 - Add a `Causes` iterator, which iterates over the causes of a failure. Can be accessed through the `Fail::causes` or `Error::causes` methods. - Add the `bail!` macro, which "throws" from the function. - Add the `ensure!` macro, which is like an "assert" which throws instead of panicking. - The derive now supports a no_std mode. - The derive is re-exported from `failure` by default, so that users do not have to directly depend on `failure_derive`. - Add a impl of `From for Context`, allowing users to `?` the `D` type to produce a `Context` (for cases where there is no further underlying error). # Version 0.1.0 - Initial version. vendor/failure-0.1.1/book/0000755000000000000000000000000013264166600014071 5ustar rootrootvendor/failure-0.1.1/book/src/0000755000000000000000000000000013264166600014660 5ustar rootrootvendor/failure-0.1.1/book/src/SUMMARY.md0000644000000000000000000000063013264166600016336 0ustar rootroot# Summary - [failure](./intro.md) - [How to use failure](./howto.md) - [The Fail trait](./fail.md) - [Deriving Fail](./derive-fail.md) - [The Error type](./error.md) - [Patterns & Guidance](./guidance.md) - [Strings as errors](./error-msg.md) - [A Custom Fail type](./custom-fail.md) - [Using the Error type](./use-error.md) - [An Error and ErrorKind pair](./error-errorkind.md) vendor/failure-0.1.1/book/src/custom-fail.md0000644000000000000000000000527113264166600017432 0ustar rootroot# A Custom Fail type This pattern is a way to define a new kind of failure. Defining a new kind of failure can be an effective way of representing an error for which you control all of the possible failure cases. It has several advantages: 1. You can enumerate exactly all of the possible failures that can occur in this context. 2. You have total control over the representation of the failure type. 3. Callers can destructure your error without any sort of downcasting. To implement this pattern, you should define your own type that implements `Fail`. You can use the [custom derive][derive-fail] to make this easier. For example: ```rust #[derive(Fail, Debug)] #[fail(display = "Input was invalid UTF-8")] pub struct Utf8Error; ``` This type can become as large and complicated as is appropriate to your use case. It can be an enum with a different variant for each possible error, and it can carry data with more precise information about the error. For example: ```rust #[derive(Fail, Debug)] #[fail(display = "Input was invalid UTF-8 at index {}", index)] pub struct Utf8Error { index: usize, } ``` ## When might you use this pattern? If you need to raise an error that doesn't come from one of your dependencies, this is a great pattern to use. You can also use this pattern in conjunction with [using `Error`][use-error] or defining an [Error and ErrorKind pair][error-errorkind]. Those functions which are "pure logic" and have a very constrained set of errors (such as parsing simple formats) might each return a different custom Fail type, and then the function which merges them all together, does IO, and so on, would return a more complex type like `Error` or your custom Error/ErrorKind. ## Caveats on this pattern When you have a dependency which returns a different error type, often you will be inclined to add it as a variant on your own error type. When you do that, you should tag the underlying error as the `#[cause]` of your error: ```rust #[derive(Fail, Debug)] pub enum MyError { #[fail(display = "Input was invalid UTF-8 at index {}", _0)] Utf8Error(usize), #[fail(display = "{}", _0)] Io(#[cause] io::Error), } ``` Up to a limit, this design can work. However, it has some problems: - It can be hard to be forward compatible with new dependencies that raise their own kinds of errors in the future. - It defines a 1-1 relationship between a variant of the error and an underlying error. Depending on your use case, as your function grows in complexity, it can be better to transition to [using Error][use-error] or [defining an Error & ErrorKind pair][error-errorkind]. [derive-fail]: ./derive-fail.html [use-error]: ./use-error.html [error-errorkind]: ./error-errorkind.html vendor/failure-0.1.1/book/src/derive-fail.md0000644000000000000000000001165213264166600017376 0ustar rootroot# Deriving `Fail` Though you can implement `Fail` yourself, we also provide a derive macro to generate the impl for you. To get access to this macro, you must tag the extenr crate declaration with `#[macro_use]`, as in: ```rust #[macro_use] extern crate failure; ``` In its smallest form, deriving Fail looks like this: ```rust #[macro_use] extern crate failure; use std::fmt; #[derive(Fail, Debug)] struct MyError; impl fmt::Display for MyError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "An error occurred.") } } ``` All failures need to implement `Display`, so we have added an impl of Display. However, implementing `Display` is much more boilerplate than implementing `Fail` - this is why we support deriving `Display` for you. ## Deriving `Display` You can derive an implementation of `Display` with a special attribute: ```rust #[macro_use] extern crate failure; #[derive(Fail, Debug)] #[fail(display = "An error occurred.")] struct MyError; ``` This attribute will cause the `Fail` derive to also generate an impl of `Display`, so that you don't have to implement one yourself. ### String interpolation String literals are not enough for error messages in many cases. Often, you want to include parts of the error value interpolated into the message. You can do this with failure using the same string interpolation syntax as Rust's formatting and printing macros: ```rust #[macro_use] extern crate failure; #[derive(Fail, Debug)] #[fail(display = "An error occurred with error code {}. ({})", code, message)] struct MyError { code: i32, message: String, } ``` Note that unlike code that would appear in a method, this does not use something like `self.code` or `self.message`; it just uses the field names directly. This is because of a limitation in Rust's current attribute syntax. As a result, you can only interpolate fields through the derivation; you cannot perform method calls or use other arbitrary expressions. ### Tuple structs With regular structs, you can use the name of the field in string interpolation. When deriving Fail for a tuple struct, you might expect to use the numeric index to refer to fields `0`, `1`, et cetera. However, a compiler limitation prevents this from parsing today. For the time being, tuple field accesses in the display attribute need to be prefixed with an underscore: ```rust #[macro_use] extern crate failure; #[derive(Fail, Debug)] #[fail(display = "An error occurred with error code {}.", _0)] struct MyError(i32); #[derive(Fail, Debug)] #[fail(display = "An error occurred with error code {} ({}).", _0, _1)] struct MyOtherError(i32, String); ``` ### Enums Implementing Display is also supported for enums by applying the attribute to each variant of the enum, rather than to the enum as a whole. The Display impl will match over the enum to generate the correct error message. For example: ```rust #[macro_use] extern crate failure; #[derive(Fail, Debug)] enum MyError { #[fail(display = "{} is not a valid version.", _0)] InvalidVersion(u32), #[fail(display = "IO error: {}", error)] IoError { error: io::Error }, #[fail(display = "An unknown error has occurred.")] UnknownError, } ``` ## Overriding `backtrace` The backtrace method will be automatically overridden if the type contains a field with the type `Backtrace`. This works for both structs and enums. ```rust #[macro_use] extern crate failure; use failure::Backtrace; /// MyError::backtrace will return a reference to the backtrace field #[derive(Fail, Debug)] #[fail(display = "An error occurred.")] struct MyError { backtrace: Backtrace, } /// MyEnumError::backtrace will return a reference to the backtrace only if it /// is Variant2, otherwise it will return None. #[derive(Fail, Debug)] enum MyEnumError { #[fail(display = "An error occurred.")] Variant1, #[fail(display = "A different error occurred.")] Variant2(Backtrace), } ``` This happens automatically; no other annotations are necessary. It only works if the type is named Backtrace, and not if you have created an alias for the Backtrace type. ## Overriding `cause` In contrast to `backtrace`, the cause cannot be determined by type name alone because it could be any type which implements `Fail`. For this reason, if your error has an underlying cause field, you need to annotate that field with the `#[cause]` attribute. This can be used in fields of enums as well as structs. ```rust #[macro_use] extern crate failure; use std::io; /// MyError::cause will return a reference to the io_error field #[derive(Fail, Debug)] #[fail(display = "An error occurred.")] struct MyError { #[cause] io_error: io::Error, } /// MyEnumError::cause will return a reference only if it is Variant2, /// otherwise it will return None. #[derive(Fail, Debug)] enum MyEnumError { #[fail(display = "An error occurred.")] Variant1, #[fail(display = "A different error occurred.")] Variant2(#[cause] io::Error), } ``` vendor/failure-0.1.1/book/src/error-errorkind.md0000644000000000000000000001142113264166600020327 0ustar rootroot# An Error and ErrorKind pair This pattern is the most robust way to manage errors - and also the most high maintenance. It combines some of the advantages of the [using Error][use-error] pattern and the [custom failure][custom-fail] patterns, while avoiding some of the disadvantages each of those patterns has: 1. Like `Error`, this is forward compatible with new underlying kinds of errors from your dependencies. 2. Like custom failures, this pattern allows you to specify additional information about the error that your dependencies don't give you. 3. Like `Error`, it can be easier to convert underlying errors from dependency into this type than for custom failures. 4. Like custom failures, users can gain some information about the error without downcasting. The pattern is to create two new failure types: an `Error` and an `ErrorKind`, and to leverage [the `Context` type][context-api] provided by failure. ```rust #[derive(Debug)] struct MyError { inner: Context, } #[derive(Copy, Clone, Eq, PartialEq, Debug, Fail)] enum MyErrorKind { // A plain enum with no data in any of its variants // // For example: #[fail(display = "A contextual error message.")] OneVariant, // ... } ``` Unfortunately, it is not easy to correctly derive `Fail` for `MyError` so that it delegates things to its inner `Context`. You should write those impls yourself: ```rust impl Fail for MyError { fn cause(&self) -> Option<&Fail> { self.inner.cause() } fn backtrace(&self) -> Option<&Backtrace> { self.inner.backtrace() } } impl Display for MyError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Display::fmt(&self.inner, f) } } ``` You should also provide some conversions and accessors, to go between a Context, your ErrorKind, and your Error: ```rust impl MyError { pub fn kind(&self) -> MyErrorKind { *self.inner.get_context() } } impl From for MyError { fn from(kind: MyErrorKind) -> MyError { MyError { inner: Context::new(kind) } } } impl From> for MyError { fn from(inner: Context) -> MyError { MyError { inner: inner } } } ``` With this code set up, you can use the context method from failure to apply your ErrorKind to errors in underlying libraries: ```rust perform_some_io().context(ErrorKind::NetworkFailure)?; ``` You can also directly throw `ErrorKind` without an underlying error when appropriate: ```rust Err(ErrorKind::DomainSpecificError)? ``` ### What should your ErrorKind contain? Your error kind probably should not carry data - and if it does, it should only carry stateless data types that provide additional information about what the `ErrorKind` means. This way, your `ErrorKind` can be `Eq`, making it easy to use as a way of comparing errors. Your ErrorKind is a way of providing information about what errors mean appropriate to the level of abstraction that your library operates at. As some examples: - If your library expects to read from the user's `Cargo.toml`, you might have a `InvalidCargoToml` variant, to capture what `io::Error` and `toml::Error` mean in the context of your library. - If your library does both file system activity and network activity, you might have `Filesystem` and `Network` variants, to divide up the `io::Error`s between which system in particular failed. Exactly what semantic information is appropriate depends entirely on what this bit of code is intended to do. ## When might you use this pattern? The most likely use cases for this pattern are mid-layer which perform a function that requires many dependencies, and that are intended to be used in production. Libraries with few dependencies do not need to manage many underlying error types and can probably suffice with a simpler [custom failure][custom-fail]. Applications that know they are almost always just going to log these errors can get away with [using the Error type][use-error] rather than managing extra context information. That said, when you need to provide the most expressive information about an error possible, this can be a good approach. ## Caveats on this pattern This pattern is the most involved pattern documented in this book. It involves a lot of boilerplate to set up (which may be automated away eventually), and it requires you to apply a contextual message to every underlying error that is thrown inside your code. It can be a lot of work to maintain this pattern. Additionally, like the Error type, the Context type may use an allocation and a dynamic dispatch internally. If you know this is too expensive for your use case, you should not use this pattern. [use-error]: ./use-error.html [custom-fail]: ./custom-fail.html [context-api]: https://boats.gitlab.io/failure/doc/failure/struct.Context.html vendor/failure-0.1.1/book/src/error-msg.md0000644000000000000000000000465013264166600017124 0ustar rootroot# Strings as errors This pattern is a way to create new errors without doing much set up. It is definitely the sloppiest way to throw errors. It can be great to use this during prototyping, but maybe not in the final product. String types do not implement `Fail`, which is why there are two adapters to create failures from a string: - [`failure::err_msg`][err-msg-api] - a function that takes a displayable type and creates a failure from it. This can take a String or a string literal. - [`format_err!`][format-err-api] - a macro with string interpolation, similar to `format!` or `println!`. ```rust fn check_range(x: usize, range: Range) -> Result { if x < range.start { return Err(format_err!("{} is below {}", x, range.start)); } if x >= range.end { return Err(format_err!("{} is above {}", x, range.end)); } Ok(x) } ``` If you're going to use strings as errors, we recommend [using `Error`][use-error] as your error type, rather than `ErrorMessage`; this way, if some of your strings are `String` and some are `&'static str`, you don't need worry about merging them into a single string type. ## When might you use this pattern? This pattern is the easiest to set up and get going with, so it can be great when prototyping or spiking out an early design. It can also be great when you know that an error variant is extremely uncommon, and that there is really no way to handle it other than to log the error and move on. ## Caveats on this pattern If you are writing a library you plan to publish to crates.io, this is probably not a good way to handle errors, because it doesn't give your clients very much control. For public, open source libraries, we'd recommend using [custom failures][custom-fail] in the cases where you would use a string as an error. This pattern can also be very brittle. If you ever want to branch over which error was returned, you would have to match on the exact contents of the string. If you ever change the string contents, that will silently break that match. For these reasons, we strongly recommend against using this pattern except for prototyping and when you know the error is just going to get logged or reported to the users. [custom-fail]: ./custom-fail.html [use-error]: ./use-error.html [err-msg-api]: https://boats.gitlab.io/failure/doc/failure/fn.err_msg.html [format-err-api]: https://boats.gitlab.io/failure/doc/failure/macro.format_err.html vendor/failure-0.1.1/book/src/error.md0000644000000000000000000000713013264166600016334 0ustar rootroot# The `Error` type In addition to the trait `Fail`, failure provides a type called `Error`. Any type that implements `Fail` can be cast into `Error` using From and Into, which allows users to throw errors using `?` which have different types, if the function returns an `Error`. For example: ```rust // Something you can deserialize #[derive(Deserialize)] struct Object { ... } impl Object { // This throws both IO Errors and JSON Errors, but they both get converted // into the Error type. fn from_file(path: &Path) -> Result { let mut string = String::new(); File::open(path)?.read_to_string(&mut string)?; let object = json::from_str(&string)?; Ok(object) } } ``` ## Causes and Backtraces The Error type has all of the methods from the Fail trait, with a few notable differences. Most importantly, the cause and backtrace methods on Error do not return Options - an Error is *guaranteed* to have a cause and a backtrace. ```rust // Both methods are guaranteed to return an &Fail and an &Backtrace println!("{}, {}", error.cause(), error.backtrace()) ``` An `Error`'s cause is always the failure that was cast into this `Error`. That failure may have further underlying causes. Unlike Fail, this means that the cause of an Error will have the same Display representation as the Error itself. As to the error's guaranteed backtrace, when the conversion into the Error type happens, if the underlying failure does not provide a backtrace, a new backtrace is constructed pointing to that conversion point (rather than the origin of the error). This construction only happens if there is no underlying backtrace; if it does have a backtrace no new backtrace is constructed. ## Downcasting The Error type also supports downcasting into any concrete Fail type. It can be downcast by reference or by value - when downcasting by value, the return type is `Result`, allowing you to get the error back out of it. ```rust match error.downcast::() { Ok(io_error) => { ... } Err(error) => { ... } } ``` ## Implementation details `Error` is essentially a trait object, but with some fanciness to store the backtrace it may generate if the underlying failure did not have one. In particular, we use a custom dynamically sized type to store the backtrace information inline with the trait object data. ```rust struct Error { // Inner is a dynamically sized type inner: Box>, } struct Inner { backtrace: Backtrace, failure: F, } ``` By storing the backtrace in the heap this way, we avoid increasing the size of the Error type beyond that of two non-nullable pointers. This keeps the size of the `Result` type from getting too large, avoiding having a negative impact on the "happy path" of returning Ok. For example, a `Result<(), Error>` should be represented as a pair of nullable pointers, with the null case representing `Ok`. Similar optimizations can be applied to values up to at least a pointer in size. To emphasize: Error is intended for use cases where the error case is considered relatively uncommon. This optimization makes the overhead of an error less than it otherwise would be for the Ok branch. In cases where errors are going to be returned extremely frequently, returning this Error type is probably not appropriate, but you should benchmark in those cases. (As a rule of thumb: if you're not sure if you can afford to have a trait object, you probably *can* afford it. Heap allocations are not nearly as cheap as stack allocations, but they're cheap enough that you can almost always afford them.) vendor/failure-0.1.1/book/src/fail.md0000644000000000000000000001303413264166600016116 0ustar rootroot# The `Fail` trait The `Fail` trait is a replacement for [`std::error::Error`][stderror]. It has been designed to support a number of operations: - Because it is bound by both `Debug` and `Display`, any failure can be printed in two ways. - It has both a `backtrace` and a `cause` method, allowing users to get information about how the error occurred. - It supports wrapping failures in additional contextual information. - Because it is bound by `Send` and `Sync`, failures can be moved and share between threads easily. - Because it is bound by `'static`, the abstract `Fail` trait object can be downcast into concrete types. Every new error type in your code should implement Fail, so it can be integrated into the entire system built around this trait. You can manually implement `Fail` yourself, or you can use the derive for Fail defined in a separate crate and documented [here][derive-docs]. Implementors of this trait are called 'failures'. ## Cause Often, an error type contains (or could contain) another underlying error type which represents the "cause" of this error - for example, if your custom error contains an `io::Error`, that is the cause of your error. The cause method on the Fail trait allows all errors to expose their underlying cause - if they have one - in a consistent way. Users can loop over the chain of causes, for example, getting the entire series of causes for an error: ```rust // Assume err is a type that implements Fail; let mut fail: &Fail = err; while let Some(cause) = fail.cause() { println!("{}", cause); // Make `fail` the reference to the cause of the previous fail, making the // loop "dig deeper" into the cause chain. fail = cause; } ``` Because `&Fail` supports downcasting, you can also inspect causes in more detail if you are expecting a certain failure: ```rust while let Some(cause) = fail.cause() { if let Some(err) = cause.downcast_ref::() { // treat io::Error specially } else { // fallback case } fail = cause; } ``` ## Backtraces Errors can also generate a backtrace when they are constructed, helping you determine the place the error was generated and every function that called into that. Like causes, this is entirely optional - the authors of each failure have to decide if generating a backtrace is appropriate in their use case. The backtrace method allows all errors to expose their backtrace if they have one. This enables a consistent method for getting the backtrace from an error: ```rust // We don't even know the type of the cause, but we can still get its // backtrace. if let Some(bt) = err.cause().and_then(|cause| cause.backtrace()) { println!("{}", bt) } ``` The Backtrace type exposed by failure is different from the Backtrace exposed by the backtrace crate, in that it has several optimizations: - It has a no_std compatible form which will never be generate (because backtraces require heap allocation), and should be entirely compiled out. - It will not be generated unless the RUST_BACKTRACE environmental variable has been set at runtime. - Symbol resolution is delayed until the backtrace is actually printed, because this is the most expensive part of generating a backtrace. ## Context Often, the libraries you are using will present error messages that don't provide very helpful information about what exactly has gone wrong. For example, if an `io::Error` says that an entity was "Not Found," that doesn't communicate much about what specific file was missing - if it even was a file (as opposed to a directory for example). You can inject additional context to be carried with this error value, providing semantic information about the nature of the error appropriate to the level of abstraction that the code you are writing operates at. The `context` method on `Fail` takes any displayable value (such as a string) to act as context for this error. Using the `ResultExt` trait, you can also get context as a convenient method on `Result` directly. For example, suppose that your code attempted to read from a Cargo.toml. You can wrap the io::Errors that occur with additional context about what operation has failed: ```rust use failure::ResultExt; let mut file = File::open(cargo_toml_path).context("Missing Cargo.toml")?; file.read_to_end(&buffer).context("Could not read Cargo.toml")?; ``` The `Context` object also has a constructor that does not take an underlying error, allowing you to create ad hoc Context errors alongside those created by applying the context method to an underlying error. ## Backwards compatibility We've taken several steps to make transitioning from std::error to failure as painless as possible. First, there is a blanket implementation of `Fail` for all types that implement `std::error::Error`, as long as they are Send, Sync, and 'static. If you are dealing with a library that hasn't shifted to `Fail`, it is automatically compatible with failure already. Second, `Fail` contains a method called compat, which produces a type that implements `std::error::Error`. If you have a type that implements `Fail`, but not the older Error trait, you can call compat to get a type that does implement that trait (for example, if you need to return a `Box`). The biggest hole in our backwards compatibility story is that you cannot implement `std::error::Error` and also override the backtrace and cause methods on `Fail`. We intend to enable this with specialization when it becomes stable. [derive-docs]: https://boats.gitlab.io/failure/derive-fail.html [stderror]: https://doc.rust-lang.org/std/error/trait.Error.html vendor/failure-0.1.1/book/src/guidance.md0000644000000000000000000000234113264166600016761 0ustar rootroot# Patterns & Guidance failure is not a "one size fits all" approach to error management. There are multiple patterns that emerge from the API this library provides, and users need to determine which pattern makes sense for them. This section documents some patterns and how users might use them. In brief, these are the patterns documented here: - **[Strings as errors](./error-msg.html):** Using strings as your error type. Good for prototyping. - **[A Custom Fail type](./custom-fail.html):** Defining a custom type to be your error type. Good for APIs where you control all or more of the possible failures. - **[Using the Error type](./use-error.html):** Using the Error type to pull together multiple failures of different types. Good for applications and APIs that know the error won't be inspected much more. - **[An Error and ErrorKind pair](./error-errorkind.html):** Using both a custom error type and an ErrorKind enum to create a very robust error type. Good for public APIs in large crates. (Though each of these items identifies a use case which this pattern would be good for, in truth each of them can be applied in various contexts. Its up to you to decide what makes the most sense for your particular use case.) vendor/failure-0.1.1/book/src/howto.md0000644000000000000000000000062313264166600016343 0ustar rootroot# How to use failure This section of the documentation is about how the APIs exposed in failure can be used. It is organized around the major APIs of failure: - **[The Fail trait](./fail.html):** The primary abstraction provided by failure. - **[Deriving Fail](./derive-fail.html):** A custom derive for the Fail trait. - **[The Error type](./error.html):** A convenient wrapper around any Fail type. vendor/failure-0.1.1/book/src/intro.md0000644000000000000000000000417113264166600016340 0ustar rootroot# failure This is the documentation for the failure crate, which provides a system for creating and managing errors in Rust. Additional documentation is found here: * [API documentation][api] * [failure source code][repo] * [failure_derive source code][derive-repo] [api]: https://boats.gitlab.io/failure/doc/failure [repo]: https://github.com/withoutboats/failure [derive-repo]: https://github.com/withoutboats/failure_derive ```rust extern crate serde; extern crate toml; #[macro_use] extern crate failure; #[macro_use] extern crate serde_derive; use std::collections::HashMap; use std::path::PathBuf; use std::str::FromStr; use failure::Error; // This is a new error type that you've created. It represents the ways a // toolchain could be invalid. // // The custom derive for Fail derives an impl of both Fail and Display. // We don't do any other magic like creating new types. #[derive(Debug, Fail)] enum ToolchainError { #[fail(display = "invalid toolchain name: {}", name)] InvalidToolchainName { name: String, }, #[fail(display = "unknown toolchain version: {}", version)] UnknownToolchainVersion { version: String, } } pub struct ToolchainId { // ... etc } impl FromStr for ToolchainId { type Err = ToolchainError; fn from_str(s: &str) -> Result { // ... etc } } pub type Toolchains = HashMap; // This opens a toml file containing associations between ToolchainIds and // Paths (the roots of those toolchains). // // This could encounter an io Error, a toml parsing error, or a ToolchainError, // all of them will be thrown into the special Error type pub fn read_toolchains(path: PathBuf) -> Result { use std::fs::File; use std::io::Read; let mut string = String::new(); File::open(path)?.read_to_string(&mut string)?; let toml: HashMap = toml::from_str(&string)?; let toolchains = toml.iter().map(|(key, path)| { let toolchain_id = key.parse()?; Ok((toolchain_id, path)) }).collect::>()?; Ok(toolchains) } vendor/failure-0.1.1/book/src/use-error.md0000644000000000000000000000401713264166600017127 0ustar rootroot# Use the `Error` type This pattern is a way to manage errors when you have multiple kinds of failure that could occur during a single function. It has several distinct advantages: 1. You can start using it without defining any of your own failure types. 2. All types that implement `Fail` can be thrown into the `Error` type using the `?` operator. 3. As you start adding new dependencies with their own failure types, you can start throwing them without making a breaking change. To use this pattern, all you need to do is return `Result<_, Error>` from your functions: ```rust use std::io; use std::io::BufRead; use failure::Error; use failure::err_msg; fn my_function() -> Result<(), Error> { let stdin = io::stdin(); for line in stdin.lock().lines() { let line = line?; if line.chars().all(|c| c.is_whitespace()) { break } if !line.starts_with("$") { return Err(format_err!("Input did not begin with `$`")); } println!("{}", &line[1..]); } Ok(()) } ``` ## When might you use this pattern? This pattern is very effective when you know you will usually not need to destructure the error this function returns. For example: - When prototyping. - When you know you are going to log this error, or display it to the user, either all of the time or nearly all of the time. - When it would be impractical for this API to report more custom context for the error (e.g. because it is a trait that doesn't want to add a new Error associated type). ## Caveats on this pattern There are two primary downsides to this pattern: - The `Error` type allocates. There are cases where this would be too expensive. In those cases you should use a [custom failure][custom-fail]. - You cannot recover more information about this error without downcasting. If your API needs to express more contextual information about the error, use the [Error and ErrorKind][error-errorkind] pattern. [custom-fail]: ./custom-fail.html [error-errorkind]: ./error-errorkind.html vendor/failure-0.1.1/build-docs.sh0000644000000000000000000000027513264166600015524 0ustar rootrootmkdir public cargo doc --no-deps cargo install mdbook --no-default-features mdbook build ./book cp -r ./target/doc/ ./public cp -r ./book/book/* ./public find $PWD/public | grep "\.html\$" vendor/failure-0.1.1/examples/0000755000000000000000000000000013264166600014755 5ustar rootrootvendor/failure-0.1.1/examples/bail_ensure.rs0000644000000000000000000000074113264166600017615 0ustar rootroot#[macro_use] extern crate failure; use failure::Error; fn bailer() -> Result<(), Error> { // bail!("ruh roh"); bail!("ruh {}", "roh"); } fn ensures() -> Result<(), Error> { ensure!(true, "true is false"); ensure!(false, "false is false"); Ok(()) } fn main() { match bailer() { Ok(_) => println!("ok"), Err(e) => println!("{}", e), } match ensures() { Ok(_) => println!("ok"), Err(e) => println!("{}", e), } } vendor/failure-0.1.1/src/0000755000000000000000000000000013264166600013726 5ustar rootrootvendor/failure-0.1.1/src/backtrace/0000755000000000000000000000000013264166600015645 5ustar rootrootvendor/failure-0.1.1/src/backtrace/internal.rs0000644000000000000000000000750613264166600020037 0ustar rootrootuse std::cell::UnsafeCell; use std::env; use std::ffi::OsString; use std::fmt; use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; use std::sync::Mutex; pub use super::backtrace::Backtrace; const GENERAL_BACKTRACE: &str = "RUST_BACKTRACE"; const FAILURE_BACKTRACE: &str = "RUST_FAILURE_BACKTRACE"; pub(super) struct InternalBacktrace { backtrace: Option, } struct MaybeResolved { resolved: Mutex, backtrace: UnsafeCell, } unsafe impl Send for MaybeResolved {} unsafe impl Sync for MaybeResolved {} impl InternalBacktrace { pub(super) fn new() -> InternalBacktrace { static ENABLED: AtomicUsize = ATOMIC_USIZE_INIT; match ENABLED.load(Ordering::SeqCst) { 0 => { let enabled = is_backtrace_enabled(|var| env::var_os(var)); ENABLED.store(enabled as usize + 1, Ordering::SeqCst); if !enabled { return InternalBacktrace { backtrace: None } } } 1 => return InternalBacktrace { backtrace: None }, _ => {} } InternalBacktrace { backtrace: Some(MaybeResolved { resolved: Mutex::new(false), backtrace: UnsafeCell::new(Backtrace::new_unresolved()), }), } } pub(super) fn none() -> InternalBacktrace { InternalBacktrace { backtrace: None } } pub(super) fn as_backtrace(&self) -> Option<&Backtrace> { let bt = match self.backtrace { Some(ref bt) => bt, None => return None, }; let mut resolved = bt.resolved.lock().unwrap(); unsafe { if !*resolved { (*bt.backtrace.get()).resolve(); *resolved = true; } Some(&*bt.backtrace.get()) } } pub(super) fn is_none(&self) -> bool { self.backtrace.is_none() } } impl fmt::Debug for InternalBacktrace { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("InternalBacktrace") .field("backtrace", &self.as_backtrace()) .finish() } } fn is_backtrace_enabled Option>(get_var: F) -> bool { match get_var(FAILURE_BACKTRACE) { Some(ref val) if val != "0" => true, Some(ref val) if val == "0" => false, _ => match get_var(GENERAL_BACKTRACE) { Some(ref val) if val != "0" => true, _ => false, } } } #[cfg(test)] mod tests { use super::*; const YEA: Option<&str> = Some("1"); const NAY: Option<&str> = Some("0"); const NOT_SET: Option<&str> = None; macro_rules! test_enabled { (failure: $failure:ident, general: $general:ident => $result:expr) => {{ assert_eq!(is_backtrace_enabled(|var| match var { FAILURE_BACKTRACE => $failure.map(OsString::from), GENERAL_BACKTRACE => $general.map(OsString::from), _ => panic!() }), $result); }} } #[test] fn always_enabled_if_failure_is_set_to_yes() { test_enabled!(failure: YEA, general: YEA => true); test_enabled!(failure: YEA, general: NOT_SET => true); test_enabled!(failure: YEA, general: NAY => true); } #[test] fn never_enabled_if_failure_is_set_to_no() { test_enabled!(failure: NAY, general: YEA => false); test_enabled!(failure: NAY, general: NOT_SET => false); test_enabled!(failure: NAY, general: NAY => false); } #[test] fn follows_general_if_failure_is_not_set() { test_enabled!(failure: NOT_SET, general: YEA => true); test_enabled!(failure: NOT_SET, general: NOT_SET => false); test_enabled!(failure: NOT_SET, general: NAY => false); } } vendor/failure-0.1.1/src/backtrace/mod.rs0000644000000000000000000001105513264166600016774 0ustar rootrootuse core::fmt::{self, Debug, Display}; without_std! { /// A `Backtrace`. /// /// This is an opaque wrapper around the backtrace provided by /// libbacktrace. A variety of optimizations have been performed to avoid /// unnecessary or ill-advised work: /// /// - If this crate is compiled in `no_std` compatible mode, `Backtrace` /// is an empty struct, and will be completely compiled away. /// - If this crate is run without the `RUST_BACKTRACE` environmental /// variable enabled, the backtrace will not be generated at runtime. /// - Even if a backtrace is generated, the most expensive part of /// generating a backtrace is symbol resolution. This backtrace does not /// perform symbol resolution until it is actually read (e.g. by /// printing it). If the Backtrace is never used for anything, symbols /// never get resolved. /// /// Even with these optimizations, including a backtrace in your failure /// may not be appropriate to your use case. You are not required to put a /// backtrace in a custom `Fail` type. /// /// > (We have detected that this crate was documented with no_std /// > compatibility turned on. The version of this crate that has been /// > documented here will never generate a backtrace.) pub struct Backtrace { _secret: (), } impl Backtrace { /// Constructs a new backtrace. This will only create a real backtrace /// if the crate is compiled in std mode and the `RUST_BACKTRACE` /// environmental variable is activated. /// /// > (We have detected that this crate was documented with no_std /// > compatibility turned on. The version of this crate that has been /// > documented here will never generate a backtrace.) pub fn new() -> Backtrace { Backtrace { _secret: () } } } impl Default for Backtrace { fn default() -> Backtrace { Backtrace::new() } } impl Debug for Backtrace { fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result { Ok(()) } } impl Display for Backtrace { fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result { Ok(()) } } } with_std! { extern crate backtrace; mod internal; use self::internal::InternalBacktrace; /// A `Backtrace`. /// /// This is an opaque wrapper around the backtrace provided by /// libbacktrace. A variety of optimizations have been performed to avoid /// unnecessary or ill-advised work: /// /// - If this crate is compiled in `no_std` compatible mode, `Backtrace` /// is an empty struct, and will be completely compiled away. /// - If this crate is run without the `RUST_BACKTRACE` environmental /// variable enabled, the backtrace will not be generated at runtime. /// - Even if a backtrace is generated, the most expensive part of /// generating a backtrace is symbol resolution. This backtrace does not /// perform symbol resolution until it is actually read (e.g. by /// printing it). If the Backtrace is never used for anything, symbols /// never get resolved. /// /// Even with these optimizations, including a backtrace in your failure /// may not be appropriate to your use case. You are not required to put a /// backtrace in a custom `Fail` type. pub struct Backtrace { internal: InternalBacktrace } impl Backtrace { /// Constructs a new backtrace. This will only create a real backtrace /// if the crate is compiled in std mode and the `RUST_BACKTRACE` /// environmental variable is activated. pub fn new() -> Backtrace { Backtrace { internal: InternalBacktrace::new() } } pub(crate) fn none() -> Backtrace { Backtrace { internal: InternalBacktrace::none() } } pub(crate) fn is_none(&self) -> bool { self.internal.is_none() } } impl Default for Backtrace { fn default() -> Backtrace { Backtrace::new() } } impl Debug for Backtrace { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if let Some(bt) = self.internal.as_backtrace() { bt.fmt(f) } else { Ok(()) } } } impl Display for Backtrace { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if let Some(bt) = self.internal.as_backtrace() { bt.fmt(f) } else { Ok(()) } } } } vendor/failure-0.1.1/src/compat.rs0000644000000000000000000000200313264166600015552 0ustar rootrootuse core::fmt::{self, Display}; /// A compatibility wrapper around an error type from this crate. /// /// `Compat` implements `std::error::Error`, allowing the types from this /// crate to be passed to interfaces that expect a type of that trait. #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default)] pub struct Compat { pub(crate) error: E, } impl Display for Compat { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Display::fmt(&self.error, f) } } impl Compat { /// Unwraps this into the inner error. pub fn into_inner(self) -> E { self.error } } with_std! { use std::fmt::Debug; use std::error::Error as StdError; use Error; impl StdError for Compat { fn description(&self) -> &'static str { "An error has occurred." } } impl From for Box { fn from(error: Error) -> Box { Box::new(Compat { error }) } } } vendor/failure-0.1.1/src/context.rs0000644000000000000000000001045313264166600015763 0ustar rootrootuse core::fmt::{self, Display, Debug}; use Fail; without_std! { /// An error with context around it. /// /// The context is intended to be a human-readable, user-facing explanation for the /// error that has occurred. The underlying error is not assumed to be end-user-relevant /// information. /// /// The `Display` impl for `Context` only prints the human-readable context, while the /// `Debug` impl also prints the underlying error. pub struct Context { context: D, } impl Context { /// Creates a new context without an underlying error message. pub fn new(context: D) -> Context { Context { context } } /// Returns a reference to the context provided with this error. pub fn get_context(&self) -> &D { &self.context } pub(crate) fn with_err(context: D, _: E) -> Context { Context { context } } } impl Fail for Context { } impl Debug for Context { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.context) } } impl Display for Context { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.context) } } } with_std! { use {Error, Backtrace}; /// An error with context around it. /// /// The context is intended to be a human-readable, user-facing explanation for the /// error that has occurred. The underlying error is not assumed to be end-user-relevant /// information. /// /// The `Display` impl for `Context` only prints the human-readable context, while the /// `Debug` impl also prints the underlying error. pub struct Context { context: D, failure: Either, } impl Context { /// Creates a new context without an underlying error message. pub fn new(context: D) -> Context { let failure = Either::This(Backtrace::new()); Context { context, failure } } /// Returns a reference to the context provided with this error. pub fn get_context(&self) -> &D { &self.context } pub(crate) fn with_err>(context: D, error: E) -> Context { let failure = Either::That(error.into()); Context { context, failure } } } impl Fail for Context { fn cause(&self) -> Option<&Fail> { self.failure.cause() } fn backtrace(&self) -> Option<&Backtrace> { Some(self.failure.backtrace()) } } impl Debug for Context { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{:?}\n\n{}", self.failure, self.context) } } impl Display for Context { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.context) } } enum Either { This(A), That(B), } impl Either { fn backtrace(&self) -> &Backtrace { match *self { Either::This(ref backtrace) => backtrace, Either::That(ref error) => error.backtrace(), } } fn cause(&self) -> Option<&Fail> { match *self { Either::This(_) => None, Either::That(ref error) => Some(error.cause()) } } } impl Debug for Either { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Either::This(ref backtrace) => write!(f, "{:?}", backtrace), Either::That(ref error) => write!(f, "{:?}", error), } } } } impl From for Context where D: Display + Send + Sync + 'static { fn from(display: D) -> Context { Context::new(display) } } vendor/failure-0.1.1/src/error.rs0000644000000000000000000001303313264166600015425 0ustar rootrootuse core::fmt::{self, Display, Debug}; use core::mem; use core::ptr; use {Causes, Fail}; use backtrace::Backtrace; use context::Context; use compat::Compat; /// The `Error` type, which can contain any failure. /// /// Functions which accumulate many kinds of errors should return this type. /// All failures can be converted into it, so functions which catch those /// errors can be tried with `?` inside of a function that returns this kind /// of error. /// /// In addition to implementing `Debug` and `Display`, this type carries `Backtrace` /// information, and can be downcast into the failure that underlies it for /// more detailed inspection. pub struct Error { pub(crate) inner: Box>, } pub(crate) struct Inner { backtrace: Backtrace, pub(crate) failure: F, } impl From for Error { fn from(failure: F) -> Error { let inner: Inner = { let backtrace = if failure.backtrace().is_none() { Backtrace::new() } else { Backtrace::none() }; Inner { failure, backtrace } }; Error { inner: Box::new(inner) } } } impl Error { /// Returns a reference to the underlying cause of this `Error`. Unlike the /// method on `Fail`, this does not return an `Option`. The `Error` type /// always has an underlying failure. pub fn cause(&self) -> &Fail { &self.inner.failure } /// Gets a reference to the `Backtrace` for this `Error`. /// /// If the failure this wrapped carried a backtrace, that backtrace will /// be returned. Otherwise, the backtrace will have been constructed at /// the point that failure was cast into the `Error` type. pub fn backtrace(&self) -> &Backtrace { self.inner.failure.backtrace().unwrap_or(&self.inner.backtrace) } /// Provides context for this `Error`. /// /// This can provide additional information about this error, appropriate /// to the semantics of the current layer. That is, if you have a /// lower-level error, such as an IO error, you can provide additional context /// about what that error means in the context of your function. This /// gives users of this function more information about what has gone /// wrong. /// /// This takes any type that implements `Display`, as well as /// `Send`/`Sync`/`'static`. In practice, this means it can take a `String` /// or a string literal, or a failure, or some other custom context-carrying /// type. pub fn context(self, context: D) -> Context { Context::with_err(context, self) } /// Wraps `Error` in a compatibility type. /// /// This type implements the `Error` trait from `std::error`. If you need /// to pass failure's `Error` to an interface that takes any `Error`, you /// can use this method to get a compatible type. pub fn compat(self) -> Compat { Compat { error: self } } /// Attempts to downcast this `Error` to a particular `Fail` type. /// /// This downcasts by value, returning an owned `T` if the underlying /// failure is of the type `T`. For this reason it returns a `Result` - in /// the case that the underlying error is of a different type, the /// original `Error` is returned. pub fn downcast(self) -> Result { let ret: Option = self.downcast_ref().map(|fail| { unsafe { // drop the backtrace let _ = ptr::read(&self.inner.backtrace as *const Backtrace); // read out the fail type ptr::read(fail as *const T) } }); match ret { Some(ret) => { // forget self (backtrace is dropped, failure is moved mem::forget(self); Ok(ret) } _ => Err(self) } } /// Returns the "root cause" of this error - the last value in the /// cause chain which does not return an underlying `cause`. pub fn root_cause(&self) -> &Fail { ::find_root_cause(self.cause()) } /// Attempts to downcast this `Error` to a particular `Fail` type by /// reference. /// /// If the underlying error is not of type `T`, this will return `None`. pub fn downcast_ref(&self) -> Option<&T> { self.inner.failure.downcast_ref() } /// Attempts to downcast this `Error` to a particular `Fail` type by /// mutable reference. /// /// If the underlying error is not of type `T`, this will return `None`. pub fn downcast_mut(&mut self) -> Option<&mut T> { self.inner.failure.downcast_mut() } /// Returns a iterator over the causes of the `Error`, beginning with /// the failure returned by the `cause` method and ending with the failure /// returned by `root_cause`. pub fn causes(&self) -> Causes { Causes { fail: Some(self.cause()) } } } impl Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Display::fmt(&self.inner.failure, f) } } impl Debug for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if self.inner.backtrace.is_none() { Debug::fmt(&self.inner.failure, f) } else { write!(f, "{:?}\n\n{:?}", &self.inner.failure, self.inner.backtrace) } } } #[cfg(test)] mod test { fn assert_just_data() { } #[test] fn assert_error_is_just_data() { assert_just_data::(); } } vendor/failure-0.1.1/src/error_message.rs0000644000000000000000000000154113264166600017132 0ustar rootrootuse core::fmt::{self, Display, Debug}; use Fail; use Error; /// Constructs a `Fail` type from a string. /// /// This is a convenient way to turn a string into an error value that /// can be passed around, if you do not want to create a new `Fail` type for /// this use case. pub fn err_msg(msg: D) -> Error { Error::from(ErrorMessage { msg }) } /// A `Fail` type that just contains an error message. You can construct /// this from the `err_msg` function. #[derive(Debug)] struct ErrorMessage { msg: D, } impl Fail for ErrorMessage { } impl Display for ErrorMessage { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Display::fmt(&self.msg, f) } } vendor/failure-0.1.1/src/lib.rs0000644000000000000000000001626213264166600015051 0ustar rootroot//! An experimental new error-handling library. //! //! The primary items exported by this library are: //! //! - `Fail`: a new trait for custom error types in Rust. //! - `Error`: a wrapper around `Fail` types to make it easy to coalesce them //! at higher levels. //! //! As a general rule, library authors should create their own error types and //! implement `Fail` for them, whereas application authors should primarily //! deal with the `Error` type. There are exceptions to this rule, though, in //! both directions, and users should do whatever seems most appropriate to //! their situation. #![cfg_attr(not(feature = "std"), no_std)] #![deny(missing_docs)] macro_rules! with_std { ($($i:item)*) => ($(#[cfg(feature = "std")]$i)*) } macro_rules! without_std { ($($i:item)*) => ($(#[cfg(not(feature = "std"))]$i)*) } mod backtrace; mod compat; mod context; mod result_ext; use core::any::TypeId; use core::fmt::{Debug, Display}; pub use backtrace::Backtrace; pub use compat::Compat; pub use context::Context; pub use result_ext::ResultExt; #[cfg(feature = "derive")] #[allow(unused_imports)] #[macro_use] extern crate failure_derive; #[cfg(feature = "derive")] #[doc(hidden)] pub use failure_derive::*; with_std! { extern crate core; mod sync_failure; pub use sync_failure::SyncFailure; mod error; use std::error::Error as StdError; pub use error::Error; mod macros; mod error_message; pub use error_message::err_msg; } /// The `Fail` trait. /// /// Implementors of this trait are called 'failures'. /// /// All error types should implement `Fail`, which provides a baseline of /// functionality that they all share. /// /// `Fail` has no required methods, but it does require that your type /// implement several other traits: /// /// - `Display`: to print a user-friendly representation of the error. /// - `Debug`: to print a verbose, developer-focused representation of the /// error. /// - `Send + Sync`: Your error type is required to be safe to transfer to and /// reference from another thread /// /// Additionally, all failures must be `'static`. This enables downcasting. /// /// `Fail` provides several methods with default implementations. Two of these /// may be appropriate to override depending on the definition of your /// particular failure: the `cause` and `backtrace` methods. /// /// The `failure_derive` crate provides a way to derive the `Fail` trait for /// your type. Additionally, all types that already implement /// `std::error::Error`, and are also `Send`, `Sync`, and `'static`, implement /// `Fail` by a blanket impl. pub trait Fail: Display + Debug + Send + Sync + 'static { /// Returns a reference to the underlying cause of this failure, if it /// is an error that wraps other errors. /// /// Returns `None` if this failure does not have another error as its /// underlying cause. By default, this returns `None`. /// /// This should **never** return a reference to `self`, but only return /// `Some` when it can return a **different** failure. Users may loop /// over the cause chain, and returning `self` would result in an infinite /// loop. fn cause(&self) -> Option<&Fail> { None } /// Returns a reference to the `Backtrace` carried by this failure, if it /// carries one. /// /// Returns `None` if this failure does not carry a backtrace. By /// default, this returns `None`. fn backtrace(&self) -> Option<&Backtrace> { None } /// Provides context for this failure. /// /// This can provide additional information about this error, appropriate /// to the semantics of the current layer. That is, if you have a /// lower-level error, such as an IO error, you can provide additional context /// about what that error means in the context of your function. This /// gives users of this function more information about what has gone /// wrong. /// /// This takes any type that implements `Display`, as well as /// `Send`/`Sync`/`'static`. In practice, this means it can take a `String` /// or a string literal, or another failure, or some other custom context-carrying /// type. fn context(self, context: D) -> Context where D: Display + Send + Sync + 'static, Self: Sized, { Context::with_err(context, self) } /// Wraps this failure in a compatibility wrapper that implements /// `std::error::Error`. /// /// This allows failures to be compatible with older crates that /// expect types that implement the `Error` trait from `std::error`. fn compat(self) -> Compat where Self: Sized, { Compat { error: self } } /// Returns a iterator over the causes of this `Fail` with itself /// as the first item and the `root_cause` as the final item. fn causes(&self) -> Causes where Self: Sized { Causes { fail: Some(self) } } /// Returns the "root cause" of this `Fail` - the last value in the /// cause chain which does not return an underlying `cause`. /// /// If this type does not have a cause, `self` is returned, because /// it is its own root cause. fn root_cause(&self) -> &Fail where Self: Sized, { find_root_cause(self) } #[doc(hidden)] fn __private_get_type_id__(&self) -> TypeId { TypeId::of::() } } impl Fail { /// Attempts to downcast this failure to a concrete type by reference. /// /// If the underlying error is not of type `T`, this will return `None`. pub fn downcast_ref(&self) -> Option<&T> { if self.__private_get_type_id__() == TypeId::of::() { unsafe { Some(&*(self as *const Fail as *const T)) } } else { None } } /// Attempts to downcast this failure to a concrete type by mutable /// reference. /// /// If the underlying error is not of type `T`, this will return `None`. pub fn downcast_mut(&mut self) -> Option<&mut T> { if self.__private_get_type_id__() == TypeId::of::() { unsafe { Some(&mut *(self as *mut Fail as *mut T)) } } else { None } } /// Returns the "root cause" of this `Fail` - the last value in the /// cause chain which does not return an underlying `cause`. /// /// If this type does not have a cause, `self` is returned, because /// it is its own root cause. pub fn root_cause(&self) -> &Fail { find_root_cause(self) } /// Returns a iterator over the causes of this `Fail` with itself /// as the first item and the `root_cause` as the final item. pub fn causes(&self) -> Causes { Causes { fail: Some(self) } } } #[cfg(feature = "std")] impl Fail for E {} /// A iterator over the causes of a `Fail` pub struct Causes<'f> { fail: Option<&'f Fail>, } impl<'f> Iterator for Causes<'f> { type Item = &'f Fail; fn next(&mut self) -> Option<&'f Fail> { self.fail.map(|fail| { self.fail = fail.cause(); fail }) } } fn find_root_cause(mut fail: &Fail) -> &Fail { while let Some(cause) = fail.cause() { fail = cause; } fail } vendor/failure-0.1.1/src/macros.rs0000644000000000000000000000240113264166600015555 0ustar rootroot/// Exits a function early with an `Error`. /// /// The `bail!` macro provides an easy way to exit a function. `bail!(X)` is /// equivalent to writing: /// /// ```rust,ignore /// return Err(format_err!(X)) /// ``` #[macro_export] macro_rules! bail { ($e:expr) => { return Err($crate::err_msg($e)); }; ($fmt:expr, $($arg:tt)+) => { return Err($crate::err_msg(format!($fmt, $($arg)+))); }; } /// Exits a function early with an `Error` if the condition is not satisfied. /// /// Similar to `assert!`, `ensure!` takes a condition and exits the function /// if the condition fails. Unlike `assert!`, `ensure!` returns an `Error`, /// it does not panic. #[macro_export] macro_rules! ensure { ($cond:expr, $e:expr) => { if !($cond) { bail!($e); } }; ($cond:expr, $fmt:expr, $($arg:tt)+) => { if !($cond) { bail!($fmt, $($arg)+); } }; } /// Constructs an `Error` using the standard string interpolation syntax. /// /// ```rust /// #[macro_use] extern crate failure; /// /// fn main() { /// let code = 101; /// let err = format_err!("Error code: {}", code); /// } /// ``` #[macro_export] macro_rules! format_err { ($($arg:tt)*) => { $crate::err_msg(format!($($arg)*)) } } vendor/failure-0.1.1/src/result_ext.rs0000644000000000000000000000374613264166600016504 0ustar rootrootuse core::fmt::Display; use {Fail, Compat, Context}; /// Extension methods for `Result`. pub trait ResultExt { /// Wraps the error in `Compat` to make it compatible with older error /// handling APIs that expect `std::error::Error`. fn compat(self) -> Result>; /// Wraps the error type in a context type. fn context(self, context: D) -> Result> where D: Display + Send + Sync + 'static; /// Wraps the error type in a context type generated by looking at the /// error value. fn with_context(self, f: F) -> Result> where F: FnOnce(&E) -> D, D: Display + Send + Sync + 'static; } impl ResultExt for Result where E: Fail, { fn compat(self) -> Result> { self.map_err(|err| err.compat()) } fn context(self, context: D) -> Result> where D: Display + Send + Sync + 'static { self.map_err(|failure| failure.context(context)) } fn with_context(self, f: F) -> Result> where F: FnOnce(&E) -> D, D: Display + Send + Sync + 'static { self.map_err(|failure| { let context = f(&failure); failure.context(context) }) } } with_std! { use Error; impl ResultExt for Result { fn compat(self) -> Result> { self.map_err(|err| err.compat()) } fn context(self, context: D) -> Result> where D: Display + Send + Sync + 'static { self.map_err(|failure| failure.context(context)) } fn with_context(self, f: F) -> Result> where F: FnOnce(&Error) -> D, D: Display + Send + Sync + 'static { self.map_err(|failure| { let context = f(&failure); failure.context(context) }) } } } vendor/failure-0.1.1/src/sync_failure.rs0000644000000000000000000000510613264166600016761 0ustar rootrootuse Fail; use std::error::Error; use std::fmt::{self, Debug, Display}; use std::sync::Mutex; /// Wrapper for `std` errors to make them `Sync`. /// /// This exists to coerce existing types that are only `Error + Send + /// 'static` into a `Fail`-compatible representation, most notably for /// types generated by `error-chain`. /// /// Unfortunately, this requires wrapping the error in a `Mutex`, which must /// be locked for every `Debug`/`Display`. Therefore, this should be /// something of a last resort in making the error work with `failure`. /// pub struct SyncFailure { inner: Mutex, } impl SyncFailure { /// Wraps a non-`Sync` `Error` in order to make it implement `Fail`. /// /// # Example /// /// ```rust /// extern crate failure; /// /// # use std::error::Error as StdError; /// # use std::fmt::{self, Display}; /// use failure::{Error, SyncFailure}; /// use std::cell::RefCell; /// /// #[derive(Debug)] /// struct NonSyncError { /// // RefCells are non-Sync, so structs containing them will be /// // non-Sync as well. /// count: RefCell, /// } /// /// // implement Display/Error for NonSyncError... /// # /// # impl StdError for NonSyncError { /// # fn description(&self) -> &str { /// # "oops!" /// # } /// # } /// # /// # impl Display for NonSyncError { /// # fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { /// # write!(f, "oops!") /// # } /// # } /// /// fn returns_error() -> Result<(), NonSyncError> { /// // Do stuff /// # Ok(()) /// } /// /// fn my_function() -> Result<(), Error> { /// // without the map_err here, we end up with a compile error /// // complaining that NonSyncError doesn't implement Sync. /// returns_error().map_err(SyncFailure::new)?; /// // Do more stuff /// # Ok(()) /// } /// # /// # fn main() { /// # my_function().unwrap(); /// # } /// ``` /// pub fn new(err: E) -> Self { SyncFailure { inner: Mutex::new(err), } } } impl Display for SyncFailure where T: Display, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.inner.lock().unwrap().fmt(f) } } impl Debug for SyncFailure where T: Debug, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.inner.lock().unwrap().fmt(f) } } impl Fail for SyncFailure {} vendor/failure_derive-0.1.1/0000755000000000000000000000000013264166600014475 5ustar rootrootvendor/failure_derive-0.1.1/.cargo-checksum.json0000644000000000000000000000013113264166600020334 0ustar rootroot{"files":{},"package":"c7cdda555bb90c9bb67a3b670a0f42de8e73f5981524123ad8578aafec8ddb8b"}vendor/failure_derive-0.1.1/.travis.yml0000644000000000000000000000012513264166600016604 0ustar rootrootlanguage: rust rust: - 1.18.0 - stable - beta - nightly cache: cargo vendor/failure_derive-0.1.1/CODE_OF_CONDUCT.md0000644000000000000000000000621613264166600017301 0ustar rootroot# 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 boats@mozilla.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/ vendor/failure_derive-0.1.1/Cargo.toml0000644000000000000000000000210513264166600016423 0ustar rootroot# 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 = "failure_derive" version = "0.1.1" authors = ["Without Boats "] description = "derives for the failure crate" homepage = "https://boats.gitlab.io/failure" documentation = "https://boats.gitlab.io/failure" license = "MIT OR Apache-2.0" repository = "https://github.com/withoutboats/failure_derive" [lib] proc-macro = true [dependencies.synstructure] version = "0.6.0" [dependencies.syn] version = "0.11.11" [dependencies.quote] version = "0.3.15" [dev-dependencies.failure] version = "0.1.0" [features] default = ["std"] std = [] vendor/failure_derive-0.1.1/LICENSE-APACHE0000644000000000000000000002513713264166600016431 0ustar rootroot 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. vendor/failure_derive-0.1.1/LICENSE-MIT0000644000000000000000000000177713264166600016145 0ustar rootrootPermission 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. vendor/failure_derive-0.1.1/README.md0000644000000000000000000000101413264166600015750 0ustar rootroot# failure_derive `failure_derive` is the derive macro for the [failure][failure] crate. Documentation is located at https://boats.gitlab.io/failure ## License failure is licensed under the terms of the MIT License or the Apache License 2.0, at your choosing. ## Code of Conduct Contribution to the failure crate is organized under the terms of the Contributor Covenant, the maintainer of failure, @withoutboats, promises to intervene to uphold that code of conduct. [failure]: https://github.com/withoutboats/failure vendor/failure_derive-0.1.1/src/0000755000000000000000000000000013264166600015264 5ustar rootrootvendor/failure_derive-0.1.1/src/lib.rs0000644000000000000000000001200613264166600016377 0ustar rootrootextern crate proc_macro; extern crate syn; #[macro_use] extern crate synstructure; #[macro_use] extern crate quote; decl_derive!([Fail, attributes(fail, cause)] => fail_derive); fn fail_derive(s: synstructure::Structure) -> quote::Tokens { let cause_body = s.each_variant(|v| { if let Some(cause) = v.bindings().iter().find(is_cause) { quote!(return Some(#cause)) } else { quote!(return None) } }); let bt_body = s.each_variant(|v| { if let Some(bi) = v.bindings().iter().find(is_backtrace) { quote!(return Some(#bi)) } else { quote!(return None) } }); #[cfg(feature = "std")] let fail = s.bound_impl("::failure::Fail", quote! { #[allow(unreachable_code)] fn cause(&self) -> ::std::option::Option<&::failure::Fail> { match *self { #cause_body } None } #[allow(unreachable_code)] fn backtrace(&self) -> ::std::option::Option<&::failure::Backtrace> { match *self { #bt_body } None } }); #[cfg(not(feature = "std"))] let fail = s.bound_impl("::failure::Fail", quote! { #[allow(unreachable_code)] fn cause(&self) -> ::core::option::Option<&::failure::Fail> { match *self { #cause_body } None } #[allow(unreachable_code)] fn backtrace(&self) -> ::core::option::Option<&::failure::Backtrace> { match *self { #bt_body } None } }); #[cfg(feature = "std")] let display = display_body(&s).map(|display_body| { s.bound_impl("::std::fmt::Display", quote! { #[allow(unreachable_code)] fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { match *self { #display_body } write!(f, "An error has occurred.") } }) }); #[cfg(not(feature = "std"))] let display = display_body(&s).map(|display_body| { s.bound_impl("::core::fmt::Display", quote! { #[allow(unreachable_code)] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match *self { #display_body } write!(f, "An error has occurred.") } }) }); quote! { #fail #display } } fn display_body(s: &synstructure::Structure) -> Option { let mut msgs = s.variants().iter().map(|v| find_error_msg(&v.ast().attrs)); if msgs.all(|msg| msg.is_none()) { return None; } Some(s.each_variant(|v| { let msg = find_error_msg(&v.ast().attrs).expect("All variants must have display attribute."); if msg.is_empty() { panic!("Expected at least one argument to fail attribute"); } let s = match msg[0] { syn::NestedMetaItem::MetaItem(syn::MetaItem::NameValue(ref i, ref lit)) if i == "display" => { lit.clone() } _ => panic!("Fail attribute must begin `display = \"\"` to control the Display message."), }; let args = msg[1..].iter().map(|arg| match *arg { syn::NestedMetaItem::Literal(syn::Lit::Int(i, _)) => { let bi = &v.bindings()[i as usize]; quote!(#bi) } syn::NestedMetaItem::MetaItem(syn::MetaItem::Word(ref id)) => { if id.as_ref().starts_with("_") { if let Ok(idx) = id.as_ref()[1..].parse::() { let bi = &v.bindings()[idx]; return quote!(#bi) } } for bi in v.bindings() { if bi.ast().ident.as_ref() == Some(id) { return quote!(#bi); } } panic!("Couldn't find a field with this name!"); } _ => panic!("Invalid argument to fail attribute!"), }); quote! { return write!(f, #s #(, #args)*) } })) } fn find_error_msg(attrs: &[syn::Attribute]) -> Option<&[syn::NestedMetaItem]> { let mut error_msg = None; for attr in attrs { if attr.name() == "fail" { if error_msg.is_some() { panic!("Cannot have two display attributes") } else { if let syn::MetaItem::List(_, ref list) = attr.value { error_msg = Some(&list[..]); } else { panic!("fail attribute must take a list in parantheses") } } } } error_msg } fn is_backtrace(bi: &&synstructure::BindingInfo) -> bool { match bi.ast().ty { syn::Ty::Path(None, syn::Path { segments: ref path, .. }) => { path.last().map_or(false, |s| s.ident == "Backtrace" && s.parameters.is_empty()) } _ => false } } fn is_cause(bi: &&synstructure::BindingInfo) -> bool { bi.ast().attrs.iter().any(|attr| attr.name() == "cause") } vendor/failure_derive-0.1.1/tests/0000755000000000000000000000000013264166600015637 5ustar rootrootvendor/failure_derive-0.1.1/tests/backtrace.rs0000644000000000000000000000323313264166600020125 0ustar rootrootextern crate failure; #[macro_use] extern crate failure_derive; use failure::{Fail, Backtrace}; #[derive(Fail, Debug)] #[fail(display = "Error code: {}", code)] struct BacktraceError { backtrace: Backtrace, code: u32, } #[test] fn backtrace_error() { let err = BacktraceError { backtrace: Backtrace::new(), code: 7 }; let s = format!("{}", err); assert_eq!(&s[..], "Error code: 7"); assert!(err.backtrace().is_some()); } #[derive(Fail, Debug)] #[fail(display = "An error has occurred.")] struct BacktraceTupleError(Backtrace); #[test] fn backtrace_tuple_error() { let err = BacktraceTupleError(Backtrace::new()); let s = format!("{}", err); assert_eq!(&s[..], "An error has occurred."); assert!(err.backtrace().is_some()); } #[derive(Fail, Debug)] enum BacktraceEnumError { #[fail(display = "Error code: {}", code)] StructVariant { code: i32, backtrace: Backtrace, }, #[fail(display = "Error: {}", _0)] TupleVariant(&'static str, Backtrace), #[fail(display = "An error has occurred.")] UnitVariant, } #[test] fn backtrace_enum_error() { let err = BacktraceEnumError::StructVariant { code: 2, backtrace: Backtrace::new() }; let s = format!("{}", err); assert_eq!(&s[..], "Error code: 2"); assert!(err.backtrace().is_some()); let err = BacktraceEnumError::TupleVariant("foobar", Backtrace::new()); let s = format!("{}", err); assert_eq!(&s[..], "Error: foobar"); assert!(err.backtrace().is_some()); let err = BacktraceEnumError::UnitVariant; let s = format!("{}", err); assert_eq!(&s[..], "An error has occurred."); assert!(err.backtrace().is_none()); } vendor/failure_derive-0.1.1/tests/no_derive_display.rs0000644000000000000000000000064513264166600021711 0ustar rootrootextern crate failure; #[macro_use] extern crate failure_derive; use std::fmt::{self, Display}; use failure::Fail; #[derive(Debug, Fail)] struct Foo; impl Display for Foo { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("An error occurred.") } } #[test] fn handwritten_display() { assert!(Foo.cause().is_none()); assert_eq!(&format!("{}", Foo)[..], "An error occurred."); } vendor/failure_derive-0.1.1/tests/tests.rs0000644000000000000000000000243513264166600017353 0ustar rootrootextern crate failure; #[macro_use] extern crate failure_derive; #[derive(Fail, Debug)] #[fail(display = "An error has occurred.")] struct UnitError; #[test] fn unit_struct() { let s = format!("{}", UnitError); assert_eq!(&s[..], "An error has occurred."); } #[derive(Fail, Debug)] #[fail(display = "Error code: {}", code)] struct RecordError { code: u32, } #[test] fn record_struct() { let s = format!("{}", RecordError { code: 0 }); assert_eq!(&s[..], "Error code: 0"); } #[derive(Fail, Debug)] #[fail(display = "Error code: {}", _0)] struct TupleError(i32); #[test] fn tuple_struct() { let s = format!("{}", TupleError(2)); assert_eq!(&s[..], "Error code: 2"); } #[derive(Fail, Debug)] enum EnumError { #[fail(display = "Error code: {}", code)] StructVariant { code: i32, }, #[fail(display = "Error: {}", _0)] TupleVariant(&'static str), #[fail(display = "An error has occurred.")] UnitVariant, } #[test] fn enum_error() { let s = format!("{}", EnumError::StructVariant { code: 2 }); assert_eq!(&s[..], "Error code: 2"); let s = format!("{}", EnumError::TupleVariant("foobar")); assert_eq!(&s[..], "Error: foobar"); let s = format!("{}", EnumError::UnitVariant); assert_eq!(&s[..], "An error has occurred."); } vendor/failure_derive-0.1.1/tests/wraps.rs0000644000000000000000000000403513264166600017343 0ustar rootrootextern crate failure; #[macro_use] extern crate failure_derive; use std::io; use std::fmt; use failure::{Backtrace, Fail}; #[derive(Fail, Debug)] #[fail(display = "An error has occurred: {}", inner)] struct WrapError { #[cause] inner: io::Error, } #[test] fn wrap_error() { let inner = io::Error::from_raw_os_error(98); let err = WrapError { inner }; assert!(err.cause().and_then(|err| err.downcast_ref::()).is_some()); } #[derive(Fail, Debug)] #[fail(display = "An error has occurred: {}", _0)] struct WrapTupleError(#[cause] io::Error); #[test] fn wrap_tuple_error() { let io_error = io::Error::from_raw_os_error(98); let err: WrapTupleError = WrapTupleError(io_error); assert!(err.cause().and_then(|err| err.downcast_ref::()).is_some()); } #[derive(Fail, Debug)] #[fail(display = "An error has occurred: {}", inner)] struct WrapBacktraceError { #[cause] inner: io::Error, backtrace: Backtrace, } #[test] fn wrap_backtrace_error() { let inner = io::Error::from_raw_os_error(98); let err: WrapBacktraceError = WrapBacktraceError { inner, backtrace: Backtrace::new() }; assert!(err.cause().and_then(|err| err.downcast_ref::()).is_some()); assert!(err.backtrace().is_some()); } #[derive(Fail, Debug)] enum WrapEnumError { #[fail(display = "An error has occurred: {}", _0)] Io(#[cause] io::Error), #[fail(display = "An error has occurred: {}", inner)] Fmt { #[cause] inner: fmt::Error, backtrace: Backtrace, }, } #[test] fn wrap_enum_error() { let io_error = io::Error::from_raw_os_error(98); let err: WrapEnumError = WrapEnumError::Io(io_error); assert!(err.cause().and_then(|err| err.downcast_ref::()).is_some()); assert!(err.backtrace().is_none()); let fmt_error = fmt::Error::default(); let err: WrapEnumError = WrapEnumError::Fmt { inner: fmt_error, backtrace: Backtrace::new() }; assert!(err.cause().and_then(|err| err.downcast_ref::()).is_some()); assert!(err.backtrace().is_some()); } vendor/filetime-0.1.15/0000755000000000000000000000000013264166600013373 5ustar rootrootvendor/filetime-0.1.15/.cargo-checksum.json0000644000000000000000000000013113264166600017232 0ustar rootroot{"files":{},"package":"714653f3e34871534de23771ac7b26e999651a0a228f47beb324dfdf1dd4b10f"}vendor/filetime-0.1.15/.travis.yml0000664000000000000000000000123313264166600015505 0ustar rootrootlanguage: rust sudo: false matrix: include: - rust: 1.21.0 - rust: stable - os: osx - rust: beta - rust: nightly - rust: nightly before_script: - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH script: - cargo doc --no-deps --all-features after_success: - travis-cargo --only nightly doc-upload script: - cargo test env: global: secure: "MIaQyJIgy7VUoYHY7KbYtxpN/t+a2eWk8PihYctz+F+1PANgD6KbgbF9JW4ip5MYaehk7UWs++kPkHiAvJFKWo2BnQswc4digTUa9Vc2n8/C0d0Ec2zn1EUXH4fkeaMvIffn8QQUPwuNdE6khifSfG8Y42siqJF4zkuPKwaLrUo=" notifications: email: on_success: never vendor/filetime-0.1.15/Cargo.toml0000644000000000000000000000221013264166600015316 0ustar rootroot# 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 = "filetime" version = "0.1.15" authors = ["Alex Crichton "] description = "Platform-agnostic accessors of timestamps in File metadata\n" homepage = "https://github.com/alexcrichton/filetime" documentation = "http://alexcrichton.com/filetime" readme = "README.md" keywords = ["timestamp", "mtime"] license = "MIT/Apache-2.0" repository = "https://github.com/alexcrichton/filetime" [dependencies.cfg-if] version = "0.1" [dev-dependencies.tempdir] version = "0.3" [target."cfg(target_os = \"redox\")".dependencies.redox_syscall] version = "0.1" [target."cfg(unix)".dependencies.libc] version = "0.2" vendor/filetime-0.1.15/LICENSE-APACHE0000664000000000000000000002513713264166600015331 0ustar rootroot 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. vendor/filetime-0.1.15/LICENSE-MIT0000664000000000000000000000204113264166600015026 0ustar rootrootCopyright (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. vendor/filetime-0.1.15/README.md0000664000000000000000000000225513264166600014660 0ustar rootroot# filetime [![Build Status](https://travis-ci.org/alexcrichton/filetime.svg?branch=master)](https://travis-ci.org/alexcrichton/filetime) [![Build status](https://ci.appveyor.com/api/projects/status/9tatexq47i3ee13k?svg=true)](https://ci.appveyor.com/project/alexcrichton/filetime) [Documentation](http://alexcrichton.com/filetime/filetime/index.html) A helper library for inspecting the various timestamps of files in Rust. This library takes into account cross-platform differences in terms of where the timestamps are located, what they are called, and how to convert them into a platform-independent representation. ```toml # Cargo.toml [dependencies] filetime = "0.1" ``` # License This project is licensed under either of * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in Serde by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. vendor/filetime-0.1.15/appveyor.yml0000664000000000000000000000076013264166600015770 0ustar rootrootenvironment: matrix: - TARGET: x86_64-pc-windows-msvc - TARGET: i686-pc-windows-msvc - TARGET: i686-pc-windows-gnu 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 - SET PATH=%PATH%;C:\MinGW\bin - rustc -V - cargo -V build: false test_script: - cargo test --verbose --target %TARGET% vendor/filetime-0.1.15/src/0000755000000000000000000000000013264166600014162 5ustar rootrootvendor/filetime-0.1.15/src/lib.rs0000664000000000000000000002332313264166600015303 0ustar rootroot//! Timestamps for files in Rust //! //! This library provides platform-agnostic inspection of the various timestamps //! present in the standard `fs::Metadata` structure. //! //! # Installation //! //! Add this to your `Cargo.toml`: //! //! ```toml //! [dependencies] //! filetime = "0.1" //! ``` //! //! # Usage //! //! ```no_run //! use std::fs; //! use filetime::FileTime; //! //! let metadata = fs::metadata("foo.txt").unwrap(); //! //! let mtime = FileTime::from_last_modification_time(&metadata); //! println!("{}", mtime); //! //! let atime = FileTime::from_last_access_time(&metadata); //! assert!(mtime < atime); //! //! // Inspect values that can be interpreted across platforms //! println!("{}", mtime.seconds_relative_to_1970()); //! println!("{}", mtime.nanoseconds()); //! //! // Print the platform-specific value of seconds //! println!("{}", mtime.seconds()); //! ``` #[macro_use] extern crate cfg_if; use std::fmt; use std::fs; use std::io; use std::path::Path; cfg_if! { if #[cfg(target_os = "redox")] { #[path = "redox.rs"] mod imp; } else if #[cfg(windows)] { #[path = "windows.rs"] mod imp; } else { #[path = "unix/mod.rs"] mod imp; } } /// A helper structure to represent a timestamp for a file. /// /// The actual value contined within is platform-specific and does not have the /// same meaning across platforms, but comparisons and stringification can be /// significant among the same platform. #[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Copy, Clone, Hash)] pub struct FileTime { seconds: u64, nanos: u32, } impl FileTime { /// Creates a new timestamp representing a 0 time. /// /// Useful for creating the base of a cmp::max chain of times. pub fn zero() -> FileTime { FileTime { seconds: 0, nanos: 0 } } /// Creates a new instance of `FileTime` with a number of seconds and /// nanoseconds relative to January 1, 1970. /// /// Note that this is typically the relative point that Unix time stamps are /// from, but on Windows the native time stamp is relative to January 1, /// 1601 so the return value of `seconds` from the returned `FileTime` /// instance may not be the same as that passed in. pub fn from_seconds_since_1970(seconds: u64, nanos: u32) -> FileTime { FileTime { seconds: seconds + if cfg!(windows) {11644473600} else {0}, nanos: nanos, } } /// Creates a new timestamp from the last modification time listed in the /// specified metadata. /// /// The returned value corresponds to the `mtime` field of `stat` on Unix /// platforms and the `ftLastWriteTime` field on Windows platforms. pub fn from_last_modification_time(meta: &fs::Metadata) -> FileTime { imp::from_last_modification_time(meta) } /// Creates a new timestamp from the last access time listed in the /// specified metadata. /// /// The returned value corresponds to the `atime` field of `stat` on Unix /// platforms and the `ftLastAccessTime` field on Windows platforms. pub fn from_last_access_time(meta: &fs::Metadata) -> FileTime { imp::from_last_access_time(meta) } /// Creates a new timestamp from the creation time listed in the specified /// metadata. /// /// The returned value corresponds to the `birthtime` field of `stat` on /// Unix platforms and the `ftCreationTime` field on Windows platforms. Note /// that not all Unix platforms have this field available and may return /// `None` in some circumstances. pub fn from_creation_time(meta: &fs::Metadata) -> Option { imp::from_creation_time(meta) } /// Returns the whole number of seconds represented by this timestamp. /// /// Note that this value's meaning is **platform specific**. On Unix /// platform time stamps are typically relative to January 1, 1970, but on /// Windows platforms time stamps are relative to January 1, 1601. pub fn seconds(&self) -> u64 { self.seconds } /// Returns the whole number of seconds represented by this timestamp, /// relative to the Unix epoch start of January 1, 1970. /// /// Note that this does not return the same value as `seconds` for Windows /// platforms as seconds are relative to a different date there. pub fn seconds_relative_to_1970(&self) -> u64 { self.seconds - if cfg!(windows) {11644473600} else {0} } /// Returns the nanosecond precision of this timestamp. /// /// The returned value is always less than one billion and represents a /// portion of a second forward from the seconds returned by the `seconds` /// method. pub fn nanoseconds(&self) -> u32 { self.nanos } } impl fmt::Display for FileTime { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}.{:09}s", self.seconds, self.nanos) } } /// Set the last access and modification times for a file on the filesystem. /// /// This function will set the `atime` and `mtime` metadata fields for a file /// on the local filesystem, returning any error encountered. pub fn set_file_times

(p: P, atime: FileTime, mtime: FileTime) -> io::Result<()> where P: AsRef { imp::set_file_times(p.as_ref(), atime, mtime) } /// Set the last access and modification times for a file on the filesystem. /// This function does not follow symlink. /// /// This function will set the `atime` and `mtime` metadata fields for a file /// on the local filesystem, returning any error encountered. pub fn set_symlink_file_times

(p: P, atime: FileTime, mtime: FileTime) -> io::Result<()> where P: AsRef { imp::set_symlink_file_times(p.as_ref(), atime, mtime) } #[cfg(test)] mod tests { extern crate tempdir; use std::io; use std::path::Path; use std::fs::{self, File}; use self::tempdir::TempDir; use super::{FileTime, set_file_times, set_symlink_file_times}; #[cfg(unix)] fn make_symlink(src: P, dst: Q) -> io::Result<()> where P: AsRef, Q: AsRef, { use std::os::unix::fs::symlink; symlink(src, dst) } #[cfg(windows)] fn make_symlink(src: P, dst: Q) -> io::Result<()> where P: AsRef, Q: AsRef, { use std::os::windows::fs::symlink_file; symlink_file(src, dst) } #[test] fn set_file_times_test() { let td = TempDir::new("filetime").unwrap(); let path = td.path().join("foo.txt"); File::create(&path).unwrap(); let metadata = fs::metadata(&path).unwrap(); let mtime = FileTime::from_last_modification_time(&metadata); let atime = FileTime::from_last_access_time(&metadata); set_file_times(&path, atime, mtime).unwrap(); let new_mtime = FileTime::from_seconds_since_1970(10_000, 0); set_file_times(&path, atime, new_mtime).unwrap(); let metadata = fs::metadata(&path).unwrap(); let mtime = FileTime::from_last_modification_time(&metadata); assert_eq!(mtime, new_mtime); let spath = td.path().join("bar.txt"); make_symlink(&path, &spath).unwrap(); let metadata = fs::symlink_metadata(&spath).unwrap(); let smtime = FileTime::from_last_modification_time(&metadata); set_file_times(&spath, atime, mtime).unwrap(); let metadata = fs::metadata(&path).unwrap(); let cur_mtime = FileTime::from_last_modification_time(&metadata); assert_eq!(mtime, cur_mtime); let metadata = fs::symlink_metadata(&spath).unwrap(); let cur_mtime = FileTime::from_last_modification_time(&metadata); assert_eq!(smtime, cur_mtime); set_file_times(&spath, atime, new_mtime).unwrap(); let metadata = fs::metadata(&path).unwrap(); let mtime = FileTime::from_last_modification_time(&metadata); assert_eq!(mtime, new_mtime); let metadata = fs::symlink_metadata(&spath).unwrap(); let mtime = FileTime::from_last_modification_time(&metadata); assert_eq!(mtime, smtime); } #[test] fn set_symlink_file_times_test() { let td = TempDir::new("filetime").unwrap(); let path = td.path().join("foo.txt"); File::create(&path).unwrap(); let metadata = fs::metadata(&path).unwrap(); let mtime = FileTime::from_last_modification_time(&metadata); let atime = FileTime::from_last_access_time(&metadata); set_symlink_file_times(&path, atime, mtime).unwrap(); let new_mtime = FileTime::from_seconds_since_1970(10_000, 0); set_symlink_file_times(&path, atime, new_mtime).unwrap(); let metadata = fs::metadata(&path).unwrap(); let mtime = FileTime::from_last_modification_time(&metadata); assert_eq!(mtime, new_mtime); let spath = td.path().join("bar.txt"); make_symlink(&path, &spath).unwrap(); let metadata = fs::symlink_metadata(&spath).unwrap(); let smtime = FileTime::from_last_modification_time(&metadata); let satime = FileTime::from_last_access_time(&metadata); set_symlink_file_times(&spath, smtime, satime).unwrap(); let metadata = fs::metadata(&path).unwrap(); let mtime = FileTime::from_last_modification_time(&metadata); assert_eq!(mtime, new_mtime); let new_smtime = FileTime::from_seconds_since_1970(20_000, 0); set_symlink_file_times(&spath, atime, new_smtime).unwrap(); let metadata = fs::metadata(&spath).unwrap(); let mtime = FileTime::from_last_modification_time(&metadata); assert_eq!(mtime, new_mtime); let metadata = fs::symlink_metadata(&spath).unwrap(); let mtime = FileTime::from_last_modification_time(&metadata); assert_eq!(mtime, new_smtime); } } vendor/filetime-0.1.15/src/redox.rs0000664000000000000000000000312113264166600015650 0ustar rootrootextern crate syscall; use std::fs; use std::io; use std::os::unix::prelude::*; use std::path::Path; use FileTime; pub fn set_file_times(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> { let fd = syscall::open(p.as_os_str().as_bytes(), 0) .map_err(|err| io::Error::from_raw_os_error(err.errno))?; set_file_times_redox(fd, atime, mtime) } pub fn set_symlink_file_times(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> { let fd = syscall::open(p.as_os_str().as_bytes(), syscall::O_NOFOLLOW) .map_err(|err| io::Error::from_raw_os_error(err.errno))?; set_file_times_redox(fd, atime, mtime) } fn set_file_times_redox(fd: usize, atime: FileTime, mtime: FileTime) -> io::Result<()> { use self::syscall::TimeSpec; fn to_timespec(ft: &FileTime) -> TimeSpec { TimeSpec { tv_sec: ft.seconds() as i64, tv_nsec: ft.nanoseconds() as i32 } } let times = [to_timespec(&atime), to_timespec(&mtime)]; let res = syscall::futimens(fd, ×); let _ = syscall::close(fd); match res { Ok(_) => Ok(()), Err(err) => Err(io::Error::from_raw_os_error(err.errno)) } } pub fn from_last_modification_time(meta: &fs::Metadata) -> FileTime { FileTime { seconds: meta.mtime() as u64, nanos: meta.mtime_nsec() as u32, } } pub fn from_last_access_time(meta: &fs::Metadata) -> FileTime { FileTime { seconds: meta.atime() as u64, nanos: meta.atime_nsec() as u32, } } pub fn from_creation_time(_meta: &fs::Metadata) -> Option { None } vendor/filetime-0.1.15/src/unix/0000755000000000000000000000000013264166600015145 5ustar rootrootvendor/filetime-0.1.15/src/unix/linux.rs0000664000000000000000000000427313264166600016662 0ustar rootroot//! On Linux we try to use the more accurate `utimensat` syscall but this isn't //! always available so we also fall back to `utimes` if we couldn't find //! `utimensat` at runtime. use std::io; use std::mem; use std::path::Path; use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT}; use FileTime; use super::libc::{self, c_int, c_char, timespec}; pub fn set_file_times(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> { set_times(p, atime, mtime, false) } pub fn set_symlink_file_times(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> { set_times(p, atime, mtime, true) } fn set_times(p: &Path, atime: FileTime, mtime: FileTime, symlink: bool) -> io::Result<()> { let flags = if symlink { libc::AT_SYMLINK_NOFOLLOW } else { 0 }; let utimes = if symlink { libc::lutimes } else { libc::utimes }; // Try to use the more-accurate `utimensat` when possible. static INVALID: AtomicBool = ATOMIC_BOOL_INIT; if !INVALID.load(Ordering::SeqCst) { if let Some(f) = utimensat() { // Even when libc has `utimensat`, the kernel may return `ENOSYS`, // and then we'll need to use the `utimes` fallback instead. match super::utimensat(p, atime, mtime, f, flags) { Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => { INVALID.store(true, Ordering::SeqCst); } valid => return valid, } } } super::utimes(p, atime, mtime, utimes) } fn utimensat() -> Option c_int> { static ADDR: AtomicUsize = ATOMIC_USIZE_INIT; unsafe { match ADDR.load(Ordering::SeqCst) { 0 => {} 1 => return None, n => return Some(mem::transmute(n)), } let name = b"utimensat\0"; let sym = libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr() as *const _); let (val, ret) = if sym.is_null() { (1, None) } else { (sym as usize, Some(mem::transmute(sym))) }; ADDR.store(val, Ordering::SeqCst); return ret } } vendor/filetime-0.1.15/src/unix/mod.rs0000664000000000000000000000634213264166600016301 0ustar rootrootextern crate libc; use std::ffi::CString; use std::fs; use std::io; use std::os::unix::prelude::*; use std::path::Path; use self::libc::{c_int, c_char, timeval, time_t, suseconds_t, c_long}; use self::libc::{timespec}; use FileTime; cfg_if! { if #[cfg(target_os = "linux")] { mod linux; pub use self::linux::*; } else if #[cfg(any(target_os = "android", target_os = "solaris", target_os = "netbsd", target_os = "openbsd"))] { mod utimensat; pub use self::utimensat::*; } else { mod utimes; pub use self::utimes::*; } } #[allow(dead_code)] fn utimes(p: &Path, atime: FileTime, mtime: FileTime, utimes: unsafe extern fn(*const c_char, *const timeval) -> c_int) -> io::Result<()> { let times = [to_timeval(&atime), to_timeval(&mtime)]; let p = try!(CString::new(p.as_os_str().as_bytes())); return if unsafe { utimes(p.as_ptr() as *const _, times.as_ptr()) == 0 } { Ok(()) } else { Err(io::Error::last_os_error()) }; fn to_timeval(ft: &FileTime) -> timeval { timeval { tv_sec: ft.seconds() as time_t, tv_usec: (ft.nanoseconds() / 1000) as suseconds_t, } } } #[allow(dead_code)] fn utimensat(p: &Path, atime: FileTime, mtime: FileTime, f: unsafe extern fn(c_int, *const c_char, *const timespec, c_int) -> c_int, flags: c_int) -> io::Result<()> { let times = [to_timespec(&atime), to_timespec(&mtime)]; let p = try!(CString::new(p.as_os_str().as_bytes())); let rc = unsafe { f(libc::AT_FDCWD, p.as_ptr() as *const _, times.as_ptr(), flags) }; return if rc == 0 { Ok(()) } else { Err(io::Error::last_os_error()) }; fn to_timespec(ft: &FileTime) -> timespec { timespec { tv_sec: ft.seconds() as time_t, tv_nsec: ft.nanoseconds() as c_long, } } } pub fn from_last_modification_time(meta: &fs::Metadata) -> FileTime { FileTime { seconds: meta.mtime() as u64, nanos: meta.mtime_nsec() as u32, } } pub fn from_last_access_time(meta: &fs::Metadata) -> FileTime { FileTime { seconds: meta.atime() as u64, nanos: meta.atime_nsec() as u32, } } pub fn from_creation_time(meta: &fs::Metadata) -> Option { macro_rules! birthtim { ($(($e:expr, $i:ident)),*) => { #[cfg(any($(target_os = $e),*))] fn imp(meta: &fs::Metadata) -> Option { $( #[cfg(target_os = $e)] use std::os::$i::fs::MetadataExt; )* Some(FileTime { seconds: meta.st_birthtime() as u64, nanos: meta.st_birthtime_nsec() as u32, }) } #[cfg(all($(not(target_os = $e)),*))] fn imp(_meta: &fs::Metadata) -> Option { None } } } birthtim! { ("bitrig", bitrig), ("freebsd", freebsd), ("ios", ios), ("macos", macos), ("openbsd", openbsd) } imp(meta) } vendor/filetime-0.1.15/src/unix/utimensat.rs0000664000000000000000000000061013264166600017523 0ustar rootrootuse std::path::Path; use std::io; use FileTime; use super::libc; pub fn set_file_times(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> { super::utimensat(p, atime, mtime, libc::utimensat, 0) } pub fn set_symlink_file_times(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> { super::utimensat(p, atime, mtime, libc::utimensat, libc::AT_SYMLINK_NOFOLLOW) } vendor/filetime-0.1.15/src/unix/utimes.rs0000664000000000000000000000053713264166600017030 0ustar rootrootuse std::path::Path; use std::io; use FileTime; use super::libc; pub fn set_file_times(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> { super::utimes(p, atime, mtime, libc::utimes) } pub fn set_symlink_file_times(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> { super::utimes(p, atime, mtime, libc::lutimes) } vendor/filetime-0.1.15/src/windows.rs0000664000000000000000000000505513264166600016231 0ustar rootroot#![allow(bad_style)] use std::fs::{self, OpenOptions}; use std::io; use std::os::windows::prelude::*; use std::path::Path; use FileTime; pub fn set_file_times(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> { set_file_times_w(p, atime, mtime, OpenOptions::new()) } pub fn set_symlink_file_times(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> { use std::os::windows::fs::OpenOptionsExt; const FILE_FLAG_OPEN_REPARSE_POINT: u32 = 0x00200000; let mut options = OpenOptions::new(); options.custom_flags(FILE_FLAG_OPEN_REPARSE_POINT); set_file_times_w(p, atime, mtime, options) } pub fn set_file_times_w(p: &Path, atime: FileTime, mtime: FileTime, mut options: OpenOptions) -> io::Result<()> { type BOOL = i32; type HANDLE = *mut u8; type DWORD = u32; #[repr(C)] struct FILETIME { dwLowDateTime: u32, dwHighDateTime: u32, } extern "system" { fn SetFileTime(hFile: HANDLE, lpCreationTime: *const FILETIME, lpLastAccessTime: *const FILETIME, lpLastWriteTime: *const FILETIME) -> BOOL; } let f = try!(options.write(true).open(p)); let atime = to_filetime(&atime); let mtime = to_filetime(&mtime); return unsafe { let ret = SetFileTime(f.as_raw_handle() as *mut _, 0 as *const _, &atime, &mtime); if ret != 0 { Ok(()) } else { Err(io::Error::last_os_error()) } }; fn to_filetime(ft: &FileTime) -> FILETIME { let intervals = ft.seconds() * (1_000_000_000 / 100) + ((ft.nanoseconds() as u64) / 100); FILETIME { dwLowDateTime: intervals as DWORD, dwHighDateTime: (intervals >> 32) as DWORD, } } } pub fn from_last_modification_time(meta: &fs::Metadata) -> FileTime { from_intervals(meta.last_write_time()) } pub fn from_last_access_time(meta: &fs::Metadata) -> FileTime { from_intervals(meta.last_access_time()) } pub fn from_creation_time(meta: &fs::Metadata) -> Option { Some(from_intervals(meta.creation_time())) } fn from_intervals(ticks: u64) -> FileTime { // Windows write times are in 100ns intervals, so do a little math to // get it into the right representation. FileTime { seconds: ticks / (1_000_000_000 / 100), nanos: ((ticks % (1_000_000_000 / 100)) * 100) as u32, } } vendor/filetime-0.2.0/0000755000000000000000000000000013264166600013306 5ustar rootrootvendor/filetime-0.2.0/.cargo-checksum.json0000644000000000000000000000013113264166600017145 0ustar rootroot{"files":{},"package":"08530a39af0bd442c40aabb9e854f442a83bd2403feb1ed58fbe982dec2385f3"}vendor/filetime-0.2.0/.travis.yml0000644000000000000000000000123313264166600015416 0ustar rootrootlanguage: rust sudo: false matrix: include: - rust: 1.21.0 - rust: stable - os: osx - rust: beta - rust: nightly - rust: nightly before_script: - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH script: - cargo doc --no-deps --all-features after_success: - travis-cargo --only nightly doc-upload script: - cargo test env: global: secure: "MIaQyJIgy7VUoYHY7KbYtxpN/t+a2eWk8PihYctz+F+1PANgD6KbgbF9JW4ip5MYaehk7UWs++kPkHiAvJFKWo2BnQswc4digTUa9Vc2n8/C0d0Ec2zn1EUXH4fkeaMvIffn8QQUPwuNdE6khifSfG8Y42siqJF4zkuPKwaLrUo=" notifications: email: on_success: never vendor/filetime-0.2.0/Cargo.toml0000644000000000000000000000220713264166600015237 0ustar rootroot# 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 = "filetime" version = "0.2.0" authors = ["Alex Crichton "] description = "Platform-agnostic accessors of timestamps in File metadata\n" homepage = "https://github.com/alexcrichton/filetime" documentation = "http://alexcrichton.com/filetime" readme = "README.md" keywords = ["timestamp", "mtime"] license = "MIT/Apache-2.0" repository = "https://github.com/alexcrichton/filetime" [dependencies.cfg-if] version = "0.1" [dev-dependencies.tempdir] version = "0.3" [target."cfg(target_os = \"redox\")".dependencies.redox_syscall] version = "0.1" [target."cfg(unix)".dependencies.libc] version = "0.2" vendor/filetime-0.2.0/LICENSE-APACHE0000644000000000000000000002513713264166600015242 0ustar rootroot 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. vendor/filetime-0.2.0/LICENSE-MIT0000644000000000000000000000204113264166600014737 0ustar rootrootCopyright (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. vendor/filetime-0.2.0/README.md0000644000000000000000000000225513264166600014571 0ustar rootroot# filetime [![Build Status](https://travis-ci.org/alexcrichton/filetime.svg?branch=master)](https://travis-ci.org/alexcrichton/filetime) [![Build status](https://ci.appveyor.com/api/projects/status/9tatexq47i3ee13k?svg=true)](https://ci.appveyor.com/project/alexcrichton/filetime) [Documentation](http://alexcrichton.com/filetime/filetime/index.html) A helper library for inspecting the various timestamps of files in Rust. This library takes into account cross-platform differences in terms of where the timestamps are located, what they are called, and how to convert them into a platform-independent representation. ```toml # Cargo.toml [dependencies] filetime = "0.2" ``` # License This project is licensed under either of * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in Serde by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. vendor/filetime-0.2.0/appveyor.yml0000644000000000000000000000076013264166600015701 0ustar rootrootenvironment: matrix: - TARGET: x86_64-pc-windows-msvc - TARGET: i686-pc-windows-msvc - TARGET: i686-pc-windows-gnu 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 - SET PATH=%PATH%;C:\MinGW\bin - rustc -V - cargo -V build: false test_script: - cargo test --verbose --target %TARGET% vendor/filetime-0.2.0/src/0000755000000000000000000000000013264166600014075 5ustar rootrootvendor/filetime-0.2.0/src/lib.rs0000644000000000000000000003541113264166600015215 0ustar rootroot//! Timestamps for files in Rust //! //! This library provides platform-agnostic inspection of the various timestamps //! present in the standard `fs::Metadata` structure. //! //! # Installation //! //! Add this to your `Cargo.toml`: //! //! ```toml //! [dependencies] //! filetime = "0.1" //! ``` //! //! # Usage //! //! ```no_run //! use std::fs; //! use filetime::FileTime; //! //! let metadata = fs::metadata("foo.txt").unwrap(); //! //! let mtime = FileTime::from_last_modification_time(&metadata); //! println!("{}", mtime); //! //! let atime = FileTime::from_last_access_time(&metadata); //! assert!(mtime < atime); //! //! // Inspect values that can be interpreted across platforms //! println!("{}", mtime.unix_seconds()); //! println!("{}", mtime.nanoseconds()); //! //! // Print the platform-specific value of seconds //! println!("{}", mtime.seconds()); //! ``` #[macro_use] extern crate cfg_if; use std::fmt; use std::fs; use std::io; use std::path::Path; use std::time::{Duration, SystemTime, UNIX_EPOCH}; cfg_if! { if #[cfg(target_os = "redox")] { #[path = "redox.rs"] mod imp; } else if #[cfg(windows)] { #[path = "windows.rs"] mod imp; } else { #[path = "unix/mod.rs"] mod imp; } } /// A helper structure to represent a timestamp for a file. /// /// The actual value contined within is platform-specific and does not have the /// same meaning across platforms, but comparisons and stringification can be /// significant among the same platform. #[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Copy, Clone, Hash)] pub struct FileTime { seconds: i64, nanos: u32, } impl FileTime { /// Creates a new timestamp representing a 0 time. /// /// Useful for creating the base of a cmp::max chain of times. pub fn zero() -> FileTime { FileTime { seconds: 0, nanos: 0 } } /// Creates a new instance of `FileTime` with a number of seconds and /// nanoseconds relative to the Unix epoch, 1970-01-01T00:00:00Z. /// /// Negative seconds represent times before the Unix epoch, and positive /// values represent times after it. Nanos always count forwards in time. /// /// Note that this is typically the relative point that Unix time stamps are /// from, but on Windows the native time stamp is relative to January 1, /// 1601 so the return value of `seconds` from the returned `FileTime` /// instance may not be the same as that passed in. pub fn from_unix_time(seconds: i64, nanos: u32) -> FileTime { FileTime { seconds: seconds + if cfg!(windows) {11644473600} else {0}, nanos, } } /// Creates a new timestamp from the last modification time listed in the /// specified metadata. /// /// The returned value corresponds to the `mtime` field of `stat` on Unix /// platforms and the `ftLastWriteTime` field on Windows platforms. pub fn from_last_modification_time(meta: &fs::Metadata) -> FileTime { imp::from_last_modification_time(meta) } /// Creates a new timestamp from the last access time listed in the /// specified metadata. /// /// The returned value corresponds to the `atime` field of `stat` on Unix /// platforms and the `ftLastAccessTime` field on Windows platforms. pub fn from_last_access_time(meta: &fs::Metadata) -> FileTime { imp::from_last_access_time(meta) } /// Creates a new timestamp from the creation time listed in the specified /// metadata. /// /// The returned value corresponds to the `birthtime` field of `stat` on /// Unix platforms and the `ftCreationTime` field on Windows platforms. Note /// that not all Unix platforms have this field available and may return /// `None` in some circumstances. pub fn from_creation_time(meta: &fs::Metadata) -> Option { imp::from_creation_time(meta) } /// Creates a new timestamp from the given SystemTime. /// /// Windows counts file times since 1601-01-01T00:00:00Z, and cannot /// represent times before this, but it's possible to create a SystemTime /// that does. This function will error if passed such a SystemTime. pub fn from_system_time(time: SystemTime) -> FileTime { let epoch = if cfg!(windows) { UNIX_EPOCH - Duration::from_secs(11644473600) } else { UNIX_EPOCH }; time.duration_since(epoch).map(|d| FileTime { seconds: d.as_secs() as i64, nanos: d.subsec_nanos() }) .unwrap_or_else(|e| { let until_epoch = e.duration(); let (sec_offset, nanos) = if until_epoch.subsec_nanos() == 0 { (0, 0) } else { (-1, 1_000_000_000 - until_epoch.subsec_nanos()) }; FileTime { seconds: -1 * until_epoch.as_secs() as i64 + sec_offset, nanos } }) } /// Returns the whole number of seconds represented by this timestamp. /// /// Note that this value's meaning is **platform specific**. On Unix /// platform time stamps are typically relative to January 1, 1970, but on /// Windows platforms time stamps are relative to January 1, 1601. pub fn seconds(&self) -> i64 { self.seconds } /// Returns the whole number of seconds represented by this timestamp, /// relative to the Unix epoch start of January 1, 1970. /// /// Note that this does not return the same value as `seconds` for Windows /// platforms as seconds are relative to a different date there. pub fn unix_seconds(&self) -> i64 { self.seconds - if cfg!(windows) {11644473600} else {0} } /// Returns the nanosecond precision of this timestamp. /// /// The returned value is always less than one billion and represents a /// portion of a second forward from the seconds returned by the `seconds` /// method. pub fn nanoseconds(&self) -> u32 { self.nanos } } impl fmt::Display for FileTime { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}.{:09}s", self.seconds, self.nanos) } } /// Set the last access and modification times for a file on the filesystem. /// /// This function will set the `atime` and `mtime` metadata fields for a file /// on the local filesystem, returning any error encountered. pub fn set_file_times

(p: P, atime: FileTime, mtime: FileTime) -> io::Result<()> where P: AsRef { imp::set_file_times(p.as_ref(), atime, mtime) } /// Set the last access and modification times for a file on the filesystem. /// This function does not follow symlink. /// /// This function will set the `atime` and `mtime` metadata fields for a file /// on the local filesystem, returning any error encountered. pub fn set_symlink_file_times

(p: P, atime: FileTime, mtime: FileTime) -> io::Result<()> where P: AsRef { imp::set_symlink_file_times(p.as_ref(), atime, mtime) } #[cfg(test)] mod tests { extern crate tempdir; use std::io; use std::path::Path; use std::fs::{self, File}; use self::tempdir::TempDir; use super::{FileTime, set_file_times, set_symlink_file_times}; use std::time::{Duration, UNIX_EPOCH}; #[cfg(unix)] fn make_symlink(src: P, dst: Q) -> io::Result<()> where P: AsRef, Q: AsRef, { use std::os::unix::fs::symlink; symlink(src, dst) } #[cfg(windows)] fn make_symlink(src: P, dst: Q) -> io::Result<()> where P: AsRef, Q: AsRef, { use std::os::windows::fs::symlink_file; symlink_file(src, dst) } #[test] #[cfg(windows)] fn from_unix_time_test() { let time = FileTime::from_unix_time(10, 100_000_000); assert_eq!(11644473610, time.seconds); assert_eq!(100_000_000, time.nanos); let time = FileTime::from_unix_time(-10, 100_000_000); assert_eq!(11644473590, time.seconds); assert_eq!(100_000_000, time.nanos); let time = FileTime::from_unix_time(-12_000_000_000, 0); assert_eq!(-355526400, time.seconds); assert_eq!(0, time.nanos); } #[test] #[cfg(not(windows))] fn from_unix_time_test() { let time = FileTime::from_unix_time(10, 100_000_000); assert_eq!(10, time.seconds); assert_eq!(100_000_000, time.nanos); let time = FileTime::from_unix_time(-10, 100_000_000); assert_eq!(-10, time.seconds); assert_eq!(100_000_000, time.nanos); let time = FileTime::from_unix_time(-12_000_000_000, 0); assert_eq!(-12_000_000_000, time.seconds); assert_eq!(0, time.nanos); } #[test] #[cfg(windows)] fn from_system_time_test() { let time = FileTime::from_system_time(UNIX_EPOCH + Duration::from_secs(10)); assert_eq!(11644473610, time.seconds); assert_eq!(0, time.nanos); let time = FileTime::from_system_time(UNIX_EPOCH - Duration::from_secs(10)); assert_eq!(11644473590, time.seconds); assert_eq!(0, time.nanos); let time = FileTime::from_system_time(UNIX_EPOCH - Duration::from_millis(1100)); assert_eq!(11644473598, time.seconds); assert_eq!(900_000_000, time.nanos); let time = FileTime::from_system_time(UNIX_EPOCH - Duration::from_secs(12_000_000_000)); assert_eq!(-355526400, time.seconds); assert_eq!(0, time.nanos); } #[test] #[cfg(not(windows))] fn from_system_time_test() { let time = FileTime::from_system_time(UNIX_EPOCH + Duration::from_secs(10)); assert_eq!(10, time.seconds); assert_eq!(0, time.nanos); let time = FileTime::from_system_time(UNIX_EPOCH - Duration::from_secs(10)); assert_eq!(-10, time.seconds); assert_eq!(0, time.nanos); let time = FileTime::from_system_time(UNIX_EPOCH - Duration::from_millis(1100)); assert_eq!(-2, time.seconds); assert_eq!(900_000_000, time.nanos); let time = FileTime::from_system_time(UNIX_EPOCH - Duration::from_secs(12_000_000_000)); assert_eq!(-12_000_000_000, time.seconds); assert_eq!(0, time.nanos); } #[test] fn set_file_times_test() { let td = TempDir::new("filetime").unwrap(); let path = td.path().join("foo.txt"); File::create(&path).unwrap(); let metadata = fs::metadata(&path).unwrap(); let mtime = FileTime::from_last_modification_time(&metadata); let atime = FileTime::from_last_access_time(&metadata); set_file_times(&path, atime, mtime).unwrap(); let new_mtime = FileTime::from_unix_time(10_000, 0); set_file_times(&path, atime, new_mtime).unwrap(); let metadata = fs::metadata(&path).unwrap(); let mtime = FileTime::from_last_modification_time(&metadata); assert_eq!(mtime, new_mtime); let spath = td.path().join("bar.txt"); make_symlink(&path, &spath).unwrap(); let metadata = fs::symlink_metadata(&spath).unwrap(); let smtime = FileTime::from_last_modification_time(&metadata); set_file_times(&spath, atime, mtime).unwrap(); let metadata = fs::metadata(&path).unwrap(); let cur_mtime = FileTime::from_last_modification_time(&metadata); assert_eq!(mtime, cur_mtime); let metadata = fs::symlink_metadata(&spath).unwrap(); let cur_mtime = FileTime::from_last_modification_time(&metadata); assert_eq!(smtime, cur_mtime); set_file_times(&spath, atime, new_mtime).unwrap(); let metadata = fs::metadata(&path).unwrap(); let mtime = FileTime::from_last_modification_time(&metadata); assert_eq!(mtime, new_mtime); let metadata = fs::symlink_metadata(&spath).unwrap(); let mtime = FileTime::from_last_modification_time(&metadata); assert_eq!(mtime, smtime); } #[test] fn set_file_times_pre_unix_epoch_test() { let td = TempDir::new("filetime").unwrap(); let path = td.path().join("foo.txt"); File::create(&path).unwrap(); let metadata = fs::metadata(&path).unwrap(); let mtime = FileTime::from_last_modification_time(&metadata); let atime = FileTime::from_last_access_time(&metadata); set_file_times(&path, atime, mtime).unwrap(); let new_mtime = FileTime::from_unix_time(-10_000, 0); set_file_times(&path, atime, new_mtime).unwrap(); let metadata = fs::metadata(&path).unwrap(); let mtime = FileTime::from_last_modification_time(&metadata); assert_eq!(mtime, new_mtime); } #[test] #[cfg(windows)] fn set_file_times_pre_windows_epoch_test() { let td = TempDir::new("filetime").unwrap(); let path = td.path().join("foo.txt"); File::create(&path).unwrap(); let metadata = fs::metadata(&path).unwrap(); let mtime = FileTime::from_last_modification_time(&metadata); let atime = FileTime::from_last_access_time(&metadata); set_file_times(&path, atime, mtime).unwrap(); let new_mtime = FileTime::from_unix_time(-12_000_000_000, 0); assert!(set_file_times(&path, atime, new_mtime).is_err()); } #[test] fn set_symlink_file_times_test() { let td = TempDir::new("filetime").unwrap(); let path = td.path().join("foo.txt"); File::create(&path).unwrap(); let metadata = fs::metadata(&path).unwrap(); let mtime = FileTime::from_last_modification_time(&metadata); let atime = FileTime::from_last_access_time(&metadata); set_symlink_file_times(&path, atime, mtime).unwrap(); let new_mtime = FileTime::from_unix_time(10_000, 0); set_symlink_file_times(&path, atime, new_mtime).unwrap(); let metadata = fs::metadata(&path).unwrap(); let mtime = FileTime::from_last_modification_time(&metadata); assert_eq!(mtime, new_mtime); let spath = td.path().join("bar.txt"); make_symlink(&path, &spath).unwrap(); let metadata = fs::symlink_metadata(&spath).unwrap(); let smtime = FileTime::from_last_modification_time(&metadata); let satime = FileTime::from_last_access_time(&metadata); set_symlink_file_times(&spath, smtime, satime).unwrap(); let metadata = fs::metadata(&path).unwrap(); let mtime = FileTime::from_last_modification_time(&metadata); assert_eq!(mtime, new_mtime); let new_smtime = FileTime::from_unix_time(20_000, 0); set_symlink_file_times(&spath, atime, new_smtime).unwrap(); let metadata = fs::metadata(&spath).unwrap(); let mtime = FileTime::from_last_modification_time(&metadata); assert_eq!(mtime, new_mtime); let metadata = fs::symlink_metadata(&spath).unwrap(); let mtime = FileTime::from_last_modification_time(&metadata); assert_eq!(mtime, new_smtime); } } vendor/filetime-0.2.0/src/redox.rs0000644000000000000000000000307413264166600015570 0ustar rootrootextern crate syscall; use std::fs; use std::io; use std::os::unix::prelude::*; use std::path::Path; use FileTime; pub fn set_file_times(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> { let fd = syscall::open(p.as_os_str().as_bytes(), 0) .map_err(|err| io::Error::from_raw_os_error(err.errno))?; set_file_times_redox(fd, atime, mtime) } pub fn set_symlink_file_times(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> { let fd = syscall::open(p.as_os_str().as_bytes(), syscall::O_NOFOLLOW) .map_err(|err| io::Error::from_raw_os_error(err.errno))?; set_file_times_redox(fd, atime, mtime) } fn set_file_times_redox(fd: usize, atime: FileTime, mtime: FileTime) -> io::Result<()> { use self::syscall::TimeSpec; fn to_timespec(ft: &FileTime) -> TimeSpec { TimeSpec { tv_sec: ft.seconds(), tv_nsec: ft.nanoseconds() as i32 } } let times = [to_timespec(&atime), to_timespec(&mtime)]; let res = syscall::futimens(fd, ×); let _ = syscall::close(fd); match res { Ok(_) => Ok(()), Err(err) => Err(io::Error::from_raw_os_error(err.errno)) } } pub fn from_last_modification_time(meta: &fs::Metadata) -> FileTime { FileTime { seconds: meta.mtime(), nanos: meta.mtime_nsec() as u32, } } pub fn from_last_access_time(meta: &fs::Metadata) -> FileTime { FileTime { seconds: meta.atime(), nanos: meta.atime_nsec() as u32, } } pub fn from_creation_time(_meta: &fs::Metadata) -> Option { None } vendor/filetime-0.2.0/src/unix/0000755000000000000000000000000013264166600015060 5ustar rootrootvendor/filetime-0.2.0/src/unix/linux.rs0000644000000000000000000000427313264166600016573 0ustar rootroot//! On Linux we try to use the more accurate `utimensat` syscall but this isn't //! always available so we also fall back to `utimes` if we couldn't find //! `utimensat` at runtime. use std::io; use std::mem; use std::path::Path; use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT}; use FileTime; use super::libc::{self, c_int, c_char, timespec}; pub fn set_file_times(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> { set_times(p, atime, mtime, false) } pub fn set_symlink_file_times(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> { set_times(p, atime, mtime, true) } fn set_times(p: &Path, atime: FileTime, mtime: FileTime, symlink: bool) -> io::Result<()> { let flags = if symlink { libc::AT_SYMLINK_NOFOLLOW } else { 0 }; let utimes = if symlink { libc::lutimes } else { libc::utimes }; // Try to use the more-accurate `utimensat` when possible. static INVALID: AtomicBool = ATOMIC_BOOL_INIT; if !INVALID.load(Ordering::SeqCst) { if let Some(f) = utimensat() { // Even when libc has `utimensat`, the kernel may return `ENOSYS`, // and then we'll need to use the `utimes` fallback instead. match super::utimensat(p, atime, mtime, f, flags) { Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => { INVALID.store(true, Ordering::SeqCst); } valid => return valid, } } } super::utimes(p, atime, mtime, utimes) } fn utimensat() -> Option c_int> { static ADDR: AtomicUsize = ATOMIC_USIZE_INIT; unsafe { match ADDR.load(Ordering::SeqCst) { 0 => {} 1 => return None, n => return Some(mem::transmute(n)), } let name = b"utimensat\0"; let sym = libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr() as *const _); let (val, ret) = if sym.is_null() { (1, None) } else { (sym as usize, Some(mem::transmute(sym))) }; ADDR.store(val, Ordering::SeqCst); return ret } } vendor/filetime-0.2.0/src/unix/mod.rs0000644000000000000000000000630013264166600016204 0ustar rootrootextern crate libc; use std::ffi::CString; use std::fs; use std::io; use std::os::unix::prelude::*; use std::path::Path; use self::libc::{c_int, c_char, timeval, time_t, suseconds_t}; use self::libc::{timespec}; use FileTime; cfg_if! { if #[cfg(target_os = "linux")] { mod linux; pub use self::linux::*; } else if #[cfg(any(target_os = "android", target_os = "solaris", target_os = "netbsd", target_os = "openbsd"))] { mod utimensat; pub use self::utimensat::*; } else { mod utimes; pub use self::utimes::*; } } #[allow(dead_code)] fn utimes(p: &Path, atime: FileTime, mtime: FileTime, utimes: unsafe extern fn(*const c_char, *const timeval) -> c_int) -> io::Result<()> { let times = [to_timeval(&atime), to_timeval(&mtime)]; let p = try!(CString::new(p.as_os_str().as_bytes())); return if unsafe { utimes(p.as_ptr() as *const _, times.as_ptr()) == 0 } { Ok(()) } else { Err(io::Error::last_os_error()) }; fn to_timeval(ft: &FileTime) -> timeval { timeval { tv_sec: ft.seconds() as time_t, tv_usec: (ft.nanoseconds() / 1000) as suseconds_t, } } } #[allow(dead_code)] fn utimensat(p: &Path, atime: FileTime, mtime: FileTime, f: unsafe extern fn(c_int, *const c_char, *const timespec, c_int) -> c_int, flags: c_int) -> io::Result<()> { let times = [to_timespec(&atime), to_timespec(&mtime)]; let p = try!(CString::new(p.as_os_str().as_bytes())); let rc = unsafe { f(libc::AT_FDCWD, p.as_ptr() as *const _, times.as_ptr(), flags) }; return if rc == 0 { Ok(()) } else { Err(io::Error::last_os_error()) }; fn to_timespec(ft: &FileTime) -> timespec { timespec { tv_sec: ft.seconds() as time_t, tv_nsec: ft.nanoseconds() as _, } } } pub fn from_last_modification_time(meta: &fs::Metadata) -> FileTime { FileTime { seconds: meta.mtime(), nanos: meta.mtime_nsec() as u32, } } pub fn from_last_access_time(meta: &fs::Metadata) -> FileTime { FileTime { seconds: meta.atime(), nanos: meta.atime_nsec() as u32, } } pub fn from_creation_time(meta: &fs::Metadata) -> Option { macro_rules! birthtim { ($(($e:expr, $i:ident)),*) => { #[cfg(any($(target_os = $e),*))] fn imp(meta: &fs::Metadata) -> Option { $( #[cfg(target_os = $e)] use std::os::$i::fs::MetadataExt; )* Some(FileTime { seconds: meta.st_birthtime(), nanos: meta.st_birthtime_nsec() as u32, }) } #[cfg(all($(not(target_os = $e)),*))] fn imp(_meta: &fs::Metadata) -> Option { None } } } birthtim! { ("bitrig", bitrig), ("freebsd", freebsd), ("ios", ios), ("macos", macos), ("openbsd", openbsd) } imp(meta) } vendor/filetime-0.2.0/src/unix/utimensat.rs0000644000000000000000000000061013264166600017434 0ustar rootrootuse std::path::Path; use std::io; use FileTime; use super::libc; pub fn set_file_times(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> { super::utimensat(p, atime, mtime, libc::utimensat, 0) } pub fn set_symlink_file_times(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> { super::utimensat(p, atime, mtime, libc::utimensat, libc::AT_SYMLINK_NOFOLLOW) } vendor/filetime-0.2.0/src/unix/utimes.rs0000644000000000000000000000053713264166600016741 0ustar rootrootuse std::path::Path; use std::io; use FileTime; use super::libc; pub fn set_file_times(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> { super::utimes(p, atime, mtime, libc::utimes) } pub fn set_symlink_file_times(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> { super::utimes(p, atime, mtime, libc::lutimes) } vendor/filetime-0.2.0/src/windows.rs0000644000000000000000000000506613264166600016144 0ustar rootroot#![allow(bad_style)] use std::fs::{self, OpenOptions}; use std::io; use std::os::windows::prelude::*; use std::path::Path; use FileTime; pub fn set_file_times(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> { set_file_times_w(p, atime, mtime, OpenOptions::new()) } pub fn set_symlink_file_times(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> { use std::os::windows::fs::OpenOptionsExt; const FILE_FLAG_OPEN_REPARSE_POINT: u32 = 0x00200000; let mut options = OpenOptions::new(); options.custom_flags(FILE_FLAG_OPEN_REPARSE_POINT); set_file_times_w(p, atime, mtime, options) } pub fn set_file_times_w(p: &Path, atime: FileTime, mtime: FileTime, mut options: OpenOptions) -> io::Result<()> { type BOOL = i32; type HANDLE = *mut u8; type DWORD = u32; #[repr(C)] struct FILETIME { dwLowDateTime: u32, dwHighDateTime: u32, } extern "system" { fn SetFileTime(hFile: HANDLE, lpCreationTime: *const FILETIME, lpLastAccessTime: *const FILETIME, lpLastWriteTime: *const FILETIME) -> BOOL; } let f = try!(options.write(true).open(p)); let atime = to_filetime(&atime); let mtime = to_filetime(&mtime); return unsafe { let ret = SetFileTime(f.as_raw_handle() as *mut _, 0 as *const _, &atime, &mtime); if ret != 0 { Ok(()) } else { Err(io::Error::last_os_error()) } }; fn to_filetime(ft: &FileTime) -> FILETIME { let intervals = ft.seconds() * (1_000_000_000 / 100) + ((ft.nanoseconds() as i64) / 100); FILETIME { dwLowDateTime: intervals as DWORD, dwHighDateTime: (intervals >> 32) as DWORD, } } } pub fn from_last_modification_time(meta: &fs::Metadata) -> FileTime { from_intervals(meta.last_write_time()) } pub fn from_last_access_time(meta: &fs::Metadata) -> FileTime { from_intervals(meta.last_access_time()) } pub fn from_creation_time(meta: &fs::Metadata) -> Option { Some(from_intervals(meta.creation_time())) } fn from_intervals(ticks: u64) -> FileTime { // Windows write times are in 100ns intervals, so do a little math to // get it into the right representation. FileTime { seconds: (ticks / (1_000_000_000 / 100)) as i64, nanos: ((ticks % (1_000_000_000 / 100)) * 100) as u32, } } vendor/flate2-1.0.1/0000755000000000000000000000000013264166600012665 5ustar rootrootvendor/flate2-1.0.1/.cargo-checksum.json0000644000000000000000000000013113264166600016524 0ustar rootroot{"files":{},"package":"9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909"}vendor/flate2-1.0.1/.travis.yml0000664000000000000000000000236513264166600015006 0ustar rootrootlanguage: rust sudo: false matrix: include: - rust: 1.21.0 - rust: stable - os: osx - rust: beta - rust: nightly - rust: nightly before_script: - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH script: - cargo doc --no-deps --all-features after_success: - travis-cargo --only nightly doc-upload script: - export CARGO_TARGET_DIR=`pwd`/target - cargo build --verbose - rustdoc --test README.md -L target/debug/deps --extern flate2=target/debug/libflate2.rlib - cargo test --verbose - cargo test --verbose --features zlib - cargo test --verbose --features tokio - cargo test --verbose --features 'tokio zlib' - cargo test --verbose --features zlib --no-default-features - cargo test --verbose --features rust_backend - cargo test --verbose --features rust_backend --no-default-features - cargo clean && cargo build - cargo doc --no-deps - cargo doc --no-deps --manifest-path=miniz-sys/Cargo.toml env: global: secure: "PHVT7IaeP5nQQVwGHKwqCYBDp0QyetSlER7se2j2Xgfx+lw3Bu6VWH6VF04B636Gb0tHPN/sUCXSgGRcvDuy6XFOev4LfynoYxNKgHJYg2E34EP2QLwsFfnvE4iujaG3GJk3o935Y7OYGv2OP1HeG4Mv6JhQK0GLnNDBZQ65kWI=" notifications: email: on_success: never vendor/flate2-1.0.1/Cargo.toml0000644000000000000000000000343613264166600014623 0ustar rootroot# 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 = "flate2" version = "1.0.1" authors = ["Alex Crichton "] description = "Bindings to miniz.c for DEFLATE compression and decompression exposed as\nReader/Writer streams. Contains bindings for zlib, deflate, and gzip-based\nstreams.\n" homepage = "https://github.com/alexcrichton/flate2-rs" documentation = "https://docs.rs/flate2" readme = "README.md" keywords = ["gzip", "flate", "zlib", "encoding"] categories = ["compression", "api-bindings"] license = "MIT/Apache-2.0" repository = "https://github.com/alexcrichton/flate2-rs" [dependencies.futures] version = "0.1" optional = true [dependencies.libc] version = "0.2" [dependencies.libz-sys] version = "1.0" optional = true [dependencies.miniz-sys] version = "0.1.7" optional = true [dependencies.miniz_oxide_c_api] version = "0.1" optional = true [dependencies.tokio-io] version = "0.1" optional = true [dev-dependencies.quickcheck] version = "0.4" default-features = false [dev-dependencies.rand] version = "0.3" [dev-dependencies.tokio-core] version = "0.1" [features] default = ["miniz-sys"] rust_backend = ["miniz_oxide_c_api"] tokio = ["tokio-io", "futures"] zlib = ["libz-sys"] [badges.appveyor] repository = "alexcrichton/flate2-rs" [badges.travis-ci] repository = "alexcrichton/flate2-rs" vendor/flate2-1.0.1/LICENSE-APACHE0000664000000000000000000002513713264166600014623 0ustar rootroot 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. vendor/flate2-1.0.1/LICENSE-MIT0000664000000000000000000000204113264166600014320 0ustar rootrootCopyright (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. vendor/flate2-1.0.1/README.md0000664000000000000000000000451013264166600014146 0ustar rootroot# flate2 [![Build Status](https://travis-ci.org/alexcrichton/flate2-rs.svg?branch=master)](https://travis-ci.org/alexcrichton/flate2-rs) [![Build status](https://ci.appveyor.com/api/projects/status/9tatexq47i3ee13k?svg=true)](https://ci.appveyor.com/project/alexcrichton/flate2-rs) [![Crates.io](https://img.shields.io/crates/v/flate2.svg?maxAge=2592000)](https://crates.io/crates/flate2) [![Documentation](https://docs.rs/flate2/badge.svg)](https://docs.rs/flate2) A streaming compression/decompression library for Rust. The underlying implementation by default uses [`miniz`](https://github.com/richgel999/miniz) but can optionally be configured to use the system zlib, if available. There is also an experimental rust backend that uses the [`miniz_oxide`](https://crates.io/crates/miniz_oxide) crate. This avoids the need to build C code, but hasn't gone through as much testing as the other backends. Supported formats: * deflate * zlib * gzip ```toml # Cargo.toml [dependencies] flate2 = "0.2" ``` Using zlib instead of miniz: ```toml [dependencies] flate2 = { version = "0.2", features = ["zlib"], default-features = false } ``` Using the rust back-end: ```toml [dependencies] flate2 = { version = "0.2", features = ["rust_backend"], default-features = false } ``` ## Compression ```rust extern crate flate2; use std::io::prelude::*; use flate2::Compression; use flate2::write::ZlibEncoder; fn main() { let mut e = ZlibEncoder::new(Vec::new(), Compression::default()); e.write(b"foo"); e.write(b"bar"); let compressed_bytes = e.finish(); } ``` ## Decompression ```rust,no_run extern crate flate2; use std::io::prelude::*; use flate2::read::GzDecoder; fn main() { let mut d = GzDecoder::new("...".as_bytes()); let mut s = String::new(); d.read_to_string(&mut s).unwrap(); println!("{}", s); } ``` # License This project is licensed under either of * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. vendor/flate2-1.0.1/appveyor.yml0000664000000000000000000000141313264166600015256 0ustar rootrootenvironment: matrix: - TARGET: x86_64-pc-windows-msvc - TARGET: x86_64-pc-windows-gnu - TARGET: i686-pc-windows-msvc - TARGET: i686-pc-windows-gnu install: - ps: >- If ($Env:TARGET -eq 'x86_64-pc-windows-gnu') { $Env:PATH += ';C:\msys64\mingw64\bin' } ElseIf ($Env:TARGET -eq 'i686-pc-windows-gnu') { $Env:PATH += ';C:\MinGW\bin' } - 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 - rustc -V - cargo -V build: false test_script: - cargo test --verbose --target %TARGET% - cargo test --verbose --target %TARGET% --features tokio vendor/flate2-1.0.1/examples/0000755000000000000000000000000013264166600014503 5ustar rootrootvendor/flate2-1.0.1/examples/deflatedecoder-bufread.rs0000664000000000000000000000134313264166600021414 0ustar rootrootextern crate flate2; use std::io::prelude::*; use std::io; use flate2::Compression; use flate2::write::DeflateEncoder; use flate2::bufread::DeflateDecoder; // Compress a sample string and print it after transformation. fn main() { let mut e = DeflateEncoder::new(Vec::new(), Compression::default()); e.write(b"Hello World").unwrap(); let bytes = e.finish().unwrap(); println!("{}", decode_reader(bytes).unwrap()); } // Uncompresses a Deflate Encoded vector of bytes and returns a string or error // Here &[u8] implements Read fn decode_reader(bytes: Vec) -> io::Result { let mut deflater = DeflateDecoder::new(&bytes[..]); let mut s = String::new(); deflater.read_to_string(&mut s)?; Ok(s) } vendor/flate2-1.0.1/examples/deflatedecoder-read.rs0000664000000000000000000000134013264166600020714 0ustar rootrootextern crate flate2; use std::io::prelude::*; use std::io; use flate2::Compression; use flate2::write::DeflateEncoder; use flate2::read::DeflateDecoder; // Compress a sample string and print it after transformation. fn main() { let mut e = DeflateEncoder::new(Vec::new(), Compression::default()); e.write(b"Hello World").unwrap(); let bytes = e.finish().unwrap(); println!("{}", decode_reader(bytes).unwrap()); } // Uncompresses a Deflate Encoded vector of bytes and returns a string or error // Here &[u8] implements Read fn decode_reader(bytes: Vec) -> io::Result { let mut deflater = DeflateDecoder::new(&bytes[..]); let mut s = String::new(); deflater.read_to_string(&mut s)?; Ok(s) } vendor/flate2-1.0.1/examples/deflatedecoder-write.rs0000664000000000000000000000153413264166600021140 0ustar rootrootextern crate flate2; use std::io::prelude::*; use std::io; use flate2::Compression; use flate2::write::DeflateEncoder; use flate2::write::DeflateDecoder; // Compress a sample string and print it after transformation. fn main() { let mut e = DeflateEncoder::new(Vec::new(), Compression::default()); e.write(b"Hello World").unwrap(); let bytes = e.finish().unwrap(); println!("{}", decode_reader(bytes).unwrap()); } // Uncompresses a Deflate Encoded vector of bytes and returns a string or error // Here Vec implements Write fn decode_reader(bytes: Vec) -> io::Result { let mut writer = Vec::new(); let mut deflater = DeflateDecoder::new(writer); deflater.write(&bytes[..])?; writer = deflater.finish()?; let return_string = String::from_utf8(writer).expect("String parsing error"); Ok(return_string) } vendor/flate2-1.0.1/examples/deflateencoder-bufread.rs0000664000000000000000000000131113264166600021421 0ustar rootrootextern crate flate2; use std::io::prelude::*; use std::io; use flate2::Compression; use flate2::bufread::DeflateEncoder; use std::fs::File; use std::io::BufReader; // Open file and debug print the contents compressed with Deflate fn main() { println!("{:?}", open_hello_world().unwrap()); } // Opens sample file, compresses the contents and returns a Vector or error // File wrapped in a BufReader implements Bufread fn open_hello_world() -> io::Result> { let f = File::open("examples/hello_world.txt")?; let b = BufReader::new(f); let mut deflater = DeflateEncoder::new(b, Compression::fast()); let mut buffer = Vec::new(); deflater.read_to_end(&mut buffer)?; Ok(buffer) } vendor/flate2-1.0.1/examples/deflateencoder-read.rs0000664000000000000000000000115013264166600020725 0ustar rootrootextern crate flate2; use std::io::prelude::*; use std::io; use flate2::Compression; use flate2::read::DeflateEncoder; // Print the Deflate compressed representation of hello world fn main() { println!("{:?}", deflateencoder_read_hello_world().unwrap()); } // Return a vector containing the Defalte compressed version of hello world fn deflateencoder_read_hello_world() -> io::Result> { let mut ret_vec = [0;100]; let c = b"hello world"; let mut deflater = DeflateEncoder::new(&c[..], Compression::fast()); let count = deflater.read(&mut ret_vec)?; Ok(ret_vec[0..count].to_vec()) } vendor/flate2-1.0.1/examples/deflateencoder-write.rs0000664000000000000000000000053713264166600021154 0ustar rootrootextern crate flate2; use std::io::prelude::*; use flate2::Compression; use flate2::write::DeflateEncoder; // Vec implements Write to print the compressed bytes of sample string fn main() { let mut e = DeflateEncoder::new(Vec::new(), Compression::default()); e.write(b"Hello World").unwrap(); println!("{:?}", e.finish().unwrap()); } vendor/flate2-1.0.1/examples/gzbuilder.rs0000664000000000000000000000122513264166600017042 0ustar rootrootextern crate flate2; use std::io::prelude::*; use std::io; use std::fs::File; use flate2::GzBuilder; use flate2::Compression; // Open file and debug print the contents compressed with gzip fn main() { sample_builder().unwrap(); } // GzBuilder opens a file and writes a sample string using Builder pattern fn sample_builder() -> Result<(), io::Error> { let f = File::create("examples/hello_world.gz")?; let mut gz = GzBuilder::new() .filename("hello_world.txt") .comment("test file, please delete") .write(f, Compression::default()); gz.write(b"hello world")?; gz.finish()?; Ok(()) } vendor/flate2-1.0.1/examples/gzdecoder-bufread.rs0000664000000000000000000000130113264166600020422 0ustar rootrootextern crate flate2; use std::io::prelude::*; use std::io; use flate2::Compression; use flate2::write::GzEncoder; use flate2::bufread::GzDecoder; // Compress a sample string and print it after transformation. fn main() { let mut e = GzEncoder::new(Vec::new(), Compression::default()); e.write(b"Hello World").unwrap(); let bytes = e.finish().unwrap(); println!("{}", decode_reader(bytes).unwrap()); } // Uncompresses a Gz Encoded vector of bytes and returns a string or error // Here &[u8] implements BufRead fn decode_reader(bytes: Vec) -> io::Result { let mut gz = GzDecoder::new(&bytes[..]); let mut s = String::new(); gz.read_to_string(&mut s)?; Ok(s) } vendor/flate2-1.0.1/examples/gzdecoder-read.rs0000664000000000000000000000127313264166600017735 0ustar rootrootextern crate flate2; use std::io::prelude::*; use std::io; use flate2::Compression; use flate2::write::GzEncoder; use flate2::read::GzDecoder; // Compress a sample string and print it after transformation. fn main() { let mut e = GzEncoder::new(Vec::new(), Compression::default()); e.write(b"Hello World").unwrap(); let bytes = e.finish().unwrap(); println!("{}", decode_reader(bytes).unwrap()); } // Uncompresses a Gz Encoded vector of bytes and returns a string or error // Here &[u8] implements Read fn decode_reader(bytes: Vec) -> io::Result { let mut gz = GzDecoder::new(&bytes[..]); let mut s = String::new(); gz.read_to_string(&mut s)?; Ok(s) } vendor/flate2-1.0.1/examples/gzencoder-bufread.rs0000664000000000000000000000126013264166600020440 0ustar rootrootextern crate flate2; use std::io::prelude::*; use std::io; use flate2::Compression; use flate2::bufread::GzEncoder; use std::fs::File; use std::io::BufReader; // Open file and debug print the contents compressed with gzip fn main() { println!("{:?}", open_hello_world().unwrap()); } // Opens sample file, compresses the contents and returns a Vector or error // File wrapped in a BufReader implements Bufread fn open_hello_world() -> io::Result> { let f = File::open("examples/hello_world.txt")?; let b = BufReader::new(f); let mut gz = GzEncoder::new(b, Compression::fast()); let mut buffer = Vec::new(); gz.read_to_end(&mut buffer)?; Ok(buffer) } vendor/flate2-1.0.1/examples/gzencoder-read.rs0000664000000000000000000000107413264166600017746 0ustar rootrootextern crate flate2; use std::io::prelude::*; use std::io; use flate2::Compression; use flate2::read::GzEncoder; // Print the GZ compressed representation of hello world fn main() { println!("{:?}", gzencoder_read_hello_world().unwrap()); } // Return a vector containing the GZ compressed version of hello world fn gzencoder_read_hello_world() -> io::Result> { let mut ret_vec = [0;100]; let c = b"hello world"; let mut z = GzEncoder::new(&c[..], Compression::fast()); let count = z.read(&mut ret_vec)?; Ok(ret_vec[0..count].to_vec()) } vendor/flate2-1.0.1/examples/gzencoder-write.rs0000664000000000000000000000052513264166600020165 0ustar rootrootextern crate flate2; use std::io::prelude::*; use flate2::Compression; use flate2::write::GzEncoder; // Vec implements Write to print the compressed bytes of sample string fn main() { let mut e = GzEncoder::new(Vec::new(), Compression::default()); e.write(b"Hello World").unwrap(); println!("{:?}", e.finish().unwrap()); } vendor/flate2-1.0.1/examples/gzmultidecoder-bufread.rs0000664000000000000000000000131313264166600021500 0ustar rootrootextern crate flate2; use std::io::prelude::*; use std::io; use flate2::Compression; use flate2::write::GzEncoder; use flate2::bufread::MultiGzDecoder; // Compress a sample string and print it after transformation. fn main() { let mut e = GzEncoder::new(Vec::new(), Compression::default()); e.write(b"Hello World").unwrap(); let bytes = e.finish().unwrap(); println!("{}", decode_reader(bytes).unwrap()); } // Uncompresses a Gz Encoded vector of bytes and returns a string or error // Here &[u8] implements BufRead fn decode_reader(bytes: Vec) -> io::Result { let mut gz = MultiGzDecoder::new(&bytes[..]); let mut s = String::new(); gz.read_to_string(&mut s)?; Ok(s) } vendor/flate2-1.0.1/examples/gzmultidecoder-read.rs0000664000000000000000000000130513264166600021004 0ustar rootrootextern crate flate2; use std::io::prelude::*; use std::io; use flate2::Compression; use flate2::write::GzEncoder; use flate2::read::MultiGzDecoder; // Compress a sample string and print it after transformation. fn main() { let mut e = GzEncoder::new(Vec::new(), Compression::default()); e.write(b"Hello World").unwrap(); let bytes = e.finish().unwrap(); println!("{}", decode_reader(bytes).unwrap()); } // Uncompresses a Gz Encoded vector of bytes and returns a string or error // Here &[u8] implements Read fn decode_reader(bytes: Vec) -> io::Result { let mut gz = MultiGzDecoder::new(&bytes[..]); let mut s = String::new(); gz.read_to_string(&mut s)?; Ok(s) } vendor/flate2-1.0.1/examples/hello_world.txt0000664000000000000000000000001413264166600017553 0ustar rootrootHello World vendor/flate2-1.0.1/examples/zlibdecoder-bufread.rs0000664000000000000000000000131713264166600020751 0ustar rootrootextern crate flate2; use std::io::prelude::*; use std::io; use flate2::Compression; use flate2::write::ZlibEncoder; use flate2::bufread::ZlibDecoder; // Compress a sample string and print it after transformation. fn main() { let mut e = ZlibEncoder::new(Vec::new(), Compression::default()); e.write(b"Hello World").unwrap(); let bytes = e.finish().unwrap(); println!("{}", decode_bufreader(bytes).unwrap()); } // Uncompresses a Zlib Encoded vector of bytes and returns a string or error // Here &[u8] implements BufRead fn decode_bufreader(bytes: Vec) -> io::Result { let mut z = ZlibDecoder::new(&bytes[..]); let mut s = String::new(); z.read_to_string(&mut s)?; Ok(s) } vendor/flate2-1.0.1/examples/zlibdecoder-read.rs0000664000000000000000000000130313264166600020247 0ustar rootrootextern crate flate2; use std::io::prelude::*; use std::io; use flate2::Compression; use flate2::write::ZlibEncoder; use flate2::read::ZlibDecoder; // Compress a sample string and print it after transformation. fn main() { let mut e = ZlibEncoder::new(Vec::new(), Compression::default()); e.write(b"Hello World").unwrap(); let bytes = e.finish().unwrap(); println!("{}", decode_reader(bytes).unwrap()); } // Uncompresses a Zlib Encoded vector of bytes and returns a string or error // Here &[u8] implements Read fn decode_reader(bytes: Vec) -> io::Result { let mut z = ZlibDecoder::new(&bytes[..]); let mut s = String::new(); z.read_to_string(&mut s)?; Ok(s) } vendor/flate2-1.0.1/examples/zlibdecoder-write.rs0000664000000000000000000000147013264166600020473 0ustar rootrootextern crate flate2; use std::io::prelude::*; use std::io; use flate2::Compression; use flate2::write::ZlibEncoder; use flate2::write::ZlibDecoder; // Compress a sample string and print it after transformation. fn main() { let mut e = ZlibEncoder::new(Vec::new(), Compression::default()); e.write(b"Hello World").unwrap(); let bytes = e.finish().unwrap(); println!("{}", decode_reader(bytes).unwrap()); } // Uncompresses a Zlib Encoded vector of bytes and returns a string or error // Here Vec implements Write fn decode_reader(bytes: Vec) -> io::Result { let mut writer = Vec::new(); let mut z = ZlibDecoder::new(writer); z.write(&bytes[..])?; writer = z.finish()?; let return_string = String::from_utf8(writer).expect("String parsing error"); Ok(return_string) } vendor/flate2-1.0.1/examples/zlibencoder-bufread.rs0000664000000000000000000000126213264166600020762 0ustar rootrootextern crate flate2; use std::io::prelude::*; use std::io; use flate2::Compression; use flate2::bufread::ZlibEncoder; use std::fs::File; use std::io::BufReader; // Open file and debug print the contents compressed with zlib fn main() { println!("{:?}", open_hello_world().unwrap()); } // Opens sample file, compresses the contents and returns a Vector or error // File wrapped in a BufReader implements Bufread fn open_hello_world() -> io::Result> { let f = File::open("examples/hello_world.txt")?; let b = BufReader::new(f); let mut z = ZlibEncoder::new(b, Compression::fast()); let mut buffer = Vec::new(); z.read_to_end(&mut buffer)?; Ok(buffer) } vendor/flate2-1.0.1/examples/zlibencoder-read.rs0000664000000000000000000000115213264166600020263 0ustar rootrootextern crate flate2; use std::io::prelude::*; use flate2::Compression; use flate2::read::ZlibEncoder; use std::fs::File; // Open file and debug print the compressed contents fn main() { println!("{:?}", open_hello_world().unwrap()); } // Opens sample file, compresses the contents and returns a Vector or error // File implements Read fn open_hello_world() -> std::io::Result> { let f = File::open("examples/hello_world.txt")?; let mut z = ZlibEncoder::new(f, Compression::fast()); let mut buffer = [0;50]; let byte_count = z.read(&mut buffer)?; Ok(buffer[0..byte_count].to_vec()) } vendor/flate2-1.0.1/examples/zlibencoder-write.rs0000664000000000000000000000053113264166600020502 0ustar rootrootextern crate flate2; use std::io::prelude::*; use flate2::Compression; use flate2::write::ZlibEncoder; // Vec implements Write to print the compressed bytes of sample string fn main() { let mut e = ZlibEncoder::new(Vec::new(), Compression::default()); e.write(b"Hello World").unwrap(); println!("{:?}", e.finish().unwrap()); } vendor/flate2-1.0.1/src/0000755000000000000000000000000013264166600013454 5ustar rootrootvendor/flate2-1.0.1/src/bufreader.rs0000664000000000000000000000530413264166600015765 0ustar rootroot// 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use std::cmp; use std::io; use std::io::prelude::*; use std::mem; pub struct BufReader { inner: R, buf: Box<[u8]>, pos: usize, cap: usize, } impl ::std::fmt::Debug for BufReader where R: ::std::fmt::Debug { fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error>{ fmt.debug_struct("BufReader") .field("reader", &self.inner) .field("buffer", &format_args!("{}/{}", self.cap - self.pos, self.buf.len())) .finish() } } impl BufReader { pub fn new(inner: R) -> BufReader { BufReader::with_buf(vec![0; 32 * 1024], inner) } pub fn with_buf(buf: Vec, inner: R) -> BufReader { BufReader { inner: inner, buf: buf.into_boxed_slice(), pos: 0, cap: 0, } } } impl BufReader { pub fn get_ref(&self) -> &R { &self.inner } pub fn get_mut(&mut self) -> &mut R { &mut self.inner } pub fn into_inner(self) -> R { self.inner } pub fn reset(&mut self, inner: R) -> R { self.pos = 0; self.cap = 0; mem::replace(&mut self.inner, inner) } } impl Read for BufReader { fn read(&mut self, buf: &mut [u8]) -> io::Result { // If we don't have any buffered data and we're doing a massive read // (larger than our internal buffer), bypass our internal buffer // entirely. if self.pos == self.cap && buf.len() >= self.buf.len() { return self.inner.read(buf); } let nread = { let mut rem = try!(self.fill_buf()); try!(rem.read(buf)) }; self.consume(nread); Ok(nread) } } impl BufRead for BufReader { fn fill_buf(&mut self) -> io::Result<&[u8]> { // If we've reached the end of our internal buffer then we need to fetch // some more data from the underlying reader. if self.pos == self.cap { self.cap = try!(self.inner.read(&mut self.buf)); self.pos = 0; } Ok(&self.buf[self.pos..self.cap]) } fn consume(&mut self, amt: usize) { self.pos = cmp::min(self.pos + amt, self.cap); } } vendor/flate2-1.0.1/src/crc.rs0000664000000000000000000000566513264166600014607 0ustar rootroot//! Simple CRC bindings backed by miniz.c use std::io::prelude::*; use std::io; use libc; use ffi; /// The CRC calculated by a [`CrcReader`]. /// /// [`CrcReader`]: struct.CrcReader.html #[derive(Debug)] pub struct Crc { crc: libc::c_ulong, amt: u32, } /// A wrapper around a [`Read`] that calculates the CRC. /// /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html #[derive(Debug)] pub struct CrcReader { inner: R, crc: Crc, } impl Crc { /// Create a new CRC. pub fn new() -> Crc { Crc { crc: 0, amt: 0 } } /// bla pub fn sum(&self) -> u32 { self.crc as u32 } /// The number of bytes that have been used to calculate the CRC. /// This value is only accurate if the amount is lower than 232. pub fn amount(&self) -> u32 { self.amt } /// Update the CRC with the bytes in `data`. pub fn update(&mut self, data: &[u8]) { self.amt = self.amt.wrapping_add(data.len() as u32); self.crc = unsafe { ffi::mz_crc32(self.crc, data.as_ptr(), data.len() as libc::size_t) }; } /// Reset the CRC. pub fn reset(&mut self) { self.crc = 0; self.amt = 0; } /// Combine the CRC with the CRC for the subsequent block of bytes. pub fn combine(&mut self, additional_crc: &Crc) { self.crc = unsafe { ffi::mz_crc32_combine(self.crc as ::libc::c_ulong, additional_crc.crc as ::libc::c_ulong, additional_crc.amt as ::libc::off_t) }; self.amt += additional_crc.amt; } } impl CrcReader { /// Create a new CrcReader. pub fn new(r: R) -> CrcReader { CrcReader { inner: r, crc: Crc::new(), } } } impl CrcReader { /// Get the Crc for this CrcReader. pub fn crc(&self) -> &Crc { &self.crc } /// Get the reader that is wrapped by this CrcReader. pub fn into_inner(self) -> R { self.inner } /// Get the reader that is wrapped by this CrcReader by reference. pub fn get_ref(&self) -> &R { &self.inner } /// Get a mutable reference to the reader that is wrapped by this CrcReader. pub fn get_mut(&mut self) -> &mut R { &mut self.inner } /// Reset the Crc in this CrcReader. pub fn reset(&mut self) { self.crc.reset(); } } impl Read for CrcReader { fn read(&mut self, into: &mut [u8]) -> io::Result { let amt = try!(self.inner.read(into)); self.crc.update(&into[..amt]); Ok(amt) } } impl BufRead for CrcReader { fn fill_buf(&mut self) -> io::Result<&[u8]> { self.inner.fill_buf() } fn consume(&mut self, amt: usize) { if let Ok(data) = self.inner.fill_buf() { self.crc.update(&data[..amt]); } self.inner.consume(amt); } } vendor/flate2-1.0.1/src/deflate/0000755000000000000000000000000013264166600015060 5ustar rootrootvendor/flate2-1.0.1/src/deflate/bufread.rs0000664000000000000000000001721613264166600017047 0ustar rootrootuse std::io::prelude::*; use std::io; use std::mem; #[cfg(feature = "tokio")] use futures::Poll; #[cfg(feature = "tokio")] use tokio_io::{AsyncRead, AsyncWrite}; use zio; use {Compress, Decompress}; /// A DEFLATE encoder, or compressor. /// /// This structure implements a [`BufRead`] interface and will read uncompressed /// data from an underlying stream and emit a stream of compressed data. /// /// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use std::io; /// use flate2::Compression; /// use flate2::bufread::DeflateEncoder; /// use std::fs::File; /// use std::io::BufReader; /// /// # fn main() { /// # println!("{:?}", open_hello_world().unwrap()); /// # } /// # /// // Opens sample file, compresses the contents and returns a Vector /// fn open_hello_world() -> io::Result> { /// let f = File::open("examples/hello_world.txt")?; /// let b = BufReader::new(f); /// let mut deflater = DeflateEncoder::new(b, Compression::fast()); /// let mut buffer = Vec::new(); /// deflater.read_to_end(&mut buffer)?; /// Ok(buffer) /// } /// ``` #[derive(Debug)] pub struct DeflateEncoder { obj: R, data: Compress, } impl DeflateEncoder { /// Creates a new encoder which will read uncompressed data from the given /// stream and emit the compressed stream. pub fn new(r: R, level: ::Compression) -> DeflateEncoder { DeflateEncoder { obj: r, data: Compress::new(level, false), } } } pub fn reset_encoder_data(zlib: &mut DeflateEncoder) { zlib.data.reset(); } impl DeflateEncoder { /// Resets the state of this encoder entirely, swapping out the input /// stream for another. /// /// This function will reset the internal state of this encoder and replace /// the input stream with the one provided, returning the previous input /// stream. Future data read from this encoder will be the compressed /// version of `r`'s data. pub fn reset(&mut self, r: R) -> R { reset_encoder_data(self); mem::replace(&mut self.obj, r) } /// Acquires a reference to the underlying reader pub fn get_ref(&self) -> &R { &self.obj } /// Acquires a mutable reference to the underlying stream /// /// Note that mutation of the stream may result in surprising results if /// this encoder is continued to be used. pub fn get_mut(&mut self) -> &mut R { &mut self.obj } /// Consumes this encoder, returning the underlying reader. pub fn into_inner(self) -> R { self.obj } /// Returns the number of bytes that have been read into this compressor. /// /// Note that not all bytes read from the underlying object may be accounted /// for, there may still be some active buffering. pub fn total_in(&self) -> u64 { self.data.total_in() } /// Returns the number of bytes that the compressor has produced. /// /// Note that not all bytes may have been read yet, some may still be /// buffered. pub fn total_out(&self) -> u64 { self.data.total_out() } } impl Read for DeflateEncoder { fn read(&mut self, buf: &mut [u8]) -> io::Result { zio::read(&mut self.obj, &mut self.data, buf) } } #[cfg(feature = "tokio")] impl AsyncRead for DeflateEncoder {} impl Write for DeflateEncoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.get_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.get_mut().flush() } } #[cfg(feature = "tokio")] impl AsyncWrite for DeflateEncoder { fn shutdown(&mut self) -> Poll<(), io::Error> { self.get_mut().shutdown() } } /// A DEFLATE decoder, or decompressor. /// /// This structure implements a [`BufRead`] interface and takes a stream of /// compressed data as input, providing the decompressed data when read from. /// /// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use std::io; /// # use flate2::Compression; /// # use flate2::write::DeflateEncoder; /// use flate2::bufread::DeflateDecoder; /// /// # fn main() { /// # let mut e = DeflateEncoder::new(Vec::new(), Compression::default()); /// # e.write(b"Hello World").unwrap(); /// # let bytes = e.finish().unwrap(); /// # println!("{}", decode_reader(bytes).unwrap()); /// # } /// // Uncompresses a Deflate Encoded vector of bytes and returns a string or error /// // Here &[u8] implements Read /// fn decode_reader(bytes: Vec) -> io::Result { /// let mut deflater = DeflateDecoder::new(&bytes[..]); /// let mut s = String::new(); /// deflater.read_to_string(&mut s)?; /// Ok(s) /// } /// ``` #[derive(Debug)] pub struct DeflateDecoder { obj: R, data: Decompress, } pub fn reset_decoder_data(zlib: &mut DeflateDecoder) { zlib.data = Decompress::new(false); } impl DeflateDecoder { /// Creates a new decoder which will decompress data read from the given /// stream. pub fn new(r: R) -> DeflateDecoder { DeflateDecoder { obj: r, data: Decompress::new(false), } } } impl DeflateDecoder { /// Resets the state of this decoder entirely, swapping out the input /// stream for another. /// /// This will reset the internal state of this decoder and replace the /// input stream with the one provided, returning the previous input /// stream. Future data read from this decoder will be the decompressed /// version of `r`'s data. pub fn reset(&mut self, r: R) -> R { reset_decoder_data(self); mem::replace(&mut self.obj, r) } /// Resets the state of this decoder's data /// /// This will reset the internal state of this decoder. It will continue /// reading from the same stream. pub fn reset_data(&mut self) { reset_decoder_data(self); } /// Acquires a reference to the underlying stream pub fn get_ref(&self) -> &R { &self.obj } /// Acquires a mutable reference to the underlying stream /// /// Note that mutation of the stream may result in surprising results if /// this encoder is continued to be used. pub fn get_mut(&mut self) -> &mut R { &mut self.obj } /// Consumes this decoder, returning the underlying reader. pub fn into_inner(self) -> R { self.obj } /// Returns the number of bytes that the decompressor has consumed. /// /// Note that this will likely be smaller than what the decompressor /// actually read from the underlying stream due to buffering. pub fn total_in(&self) -> u64 { self.data.total_in() } /// Returns the number of bytes that the decompressor has produced. pub fn total_out(&self) -> u64 { self.data.total_out() } } impl Read for DeflateDecoder { fn read(&mut self, into: &mut [u8]) -> io::Result { zio::read(&mut self.obj, &mut self.data, into) } } #[cfg(feature = "tokio")] impl AsyncRead for DeflateDecoder {} impl Write for DeflateDecoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.get_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.get_mut().flush() } } #[cfg(feature = "tokio")] impl AsyncWrite for DeflateDecoder { fn shutdown(&mut self) -> Poll<(), io::Error> { self.get_mut().shutdown() } } vendor/flate2-1.0.1/src/deflate/mod.rs0000664000000000000000000001423613264166600016215 0ustar rootrootpub mod bufread; pub mod read; pub mod write; #[cfg(test)] mod tests { use std::io::prelude::*; use rand::{thread_rng, Rng}; use super::{read, write}; use Compression; #[test] fn roundtrip() { let mut real = Vec::new(); let mut w = write::DeflateEncoder::new(Vec::new(), Compression::default()); let v = thread_rng().gen_iter::().take(1024).collect::>(); for _ in 0..200 { let to_write = &v[..thread_rng().gen_range(0, v.len())]; real.extend(to_write.iter().map(|x| *x)); w.write_all(to_write).unwrap(); } let result = w.finish().unwrap(); let mut r = read::DeflateDecoder::new(&result[..]); let mut ret = Vec::new(); r.read_to_end(&mut ret).unwrap(); assert!(ret == real); } #[test] fn drop_writes() { let mut data = Vec::new(); write::DeflateEncoder::new(&mut data, Compression::default()) .write_all(b"foo") .unwrap(); let mut r = read::DeflateDecoder::new(&data[..]); let mut ret = Vec::new(); r.read_to_end(&mut ret).unwrap(); assert!(ret == b"foo"); } #[test] fn total_in() { let mut real = Vec::new(); let mut w = write::DeflateEncoder::new(Vec::new(), Compression::default()); let v = thread_rng().gen_iter::().take(1024).collect::>(); for _ in 0..200 { let to_write = &v[..thread_rng().gen_range(0, v.len())]; real.extend(to_write.iter().map(|x| *x)); w.write_all(to_write).unwrap(); } let mut result = w.finish().unwrap(); let result_len = result.len(); for _ in 0..200 { result.extend(v.iter().map(|x| *x)); } let mut r = read::DeflateDecoder::new(&result[..]); let mut ret = Vec::new(); r.read_to_end(&mut ret).unwrap(); assert!(ret == real); assert_eq!(r.total_in(), result_len as u64); } #[test] fn roundtrip2() { let v = thread_rng() .gen_iter::() .take(1024 * 1024) .collect::>(); let mut r = read::DeflateDecoder::new(read::DeflateEncoder::new(&v[..], Compression::default())); let mut ret = Vec::new(); r.read_to_end(&mut ret).unwrap(); assert_eq!(ret, v); } #[test] fn roundtrip3() { let v = thread_rng() .gen_iter::() .take(1024 * 1024) .collect::>(); let mut w = write::DeflateEncoder::new(write::DeflateDecoder::new(Vec::new()), Compression::default()); w.write_all(&v).unwrap(); let w = w.finish().unwrap().finish().unwrap(); assert!(w == v); } #[test] fn reset_writer() { let v = thread_rng() .gen_iter::() .take(1024 * 1024) .collect::>(); let mut w = write::DeflateEncoder::new(Vec::new(), Compression::default()); w.write_all(&v).unwrap(); let a = w.reset(Vec::new()).unwrap(); w.write_all(&v).unwrap(); let b = w.finish().unwrap(); let mut w = write::DeflateEncoder::new(Vec::new(), Compression::default()); w.write_all(&v).unwrap(); let c = w.finish().unwrap(); assert!(a == b && b == c); } #[test] fn reset_reader() { let v = thread_rng() .gen_iter::() .take(1024 * 1024) .collect::>(); let (mut a, mut b, mut c) = (Vec::new(), Vec::new(), Vec::new()); let mut r = read::DeflateEncoder::new(&v[..], Compression::default()); r.read_to_end(&mut a).unwrap(); r.reset(&v[..]); r.read_to_end(&mut b).unwrap(); let mut r = read::DeflateEncoder::new(&v[..], Compression::default()); r.read_to_end(&mut c).unwrap(); assert!(a == b && b == c); } #[test] fn reset_decoder() { let v = thread_rng() .gen_iter::() .take(1024 * 1024) .collect::>(); let mut w = write::DeflateEncoder::new(Vec::new(), Compression::default()); w.write_all(&v).unwrap(); let data = w.finish().unwrap(); { let (mut a, mut b, mut c) = (Vec::new(), Vec::new(), Vec::new()); let mut r = read::DeflateDecoder::new(&data[..]); r.read_to_end(&mut a).unwrap(); r.reset(&data); r.read_to_end(&mut b).unwrap(); let mut r = read::DeflateDecoder::new(&data[..]); r.read_to_end(&mut c).unwrap(); assert!(a == b && b == c && c == v); } { let mut w = write::DeflateDecoder::new(Vec::new()); w.write_all(&data).unwrap(); let a = w.reset(Vec::new()).unwrap(); w.write_all(&data).unwrap(); let b = w.finish().unwrap(); let mut w = write::DeflateDecoder::new(Vec::new()); w.write_all(&data).unwrap(); let c = w.finish().unwrap(); assert!(a == b && b == c && c == v); } } #[test] fn zero_length_read_with_data() { let m = vec![3u8; 128 * 1024 + 1]; let mut c = read::DeflateEncoder::new(&m[..], Compression::default()); let mut result = Vec::new(); c.read_to_end(&mut result).unwrap(); let mut d = read::DeflateDecoder::new(&result[..]); let mut data = Vec::new(); assert!(d.read(&mut data).unwrap() == 0); } #[test] fn qc_reader() { ::quickcheck::quickcheck(test as fn(_) -> _); fn test(v: Vec) -> bool { let mut r = read::DeflateDecoder::new(read::DeflateEncoder::new(&v[..], Compression::default())); let mut v2 = Vec::new(); r.read_to_end(&mut v2).unwrap(); v == v2 } } #[test] fn qc_writer() { ::quickcheck::quickcheck(test as fn(_) -> _); fn test(v: Vec) -> bool { let mut w = write::DeflateEncoder::new(write::DeflateDecoder::new(Vec::new()), Compression::default()); w.write_all(&v).unwrap(); v == w.finish().unwrap().finish().unwrap() } } } vendor/flate2-1.0.1/src/deflate/read.rs0000664000000000000000000002050013264166600016340 0ustar rootrootuse std::io::prelude::*; use std::io; #[cfg(feature = "tokio")] use futures::Poll; #[cfg(feature = "tokio")] use tokio_io::{AsyncRead, AsyncWrite}; use bufreader::BufReader; use super::bufread; /// A DEFLATE encoder, or compressor. /// /// This structure implements a [`Read`] interface and will read uncompressed /// data from an underlying stream and emit a stream of compressed data. /// /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use std::io; /// use flate2::Compression; /// use flate2::read::DeflateEncoder; /// /// # fn main() { /// # println!("{:?}", deflateencoder_read_hello_world().unwrap()); /// # } /// # /// // Return a vector containing the Deflate compressed version of hello world /// fn deflateencoder_read_hello_world() -> io::Result> { /// let mut ret_vec = [0;100]; /// let c = b"hello world"; /// let mut deflater = DeflateEncoder::new(&c[..], Compression::fast()); /// let count = deflater.read(&mut ret_vec)?; /// Ok(ret_vec[0..count].to_vec()) /// } /// ``` #[derive(Debug)] pub struct DeflateEncoder { inner: bufread::DeflateEncoder>, } impl DeflateEncoder { /// Creates a new encoder which will read uncompressed data from the given /// stream and emit the compressed stream. pub fn new(r: R, level: ::Compression) -> DeflateEncoder { DeflateEncoder { inner: bufread::DeflateEncoder::new(BufReader::new(r), level), } } } impl DeflateEncoder { /// Resets the state of this encoder entirely, swapping out the input /// stream for another. /// /// This function will reset the internal state of this encoder and replace /// the input stream with the one provided, returning the previous input /// stream. Future data read from this encoder will be the compressed /// version of `r`'s data. /// /// Note that there may be currently buffered data when this function is /// called, and in that case the buffered data is discarded. pub fn reset(&mut self, r: R) -> R { super::bufread::reset_encoder_data(&mut self.inner); self.inner.get_mut().reset(r) } /// Acquires a reference to the underlying reader pub fn get_ref(&self) -> &R { self.inner.get_ref().get_ref() } /// Acquires a mutable reference to the underlying stream /// /// Note that mutation of the stream may result in surprising results if /// this encoder is continued to be used. pub fn get_mut(&mut self) -> &mut R { self.inner.get_mut().get_mut() } /// Consumes this encoder, returning the underlying reader. /// /// Note that there may be buffered bytes which are not re-acquired as part /// of this transition. It's recommended to only call this function after /// EOF has been reached. pub fn into_inner(self) -> R { self.inner.into_inner().into_inner() } /// Returns the number of bytes that have been read into this compressor. /// /// Note that not all bytes read from the underlying object may be accounted /// for, there may still be some active buffering. pub fn total_in(&self) -> u64 { self.inner.total_in() } /// Returns the number of bytes that the compressor has produced. /// /// Note that not all bytes may have been read yet, some may still be /// buffered. pub fn total_out(&self) -> u64 { self.inner.total_out() } } impl Read for DeflateEncoder { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.read(buf) } } #[cfg(feature = "tokio")] impl AsyncRead for DeflateEncoder {} impl Write for DeflateEncoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.get_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.get_mut().flush() } } #[cfg(feature = "tokio")] impl AsyncWrite for DeflateEncoder { fn shutdown(&mut self) -> Poll<(), io::Error> { self.get_mut().shutdown() } } /// A DEFLATE decoder, or decompressor. /// /// This structure implements a [`Read`] interface and takes a stream of /// compressed data as input, providing the decompressed data when read from. /// /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use std::io; /// # use flate2::Compression; /// # use flate2::write::DeflateEncoder; /// use flate2::read::DeflateDecoder; /// /// # fn main() { /// # let mut e = DeflateEncoder::new(Vec::new(), Compression::default()); /// # e.write(b"Hello World").unwrap(); /// # let bytes = e.finish().unwrap(); /// # println!("{}", decode_reader(bytes).unwrap()); /// # } /// // Uncompresses a Deflate Encoded vector of bytes and returns a string or error /// // Here &[u8] implements Read /// fn decode_reader(bytes: Vec) -> io::Result { /// let mut deflater = DeflateDecoder::new(&bytes[..]); /// let mut s = String::new(); /// deflater.read_to_string(&mut s)?; /// Ok(s) /// } /// ``` #[derive(Debug)] pub struct DeflateDecoder { inner: bufread::DeflateDecoder>, } impl DeflateDecoder { /// Creates a new decoder which will decompress data read from the given /// stream. pub fn new(r: R) -> DeflateDecoder { DeflateDecoder::new_with_buf(r, vec![0; 32 * 1024]) } /// Same as `new`, but the intermediate buffer for data is specified. /// /// Note that the capacity of the intermediate buffer is never increased, /// and it is recommended for it to be large. pub fn new_with_buf(r: R, buf: Vec) -> DeflateDecoder { DeflateDecoder { inner: bufread::DeflateDecoder::new(BufReader::with_buf(buf, r)), } } } impl DeflateDecoder { /// Resets the state of this decoder entirely, swapping out the input /// stream for another. /// /// This will reset the internal state of this decoder and replace the /// input stream with the one provided, returning the previous input /// stream. Future data read from this decoder will be the decompressed /// version of `r`'s data. /// /// Note that there may be currently buffered data when this function is /// called, and in that case the buffered data is discarded. pub fn reset(&mut self, r: R) -> R { super::bufread::reset_decoder_data(&mut self.inner); self.inner.get_mut().reset(r) } /// Acquires a reference to the underlying stream pub fn get_ref(&self) -> &R { self.inner.get_ref().get_ref() } /// Acquires a mutable reference to the underlying stream /// /// Note that mutation of the stream may result in surprising results if /// this encoder is continued to be used. pub fn get_mut(&mut self) -> &mut R { self.inner.get_mut().get_mut() } /// Consumes this decoder, returning the underlying reader. /// /// Note that there may be buffered bytes which are not re-acquired as part /// of this transition. It's recommended to only call this function after /// EOF has been reached. pub fn into_inner(self) -> R { self.inner.into_inner().into_inner() } /// Returns the number of bytes that the decompressor has consumed. /// /// Note that this will likely be smaller than what the decompressor /// actually read from the underlying stream due to buffering. pub fn total_in(&self) -> u64 { self.inner.total_in() } /// Returns the number of bytes that the decompressor has produced. pub fn total_out(&self) -> u64 { self.inner.total_out() } } impl Read for DeflateDecoder { fn read(&mut self, into: &mut [u8]) -> io::Result { self.inner.read(into) } } #[cfg(feature = "tokio")] impl AsyncRead for DeflateDecoder {} impl Write for DeflateDecoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.get_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.get_mut().flush() } } #[cfg(feature = "tokio")] impl AsyncWrite for DeflateDecoder { fn shutdown(&mut self) -> Poll<(), io::Error> { self.get_mut().shutdown() } } vendor/flate2-1.0.1/src/deflate/write.rs0000664000000000000000000002724613264166600016575 0ustar rootrootuse std::io::prelude::*; use std::io; #[cfg(feature = "tokio")] use futures::Poll; #[cfg(feature = "tokio")] use tokio_io::{AsyncRead, AsyncWrite}; use zio; use {Compress, Decompress}; /// A DEFLATE encoder, or compressor. /// /// This structure implements a [`Write`] interface and takes a stream of /// uncompressed data, writing the compressed data to the wrapped writer. /// /// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use flate2::Compression; /// use flate2::write::DeflateEncoder; /// /// // Vec implements Write to print the compressed bytes of sample string /// # fn main() { /// /// let mut e = DeflateEncoder::new(Vec::new(), Compression::default()); /// e.write(b"Hello World").unwrap(); /// println!("{:?}", e.finish().unwrap()); /// # } /// ``` #[derive(Debug)] pub struct DeflateEncoder { inner: zio::Writer, } impl DeflateEncoder { /// Creates a new encoder which will write compressed data to the stream /// given at the given compression level. /// /// When this encoder is dropped or unwrapped the final pieces of data will /// be flushed. pub fn new(w: W, level: ::Compression) -> DeflateEncoder { DeflateEncoder { inner: zio::Writer::new(w, Compress::new(level, false)), } } /// Acquires a reference to the underlying writer. pub fn get_ref(&self) -> &W { self.inner.get_ref() } /// Acquires a mutable reference to the underlying writer. /// /// Note that mutating the output/input state of the stream may corrupt this /// object, so care must be taken when using this method. pub fn get_mut(&mut self) -> &mut W { self.inner.get_mut() } /// Resets the state of this encoder entirely, swapping out the output /// stream for another. /// /// This function will finish encoding the current stream into the current /// output stream before swapping out the two output streams. If the stream /// cannot be finished an error is returned. /// /// After the current stream has been finished, this will reset the internal /// state of this encoder and replace the output stream with the one /// provided, returning the previous output stream. Future data written to /// this encoder will be the compressed into the stream `w` provided. /// /// # Errors /// /// This function will perform I/O to complete this stream, and any I/O /// errors which occur will be returned from this function. pub fn reset(&mut self, w: W) -> io::Result { try!(self.inner.finish()); self.inner.data.reset(); Ok(self.inner.replace(w)) } /// Attempt to finish this output stream, writing out final chunks of data. /// /// Note that this function can only be used once data has finished being /// written to the output stream. After this function is called then further /// calls to `write` may result in a panic. /// /// # Panics /// /// Attempts to write data to this stream may result in a panic after this /// function is called. /// /// # Errors /// /// This function will perform I/O to complete this stream, and any I/O /// errors which occur will be returned from this function. pub fn try_finish(&mut self) -> io::Result<()> { self.inner.finish() } /// Consumes this encoder, flushing the output stream. /// /// This will flush the underlying data stream, close off the compressed /// stream and, if successful, return the contained writer. /// /// Note that this function may not be suitable to call in a situation where /// the underlying stream is an asynchronous I/O stream. To finish a stream /// the `try_finish` (or `shutdown`) method should be used instead. To /// re-acquire ownership of a stream it is safe to call this method after /// `try_finish` or `shutdown` has returned `Ok`. /// /// # Errors /// /// This function will perform I/O to complete this stream, and any I/O /// errors which occur will be returned from this function. pub fn finish(mut self) -> io::Result { try!(self.inner.finish()); Ok(self.inner.take_inner()) } /// Consumes this encoder, flushing the output stream. /// /// This will flush the underlying data stream and then return the contained /// writer if the flush succeeded. /// The compressed stream will not closed but only flushed. This /// means that obtained byte array can by extended by another deflated /// stream. To close the stream add the two bytes 0x3 and 0x0. /// /// # Errors /// /// This function will perform I/O to complete this stream, and any I/O /// errors which occur will be returned from this function. pub fn flush_finish(mut self) -> io::Result { try!(self.inner.flush()); Ok(self.inner.take_inner()) } /// Returns the number of bytes that have been written to this compresor. /// /// Note that not all bytes written to this object may be accounted for, /// there may still be some active buffering. pub fn total_in(&self) -> u64 { self.inner.data.total_in() } /// Returns the number of bytes that the compressor has produced. /// /// Note that not all bytes may have been written yet, some may still be /// buffered. pub fn total_out(&self) -> u64 { self.inner.data.total_out() } } impl Write for DeflateEncoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.inner.write(buf) } fn flush(&mut self) -> io::Result<()> { self.inner.flush() } } #[cfg(feature = "tokio")] impl AsyncWrite for DeflateEncoder { fn shutdown(&mut self) -> Poll<(), io::Error> { try_nb!(self.inner.finish()); self.inner.get_mut().shutdown() } } impl Read for DeflateEncoder { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.get_mut().read(buf) } } #[cfg(feature = "tokio")] impl AsyncRead for DeflateEncoder {} /// A DEFLATE decoder, or decompressor. /// /// This structure implements a [`Write`] and will emit a stream of decompressed /// data when fed a stream of compressed data. /// /// [`Write`]: https://doc.rust-lang.org/std/io/trait.Read.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use std::io; /// # use flate2::Compression; /// # use flate2::write::DeflateEncoder; /// use flate2::write::DeflateDecoder; /// /// # fn main() { /// # let mut e = DeflateEncoder::new(Vec::new(), Compression::default()); /// # e.write(b"Hello World").unwrap(); /// # let bytes = e.finish().unwrap(); /// # println!("{}", decode_writer(bytes).unwrap()); /// # } /// // Uncompresses a Deflate Encoded vector of bytes and returns a string or error /// // Here Vec implements Write /// fn decode_writer(bytes: Vec) -> io::Result { /// let mut writer = Vec::new(); /// let mut deflater = DeflateDecoder::new(writer); /// deflater.write(&bytes[..])?; /// writer = deflater.finish()?; /// let return_string = String::from_utf8(writer).expect("String parsing error"); /// Ok(return_string) /// } /// ``` #[derive(Debug)] pub struct DeflateDecoder { inner: zio::Writer, } impl DeflateDecoder { /// Creates a new decoder which will write uncompressed data to the stream. /// /// When this encoder is dropped or unwrapped the final pieces of data will /// be flushed. pub fn new(w: W) -> DeflateDecoder { DeflateDecoder { inner: zio::Writer::new(w, Decompress::new(false)), } } /// Acquires a reference to the underlying writer. pub fn get_ref(&self) -> &W { self.inner.get_ref() } /// Acquires a mutable reference to the underlying writer. /// /// Note that mutating the output/input state of the stream may corrupt this /// object, so care must be taken when using this method. pub fn get_mut(&mut self) -> &mut W { self.inner.get_mut() } /// Resets the state of this decoder entirely, swapping out the output /// stream for another. /// /// This function will finish encoding the current stream into the current /// output stream before swapping out the two output streams. /// /// This will then reset the internal state of this decoder and replace the /// output stream with the one provided, returning the previous output /// stream. Future data written to this decoder will be decompressed into /// the output stream `w`. /// /// # Errors /// /// This function will perform I/O to finish the stream, and if that I/O /// returns an error then that will be returned from this function. pub fn reset(&mut self, w: W) -> io::Result { try!(self.inner.finish()); self.inner.data = Decompress::new(false); Ok(self.inner.replace(w)) } /// Attempt to finish this output stream, writing out final chunks of data. /// /// Note that this function can only be used once data has finished being /// written to the output stream. After this function is called then further /// calls to `write` may result in a panic. /// /// # Panics /// /// Attempts to write data to this stream may result in a panic after this /// function is called. /// /// # Errors /// /// This function will perform I/O to finish the stream, returning any /// errors which happen. pub fn try_finish(&mut self) -> io::Result<()> { self.inner.finish() } /// Consumes this encoder, flushing the output stream. /// /// This will flush the underlying data stream and then return the contained /// writer if the flush succeeded. /// /// Note that this function may not be suitable to call in a situation where /// the underlying stream is an asynchronous I/O stream. To finish a stream /// the `try_finish` (or `shutdown`) method should be used instead. To /// re-acquire ownership of a stream it is safe to call this method after /// `try_finish` or `shutdown` has returned `Ok`. /// /// # Errors /// /// This function will perform I/O to complete this stream, and any I/O /// errors which occur will be returned from this function. pub fn finish(mut self) -> io::Result { try!(self.inner.finish()); Ok(self.inner.take_inner()) } /// Returns the number of bytes that the decompressor has consumed for /// decompression. /// /// Note that this will likely be smaller than the number of bytes /// successfully written to this stream due to internal buffering. pub fn total_in(&self) -> u64 { self.inner.data.total_in() } /// Returns the number of bytes that the decompressor has written to its /// output stream. pub fn total_out(&self) -> u64 { self.inner.data.total_out() } } impl Write for DeflateDecoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.inner.write(buf) } fn flush(&mut self) -> io::Result<()> { self.inner.flush() } } #[cfg(feature = "tokio")] impl AsyncWrite for DeflateDecoder { fn shutdown(&mut self) -> Poll<(), io::Error> { try_nb!(self.inner.finish()); self.inner.get_mut().shutdown() } } impl Read for DeflateDecoder { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.get_mut().read(buf) } } #[cfg(feature = "tokio")] impl AsyncRead for DeflateDecoder {} vendor/flate2-1.0.1/src/ffi.rs0000664000000000000000000001716013264166600014575 0ustar rootrootpub use self::imp::*; #[cfg(feature = "zlib")] #[allow(bad_style)] mod imp { extern crate libz_sys as z; use std::mem; use std::ops::{Deref, DerefMut}; use libc::{c_int, size_t, c_ulong, c_uint, c_char}; pub use self::z::*; pub use self::z::deflateEnd as mz_deflateEnd; pub use self::z::inflateEnd as mz_inflateEnd; pub use self::z::deflateReset as mz_deflateReset; pub use self::z::deflate as mz_deflate; pub use self::z::inflate as mz_inflate; pub use self::z::z_stream as mz_stream; pub use self::z::Z_BLOCK as MZ_BLOCK; pub use self::z::Z_BUF_ERROR as MZ_BUF_ERROR; pub use self::z::Z_DATA_ERROR as MZ_DATA_ERROR; pub use self::z::Z_DEFAULT_STRATEGY as MZ_DEFAULT_STRATEGY; pub use self::z::Z_DEFLATED as MZ_DEFLATED; pub use self::z::Z_FINISH as MZ_FINISH; pub use self::z::Z_FULL_FLUSH as MZ_FULL_FLUSH; pub use self::z::Z_NO_FLUSH as MZ_NO_FLUSH; pub use self::z::Z_OK as MZ_OK; pub use self::z::Z_PARTIAL_FLUSH as MZ_PARTIAL_FLUSH; pub use self::z::Z_STREAM_END as MZ_STREAM_END; pub use self::z::Z_SYNC_FLUSH as MZ_SYNC_FLUSH; pub use self::z::Z_STREAM_ERROR as MZ_STREAM_ERROR; pub const MZ_DEFAULT_WINDOW_BITS: c_int = 15; pub unsafe extern fn mz_crc32(crc: c_ulong, ptr: *const u8, len: size_t) -> c_ulong { z::crc32(crc, ptr, len as c_uint) } pub unsafe extern fn mz_crc32_combine(crc1: c_ulong, crc2: c_ulong, len2: z_off_t) -> c_ulong { z::crc32_combine(crc1, crc2, len2) } const ZLIB_VERSION: &'static str = "1.2.8\0"; pub unsafe extern fn mz_deflateInit2(stream: *mut mz_stream, level: c_int, method: c_int, window_bits: c_int, mem_level: c_int, strategy: c_int) -> c_int { z::deflateInit2_(stream, level, method, window_bits, mem_level, strategy, ZLIB_VERSION.as_ptr() as *const c_char, mem::size_of::() as c_int) } pub unsafe extern fn mz_inflateInit2(stream: *mut mz_stream, window_bits: c_int) -> c_int { z::inflateInit2_(stream, window_bits, ZLIB_VERSION.as_ptr() as *const c_char, mem::size_of::() as c_int) } pub struct StreamWrapper{ inner: Box, } impl ::std::fmt::Debug for StreamWrapper{ fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error>{ write!(f, "StreamWrapper") } } impl Default for StreamWrapper { fn default() -> StreamWrapper { StreamWrapper { inner: Box::new(unsafe{ mem::zeroed() }) } } } impl Deref for StreamWrapper { type Target = mz_stream; fn deref(&self) -> &Self::Target { & *self.inner } } impl DerefMut for StreamWrapper { fn deref_mut(&mut self) -> &mut Self::Target { &mut *self.inner } } } #[cfg(all(not(feature = "zlib"), feature = "rust_backend"))] mod imp { extern crate miniz_oxide_c_api; use std::ops::{Deref, DerefMut}; pub use ffi::crc_imp::*; pub use self::miniz_oxide_c_api::*; pub use self::miniz_oxide_c_api::lib_oxide::*; #[derive(Debug, Default)] pub struct StreamWrapper { inner: mz_stream, } impl Deref for StreamWrapper { type Target = mz_stream; fn deref(&self) -> &Self::Target { &self.inner } } impl DerefMut for StreamWrapper { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.inner } } } #[cfg(all(not(feature = "zlib"), not(feature = "rust_backend")))] mod imp { extern crate miniz_sys; use std::mem; use std::ops::{Deref, DerefMut}; pub use self::miniz_sys::*; pub use ffi::crc_imp::*; pub struct StreamWrapper { inner: mz_stream, } impl ::std::fmt::Debug for StreamWrapper{ fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error>{ write!(f, "StreamWrapper") } } impl Default for StreamWrapper { fn default() -> StreamWrapper { StreamWrapper { inner : unsafe{ mem::zeroed() } } } } impl Deref for StreamWrapper { type Target = mz_stream; fn deref(&self) -> &Self::Target { &self.inner } } impl DerefMut for StreamWrapper { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.inner } } } #[cfg(not(feature = "zlib"))] mod crc_imp { use libc::{c_ulong, off_t}; pub unsafe extern fn mz_crc32_combine(crc1: c_ulong, crc2: c_ulong, len2: off_t) -> c_ulong { crc32_combine_(crc1, crc2, len2) } // gf2_matrix_times, gf2_matrix_square and crc32_combine_ are ported from // zlib. fn gf2_matrix_times(mat: &[c_ulong; 32], mut vec: c_ulong) -> c_ulong { let mut sum = 0; let mut mat_pos = 0; while vec != 0 { if vec & 1 == 1 { sum ^= mat[mat_pos]; } vec >>= 1; mat_pos += 1; } sum } fn gf2_matrix_square(square: &mut [c_ulong; 32], mat: &[c_ulong; 32]) { for n in 0..32 { square[n] = gf2_matrix_times(mat, mat[n]); } } fn crc32_combine_(mut crc1: c_ulong, crc2: c_ulong, mut len2: off_t) -> c_ulong { let mut row; let mut even = [0; 32]; /* even-power-of-two zeros operator */ let mut odd = [0; 32]; /* odd-power-of-two zeros operator */ /* degenerate case (also disallow negative lengths) */ if len2 <= 0 { return crc1; } /* put operator for one zero bit in odd */ odd[0] = 0xedb88320; /* CRC-32 polynomial */ row = 1; for n in 1..32 { odd[n] = row; row <<= 1; } /* put operator for two zero bits in even */ gf2_matrix_square(&mut even, &odd); /* put operator for four zero bits in odd */ gf2_matrix_square(&mut odd, &even); /* apply len2 zeros to crc1 (first square will put the operator for one zero byte, eight zero bits, in even) */ loop { /* apply zeros operator for this bit of len2 */ gf2_matrix_square(&mut even, &odd); if len2 & 1 == 1 { crc1 = gf2_matrix_times(&even, crc1); } len2 >>= 1; /* if no more bits set, then done */ if len2 == 0 { break; } /* another iteration of the loop with odd and even swapped */ gf2_matrix_square(&mut odd, &even); if len2 & 1 == 1 { crc1 = gf2_matrix_times(&odd, crc1); } len2 >>= 1; /* if no more bits set, then done */ if len2 == 0 { break; } } /* return combined crc */ crc1 ^= crc2; crc1 } } #[test] fn crc32_combine() { let crc32 = unsafe { imp::mz_crc32_combine(1, 2, 3) }; assert_eq!(crc32, 29518389); } vendor/flate2-1.0.1/src/gz/0000755000000000000000000000000013264166600014074 5ustar rootrootvendor/flate2-1.0.1/src/gz/bufread.rs0000664000000000000000000003670713264166600016071 0ustar rootrootuse std::cmp; use std::io::prelude::*; use std::io; use std::mem; use super::{GzBuilder, GzHeader}; use super::{FCOMMENT, FEXTRA, FHCRC, FNAME}; use Compression; use crc::CrcReader; use deflate; fn copy(into: &mut [u8], from: &[u8], pos: &mut usize) -> usize { let min = cmp::min(into.len(), from.len() - *pos); for (slot, val) in into.iter_mut().zip(from[*pos..*pos + min].iter()) { *slot = *val; } *pos += min; return min; } fn corrupt() -> io::Error { io::Error::new( io::ErrorKind::InvalidInput, "corrupt gzip stream does not have a matching checksum", ) } fn bad_header() -> io::Error { io::Error::new(io::ErrorKind::InvalidInput, "invalid gzip header") } fn read_le_u16(r: &mut R) -> io::Result { let mut b = [0; 2]; try!(r.read_exact(&mut b)); Ok((b[0] as u16) | ((b[1] as u16) << 8)) } fn read_gz_header(r: &mut R) -> io::Result { let mut crc_reader = CrcReader::new(r); let mut header = [0; 10]; try!(crc_reader.read_exact(&mut header)); let id1 = header[0]; let id2 = header[1]; if id1 != 0x1f || id2 != 0x8b { return Err(bad_header()); } let cm = header[2]; if cm != 8 { return Err(bad_header()); } let flg = header[3]; let mtime = ((header[4] as u32) << 0) | ((header[5] as u32) << 8) | ((header[6] as u32) << 16) | ((header[7] as u32) << 24); let _xfl = header[8]; let os = header[9]; let extra = if flg & FEXTRA != 0 { let xlen = try!(read_le_u16(&mut crc_reader)); let mut extra = vec![0; xlen as usize]; try!(crc_reader.read_exact(&mut extra)); Some(extra) } else { None }; let filename = if flg & FNAME != 0 { // wow this is slow let mut b = Vec::new(); for byte in crc_reader.by_ref().bytes() { let byte = try!(byte); if byte == 0 { break; } b.push(byte); } Some(b) } else { None }; let comment = if flg & FCOMMENT != 0 { // wow this is slow let mut b = Vec::new(); for byte in crc_reader.by_ref().bytes() { let byte = try!(byte); if byte == 0 { break; } b.push(byte); } Some(b) } else { None }; if flg & FHCRC != 0 { let calced_crc = crc_reader.crc().sum() as u16; let stored_crc = try!(read_le_u16(&mut crc_reader)); if calced_crc != stored_crc { return Err(corrupt()); } } Ok(GzHeader { extra: extra, filename: filename, comment: comment, operating_system: os, mtime: mtime, }) } /// A gzip streaming encoder /// /// This structure exposes a [`BufRead`] interface that will read uncompressed data /// from the underlying reader and expose the compressed version as a [`BufRead`] /// interface. /// /// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use std::io; /// use flate2::Compression; /// use flate2::bufread::GzEncoder; /// use std::fs::File; /// use std::io::BufReader; /// /// // Opens sample file, compresses the contents and returns a Vector or error /// // File wrapped in a BufReader implements BufRead /// /// fn open_hello_world() -> io::Result> { /// let f = File::open("examples/hello_world.txt")?; /// let b = BufReader::new(f); /// let mut gz = GzEncoder::new(b, Compression::fast()); /// let mut buffer = Vec::new(); /// gz.read_to_end(&mut buffer)?; /// Ok(buffer) /// } /// ``` #[derive(Debug)] pub struct GzEncoder { inner: deflate::bufread::DeflateEncoder>, header: Vec, pos: usize, eof: bool, } pub fn gz_encoder(header: Vec, r: R, lvl: Compression) -> GzEncoder { let crc = CrcReader::new(r); GzEncoder { inner: deflate::bufread::DeflateEncoder::new(crc, lvl), header: header, pos: 0, eof: false, } } impl GzEncoder { /// Creates a new encoder which will use the given compression level. /// /// The encoder is not configured specially for the emitted header. For /// header configuration, see the `GzBuilder` type. /// /// The data read from the stream `r` will be compressed and available /// through the returned reader. pub fn new(r: R, level: Compression) -> GzEncoder { GzBuilder::new().buf_read(r, level) } fn read_footer(&mut self, into: &mut [u8]) -> io::Result { if self.pos == 8 { return Ok(0); } let crc = self.inner.get_ref().crc(); let ref arr = [ (crc.sum() >> 0) as u8, (crc.sum() >> 8) as u8, (crc.sum() >> 16) as u8, (crc.sum() >> 24) as u8, (crc.amount() >> 0) as u8, (crc.amount() >> 8) as u8, (crc.amount() >> 16) as u8, (crc.amount() >> 24) as u8, ]; Ok(copy(into, arr, &mut self.pos)) } } impl GzEncoder { /// Acquires a reference to the underlying reader. pub fn get_ref(&self) -> &R { self.inner.get_ref().get_ref() } /// Acquires a mutable reference to the underlying reader. /// /// Note that mutation of the reader may result in surprising results if /// this encoder is continued to be used. pub fn get_mut(&mut self) -> &mut R { self.inner.get_mut().get_mut() } /// Returns the underlying stream, consuming this encoder pub fn into_inner(self) -> R { self.inner.into_inner().into_inner() } } impl Read for GzEncoder { fn read(&mut self, mut into: &mut [u8]) -> io::Result { let mut amt = 0; if self.eof { return self.read_footer(into); } else if self.pos < self.header.len() { amt += copy(into, &self.header, &mut self.pos); if amt == into.len() { return Ok(amt); } let tmp = into; into = &mut tmp[amt..]; } match try!(self.inner.read(into)) { 0 => { self.eof = true; self.pos = 0; self.read_footer(into) } n => Ok(amt + n), } } } impl Write for GzEncoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.get_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.get_mut().flush() } } /// A gzip streaming decoder /// /// This structure exposes a [`ReadBuf`] interface that will consume compressed /// data from the underlying reader and emit uncompressed data. /// /// [`ReadBuf`]: https://doc.rust-lang.org/std/io/trait.BufRead.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use std::io; /// # use flate2::Compression; /// # use flate2::write::GzEncoder; /// use flate2::bufread::GzDecoder; /// /// # fn main() { /// # let mut e = GzEncoder::new(Vec::new(), Compression::default()); /// # e.write(b"Hello World").unwrap(); /// # let bytes = e.finish().unwrap(); /// # println!("{}", decode_reader(bytes).unwrap()); /// # } /// # /// // Uncompresses a Gz Encoded vector of bytes and returns a string or error /// // Here &[u8] implements BufRead /// /// fn decode_reader(bytes: Vec) -> io::Result { /// let mut gz = GzDecoder::new(&bytes[..]); /// let mut s = String::new(); /// gz.read_to_string(&mut s)?; /// Ok(s) /// } /// ``` #[derive(Debug)] pub struct GzDecoder { inner: CrcReader>, header: io::Result, finished: bool, } impl GzDecoder { /// Creates a new decoder from the given reader, immediately parsing the /// gzip header. pub fn new(mut r: R) -> GzDecoder { let header = read_gz_header(&mut r); let flate = deflate::bufread::DeflateDecoder::new(r); GzDecoder { inner: CrcReader::new(flate), header: header, finished: false, } } fn finish(&mut self) -> io::Result<()> { if self.finished { return Ok(()); } let ref mut buf = [0u8; 8]; { let mut len = 0; while len < buf.len() { match try!(self.inner.get_mut().get_mut().read(&mut buf[len..])) { 0 => return Err(corrupt()), n => len += n, } } } let crc = ((buf[0] as u32) << 0) | ((buf[1] as u32) << 8) | ((buf[2] as u32) << 16) | ((buf[3] as u32) << 24); let amt = ((buf[4] as u32) << 0) | ((buf[5] as u32) << 8) | ((buf[6] as u32) << 16) | ((buf[7] as u32) << 24); if crc != self.inner.crc().sum() as u32 { return Err(corrupt()); } if amt != self.inner.crc().amount() { return Err(corrupt()); } self.finished = true; Ok(()) } } impl GzDecoder { /// Returns the header associated with this stream, if it was valid pub fn header(&self) -> Option<&GzHeader> { self.header.as_ref().ok() } /// Acquires a reference to the underlying reader. pub fn get_ref(&self) -> &R { self.inner.get_ref().get_ref() } /// Acquires a mutable reference to the underlying stream. /// /// Note that mutation of the stream may result in surprising results if /// this encoder is continued to be used. pub fn get_mut(&mut self) -> &mut R { self.inner.get_mut().get_mut() } /// Consumes this decoder, returning the underlying reader. pub fn into_inner(self) -> R { self.inner.into_inner().into_inner() } } impl Read for GzDecoder { fn read(&mut self, into: &mut [u8]) -> io::Result { if let Err(ref mut e) = self.header { let another_error = io::ErrorKind::Other.into(); return Err(mem::replace(e, another_error)) } match try!(self.inner.read(into)) { 0 => { try!(self.finish()); Ok(0) } n => Ok(n), } } } impl Write for GzDecoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.get_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.get_mut().flush() } } /// A gzip streaming decoder that decodes all members of a multistream /// /// A gzip member consists of a header, compressed data and a trailer. The [gzip /// specification](https://tools.ietf.org/html/rfc1952), however, allows multiple /// gzip members to be joined in a single stream. `MultiGzDecoder` will /// decode all consecutive members while `GzDecoder` will only decompress /// the first gzip member. The multistream format is commonly used in /// bioinformatics, for example when using the BGZF compressed data. /// /// This structure exposes a [`BufRead`] interface that will consume all gzip members /// from the underlying reader and emit uncompressed data. /// /// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use std::io; /// # use flate2::Compression; /// # use flate2::write::GzEncoder; /// use flate2::bufread::MultiGzDecoder; /// /// # fn main() { /// # let mut e = GzEncoder::new(Vec::new(), Compression::default()); /// # e.write(b"Hello World").unwrap(); /// # let bytes = e.finish().unwrap(); /// # println!("{}", decode_reader(bytes).unwrap()); /// # } /// # /// // Uncompresses a Gz Encoded vector of bytes and returns a string or error /// // Here &[u8] implements BufRead /// /// fn decode_reader(bytes: Vec) -> io::Result { /// let mut gz = MultiGzDecoder::new(&bytes[..]); /// let mut s = String::new(); /// gz.read_to_string(&mut s)?; /// Ok(s) /// } /// ``` #[derive(Debug)] pub struct MultiGzDecoder { inner: CrcReader>, header: io::Result, finished: bool, } impl MultiGzDecoder { /// Creates a new decoder from the given reader, immediately parsing the /// (first) gzip header. If the gzip stream contains multiple members all will /// be decoded. pub fn new(mut r: R) -> MultiGzDecoder { let header = read_gz_header(&mut r); let flate = deflate::bufread::DeflateDecoder::new(r); MultiGzDecoder { inner: CrcReader::new(flate), header: header, finished: false, } } fn finish_member(&mut self) -> io::Result { if self.finished { return Ok(0); } let ref mut buf = [0u8; 8]; { let mut len = 0; while len < buf.len() { match try!(self.inner.get_mut().get_mut().read(&mut buf[len..])) { 0 => return Err(corrupt()), n => len += n, } } } let crc = ((buf[0] as u32) << 0) | ((buf[1] as u32) << 8) | ((buf[2] as u32) << 16) | ((buf[3] as u32) << 24); let amt = ((buf[4] as u32) << 0) | ((buf[5] as u32) << 8) | ((buf[6] as u32) << 16) | ((buf[7] as u32) << 24); if crc != self.inner.crc().sum() as u32 { return Err(corrupt()); } if amt != self.inner.crc().amount() { return Err(corrupt()); } let remaining = match self.inner.get_mut().get_mut().fill_buf() { Ok(b) => if b.is_empty() { self.finished = true; return Ok(0); } else { b.len() }, Err(e) => return Err(e), }; let next_header = read_gz_header(self.inner.get_mut().get_mut()); drop(mem::replace(&mut self.header, next_header)); self.inner.reset(); self.inner.get_mut().reset_data(); Ok(remaining) } } impl MultiGzDecoder { /// Returns the current header associated with this stream, if it's valid pub fn header(&self) -> Option<&GzHeader> { self.header.as_ref().ok() } /// Acquires a reference to the underlying reader. pub fn get_ref(&self) -> &R { self.inner.get_ref().get_ref() } /// Acquires a mutable reference to the underlying stream. /// /// Note that mutation of the stream may result in surprising results if /// this encoder is continued to be used. pub fn get_mut(&mut self) -> &mut R { self.inner.get_mut().get_mut() } /// Consumes this decoder, returning the underlying reader. pub fn into_inner(self) -> R { self.inner.into_inner().into_inner() } } impl Read for MultiGzDecoder { fn read(&mut self, into: &mut [u8]) -> io::Result { if let Err(ref mut e) = self.header { let another_error = io::ErrorKind::Other.into(); return Err(mem::replace(e, another_error)) } match try!(self.inner.read(into)) { 0 => match self.finish_member() { Ok(0) => Ok(0), Ok(_) => self.read(into), Err(e) => Err(e), }, n => Ok(n), } } } impl Write for MultiGzDecoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.get_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.get_mut().flush() } } vendor/flate2-1.0.1/src/gz/mod.rs0000664000000000000000000002632613264166600015234 0ustar rootrootuse std::ffi::CString; use std::io::prelude::*; use std::time; use Compression; use bufreader::BufReader; pub static FHCRC: u8 = 1 << 1; pub static FEXTRA: u8 = 1 << 2; pub static FNAME: u8 = 1 << 3; pub static FCOMMENT: u8 = 1 << 4; pub mod bufread; pub mod read; pub mod write; /// A structure representing the header of a gzip stream. /// /// The header can contain metadata about the file that was compressed, if /// present. #[derive(PartialEq, Clone, Debug)] pub struct GzHeader { extra: Option>, filename: Option>, comment: Option>, operating_system: u8, mtime: u32, } impl GzHeader { /// Returns the `filename` field of this gzip stream's header, if present. pub fn filename(&self) -> Option<&[u8]> { self.filename.as_ref().map(|s| &s[..]) } /// Returns the `extra` field of this gzip stream's header, if present. pub fn extra(&self) -> Option<&[u8]> { self.extra.as_ref().map(|s| &s[..]) } /// Returns the `comment` field of this gzip stream's header, if present. pub fn comment(&self) -> Option<&[u8]> { self.comment.as_ref().map(|s| &s[..]) } /// Returns the `operating_system` field of this gzip stream's header. /// /// There are predefined values for various operating systems. /// 255 means that the value is unknown. pub fn operating_system(&self) -> u8 { self.operating_system } /// This gives the most recent modification time of the original file being compressed. /// /// The time is in Unix format, i.e., seconds since 00:00:00 GMT, Jan. 1, 1970. /// (Note that this may cause problems for MS-DOS and other systems that use local /// rather than Universal time.) If the compressed data did not come from a file, /// `mtime` is set to the time at which compression started. /// `mtime` = 0 means no time stamp is available. /// /// The usage of `mtime` is discouraged because of Year 2038 problem. pub fn mtime(&self) -> u32 { self.mtime } /// Returns the most recent modification time represented by a date-time type. /// Returns `None` if the value of the underlying counter is 0, /// indicating no time stamp is available. /// /// /// The time is measured as seconds since 00:00:00 GMT, Jan. 1 1970. /// See [`mtime`](#method.mtime) for more detail. pub fn mtime_as_datetime(&self) -> Option { if self.mtime == 0 { None } else { let duration = time::Duration::new(u64::from(self.mtime), 0); let datetime = time::UNIX_EPOCH + duration; Some(datetime) } } } /// A builder structure to create a new gzip Encoder. /// /// This structure controls header configuration options such as the filename. /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// # use std::io; /// use std::fs::File; /// use flate2::GzBuilder; /// use flate2::Compression; /// /// // GzBuilder opens a file and writes a sample string using GzBuilder pattern /// /// # fn sample_builder() -> Result<(), io::Error> { /// let f = File::create("examples/hello_world.gz")?; /// let mut gz = GzBuilder::new() /// .filename("hello_world.txt") /// .comment("test file, please delete") /// .write(f, Compression::default()); /// gz.write(b"hello world")?; /// gz.finish()?; /// # Ok(()) /// # } /// ``` #[derive(Debug)] pub struct GzBuilder { extra: Option>, filename: Option, comment: Option, operating_system: Option, mtime: u32, } impl GzBuilder { /// Create a new blank builder with no header by default. pub fn new() -> GzBuilder { GzBuilder { extra: None, filename: None, comment: None, operating_system: None, mtime: 0, } } /// Configure the `mtime` field in the gzip header. pub fn mtime(mut self, mtime: u32) -> GzBuilder { self.mtime = mtime; self } /// Configure the `operating_system` field in the gzip header. pub fn operating_system(mut self, os: u8) -> GzBuilder { self.operating_system = Some(os); self } /// Configure the `extra` field in the gzip header. pub fn extra>>(mut self, extra: T) -> GzBuilder { self.extra = Some(extra.into()); self } /// Configure the `filename` field in the gzip header. /// /// # Panics /// /// Panics if the `filename` slice contains a zero. pub fn filename>>(mut self, filename: T) -> GzBuilder { self.filename = Some(CString::new(filename.into()).unwrap()); self } /// Configure the `comment` field in the gzip header. /// /// # Panics /// /// Panics if the `comment` slice contains a zero. pub fn comment>>(mut self, comment: T) -> GzBuilder { self.comment = Some(CString::new(comment.into()).unwrap()); self } /// Consume this builder, creating a writer encoder in the process. /// /// The data written to the returned encoder will be compressed and then /// written out to the supplied parameter `w`. pub fn write(self, w: W, lvl: Compression) -> write::GzEncoder { write::gz_encoder(self.into_header(lvl), w, lvl) } /// Consume this builder, creating a reader encoder in the process. /// /// Data read from the returned encoder will be the compressed version of /// the data read from the given reader. pub fn read(self, r: R, lvl: Compression) -> read::GzEncoder { read::gz_encoder(self.buf_read(BufReader::new(r), lvl)) } /// Consume this builder, creating a reader encoder in the process. /// /// Data read from the returned encoder will be the compressed version of /// the data read from the given reader. pub fn buf_read(self, r: R, lvl: Compression) -> bufread::GzEncoder where R: BufRead, { bufread::gz_encoder(self.into_header(lvl), r, lvl) } fn into_header(self, lvl: Compression) -> Vec { let GzBuilder { extra, filename, comment, operating_system, mtime, } = self; let mut flg = 0; let mut header = vec![0u8; 10]; match extra { Some(v) => { flg |= FEXTRA; header.push((v.len() >> 0) as u8); header.push((v.len() >> 8) as u8); header.extend(v); } None => {} } match filename { Some(filename) => { flg |= FNAME; header.extend(filename.as_bytes_with_nul().iter().map(|x| *x)); } None => {} } match comment { Some(comment) => { flg |= FCOMMENT; header.extend(comment.as_bytes_with_nul().iter().map(|x| *x)); } None => {} } header[0] = 0x1f; header[1] = 0x8b; header[2] = 8; header[3] = flg; header[4] = (mtime >> 0) as u8; header[5] = (mtime >> 8) as u8; header[6] = (mtime >> 16) as u8; header[7] = (mtime >> 24) as u8; header[8] = if lvl.0 >= Compression::best().0 { 2 } else if lvl.0 <= Compression::fast().0 { 4 } else { 0 }; // Typically this byte indicates what OS the gz stream was created on, // but in an effort to have cross-platform reproducible streams just // default this value to 255. I'm not sure that if we "correctly" set // this it'd do anything anyway... header[9] = operating_system.unwrap_or(255); return header; } } #[cfg(test)] mod tests { use std::io::prelude::*; use super::{read, write, GzBuilder}; use Compression; use rand::{thread_rng, Rng}; #[test] fn roundtrip() { let mut e = write::GzEncoder::new(Vec::new(), Compression::default()); e.write_all(b"foo bar baz").unwrap(); let inner = e.finish().unwrap(); let mut d = read::GzDecoder::new(&inner[..]); let mut s = String::new(); d.read_to_string(&mut s).unwrap(); assert_eq!(s, "foo bar baz"); } #[test] fn roundtrip_zero() { let e = write::GzEncoder::new(Vec::new(), Compression::default()); let inner = e.finish().unwrap(); let mut d = read::GzDecoder::new(&inner[..]); let mut s = String::new(); d.read_to_string(&mut s).unwrap(); assert_eq!(s, ""); } #[test] fn roundtrip_big() { let mut real = Vec::new(); let mut w = write::GzEncoder::new(Vec::new(), Compression::default()); let v = thread_rng().gen_iter::().take(1024).collect::>(); for _ in 0..200 { let to_write = &v[..thread_rng().gen_range(0, v.len())]; real.extend(to_write.iter().map(|x| *x)); w.write_all(to_write).unwrap(); } let result = w.finish().unwrap(); let mut r = read::GzDecoder::new(&result[..]); let mut v = Vec::new(); r.read_to_end(&mut v).unwrap(); assert!(v == real); } #[test] fn roundtrip_big2() { let v = thread_rng() .gen_iter::() .take(1024 * 1024) .collect::>(); let mut r = read::GzDecoder::new(read::GzEncoder::new(&v[..], Compression::default())); let mut res = Vec::new(); r.read_to_end(&mut res).unwrap(); assert!(res == v); } #[test] fn fields() { let r = vec![0, 2, 4, 6]; let e = GzBuilder::new() .filename("foo.rs") .comment("bar") .extra(vec![0, 1, 2, 3]) .read(&r[..], Compression::default()); let mut d = read::GzDecoder::new(e); assert_eq!(d.header().unwrap().filename(), Some(&b"foo.rs"[..])); assert_eq!(d.header().unwrap().comment(), Some(&b"bar"[..])); assert_eq!(d.header().unwrap().extra(), Some(&b"\x00\x01\x02\x03"[..])); let mut res = Vec::new(); d.read_to_end(&mut res).unwrap(); assert_eq!(res, vec![0, 2, 4, 6]); } #[test] fn keep_reading_after_end() { let mut e = write::GzEncoder::new(Vec::new(), Compression::default()); e.write_all(b"foo bar baz").unwrap(); let inner = e.finish().unwrap(); let mut d = read::GzDecoder::new(&inner[..]); let mut s = String::new(); d.read_to_string(&mut s).unwrap(); assert_eq!(s, "foo bar baz"); d.read_to_string(&mut s).unwrap(); assert_eq!(s, "foo bar baz"); } #[test] fn qc_reader() { ::quickcheck::quickcheck(test as fn(_) -> _); fn test(v: Vec) -> bool { let r = read::GzEncoder::new(&v[..], Compression::default()); let mut r = read::GzDecoder::new(r); let mut v2 = Vec::new(); r.read_to_end(&mut v2).unwrap(); v == v2 } } #[test] fn flush_after_write() { let mut f = write::GzEncoder::new(Vec::new(), Compression::default()); write!(f, "Hello world").unwrap(); f.flush().unwrap(); } } vendor/flate2-1.0.1/src/gz/read.rs0000664000000000000000000001774513264166600015375 0ustar rootrootuse std::io::prelude::*; use std::io; use super::{GzBuilder, GzHeader}; use Compression; use bufreader::BufReader; use super::bufread; /// A gzip streaming encoder /// /// This structure exposes a [`Read`] interface that will read uncompressed data /// from the underlying reader and expose the compressed version as a [`Read`] /// interface. /// /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use std::io; /// use flate2::Compression; /// use flate2::read::GzEncoder; /// /// // Return a vector containing the GZ compressed version of hello world /// /// fn gzencode_hello_world() -> io::Result> { /// let mut ret_vec = [0;100]; /// let bytestring = b"hello world"; /// let mut gz = GzEncoder::new(&bytestring[..], Compression::fast()); /// let count = gz.read(&mut ret_vec)?; /// Ok(ret_vec[0..count].to_vec()) /// } /// ``` #[derive(Debug)] pub struct GzEncoder { inner: bufread::GzEncoder>, } pub fn gz_encoder(inner: bufread::GzEncoder>) -> GzEncoder { GzEncoder { inner: inner } } impl GzEncoder { /// Creates a new encoder which will use the given compression level. /// /// The encoder is not configured specially for the emitted header. For /// header configuration, see the `GzBuilder` type. /// /// The data read from the stream `r` will be compressed and available /// through the returned reader. pub fn new(r: R, level: Compression) -> GzEncoder { GzBuilder::new().read(r, level) } } impl GzEncoder { /// Acquires a reference to the underlying reader. pub fn get_ref(&self) -> &R { self.inner.get_ref().get_ref() } /// Acquires a mutable reference to the underlying reader. /// /// Note that mutation of the reader may result in surprising results if /// this encoder is continued to be used. pub fn get_mut(&mut self) -> &mut R { self.inner.get_mut().get_mut() } /// Returns the underlying stream, consuming this encoder pub fn into_inner(self) -> R { self.inner.into_inner().into_inner() } } impl Read for GzEncoder { fn read(&mut self, into: &mut [u8]) -> io::Result { self.inner.read(into) } } impl Write for GzEncoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.get_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.get_mut().flush() } } /// A gzip streaming decoder /// /// This structure exposes a [`Read`] interface that will consume compressed /// data from the underlying reader and emit uncompressed data. /// /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html /// /// # Examples /// /// ``` /// /// use std::io::prelude::*; /// use std::io; /// # use flate2::Compression; /// # use flate2::write::GzEncoder; /// use flate2::read::GzDecoder; /// /// # fn main() { /// # let mut e = GzEncoder::new(Vec::new(), Compression::default()); /// # e.write(b"Hello World").unwrap(); /// # let bytes = e.finish().unwrap(); /// # println!("{}", decode_reader(bytes).unwrap()); /// # } /// # /// // Uncompresses a Gz Encoded vector of bytes and returns a string or error /// // Here &[u8] implements Read /// /// fn decode_reader(bytes: Vec) -> io::Result { /// let mut gz = GzDecoder::new(&bytes[..]); /// let mut s = String::new(); /// gz.read_to_string(&mut s)?; /// Ok(s) /// } /// ``` #[derive(Debug)] pub struct GzDecoder { inner: bufread::GzDecoder>, } impl GzDecoder { /// Creates a new decoder from the given reader, immediately parsing the /// gzip header. pub fn new(r: R) -> GzDecoder { GzDecoder { inner: bufread::GzDecoder::new(BufReader::new(r)), } } } impl GzDecoder { /// Returns the header associated with this stream, if it was valid. pub fn header(&self) -> Option<&GzHeader> { self.inner.header() } /// Acquires a reference to the underlying reader. pub fn get_ref(&self) -> &R { self.inner.get_ref().get_ref() } /// Acquires a mutable reference to the underlying stream. /// /// Note that mutation of the stream may result in surprising results if /// this encoder is continued to be used. pub fn get_mut(&mut self) -> &mut R { self.inner.get_mut().get_mut() } /// Consumes this decoder, returning the underlying reader. pub fn into_inner(self) -> R { self.inner.into_inner().into_inner() } } impl Read for GzDecoder { fn read(&mut self, into: &mut [u8]) -> io::Result { self.inner.read(into) } } impl Write for GzDecoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.get_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.get_mut().flush() } } /// A gzip streaming decoder that decodes all members of a multistream /// /// A gzip member consists of a header, compressed data and a trailer. The [gzip /// specification](https://tools.ietf.org/html/rfc1952), however, allows multiple /// gzip members to be joined in a single stream. `MultiGzDecoder` will /// decode all consecutive members while `GzDecoder` will only decompress the /// first gzip member. The multistream format is commonly used in bioinformatics, /// for example when using the BGZF compressed data. /// /// This structure exposes a [`Read`] interface that will consume all gzip members /// from the underlying reader and emit uncompressed data. /// /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use std::io; /// # use flate2::Compression; /// # use flate2::write::GzEncoder; /// use flate2::read::MultiGzDecoder; /// /// # fn main() { /// # let mut e = GzEncoder::new(Vec::new(), Compression::default()); /// # e.write(b"Hello World").unwrap(); /// # let bytes = e.finish().unwrap(); /// # println!("{}", decode_reader(bytes).unwrap()); /// # } /// # /// // Uncompresses a Gz Encoded vector of bytes and returns a string or error /// // Here &[u8] implements Read /// /// fn decode_reader(bytes: Vec) -> io::Result { /// let mut gz = MultiGzDecoder::new(&bytes[..]); /// let mut s = String::new(); /// gz.read_to_string(&mut s)?; /// Ok(s) /// } /// ``` #[derive(Debug)] pub struct MultiGzDecoder { inner: bufread::MultiGzDecoder>, } impl MultiGzDecoder { /// Creates a new decoder from the given reader, immediately parsing the /// (first) gzip header. If the gzip stream contains multiple members all will /// be decoded. pub fn new(r: R) -> MultiGzDecoder { MultiGzDecoder { inner: bufread::MultiGzDecoder::new(BufReader::new(r)), } } } impl MultiGzDecoder { /// Returns the current header associated with this stream, if it's valid. pub fn header(&self) -> Option<&GzHeader> { self.inner.header() } /// Acquires a reference to the underlying reader. pub fn get_ref(&self) -> &R { self.inner.get_ref().get_ref() } /// Acquires a mutable reference to the underlying stream. /// /// Note that mutation of the stream may result in surprising results if /// this encoder is continued to be used. pub fn get_mut(&mut self) -> &mut R { self.inner.get_mut().get_mut() } /// Consumes this decoder, returning the underlying reader. pub fn into_inner(self) -> R { self.inner.into_inner().into_inner() } } impl Read for MultiGzDecoder { fn read(&mut self, into: &mut [u8]) -> io::Result { self.inner.read(into) } } impl Write for MultiGzDecoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.get_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.get_mut().flush() } } vendor/flate2-1.0.1/src/gz/write.rs0000664000000000000000000001261413264166600015602 0ustar rootrootuse std::io::prelude::*; use std::io; #[cfg(feature = "tokio")] use futures::Poll; #[cfg(feature = "tokio")] use tokio_io::{AsyncRead, AsyncWrite}; use super::GzBuilder; use {Compress, Compression}; use crc::Crc; use zio; /// A gzip streaming encoder /// /// This structure exposes a [`Write`] interface that will emit compressed data /// to the underlying writer `W`. /// /// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use flate2::Compression; /// use flate2::write::GzEncoder; /// /// // Vec implements Write to print the compressed bytes of sample string /// # fn main() { /// /// let mut e = GzEncoder::new(Vec::new(), Compression::default()); /// e.write(b"Hello World").unwrap(); /// println!("{:?}", e.finish().unwrap()); /// # } /// ``` #[derive(Debug)] pub struct GzEncoder { inner: zio::Writer, crc: Crc, crc_bytes_written: usize, header: Vec, } pub fn gz_encoder(header: Vec, w: W, lvl: Compression) -> GzEncoder { GzEncoder { inner: zio::Writer::new(w, Compress::new(lvl, false)), crc: Crc::new(), header: header, crc_bytes_written: 0, } } impl GzEncoder { /// Creates a new encoder which will use the given compression level. /// /// The encoder is not configured specially for the emitted header. For /// header configuration, see the `GzBuilder` type. /// /// The data written to the returned encoder will be compressed and then /// written to the stream `w`. pub fn new(w: W, level: Compression) -> GzEncoder { GzBuilder::new().write(w, level) } /// Acquires a reference to the underlying writer. pub fn get_ref(&self) -> &W { self.inner.get_ref() } /// Acquires a mutable reference to the underlying writer. /// /// Note that mutation of the writer may result in surprising results if /// this encoder is continued to be used. pub fn get_mut(&mut self) -> &mut W { self.inner.get_mut() } /// Attempt to finish this output stream, writing out final chunks of data. /// /// Note that this function can only be used once data has finished being /// written to the output stream. After this function is called then further /// calls to `write` may result in a panic. /// /// # Panics /// /// Attempts to write data to this stream may result in a panic after this /// function is called. /// /// # Errors /// /// This function will perform I/O to complete this stream, and any I/O /// errors which occur will be returned from this function. pub fn try_finish(&mut self) -> io::Result<()> { try!(self.write_header()); try!(self.inner.finish()); while self.crc_bytes_written < 8 { let (sum, amt) = (self.crc.sum() as u32, self.crc.amount()); let buf = [ (sum >> 0) as u8, (sum >> 8) as u8, (sum >> 16) as u8, (sum >> 24) as u8, (amt >> 0) as u8, (amt >> 8) as u8, (amt >> 16) as u8, (amt >> 24) as u8, ]; let inner = self.inner.get_mut(); let n = try!(inner.write(&buf[self.crc_bytes_written..])); self.crc_bytes_written += n; } Ok(()) } /// Finish encoding this stream, returning the underlying writer once the /// encoding is done. /// /// Note that this function may not be suitable to call in a situation where /// the underlying stream is an asynchronous I/O stream. To finish a stream /// the `try_finish` (or `shutdown`) method should be used instead. To /// re-acquire ownership of a stream it is safe to call this method after /// `try_finish` or `shutdown` has returned `Ok`. /// /// # Errors /// /// This function will perform I/O to complete this stream, and any I/O /// errors which occur will be returned from this function. pub fn finish(mut self) -> io::Result { try!(self.try_finish()); Ok(self.inner.take_inner()) } fn write_header(&mut self) -> io::Result<()> { while self.header.len() > 0 { let n = try!(self.inner.get_mut().write(&self.header)); self.header.drain(..n); } Ok(()) } } impl Write for GzEncoder { fn write(&mut self, buf: &[u8]) -> io::Result { assert_eq!(self.crc_bytes_written, 0); try!(self.write_header()); let n = try!(self.inner.write(buf)); self.crc.update(&buf[..n]); Ok(n) } fn flush(&mut self) -> io::Result<()> { assert_eq!(self.crc_bytes_written, 0); try!(self.write_header()); self.inner.flush() } } #[cfg(feature = "tokio")] impl AsyncWrite for GzEncoder { fn shutdown(&mut self) -> Poll<(), io::Error> { try_nb!(self.try_finish()); self.get_mut().shutdown() } } impl Read for GzEncoder { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.get_mut().read(buf) } } #[cfg(feature = "tokio")] impl AsyncRead for GzEncoder {} impl Drop for GzEncoder { fn drop(&mut self) { if self.inner.is_present() { let _ = self.try_finish(); } } } vendor/flate2-1.0.1/src/lib.rs0000664000000000000000000001522413264166600014576 0ustar rootroot//! A DEFLATE-based stream compression/decompression library //! //! This library is meant to supplement/replace the //! `flate` library that was previously part of the standard rust distribution //! providing a streaming encoder/decoder rather than purely //! an in-memory encoder/decoder. //! //! Like with [`flate`], flate2 is based on [`miniz.c`][1] //! //! [1]: https://github.com/richgel999/miniz //! [`flate`]: https://github.com/rust-lang/rust/tree/1.19.0/src/libflate //! //! # Organization //! //! This crate consists mainly of three modules, [`read`], [`write`], and //! [`bufread`]. Each module contains a number of types used to encode and //! decode various streams of data. All types in the [`write`] module work on //! instances of [`Write`][write], whereas all types in the [`read`] module work on //! instances of [`Read`][read] and [`bufread`] works with [`BufRead`][bufread]. //! //! ``` //! use flate2::write::GzEncoder; //! use flate2::Compression; //! use std::io; //! use std::io::prelude::*; //! //! # fn main() { let _ = run(); } //! # fn run() -> io::Result<()> { //! let mut encoder = GzEncoder::new(Vec::new(), Compression::default()); //! encoder.write(b"Example")?; //! # Ok(()) //! # } //! ``` //! //! //! Other various types are provided at the top-level of the crate for //! management and dealing with encoders/decoders. Also note that types which //! operate over a specific trait often implement the mirroring trait as well. //! For example a `flate2::read::DeflateDecoder` *also* implements the //! `Write` trait if `T: Write`. That is, the "dual trait" is forwarded directly //! to the underlying object if available. //! //! [`read`]: read/index.html //! [`bufread`]: bufread/index.html //! [`write`]: write/index.html //! [read]: https://doc.rust-lang.org/std/io/trait.Read.html //! [write]: https://doc.rust-lang.org/std/io/trait.Write.html //! [bufread]: https://doc.rust-lang.org/std/io/trait.BufRead.html //! //! # Async I/O //! //! This crate optionally can support async I/O streams with the [Tokio stack] via //! the `tokio` feature of this crate: //! //! [Tokio stack]: https://tokio.rs/ //! //! ```toml //! flate2 = { version = "0.2", features = ["tokio"] } //! ``` //! //! All methods are internally capable of working with streams that may return //! [`ErrorKind::WouldBlock`] when they're not ready to perform the particular //! operation. //! //! [`ErrorKind::WouldBlock`]: https://doc.rust-lang.org/std/io/enum.ErrorKind.html //! //! Note that care needs to be taken when using these objects, however. The //! Tokio runtime, in particular, requires that data is fully flushed before //! dropping streams. For compatibility with blocking streams all streams are //! flushed/written when they are dropped, and this is not always a suitable //! time to perform I/O. If I/O streams are flushed before drop, however, then //! these operations will be a noop. #![doc(html_root_url = "https://docs.rs/flate2/0.2")] #![deny(missing_docs)] #![deny(missing_debug_implementations)] #![allow(trivial_numeric_casts)] #![cfg_attr(test, deny(warnings))] #[cfg(feature = "tokio")] extern crate futures; extern crate libc; #[cfg(test)] extern crate quickcheck; #[cfg(test)] extern crate rand; #[cfg(feature = "tokio")] #[macro_use] extern crate tokio_io; pub use gz::GzBuilder; pub use gz::GzHeader; pub use mem::{Compress, CompressError, DecompressError, Decompress, Status}; pub use mem::{FlushCompress, FlushDecompress}; pub use crc::{Crc, CrcReader}; mod bufreader; mod crc; mod deflate; mod ffi; mod gz; mod zio; mod mem; mod zlib; /// Types which operate over [`Read`] streams, both encoders and decoders for /// various formats. /// /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html pub mod read { pub use deflate::read::DeflateEncoder; pub use deflate::read::DeflateDecoder; pub use zlib::read::ZlibEncoder; pub use zlib::read::ZlibDecoder; pub use gz::read::GzEncoder; pub use gz::read::GzDecoder; pub use gz::read::MultiGzDecoder; } /// Types which operate over [`Write`] streams, both encoders and decoders for /// various formats. /// /// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html pub mod write { pub use deflate::write::DeflateEncoder; pub use deflate::write::DeflateDecoder; pub use zlib::write::ZlibEncoder; pub use zlib::write::ZlibDecoder; pub use gz::write::GzEncoder; } /// Types which operate over [`BufRead`] streams, both encoders and decoders for /// various formats. /// /// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html pub mod bufread { pub use deflate::bufread::DeflateEncoder; pub use deflate::bufread::DeflateDecoder; pub use zlib::bufread::ZlibEncoder; pub use zlib::bufread::ZlibDecoder; pub use gz::bufread::GzEncoder; pub use gz::bufread::GzDecoder; pub use gz::bufread::MultiGzDecoder; } fn _assert_send_sync() { fn _assert_send_sync() {} _assert_send_sync::>(); _assert_send_sync::>(); _assert_send_sync::>(); _assert_send_sync::>(); _assert_send_sync::>(); _assert_send_sync::>(); _assert_send_sync::>(); _assert_send_sync::>>(); _assert_send_sync::>>(); _assert_send_sync::>>(); _assert_send_sync::>>(); _assert_send_sync::>>(); } /// When compressing data, the compression level can be specified by a value in /// this enum. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub struct Compression(u32); impl Compression { /// Creates a new description of the compression level with an explicitly /// specified integer. /// /// The integer here is typically on a scale of 0-9 where 0 means "no /// compression" and 9 means "take as long as you'd like". pub fn new(level: u32) -> Compression { Compression(level) } /// No compression is to be performed, this may actually inflate data /// slightly when encoding. pub fn none() -> Compression { Compression(0) } /// Optimize for the best speed of encoding. pub fn fast() -> Compression { Compression(1) } /// Optimize for the size of data being encoded. pub fn best() -> Compression { Compression(9) } /// Returns an integer representing the compression level, typically on a /// scale of 0-9 pub fn level(&self) -> u32 { self.0 } } impl Default for Compression { fn default() -> Compression { Compression(6) } } vendor/flate2-1.0.1/src/mem.rs0000664000000000000000000005137313264166600014613 0ustar rootrootuse std::error::Error; use std::fmt; use std::io; use std::marker; use std::slice; use libc::{c_int, c_uint}; use Compression; use ffi; /// Raw in-memory compression stream for blocks of data. /// /// This type is the building block for the I/O streams in the rest of this /// crate. It requires more management than the [`Read`]/[`Write`] API but is /// maximally flexible in terms of accepting input from any source and being /// able to produce output to any memory location. /// /// It is recommended to use the I/O stream adaptors over this type as they're /// easier to use. /// /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html /// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html #[derive(Debug)] pub struct Compress { inner: Stream, } /// Raw in-memory decompression stream for blocks of data. /// /// This type is the building block for the I/O streams in the rest of this /// crate. It requires more management than the [`Read`]/[`Write`] API but is /// maximally flexible in terms of accepting input from any source and being /// able to produce output to any memory location. /// /// It is recommended to use the I/O stream adaptors over this type as they're /// easier to use. /// /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html /// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html #[derive(Debug)] pub struct Decompress { inner: Stream, } #[derive(Debug)] struct Stream { stream_wrapper: ffi::StreamWrapper, total_in: u64, total_out: u64, _marker: marker::PhantomData, } unsafe impl Send for Stream {} unsafe impl Sync for Stream {} trait Direction { unsafe fn destroy(stream: *mut ffi::mz_stream) -> c_int; } #[derive(Debug)] enum DirCompress {} #[derive(Debug)] enum DirDecompress {} #[derive(Copy, Clone, PartialEq, Eq, Debug)] /// Values which indicate the form of flushing to be used when compressing /// in-memory data. pub enum FlushCompress { /// A typical parameter for passing to compression/decompression functions, /// this indicates that the underlying stream to decide how much data to /// accumulate before producing output in order to maximize compression. None = ffi::MZ_NO_FLUSH as isize, /// All pending output is flushed to the output buffer and the output is /// aligned on a byte boundary so that the decompressor can get all input /// data available so far. /// /// Flushing may degrade compression for some compression algorithms and so /// it should only be used when necessary. This will complete the current /// deflate block and follow it with an empty stored block. Sync = ffi::MZ_SYNC_FLUSH as isize, /// All pending output is flushed to the output buffer, but the output is /// not aligned to a byte boundary. /// /// All of the input data so far will be available to the decompressor (as /// with `Flush::Sync`. This completes the current deflate block and follows /// it with an empty fixed codes block that is 10 bites long, and it assures /// that enough bytes are output in order for the decompessor to finish the /// block before the empty fixed code block. Partial = ffi::MZ_PARTIAL_FLUSH as isize, /// All output is flushed as with `Flush::Sync` and the compression state is /// reset so decompression can restart from this point if previous /// compressed data has been damaged or if random access is desired. /// /// Using this option too often can seriously degrade compression. Full = ffi::MZ_FULL_FLUSH as isize, /// Pending input is processed and pending output is flushed. /// /// The return value may indicate that the stream is not yet done and more /// data has yet to be processed. Finish = ffi::MZ_FINISH as isize, #[doc(hidden)] _Nonexhaustive } #[derive(Copy, Clone, PartialEq, Eq, Debug)] /// Values which indicate the form of flushing to be used when /// decompressing in-memory data. pub enum FlushDecompress { /// A typical parameter for passing to compression/decompression functions, /// this indicates that the underlying stream to decide how much data to /// accumulate before producing output in order to maximize compression. None = ffi::MZ_NO_FLUSH as isize, /// All pending output is flushed to the output buffer and the output is /// aligned on a byte boundary so that the decompressor can get all input /// data available so far. /// /// Flushing may degrade compression for some compression algorithms and so /// it should only be used when necessary. This will complete the current /// deflate block and follow it with an empty stored block. Sync = ffi::MZ_SYNC_FLUSH as isize, /// Pending input is processed and pending output is flushed. /// /// The return value may indicate that the stream is not yet done and more /// data has yet to be processed. Finish = ffi::MZ_FINISH as isize, #[doc(hidden)] _Nonexhaustive } /// Error returned when a decompression object finds that the input stream of /// bytes was not a valid input stream of bytes. #[derive(Debug)] pub struct DecompressError(()); /// Error returned when a compression object is used incorrectly or otherwise /// generates an error. #[derive(Debug)] pub struct CompressError(()); /// Possible status results of compressing some data or successfully /// decompressing a block of data. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum Status { /// Indicates success. /// /// Means that more input may be needed but isn't available /// and/or there's more output to be written but the output buffer is full. Ok, /// Indicates that forward progress is not possible due to input or output /// buffers being empty. /// /// For compression it means the input buffer needs some more data or the /// output buffer needs to be freed up before trying again. /// /// For decompression this means that more input is needed to continue or /// the output buffer isn't large enough to contain the result. The function /// can be called again after fixing both. BufError, /// Indicates that all input has been consumed and all output bytes have /// been written. Decompression/compression should not be called again. /// /// For decompression with zlib streams the adler-32 of the decompressed /// data has also been verified. StreamEnd, } impl Compress { /// Creates a new object ready for compressing data that it's given. /// /// The `level` argument here indicates what level of compression is going /// to be performed, and the `zlib_header` argument indicates whether the /// output data should have a zlib header or not. pub fn new(level: Compression, zlib_header: bool) -> Compress { unsafe { let mut state = ffi::StreamWrapper::default(); let ret = ffi::mz_deflateInit2(&mut *state, level.0 as c_int, ffi::MZ_DEFLATED, if zlib_header { ffi::MZ_DEFAULT_WINDOW_BITS } else { -ffi::MZ_DEFAULT_WINDOW_BITS }, 9, ffi::MZ_DEFAULT_STRATEGY); debug_assert_eq!(ret, 0); Compress { inner: Stream { stream_wrapper: state, total_in: 0, total_out: 0, _marker: marker::PhantomData, }, } } } /// Returns the total number of input bytes which have been processed by /// this compression object. pub fn total_in(&self) -> u64 { self.inner.total_in } /// Returns the total number of output bytes which have been produced by /// this compression object. pub fn total_out(&self) -> u64 { self.inner.total_out } /// Quickly resets this compressor without having to reallocate anything. /// /// This is equivalent to dropping this object and then creating a new one. pub fn reset(&mut self) { let rc = unsafe { ffi::mz_deflateReset(&mut *self.inner.stream_wrapper) }; assert_eq!(rc, ffi::MZ_OK); self.inner.total_in = 0; self.inner.total_out = 0; } /// Compresses the input data into the output, consuming only as much /// input as needed and writing as much output as possible. /// /// The flush option can be any of the available `FlushCompress` parameters. /// /// To learn how much data was consumed or how much output was produced, use /// the `total_in` and `total_out` functions before/after this is called. pub fn compress(&mut self, input: &[u8], output: &mut [u8], flush: FlushCompress) -> Result { let raw = &mut *self.inner.stream_wrapper; raw.next_in = input.as_ptr() as *mut _; raw.avail_in = input.len() as c_uint; raw.next_out = output.as_mut_ptr(); raw.avail_out = output.len() as c_uint; let rc = unsafe { ffi::mz_deflate(raw, flush as c_int) }; // Unfortunately the total counters provided by zlib might be only // 32 bits wide and overflow while processing large amounts of data. self.inner.total_in += (raw.next_in as usize - input.as_ptr() as usize) as u64; self.inner.total_out += (raw.next_out as usize - output.as_ptr() as usize) as u64; match rc { ffi::MZ_OK => Ok(Status::Ok), ffi::MZ_BUF_ERROR => Ok(Status::BufError), ffi::MZ_STREAM_END => Ok(Status::StreamEnd), ffi::MZ_STREAM_ERROR => Err(CompressError(())), c => panic!("unknown return code: {}", c), } } /// Compresses the input data into the extra space of the output, consuming /// only as much input as needed and writing as much output as possible. /// /// This function has the same semantics as `compress`, except that the /// length of `vec` is managed by this function. This will not reallocate /// the vector provided or attempt to grow it, so space for the output must /// be reserved in the output vector by the caller before calling this /// function. pub fn compress_vec(&mut self, input: &[u8], output: &mut Vec, flush: FlushCompress) -> Result { let cap = output.capacity(); let len = output.len(); unsafe { let before = self.total_out(); let ret = { let ptr = output.as_mut_ptr().offset(len as isize); let out = slice::from_raw_parts_mut(ptr, cap - len); self.compress(input, out, flush) }; output.set_len((self.total_out() - before) as usize + len); return ret } } } impl Decompress { /// Creates a new object ready for decompressing data that it's given. /// /// The `zlib_header` argument indicates whether the input data is expected /// to have a zlib header or not. pub fn new(zlib_header: bool) -> Decompress { unsafe { let mut state = ffi::StreamWrapper::default(); let ret = ffi::mz_inflateInit2(&mut *state, if zlib_header { ffi::MZ_DEFAULT_WINDOW_BITS } else { -ffi::MZ_DEFAULT_WINDOW_BITS }); debug_assert_eq!(ret, 0); Decompress { inner: Stream { stream_wrapper: state, total_in: 0, total_out: 0, _marker: marker::PhantomData, }, } } } /// Returns the total number of input bytes which have been processed by /// this decompression object. pub fn total_in(&self) -> u64 { self.inner.total_in } /// Returns the total number of output bytes which have been produced by /// this decompression object. pub fn total_out(&self) -> u64 { self.inner.total_out } /// Decompresses the input data into the output, consuming only as much /// input as needed and writing as much output as possible. /// /// The flush option can be any of the available `FlushDecompress` parameters. /// /// If the first call passes `FlushDecompress::Finish` it is assumed that /// the input and output buffers are both sized large enough to decompress /// the entire stream in a single call. /// /// A flush value of `FlushDecompress::Finish` indicates that there are no /// more source bytes available beside what's already in the input buffer, /// and the output buffer is large enough to hold the rest of the /// decompressed data. /// /// To learn how much data was consumed or how much output was produced, use /// the `total_in` and `total_out` functions before/after this is called. /// /// # Errors /// /// If the input data to this instance of `Decompress` is not a valid /// zlib/deflate stream then this function may return an instance of /// `DecompressError` to indicate that the stream of input bytes is corrupted. pub fn decompress(&mut self, input: &[u8], output: &mut [u8], flush: FlushDecompress) -> Result { let raw = &mut *self.inner.stream_wrapper; raw.next_in = input.as_ptr() as *mut u8; raw.avail_in = input.len() as c_uint; raw.next_out = output.as_mut_ptr(); raw.avail_out = output.len() as c_uint; let rc = unsafe { ffi::mz_inflate(raw, flush as c_int) }; // Unfortunately the total counters provided by zlib might be only // 32 bits wide and overflow while processing large amounts of data. self.inner.total_in += (raw.next_in as usize - input.as_ptr() as usize) as u64; self.inner.total_out += (raw.next_out as usize - output.as_ptr() as usize) as u64; match rc { ffi::MZ_DATA_ERROR | ffi::MZ_STREAM_ERROR => Err(DecompressError(())), ffi::MZ_OK => Ok(Status::Ok), ffi::MZ_BUF_ERROR => Ok(Status::BufError), ffi::MZ_STREAM_END => Ok(Status::StreamEnd), c => panic!("unknown return code: {}", c), } } /// Decompresses the input data into the extra space in the output vector /// specified by `output`. /// /// This function has the same semantics as `decompress`, except that the /// length of `vec` is managed by this function. This will not reallocate /// the vector provided or attempt to grow it, so space for the output must /// be reserved in the output vector by the caller before calling this /// function. /// /// # Errors /// /// If the input data to this instance of `Decompress` is not a valid /// zlib/deflate stream then this function may return an instance of /// `DecompressError` to indicate that the stream of input bytes is corrupted. pub fn decompress_vec(&mut self, input: &[u8], output: &mut Vec, flush: FlushDecompress) -> Result { let cap = output.capacity(); let len = output.len(); unsafe { let before = self.total_out(); let ret = { let ptr = output.as_mut_ptr().offset(len as isize); let out = slice::from_raw_parts_mut(ptr, cap - len); self.decompress(input, out, flush) }; output.set_len((self.total_out() - before) as usize + len); return ret } } /// Performs the equivalent of replacing this decompression state with a /// freshly allocated copy. /// /// This function may not allocate memory, though, and attempts to reuse any /// previously existing resources. /// /// The argument provided here indicates whether the reset state will /// attempt to decode a zlib header first or not. pub fn reset(&mut self, zlib_header: bool) { self._reset(zlib_header); } #[cfg(feature = "zlib")] fn _reset(&mut self, zlib_header: bool) { let bits = if zlib_header { ffi::MZ_DEFAULT_WINDOW_BITS } else { -ffi::MZ_DEFAULT_WINDOW_BITS }; unsafe { ffi::inflateReset2(&mut *self.inner.stream_wrapper, bits); } self.inner.total_out = 0; self.inner.total_in = 0; } #[cfg(not(feature = "zlib"))] fn _reset(&mut self, zlib_header: bool) { *self = Decompress::new(zlib_header); } } impl Error for DecompressError { fn description(&self) -> &str { "deflate decompression error" } } impl From for io::Error { fn from(data: DecompressError) -> io::Error { io::Error::new(io::ErrorKind::Other, data) } } impl fmt::Display for DecompressError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.description().fmt(f) } } impl Error for CompressError { fn description(&self) -> &str { "deflate compression error" } } impl From for io::Error { fn from(data: CompressError) -> io::Error { io::Error::new(io::ErrorKind::Other, data) } } impl fmt::Display for CompressError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.description().fmt(f) } } impl Direction for DirCompress { unsafe fn destroy(stream: *mut ffi::mz_stream) -> c_int { ffi::mz_deflateEnd(stream) } } impl Direction for DirDecompress { unsafe fn destroy(stream: *mut ffi::mz_stream) -> c_int { ffi::mz_inflateEnd(stream) } } impl Drop for Stream { fn drop(&mut self) { unsafe { let _ = D::destroy(&mut *self.stream_wrapper); } } } #[cfg(test)] mod tests { use std::io::Write; use write; use {Compression, Decompress, FlushDecompress}; #[test] fn issue51() { let data = vec![ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xb3, 0xc9, 0x28, 0xc9, 0xcd, 0xb1, 0xe3, 0xe5, 0xb2, 0xc9, 0x48, 0x4d, 0x4c, 0xb1, 0xb3, 0x29, 0xc9, 0x2c, 0xc9, 0x49, 0xb5, 0x33, 0x31, 0x30, 0x51, 0xf0, 0xcb, 0x2f, 0x51, 0x70, 0xcb, 0x2f, 0xcd, 0x4b, 0xb1, 0xd1, 0x87, 0x08, 0xda, 0xe8, 0x83, 0x95, 0x00, 0x95, 0x26, 0xe5, 0xa7, 0x54, 0x2a, 0x24, 0xa5, 0x27, 0xe7, 0xe7, 0xe4, 0x17, 0xd9, 0x2a, 0x95, 0x67, 0x64, 0x96, 0xa4, 0x2a, 0x81, 0x8c, 0x48, 0x4e, 0xcd, 0x2b, 0x49, 0x2d, 0xb2, 0xb3, 0xc9, 0x30, 0x44, 0x37, 0x01, 0x28, 0x62, 0xa3, 0x0f, 0x95, 0x06, 0xd9, 0x05, 0x54, 0x04, 0xe5, 0xe5, 0xa5, 0x67, 0xe6, 0x55, 0xe8, 0x1b, 0xea, 0x99, 0xe9, 0x19, 0x21, 0xab, 0xd0, 0x07, 0xd9, 0x01, 0x32, 0x53, 0x1f, 0xea, 0x3e, 0x00, 0x94, 0x85, 0xeb, 0xe4, 0xa8, 0x00, 0x00, 0x00 ]; let mut decoded = Vec::with_capacity(data.len()*2); let mut d = Decompress::new(false); // decompressed whole deflate stream assert!(d.decompress_vec(&data[10..], &mut decoded, FlushDecompress::Finish).is_ok()); // decompress data that has nothing to do with the deflate stream (this // used to panic) drop(d.decompress_vec(&[0], &mut decoded, FlushDecompress::None)); } #[test] fn reset() { let string = "hello world".as_bytes(); let mut zlib = Vec::new(); let mut deflate = Vec::new(); let comp = Compression::default(); write::ZlibEncoder::new(&mut zlib, comp).write_all(string).unwrap(); write::DeflateEncoder::new(&mut deflate, comp).write_all(string).unwrap(); let mut dst = [0; 1024]; let mut decoder = Decompress::new(true); decoder.decompress(&zlib, &mut dst, FlushDecompress::Finish).unwrap(); assert_eq!(decoder.total_out(), string.len() as u64); assert!(dst.starts_with(string)); decoder.reset(false); decoder.decompress(&deflate, &mut dst, FlushDecompress::Finish).unwrap(); assert_eq!(decoder.total_out(), string.len() as u64); assert!(dst.starts_with(string)); } } vendor/flate2-1.0.1/src/zio.rs0000664000000000000000000001634113264166600014632 0ustar rootrootuse std::io::prelude::*; use std::io; use std::mem; use {Decompress, Compress, Status, FlushDecompress, FlushCompress, DecompressError}; #[derive(Debug)] pub struct Writer { obj: Option, pub data: D, buf: Vec, } pub trait Ops { type Flush: Flush; fn total_in(&self) -> u64; fn total_out(&self) -> u64; fn run(&mut self, input: &[u8], output: &mut [u8], flush: Self::Flush) -> Result; fn run_vec(&mut self, input: &[u8], output: &mut Vec, flush: Self::Flush) -> Result; } impl Ops for Compress { type Flush = FlushCompress; fn total_in(&self) -> u64 { self.total_in() } fn total_out(&self) -> u64 { self.total_out() } fn run(&mut self, input: &[u8], output: &mut [u8], flush: FlushCompress) -> Result { Ok(self.compress(input, output, flush).unwrap()) } fn run_vec(&mut self, input: &[u8], output: &mut Vec, flush: FlushCompress) -> Result { Ok(self.compress_vec(input, output, flush).unwrap()) } } impl Ops for Decompress { type Flush = FlushDecompress; fn total_in(&self) -> u64 { self.total_in() } fn total_out(&self) -> u64 { self.total_out() } fn run(&mut self, input: &[u8], output: &mut [u8], flush: FlushDecompress) -> Result { self.decompress(input, output, flush) } fn run_vec(&mut self, input: &[u8], output: &mut Vec, flush: FlushDecompress) -> Result { self.decompress_vec(input, output, flush) } } pub trait Flush { fn none() -> Self; fn sync() -> Self; fn finish() -> Self; } impl Flush for FlushCompress { fn none() -> Self { FlushCompress::None } fn sync() -> Self { FlushCompress::Sync } fn finish() -> Self { FlushCompress::Finish } } impl Flush for FlushDecompress { fn none() -> Self { FlushDecompress::None } fn sync() -> Self { FlushDecompress::Sync } fn finish() -> Self { FlushDecompress::Finish } } pub fn read(obj: &mut R, data: &mut D, dst: &mut [u8]) -> io::Result where R: BufRead, D: Ops { loop { let (read, consumed, ret, eof); { let input = try!(obj.fill_buf()); eof = input.is_empty(); let before_out = data.total_out(); let before_in = data.total_in(); let flush = if eof { D::Flush::finish() } else { D::Flush::none() }; ret = data.run(input, dst, flush); read = (data.total_out() - before_out) as usize; consumed = (data.total_in() - before_in) as usize; } obj.consume(consumed); match ret { // If we haven't ready any data and we haven't hit EOF yet, // then we need to keep asking for more data because if we // return that 0 bytes of data have been read then it will // be interpreted as EOF. Ok(Status::Ok) | Ok(Status::BufError) if read == 0 && !eof && dst.len() > 0 => { continue } Ok(Status::Ok) | Ok(Status::BufError) | Ok(Status::StreamEnd) => return Ok(read), Err(..) => return Err(io::Error::new(io::ErrorKind::InvalidInput, "corrupt deflate stream")) } } } impl Writer { pub fn new(w: W, d: D) -> Writer { Writer { obj: Some(w), data: d, buf: Vec::with_capacity(32 * 1024), } } pub fn finish(&mut self) -> io::Result<()> { loop { try!(self.dump()); let before = self.data.total_out(); try!(self.data.run_vec(&[], &mut self.buf, D::Flush::finish())); if before == self.data.total_out() { return Ok(()) } } } pub fn replace(&mut self, w: W) -> W { self.buf.truncate(0); mem::replace(self.get_mut(), w) } pub fn get_ref(&self) -> &W { self.obj.as_ref().unwrap() } pub fn get_mut(&mut self) -> &mut W { self.obj.as_mut().unwrap() } // Note that this should only be called if the outer object is just about // to be consumed! // // (e.g. an implementation of `into_inner`) pub fn take_inner(&mut self) -> W { self.obj.take().unwrap() } pub fn is_present(&self) -> bool { self.obj.is_some() } fn dump(&mut self) -> io::Result<()> { // TODO: should manage this buffer not with `drain` but probably more of // a deque-like strategy. while self.buf.len() > 0 { let n = try!(self.obj.as_mut().unwrap().write(&self.buf)); if n == 0 { return Err(io::ErrorKind::WriteZero.into()) } self.buf.drain(..n); } Ok(()) } } impl Write for Writer { fn write(&mut self, buf: &[u8]) -> io::Result { // miniz isn't guaranteed to actually write any of the buffer provided, // it may be in a flushing mode where it's just giving us data before // we're actually giving it any data. We don't want to spuriously return // `Ok(0)` when possible as it will cause calls to write_all() to fail. // As a result we execute this in a loop to ensure that we try our // darndest to write the data. loop { try!(self.dump()); let before_in = self.data.total_in(); let ret = self.data.run_vec(buf, &mut self.buf, D::Flush::none()); let written = (self.data.total_in() - before_in) as usize; if buf.len() > 0 && written == 0 && ret.is_ok() { continue } return match ret { Ok(Status::Ok) | Ok(Status::BufError) | Ok(Status::StreamEnd) => Ok(written), Err(..) => Err(io::Error::new(io::ErrorKind::InvalidInput, "corrupt deflate stream")) } } } fn flush(&mut self) -> io::Result<()> { self.data.run_vec(&[], &mut self.buf, D::Flush::sync()).unwrap(); // Unfortunately miniz doesn't actually tell us when we're done with // pulling out all the data from the internal stream. To remedy this we // have to continually ask the stream for more memory until it doesn't // give us a chunk of memory the same size as our own internal buffer, // at which point we assume it's reached the end. loop { try!(self.dump()); let before = self.data.total_out(); self.data.run_vec(&[], &mut self.buf, D::Flush::none()).unwrap(); if before == self.data.total_out() { break } } self.obj.as_mut().unwrap().flush() } } impl Drop for Writer { fn drop(&mut self) { if self.obj.is_some() { let _ = self.finish(); } } } vendor/flate2-1.0.1/src/zlib/0000755000000000000000000000000013264166600014414 5ustar rootrootvendor/flate2-1.0.1/src/zlib/bufread.rs0000664000000000000000000001626713264166600016410 0ustar rootrootuse std::io::prelude::*; use std::io; use std::mem; #[cfg(feature = "tokio")] use futures::Poll; #[cfg(feature = "tokio")] use tokio_io::{AsyncRead, AsyncWrite}; use zio; use {Compress, Decompress}; /// A ZLIB encoder, or compressor. /// /// This structure implements a [`BufRead`] interface and will read uncompressed /// data from an underlying stream and emit a stream of compressed data. /// /// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use flate2::Compression; /// use flate2::bufread::ZlibEncoder; /// use std::fs::File; /// use std::io::BufReader; /// /// // Use a buffered file to compress contents into a Vec /// /// # fn open_hello_world() -> std::io::Result> { /// let f = File::open("examples/hello_world.txt")?; /// let b = BufReader::new(f); /// let mut z = ZlibEncoder::new(b, Compression::fast()); /// let mut buffer = Vec::new(); /// z.read_to_end(&mut buffer)?; /// # Ok(buffer) /// # } /// ``` #[derive(Debug)] pub struct ZlibEncoder { obj: R, data: Compress, } impl ZlibEncoder { /// Creates a new encoder which will read uncompressed data from the given /// stream and emit the compressed stream. pub fn new(r: R, level: ::Compression) -> ZlibEncoder { ZlibEncoder { obj: r, data: Compress::new(level, true), } } } pub fn reset_encoder_data(zlib: &mut ZlibEncoder) { zlib.data.reset() } impl ZlibEncoder { /// Resets the state of this encoder entirely, swapping out the input /// stream for another. /// /// This function will reset the internal state of this encoder and replace /// the input stream with the one provided, returning the previous input /// stream. Future data read from this encoder will be the compressed /// version of `r`'s data. pub fn reset(&mut self, r: R) -> R { reset_encoder_data(self); mem::replace(&mut self.obj, r) } /// Acquires a reference to the underlying reader pub fn get_ref(&self) -> &R { &self.obj } /// Acquires a mutable reference to the underlying stream /// /// Note that mutation of the stream may result in surprising results if /// this encoder is continued to be used. pub fn get_mut(&mut self) -> &mut R { &mut self.obj } /// Consumes this encoder, returning the underlying reader. pub fn into_inner(self) -> R { self.obj } /// Returns the number of bytes that have been read into this compressor. /// /// Note that not all bytes read from the underlying object may be accounted /// for, there may still be some active buffering. pub fn total_in(&self) -> u64 { self.data.total_in() } /// Returns the number of bytes that the compressor has produced. /// /// Note that not all bytes may have been read yet, some may still be /// buffered. pub fn total_out(&self) -> u64 { self.data.total_out() } } impl Read for ZlibEncoder { fn read(&mut self, buf: &mut [u8]) -> io::Result { zio::read(&mut self.obj, &mut self.data, buf) } } #[cfg(feature = "tokio")] impl AsyncRead for ZlibEncoder {} impl Write for ZlibEncoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.get_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.get_mut().flush() } } #[cfg(feature = "tokio")] impl AsyncWrite for ZlibEncoder { fn shutdown(&mut self) -> Poll<(), io::Error> { self.get_mut().shutdown() } } /// A ZLIB decoder, or decompressor. /// /// This structure implements a [`BufRead`] interface and takes a stream of /// compressed data as input, providing the decompressed data when read from. /// /// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use std::io; /// # use flate2::Compression; /// # use flate2::write::ZlibEncoder; /// use flate2::bufread::ZlibDecoder; /// /// # fn main() { /// # let mut e = ZlibEncoder::new(Vec::new(), Compression::default()); /// # e.write(b"Hello World").unwrap(); /// # let bytes = e.finish().unwrap(); /// # println!("{}", decode_bufreader(bytes).unwrap()); /// # } /// # /// // Uncompresses a Zlib Encoded vector of bytes and returns a string or error /// // Here &[u8] implements BufRead /// /// fn decode_bufreader(bytes: Vec) -> io::Result { /// let mut z = ZlibDecoder::new(&bytes[..]); /// let mut s = String::new(); /// z.read_to_string(&mut s)?; /// Ok(s) /// } /// ``` #[derive(Debug)] pub struct ZlibDecoder { obj: R, data: Decompress, } impl ZlibDecoder { /// Creates a new decoder which will decompress data read from the given /// stream. pub fn new(r: R) -> ZlibDecoder { ZlibDecoder { obj: r, data: Decompress::new(true), } } } pub fn reset_decoder_data(zlib: &mut ZlibDecoder) { zlib.data = Decompress::new(true); } impl ZlibDecoder { /// Resets the state of this decoder entirely, swapping out the input /// stream for another. /// /// This will reset the internal state of this decoder and replace the /// input stream with the one provided, returning the previous input /// stream. Future data read from this decoder will be the decompressed /// version of `r`'s data. pub fn reset(&mut self, r: R) -> R { reset_decoder_data(self); mem::replace(&mut self.obj, r) } /// Acquires a reference to the underlying stream pub fn get_ref(&self) -> &R { &self.obj } /// Acquires a mutable reference to the underlying stream /// /// Note that mutation of the stream may result in surprising results if /// this encoder is continued to be used. pub fn get_mut(&mut self) -> &mut R { &mut self.obj } /// Consumes this decoder, returning the underlying reader. pub fn into_inner(self) -> R { self.obj } /// Returns the number of bytes that the decompressor has consumed. /// /// Note that this will likely be smaller than what the decompressor /// actually read from the underlying stream due to buffering. pub fn total_in(&self) -> u64 { self.data.total_in() } /// Returns the number of bytes that the decompressor has produced. pub fn total_out(&self) -> u64 { self.data.total_out() } } impl Read for ZlibDecoder { fn read(&mut self, into: &mut [u8]) -> io::Result { zio::read(&mut self.obj, &mut self.data, into) } } #[cfg(feature = "tokio")] impl AsyncRead for ZlibDecoder {} impl Write for ZlibDecoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.get_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.get_mut().flush() } } #[cfg(feature = "tokio")] impl AsyncWrite for ZlibDecoder { fn shutdown(&mut self) -> Poll<(), io::Error> { self.get_mut().shutdown() } } vendor/flate2-1.0.1/src/zlib/mod.rs0000664000000000000000000001201613264166600015543 0ustar rootrootpub mod bufread; pub mod read; pub mod write; #[cfg(test)] mod tests { use std::io::prelude::*; use std::io; use rand::{thread_rng, Rng}; use zlib::{read, write}; use Compression; #[test] fn roundtrip() { let mut real = Vec::new(); let mut w = write::ZlibEncoder::new(Vec::new(), Compression::default()); let v = thread_rng().gen_iter::().take(1024).collect::>(); for _ in 0..200 { let to_write = &v[..thread_rng().gen_range(0, v.len())]; real.extend(to_write.iter().map(|x| *x)); w.write_all(to_write).unwrap(); } let result = w.finish().unwrap(); let mut r = read::ZlibDecoder::new(&result[..]); let mut ret = Vec::new(); r.read_to_end(&mut ret).unwrap(); assert!(ret == real); } #[test] fn drop_writes() { let mut data = Vec::new(); write::ZlibEncoder::new(&mut data, Compression::default()) .write_all(b"foo") .unwrap(); let mut r = read::ZlibDecoder::new(&data[..]); let mut ret = Vec::new(); r.read_to_end(&mut ret).unwrap(); assert!(ret == b"foo"); } #[test] fn total_in() { let mut real = Vec::new(); let mut w = write::ZlibEncoder::new(Vec::new(), Compression::default()); let v = thread_rng().gen_iter::().take(1024).collect::>(); for _ in 0..200 { let to_write = &v[..thread_rng().gen_range(0, v.len())]; real.extend(to_write.iter().map(|x| *x)); w.write_all(to_write).unwrap(); } let mut result = w.finish().unwrap(); let result_len = result.len(); for _ in 0..200 { result.extend(v.iter().map(|x| *x)); } let mut r = read::ZlibDecoder::new(&result[..]); let mut ret = Vec::new(); r.read_to_end(&mut ret).unwrap(); assert!(ret == real); assert_eq!(r.total_in(), result_len as u64); } #[test] fn roundtrip2() { let v = thread_rng() .gen_iter::() .take(1024 * 1024) .collect::>(); let mut r = read::ZlibDecoder::new(read::ZlibEncoder::new(&v[..], Compression::default())); let mut ret = Vec::new(); r.read_to_end(&mut ret).unwrap(); assert_eq!(ret, v); } #[test] fn roundtrip3() { let v = thread_rng() .gen_iter::() .take(1024 * 1024) .collect::>(); let mut w = write::ZlibEncoder::new(write::ZlibDecoder::new(Vec::new()), Compression::default()); w.write_all(&v).unwrap(); let w = w.finish().unwrap().finish().unwrap(); assert!(w == v); } #[test] fn reset_decoder() { let v = thread_rng() .gen_iter::() .take(1024 * 1024) .collect::>(); let mut w = write::ZlibEncoder::new(Vec::new(), Compression::default()); w.write_all(&v).unwrap(); let data = w.finish().unwrap(); { let (mut a, mut b, mut c) = (Vec::new(), Vec::new(), Vec::new()); let mut r = read::ZlibDecoder::new(&data[..]); r.read_to_end(&mut a).unwrap(); r.reset(&data); r.read_to_end(&mut b).unwrap(); let mut r = read::ZlibDecoder::new(&data[..]); r.read_to_end(&mut c).unwrap(); assert!(a == b && b == c && c == v); } { let mut w = write::ZlibDecoder::new(Vec::new()); w.write_all(&data).unwrap(); let a = w.reset(Vec::new()).unwrap(); w.write_all(&data).unwrap(); let b = w.finish().unwrap(); let mut w = write::ZlibDecoder::new(Vec::new()); w.write_all(&data).unwrap(); let c = w.finish().unwrap(); assert!(a == b && b == c && c == v); } } #[test] fn bad_input() { // regress tests: previously caused a panic on drop let mut out: Vec = Vec::new(); let data: Vec = (0..255).cycle().take(1024).collect(); let mut w = write::ZlibDecoder::new(&mut out); match w.write_all(&data[..]) { Ok(_) => panic!("Expected an error to be returned!"), Err(e) => assert_eq!(e.kind(), io::ErrorKind::InvalidInput), } } #[test] fn qc_reader() { ::quickcheck::quickcheck(test as fn(_) -> _); fn test(v: Vec) -> bool { let mut r = read::ZlibDecoder::new(read::ZlibEncoder::new(&v[..], Compression::default())); let mut v2 = Vec::new(); r.read_to_end(&mut v2).unwrap(); v == v2 } } #[test] fn qc_writer() { ::quickcheck::quickcheck(test as fn(_) -> _); fn test(v: Vec) -> bool { let mut w = write::ZlibEncoder::new(write::ZlibDecoder::new(Vec::new()), Compression::default()); w.write_all(&v).unwrap(); v == w.finish().unwrap().finish().unwrap() } } } vendor/flate2-1.0.1/src/zlib/read.rs0000664000000000000000000002016313264166600015701 0ustar rootrootuse std::io::prelude::*; use std::io; #[cfg(feature = "tokio")] use futures::Poll; #[cfg(feature = "tokio")] use tokio_io::{AsyncRead, AsyncWrite}; use bufreader::BufReader; use super::bufread; /// A ZLIB encoder, or compressor. /// /// This structure implements a [`Read`] interface and will read uncompressed /// data from an underlying stream and emit a stream of compressed data. /// /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use flate2::Compression; /// use flate2::read::ZlibEncoder; /// use std::fs::File; /// /// // Open example file and compress the contents using Read interface /// /// # fn open_hello_world() -> std::io::Result> { /// let f = File::open("examples/hello_world.txt")?; /// let mut z = ZlibEncoder::new(f, Compression::fast()); /// let mut buffer = [0;50]; /// let byte_count = z.read(&mut buffer)?; /// # Ok(buffer[0..byte_count].to_vec()) /// # } /// ``` #[derive(Debug)] pub struct ZlibEncoder { inner: bufread::ZlibEncoder>, } impl ZlibEncoder { /// Creates a new encoder which will read uncompressed data from the given /// stream and emit the compressed stream. pub fn new(r: R, level: ::Compression) -> ZlibEncoder { ZlibEncoder { inner: bufread::ZlibEncoder::new(BufReader::new(r), level), } } } impl ZlibEncoder { /// Resets the state of this encoder entirely, swapping out the input /// stream for another. /// /// This function will reset the internal state of this encoder and replace /// the input stream with the one provided, returning the previous input /// stream. Future data read from this encoder will be the compressed /// version of `r`'s data. /// /// Note that there may be currently buffered data when this function is /// called, and in that case the buffered data is discarded. pub fn reset(&mut self, r: R) -> R { super::bufread::reset_encoder_data(&mut self.inner); self.inner.get_mut().reset(r) } /// Acquires a reference to the underlying stream pub fn get_ref(&self) -> &R { self.inner.get_ref().get_ref() } /// Acquires a mutable reference to the underlying stream /// /// Note that mutation of the stream may result in surprising results if /// this encoder is continued to be used. pub fn get_mut(&mut self) -> &mut R { self.inner.get_mut().get_mut() } /// Consumes this encoder, returning the underlying reader. /// /// Note that there may be buffered bytes which are not re-acquired as part /// of this transition. It's recommended to only call this function after /// EOF has been reached. pub fn into_inner(self) -> R { self.inner.into_inner().into_inner() } /// Returns the number of bytes that have been read into this compressor. /// /// Note that not all bytes read from the underlying object may be accounted /// for, there may still be some active buffering. pub fn total_in(&self) -> u64 { self.inner.total_in() } /// Returns the number of bytes that the compressor has produced. /// /// Note that not all bytes may have been read yet, some may still be /// buffered. pub fn total_out(&self) -> u64 { self.inner.total_out() } } impl Read for ZlibEncoder { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.read(buf) } } #[cfg(feature = "tokio")] impl AsyncRead for ZlibEncoder {} impl Write for ZlibEncoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.get_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.get_mut().flush() } } #[cfg(feature = "tokio")] impl AsyncWrite for ZlibEncoder { fn shutdown(&mut self) -> Poll<(), io::Error> { self.get_mut().shutdown() } } /// A ZLIB decoder, or decompressor. /// /// This structure implements a [`Read`] interface and takes a stream of /// compressed data as input, providing the decompressed data when read from. /// /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use std::io; /// # use flate2::Compression; /// # use flate2::write::ZlibEncoder; /// use flate2::read::ZlibDecoder; /// /// # fn main() { /// # let mut e = ZlibEncoder::new(Vec::new(), Compression::default()); /// # e.write(b"Hello World").unwrap(); /// # let bytes = e.finish().unwrap(); /// # println!("{}", decode_reader(bytes).unwrap()); /// # } /// # /// // Uncompresses a Zlib Encoded vector of bytes and returns a string or error /// // Here &[u8] implements Read /// /// fn decode_reader(bytes: Vec) -> io::Result { /// let mut z = ZlibDecoder::new(&bytes[..]); /// let mut s = String::new(); /// z.read_to_string(&mut s)?; /// Ok(s) /// } /// ``` #[derive(Debug)] pub struct ZlibDecoder { inner: bufread::ZlibDecoder>, } impl ZlibDecoder { /// Creates a new decoder which will decompress data read from the given /// stream. pub fn new(r: R) -> ZlibDecoder { ZlibDecoder::new_with_buf(r, vec![0; 32 * 1024]) } /// Same as `new`, but the intermediate buffer for data is specified. /// /// Note that the specified buffer will only be used up to its current /// length. The buffer's capacity will also not grow over time. pub fn new_with_buf(r: R, buf: Vec) -> ZlibDecoder { ZlibDecoder { inner: bufread::ZlibDecoder::new(BufReader::with_buf(buf, r)), } } } impl ZlibDecoder { /// Resets the state of this decoder entirely, swapping out the input /// stream for another. /// /// This will reset the internal state of this decoder and replace the /// input stream with the one provided, returning the previous input /// stream. Future data read from this decoder will be the decompressed /// version of `r`'s data. /// /// Note that there may be currently buffered data when this function is /// called, and in that case the buffered data is discarded. pub fn reset(&mut self, r: R) -> R { super::bufread::reset_decoder_data(&mut self.inner); self.inner.get_mut().reset(r) } /// Acquires a reference to the underlying stream pub fn get_ref(&self) -> &R { self.inner.get_ref().get_ref() } /// Acquires a mutable reference to the underlying stream /// /// Note that mutation of the stream may result in surprising results if /// this encoder is continued to be used. pub fn get_mut(&mut self) -> &mut R { self.inner.get_mut().get_mut() } /// Consumes this decoder, returning the underlying reader. /// /// Note that there may be buffered bytes which are not re-acquired as part /// of this transition. It's recommended to only call this function after /// EOF has been reached. pub fn into_inner(self) -> R { self.inner.into_inner().into_inner() } /// Returns the number of bytes that the decompressor has consumed. /// /// Note that this will likely be smaller than what the decompressor /// actually read from the underlying stream due to buffering. pub fn total_in(&self) -> u64 { self.inner.total_in() } /// Returns the number of bytes that the decompressor has produced. pub fn total_out(&self) -> u64 { self.inner.total_out() } } impl Read for ZlibDecoder { fn read(&mut self, into: &mut [u8]) -> io::Result { self.inner.read(into) } } #[cfg(feature = "tokio")] impl AsyncRead for ZlibDecoder {} impl Write for ZlibDecoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.get_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.get_mut().flush() } } #[cfg(feature = "tokio")] impl AsyncWrite for ZlibDecoder { fn shutdown(&mut self) -> Poll<(), io::Error> { self.get_mut().shutdown() } } vendor/flate2-1.0.1/src/zlib/write.rs0000664000000000000000000002663613264166600016133 0ustar rootrootuse std::io::prelude::*; use std::io; #[cfg(feature = "tokio")] use futures::Poll; #[cfg(feature = "tokio")] use tokio_io::{AsyncRead, AsyncWrite}; use zio; use {Compress, Decompress}; /// A ZLIB encoder, or compressor. /// /// This structure implements a [`Write`] interface and takes a stream of /// uncompressed data, writing the compressed data to the wrapped writer. /// /// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use flate2::Compression; /// use flate2::write::ZlibEncoder; /// /// // Vec implements Write, assigning the compressed bytes of sample string /// /// # fn zlib_encoding() -> std::io::Result<()> { /// let mut e = ZlibEncoder::new(Vec::new(), Compression::default()); /// e.write(b"Hello World")?; /// let compressed = e.finish()?; /// # Ok(()) /// # } /// ``` #[derive(Debug)] pub struct ZlibEncoder { inner: zio::Writer, } impl ZlibEncoder { /// Creates a new encoder which will write compressed data to the stream /// given at the given compression level. /// /// When this encoder is dropped or unwrapped the final pieces of data will /// be flushed. pub fn new(w: W, level: ::Compression) -> ZlibEncoder { ZlibEncoder { inner: zio::Writer::new(w, Compress::new(level, true)), } } /// Acquires a reference to the underlying writer. pub fn get_ref(&self) -> &W { self.inner.get_ref() } /// Acquires a mutable reference to the underlying writer. /// /// Note that mutating the output/input state of the stream may corrupt this /// object, so care must be taken when using this method. pub fn get_mut(&mut self) -> &mut W { self.inner.get_mut() } /// Resets the state of this encoder entirely, swapping out the output /// stream for another. /// /// This function will finish encoding the current stream into the current /// output stream before swapping out the two output streams. /// /// After the current stream has been finished, this will reset the internal /// state of this encoder and replace the output stream with the one /// provided, returning the previous output stream. Future data written to /// this encoder will be the compressed into the stream `w` provided. /// /// # Errors /// /// This function will perform I/O to complete this stream, and any I/O /// errors which occur will be returned from this function. pub fn reset(&mut self, w: W) -> io::Result { try!(self.inner.finish()); self.inner.data.reset(); Ok(self.inner.replace(w)) } /// Attempt to finish this output stream, writing out final chunks of data. /// /// Note that this function can only be used once data has finished being /// written to the output stream. After this function is called then further /// calls to `write` may result in a panic. /// /// # Panics /// /// Attempts to write data to this stream may result in a panic after this /// function is called. /// /// # Errors /// /// This function will perform I/O to complete this stream, and any I/O /// errors which occur will be returned from this function. pub fn try_finish(&mut self) -> io::Result<()> { self.inner.finish() } /// Consumes this encoder, flushing the output stream. /// /// This will flush the underlying data stream, close off the compressed /// stream and, if successful, return the contained writer. /// /// Note that this function may not be suitable to call in a situation where /// the underlying stream is an asynchronous I/O stream. To finish a stream /// the `try_finish` (or `shutdown`) method should be used instead. To /// re-acquire ownership of a stream it is safe to call this method after /// `try_finish` or `shutdown` has returned `Ok`. /// /// # Errors /// /// This function will perform I/O to complete this stream, and any I/O /// errors which occur will be returned from this function. pub fn finish(mut self) -> io::Result { try!(self.inner.finish()); Ok(self.inner.take_inner()) } /// Consumes this encoder, flushing the output stream. /// /// This will flush the underlying data stream and then return the contained /// writer if the flush succeeded. /// The compressed stream will not closed but only flushed. This /// means that obtained byte array can by extended by another deflated /// stream. To close the stream add the two bytes 0x3 and 0x0. /// /// # Errors /// /// This function will perform I/O to complete this stream, and any I/O /// errors which occur will be returned from this function. pub fn flush_finish(mut self) -> io::Result { try!(self.inner.flush()); Ok(self.inner.take_inner()) } /// Returns the number of bytes that have been written to this compresor. /// /// Note that not all bytes written to this object may be accounted for, /// there may still be some active buffering. pub fn total_in(&self) -> u64 { self.inner.data.total_in() } /// Returns the number of bytes that the compressor has produced. /// /// Note that not all bytes may have been written yet, some may still be /// buffered. pub fn total_out(&self) -> u64 { self.inner.data.total_out() } } impl Write for ZlibEncoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.inner.write(buf) } fn flush(&mut self) -> io::Result<()> { self.inner.flush() } } #[cfg(feature = "tokio")] impl AsyncWrite for ZlibEncoder { fn shutdown(&mut self) -> Poll<(), io::Error> { try_nb!(self.try_finish()); self.get_mut().shutdown() } } impl Read for ZlibEncoder { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.get_mut().read(buf) } } #[cfg(feature = "tokio")] impl AsyncRead for ZlibEncoder {} /// A ZLIB decoder, or decompressor. /// /// This structure implements a [`Write`] and will emit a stream of decompressed /// data when fed a stream of compressed data. /// /// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use std::io; /// # use flate2::Compression; /// # use flate2::write::ZlibEncoder; /// use flate2::write::ZlibDecoder; /// /// # fn main() { /// # let mut e = ZlibEncoder::new(Vec::new(), Compression::default()); /// # e.write(b"Hello World").unwrap(); /// # let bytes = e.finish().unwrap(); /// # println!("{}", decode_reader(bytes).unwrap()); /// # } /// # /// // Uncompresses a Zlib Encoded vector of bytes and returns a string or error /// // Here Vec implements Write /// /// fn decode_reader(bytes: Vec) -> io::Result { /// let mut writer = Vec::new(); /// let mut z = ZlibDecoder::new(writer); /// z.write(&bytes[..])?; /// writer = z.finish()?; /// let return_string = String::from_utf8(writer).expect("String parsing error"); /// Ok(return_string) /// } /// ``` #[derive(Debug)] pub struct ZlibDecoder { inner: zio::Writer, } impl ZlibDecoder { /// Creates a new decoder which will write uncompressed data to the stream. /// /// When this decoder is dropped or unwrapped the final pieces of data will /// be flushed. pub fn new(w: W) -> ZlibDecoder { ZlibDecoder { inner: zio::Writer::new(w, Decompress::new(true)), } } /// Acquires a reference to the underlying writer. pub fn get_ref(&self) -> &W { self.inner.get_ref() } /// Acquires a mutable reference to the underlying writer. /// /// Note that mutating the output/input state of the stream may corrupt this /// object, so care must be taken when using this method. pub fn get_mut(&mut self) -> &mut W { self.inner.get_mut() } /// Resets the state of this decoder entirely, swapping out the output /// stream for another. /// /// This will reset the internal state of this decoder and replace the /// output stream with the one provided, returning the previous output /// stream. Future data written to this decoder will be decompressed into /// the output stream `w`. /// /// # Errors /// /// This function will perform I/O to complete this stream, and any I/O /// errors which occur will be returned from this function. pub fn reset(&mut self, w: W) -> io::Result { try!(self.inner.finish()); self.inner.data = Decompress::new(true); Ok(self.inner.replace(w)) } /// Attempt to finish this output stream, writing out final chunks of data. /// /// Note that this function can only be used once data has finished being /// written to the output stream. After this function is called then further /// calls to `write` may result in a panic. /// /// # Panics /// /// Attempts to write data to this stream may result in a panic after this /// function is called. /// /// # Errors /// /// This function will perform I/O to complete this stream, and any I/O /// errors which occur will be returned from this function. pub fn try_finish(&mut self) -> io::Result<()> { self.inner.finish() } /// Consumes this encoder, flushing the output stream. /// /// This will flush the underlying data stream and then return the contained /// writer if the flush succeeded. /// /// Note that this function may not be suitable to call in a situation where /// the underlying stream is an asynchronous I/O stream. To finish a stream /// the `try_finish` (or `shutdown`) method should be used instead. To /// re-acquire ownership of a stream it is safe to call this method after /// `try_finish` or `shutdown` has returned `Ok`. /// /// # Errors /// /// This function will perform I/O to complete this stream, and any I/O /// errors which occur will be returned from this function. pub fn finish(mut self) -> io::Result { try!(self.inner.finish()); Ok(self.inner.take_inner()) } /// Returns the number of bytes that the decompressor has consumed for /// decompression. /// /// Note that this will likely be smaller than the number of bytes /// successfully written to this stream due to internal buffering. pub fn total_in(&self) -> u64 { self.inner.data.total_in() } /// Returns the number of bytes that the decompressor has written to its /// output stream. pub fn total_out(&self) -> u64 { self.inner.data.total_out() } } impl Write for ZlibDecoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.inner.write(buf) } fn flush(&mut self) -> io::Result<()> { self.inner.flush() } } #[cfg(feature = "tokio")] impl AsyncWrite for ZlibDecoder { fn shutdown(&mut self) -> Poll<(), io::Error> { try_nb!(self.inner.finish()); self.inner.get_mut().shutdown() } } impl Read for ZlibDecoder { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.get_mut().read(buf) } } #[cfg(feature = "tokio")] impl AsyncRead for ZlibDecoder {} vendor/flate2-1.0.1/tests/0000755000000000000000000000000013264166600014027 5ustar rootrootvendor/flate2-1.0.1/tests/corrupt-file.gz0000664000000000000000000001573013264166600017014 0ustar rootrootMK. ǿVzR24;1RVAE_~Kۿ~ǯۿϿ_~{ʟmZ'ʊʱZBw\fOQ>cS,Xc4޷>c)Om e4!4JzSsڶ51xQkS9%?s*̹hH9gG*9vS1w*SujdmcNM]R{‡f>AOU)t-Ijs6-[CZ>e~{+QViõ6nhYu$-O#7L1XNMkusӾkU0LmV7Tۨ-wƶj3k,M=ƶ֘o۪\e=cW6b!I񅼲SҮ7Ϸvj>WweOh2ϕSS8zy}]Ƨq{EאӶkJ+{ZvmKP>^}?{cվi'K'͚F h1"ruj2uuhAy1v}&AO4Xy4g~vuuE"hciQ4 nddŘzb3FiZCQ[<1KMK. ǿVzR24;1RVAE_~Kۿ~ǯۿϿ_~{ʟmZ'ʊʱZBw\fOQ>cS,Xc4޷>c)Om e4!4JzSsڶ51xQkS9%?s*̹hH9gG*9vS1w*SujdmcNM]R{‡f>AOU)t-Ijs6-[CZ>e~{+QViõ6nhYu$-O#7L1XNMkusӾkU0LmV7Tۨ-wƶj3k,M=ƶ֘o۪\e=cW6b!I񅼲SҮ7Ϸvj>WweOh2ϕSS8zy}]Ƨq{EאӶkJ+{ZvmKP>^}?{cվi'K'͚F h1"ruj2uuhAy1v}&AO4Xy4g~vuuE"hciQ4 nddŘzb3FiZCQ[<1KW6m)]B#()oJxhzkkFu@$mK" d @Z˶6 Rp[< ַm+lwKaC(bk1LЉ)A3Ɂa5 D2'JkWDRaH.EH$,I-8+uIHe3^YHr!rdBSwe,݈i0ē M,a6r0*?ej l[Z#6"aY#+,d9^7M82]JS_ZI1#k 굅ԉC\BGNT:Wh{f'wY7߸u~Ɠ˺5wZlYWk ͜zc?YHJivy5Cƴ]/:Hv{5-b:`Sot0@P,smu汹:-bmR.8kXih#e%Yj F ְfcF, ڣYt2Ԉ@gfpU]xYl>Z9:O%ŶRҝX:͜4CJGZ#)©|+o'vkCLZ`^?$}/b7KQSThux=rJw}ۛ)gX/Ȧmp vFgRv\suMn9Ub@IpIn5+N;)N:y(wP@U5dWS=u<;tDVF%:%[' ?/QXdIUXKv¢~xDՙ+_R #[ .yH0 p=ә@ a8 WApHyu ZO%gb!JA5G'.E{1XlP&ln%؊SeI$CգL#Y*>ږ9+@kY'CΐW(N$5yzt2$*uX- Dn֒pLu~2#A, ~#\N7Xnfc-" w9Y yLo߈iw&Wvq⪾U["789PHM oNl*" 0jTaMͰMvPM=s4ՒtuB8 R=T55R]Œ_W)k]zڈ]b='t$v%V9lˣa*"m寬~p(+:7eO : צ9m LUstE*`X nLϝ  8FVA Ka O|# ڷ8x]& #` )00\D~ h2 & (( zfC+!?bh%SAǁ6Sp1@9j7Qs4ՙmL` ]oX--֪ jZ49ok -a(h C^8豭w_f!8NjGdLe1'[Qa-`>^H~5CouVId#H1w֍/}SpE MCWֶ|!hr@ @'Z0z7 ~Sp.K8(L[-ȻyJUucZqa _űkmGGmd΄TⅬ,TȺMe+E'ִJZ04O(. _KKۅG=Z7c*vezS[|Who(me?bBMŇϓ婬muK@GV?fW0GSqoj*-[3ׇ0(ulu?eHPiTX%)ȦCv@L@Y Dlt'OƂ(d='j(KJ(@cY)jQ5g}$wCo2 V,˷*o׫&l#eZ:CDފv@Fo8(>fd(A]~\+(4g ~62kgq'=J`]p[͙xF$Hxoabkx+y9]w)„J~^eA)e: hmG& t!_G}I^vU =Ǚ~pAlq! Rm.U ]>`5hyg.c=; NY2k$wW˪zXܢ2o .-{eP2nlu}.;XaI:їO & Ja(2 鄌wAOL+RLk bLCgn4]SqqV}󩞺ª1,V JAykkcۏ J66U־.ׇjEyr<_39JpףXkv55+NUaZ 2Q 6p 6&L 'gnOZ]I (n cq^or $X@-*gD-УWhEkBHaY`kڤү`HUPO/U#>\RE/.OMYM D_ECP@ZSyyEsV5Uw S>̫u*GAUwP T~.qm Du0OD]h4УYf g–Qpq ! XUu"Bo[=&U:7|r(mݣK*]i\L?BY=8t/èE[Z8ϣ2P ) >Z @Bb\7lSAe*G!#T;&^oI qT(K998x݉9E\ww>Nkzh#S*$_>U\SØmT(n^֘(\ƭ5ۡ"'ND8{18QZT#L:CԠZ[M& Ȋ6~Ym(pTgl)u-İ=\n @!:!R,; K5?3Sޠ*p8 ]>tEWj8 U1@U-QjZǾa\+NVT c_n0Wξ^@Fپd\}p۾iPNU99B{GkGTW穨l5+?RIacV~z~iКq a?m5)CYi>gyU?2g(XOeѧOe]T S-0YS,n]KS{kgS+~l1nbц>Ӫԕчv՟_Wmni>G?~6s]:k\{8fS>ni:a]kck~^zlH:[mO;ھh(ٴr?jg݌`3嵔uRVZuG-6bctquwU:ᣳzZ)koS?ı]ʭzfOg|z˷vOXfiz&?m  X)ݟ:'o8vkkLiy{z]WCw׶<^6X#{apxq|Fu?>G[^/qGǬM>og\ 4Я=\?C.?V3n8p}7t)t}c<~ φD#t>-A:s?r"cMb*-O>Ptb+a0*OpںF2mc6]>O`3c:"W(RER{&$dd?LoImFt7=swkAW -7IT }S[<ƃA׻\ol.FW͛:p\ضwH]4X !мd7~F/ oC) ~F }=U߿YAOEY53EXoHq>γ7):DfnM?jf!0DQ"m)s b*bH( hy!JC"!ȵ•'lG~=46/KX̎(y-<}xq BvUXCL YDHw=SRwfi*!'`cI *-`J2ŗ`/` 4 S7H=^PQʶdL窸81H0ȃ]dho@twПG֋I/, al ?vFHγ7lV4l_Ɋ0'()69X l!X)пwHGG h/VAToC@\hlq>wKW榬dqhZ9+U(laO=-I_ڕ_#?t%He^L!PH2Όǂex )vL|׈Z2`}Ļ)F 4eKsHXUR@q RMoMDJH3!eA2 iz @q$qxdfd]?4)+Bb!Ե}!EW`r1<FvVTuqEu]a[ X-=u^vƖl@-)^ʞs 4xL!@l 8I'< RZY2 (#̳" \ϬSCPK63t|H俼P kTd;m҆W{e}1K1^2 ZI n,Qup ^K0V\"t~T -Z` ?j+D\gt-֍![%Dp$sԀu̢_ ht2׌ `@Ap'o_\ .DK8 b9, OxP9B6Y Z#ii%PIp?FF]9@K7" Sih{If ({Ip!ݝ>[% PG I7^ ?ņ8y/J]N,5uOB 2Izr*%4XSFT07:q2`)ZCbqjBίAntvWn!{Gzu|K/u!Q~\zps~o_t}fPqfa2 JkiZA #Qv{Ɋdӣ7 c/Oܳ +YQ, X)-64|(QJ 5u<7^i1 j Ih3}z*2Ϯ[_  H`9{6ѢD$Ţ22p9"=yG?1,,c]ƕ&r'+~PТ)+D{VnEOP&7Q>\/yIS:Cx/J_IXiP>vGfXu6t5 `|Ew oH<`T=v>X% BOoL>BtאBt__Wn;!+/ `RS`4*nRR12 D<}&]Jr]8W̳,L)*[}E)h7k%IiytE4\WDQR[Y(7=$@3 0*C ,x =K⼔,5ic mk'o[7 dt#|(%T_q_>9.7ᕘ $ Q|1r'_ûObAƷH%#Щ7l63n_P.ۏ mn wPwo_ N;كݴkwywJFu^]n|vEIg-ITnZ9@ap˝(=#5ul=aHH1nU4EQ;"8Co)2h撣[ع7dӚ#7=B@ ^1{%,KLDE}FVK0}$GkƜVoF Po5̤nR2a#vgmZdPaQci^tURT{.b]!$i#/ca\m-tP}܆=jް޸21THTwa@3P3N_nN'M ,_SCq|dN)i Ec,B,:ݴʬ2qȔfg*)U0d1':@ks3MP,+|e=ƙEy1'd"ERc>!#%ilIKN_:uG2?Qj9>̯Tg1Blɐ4r}Dg:z wB~(_Y$7˯Q@YJ?OcZKoǟ1ȓgG4'=qLJhx}zPT]9s}ڑɳ@֘[b+1.Qx;EńQ4f՘p1CJi}y%-  S S~㌃17c?QoG-It}9 ]ۙ5_^1JcP"[a{^vySI&U$֌-l`",q28~i87wo10*b~;Xox ޸E*Fw}o@)v4h!8\#ġ'd PztV=c.~bs)uR8t1ߋL]U(dМ'IRO',C|!rU%Y*=:ʫ`ztJuςL KNH˚494y<O즯'"ڣ'G*!ݓAXÎĠ<_}GgQ~f$ۈP8 QJ^ $fn_=4Y)%B6uf-O _XFPqJB46eճ"aV?n̬`'E;czhf4 3q9Jq;3"Y!,fGE3gMl n>B@ϟSЈa]n4ot 20ב㛆Ry@D M+CCdgGG oUɒ" 7KЙ/A&s,@f"R>q0}gjoW+l7xdzSJV^O*3_3F%c+x™HZbޖBLf6Qd?u8Y?M3 C|WXERi1IS{`/#xrKfxĐ. #Y 0/*#ȦbYЅef ԉ,HXQG&M:vendor/flate2-1.0.1/tests/good-file.txt0000664000000000000000000003503513264166600016445 0ustar rootroot## ## timestep simulated EIR patent hosts 0 0.136402 16855 1 0.146872 18564 2 0.150157 20334 3 0.146358 22159 4 0.136315 23655 5 0.122354 24848 6 0.104753 25887 7 0.084439 26770 8 0.06417 27238 9 0.0450397 27349 10 0.0295473 27274 11 0.0184662 26909 12 0.0110032 26324 13 0.00634348 25513 14 0.0036144 24469 15 0.00208133 23383 16 0.00122468 22345 17 0.000752514 21342 18 0.000545333 20416 19 0.000546139 19657 20 0.00054572 18806 21 0.000545757 18015 22 0.000545898 17349 23 0.000546719 16594 24 0.000547353 15955 25 0.000547944 15374 26 0.000547606 14765 27 0.000594773 14212 28 0.000969163 13677 29 0.00168295 13180 30 0.003059 12760 31 0.00571599 12313 32 0.0107918 11896 33 0.0201943 11512 34 0.0368013 11340 35 0.0640629 11323 36 0.104447 11769 37 0.157207 12728 38 0.216682 14261 39 0.271159 16491 40 0.303552 19274 41 0.303678 22157 42 0.271945 24875 43 0.215445 27027 44 0.154503 28690 45 0.100717 30046 46 0.0600343 30602 47 0.0328576 30709 48 0.016964 30315 49 0.00841526 29310 50 0.0040958 28058 51 0.0019953 26662 52 0.000986531 25259 53 0.000545786 24049 54 0.000546405 22966 55 0.000546036 21933 56 0.00054427 20953 57 0.000542769 20057 58 0.000541566 19304 59 0.000541822 18477 60 0.000541643 17695 61 0.000541989 17002 62 0.000769298 16391 63 0.00150811 15805 64 0.00295097 15172 65 0.00566197 14690 66 0.0105243 14206 67 0.0186965 13791 68 0.0313363 13470 69 0.0490605 13377 70 0.0711679 13631 71 0.0953625 14209 72 0.118026 15277 73 0.134612 16760 74 0.144311 18339 75 0.146328 20124 76 0.142936 21803 77 0.134029 23435 78 0.120562 24854 79 0.103157 25880 80 0.0834054 26597 81 0.0632474 27226 82 0.0447785 27294 83 0.0295654 27169 84 0.0184081 26803 85 0.0109489 26265 86 0.00631234 25375 87 0.00359978 24306 88 0.00206967 23260 89 0.00122197 22225 90 0.000751031 21277 91 0.000544507 20295 92 0.000543897 19417 93 0.000543483 18623 94 0.000542926 17837 95 0.000542685 17070 96 0.000542387 16424 97 0.000541194 15838 98 0.000540427 15177 99 0.000540774 14608 100 0.000588312 14066 101 0.000959183 13499 102 0.00166774 12979 103 0.00303278 12545 104 0.00567457 12067 105 0.0107272 11712 106 0.0200606 11368 107 0.0364637 11207 108 0.063339 11238 109 0.103717 11660 110 0.156884 12621 111 0.217072 14151 112 0.272311 16358 113 0.305046 19005 114 0.304927 21926 115 0.272427 24662 116 0.216478 27080 117 0.155168 29064 118 0.10079 30370 119 0.0599659 30992 120 0.0331287 30975 121 0.017235 30317 122 0.00860221 29455 123 0.00419286 28172 124 0.00203361 26809 125 0.000998847 25476 126 0.000551418 24230 127 0.000551119 23106 128 0.000552786 22147 129 0.000553814 21183 130 0.000553743 20280 131 0.000554428 19423 132 0.000555022 18598 133 0.000555921 17864 134 0.000556687 17187 135 0.000789996 16527 136 0.00154597 15870 137 0.00302776 15226 138 0.00581484 14685 139 0.010812 14234 140 0.0191832 13818 141 0.0321572 13571 142 0.050328 13538 143 0.072817 13812 144 0.0974321 14368 145 0.120225 15436 146 0.137418 16988 147 0.147086 18775 148 0.149165 20563 149 0.144943 22223 150 0.136631 23741 151 0.123355 24920 152 0.105401 25779 153 0.0851918 26781 154 0.0641702 27265 155 0.0450746 27505 156 0.0294136 27416 157 0.0183811 27028 158 0.0109285 26260 159 0.00634296 25451 160 0.00364513 24472 161 0.0021051 23427 162 0.00123693 22403 163 0.000759531 21393 164 0.000551727 20485 165 0.000552256 19660 166 0.000552303 18862 167 0.000550927 18094 168 0.000551098 17378 169 0.000551093 16691 170 0.000551885 16050 171 0.000552282 15420 172 0.000552591 14878 173 0.00060109 14357 174 0.000980446 13768 175 0.00170301 13241 176 0.003096 12745 177 0.00579971 12294 178 0.010976 11879 179 0.0205422 11636 180 0.0374515 11431 181 0.0649916 11517 182 0.106008 11966 183 0.159983 12918 184 0.221127 14484 185 0.276503 16696 186 0.310316 19518 187 0.311205 22301 188 0.276769 25047 189 0.220506 27360 190 0.159123 29133 191 0.103761 30440 192 0.0613797 31087 193 0.033583 31037 194 0.0173275 30555 195 0.00861968 29617 196 0.00419503 28292 197 0.00203304 26944 198 0.00100126 25569 199 0.000553511 24349 200 0.000554687 23257 201 0.00055586 22204 202 0.000555419 21176 203 0.000556032 20316 204 0.000555974 19509 205 0.000556859 18746 206 0.000556996 17978 207 0.000557102 17288 208 0.000790187 16672 209 0.00154711 16057 210 0.00303521 15449 211 0.00584201 14915 212 0.0108854 14397 213 0.0193386 14010 214 0.0324346 13730 215 0.0507192 13674 216 0.0736661 13874 217 0.0987887 14515 218 0.122411 15693 219 0.139964 17265 220 0.149125 18894 221 0.151434 20662 222 0.148067 22442 223 0.138894 24116 224 0.125436 25367 225 0.107664 26360 226 0.0865709 27044 227 0.0655588 27428 228 0.0459664 27714 229 0.0301384 27687 230 0.0186481 27262 231 0.01103 26677 232 0.00636957 25722 233 0.00366188 24662 234 0.00212213 23575 235 0.00125358 22520 236 0.000768665 21480 237 0.000556393 20563 238 0.000555892 19706 239 0.00055534 18914 240 0.000555027 18165 241 0.000555062 17432 242 0.000553766 16733 243 0.000552984 16070 244 0.000553634 15396 245 0.000554286 14867 246 0.000603759 14362 247 0.000982974 13867 248 0.00170532 13379 249 0.00310471 12907 250 0.00582577 12446 251 0.0110122 12018 252 0.0206284 11730 253 0.0375835 11546 254 0.0652192 11605 255 0.10646 11981 256 0.160858 12949 257 0.223122 14478 258 0.279678 16810 259 0.312171 19452 260 0.311778 22391 261 0.276966 25204 262 0.22251 27379 263 0.159246 29248 264 0.104109 30532 265 0.0617903 30995 266 0.0338421 31042 267 0.0174647 30620 268 0.00867821 29589 269 0.00419968 28293 270 0.00203244 26916 271 0.00100204 25464 272 0.000555586 24219 273 0.000555599 23207 274 0.00055582 22187 275 0.00055516 21136 276 0.000555436 20243 277 0.000555618 19426 278 0.000556778 18635 279 0.000556976 17870 280 0.000557162 17190 281 0.0007904 16506 282 0.00154557 15837 283 0.00302973 15234 284 0.00584543 14717 285 0.0108796 14225 286 0.0192919 13810 287 0.032329 13605 288 0.0505293 13536 289 0.0733417 13760 290 0.0982413 14378 291 0.121477 15400 292 0.138636 17017 293 0.14875 18764 294 0.150515 20516 295 0.146372 22389 296 0.137332 23975 297 0.124076 25120 298 0.106469 26137 299 0.0862987 26973 300 0.0650552 27584 301 0.0456456 27741 302 0.0300744 27565 303 0.0187879 27212 304 0.0112085 26432 305 0.00648306 25501 306 0.00370346 24466 307 0.00213399 23472 308 0.00125463 22415 309 0.000765794 21427 310 0.000552587 20533 311 0.000553175 19632 312 0.000553525 18831 313 0.000554941 18119 314 0.000556327 17336 315 0.000556008 16721 316 0.00055593 16086 317 0.000556421 15516 318 0.000557308 14918 319 0.00060681 14402 320 0.000990746 13849 321 0.00172359 13355 322 0.00313688 12902 323 0.0058708 12425 324 0.0110637 12087 325 0.0206777 11743 326 0.0376394 11531 327 0.0656182 11582 328 0.107414 12034 329 0.162101 12955 330 0.223525 14571 331 0.279935 16842 332 0.314601 19566 333 0.313556 22575 334 0.279571 25279 335 0.221638 27642 336 0.158038 29275 337 0.102505 30638 338 0.0608328 31209 339 0.0335531 31260 340 0.0173332 30520 341 0.00861545 29604 342 0.00419454 28370 343 0.00202587 26940 344 0.000994029 25614 345 0.000549339 24445 346 0.000551477 23239 347 0.000552891 22300 348 0.000551775 21280 349 0.000552425 20424 350 0.000552135 19571 351 0.000552542 18753 352 0.000552863 18058 353 0.000554438 17348 354 0.000786735 16671 355 0.00153958 16047 356 0.00301482 15500 357 0.00580589 14883 358 0.0108227 14347 359 0.0192357 13947 360 0.0321613 13672 361 0.050229 13606 362 0.0729462 13815 363 0.0978564 14566 364 0.120879 15674 365 0.137663 17049 366 0.147092 18813 367 0.150184 20578 368 0.146971 22245 369 0.136769 23723 370 0.12367 24905 371 0.106187 25871 372 0.0860921 26687 373 0.0645899 27375 374 0.0453473 27635 375 0.0298122 27551 376 0.0185448 27134 377 0.0110517 26468 378 0.00640294 25661 379 0.00367011 24653 380 0.00211832 23556 381 0.00125246 22513 382 0.00076891 21568 383 0.000557384 20672 384 0.000557295 19811 385 0.000556837 18982 386 0.000557433 18179 387 0.000557376 17457 388 0.000557751 16720 389 0.000556844 16112 390 0.000555603 15479 391 0.000554871 14809 392 0.00060335 14275 393 0.000982808 13757 394 0.00170757 13221 395 0.00310351 12758 396 0.0058181 12286 397 0.010991 11906 398 0.0205342 11557 399 0.0373486 11393 400 0.0647659 11487 401 0.105589 11887 402 0.15967 12798 403 0.220945 14260 404 0.277122 16477 405 0.310108 19295 406 0.308854 22110 407 0.274911 24915 408 0.218618 27273 409 0.156618 29189 410 0.101775 30572 411 0.0607503 31174 412 0.0334708 31316 413 0.0173443 30731 414 0.00865633 29636 415 0.00421141 28342 416 0.00204387 26991 417 0.00100602 25595 418 0.000555131 24336 419 0.000555037 23251 420 0.000555559 22267 421 0.000554916 21212 422 0.000554432 20306 423 0.000554751 19488 424 0.00055638 18727 425 0.000556727 17927 426 0.000556368 17198 427 0.000788004 16578 428 0.00154404 15944 429 0.00302383 15315 430 0.00582586 14786 431 0.0108457 14290 432 0.0192962 13815 433 0.0323072 13561 434 0.0505101 13456 435 0.0732162 13811 436 0.0978737 14403 437 0.121405 15460 438 0.138202 16993 439 0.1482 18710 440 0.149707 20578 441 0.146945 22256 442 0.137785 23713 443 0.123767 25058 444 0.105989 26087 445 0.085483 26759 446 0.0646144 27375 447 0.0454389 27680 448 0.0299337 27531 449 0.018663 27041 450 0.0111347 26416 451 0.00644197 25614 452 0.00369229 24666 453 0.00211986 23647 454 0.00124761 22650 455 0.000769104 21642 456 0.000558796 20693 457 0.000559908 19746 458 0.000559562 18952 459 0.00056042 18100 460 0.000559447 17401 461 0.000557893 16756 462 0.000557137 16148 463 0.000557269 15504 464 0.000557596 14974 465 0.000606298 14408 466 0.000987712 13909 467 0.00171257 13402 468 0.00311667 12891 469 0.00584794 12433 470 0.0110774 11980 471 0.0207006 11713 472 0.037673 11583 473 0.0654988 11677 474 0.106982 12072 475 0.161926 12898 476 0.224327 14548 477 0.281709 16796 478 0.314567 19512 479 0.313419 22428 480 0.278962 25186 481 0.221864 27755 482 0.158559 29556 483 0.103532 30572 484 0.0611592 31162 485 0.0337539 31197 486 0.0175096 30619 487 0.00865906 29606 488 0.00420125 28271 489 0.00203207 26856 490 0.00100238 25542 491 0.000554405 24306 492 0.00055373 23160 493 0.0005552 22152 494 0.000553776 21192 495 0.000553636 20302 496 0.000553165 19505 497 0.000554014 18719 498 0.00055519 17993 499 0.000556582 17233 500 0.000788165 16569 501 0.00154132 15953 502 0.00302099 15350 503 0.00581186 14752 504 0.0108291 14267 505 0.0192368 13946 506 0.0322191 13677 507 0.0503789 13594 508 0.0730706 13768 509 0.0980646 14416 510 0.121601 15634 511 0.139046 17110 512 0.147779 18876 513 0.149612 20734 514 0.145796 22414 515 0.136936 23884 516 0.123807 25078 517 0.106212 26066 518 0.0855482 26779 519 0.0643386 27340 520 0.0452926 27530 521 0.0298659 27573 522 0.0185447 27169 523 0.0110178 26489 524 0.00635235 25588 525 0.00362881 24549 526 0.00209238 23528 527 0.00123133 22541 528 0.000755917 21498 529 0.000546368 20607 530 0.000547382 19712 531 0.000547084 18975 532 0.000546453 18178 533 0.000546062 17452 534 0.000546085 16749 535 0.000546151 16135 536 0.000545628 15567 537 0.000545969 14968 538 0.000594606 14392 539 0.000968849 13854 540 0.00168489 13360 541 0.00306337 12899 542 0.00573505 12407 543 0.0108348 12017 544 0.02025 11713 545 0.0368201 11517 546 0.0639795 11556 547 0.104882 11941 548 0.158923 12854 549 0.219796 14396 550 0.275801 16733 551 0.307622 19367 552 0.30785 22230 553 0.272898 24873 554 0.217351 27152 555 0.156138 29108 556 0.101477 30379 557 0.0601091 30971 558 0.0331551 31126 559 0.017167 30418 560 0.00853886 29430 561 0.00415201 28190 562 0.00201849 26849 563 0.000991957 25528 564 0.000546751 24180 565 0.00054534 23090 566 0.000544403 22096 567 0.00054368 21140 568 0.000543407 20213 569 0.000544421 19405 570 0.000545241 18625 571 0.000546995 17868 572 0.000547101 17102 573 0.00077428 16423 574 0.00151348 15783 575 0.00296212 15220 576 0.00569555 14602 577 0.0106307 14154 578 0.0188783 13743 579 0.0316572 13538 580 0.0495211 13467 581 0.0718936 13665 582 0.0961304 14240 583 0.119127 15341 584 0.136233 16912 585 0.145327 18567 586 0.146983 20301 587 0.143022 21953 588 0.134931 23439 589 0.121892 24750 590 0.103955 25688 591 0.0833804 26253 592 0.0625106 26918 593 0.0440419 27279 594 0.0290823 27159 595 0.0180758 26786 596 0.0107654 26049 597 0.00622673 25202 598 0.00356716 24168 599 0.00205866 23122 600 0.00121254 22076 601 0.000745744 21100 602 0.000537789 20207 603 0.000537982 19340 604 0.000537795 18527 605 0.000537955 17768 606 0.000539259 17117 607 0.00053942 16425 608 0.000540477 15701 609 0.000540424 15134 610 0.000540084 14558 611 0.00058571 14069 612 0.00095364 13498 613 0.00165505 13054 614 0.00300205 12616 615 0.00561724 12142 616 0.0106079 11720 617 0.0198178 11410 618 0.0360368 11231 619 0.0623418 11314 620 0.101856 11688 621 0.15376 12623 622 0.213046 14078 623 0.267285 16225 624 0.299225 18856 625 0.299517 21756 626 0.26697 24652 627 0.2119 27051 628 0.151393 28925 629 0.098869 30065 630 0.0593653 30570 631 0.0327177 30483 632 0.0170081 29735 633 0.0084493 28844 634 0.00409333 27665 635 0.00197466 26356 636 0.000967996 25009 637 0.000533137 23839 638 0.000532992 22721 639 0.000534258 21676 640 0.000534251 20709 641 0.000534556 19798 642 0.000535287 19008 643 0.000536214 18278 644 0.000536647 17547 645 0.000536556 16901 646 0.000761043 16256 647 0.00149108 15621 648 0.00292808 15032 649 0.0056527 14504 650 0.0105421 14010 651 0.0186823 13646 652 0.0312164 13356 653 0.0485643 13404 654 0.0704061 13612 655 0.0945219 14230 656 0.117178 15374 657 0.134568 16843 658 0.144475 18492 659 0.146915 20238 660 0.14393 21958 661 0.134621 23537 662 0.121737 24773 663 0.104744 25772 664 0.0846226 26427 665 0.0639754 27040 666 0.0448457 27279 667 0.029482 27106 668 0.0183036 26853 669 0.0108721 26178 670 0.00627116 25425 671 0.0035776 24326 672 0.00206466 23279 673 0.00122064 22191 674 0.000751578 21231 675 0.000542574 20323 676 0.000540396 19496 677 0.000538805 18651 678 0.00053881 17920 679 0.000537801 17217 680 0.000537866 16520 681 0.000538522 15876 682 0.000538795 15229 683 0.000539519 14656 684 0.000587348 14121 685 0.000955855 13626 686 0.00165656 13086 687 0.00301095 12666 688 0.00564993 12250 689 0.0106767 11869 690 0.0199729 11524 691 0.03641 11331 692 0.0632378 11402 693 0.103483 11788 694 0.156399 12682 695 0.215591 14337 696 0.269462 16547 697 0.303615 19239 698 0.304506 22023 699 0.273068 24769 700 0.21682 27223 701 0.154934 29029 702 0.100495 30241 703 0.0597382 30801 704 0.0329221 30881 705 0.0170591 30288 706 0.00845353 29329 707 0.00408176 28108 708 0.00198037 26715 709 0.000977102 25340 710 0.000541566 24039 711 0.000542333 22965 712 0.000542417 21858 713 0.000541182 20952 714 0.00054038 20049 715 0.000539725 19192 716 0.000539603 18409 717 0.000539754 17700 718 0.000539679 16960 719 0.000763508 16287 720 0.00149327 15637 721 0.00292609 15057 722 0.00563308 14524 723 0.0104893 14003 724 0.0185874 13625 725 0.0310985 13319 726 0.0487417 13278 727 0.0707124 13502 728 0.0947795 14147 729 0.117155 15183 730 0.133995 16622 vendor/flate2-1.0.1/tests/gunzip.rs0000664000000000000000000000366613264166600015726 0ustar rootrootextern crate flate2; use std::fs::File; use std::io::prelude::*; use std::io::{self, BufReader}; use std::path::Path; use flate2::read::GzDecoder; use flate2::read::MultiGzDecoder; // test extraction of a gzipped file #[test] fn test_extract_success() { let content = extract_file(Path::new("tests/good-file.gz")).unwrap(); let mut expected = Vec::new(); File::open("tests/good-file.txt").unwrap().read_to_end(&mut expected).unwrap(); assert!(content == expected); } // // test partial extraction of a multistream gzipped file #[test] fn test_extract_success_partial_multi() { let content = extract_file(Path::new("tests/multi.gz")).unwrap(); let mut expected = String::new(); BufReader::new(File::open("tests/multi.txt").unwrap()).read_line(&mut expected).unwrap(); assert_eq!(content, expected.as_bytes()); } // test extraction fails on a corrupt file #[test] fn test_extract_failure() { let result = extract_file(Path::new("tests/corrupt-file.gz")); assert_eq!(result.err().unwrap().kind(), io::ErrorKind::InvalidInput); } //test complete extraction of a multistream gzipped file #[test] fn test_extract_success_multi() { let content = extract_file_multi(Path::new("tests/multi.gz")).unwrap(); let mut expected = Vec::new(); File::open("tests/multi.txt").unwrap().read_to_end(&mut expected).unwrap(); assert_eq!(content, expected); } // Tries to extract path into memory (assuming a .gz file). fn extract_file(path_compressed: &Path) -> io::Result>{ let mut v = Vec::new(); let f = try!(File::open(path_compressed)); try!(GzDecoder::new(f).read_to_end(&mut v)); Ok(v) } // Tries to extract path into memory (decompressing all members in case // of a multi member .gz file). fn extract_file_multi(path_compressed: &Path) -> io::Result>{ let mut v = Vec::new(); let f = try!(File::open(path_compressed)); try!(MultiGzDecoder::new(f).read_to_end(&mut v)); Ok(v) } vendor/flate2-1.0.1/tests/multi.gz0000664000000000000000000000006513264166600015526 0ustar rootroot5WK,*.*Jȕ5W+NMK~vendor/flate2-1.0.1/tests/multi.txt0000664000000000000000000000001513264166600015720 0ustar rootrootfirst second vendor/flate2-1.0.1/tests/tokio.rs0000664000000000000000000000704013264166600015525 0ustar rootroot#![cfg(feature = "tokio")] extern crate tokio_core; extern crate flate2; extern crate tokio_io; extern crate futures; extern crate rand; use std::thread; use std::net::{Shutdown, TcpListener}; use std::io::{Read, Write}; use flate2::Compression; use flate2::read; use flate2::write; use futures::Future; use rand::{Rng, thread_rng}; use tokio_core::net::TcpStream; use tokio_core::reactor::Core; use tokio_io::AsyncRead; use tokio_io::io::{copy, shutdown}; #[test] fn tcp_stream_echo_pattern() { const N: u8 = 16; const M: usize = 16 * 1024; let mut core = Core::new().unwrap(); let listener = TcpListener::bind("127.0.0.1:0").unwrap(); let addr = listener.local_addr().unwrap(); let t = thread::spawn(move || { let a = listener.accept().unwrap().0; let b = a.try_clone().unwrap(); let t = thread::spawn(move || { let mut b = read::DeflateDecoder::new(b); let mut buf = [0; M]; for i in 0..N { b.read_exact(&mut buf).unwrap(); for byte in buf.iter() { assert_eq!(*byte, i); } } assert_eq!(b.read(&mut buf).unwrap(), 0); }); let mut a = write::ZlibEncoder::new(a, Compression::default()); for i in 0..N { let buf = [i; M]; a.write_all(&buf).unwrap(); } a.finish().unwrap() .shutdown(Shutdown::Write).unwrap(); t.join().unwrap(); }); let handle = core.handle(); let stream = TcpStream::connect(&addr, &handle); let copy = stream.and_then(|s| { let (a, b) = s.split(); let a = read::ZlibDecoder::new(a); let b = write::DeflateEncoder::new(b, Compression::default()); copy(a, b) }).then(|result| { let (amt, _a, b) = result.unwrap(); assert_eq!(amt, (N as u64) * (M as u64)); shutdown(b).map(|_| ()) }); core.run(copy).unwrap(); t.join().unwrap(); } #[test] fn echo_random() { let v = thread_rng().gen_iter::().take(1024 * 1024).collect::>(); let mut core = Core::new().unwrap(); let listener = TcpListener::bind("127.0.0.1:0").unwrap(); let addr = listener.local_addr().unwrap(); let v2 = v.clone(); let t = thread::spawn(move || { let a = listener.accept().unwrap().0; let b = a.try_clone().unwrap(); let mut v3 = v2.clone(); let t = thread::spawn(move || { let mut b = read::DeflateDecoder::new(b); let mut buf = [0; 1024]; while v3.len() > 0 { let n = b.read(&mut buf).unwrap(); for (actual, expected) in buf[..n].iter().zip(&v3) { assert_eq!(*actual, *expected); } v3.drain(..n); } assert_eq!(b.read(&mut buf).unwrap(), 0); }); let mut a = write::ZlibEncoder::new(a, Compression::default()); a.write_all(&v2).unwrap(); a.finish().unwrap() .shutdown(Shutdown::Write).unwrap(); t.join().unwrap(); }); let handle = core.handle(); let stream = TcpStream::connect(&addr, &handle); let copy = stream.and_then(|s| { let (a, b) = s.split(); let a = read::ZlibDecoder::new(a); let b = write::DeflateEncoder::new(b, Compression::default()); copy(a, b) }).then(|result| { let (amt, _a, b) = result.unwrap(); assert_eq!(amt, v.len() as u64); shutdown(b).map(|_| ()) }); core.run(copy).unwrap(); t.join().unwrap(); } vendor/flate2-1.0.1/tests/zero-write.rs0000664000000000000000000000033613264166600016510 0ustar rootrootextern crate flate2; #[test] fn zero_write_is_error() { let mut buf = [0u8]; let writer = flate2::write::DeflateEncoder::new(&mut buf[..], flate2::Compression::default()); assert!(writer.finish().is_err()); } vendor/fnv-1.0.6/0000755000000000000000000000000013264166600012306 5ustar rootrootvendor/fnv-1.0.6/.cargo-checksum.json0000644000000000000000000000013113264166600016145 0ustar rootroot{"files":{},"package":"2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"}vendor/fnv-1.0.6/.travis.yml0000644000000000000000000000016513264166600014421 0ustar rootrootlanguage: rust rust: - nightly - beta - stable notifications: webhooks: http://build.servo.org:54856/travis vendor/fnv-1.0.6/Cargo.toml0000644000000000000000000000151613264166600014241 0ustar rootroot# 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 = "fnv" version = "1.0.6" authors = ["Alex Crichton "] description = "Fowler–Noll–Vo hash function" documentation = "https://doc.servo.org/fnv/" readme = "README.md" license = "Apache-2.0 / MIT" repository = "https://github.com/servo/rust-fnv" [lib] name = "fnv" path = "lib.rs" vendor/fnv-1.0.6/LICENSE-APACHE0000644000000000000000000002513713264166600014242 0ustar rootroot 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. vendor/fnv-1.0.6/LICENSE-MIT0000644000000000000000000000204013264166600013736 0ustar rootrootCopyright (c) 2017 Contributors 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. vendor/fnv-1.0.6/README.md0000644000000000000000000000437513264166600013576 0ustar rootroot# rust-fnv An implementation of the [Fowler–Noll–Vo hash function][chongo]. ### [Read the documentation](https://doc.servo.org/fnv/) ## About The FNV hash function is a custom `Hasher` implementation that is more efficient for smaller hash keys. [The Rust FAQ states that][faq] while the default `Hasher` implementation, SipHash, is good in many cases, it is notably slower than other algorithms with short keys, such as when you have a map of integers to other values. In cases like these, [FNV is demonstrably faster][graphs]. Its disadvantages are that it performs badly on larger inputs, and provides no protection against collision attacks, where a malicious user can craft specific keys designed to slow a hasher down. Thus, it is important to profile your program to ensure that you are using small hash keys, and be certain that your program could not be exposed to malicious inputs (including being a networked server). The Rust compiler itself uses FNV, as it is not worried about denial-of-service attacks, and can assume that its inputs are going to be small—a perfect use case for FNV. ## Usage To include this crate in your program, add the following to your `Cargo.toml`: ```toml [dependencies] fnv = "1.0.3" ``` ## Using FNV in a HashMap The `FnvHashMap` type alias is the easiest way to use the standard library’s `HashMap` with FNV. ```rust use fnv::FnvHashMap; let mut map = FnvHashMap::default(); map.insert(1, "one"); map.insert(2, "two"); map = FnvHashMap::with_capacity_and_hasher(10, Default::default()); map.insert(1, "one"); map.insert(2, "two"); ``` Note, the standard library’s `HashMap::new` and `HashMap::with_capacity` are only implemented for the `RandomState` hasher, so using `Default` to get the hasher is the next best option. ## Using FNV in a HashSet Similarly, `FnvHashSet` is a type alias for the standard library’s `HashSet` with FNV. ```rust use fnv::FnvHashSet; let mut set = FnvHashSet::default(); set.insert(1); set.insert(2); set = FnvHashSet::with_capacity_and_hasher(10, Default::default()); set.insert(1); set.insert(2); ``` [chongo]: http://www.isthe.com/chongo/tech/comp/fnv/index.html [faq]: https://www.rust-lang.org/en-US/faq.html#why-are-rusts-hashmaps-slow [graphs]: http://cglab.ca/~abeinges/blah/hash-rs/ vendor/fnv-1.0.6/lib.rs0000644000000000000000000004462113264166600013431 0ustar rootroot//! An implementation of the [Fowler–Noll–Vo hash function][chongo]. //! //! ## About //! //! The FNV hash function is a custom `Hasher` implementation that is more //! efficient for smaller hash keys. //! //! [The Rust FAQ states that][faq] while the default `Hasher` implementation, //! SipHash, is good in many cases, it is notably slower than other algorithms //! with short keys, such as when you have a map of integers to other values. //! In cases like these, [FNV is demonstrably faster][graphs]. //! //! Its disadvantages are that it performs badly on larger inputs, and //! provides no protection against collision attacks, where a malicious user //! can craft specific keys designed to slow a hasher down. Thus, it is //! important to profile your program to ensure that you are using small hash //! keys, and be certain that your program could not be exposed to malicious //! inputs (including being a networked server). //! //! The Rust compiler itself uses FNV, as it is not worried about //! denial-of-service attacks, and can assume that its inputs are going to be //! small—a perfect use case for FNV. //! //! //! ## Using FNV in a `HashMap` //! //! The `FnvHashMap` type alias is the easiest way to use the standard library’s //! `HashMap` with FNV. //! //! ```rust //! use fnv::FnvHashMap; //! //! let mut map = FnvHashMap::default(); //! map.insert(1, "one"); //! map.insert(2, "two"); //! //! map = FnvHashMap::with_capacity_and_hasher(10, Default::default()); //! map.insert(1, "one"); //! map.insert(2, "two"); //! ``` //! //! Note, the standard library’s `HashMap::new` and `HashMap::with_capacity` //! are only implemented for the `RandomState` hasher, so using `Default` to //! get the hasher is the next best option. //! //! ## Using FNV in a `HashSet` //! //! Similarly, `FnvHashSet` is a type alias for the standard library’s `HashSet` //! with FNV. //! //! ```rust //! use fnv::FnvHashSet; //! //! let mut set = FnvHashSet::default(); //! set.insert(1); //! set.insert(2); //! //! set = FnvHashSet::with_capacity_and_hasher(10, Default::default()); //! set.insert(1); //! set.insert(2); //! ``` //! //! [chongo]: http://www.isthe.com/chongo/tech/comp/fnv/index.html //! [faq]: https://www.rust-lang.org/en-US/faq.html#why-are-rusts-hashmaps-slow //! [graphs]: http://cglab.ca/~abeinges/blah/hash-rs/ use std::default::Default; use std::hash::{Hasher, BuildHasherDefault}; use std::collections::{HashMap, HashSet}; /// An implementation of the Fowler–Noll–Vo hash function. /// /// See the [crate documentation](index.html) for more details. #[allow(missing_copy_implementations)] pub struct FnvHasher(u64); impl Default for FnvHasher { #[inline] fn default() -> FnvHasher { FnvHasher(0xcbf29ce484222325) } } impl FnvHasher { /// Create an FNV hasher starting with a state corresponding /// to the hash `key`. #[inline] pub fn with_key(key: u64) -> FnvHasher { FnvHasher(key) } } impl Hasher for FnvHasher { #[inline] fn finish(&self) -> u64 { self.0 } #[inline] fn write(&mut self, bytes: &[u8]) { let FnvHasher(mut hash) = *self; for byte in bytes.iter() { hash = hash ^ (*byte as u64); hash = hash.wrapping_mul(0x100000001b3); } *self = FnvHasher(hash); } } /// A builder for default FNV hashers. pub type FnvBuildHasher = BuildHasherDefault; /// A `HashMap` using a default FNV hasher. pub type FnvHashMap = HashMap; /// A `HashSet` using a default FNV hasher. pub type FnvHashSet = HashSet; #[cfg(test)] mod test { use super::*; use std::hash::Hasher; fn fnv1a(bytes: &[u8]) -> u64 { let mut hasher = FnvHasher::default(); hasher.write(bytes); hasher.finish() } fn repeat_10(bytes: &[u8]) -> Vec { (0..10).flat_map(|_| bytes.iter().cloned()).collect() } fn repeat_500(bytes: &[u8]) -> Vec { (0..500).flat_map(|_| bytes.iter().cloned()).collect() } #[test] fn basic_tests() { assert_eq!(fnv1a(b""), 0xcbf29ce484222325); assert_eq!(fnv1a(b"a"), 0xaf63dc4c8601ec8c); assert_eq!(fnv1a(b"b"), 0xaf63df4c8601f1a5); assert_eq!(fnv1a(b"c"), 0xaf63de4c8601eff2); assert_eq!(fnv1a(b"d"), 0xaf63d94c8601e773); assert_eq!(fnv1a(b"e"), 0xaf63d84c8601e5c0); assert_eq!(fnv1a(b"f"), 0xaf63db4c8601ead9); assert_eq!(fnv1a(b"fo"), 0x08985907b541d342); assert_eq!(fnv1a(b"foo"), 0xdcb27518fed9d577); assert_eq!(fnv1a(b"foob"), 0xdd120e790c2512af); assert_eq!(fnv1a(b"fooba"), 0xcac165afa2fef40a); assert_eq!(fnv1a(b"foobar"), 0x85944171f73967e8); assert_eq!(fnv1a(b"\0"), 0xaf63bd4c8601b7df); assert_eq!(fnv1a(b"a\0"), 0x089be207b544f1e4); assert_eq!(fnv1a(b"b\0"), 0x08a61407b54d9b5f); assert_eq!(fnv1a(b"c\0"), 0x08a2ae07b54ab836); assert_eq!(fnv1a(b"d\0"), 0x0891b007b53c4869); assert_eq!(fnv1a(b"e\0"), 0x088e4a07b5396540); assert_eq!(fnv1a(b"f\0"), 0x08987c07b5420ebb); assert_eq!(fnv1a(b"fo\0"), 0xdcb28a18fed9f926); assert_eq!(fnv1a(b"foo\0"), 0xdd1270790c25b935); assert_eq!(fnv1a(b"foob\0"), 0xcac146afa2febf5d); assert_eq!(fnv1a(b"fooba\0"), 0x8593d371f738acfe); assert_eq!(fnv1a(b"foobar\0"), 0x34531ca7168b8f38); assert_eq!(fnv1a(b"ch"), 0x08a25607b54a22ae); assert_eq!(fnv1a(b"cho"), 0xf5faf0190cf90df3); assert_eq!(fnv1a(b"chon"), 0xf27397910b3221c7); assert_eq!(fnv1a(b"chong"), 0x2c8c2b76062f22e0); assert_eq!(fnv1a(b"chongo"), 0xe150688c8217b8fd); assert_eq!(fnv1a(b"chongo "), 0xf35a83c10e4f1f87); assert_eq!(fnv1a(b"chongo w"), 0xd1edd10b507344d0); assert_eq!(fnv1a(b"chongo wa"), 0x2a5ee739b3ddb8c3); assert_eq!(fnv1a(b"chongo was"), 0xdcfb970ca1c0d310); assert_eq!(fnv1a(b"chongo was "), 0x4054da76daa6da90); assert_eq!(fnv1a(b"chongo was h"), 0xf70a2ff589861368); assert_eq!(fnv1a(b"chongo was he"), 0x4c628b38aed25f17); assert_eq!(fnv1a(b"chongo was her"), 0x9dd1f6510f78189f); assert_eq!(fnv1a(b"chongo was here"), 0xa3de85bd491270ce); assert_eq!(fnv1a(b"chongo was here!"), 0x858e2fa32a55e61d); assert_eq!(fnv1a(b"chongo was here!\n"), 0x46810940eff5f915); assert_eq!(fnv1a(b"ch\0"), 0xf5fadd190cf8edaa); assert_eq!(fnv1a(b"cho\0"), 0xf273ed910b32b3e9); assert_eq!(fnv1a(b"chon\0"), 0x2c8c5276062f6525); assert_eq!(fnv1a(b"chong\0"), 0xe150b98c821842a0); assert_eq!(fnv1a(b"chongo\0"), 0xf35aa3c10e4f55e7); assert_eq!(fnv1a(b"chongo \0"), 0xd1ed680b50729265); assert_eq!(fnv1a(b"chongo w\0"), 0x2a5f0639b3dded70); assert_eq!(fnv1a(b"chongo wa\0"), 0xdcfbaa0ca1c0f359); assert_eq!(fnv1a(b"chongo was\0"), 0x4054ba76daa6a430); assert_eq!(fnv1a(b"chongo was \0"), 0xf709c7f5898562b0); assert_eq!(fnv1a(b"chongo was h\0"), 0x4c62e638aed2f9b8); assert_eq!(fnv1a(b"chongo was he\0"), 0x9dd1a8510f779415); assert_eq!(fnv1a(b"chongo was her\0"), 0xa3de2abd4911d62d); assert_eq!(fnv1a(b"chongo was here\0"), 0x858e0ea32a55ae0a); assert_eq!(fnv1a(b"chongo was here!\0"), 0x46810f40eff60347); assert_eq!(fnv1a(b"chongo was here!\n\0"), 0xc33bce57bef63eaf); assert_eq!(fnv1a(b"cu"), 0x08a24307b54a0265); assert_eq!(fnv1a(b"cur"), 0xf5b9fd190cc18d15); assert_eq!(fnv1a(b"curd"), 0x4c968290ace35703); assert_eq!(fnv1a(b"curds"), 0x07174bd5c64d9350); assert_eq!(fnv1a(b"curds "), 0x5a294c3ff5d18750); assert_eq!(fnv1a(b"curds a"), 0x05b3c1aeb308b843); assert_eq!(fnv1a(b"curds an"), 0xb92a48da37d0f477); assert_eq!(fnv1a(b"curds and"), 0x73cdddccd80ebc49); assert_eq!(fnv1a(b"curds and "), 0xd58c4c13210a266b); assert_eq!(fnv1a(b"curds and w"), 0xe78b6081243ec194); assert_eq!(fnv1a(b"curds and wh"), 0xb096f77096a39f34); assert_eq!(fnv1a(b"curds and whe"), 0xb425c54ff807b6a3); assert_eq!(fnv1a(b"curds and whey"), 0x23e520e2751bb46e); assert_eq!(fnv1a(b"curds and whey\n"), 0x1a0b44ccfe1385ec); assert_eq!(fnv1a(b"cu\0"), 0xf5ba4b190cc2119f); assert_eq!(fnv1a(b"cur\0"), 0x4c962690ace2baaf); assert_eq!(fnv1a(b"curd\0"), 0x0716ded5c64cda19); assert_eq!(fnv1a(b"curds\0"), 0x5a292c3ff5d150f0); assert_eq!(fnv1a(b"curds \0"), 0x05b3e0aeb308ecf0); assert_eq!(fnv1a(b"curds a\0"), 0xb92a5eda37d119d9); assert_eq!(fnv1a(b"curds an\0"), 0x73ce41ccd80f6635); assert_eq!(fnv1a(b"curds and\0"), 0xd58c2c132109f00b); assert_eq!(fnv1a(b"curds and \0"), 0xe78baf81243f47d1); assert_eq!(fnv1a(b"curds and w\0"), 0xb0968f7096a2ee7c); assert_eq!(fnv1a(b"curds and wh\0"), 0xb425a84ff807855c); assert_eq!(fnv1a(b"curds and whe\0"), 0x23e4e9e2751b56f9); assert_eq!(fnv1a(b"curds and whey\0"), 0x1a0b4eccfe1396ea); assert_eq!(fnv1a(b"curds and whey\n\0"), 0x54abd453bb2c9004); assert_eq!(fnv1a(b"hi"), 0x08ba5f07b55ec3da); assert_eq!(fnv1a(b"hi\0"), 0x337354193006cb6e); assert_eq!(fnv1a(b"hello"), 0xa430d84680aabd0b); assert_eq!(fnv1a(b"hello\0"), 0xa9bc8acca21f39b1); assert_eq!(fnv1a(b"\xff\x00\x00\x01"), 0x6961196491cc682d); assert_eq!(fnv1a(b"\x01\x00\x00\xff"), 0xad2bb1774799dfe9); assert_eq!(fnv1a(b"\xff\x00\x00\x02"), 0x6961166491cc6314); assert_eq!(fnv1a(b"\x02\x00\x00\xff"), 0x8d1bb3904a3b1236); assert_eq!(fnv1a(b"\xff\x00\x00\x03"), 0x6961176491cc64c7); assert_eq!(fnv1a(b"\x03\x00\x00\xff"), 0xed205d87f40434c7); assert_eq!(fnv1a(b"\xff\x00\x00\x04"), 0x6961146491cc5fae); assert_eq!(fnv1a(b"\x04\x00\x00\xff"), 0xcd3baf5e44f8ad9c); assert_eq!(fnv1a(b"\x40\x51\x4e\x44"), 0xe3b36596127cd6d8); assert_eq!(fnv1a(b"\x44\x4e\x51\x40"), 0xf77f1072c8e8a646); assert_eq!(fnv1a(b"\x40\x51\x4e\x4a"), 0xe3b36396127cd372); assert_eq!(fnv1a(b"\x4a\x4e\x51\x40"), 0x6067dce9932ad458); assert_eq!(fnv1a(b"\x40\x51\x4e\x54"), 0xe3b37596127cf208); assert_eq!(fnv1a(b"\x54\x4e\x51\x40"), 0x4b7b10fa9fe83936); assert_eq!(fnv1a(b"127.0.0.1"), 0xaabafe7104d914be); assert_eq!(fnv1a(b"127.0.0.1\0"), 0xf4d3180b3cde3eda); assert_eq!(fnv1a(b"127.0.0.2"), 0xaabafd7104d9130b); assert_eq!(fnv1a(b"127.0.0.2\0"), 0xf4cfb20b3cdb5bb1); assert_eq!(fnv1a(b"127.0.0.3"), 0xaabafc7104d91158); assert_eq!(fnv1a(b"127.0.0.3\0"), 0xf4cc4c0b3cd87888); assert_eq!(fnv1a(b"64.81.78.68"), 0xe729bac5d2a8d3a7); assert_eq!(fnv1a(b"64.81.78.68\0"), 0x74bc0524f4dfa4c5); assert_eq!(fnv1a(b"64.81.78.74"), 0xe72630c5d2a5b352); assert_eq!(fnv1a(b"64.81.78.74\0"), 0x6b983224ef8fb456); assert_eq!(fnv1a(b"64.81.78.84"), 0xe73042c5d2ae266d); assert_eq!(fnv1a(b"64.81.78.84\0"), 0x8527e324fdeb4b37); assert_eq!(fnv1a(b"feedface"), 0x0a83c86fee952abc); assert_eq!(fnv1a(b"feedface\0"), 0x7318523267779d74); assert_eq!(fnv1a(b"feedfacedaffdeed"), 0x3e66d3d56b8caca1); assert_eq!(fnv1a(b"feedfacedaffdeed\0"), 0x956694a5c0095593); assert_eq!(fnv1a(b"feedfacedeadbeef"), 0xcac54572bb1a6fc8); assert_eq!(fnv1a(b"feedfacedeadbeef\0"), 0xa7a4c9f3edebf0d8); assert_eq!(fnv1a(b"line 1\nline 2\nline 3"), 0x7829851fac17b143); assert_eq!(fnv1a(b"chongo /\\../\\"), 0x2c8f4c9af81bcf06); assert_eq!(fnv1a(b"chongo /\\../\\\0"), 0xd34e31539740c732); assert_eq!(fnv1a(b"chongo (Landon Curt Noll) /\\../\\"), 0x3605a2ac253d2db1); assert_eq!(fnv1a(b"chongo (Landon Curt Noll) /\\../\\\0"), 0x08c11b8346f4a3c3); assert_eq!(fnv1a(b"http://antwrp.gsfc.nasa.gov/apod/astropix.html"), 0x6be396289ce8a6da); assert_eq!(fnv1a(b"http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash"), 0xd9b957fb7fe794c5); assert_eq!(fnv1a(b"http://epod.usra.edu/"), 0x05be33da04560a93); assert_eq!(fnv1a(b"http://exoplanet.eu/"), 0x0957f1577ba9747c); assert_eq!(fnv1a(b"http://hvo.wr.usgs.gov/cam3/"), 0xda2cc3acc24fba57); assert_eq!(fnv1a(b"http://hvo.wr.usgs.gov/cams/HMcam/"), 0x74136f185b29e7f0); assert_eq!(fnv1a(b"http://hvo.wr.usgs.gov/kilauea/update/deformation.html"), 0xb2f2b4590edb93b2); assert_eq!(fnv1a(b"http://hvo.wr.usgs.gov/kilauea/update/images.html"), 0xb3608fce8b86ae04); assert_eq!(fnv1a(b"http://hvo.wr.usgs.gov/kilauea/update/maps.html"), 0x4a3a865079359063); assert_eq!(fnv1a(b"http://hvo.wr.usgs.gov/volcanowatch/current_issue.html"), 0x5b3a7ef496880a50); assert_eq!(fnv1a(b"http://neo.jpl.nasa.gov/risk/"), 0x48fae3163854c23b); assert_eq!(fnv1a(b"http://norvig.com/21-days.html"), 0x07aaa640476e0b9a); assert_eq!(fnv1a(b"http://primes.utm.edu/curios/home.php"), 0x2f653656383a687d); assert_eq!(fnv1a(b"http://slashdot.org/"), 0xa1031f8e7599d79c); assert_eq!(fnv1a(b"http://tux.wr.usgs.gov/Maps/155.25-19.5.html"), 0xa31908178ff92477); assert_eq!(fnv1a(b"http://volcano.wr.usgs.gov/kilaueastatus.php"), 0x097edf3c14c3fb83); assert_eq!(fnv1a(b"http://www.avo.alaska.edu/activity/Redoubt.php"), 0xb51ca83feaa0971b); assert_eq!(fnv1a(b"http://www.dilbert.com/fast/"), 0xdd3c0d96d784f2e9); assert_eq!(fnv1a(b"http://www.fourmilab.ch/gravitation/orbits/"), 0x86cd26a9ea767d78); assert_eq!(fnv1a(b"http://www.fpoa.net/"), 0xe6b215ff54a30c18); assert_eq!(fnv1a(b"http://www.ioccc.org/index.html"), 0xec5b06a1c5531093); assert_eq!(fnv1a(b"http://www.isthe.com/cgi-bin/number.cgi"), 0x45665a929f9ec5e5); assert_eq!(fnv1a(b"http://www.isthe.com/chongo/bio.html"), 0x8c7609b4a9f10907); assert_eq!(fnv1a(b"http://www.isthe.com/chongo/index.html"), 0x89aac3a491f0d729); assert_eq!(fnv1a(b"http://www.isthe.com/chongo/src/calc/lucas-calc"), 0x32ce6b26e0f4a403); assert_eq!(fnv1a(b"http://www.isthe.com/chongo/tech/astro/venus2004.html"), 0x614ab44e02b53e01); assert_eq!(fnv1a(b"http://www.isthe.com/chongo/tech/astro/vita.html"), 0xfa6472eb6eef3290); assert_eq!(fnv1a(b"http://www.isthe.com/chongo/tech/comp/c/expert.html"), 0x9e5d75eb1948eb6a); assert_eq!(fnv1a(b"http://www.isthe.com/chongo/tech/comp/calc/index.html"), 0xb6d12ad4a8671852); assert_eq!(fnv1a(b"http://www.isthe.com/chongo/tech/comp/fnv/index.html"), 0x88826f56eba07af1); assert_eq!(fnv1a(b"http://www.isthe.com/chongo/tech/math/number/howhigh.html"), 0x44535bf2645bc0fd); assert_eq!(fnv1a(b"http://www.isthe.com/chongo/tech/math/number/number.html"), 0x169388ffc21e3728); assert_eq!(fnv1a(b"http://www.isthe.com/chongo/tech/math/prime/mersenne.html"), 0xf68aac9e396d8224); assert_eq!(fnv1a(b"http://www.isthe.com/chongo/tech/math/prime/mersenne.html#largest"), 0x8e87d7e7472b3883); assert_eq!(fnv1a(b"http://www.lavarnd.org/cgi-bin/corpspeak.cgi"), 0x295c26caa8b423de); assert_eq!(fnv1a(b"http://www.lavarnd.org/cgi-bin/haiku.cgi"), 0x322c814292e72176); assert_eq!(fnv1a(b"http://www.lavarnd.org/cgi-bin/rand-none.cgi"), 0x8a06550eb8af7268); assert_eq!(fnv1a(b"http://www.lavarnd.org/cgi-bin/randdist.cgi"), 0xef86d60e661bcf71); assert_eq!(fnv1a(b"http://www.lavarnd.org/index.html"), 0x9e5426c87f30ee54); assert_eq!(fnv1a(b"http://www.lavarnd.org/what/nist-test.html"), 0xf1ea8aa826fd047e); assert_eq!(fnv1a(b"http://www.macosxhints.com/"), 0x0babaf9a642cb769); assert_eq!(fnv1a(b"http://www.mellis.com/"), 0x4b3341d4068d012e); assert_eq!(fnv1a(b"http://www.nature.nps.gov/air/webcams/parks/havoso2alert/havoalert.cfm"), 0xd15605cbc30a335c); assert_eq!(fnv1a(b"http://www.nature.nps.gov/air/webcams/parks/havoso2alert/timelines_24.cfm"), 0x5b21060aed8412e5); assert_eq!(fnv1a(b"http://www.paulnoll.com/"), 0x45e2cda1ce6f4227); assert_eq!(fnv1a(b"http://www.pepysdiary.com/"), 0x50ae3745033ad7d4); assert_eq!(fnv1a(b"http://www.sciencenews.org/index/home/activity/view"), 0xaa4588ced46bf414); assert_eq!(fnv1a(b"http://www.skyandtelescope.com/"), 0xc1b0056c4a95467e); assert_eq!(fnv1a(b"http://www.sput.nl/~rob/sirius.html"), 0x56576a71de8b4089); assert_eq!(fnv1a(b"http://www.systemexperts.com/"), 0xbf20965fa6dc927e); assert_eq!(fnv1a(b"http://www.tq-international.com/phpBB3/index.php"), 0x569f8383c2040882); assert_eq!(fnv1a(b"http://www.travelquesttours.com/index.htm"), 0xe1e772fba08feca0); assert_eq!(fnv1a(b"http://www.wunderground.com/global/stations/89606.html"), 0x4ced94af97138ac4); assert_eq!(fnv1a(&repeat_10(b"21701")), 0xc4112ffb337a82fb); assert_eq!(fnv1a(&repeat_10(b"M21701")), 0xd64a4fd41de38b7d); assert_eq!(fnv1a(&repeat_10(b"2^21701-1")), 0x4cfc32329edebcbb); assert_eq!(fnv1a(&repeat_10(b"\x54\xc5")), 0x0803564445050395); assert_eq!(fnv1a(&repeat_10(b"\xc5\x54")), 0xaa1574ecf4642ffd); assert_eq!(fnv1a(&repeat_10(b"23209")), 0x694bc4e54cc315f9); assert_eq!(fnv1a(&repeat_10(b"M23209")), 0xa3d7cb273b011721); assert_eq!(fnv1a(&repeat_10(b"2^23209-1")), 0x577c2f8b6115bfa5); assert_eq!(fnv1a(&repeat_10(b"\x5a\xa9")), 0xb7ec8c1a769fb4c1); assert_eq!(fnv1a(&repeat_10(b"\xa9\x5a")), 0x5d5cfce63359ab19); assert_eq!(fnv1a(&repeat_10(b"391581216093")), 0x33b96c3cd65b5f71); assert_eq!(fnv1a(&repeat_10(b"391581*2^216093-1")), 0xd845097780602bb9); assert_eq!(fnv1a(&repeat_10(b"\x05\xf9\x9d\x03\x4c\x81")), 0x84d47645d02da3d5); assert_eq!(fnv1a(&repeat_10(b"FEDCBA9876543210")), 0x83544f33b58773a5); assert_eq!(fnv1a(&repeat_10(b"\xfe\xdc\xba\x98\x76\x54\x32\x10")), 0x9175cbb2160836c5); assert_eq!(fnv1a(&repeat_10(b"EFCDAB8967452301")), 0xc71b3bc175e72bc5); assert_eq!(fnv1a(&repeat_10(b"\xef\xcd\xab\x89\x67\x45\x23\x01")), 0x636806ac222ec985); assert_eq!(fnv1a(&repeat_10(b"0123456789ABCDEF")), 0xb6ef0e6950f52ed5); assert_eq!(fnv1a(&repeat_10(b"\x01\x23\x45\x67\x89\xab\xcd\xef")), 0xead3d8a0f3dfdaa5); assert_eq!(fnv1a(&repeat_10(b"1032547698BADCFE")), 0x922908fe9a861ba5); assert_eq!(fnv1a(&repeat_10(b"\x10\x32\x54\x76\x98\xba\xdc\xfe")), 0x6d4821de275fd5c5); assert_eq!(fnv1a(&repeat_500(b"\x00")), 0x1fe3fce62bd816b5); assert_eq!(fnv1a(&repeat_500(b"\x07")), 0xc23e9fccd6f70591); assert_eq!(fnv1a(&repeat_500(b"~")), 0xc1af12bdfe16b5b5); assert_eq!(fnv1a(&repeat_500(b"\x7f")), 0x39e9f18f2f85e221); } } vendor/foreign-types-0.3.2/0000755000000000000000000000000013264166600014306 5ustar rootrootvendor/foreign-types-0.3.2/.cargo-checksum.json0000644000000000000000000000013113264166600020145 0ustar rootroot{"files":{},"package":"f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"}vendor/foreign-types-0.3.2/Cargo.toml0000644000000000000000000000151013264166600016233 0ustar rootroot# 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 = "foreign-types" version = "0.3.2" authors = ["Steven Fackler "] description = "A framework for Rust wrappers over C APIs" readme = "README.md" license = "MIT/Apache-2.0" repository = "https://github.com/sfackler/foreign-types" [dependencies.foreign-types-shared] version = "0.1" vendor/foreign-types-0.3.2/LICENSE-APACHE0000644000000000000000000002613613264166600016242 0ustar rootroot 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. vendor/foreign-types-0.3.2/LICENSE-MIT0000644000000000000000000000206013264166600015740 0ustar rootrootCopyright (c) 2017 The foreign-types 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. vendor/foreign-types-0.3.2/README.md0000644000000000000000000000133713264166600015571 0ustar rootroot# foreign-types [![CircleCI](https://circleci.com/gh/sfackler/foreign-types.svg?style=shield)](https://circleci.com/gh/sfackler/foreign-types) [Documentation](https://docs.rs/foreign-types) A framework for Rust wrappers over C APIs. ## License Licensed under either of * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. vendor/foreign-types-0.3.2/src/0000755000000000000000000000000013264166600015075 5ustar rootrootvendor/foreign-types-0.3.2/src/lib.rs0000644000000000000000000002030013264166600016204 0ustar rootroot//! A framework for Rust wrappers over C APIs. //! //! Ownership is as important in C as it is in Rust, but the semantics are often implicit. In //! particular, pointer-to-value is commonly used to pass C values both when transferring ownership //! or a borrow. //! //! This crate provides a framework to define a Rust wrapper over these kinds of raw C APIs in a way //! that allows ownership semantics to be expressed in an ergonomic manner. The framework takes a //! dual-type approach similar to APIs in the standard library such as `PathBuf`/`Path` or `String`/ //! `str`. One type represents an owned value and references to the other represent borrowed //! values. //! //! # Examples //! //! ``` //! use foreign_types::{ForeignType, ForeignTypeRef, Opaque}; //! use std::ops::{Deref, DerefMut}; //! //! mod foo_sys { //! pub enum FOO {} //! //! extern { //! pub fn FOO_free(foo: *mut FOO); //! } //! } //! //! // The borrowed type is a newtype wrapper around an `Opaque` value. //! // //! // `FooRef` values never exist; we instead create references to `FooRef`s //! // from raw C pointers. //! pub struct FooRef(Opaque); //! //! impl ForeignTypeRef for FooRef { //! type CType = foo_sys::FOO; //! } //! //! // The owned type is simply a newtype wrapper around the raw C type. //! // //! // It dereferences to `FooRef`, so methods that do not require ownership //! // should be defined there. //! pub struct Foo(*mut foo_sys::FOO); //! //! impl Drop for Foo { //! fn drop(&mut self) { //! unsafe { foo_sys::FOO_free(self.0) } //! } //! } //! //! impl ForeignType for Foo { //! type CType = foo_sys::FOO; //! type Ref = FooRef; //! //! unsafe fn from_ptr(ptr: *mut foo_sys::FOO) -> Foo { //! Foo(ptr) //! } //! //! fn as_ptr(&self) -> *mut foo_sys::FOO { //! self.0 //! } //! } //! //! impl Deref for Foo { //! type Target = FooRef; //! //! fn deref(&self) -> &FooRef { //! unsafe { FooRef::from_ptr(self.0) } //! } //! } //! //! impl DerefMut for Foo { //! fn deref_mut(&mut self) -> &mut FooRef { //! unsafe { FooRef::from_ptr_mut(self.0) } //! } //! } //! ``` //! //! The `foreign_type!` macro can generate this boilerplate for you: //! //! ``` //! #[macro_use] //! extern crate foreign_types; //! //! mod foo_sys { //! pub enum FOO {} //! //! extern { //! pub fn FOO_free(foo: *mut FOO); //! pub fn FOO_duplicate(foo: *mut FOO) -> *mut FOO; // Optional //! } //! } //! //! foreign_type! { //! type CType = foo_sys::FOO; //! fn drop = foo_sys::FOO_free; //! fn clone = foo_sys::FOO_duplicate; // Optional //! /// A Foo. //! pub struct Foo; //! /// A borrowed Foo. //! pub struct FooRef; //! } //! //! # fn main() {} //! ``` //! //! If `fn clone` is specified, then it must take `CType` as an argument and return a copy of it as `CType`. //! It will be used to implement `ToOwned` and `Clone`. //! //! `#[derive(…)] is permitted before the lines with `pub struct`. //! `#[doc(hidden)]` before the `type CType` line will hide the `foreign_type!` implementations from documentation. //! //! Say we then have a separate type in our C API that contains a `FOO`: //! //! ``` //! mod foo_sys { //! pub enum FOO {} //! pub enum BAR {} //! //! extern { //! pub fn FOO_free(foo: *mut FOO); //! pub fn BAR_free(bar: *mut BAR); //! pub fn BAR_get_foo(bar: *mut BAR) -> *mut FOO; //! } //! } //! ``` //! //! The documentation for the C library states that `BAR_get_foo` returns a reference into the `BAR` //! passed to it, which translates into a reference in Rust. It also says that we're allowed to //! modify the `FOO`, so we'll define a pair of accessor methods, one immutable and one mutable: //! //! ``` //! #[macro_use] //! extern crate foreign_types; //! //! use foreign_types::ForeignTypeRef; //! //! mod foo_sys { //! pub enum FOO {} //! pub enum BAR {} //! //! extern { //! pub fn FOO_free(foo: *mut FOO); //! pub fn BAR_free(bar: *mut BAR); //! pub fn BAR_get_foo(bar: *mut BAR) -> *mut FOO; //! } //! } //! //! foreign_type! { //! #[doc(hidden)] //! type CType = foo_sys::FOO; //! fn drop = foo_sys::FOO_free; //! /// A Foo. //! pub struct Foo; //! /// A borrowed Foo. //! pub struct FooRef; //! } //! //! foreign_type! { //! type CType = foo_sys::BAR; //! fn drop = foo_sys::BAR_free; //! /// A Foo. //! pub struct Bar; //! /// A borrowed Bar. //! pub struct BarRef; //! } //! //! impl BarRef { //! fn foo(&self) -> &FooRef { //! unsafe { FooRef::from_ptr(foo_sys::BAR_get_foo(self.as_ptr())) } //! } //! //! fn foo_mut(&mut self) -> &mut FooRef { //! unsafe { FooRef::from_ptr_mut(foo_sys::BAR_get_foo(self.as_ptr())) } //! } //! } //! //! # fn main() {} //! ``` #![no_std] #![warn(missing_docs)] #![doc(html_root_url="https://docs.rs/foreign-types/0.3")] extern crate foreign_types_shared; #[doc(inline)] pub use foreign_types_shared::*; /// A macro to easily define wrappers for foreign types. /// /// # Examples /// /// ``` /// #[macro_use] /// extern crate foreign_types; /// /// # mod openssl_sys { pub type SSL = (); pub unsafe fn SSL_free(_: *mut SSL) {} pub unsafe fn SSL_dup(x: *mut SSL) -> *mut SSL {x} } /// foreign_type! { /// type CType = openssl_sys::SSL; /// fn drop = openssl_sys::SSL_free; /// fn clone = openssl_sys::SSL_dup; /// /// Documentation for the owned type. /// pub struct Ssl; /// /// Documentation for the borrowed type. /// pub struct SslRef; /// } /// /// # fn main() {} /// ``` #[macro_export] macro_rules! foreign_type { ( $(#[$impl_attr:meta])* type CType = $ctype:ty; fn drop = $drop:expr; $(fn clone = $clone:expr;)* $(#[$owned_attr:meta])* pub struct $owned:ident; $(#[$borrowed_attr:meta])* pub struct $borrowed:ident; ) => { $(#[$owned_attr])* pub struct $owned(*mut $ctype); $(#[$impl_attr])* impl $crate::ForeignType for $owned { type CType = $ctype; type Ref = $borrowed; #[inline] unsafe fn from_ptr(ptr: *mut $ctype) -> $owned { $owned(ptr) } #[inline] fn as_ptr(&self) -> *mut $ctype { self.0 } } impl Drop for $owned { #[inline] fn drop(&mut self) { unsafe { $drop(self.0) } } } $( impl Clone for $owned { #[inline] fn clone(&self) -> $owned { unsafe { let handle: *mut $ctype = $clone(self.0); $crate::ForeignType::from_ptr(handle) } } } impl ::std::borrow::ToOwned for $borrowed { type Owned = $owned; #[inline] fn to_owned(&self) -> $owned { unsafe { let handle: *mut $ctype = $clone($crate::ForeignTypeRef::as_ptr(self)); $crate::ForeignType::from_ptr(handle) } } } )* impl ::std::ops::Deref for $owned { type Target = $borrowed; #[inline] fn deref(&self) -> &$borrowed { unsafe { $crate::ForeignTypeRef::from_ptr(self.0) } } } impl ::std::ops::DerefMut for $owned { #[inline] fn deref_mut(&mut self) -> &mut $borrowed { unsafe { $crate::ForeignTypeRef::from_ptr_mut(self.0) } } } impl ::std::borrow::Borrow<$borrowed> for $owned { #[inline] fn borrow(&self) -> &$borrowed { &**self } } impl ::std::convert::AsRef<$borrowed> for $owned { #[inline] fn as_ref(&self) -> &$borrowed { &**self } } $(#[$borrowed_attr])* pub struct $borrowed($crate::Opaque); $(#[$impl_attr])* impl $crate::ForeignTypeRef for $borrowed { type CType = $ctype; } } } vendor/foreign-types-shared-0.1.1/0000755000000000000000000000000013264166600015547 5ustar rootrootvendor/foreign-types-shared-0.1.1/.cargo-checksum.json0000644000000000000000000000013113264166600021406 0ustar rootroot{"files":{},"package":"00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"}vendor/foreign-types-shared-0.1.1/Cargo.toml0000644000000000000000000000142413264166600017500 0ustar rootroot# 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 = "foreign-types-shared" version = "0.1.1" authors = ["Steven Fackler "] description = "An internal crate used by foreign-types" license = "MIT/Apache-2.0" repository = "https://github.com/sfackler/foreign-types" [dependencies] vendor/foreign-types-shared-0.1.1/LICENSE-APACHE0000644000000000000000000002613613264166600017503 0ustar rootroot 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. vendor/foreign-types-shared-0.1.1/LICENSE-MIT0000644000000000000000000000206013264166600017201 0ustar rootrootCopyright (c) 2017 The foreign-types 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. vendor/foreign-types-shared-0.1.1/src/0000755000000000000000000000000013264166600016336 5ustar rootrootvendor/foreign-types-shared-0.1.1/src/lib.rs0000644000000000000000000000272113264166600017454 0ustar rootroot//! Internal crate used by foreign-types #![no_std] #![warn(missing_docs)] #![doc(html_root_url="https://docs.rs/foreign-types-shared/0.1")] use core::cell::UnsafeCell; /// An opaque type used to define `ForeignTypeRef` types. /// /// A type implementing `ForeignTypeRef` should simply be a newtype wrapper around this type. pub struct Opaque(UnsafeCell<()>); /// A type implemented by wrappers over foreign types. pub trait ForeignType: Sized { /// The raw C type. type CType; /// The type representing a reference to this type. type Ref: ForeignTypeRef; /// Constructs an instance of this type from its raw type. unsafe fn from_ptr(ptr: *mut Self::CType) -> Self; /// Returns a raw pointer to the wrapped value. fn as_ptr(&self) -> *mut Self::CType; } /// A trait implemented by types which reference borrowed foreign types. pub trait ForeignTypeRef: Sized { /// The raw C type. type CType; /// Constructs a shared instance of this type from its raw type. #[inline] unsafe fn from_ptr<'a>(ptr: *mut Self::CType) -> &'a Self { &*(ptr as *mut _) } /// Constructs a mutable reference of this type from its raw type. #[inline] unsafe fn from_ptr_mut<'a>(ptr: *mut Self::CType) -> &'a mut Self { &mut *(ptr as *mut _) } /// Returns a raw pointer to the wrapped value. #[inline] fn as_ptr(&self) -> *mut Self::CType { self as *const _ as *mut _ } } vendor/fs2-0.4.3/0000755000000000000000000000000013264166600012207 5ustar rootrootvendor/fs2-0.4.3/.appveyor.yml0000644000000000000000000000077313264166600014664 0ustar rootrootenvironment: matrix: - TARGET: x86_64-pc-windows-msvc - TARGET: i686-pc-windows-msvc - TARGET: x86_64-pc-windows-gnu - TARGET: i686-pc-windows-gnu install: - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe" -FileName "rust-nightly.exe" - ps: .\rust-nightly.exe /VERYSILENT /NORESTART /DIR="C:\rust" | Out-Null - ps: $env:PATH="$env:PATH;C:\rust\bin" build_script: - cargo build -v test_script: - SET RUST_BACKTRACE=1 - cargo test -v vendor/fs2-0.4.3/.cargo-checksum.json0000644000000000000000000000013113264166600016046 0ustar rootroot{"files":{},"package":"9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"}vendor/fs2-0.4.3/.travis.yml0000644000000000000000000000040113264166600014313 0ustar rootrootlanguage: rust rust: - 1.8.0 - stable - nightly os: - linux - osx env: matrix: - ARCH=x86_64 - ARCH=i686 script: - cargo build --verbose - if [[ $TRAVIS_RUST_VERSION = nightly* ]]; then env RUST_BACKTRACE=1 cargo test -v; fi vendor/fs2-0.4.3/Cargo.toml0000644000000000000000000000227213264166600014142 0ustar rootroot# 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 = "fs2" version = "0.4.3" authors = ["Dan Burkert "] description = "Cross-platform file locks and file duplication." documentation = "https://docs.rs/fs2" keywords = ["file", "file-system", "lock", "duplicate", "flock"] license = "MIT/Apache-2.0" repository = "https://github.com/danburkert/fs2-rs" [dev-dependencies.tempdir] version = "0.3" [target."cfg(unix)".dependencies.libc] version = "0.2.30" [target."cfg(windows)".dependencies.winapi] version = "0.3" features = ["handleapi", "processthreadsapi", "winerror", "fileapi", "winbase", "std"] [badges.appveyor] repository = "danburkert/fs2-rs" [badges.travis-ci] repository = "danburkert/fs2-rs" vendor/fs2-0.4.3/LICENSE-APACHE0000644000000000000000000002513713264166600014143 0ustar rootroot 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. vendor/fs2-0.4.3/LICENSE-MIT0000644000000000000000000000205713264166600013647 0ustar rootrootCopyright (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. vendor/fs2-0.4.3/README.md0000644000000000000000000000353113264166600013470 0ustar rootroot# fs2 Extended utilities for working with files and filesystems in Rust. `fs2` requires Rust stable 1.8 or greater. [![Build Status](https://travis-ci.org/danburkert/fs2-rs.svg?branch=master)](https://travis-ci.org/danburkert/fs2-rs) [![Windows Build status](https://ci.appveyor.com/api/projects/status/iuvjv1aaaml0rntt/branch/master?svg=true)](https://ci.appveyor.com/project/danburkert/fs2-rs/branch/master) [![Documentation](https://docs.rs/fs2/badge.svg)](https://docs.rs/memmap) [![Crate](https://img.shields.io/crates/v/fs2.svg)](https://crates.io/crates/memmap) ## Features - [x] file descriptor duplication. - [x] file locks. - [x] file (pre)allocation. - [x] file allocation information. - [x] filesystem space usage information. ## Platforms `fs2` should work on any platform supported by [`libc`](https://github.com/rust-lang-nursery/libc#platforms-and-documentation). `fs2` is continuously tested on: * `x86_64-unknown-linux-gnu` (Linux) * `i686-unknown-linux-gnu` * `x86_64-apple-darwin` (OSX) * `i686-apple-darwin` * `x86_64-pc-windows-msvc` (Windows) * `i686-pc-windows-msvc` * `x86_64-pc-windows-gnu` * `i686-pc-windows-gnu` ## Benchmarks Simple benchmarks are provided for the methods provided. Many of these benchmarks use files in a temporary directory. On many modern Linux distros the default temporary directory, `/tmp`, is mounted on a tempfs filesystem, which will have different performance characteristics than a disk-backed filesystem. The temporary directory is configurable at runtime through the environment (see [`env::temp_dir`](https://doc.rust-lang.org/stable/std/env/fn.temp_dir.html)). ## License `fs2` is primarily distributed under the terms of both the MIT license and the Apache License (Version 2.0). See [LICENSE-APACHE](LICENSE-APACHE), [LICENSE-MIT](LICENSE-MIT) for details. Copyright (c) 2015 Dan Burkert. vendor/fs2-0.4.3/src/0000755000000000000000000000000013264166600012776 5ustar rootrootvendor/fs2-0.4.3/src/lib.rs0000644000000000000000000004002313264166600014111 0ustar rootroot//! Extended utilities for working with files and filesystems in Rust. #![doc(html_root_url = "https://docs.rs/fs2/0.4.3")] #![cfg_attr(test, feature(test))] #[cfg(windows)] extern crate winapi; #[cfg(unix)] mod unix; #[cfg(unix)] use unix as sys; #[cfg(windows)] mod windows; #[cfg(windows)] use windows as sys; use std::fs::File; use std::io::{Error, Result}; use std::path::Path; /// Extension trait for `std::fs::File` which provides allocation, duplication and locking methods. /// /// ## Notes on File Locks /// /// This library provides whole-file locks in both shared (read) and exclusive /// (read-write) varieties. /// /// File locks are a cross-platform hazard since the file lock APIs exposed by /// operating system kernels vary in subtle and not-so-subtle ways. /// /// The API exposed by this library can be safely used across platforms as long /// as the following rules are followed: /// /// * Multiple locks should not be created on an individual `File` instance /// concurrently. /// * Duplicated files should not be locked without great care. /// * Files to be locked should be opened with at least read or write /// permissions. /// * File locks may only be relied upon to be advisory. /// /// See the tests in `lib.rs` for cross-platform lock behavior that may be /// relied upon; see the tests in `unix.rs` and `windows.rs` for examples of /// platform-specific behavior. File locks are implemented with /// [`flock(2)`](http://man7.org/linux/man-pages/man2/flock.2.html) on Unix and /// [`LockFile`](https://msdn.microsoft.com/en-us/library/windows/desktop/aa365202(v=vs.85).aspx) /// on Windows. pub trait FileExt { /// Returns a duplicate instance of the file. /// /// The returned file will share the same file position as the original /// file. /// /// If using rustc version 1.9 or later, prefer using `File::try_clone` to this. /// /// # Notes /// /// This is implemented with /// [`dup(2)`](http://man7.org/linux/man-pages/man2/dup.2.html) on Unix and /// [`DuplicateHandle`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms724251(v=vs.85).aspx) /// on Windows. fn duplicate(&self) -> Result; /// Returns the amount of physical space allocated for a file. fn allocated_size(&self) -> Result; /// Ensures that at least `len` bytes of disk space are allocated for the /// file, and the file size is at least `len` bytes. After a successful call /// to `allocate`, subsequent writes to the file within the specified length /// are guaranteed not to fail because of lack of disk space. fn allocate(&self, len: u64) -> Result<()>; /// Locks the file for shared usage, blocking if the file is currently /// locked exclusively. fn lock_shared(&self) -> Result<()>; /// Locks the file for exclusive usage, blocking if the file is currently /// locked. fn lock_exclusive(&self) -> Result<()>; /// Locks the file for shared usage, or returns a an error if the file is /// currently locked (see `lock_contended_error`). fn try_lock_shared(&self) -> Result<()>; /// Locks the file for shared usage, or returns a an error if the file is /// currently locked (see `lock_contended_error`). fn try_lock_exclusive(&self) -> Result<()>; /// Unlocks the file. fn unlock(&self) -> Result<()>; } impl FileExt for File { fn duplicate(&self) -> Result { sys::duplicate(self) } fn allocated_size(&self) -> Result { sys::allocated_size(self) } fn allocate(&self, len: u64) -> Result<()> { sys::allocate(self, len) } fn lock_shared(&self) -> Result<()> { sys::lock_shared(self) } fn lock_exclusive(&self) -> Result<()> { sys::lock_exclusive(self) } fn try_lock_shared(&self) -> Result<()> { sys::try_lock_shared(self) } fn try_lock_exclusive(&self) -> Result<()> { sys::try_lock_exclusive(self) } fn unlock(&self) -> Result<()> { sys::unlock(self) } } /// Returns the error that a call to a try lock method on a contended file will /// return. pub fn lock_contended_error() -> Error { sys::lock_error() } /// `FsStats` contains some common stats about a file system. #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct FsStats { free_space: u64, available_space: u64, total_space: u64, allocation_granularity: u64, } impl FsStats { /// Returns the number of free bytes in the file system containing the provided /// path. pub fn free_space(&self) -> u64 { self.free_space } /// Returns the available space in bytes to non-priveleged users in the file /// system containing the provided path. pub fn available_space(&self) -> u64 { self.available_space } /// Returns the total space in bytes in the file system containing the provided /// path. pub fn total_space(&self) -> u64 { self.total_space } /// Returns the filesystem's disk space allocation granularity in bytes. /// The provided path may be for any file in the filesystem. /// /// On Posix, this is equivalent to the filesystem's block size. /// On Windows, this is equivalent to the filesystem's cluster size. pub fn allocation_granularity(&self) -> u64 { self.allocation_granularity } } /// Get the stats of the file system containing the provided path. pub fn statvfs

(path: P) -> Result where P: AsRef { sys::statvfs(path.as_ref()) } /// Returns the number of free bytes in the file system containing the provided /// path. pub fn free_space

(path: P) -> Result where P: AsRef { statvfs(path).map(|stat| stat.free_space) } /// Returns the available space in bytes to non-priveleged users in the file /// system containing the provided path. pub fn available_space

(path: P) -> Result where P: AsRef { statvfs(path).map(|stat| stat.available_space) } /// Returns the total space in bytes in the file system containing the provided /// path. pub fn total_space

(path: P) -> Result where P: AsRef { statvfs(path).map(|stat| stat.total_space) } /// Returns the filesystem's disk space allocation granularity in bytes. /// The provided path may be for any file in the filesystem. /// /// On Posix, this is equivalent to the filesystem's block size. /// On Windows, this is equivalent to the filesystem's cluster size. pub fn allocation_granularity

(path: P) -> Result where P: AsRef { statvfs(path).map(|stat| stat.allocation_granularity) } #[cfg(test)] mod test { extern crate tempdir; extern crate test; use std::fs; use super::*; use std::io::{Read, Seek, SeekFrom, Write}; /// Tests file duplication. #[test] fn duplicate() { let tempdir = tempdir::TempDir::new("fs2").unwrap(); let path = tempdir.path().join("fs2"); let mut file1 = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap(); let mut file2 = file1.duplicate().unwrap(); // Write into the first file and then drop it. file1.write_all(b"foo").unwrap(); drop(file1); let mut buf = vec![]; // Read from the second file; since the position is shared it will already be at EOF. file2.read_to_end(&mut buf).unwrap(); assert_eq!(0, buf.len()); // Rewind and read. file2.seek(SeekFrom::Start(0)).unwrap(); file2.read_to_end(&mut buf).unwrap(); assert_eq!(&buf, &b"foo"); } /// Tests shared file lock operations. #[test] fn lock_shared() { let tempdir = tempdir::TempDir::new("fs2").unwrap(); let path = tempdir.path().join("fs2"); let file1 = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap(); let file2 = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap(); let file3 = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap(); // Concurrent shared access is OK, but not shared and exclusive. file1.lock_shared().unwrap(); file2.lock_shared().unwrap(); assert_eq!(file3.try_lock_exclusive().unwrap_err().kind(), lock_contended_error().kind()); file1.unlock().unwrap(); assert_eq!(file3.try_lock_exclusive().unwrap_err().kind(), lock_contended_error().kind()); // Once all shared file locks are dropped, an exclusive lock may be created; file2.unlock().unwrap(); file3.lock_exclusive().unwrap(); } /// Tests exclusive file lock operations. #[test] fn lock_exclusive() { let tempdir = tempdir::TempDir::new("fs2").unwrap(); let path = tempdir.path().join("fs2"); let file1 = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap(); let file2 = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap(); // No other access is possible once an exclusive lock is created. file1.lock_exclusive().unwrap(); assert_eq!(file2.try_lock_exclusive().unwrap_err().kind(), lock_contended_error().kind()); assert_eq!(file2.try_lock_shared().unwrap_err().kind(), lock_contended_error().kind()); // Once the exclusive lock is dropped, the second file is able to create a lock. file1.unlock().unwrap(); file2.lock_exclusive().unwrap(); } /// Tests that a lock is released after the file that owns it is dropped. #[test] fn lock_cleanup() { let tempdir = tempdir::TempDir::new("fs2").unwrap(); let path = tempdir.path().join("fs2"); let file1 = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap(); let file2 = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap(); file1.lock_exclusive().unwrap(); assert_eq!(file2.try_lock_shared().unwrap_err().kind(), lock_contended_error().kind()); // Drop file1; the lock should be released. drop(file1); file2.lock_shared().unwrap(); } /// Tests file allocation. #[test] fn allocate() { let tempdir = tempdir::TempDir::new("fs2").unwrap(); let path = tempdir.path().join("fs2"); let file = fs::OpenOptions::new().write(true).create(true).open(&path).unwrap(); let blksize = allocation_granularity(&path).unwrap(); // New files are created with no allocated size. assert_eq!(0, file.allocated_size().unwrap()); assert_eq!(0, file.metadata().unwrap().len()); // Allocate space for the file, checking that the allocated size steps // up by block size, and the file length matches the allocated size. file.allocate(2 * blksize - 1).unwrap(); assert_eq!(2 * blksize, file.allocated_size().unwrap()); assert_eq!(2 * blksize - 1, file.metadata().unwrap().len()); // Truncate the file, checking that the allocated size steps down by // block size. file.set_len(blksize + 1).unwrap(); assert_eq!(2 * blksize, file.allocated_size().unwrap()); assert_eq!(blksize + 1, file.metadata().unwrap().len()); } /// Checks filesystem space methods. #[test] fn filesystem_space() { let tempdir = tempdir::TempDir::new("fs2").unwrap(); let total_space = total_space(&tempdir.path()).unwrap(); let free_space = free_space(&tempdir.path()).unwrap(); let available_space = available_space(&tempdir.path()).unwrap(); assert!(total_space > free_space); assert!(total_space > available_space); assert!(available_space <= free_space); } /// Benchmarks creating and removing a file. This is a baseline benchmark /// for comparing against the truncate and allocate benchmarks. #[bench] fn bench_file_create(b: &mut test::Bencher) { let tempdir = tempdir::TempDir::new("fs2").unwrap(); let path = tempdir.path().join("file"); b.iter(|| { fs::OpenOptions::new() .read(true) .write(true) .create(true) .open(&path) .unwrap(); fs::remove_file(&path).unwrap(); }); } /// Benchmarks creating a file, truncating it to 32MiB, and deleting it. #[bench] fn bench_file_truncate(b: &mut test::Bencher) { let size = 32 * 1024 * 1024; let tempdir = tempdir::TempDir::new("fs2").unwrap(); let path = tempdir.path().join("file"); b.iter(|| { let file = fs::OpenOptions::new() .read(true) .write(true) .create(true) .open(&path) .unwrap(); file.set_len(size).unwrap(); fs::remove_file(&path).unwrap(); }); } /// Benchmarks creating a file, allocating 32MiB for it, and deleting it. #[bench] fn bench_file_allocate(b: &mut test::Bencher) { let size = 32 * 1024 * 1024; let tempdir = tempdir::TempDir::new("fs2").unwrap(); let path = tempdir.path().join("file"); b.iter(|| { let file = fs::OpenOptions::new() .read(true) .write(true) .create(true) .open(&path) .unwrap(); file.allocate(size).unwrap(); fs::remove_file(&path).unwrap(); }); } /// Benchmarks creating a file, allocating 32MiB for it, and deleting it. #[bench] fn bench_allocated_size(b: &mut test::Bencher) { let size = 32 * 1024 * 1024; let tempdir = tempdir::TempDir::new("fs2").unwrap(); let path = tempdir.path().join("file"); let file = fs::OpenOptions::new() .read(true) .write(true) .create(true) .open(&path) .unwrap(); file.allocate(size).unwrap(); b.iter(|| { file.allocated_size().unwrap(); }); } /// Benchmarks duplicating a file descriptor or handle. #[bench] fn bench_duplicate(b: &mut test::Bencher) { let tempdir = tempdir::TempDir::new("fs2").unwrap(); let path = tempdir.path().join("fs2"); let file = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap(); b.iter(|| test::black_box(file.duplicate().unwrap())); } /// Benchmarks locking and unlocking a file lock. #[bench] fn bench_lock_unlock(b: &mut test::Bencher) { let tempdir = tempdir::TempDir::new("fs2").unwrap(); let path = tempdir.path().join("fs2"); let file = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap(); b.iter(|| { file.lock_exclusive().unwrap(); file.unlock().unwrap(); }); } /// Benchmarks the free space method. #[bench] fn bench_free_space(b: &mut test::Bencher) { let tempdir = tempdir::TempDir::new("fs2").unwrap(); b.iter(|| { test::black_box(free_space(&tempdir.path()).unwrap()); }); } /// Benchmarks the available space method. #[bench] fn bench_available_space(b: &mut test::Bencher) { let tempdir = tempdir::TempDir::new("fs2").unwrap(); b.iter(|| { test::black_box(available_space(&tempdir.path()).unwrap()); }); } /// Benchmarks the total space method. #[bench] fn bench_total_space(b: &mut test::Bencher) { let tempdir = tempdir::TempDir::new("fs2").unwrap(); b.iter(|| { test::black_box(total_space(&tempdir.path()).unwrap()); }); } } vendor/fs2-0.4.3/src/unix.rs0000644000000000000000000001772013264166600014336 0ustar rootrootextern crate libc; use std::ffi::CString; use std::fs::File; use std::io::{Error, ErrorKind, Result}; use std::mem; use std::os::unix::ffi::OsStrExt; use std::os::unix::fs::MetadataExt; use std::os::unix::io::{AsRawFd, FromRawFd}; use std::path::Path; use FsStats; pub fn duplicate(file: &File) -> Result { unsafe { let fd = libc::dup(file.as_raw_fd()); if fd < 0 { Err(Error::last_os_error()) } else { Ok(File::from_raw_fd(fd)) } } } pub fn lock_shared(file: &File) -> Result<()> { flock(file, libc::LOCK_SH) } pub fn lock_exclusive(file: &File) -> Result<()> { flock(file, libc::LOCK_EX) } pub fn try_lock_shared(file: &File) -> Result<()> { flock(file, libc::LOCK_SH | libc::LOCK_NB) } pub fn try_lock_exclusive(file: &File) -> Result<()> { flock(file, libc::LOCK_EX | libc::LOCK_NB) } pub fn unlock(file: &File) -> Result<()> { flock(file, libc::LOCK_UN) } pub fn lock_error() -> Error { Error::from_raw_os_error(libc::EWOULDBLOCK) } #[cfg(not(target_os = "solaris"))] fn flock(file: &File, flag: libc::c_int) -> Result<()> { let ret = unsafe { libc::flock(file.as_raw_fd(), flag) }; if ret < 0 { Err(Error::last_os_error()) } else { Ok(()) } } /// Simulate flock() using fcntl(); primarily for Oracle Solaris. #[cfg(target_os = "solaris")] fn flock(file: &File, flag: libc::c_int) -> Result<()> { let mut fl = libc::flock { l_whence: 0, l_start: 0, l_len: 0, l_type: 0, l_pad: [0; 4], l_pid: 0, l_sysid: 0, }; // In non-blocking mode, use F_SETLK for cmd, F_SETLKW otherwise, and don't forget to clear // LOCK_NB. let (cmd, operation) = match flag & libc::LOCK_NB { 0 => (libc::F_SETLKW, flag), _ => (libc::F_SETLK, flag & !libc::LOCK_NB), }; match operation { libc::LOCK_SH => fl.l_type |= libc::F_RDLCK, libc::LOCK_EX => fl.l_type |= libc::F_WRLCK, libc::LOCK_UN => fl.l_type |= libc::F_UNLCK, _ => return Err(Error::from_raw_os_error(libc::EINVAL)), } let ret = unsafe { libc::fcntl(file.as_raw_fd(), cmd, &fl) }; match ret { // Translate EACCES to EWOULDBLOCK -1 => match Error::last_os_error().raw_os_error() { Some(libc::EACCES) => return Err(lock_error()), _ => return Err(Error::last_os_error()) }, _ => Ok(()) } } pub fn allocated_size(file: &File) -> Result { file.metadata().map(|m| m.blocks() as u64 * 512) } #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "android", target_os = "nacl"))] pub fn allocate(file: &File, len: u64) -> Result<()> { let ret = unsafe { libc::posix_fallocate(file.as_raw_fd(), 0, len as libc::off_t) }; if ret == 0 { Ok(()) } else { Err(Error::last_os_error()) } } #[cfg(any(target_os = "macos", target_os = "ios"))] pub fn allocate(file: &File, len: u64) -> Result<()> { let stat = try!(file.metadata()); if len > stat.blocks() as u64 * 512 { let mut fstore = libc::fstore_t { fst_flags: libc::F_ALLOCATECONTIG, fst_posmode: libc::F_PEOFPOSMODE, fst_offset: 0, fst_length: len as libc::off_t, fst_bytesalloc: 0, }; let ret = unsafe { libc::fcntl(file.as_raw_fd(), libc::F_PREALLOCATE, &fstore) }; if ret == -1 { // Unable to allocate contiguous disk space; attempt to allocate non-contiguously. fstore.fst_flags = libc::F_ALLOCATEALL; let ret = unsafe { libc::fcntl(file.as_raw_fd(), libc::F_PREALLOCATE, &fstore) }; if ret == -1 { return Err(Error::last_os_error()); } } } if len > stat.size() as u64 { file.set_len(len) } else { Ok(()) } } #[cfg(any(target_os = "openbsd", target_os = "netbsd", target_os = "dragonfly", target_os = "solaris", target_os = "haiku"))] pub fn allocate(file: &File, len: u64) -> Result<()> { // No file allocation API available, just set the length if necessary. if len > try!(file.metadata()).len() as u64 { file.set_len(len) } else { Ok(()) } } pub fn statvfs(path: &Path) -> Result { let cstr = match CString::new(path.as_os_str().as_bytes()) { Ok(cstr) => cstr, Err(..) => return Err(Error::new(ErrorKind::InvalidInput, "path contained a null")), }; unsafe { let mut stat: libc::statvfs = mem::zeroed(); // danburkert/fs2-rs#1: cast is necessary for platforms where c_char != u8. if libc::statvfs(cstr.as_ptr() as *const _, &mut stat) != 0 { Err(Error::last_os_error()) } else { Ok(FsStats { free_space: stat.f_frsize as u64 * stat.f_bfree as u64, available_space: stat.f_frsize as u64 * stat.f_bavail as u64, total_space: stat.f_frsize as u64 * stat.f_blocks as u64, allocation_granularity: stat.f_frsize as u64, }) } } } #[cfg(test)] mod test { extern crate tempdir; extern crate libc; use std::fs::{self, File}; use std::os::unix::io::AsRawFd; use {FileExt, lock_contended_error}; /// The duplicate method returns a file with a new file descriptor. #[test] fn duplicate_new_fd() { let tempdir = tempdir::TempDir::new("fs2").unwrap(); let path = tempdir.path().join("fs2"); let file1 = fs::OpenOptions::new().write(true).create(true).open(&path).unwrap(); let file2 = file1.duplicate().unwrap(); assert!(file1.as_raw_fd() != file2.as_raw_fd()); } /// The duplicate method should preservesthe close on exec flag. #[test] fn duplicate_cloexec() { fn flags(file: &File) -> libc::c_int { unsafe { libc::fcntl(file.as_raw_fd(), libc::F_GETFL, 0) } } let tempdir = tempdir::TempDir::new("fs2").unwrap(); let path = tempdir.path().join("fs2"); let file1 = fs::OpenOptions::new().write(true).create(true).open(&path).unwrap(); let file2 = file1.duplicate().unwrap(); assert_eq!(flags(&file1), flags(&file2)); } /// Tests that locking a file descriptor will replace any existing locks /// held on the file descriptor. #[test] fn lock_replace() { let tempdir = tempdir::TempDir::new("fs2").unwrap(); let path = tempdir.path().join("fs2"); let file1 = fs::OpenOptions::new().write(true).create(true).open(&path).unwrap(); let file2 = fs::OpenOptions::new().write(true).create(true).open(&path).unwrap(); // Creating a shared lock will drop an exclusive lock. file1.lock_exclusive().unwrap(); file1.lock_shared().unwrap(); file2.lock_shared().unwrap(); // Attempting to replace a shared lock with an exclusive lock will fail // with multiple lock holders, and remove the original shared lock. assert_eq!(file2.try_lock_exclusive().unwrap_err().raw_os_error(), lock_contended_error().raw_os_error()); file1.lock_shared().unwrap(); } /// Tests that locks are shared among duplicated file descriptors. #[test] fn lock_duplicate() { let tempdir = tempdir::TempDir::new("fs2").unwrap(); let path = tempdir.path().join("fs2"); let file1 = fs::OpenOptions::new().write(true).create(true).open(&path).unwrap(); let file2 = file1.duplicate().unwrap(); let file3 = fs::OpenOptions::new().write(true).create(true).open(&path).unwrap(); // Create a lock through fd1, then replace it through fd2. file1.lock_shared().unwrap(); file2.lock_exclusive().unwrap(); assert_eq!(file3.try_lock_shared().unwrap_err().raw_os_error(), lock_contended_error().raw_os_error()); // Either of the file descriptors should be able to unlock. file1.unlock().unwrap(); file3.lock_shared().unwrap(); } } vendor/fs2-0.4.3/src/windows.rs0000644000000000000000000002436413264166600015047 0ustar rootrootuse std::fs::File; use std::io::{Error, Result}; use std::mem; use std::os::windows::ffi::OsStrExt; use std::os::windows::io::{AsRawHandle, FromRawHandle}; use std::path::Path; use std::ptr; use winapi::shared::minwindef::{BOOL, DWORD}; use winapi::shared::winerror::ERROR_LOCK_VIOLATION; use winapi::um::fileapi::{FILE_ALLOCATION_INFO, FILE_STANDARD_INFO, GetDiskFreeSpaceW}; use winapi::um::fileapi::{GetVolumePathNameW, LockFileEx, UnlockFile, SetFileInformationByHandle}; use winapi::um::handleapi::DuplicateHandle; use winapi::um::minwinbase::{FileAllocationInfo, FileStandardInfo}; use winapi::um::minwinbase::{LOCKFILE_FAIL_IMMEDIATELY, LOCKFILE_EXCLUSIVE_LOCK}; use winapi::um::processthreadsapi::GetCurrentProcess; use winapi::um::winbase::GetFileInformationByHandleEx; use winapi::um::winnt::DUPLICATE_SAME_ACCESS; use FsStats; pub fn duplicate(file: &File) -> Result { unsafe { let mut handle = ptr::null_mut(); let current_process = GetCurrentProcess(); let ret = DuplicateHandle(current_process, file.as_raw_handle(), current_process, &mut handle, 0, true as BOOL, DUPLICATE_SAME_ACCESS); if ret == 0 { Err(Error::last_os_error()) } else { Ok(File::from_raw_handle(handle)) } } } pub fn allocated_size(file: &File) -> Result { unsafe { let mut info: FILE_STANDARD_INFO = mem::zeroed(); let ret = GetFileInformationByHandleEx( file.as_raw_handle(), FileStandardInfo, &mut info as *mut _ as *mut _, mem::size_of::() as DWORD); if ret == 0 { Err(Error::last_os_error()) } else { Ok(*info.AllocationSize.QuadPart() as u64) } } } pub fn allocate(file: &File, len: u64) -> Result<()> { if try!(allocated_size(file)) < len { unsafe { let mut info: FILE_ALLOCATION_INFO = mem::zeroed(); *info.AllocationSize.QuadPart_mut() = len as i64; let ret = SetFileInformationByHandle( file.as_raw_handle(), FileAllocationInfo, &mut info as *mut _ as *mut _, mem::size_of::() as DWORD); if ret == 0 { return Err(Error::last_os_error()); } } } if try!(file.metadata()).len() < len { file.set_len(len) } else { Ok(()) } } pub fn lock_shared(file: &File) -> Result<()> { lock_file(file, 0) } pub fn lock_exclusive(file: &File) -> Result<()> { lock_file(file, LOCKFILE_EXCLUSIVE_LOCK) } pub fn try_lock_shared(file: &File) -> Result<()> { lock_file(file, LOCKFILE_FAIL_IMMEDIATELY) } pub fn try_lock_exclusive(file: &File) -> Result<()> { lock_file(file, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY) } pub fn unlock(file: &File) -> Result<()> { unsafe { let ret = UnlockFile(file.as_raw_handle(), 0, 0, !0, !0); if ret == 0 { Err(Error::last_os_error()) } else { Ok(()) } } } pub fn lock_error() -> Error { Error::from_raw_os_error(ERROR_LOCK_VIOLATION as i32) } fn lock_file(file: &File, flags: DWORD) -> Result<()> { unsafe { let mut overlapped = mem::zeroed(); let ret = LockFileEx(file.as_raw_handle(), flags, 0, !0, !0, &mut overlapped); if ret == 0 { Err(Error::last_os_error()) } else { Ok(()) } } } fn volume_path(path: &Path, volume_path: &mut [u16]) -> Result<()> { let path_utf8: Vec = path.as_os_str().encode_wide().chain(Some(0)).collect(); unsafe { let ret = GetVolumePathNameW(path_utf8.as_ptr(), volume_path.as_mut_ptr(), volume_path.len() as DWORD); if ret == 0 { Err(Error::last_os_error()) } else { Ok(()) } } } pub fn statvfs(path: &Path) -> Result { let root_path: &mut [u16] = &mut [0; 261]; try!(volume_path(path, root_path)); unsafe { let mut sectors_per_cluster = 0; let mut bytes_per_sector = 0; let mut number_of_free_clusters = 0; let mut total_number_of_clusters = 0; let ret = GetDiskFreeSpaceW(root_path.as_ptr(), &mut sectors_per_cluster, &mut bytes_per_sector, &mut number_of_free_clusters, &mut total_number_of_clusters); if ret == 0 { Err(Error::last_os_error()) } else { let bytes_per_cluster = sectors_per_cluster as u64 * bytes_per_sector as u64; let free_space = bytes_per_cluster * number_of_free_clusters as u64; let total_space = bytes_per_cluster * total_number_of_clusters as u64; Ok(FsStats { free_space: free_space, available_space: free_space, total_space: total_space, allocation_granularity: bytes_per_cluster, }) } } } #[cfg(test)] mod test { extern crate tempdir; use std::fs; use std::os::windows::io::AsRawHandle; use {FileExt, lock_contended_error}; /// The duplicate method returns a file with a new file handle. #[test] fn duplicate_new_handle() { let tempdir = tempdir::TempDir::new("fs2").unwrap(); let path = tempdir.path().join("fs2"); let file1 = fs::OpenOptions::new().write(true).create(true).open(&path).unwrap(); let file2 = file1.duplicate().unwrap(); assert!(file1.as_raw_handle() != file2.as_raw_handle()); } /// A duplicated file handle does not have access to the original handle's locks. #[test] fn lock_duplicate_handle_independence() { let tempdir = tempdir::TempDir::new("fs2").unwrap(); let path = tempdir.path().join("fs2"); let file1 = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap(); let file2 = file1.duplicate().unwrap(); // Locking the original file handle will block the duplicate file handle from opening a lock. file1.lock_shared().unwrap(); assert_eq!(file2.try_lock_exclusive().unwrap_err().raw_os_error(), lock_contended_error().raw_os_error()); // Once the original file handle is unlocked, the duplicate handle can proceed with a lock. file1.unlock().unwrap(); file2.lock_exclusive().unwrap(); } /// A file handle may not be exclusively locked multiple times, or exclusively locked and then /// shared locked. #[test] fn lock_non_reentrant() { let tempdir = tempdir::TempDir::new("fs2").unwrap(); let path = tempdir.path().join("fs2"); let file = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap(); // Multiple exclusive locks fails. file.lock_exclusive().unwrap(); assert_eq!(file.try_lock_exclusive().unwrap_err().raw_os_error(), lock_contended_error().raw_os_error()); file.unlock().unwrap(); // Shared then Exclusive locks fails. file.lock_shared().unwrap(); assert_eq!(file.try_lock_exclusive().unwrap_err().raw_os_error(), lock_contended_error().raw_os_error()); } /// A file handle can hold an exclusive lock and any number of shared locks, all of which must /// be unlocked independently. #[test] fn lock_layering() { let tempdir = tempdir::TempDir::new("fs2").unwrap(); let path = tempdir.path().join("fs2"); let file = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap(); // Open two shared locks on the file, and then try and fail to open an exclusive lock. file.lock_exclusive().unwrap(); file.lock_shared().unwrap(); file.lock_shared().unwrap(); assert_eq!(file.try_lock_exclusive().unwrap_err().raw_os_error(), lock_contended_error().raw_os_error()); // Pop one of the shared locks and try again. file.unlock().unwrap(); assert_eq!(file.try_lock_exclusive().unwrap_err().raw_os_error(), lock_contended_error().raw_os_error()); // Pop the second shared lock and try again. file.unlock().unwrap(); assert_eq!(file.try_lock_exclusive().unwrap_err().raw_os_error(), lock_contended_error().raw_os_error()); // Pop the exclusive lock and finally succeed. file.unlock().unwrap(); file.lock_exclusive().unwrap(); } /// A file handle with multiple open locks will have all locks closed on drop. #[test] fn lock_layering_cleanup() { let tempdir = tempdir::TempDir::new("fs2").unwrap(); let path = tempdir.path().join("fs2"); let file1 = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap(); let file2 = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap(); // Open two shared locks on the file, and then try and fail to open an exclusive lock. file1.lock_shared().unwrap(); assert_eq!(file2.try_lock_exclusive().unwrap_err().raw_os_error(), lock_contended_error().raw_os_error()); drop(file1); file2.lock_exclusive().unwrap(); } /// A file handle's locks will not be released until the original handle and all of its /// duplicates have been closed. This on really smells like a bug in Windows. #[test] fn lock_duplicate_cleanup() { let tempdir = tempdir::TempDir::new("fs2").unwrap(); let path = tempdir.path().join("fs2"); let file1 = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap(); let file2 = file1.duplicate().unwrap(); // Open a lock on the original handle, then close it. file1.lock_shared().unwrap(); drop(file1); // Attempting to create a lock on the file with the duplicate handle will fail. assert_eq!(file2.try_lock_exclusive().unwrap_err().raw_os_error(), lock_contended_error().raw_os_error()); } } vendor/fuchsia-zircon-0.3.3/0000755000000000000000000000000013264166600014440 5ustar rootrootvendor/fuchsia-zircon-0.3.3/.cargo-checksum.json0000644000000000000000000000013113264166600020277 0ustar rootroot{"files":{},"package":"2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"}vendor/fuchsia-zircon-0.3.3/BUILD.gn0000640000000000000000000000060713264166600015624 0ustar rootroot# Copyright 2017 The Fuchsia Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. import("//build/rust/rust_library.gni") rust_library("fuchsia-zircon") { deps = [ "//garnet/public/rust/crates/fuchsia-zircon/fuchsia-zircon-sys", "//third_party/rust-crates:bitflags-0.7.0", ] with_tests = true } vendor/fuchsia-zircon-0.3.3/Cargo.toml0000644000000000000000000000152013264166600016366 0ustar rootroot# 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 = "fuchsia-zircon" version = "0.3.3" authors = ["Raph Levien "] description = "Rust bindings for the Zircon kernel" license = "BSD-3-Clause" repository = "https://fuchsia.googlesource.com/garnet/" [dependencies.bitflags] version = "1.0.0" [dependencies.fuchsia-zircon-sys] version = "0.3.3" vendor/fuchsia-zircon-0.3.3/LICENSE0000640000000000000000000000302613264166600015442 0ustar rootroot// Copyright 2016 The Fuchsia Authors. All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * 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. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "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 COPYRIGHT // OWNER OR CONTRIBUTORS 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. vendor/fuchsia-zircon-0.3.3/README.md0000640000000000000000000000110013264166600015703 0ustar rootrootRust bindings for Zircon kernel ================================ This repository contains Rust language bindings for Zircon kernel syscalls. The main crate contains type-safe wrappers, while the inner "sys" crate contains the raw types and FFI declarations. There are two ways to build Rust artifacts targeting Fuchsia; using the [Fargo](https://fuchsia.googlesource.com/fargo/) cross compiling tool or including your [artifact in the GN build](https://fuchsia.googlesource.com/docs/+/master/rust.md). Of the two, Fargo is likely better for exploration and experimentation. vendor/fuchsia-zircon-0.3.3/examples/0000755000000000000000000000000013264166600016256 5ustar rootrootvendor/fuchsia-zircon-0.3.3/examples/BUILD.gn0000640000000000000000000000052513264166600017441 0ustar rootroot# Copyright 2017 The Fuchsia Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. import("//build/package.gni") package("zircon_rust_examples") { system_image = true deps = [ "zx_toy", ] binaries = [ { name = "example_zx_toy" } ] } vendor/fuchsia-zircon-0.3.3/src/0000755000000000000000000000000013264166600015227 5ustar rootrootvendor/fuchsia-zircon-0.3.3/src/channel.rs0000640000000000000000000003711613264166600017211 0ustar rootroot// Copyright 2017 The Fuchsia Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. //! Type-safe bindings for Zircon channel objects. use {AsHandleRef, HandleBased, Handle, HandleRef, Peered, Status, Time, usize_into_u32, size_to_u32_sat}; use {sys, ok}; use std::mem; /// An object representing a Zircon /// [channel](https://fuchsia.googlesource.com/zircon/+/master/docs/objects/channel.md). /// /// As essentially a subtype of `Handle`, it can be freely interconverted. #[derive(Debug, Eq, PartialEq, Hash)] pub struct Channel(Handle); impl_handle_based!(Channel); impl Peered for Channel {} impl Channel { /// Create a channel, resulting an a pair of `Channel` objects representing both /// sides of the channel. Messages written into one maybe read from the opposite. /// /// Wraps the /// [zx_channel_create](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/channel_create.md) /// syscall. pub fn create() -> Result<(Channel, Channel), Status> { unsafe { let mut handle0 = 0; let mut handle1 = 0; let opts = 0; ok(sys::zx_channel_create(opts, &mut handle0, &mut handle1))?; Ok(( Self::from(Handle::from_raw(handle0)), Self::from(Handle::from_raw(handle1)) )) } } /// Read a message from a channel. Wraps the /// [zx_channel_read](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/channel_read.md) /// syscall. /// /// If the `MessageBuf` lacks the capacity to hold the pending message, /// returns an `Err` with the number of bytes and number of handles needed. /// Otherwise returns an `Ok` with the result as usual. pub fn read_raw(&self, buf: &mut MessageBuf) -> Result, (usize, usize)> { let opts = 0; unsafe { buf.clear(); let raw_handle = self.raw_handle(); let mut num_bytes: u32 = size_to_u32_sat(buf.bytes.capacity()); let mut num_handles: u32 = size_to_u32_sat(buf.handles.capacity()); let status = ok(sys::zx_channel_read(raw_handle, opts, buf.bytes.as_mut_ptr(), buf.handles.as_mut_ptr() as *mut _, num_bytes, num_handles, &mut num_bytes, &mut num_handles)); if status == Err(Status::BUFFER_TOO_SMALL) { Err((num_bytes as usize, num_handles as usize)) } else { Ok(status.map(|()| { buf.bytes.set_len(num_bytes as usize); buf.handles.set_len(num_handles as usize); })) } } } /// Read a message from a channel. /// /// Note that this method can cause internal reallocations in the `MessageBuf` /// if it is lacks capacity to hold the full message. If such reallocations /// are not desirable, use `read_raw` instead. pub fn read(&self, buf: &mut MessageBuf) -> Result<(), Status> { loop { match self.read_raw(buf) { Ok(result) => return result, Err((num_bytes, num_handles)) => { buf.ensure_capacity_bytes(num_bytes); buf.ensure_capacity_handles(num_handles); } } } } /// Write a message to a channel. Wraps the /// [zx_channel_write](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/channel_write.md) /// syscall. pub fn write(&self, bytes: &[u8], handles: &mut Vec) -> Result<(), Status> { let opts = 0; let n_bytes = try!(usize_into_u32(bytes.len()).map_err(|_| Status::OUT_OF_RANGE)); let n_handles = try!(usize_into_u32(handles.len()).map_err(|_| Status::OUT_OF_RANGE)); unsafe { let status = sys::zx_channel_write(self.raw_handle(), opts, bytes.as_ptr(), n_bytes, handles.as_ptr() as *const sys::zx_handle_t, n_handles); ok(status)?; // Handles were successfully transferred, forget them on sender side handles.set_len(0); Ok(()) } } /// Send a message consisting of the given bytes and handles to a channel and await a reply. The /// bytes should start with a four byte 'txid' which is used to identify the matching reply. /// /// Wraps the /// [zx_channel_call](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/channel_call.md) /// syscall. /// /// Note that unlike [`read`][read], the caller must ensure that the MessageBuf has enough /// capacity for the bytes and handles which will be received, as replies which are too large /// are discarded. /// /// On failure returns the both the main and read status. /// /// [read]: struct.Channel.html#method.read pub fn call(&self, timeout: Time, bytes: &[u8], handles: &mut Vec, buf: &mut MessageBuf) -> Result<(), (Status, Status)> { let write_num_bytes = try!(usize_into_u32(bytes.len()).map_err( |_| (Status::OUT_OF_RANGE, Status::OK))); let write_num_handles = try!(usize_into_u32(handles.len()).map_err( |_| (Status::OUT_OF_RANGE, Status::OK))); buf.clear(); let read_num_bytes: u32 = size_to_u32_sat(buf.bytes.capacity()); let read_num_handles: u32 = size_to_u32_sat(buf.handles.capacity()); let args = sys::zx_channel_call_args_t { wr_bytes: bytes.as_ptr(), wr_handles: handles.as_ptr() as *const sys::zx_handle_t, rd_bytes: buf.bytes.as_mut_ptr(), rd_handles: buf.handles.as_mut_ptr() as *mut _, wr_num_bytes: write_num_bytes, wr_num_handles: write_num_handles, rd_num_bytes: read_num_bytes, rd_num_handles: read_num_handles, }; let mut actual_read_bytes: u32 = 0; let mut actual_read_handles: u32 = 0; let mut read_status = Status::OK.into_raw(); let options = 0; let status = unsafe { Status::from_raw( sys::zx_channel_call( self.raw_handle(), options, timeout.nanos(), &args, &mut actual_read_bytes, &mut actual_read_handles, &mut read_status)) }; match status { Status::OK | Status::TIMED_OUT | Status::CALL_FAILED => { // Handles were successfully transferred, // even if we didn't get a response, so forget // them on the sender side. unsafe { handles.set_len(0); } } _ => {} } unsafe { buf.bytes.set_len(actual_read_bytes as usize); buf.handles.set_len(actual_read_handles as usize); } if Status::OK == status { Ok(()) } else { Err((status, Status::from_raw(read_status))) } } } #[test] pub fn test_handle_repr() { assert_eq!(::std::mem::size_of::(), 4); assert_eq!(::std::mem::size_of::(), 4); assert_eq!(::std::mem::align_of::(), ::std::mem::align_of::()); // This test asserts that repr(transparent) still works for Handle -> zx_handle_t let n: Vec = vec![0, 100, 2<<32-1]; let v: Vec = n.iter().map(|h| unsafe { Handle::from_raw(*h) } ).collect(); for (handle, raw) in v.iter().zip(n.iter()) { unsafe { assert_eq!(*(handle as *const _ as *const [u8; 4]), *(raw as *const _ as *const [u8; 4])); } } for h in v.into_iter() { ::std::mem::forget(h); } } impl AsRef for Channel { fn as_ref(&self) -> &Self { &self } } /// A buffer for _receiving_ messages from a channel. /// /// A `MessageBuf` is essentially a byte buffer and a vector of /// handles, but move semantics for "taking" handles requires special handling. /// /// Note that for sending messages to a channel, the caller manages the buffers, /// using a plain byte slice and `Vec`. #[derive(Default)] #[derive(Debug)] pub struct MessageBuf { bytes: Vec, handles: Vec, } impl MessageBuf { /// Create a new, empty, message buffer. pub fn new() -> Self { Default::default() } /// Create a new non-empty message buffer. pub fn new_with(v: Vec, h: Vec) -> Self { Self{ bytes: v, handles: h, } } /// Ensure that the buffer has the capacity to hold at least `n_bytes` bytes. pub fn ensure_capacity_bytes(&mut self, n_bytes: usize) { ensure_capacity(&mut self.bytes, n_bytes); } /// Ensure that the buffer has the capacity to hold at least `n_handles` handles. pub fn ensure_capacity_handles(&mut self, n_handles: usize) { ensure_capacity(&mut self.handles, n_handles); } /// Ensure that at least n_bytes bytes are initialized (0 fill). pub fn ensure_initialized_bytes(&mut self, n_bytes: usize) { if n_bytes <= self.bytes.len() { return; } self.bytes.resize(n_bytes, 0); } /// Get a reference to the bytes of the message buffer, as a `&[u8]` slice. pub fn bytes(&self) -> &[u8] { self.bytes.as_slice() } /// The number of handles in the message buffer. Note this counts the number /// available when the message was received; `take_handle` does not affect /// the count. pub fn n_handles(&self) -> usize { self.handles.len() } /// Take the handle at the specified index from the message buffer. If the /// method is called again with the same index, it will return `None`, as /// will happen if the index exceeds the number of handles available. pub fn take_handle(&mut self, index: usize) -> Option { self.handles.get_mut(index).and_then(|handle| if handle.is_invalid() { None } else { Some(mem::replace(handle, Handle::invalid())) } ) } /// Clear the bytes and handles contained in the buf. This will drop any /// contained handles, resulting in their resources being freed. pub fn clear(&mut self) { self.bytes.clear(); self.handles.clear(); } } fn ensure_capacity(vec: &mut Vec, size: usize) { let len = vec.len(); if size > len { vec.reserve(size - len); } } #[cfg(test)] mod tests { use super::*; use {DurationNum, Rights, Signals, Vmo}; use std::thread; #[test] fn channel_basic() { let (p1, p2) = Channel::create().unwrap(); let mut empty = vec![]; assert!(p1.write(b"hello", &mut empty).is_ok()); let mut buf = MessageBuf::new(); assert!(p2.read(&mut buf).is_ok()); assert_eq!(buf.bytes(), b"hello"); } #[test] fn channel_read_raw_too_small() { let (p1, p2) = Channel::create().unwrap(); let mut empty = vec![]; assert!(p1.write(b"hello", &mut empty).is_ok()); let mut buf = MessageBuf::new(); let result = p2.read_raw(&mut buf); assert_eq!(result, Err((5, 0))); assert_eq!(buf.bytes(), b""); } #[test] fn channel_send_handle() { let hello_length: usize = 5; // Create a pair of channels and a virtual memory object. let (p1, p2) = Channel::create().unwrap(); let vmo = Vmo::create(hello_length as u64).unwrap(); // Duplicate VMO handle and send it down the channel. let duplicate_vmo_handle = vmo.duplicate_handle(Rights::SAME_RIGHTS).unwrap().into(); let mut handles_to_send: Vec = vec![duplicate_vmo_handle]; assert!(p1.write(b"", &mut handles_to_send).is_ok()); // Handle should be removed from vector. assert!(handles_to_send.is_empty()); // Read the handle from the receiving channel. let mut buf = MessageBuf::new(); assert!(p2.read(&mut buf).is_ok()); assert_eq!(buf.n_handles(), 1); // Take the handle from the buffer. let received_handle = buf.take_handle(0).unwrap(); // Should not affect number of handles. assert_eq!(buf.n_handles(), 1); // Trying to take it again should fail. assert!(buf.take_handle(0).is_none()); // Now to test that we got the right handle, try writing something to it... let received_vmo = Vmo::from(received_handle); assert_eq!(received_vmo.write(b"hello", 0).unwrap(), hello_length); // ... and reading it back from the original VMO. let mut read_vec = vec![0; hello_length]; assert_eq!(vmo.read(&mut read_vec, 0).unwrap(), hello_length); assert_eq!(read_vec, b"hello"); } #[test] fn channel_call_timeout() { let ten_ms = 10.millis(); // Create a pair of channels and a virtual memory object. let (p1, p2) = Channel::create().unwrap(); let vmo = Vmo::create(0 as u64).unwrap(); // Duplicate VMO handle and send it along with the call. let duplicate_vmo_handle = vmo.duplicate_handle(Rights::SAME_RIGHTS).unwrap().into(); let mut handles_to_send: Vec = vec![duplicate_vmo_handle]; let mut buf = MessageBuf::new(); assert_eq!(p1.call(ten_ms.after_now(), b"call", &mut handles_to_send, &mut buf), Err((Status::TIMED_OUT, Status::OK))); // Handle should be removed from vector even though we didn't get a response, as it was // still sent over the channel. assert!(handles_to_send.is_empty()); // Should be able to read call even though it timed out waiting for a response. let mut buf = MessageBuf::new(); assert!(p2.read(&mut buf).is_ok()); assert_eq!(buf.bytes(), b"call"); assert_eq!(buf.n_handles(), 1); } #[test] fn channel_call() { // Create a pair of channels let (p1, p2) = Channel::create().unwrap(); // create an mpsc channel for communicating the call data for later assertion let (tx, rx) = ::std::sync::mpsc::channel(); // Start a new thread to respond to the call. thread::spawn(move || { let mut buf = MessageBuf::new(); // if either the read or the write fail, this thread will panic, // resulting in tx being dropped, which will be noticed by the rx. p2.wait_handle(Signals::CHANNEL_READABLE, 1.seconds().after_now()).expect("callee wait error"); p2.read(&mut buf).expect("callee read error"); p2.write(b"txidresponse", &mut vec![]).expect("callee write error"); tx.send(buf).expect("callee mpsc send error"); }); // Make the call. let mut buf = MessageBuf::new(); buf.ensure_capacity_bytes(12); // NOTE(raggi): CQ has been seeing some long stalls from channel call, // and it's as yet unclear why. The timeout here has been made much // larger in order to avoid that, as the issues are not issues with this // crate's concerns. The timeout is here just to prevent the tests from // stalling forever if a developer makes a mistake locally in this // crate. Tests of Zircon behavior or virtualization behavior should be // covered elsewhere. See ZX-1324. p1.call(30.seconds().after_now(), b"txidcall", &mut vec![], &mut buf).expect("channel call error"); assert_eq!(buf.bytes(), b"txidresponse"); assert_eq!(buf.n_handles(), 0); let sbuf = rx.recv().expect("mpsc channel recv error"); assert_eq!(sbuf.bytes(), b"txidcall"); assert_eq!(sbuf.n_handles(), 0); } } vendor/fuchsia-zircon-0.3.3/src/cprng.rs0000640000000000000000000000405713264166600016710 0ustar rootrootuse {Status, ok, sys}; /// Draw random bytes from the kernel's CPRNG to fill the given buffer. Returns the actual number of /// bytes drawn, which may sometimes be less than the size of the buffer provided. /// /// The buffer must have length less than `ZX_CPRNG_DRAW_MAX_LEN`. /// /// Wraps the /// [zx_cprng_draw](https://fuchsia.googlesource.com/zircon/+/HEAD/docs/syscalls/cprng_draw.md) /// syscall. pub fn cprng_draw(buffer: &mut [u8]) -> Result { let mut actual = 0; let status = unsafe { sys::zx_cprng_draw(buffer.as_mut_ptr(), buffer.len(), &mut actual) }; ok(status).map(|()| actual) } /// Mix the given entropy into the kernel CPRNG. /// /// The buffer must have length less than `ZX_CPRNG_ADD_ENTROPY_MAX_LEN`. /// /// Wraps the /// [zx_cprng_add_entropy](https://fuchsia.googlesource.com/zircon/+/HEAD/docs/syscalls/cprng_add_entropy.md) /// syscall. pub fn cprng_add_entropy(buffer: &[u8]) -> Result<(), Status> { let status = unsafe { sys::zx_cprng_add_entropy(buffer.as_ptr(), buffer.len()) }; ok(status) } #[cfg(test)] mod tests { use super::*; #[test] fn cprng() { let mut buffer = [0; 20]; assert_eq!(cprng_draw(&mut buffer), Ok(20)); let mut first_zero = 0; let mut last_zero = 0; for _ in 0..30 { let mut buffer = [0; 20]; assert_eq!(cprng_draw(&mut buffer), Ok(20)); if buffer[0] == 0 { first_zero += 1; } if buffer[19] == 0 { last_zero += 1; } } assert_ne!(first_zero, 30); assert_ne!(last_zero, 30); } #[test] fn cprng_too_large() { let mut buffer = [0; sys::ZX_CPRNG_DRAW_MAX_LEN + 1]; assert_eq!(cprng_draw(&mut buffer), Err(Status::INVALID_ARGS)); for mut s in buffer.chunks_mut(sys::ZX_CPRNG_DRAW_MAX_LEN) { assert_eq!(cprng_draw(&mut s), Ok(s.len())); } } #[test] fn cprng_add() { let buffer = [0, 1, 2]; assert_eq!(cprng_add_entropy(&buffer), Ok(())); } }vendor/fuchsia-zircon-0.3.3/src/event.rs0000640000000000000000000000213213264166600016710 0ustar rootroot// Copyright 2017 The Fuchsia Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. //! Type-safe bindings for Zircon event objects. use {AsHandleRef, Cookied, HandleBased, Handle, HandleRef, Status}; use {sys, ok}; /// An object representing a Zircon /// [event object](https://fuchsia.googlesource.com/zircon/+/master/docs/objects/event.md). /// /// As essentially a subtype of `Handle`, it can be freely interconverted. #[derive(Debug, Eq, PartialEq)] pub struct Event(Handle); impl_handle_based!(Event); impl Cookied for Event {} impl Event { /// Create an event object, an object which is signalable but nothing else. Wraps the /// [zx_event_create](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/event_create.md) /// syscall. pub fn create() -> Result { let mut out = 0; let opts = 0; let status = unsafe { sys::zx_event_create(opts, &mut out) }; ok(status)?; unsafe { Ok(Self::from(Handle::from_raw(out))) } } } vendor/fuchsia-zircon-0.3.3/src/eventpair.rs0000640000000000000000000000456413264166600017577 0ustar rootroot// Copyright 2016 The Fuchsia Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. //! Type-safe bindings for Zircon event pairs. use {AsHandleRef, Cookied, HandleBased, Handle, HandleRef, Peered, Status}; use {sys, ok}; /// An object representing a Zircon /// [event pair](https://fuchsia.googlesource.com/zircon/+/master/docs/concepts.md#Other-IPC_Events_Event-Pairs_and-User-Signals). /// /// As essentially a subtype of `Handle`, it can be freely interconverted. #[derive(Debug, Eq, PartialEq)] pub struct EventPair(Handle); impl_handle_based!(EventPair); impl Peered for EventPair {} impl Cookied for EventPair {} impl EventPair { /// Create an event pair, a pair of objects which can signal each other. Wraps the /// [zx_eventpair_create](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/eventpair_create.md) /// syscall. pub fn create() -> Result<(EventPair, EventPair), Status> { let mut out0 = 0; let mut out1 = 0; let options = 0; let status = unsafe { sys::zx_eventpair_create(options, &mut out0, &mut out1) }; ok(status)?; unsafe { Ok(( Self::from(Handle::from_raw(out0)), Self::from(Handle::from_raw(out1)) )) } } } #[cfg(test)] mod tests { use super::*; use {DurationNum, Signals}; #[test] fn wait_and_signal_peer() { let (p1, p2) = EventPair::create().unwrap(); let eighty_ms = 80.millis(); // Waiting on one without setting any signal should time out. assert_eq!(p2.wait_handle(Signals::USER_0, eighty_ms.after_now()), Err(Status::TIMED_OUT)); // If we set a signal, we should be able to wait for it. assert!(p1.signal_peer(Signals::NONE, Signals::USER_0).is_ok()); assert_eq!(p2.wait_handle(Signals::USER_0, eighty_ms.after_now()).unwrap(), Signals::USER_0); // Should still work, signals aren't automatically cleared. assert_eq!(p2.wait_handle(Signals::USER_0, eighty_ms.after_now()).unwrap(), Signals::USER_0); // Now clear it, and waiting should time out again. assert!(p1.signal_peer(Signals::USER_0, Signals::NONE).is_ok()); assert_eq!(p2.wait_handle(Signals::USER_0, eighty_ms.after_now()), Err(Status::TIMED_OUT)); } } vendor/fuchsia-zircon-0.3.3/src/fifo.rs0000640000000000000000000000721513264166600016521 0ustar rootroot// Copyright 2017 The Fuchsia Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. //! Type-safe bindings for Zircon fifo objects. use {AsHandleRef, HandleBased, Handle, HandleRef, Status}; use {sys, ok}; /// An object representing a Zircon fifo. /// /// As essentially a subtype of `Handle`, it can be freely interconverted. #[derive(Debug, Eq, PartialEq)] pub struct Fifo(Handle); impl_handle_based!(Fifo); impl Fifo { /// Create a pair of fifos and return their endpoints. Writing to one endpoint enqueues an /// element into the fifo from which the opposing endpoint reads. Wraps the /// [zx_fifo_create](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/fifo_create.md) /// syscall. pub fn create(elem_count: u32, elem_size: u32) -> Result<(Fifo, Fifo), Status> { let mut out0 = 0; let mut out1 = 0; let options = 0; let status = unsafe { sys::zx_fifo_create(elem_count, elem_size, options, &mut out0, &mut out1) }; ok(status)?; unsafe { Ok(( Self::from(Handle::from_raw(out0)), Self::from(Handle::from_raw(out1)) ))} } /// Attempts to write some number of elements into the fifo. The number of bytes written will be /// rounded down to a multiple of the fifo's element size. /// Return value (on success) is number of elements actually written. /// /// Wraps /// [zx_fifo_write](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/fifo_write.md). pub fn write(&self, bytes: &[u8]) -> Result { let mut num_entries_written = 0; let status = unsafe { sys::zx_fifo_write(self.raw_handle(), bytes.as_ptr(), bytes.len(), &mut num_entries_written) }; ok(status).map(|()| num_entries_written) } /// Attempts to read some number of elements out of the fifo. The number of bytes read will /// always be a multiple of the fifo's element size. /// Return value (on success) is number of elements actually read. /// /// Wraps /// [zx_fifo_read](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/fifo_read.md). pub fn read(&self, bytes: &mut [u8]) -> Result { let mut num_entries_read = 0; let status = unsafe { sys::zx_fifo_read(self.raw_handle(), bytes.as_mut_ptr(), bytes.len(), &mut num_entries_read) }; ok(status).map(|()| num_entries_read) } } #[cfg(test)] mod tests { use super::*; #[test] fn fifo_basic() { let (fifo1, fifo2) = Fifo::create(4, 2).unwrap(); // Trying to write less than one element should fail. assert_eq!(fifo1.write(b""), Err(Status::OUT_OF_RANGE)); assert_eq!(fifo1.write(b"h"), Err(Status::OUT_OF_RANGE)); // Should write one element "he" and ignore the last half-element as it rounds down. assert_eq!(fifo1.write(b"hex").unwrap(), 1); // Should write three elements "ll" "o " "wo" and drop the rest as it is full. assert_eq!(fifo1.write(b"llo worlds").unwrap(), 3); // Now that the fifo is full any further attempts to write should fail. assert_eq!(fifo1.write(b"blah blah"), Err(Status::SHOULD_WAIT)); // Read all 4 entries from the other end. let mut read_vec = vec![0; 8]; assert_eq!(fifo2.read(&mut read_vec).unwrap(), 4); assert_eq!(read_vec, b"hello wo"); // Reading again should fail as the fifo is empty. assert_eq!(fifo2.read(&mut read_vec), Err(Status::SHOULD_WAIT)); } } vendor/fuchsia-zircon-0.3.3/src/handle.rs0000640000000000000000000002236713264166600017036 0ustar rootrootuse {Port, Rights, Signals, Status, Time, WaitAsyncOpts, ok, sys}; use std::marker::PhantomData; use std::mem; /// An object representing a Zircon /// [handle](https://fuchsia.googlesource.com/zircon/+/master/docs/handles.md). /// /// Internally, it is represented as a 32-bit integer, but this wrapper enforces /// strict ownership semantics. The `Drop` implementation closes the handle. /// /// This type represents the most general reference to a kernel object, and can /// be interconverted to and from more specific types. Those conversions are not /// enforced in the type system; attempting to use them will result in errors /// returned by the kernel. These conversions don't change the underlying /// representation, but do change the type and thus what operations are available. #[derive(Debug, Eq, PartialEq, Hash)] pub struct Handle(sys::zx_handle_t); impl AsHandleRef for Handle { fn as_handle_ref(&self) -> HandleRef { HandleRef { handle: self.0, phantom: Default::default() } } } impl HandleBased for Handle {} impl Drop for Handle { fn drop(&mut self) { if self.0 != sys::ZX_HANDLE_INVALID { unsafe { sys::zx_handle_close(self.0) }; } } } impl Handle { /// Initialize a handle backed by ZX_HANDLE_INVALID, the only safe non-handle. pub fn invalid() -> Handle { Handle(sys::ZX_HANDLE_INVALID) } /// If a raw handle is obtained from some other source, this method converts /// it into a type-safe owned handle. pub unsafe fn from_raw(raw: sys::zx_handle_t) -> Handle { Handle(raw) } pub fn is_invalid(&self) -> bool { self.0 == sys::ZX_HANDLE_INVALID } pub fn replace(self, rights: Rights) -> Result { let handle = self.0; let mut out = 0; let status = unsafe { sys::zx_handle_replace(handle, rights.bits(), &mut out) }; ok(status).map(|()| Handle(out)) } } /// A borrowed reference to a `Handle`. /// /// Mostly useful as part of a `WaitItem`. #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub struct HandleRef<'a> { handle: sys::zx_handle_t, phantom: PhantomData<&'a sys::zx_handle_t>, } impl<'a> HandleRef<'a> { pub fn raw_handle(&self) -> sys::zx_handle_t { self.handle } pub fn duplicate(&self, rights: Rights) -> Result { let handle = self.handle; let mut out = 0; let status = unsafe { sys::zx_handle_duplicate(handle, rights.bits(), &mut out) }; ok(status).map(|()| Handle(out)) } pub fn signal(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> { let handle = self.handle; let status = unsafe { sys::zx_object_signal(handle, clear_mask.bits(), set_mask.bits()) }; ok(status) } pub fn wait(&self, signals: Signals, deadline: Time) -> Result { let handle = self.handle; let mut pending = Signals::empty().bits(); let status = unsafe { sys::zx_object_wait_one(handle, signals.bits(), deadline.nanos(), &mut pending) }; ok(status).map(|()| Signals::from_bits_truncate(pending)) } pub fn wait_async(&self, port: &Port, key: u64, signals: Signals, options: WaitAsyncOpts) -> Result<(), Status> { let handle = self.handle; let status = unsafe { sys::zx_object_wait_async( handle, port.raw_handle(), key, signals.bits(), options as u32) }; ok(status) } } /// A trait to get a reference to the underlying handle of an object. pub trait AsHandleRef { /// Get a reference to the handle. One important use of such a reference is /// for `object_wait_many`. fn as_handle_ref(&self) -> HandleRef; /// Interpret the reference as a raw handle (an integer type). Two distinct /// handles will have different raw values (so it can perhaps be used as a /// key in a data structure). fn raw_handle(&self) -> sys::zx_handle_t { self.as_handle_ref().raw_handle() } /// Set and clear userspace-accessible signal bits on an object. Wraps the /// [zx_object_signal](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/object_signal.md) /// syscall. fn signal_handle(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> { self.as_handle_ref().signal(clear_mask, set_mask) } /// Waits on a handle. Wraps the /// [zx_object_wait_one](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/object_wait_one.md) /// syscall. fn wait_handle(&self, signals: Signals, deadline: Time) -> Result { self.as_handle_ref().wait(signals, deadline) } /// Causes packet delivery on the given port when the object changes state and matches signals. /// [zx_object_wait_async](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/object_wait_async.md) /// syscall. fn wait_async_handle(&self, port: &Port, key: u64, signals: Signals, options: WaitAsyncOpts) -> Result<(), Status> { self.as_handle_ref().wait_async(port, key, signals, options) } } impl<'a> AsHandleRef for HandleRef<'a> { fn as_handle_ref(&self) -> HandleRef { *self } } /// A trait implemented by all handle-based types. /// /// Note: it is reasonable for user-defined objects wrapping a handle to implement /// this trait. For example, a specific interface in some protocol might be /// represented as a newtype of `Channel`, and implement the `as_handle_ref` /// method and the `From` trait to facilitate conversion from and to the /// interface. pub trait HandleBased: AsHandleRef + From + Into { /// Duplicate a handle, possibly reducing the rights available. Wraps the /// [zx_handle_duplicate](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/handle_duplicate.md) /// syscall. fn duplicate_handle(&self, rights: Rights) -> Result { self.as_handle_ref().duplicate(rights).map(|handle| Self::from(handle)) } /// Create a replacement for a handle, possibly reducing the rights available. This invalidates /// the original handle. Wraps the /// [zx_handle_replace](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/handle_replace.md) /// syscall. fn replace_handle(self, rights: Rights) -> Result { >::into(self) .replace(rights).map(|handle| Self::from(handle)) } /// Converts the value into its inner handle. /// /// This is a convenience function which simply forwards to the `Into` trait. fn into_handle(self) -> Handle { self.into() } /// Converts the handle into it's raw representation. /// /// The caller takes ownership over the raw handle, and must close or transfer it to avoid a handle leak. fn into_raw(self) -> sys::zx_handle_t { let h = self.into_handle(); let r = h.0; mem::forget(h); r } /// Creates an instance of this type from a handle. /// /// This is a convenience function which simply forwards to the `From` trait. fn from_handle(handle: Handle) -> Self { Self::from(handle) } /// Creates an instance of another handle-based type from this value's inner handle. fn into_handle_based(self) -> H { H::from_handle(self.into_handle()) } /// Creates an instance of this type from the inner handle of another /// handle-based type. fn from_handle_based(h: H) -> Self { Self::from_handle(h.into_handle()) } } /// A trait implemented by all handles for objects which have a peer. pub trait Peered: HandleBased { /// Set and clear userspace-accessible signal bits on the object's peer. Wraps the /// [zx_object_signal_peer](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/object_signal.md) /// syscall. fn signal_peer(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> { let handle = self.as_handle_ref().handle; let status = unsafe { sys::zx_object_signal_peer(handle, clear_mask.bits(), set_mask.bits()) }; ok(status) } } /// A trait implemented by all handles for objects which can have a cookie attached. pub trait Cookied: HandleBased { /// Get the cookie attached to this object, if any. Wraps the /// [zx_object_get_cookie](https://fuchsia.googlesource.com/zircon/+/HEAD/docs/syscalls/object_get_cookie.md) /// syscall. fn get_cookie(&self, scope: &HandleRef) -> Result { let handle = self.as_handle_ref().handle; let mut cookie = 0; let status = unsafe { sys::zx_object_get_cookie(handle, scope.handle, &mut cookie) }; ok(status).map(|()| cookie) } /// Attach an opaque cookie to this object with the given scope. The cookie may be read or /// changed in future only with the same scope. Wraps the /// [zx_object_set_cookie](https://fuchsia.googlesource.com/zircon/+/HEAD/docs/syscalls/object_set_cookie.md) /// syscall. fn set_cookie(&self, scope: &HandleRef, cookie: u64) -> Result<(), Status> { let handle = self.as_handle_ref().handle; let status = unsafe { sys::zx_object_set_cookie(handle, scope.handle, cookie) }; ok(status) } } vendor/fuchsia-zircon-0.3.3/src/job.rs0000640000000000000000000000071113264166600016342 0ustar rootroot// Copyright 2017 The Fuchsia Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. //! Type-safe bindings for Zircon job. use {AsHandleRef, HandleBased, Handle, HandleRef}; /// An object representing a Zircon job. /// /// As essentially a subtype of `Handle`, it can be freely interconverted. #[derive(Debug, Eq, PartialEq)] pub struct Job(Handle); impl_handle_based!(Job);vendor/fuchsia-zircon-0.3.3/src/lib.rs0000640000000000000000000002654313264166600016351 0ustar rootroot// Copyright 2016 The Fuchsia Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. //! Type-safe bindings for Zircon kernel //! [syscalls](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls.md). #![deny(warnings)] #[macro_use] extern crate bitflags; pub extern crate fuchsia_zircon_sys as sys; #[deprecated(note="use fuchsia_zircon::sys::ZX_CPRNG_DRAW_MAX_LEN instead")] #[doc(hidden)] pub use sys::ZX_CPRNG_DRAW_MAX_LEN; // Implements the HandleBased traits for a Handle newtype struct macro_rules! impl_handle_based { ($type_name:path) => { impl AsHandleRef for $type_name { fn as_handle_ref(&self) -> HandleRef { self.0.as_handle_ref() } } impl From for $type_name { fn from(handle: Handle) -> Self { $type_name(handle) } } impl From<$type_name> for Handle { fn from(x: $type_name) -> Handle { x.0 } } impl HandleBased for $type_name {} } } // Creates associated constants of TypeName of the form // `pub const NAME: TypeName = TypeName(value);` macro_rules! assoc_consts { ($typename:ident, [$($name:ident = $num:expr;)*]) => { #[allow(non_upper_case_globals)] impl $typename { $( pub const $name: $typename = $typename($num); )* } } } mod channel; mod cprng; mod event; mod eventpair; mod fifo; mod handle; mod job; mod port; mod process; mod rights; mod socket; mod signals; mod status; mod time; mod thread; mod vmar; mod vmo; pub use channel::*; pub use cprng::*; pub use event::*; pub use eventpair::*; pub use fifo::*; pub use handle::*; pub use job::*; pub use port::*; pub use process::*; pub use rights::*; pub use socket::*; pub use signals::*; pub use status::*; pub use thread::*; pub use time::*; pub use vmar::*; pub use vmo::*; /// Prelude containing common utility traits. /// Designed for use like `use fuchsia_zircon::prelude::*;` pub mod prelude { pub use { AsHandleRef, Cookied, DurationNum, HandleBased, Peered, }; } /// Convenience re-export of `Status::ok`. pub fn ok(raw: sys::zx_status_t) -> Result<(), Status> { Status::ok(raw) } /// A "wait item" containing a handle reference and information about what signals /// to wait on, and, on return from `object_wait_many`, which are pending. #[repr(C)] #[derive(Debug)] pub struct WaitItem<'a> { /// The handle to wait on. pub handle: HandleRef<'a>, /// A set of signals to wait for. pub waitfor: Signals, /// The set of signals pending, on return of `object_wait_many`. pub pending: Signals, } /// An identifier to select a particular clock. See /// [zx_time_get](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/time_get.md) /// for more information about the possible values. #[repr(u32)] #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum ClockId { /// The number of nanoseconds since the system was powered on. Corresponds to /// `ZX_CLOCK_MONOTONIC`. Monotonic = 0, /// The number of wall clock nanoseconds since the Unix epoch (midnight on January 1 1970) in /// UTC. Corresponds to ZX_CLOCK_UTC. UTC = 1, /// The number of nanoseconds the current thread has been running for. Corresponds to /// ZX_CLOCK_THREAD. Thread = 2, } /// Wait on multiple handles. /// The success return value is a bool indicating whether one or more of the /// provided handle references was closed during the wait. /// /// Wraps the /// [zx_object_wait_many](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/object_wait_many.md) /// syscall. pub fn object_wait_many(items: &mut [WaitItem], deadline: Time) -> Result { let len = try!(usize_into_u32(items.len()).map_err(|_| Status::OUT_OF_RANGE)); let items_ptr = items.as_mut_ptr() as *mut sys::zx_wait_item_t; let status = unsafe { sys::zx_object_wait_many( items_ptr, len, deadline.nanos()) }; if status == sys::ZX_ERR_CANCELED { return Ok(true) } ok(status).map(|()| false) } #[cfg(test)] mod tests { use super::*; #[allow(unused_imports)] use super::prelude::*; #[test] fn monotonic_time_increases() { let time1 = Time::get(ClockId::Monotonic); 1_000.nanos().sleep(); let time2 = Time::get(ClockId::Monotonic); assert!(time2 > time1); } #[test] fn utc_time_increases() { let time1 = Time::get(ClockId::UTC); 1_000.nanos().sleep(); let time2 = Time::get(ClockId::UTC); assert!(time2 > time1); } #[test] fn thread_time_increases() { let time1 = Time::get(ClockId::Thread); 1_000.nanos().sleep(); let time2 = Time::get(ClockId::Thread); assert!(time2 > time1); } #[test] fn ticks_increases() { let ticks1 = ticks_get(); 1_000.nanos().sleep(); let ticks2 = ticks_get(); assert!(ticks2 > ticks1); } #[test] fn tick_length() { let sleep_time = 1.milli(); let ticks1 = ticks_get(); sleep_time.sleep(); let ticks2 = ticks_get(); // The number of ticks should have increased by at least 1 ms worth let sleep_ticks = sleep_time.millis() * ticks_per_second() / 1000; assert!(ticks2 >= (ticks1 + sleep_ticks)); } #[test] fn into_raw() { let vmo = Vmo::create(1).unwrap(); let h = vmo.into_raw(); let vmo2 = Vmo::from(unsafe { Handle::from_raw(h) }); assert!(vmo2.write(b"1", 0).is_ok()); } #[test] fn sleep() { let sleep_ns = 1.millis(); let time1 = Time::get(ClockId::Monotonic); sleep_ns.sleep(); let time2 = Time::get(ClockId::Monotonic); assert!(time2 > time1 + sleep_ns); } /// Test duplication by means of a VMO #[test] fn duplicate() { let hello_length: usize = 5; // Create a VMO and write some data to it. let vmo = Vmo::create(hello_length as u64).unwrap(); assert!(vmo.write(b"hello", 0).is_ok()); // Replace, reducing rights to read. let readonly_vmo = vmo.duplicate_handle(Rights::READ).unwrap(); // Make sure we can read but not write. let mut read_vec = vec![0; hello_length]; assert_eq!(readonly_vmo.read(&mut read_vec, 0).unwrap(), hello_length); assert_eq!(read_vec, b"hello"); assert_eq!(readonly_vmo.write(b"", 0), Err(Status::ACCESS_DENIED)); // Write new data to the original handle, and read it from the new handle assert!(vmo.write(b"bye", 0).is_ok()); assert_eq!(readonly_vmo.read(&mut read_vec, 0).unwrap(), hello_length); assert_eq!(read_vec, b"byelo"); } // Test replace by means of a VMO #[test] fn replace() { let hello_length: usize = 5; // Create a VMO and write some data to it. let vmo = Vmo::create(hello_length as u64).unwrap(); assert!(vmo.write(b"hello", 0).is_ok()); // Replace, reducing rights to read. let readonly_vmo = vmo.replace_handle(Rights::READ).unwrap(); // Make sure we can read but not write. let mut read_vec = vec![0; hello_length]; assert_eq!(readonly_vmo.read(&mut read_vec, 0).unwrap(), hello_length); assert_eq!(read_vec, b"hello"); assert_eq!(readonly_vmo.write(b"", 0), Err(Status::ACCESS_DENIED)); } #[test] fn wait_and_signal() { let event = Event::create().unwrap(); let ten_ms = 10.millis(); // Waiting on it without setting any signal should time out. assert_eq!(event.wait_handle( Signals::USER_0, ten_ms.after_now()), Err(Status::TIMED_OUT)); // If we set a signal, we should be able to wait for it. assert!(event.signal_handle(Signals::NONE, Signals::USER_0).is_ok()); assert_eq!(event.wait_handle(Signals::USER_0, ten_ms.after_now()).unwrap(), Signals::USER_0); // Should still work, signals aren't automatically cleared. assert_eq!(event.wait_handle(Signals::USER_0, ten_ms.after_now()).unwrap(), Signals::USER_0); // Now clear it, and waiting should time out again. assert!(event.signal_handle(Signals::USER_0, Signals::NONE).is_ok()); assert_eq!(event.wait_handle( Signals::USER_0, ten_ms.after_now()), Err(Status::TIMED_OUT)); } #[test] fn wait_many_and_signal() { let ten_ms = 10.millis(); let e1 = Event::create().unwrap(); let e2 = Event::create().unwrap(); // Waiting on them now should time out. let mut items = vec![ WaitItem { handle: e1.as_handle_ref(), waitfor: Signals::USER_0, pending: Signals::NONE }, WaitItem { handle: e2.as_handle_ref(), waitfor: Signals::USER_1, pending: Signals::NONE }, ]; assert_eq!(object_wait_many(&mut items, ten_ms.after_now()), Err(Status::TIMED_OUT)); assert_eq!(items[0].pending, Signals::NONE); assert_eq!(items[1].pending, Signals::NONE); // Signal one object and it should return success. assert!(e1.signal_handle(Signals::NONE, Signals::USER_0).is_ok()); assert!(object_wait_many(&mut items, ten_ms.after_now()).is_ok()); assert_eq!(items[0].pending, Signals::USER_0); assert_eq!(items[1].pending, Signals::NONE); // Signal the other and it should return both. assert!(e2.signal_handle(Signals::NONE, Signals::USER_1).is_ok()); assert!(object_wait_many(&mut items, ten_ms.after_now()).is_ok()); assert_eq!(items[0].pending, Signals::USER_0); assert_eq!(items[1].pending, Signals::USER_1); // Clear signals on both; now it should time out again. assert!(e1.signal_handle(Signals::USER_0, Signals::NONE).is_ok()); assert!(e2.signal_handle(Signals::USER_1, Signals::NONE).is_ok()); assert_eq!(object_wait_many(&mut items, ten_ms.after_now()), Err(Status::TIMED_OUT)); assert_eq!(items[0].pending, Signals::NONE); assert_eq!(items[1].pending, Signals::NONE); } #[test] fn cookies() { let event = Event::create().unwrap(); let scope = Event::create().unwrap(); // Getting a cookie when none has been set should fail. assert_eq!(event.get_cookie(&scope.as_handle_ref()), Err(Status::ACCESS_DENIED)); // Set a cookie. assert_eq!(event.set_cookie(&scope.as_handle_ref(), 42), Ok(())); // Should get it back.... assert_eq!(event.get_cookie(&scope.as_handle_ref()), Ok(42)); // but not with the wrong scope! assert_eq!(event.get_cookie(&event.as_handle_ref()), Err(Status::ACCESS_DENIED)); // Can change it, with the same scope... assert_eq!(event.set_cookie(&scope.as_handle_ref(), 123), Ok(())); // but not with a different scope. assert_eq!(event.set_cookie(&event.as_handle_ref(), 123), Err(Status::ACCESS_DENIED)); } } pub fn usize_into_u32(n: usize) -> Result { if n > ::std::u32::MAX as usize || n < ::std::u32::MIN as usize { return Err(()) } Ok(n as u32) } pub fn size_to_u32_sat(n: usize) -> u32 { if n > ::std::u32::MAX as usize { return ::std::u32::MAX; } if n < ::std::u32::MIN as usize { return ::std::u32::MIN; } n as u32 } vendor/fuchsia-zircon-0.3.3/src/port.rs0000640000000000000000000003070013264166600016555 0ustar rootroot// Copyright 2017 The Fuchsia Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. //! Type-safe bindings for Zircon port objects. use std::mem; use {AsHandleRef, HandleBased, Handle, HandleRef, Signals, Status, Time}; use {sys, ok}; /// An object representing a Zircon /// [port](https://fuchsia.googlesource.com/zircon/+/master/docs/objects/port.md). /// /// As essentially a subtype of `Handle`, it can be freely interconverted. #[derive(Debug, Eq, PartialEq)] pub struct Port(Handle); impl_handle_based!(Port); /// A packet sent through a port. This is a type-safe wrapper for /// [zx_port_packet_t](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/port_wait.md). #[derive(PartialEq, Eq, Debug)] pub struct Packet(sys::zx_port_packet_t); /// The contents of a `Packet`. #[derive(Debug, Copy, Clone)] pub enum PacketContents { /// A user-generated packet. User(UserPacket), /// A one-shot signal packet generated via `object_wait_async`. SignalOne(SignalPacket), /// A repeating signal packet generated via `object_wait_async`. SignalRep(SignalPacket), #[doc(hidden)] __Nonexhaustive } /// Contents of a user packet (one sent by `port_queue`). This is a type-safe wrapper for /// [zx_packet_user_t](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/port_wait.md). #[derive(Debug, Copy, Clone)] pub struct UserPacket(sys::zx_packet_user_t); /// Contents of a signal packet (one generated by the kernel). This is a type-safe wrapper for /// [zx_packet_signal_t](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/port_wait.md). #[derive(Debug, Copy, Clone)] pub struct SignalPacket(sys::zx_packet_signal_t); impl Packet { /// Creates a new packet with `UserPacket` data. pub fn from_user_packet(key: u64, status: i32, user: UserPacket) -> Packet { Packet( sys::zx_port_packet_t { key: key, packet_type: sys::zx_packet_type_t::ZX_PKT_TYPE_USER, status: status, union: user.0, } ) } /// The packet's key. pub fn key(&self) -> u64 { self.0.key } /// The packet's status. // TODO: should this type be wrapped? pub fn status(&self) -> i32 { self.0.status } /// The contents of the packet. pub fn contents(&self) -> PacketContents { if self.0.packet_type == sys::zx_packet_type_t::ZX_PKT_TYPE_USER { PacketContents::User(UserPacket(self.0.union)) } else if self.0.packet_type == sys::zx_packet_type_t::ZX_PKT_TYPE_SIGNAL_ONE { PacketContents::SignalOne(SignalPacket(unsafe { mem::transmute_copy(&self.0.union) })) } else if self.0.packet_type == sys::zx_packet_type_t::ZX_PKT_TYPE_SIGNAL_REP { PacketContents::SignalRep(SignalPacket(unsafe { mem::transmute_copy(&self.0.union) })) } else { panic!("unexpected packet type"); } } } impl UserPacket { pub fn from_u8_array(val: [u8; 32]) -> UserPacket { UserPacket(val) } pub fn as_u8_array(&self) -> &[u8; 32] { &self.0 } pub fn as_mut_u8_array(&mut self) -> &mut [u8; 32] { &mut self.0 } } impl SignalPacket { /// The signals used in the call to `object_wait_async`. pub fn trigger(&self) -> Signals { Signals::from_bits_truncate(self.0.trigger) } /// The observed signals. pub fn observed(&self) -> Signals { Signals::from_bits_truncate(self.0.observed) } /// A per object count of pending operations. pub fn count(&self) -> u64 { self.0.count } } impl Port { /// Create an IO port, allowing IO packets to be read and enqueued. /// /// Wraps the /// [zx_port_create](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/port_create.md) /// syscall. pub fn create() -> Result { unsafe { let mut handle = 0; let opts = 0; let status = sys::zx_port_create(opts, &mut handle); ok(status)?; Ok(Handle::from_raw(handle).into()) } } /// Attempt to queue a user packet to the IO port. /// /// Wraps the /// [zx_port_queue](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/port_queue.md) /// syscall. pub fn queue(&self, packet: &Packet) -> Result<(), Status> { let status = unsafe { sys::zx_port_queue(self.raw_handle(), &packet.0 as *const sys::zx_port_packet_t, 0) }; ok(status) } /// Wait for a packet to arrive on a (V2) port. /// /// Wraps the /// [zx_port_wait](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/port_wait.md) /// syscall. pub fn wait(&self, deadline: Time) -> Result { let mut packet = Default::default(); let status = unsafe { sys::zx_port_wait(self.raw_handle(), deadline.nanos(), &mut packet as *mut sys::zx_port_packet_t, 0) }; ok(status)?; Ok(Packet(packet)) } /// Cancel pending wait_async calls for an object with the given key. /// /// Wraps the /// [zx_port_cancel](https://fuchsia.googlesource.com/zircon/+/HEAD/docs/syscalls/port_cancel.md) /// syscall. pub fn cancel(&self, source: &H, key: u64) -> Result<(), Status> where H: HandleBased { let status = unsafe { sys::zx_port_cancel(self.raw_handle(), source.raw_handle(), key) }; ok(status) } } /// Options for wait_async. #[repr(u32)] #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum WaitAsyncOpts { Once = sys::ZX_WAIT_ASYNC_ONCE, Repeating = sys::ZX_WAIT_ASYNC_REPEATING, } #[cfg(test)] mod tests { use super::*; use {DurationNum, Event}; #[test] fn port_basic() { let ten_ms = 10.millis(); let port = Port::create().unwrap(); // Waiting now should time out. assert_eq!(port.wait(ten_ms.after_now()), Err(Status::TIMED_OUT)); // Send a valid packet. let packet = Packet::from_user_packet( 42, 123, UserPacket::from_u8_array([13; 32]), ); assert!(port.queue(&packet).is_ok()); // Waiting should succeed this time. We should get back the packet we sent. let read_packet = port.wait(ten_ms.after_now()).unwrap(); assert_eq!(read_packet, packet); } #[test] fn wait_async_once() { let ten_ms = 10.millis(); let key = 42; let port = Port::create().unwrap(); let event = Event::create().unwrap(); assert!(event.wait_async_handle(&port, key, Signals::USER_0 | Signals::USER_1, WaitAsyncOpts::Once).is_ok()); // Waiting without setting any signal should time out. assert_eq!(port.wait(ten_ms.after_now()), Err(Status::TIMED_OUT)); // If we set a signal, we should be able to wait for it. assert!(event.signal_handle(Signals::NONE, Signals::USER_0).is_ok()); let read_packet = port.wait(ten_ms.after_now()).unwrap(); assert_eq!(read_packet.key(), key); assert_eq!(read_packet.status(), 0); match read_packet.contents() { PacketContents::SignalOne(sig) => { assert_eq!(sig.trigger(), Signals::USER_0 | Signals::USER_1); assert_eq!(sig.observed(), Signals::USER_0); assert_eq!(sig.count(), 1); } _ => panic!("wrong packet type"), } // Shouldn't get any more packets. assert_eq!(port.wait(ten_ms.after_now()), Err(Status::TIMED_OUT)); // Calling wait_async again should result in another packet. assert!(event.wait_async_handle(&port, key, Signals::USER_0, WaitAsyncOpts::Once).is_ok()); let read_packet = port.wait(ten_ms.after_now()).unwrap(); assert_eq!(read_packet.key(), key); assert_eq!(read_packet.status(), 0); match read_packet.contents() { PacketContents::SignalOne(sig) => { assert_eq!(sig.trigger(), Signals::USER_0); assert_eq!(sig.observed(), Signals::USER_0); assert_eq!(sig.count(), 1); } _ => panic!("wrong packet type"), } // Calling wait_async_handle then cancel, we should not get a packet as cancel will // remove it from the queue. assert!(event.wait_async_handle(&port, key, Signals::USER_0, WaitAsyncOpts::Once).is_ok()); assert!(port.cancel(&event, key).is_ok()); assert_eq!(port.wait(ten_ms.after_now()), Err(Status::TIMED_OUT)); // If the event is signalled after the cancel, we also shouldn't get a packet. assert!(event.signal_handle(Signals::USER_0, Signals::NONE).is_ok()); // clear signal assert!(event.wait_async_handle(&port, key, Signals::USER_0, WaitAsyncOpts::Once).is_ok()); assert!(port.cancel(&event, key).is_ok()); assert!(event.signal_handle(Signals::NONE, Signals::USER_0).is_ok()); assert_eq!(port.wait(ten_ms.after_now()), Err(Status::TIMED_OUT)); } #[test] fn wait_async_repeating() { let ten_ms = 10.millis(); let key = 42; let port = Port::create().unwrap(); let event = Event::create().unwrap(); assert!(event.wait_async_handle(&port, key, Signals::USER_0 | Signals::USER_1, WaitAsyncOpts::Repeating).is_ok()); // Waiting without setting any signal should time out. assert_eq!(port.wait(ten_ms.after_now()), Err(Status::TIMED_OUT)); // If we set a signal, we should be able to wait for it. assert!(event.signal_handle(Signals::NONE, Signals::USER_0).is_ok()); let read_packet = port.wait(ten_ms.after_now()).unwrap(); assert_eq!(read_packet.key(), key); assert_eq!(read_packet.status(), 0); match read_packet.contents() { PacketContents::SignalRep(sig) => { assert_eq!(sig.trigger(), Signals::USER_0 | Signals::USER_1); assert_eq!(sig.observed(), Signals::USER_0); assert_eq!(sig.count(), 1); } _ => panic!("wrong packet type"), } // Should not get any more packets, as ZX_WAIT_ASYNC_REPEATING is edge triggered rather than // level triggered. assert_eq!(port.wait(ten_ms.after_now()), Err(Status::TIMED_OUT)); // If we clear and resignal, we should get the same packet again, // even though we didn't call event.wait_async again. assert!(event.signal_handle(Signals::USER_0, Signals::NONE).is_ok()); // clear signal assert!(event.signal_handle(Signals::NONE, Signals::USER_0).is_ok()); let read_packet = port.wait(ten_ms.after_now()).unwrap(); assert_eq!(read_packet.key(), key); assert_eq!(read_packet.status(), 0); match read_packet.contents() { PacketContents::SignalRep(sig) => { assert_eq!(sig.trigger(), Signals::USER_0 | Signals::USER_1); assert_eq!(sig.observed(), Signals::USER_0); assert_eq!(sig.count(), 1); } _ => panic!("wrong packet type"), } // Cancelling the wait should stop us getting packets... assert!(port.cancel(&event, key).is_ok()); assert_eq!(port.wait(ten_ms.after_now()), Err(Status::TIMED_OUT)); // ... even if we clear and resignal assert!(event.signal_handle(Signals::USER_0, Signals::NONE).is_ok()); // clear signal assert!(event.signal_handle(Signals::NONE, Signals::USER_0).is_ok()); assert_eq!(port.wait(ten_ms.after_now()), Err(Status::TIMED_OUT)); // Calling wait_async again should result in another packet. assert!(event.wait_async_handle( &port, key, Signals::USER_0, WaitAsyncOpts::Repeating).is_ok()); let read_packet = port.wait(ten_ms.after_now()).unwrap(); assert_eq!(read_packet.key(), key); assert_eq!(read_packet.status(), 0); match read_packet.contents() { PacketContents::SignalRep(sig) => { assert_eq!(sig.trigger(), Signals::USER_0); assert_eq!(sig.observed(), Signals::USER_0); assert_eq!(sig.count(), 1); } _ => panic!("wrong packet type"), } // Closing the handle should stop us getting packets. drop(event); assert_eq!(port.wait(ten_ms.after_now()), Err(Status::TIMED_OUT)); } } vendor/fuchsia-zircon-0.3.3/src/process.rs0000640000000000000000000000073113264166600017250 0ustar rootroot// Copyright 2017 The Fuchsia Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. //! Type-safe bindings for Zircon process. use {AsHandleRef, HandleBased, Handle, HandleRef}; /// An object representing a Zircon process. /// /// As essentially a subtype of `Handle`, it can be freely interconverted. #[derive(Debug, Eq, PartialEq)] pub struct Process(Handle); impl_handle_based!(Process);vendor/fuchsia-zircon-0.3.3/src/rights.rs0000640000000000000000000000217713264166600017100 0ustar rootrootuse sys; bitflags! { /// Rights associated with a handle. /// /// See [rights.md](https://fuchsia.googlesource.com/zircon/+/master/docs/rights.md) /// for more information. #[repr(C)] pub struct Rights: sys::zx_rights_t { const NONE = sys::ZX_RIGHT_NONE; const DUPLICATE = sys::ZX_RIGHT_DUPLICATE; const TRANSFER = sys::ZX_RIGHT_TRANSFER; const READ = sys::ZX_RIGHT_READ; const WRITE = sys::ZX_RIGHT_WRITE; const EXECUTE = sys::ZX_RIGHT_EXECUTE; const MAP = sys::ZX_RIGHT_MAP; const GET_PROPERTY = sys::ZX_RIGHT_GET_PROPERTY; const SET_PROPERTY = sys::ZX_RIGHT_SET_PROPERTY; const ENUMERATE = sys::ZX_RIGHT_ENUMERATE; const DESTROY = sys::ZX_RIGHT_DESTROY; const SET_POLICY = sys::ZX_RIGHT_SET_POLICY; const GET_POLICY = sys::ZX_RIGHT_GET_POLICY; const SIGNAL = sys::ZX_RIGHT_SIGNAL; const SIGNAL_PEER = sys::ZX_RIGHT_SIGNAL_PEER; const WAIT = sys::ZX_RIGHT_WAIT; const SAME_RIGHTS = sys::ZX_RIGHT_SAME_RIGHTS; } }vendor/fuchsia-zircon-0.3.3/src/signals.rs0000640000000000000000000000767313264166600017246 0ustar rootrootuse sys::*; bitflags! { /// Signals that can be waited upon. /// /// See /// [Objects and signals](https://fuchsia.googlesource.com/zircon/+/master/docs/concepts.md#Objects-and-Signals) /// in the Zircon kernel documentation. Note: the names of signals are still in flux. #[repr(C)] pub struct Signals: zx_signals_t { const NONE = ZX_SIGNAL_NONE; const OBJECT_ALL = ZX_OBJECT_SIGNAL_ALL; const USER_ALL = ZX_USER_SIGNAL_ALL; const OBJECT_0 = ZX_OBJECT_SIGNAL_0; const OBJECT_1 = ZX_OBJECT_SIGNAL_1; const OBJECT_2 = ZX_OBJECT_SIGNAL_2; const OBJECT_3 = ZX_OBJECT_SIGNAL_3; const OBJECT_4 = ZX_OBJECT_SIGNAL_4; const OBJECT_5 = ZX_OBJECT_SIGNAL_5; const OBJECT_6 = ZX_OBJECT_SIGNAL_6; const OBJECT_7 = ZX_OBJECT_SIGNAL_7; const OBJECT_8 = ZX_OBJECT_SIGNAL_8; const OBJECT_9 = ZX_OBJECT_SIGNAL_9; const OBJECT_10 = ZX_OBJECT_SIGNAL_10; const OBJECT_11 = ZX_OBJECT_SIGNAL_11; const OBJECT_12 = ZX_OBJECT_SIGNAL_12; const OBJECT_13 = ZX_OBJECT_SIGNAL_13; const OBJECT_14 = ZX_OBJECT_SIGNAL_14; const OBJECT_15 = ZX_OBJECT_SIGNAL_15; const OBJECT_16 = ZX_OBJECT_SIGNAL_16; const OBJECT_17 = ZX_OBJECT_SIGNAL_17; const OBJECT_18 = ZX_OBJECT_SIGNAL_18; const OBJECT_19 = ZX_OBJECT_SIGNAL_19; const OBJECT_20 = ZX_OBJECT_SIGNAL_20; const OBJECT_21 = ZX_OBJECT_SIGNAL_21; const OBJECT_22 = ZX_OBJECT_SIGNAL_22; const OBJECT_HANDLE_CLOSED = ZX_OBJECT_HANDLE_CLOSED; const USER_0 = ZX_USER_SIGNAL_0; const USER_1 = ZX_USER_SIGNAL_1; const USER_2 = ZX_USER_SIGNAL_2; const USER_3 = ZX_USER_SIGNAL_3; const USER_4 = ZX_USER_SIGNAL_4; const USER_5 = ZX_USER_SIGNAL_5; const USER_6 = ZX_USER_SIGNAL_6; const USER_7 = ZX_USER_SIGNAL_7; const OBJECT_READABLE = ZX_OBJECT_READABLE; const OBJECT_WRITABLE = ZX_OBJECT_WRITABLE; const OBJECT_PEER_CLOSED = ZX_OBJECT_PEER_CLOSED; // Cancelation (handle was closed while waiting with it) const HANDLE_CLOSED = ZX_SIGNAL_HANDLE_CLOSED; // Event const EVENT_SIGNALED = ZX_EVENT_SIGNALED; // EventPair const EVENT_PAIR_SIGNALED = ZX_EPAIR_SIGNALED; const EVENT_PAIR_CLOSED = ZX_EPAIR_CLOSED; // Task signals (process, thread, job) const TASK_TERMINATED = ZX_TASK_TERMINATED; // Channel const CHANNEL_READABLE = ZX_CHANNEL_READABLE; const CHANNEL_WRITABLE = ZX_CHANNEL_WRITABLE; const CHANNEL_PEER_CLOSED = ZX_CHANNEL_PEER_CLOSED; // Socket const SOCKET_READABLE = ZX_SOCKET_READABLE; const SOCKET_WRITABLE = ZX_SOCKET_WRITABLE; const SOCKET_PEER_CLOSED = ZX_SOCKET_PEER_CLOSED; // Port const PORT_READABLE = ZX_PORT_READABLE; // Resource const RESOURCE_DESTROYED = ZX_RESOURCE_DESTROYED; const RESOURCE_READABLE = ZX_RESOURCE_READABLE; const RESOURCE_WRITABLE = ZX_RESOURCE_WRITABLE; const RESOURCE_CHILD_ADDED = ZX_RESOURCE_CHILD_ADDED; // Fifo const FIFO_READABLE = ZX_FIFO_READABLE; const FIFO_WRITABLE = ZX_FIFO_WRITABLE; const FIFO_PEER_CLOSED = ZX_FIFO_PEER_CLOSED; // Job const JOB_NO_PROCESSES = ZX_JOB_NO_PROCESSES; const JOB_NO_JOBS = ZX_JOB_NO_JOBS; // Process const PROCESS_TERMINATED = ZX_PROCESS_TERMINATED; // Thread const THREAD_TERMINATED = ZX_THREAD_TERMINATED; // Log const LOG_READABLE = ZX_LOG_READABLE; const LOG_WRITABLE = ZX_LOG_WRITABLE; // Timer const TIMER_SIGNALED = ZX_TIMER_SIGNALED; } }vendor/fuchsia-zircon-0.3.3/src/socket.rs0000640000000000000000000001063713264166600017070 0ustar rootroot// Copyright 2016 The Fuchsia Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. //! Type-safe bindings for Zircon sockets. use {AsHandleRef, HandleBased, Handle, HandleRef, Peered}; use {sys, Status, ok}; use std::ptr; /// An object representing a Zircon /// [socket](https://fuchsia.googlesource.com/zircon/+/master/docs/concepts.md#Message-Passing_Sockets-and-Channels). /// /// As essentially a subtype of `Handle`, it can be freely interconverted. #[derive(Debug, Eq, PartialEq)] pub struct Socket(Handle); impl_handle_based!(Socket); impl Peered for Socket {} impl Socket { /// Create a socket, accessed through a pair of endpoints. Data written /// into one may be read from the other. /// /// Wraps /// [zx_socket_create](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/socket_create.md). pub fn create() -> Result<(Socket, Socket), Status> { unsafe { let mut out0 = 0; let mut out1 = 0; let opts = 0; let status = sys::zx_socket_create(opts, &mut out0, &mut out1); ok(status)?; Ok(( Self::from(Handle::from_raw(out0)), Self::from(Handle::from_raw(out1)) )) } } /// Write the given bytes into the socket. /// Return value (on success) is number of bytes actually written. /// /// Wraps /// [zx_socket_write](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/socket_write.md). pub fn write(&self, bytes: &[u8]) -> Result { let mut actual = 0; let opts = 0; let status = unsafe { sys::zx_socket_write(self.raw_handle(), opts, bytes.as_ptr(), bytes.len(), &mut actual) }; ok(status).map(|()| actual) } /// Read the given bytes from the socket. /// Return value (on success) is number of bytes actually read. /// /// Wraps /// [zx_socket_read](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/socket_read.md). pub fn read(&self, bytes: &mut [u8]) -> Result { let mut actual = 0; let opts = 0; let status = unsafe { sys::zx_socket_read(self.raw_handle(), opts, bytes.as_mut_ptr(), bytes.len(), &mut actual) }; ok(status) .map(|()| actual) .map_err(|status| { // If an error is returned then actual is undefined, so to be safe // we set it to 0 and ignore any data that is set in bytes. actual = 0; status }) } /// Close half of the socket, so attempts by the other side to write will fail. /// /// Implements the `ZX_SOCKET_HALF_CLOSE` option of /// [zx_socket_write](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/socket_write.md). pub fn half_close(&self) -> Result<(), Status> { let status = unsafe { sys::zx_socket_write(self.raw_handle(), sys::ZX_SOCKET_HALF_CLOSE, ptr::null(), 0, ptr::null_mut()) }; ok(status) } pub fn outstanding_read_bytes(&self) -> Result { let mut outstanding = 0; let status = unsafe { sys::zx_socket_read(self.raw_handle(), 0, ptr::null_mut(), 0, &mut outstanding) }; ok(status).map(|()| outstanding) } } #[cfg(test)] mod tests { use super::*; #[test] fn socket_basic() { let (s1, s2) = Socket::create().unwrap(); // Write in one end and read it back out the other. assert_eq!(s1.write(b"hello").unwrap(), 5); let mut read_vec = vec![0; 8]; assert_eq!(s2.read(&mut read_vec).unwrap(), 5); assert_eq!(&read_vec[0..5], b"hello"); // Try reading when there is nothing to read. assert_eq!(s2.read(&mut read_vec), Err(Status::SHOULD_WAIT)); // Close the socket from one end. assert!(s1.half_close().is_ok()); assert_eq!(s2.read(&mut read_vec), Err(Status::BAD_STATE)); assert_eq!(s1.write(b"fail"), Err(Status::BAD_STATE)); // Writing in the other direction should still work. assert_eq!(s1.read(&mut read_vec), Err(Status::SHOULD_WAIT)); assert_eq!(s2.write(b"back").unwrap(), 4); assert_eq!(s1.read(&mut read_vec).unwrap(), 4); assert_eq!(&read_vec[0..4], b"back"); } } vendor/fuchsia-zircon-0.3.3/src/status.rs0000640000000000000000000001257213264166600017123 0ustar rootrootuse std::ffi::NulError; use std::io; use sys; /// Status type indicating the result of a Fuchsia syscall. /// /// This type is generally used to indicate the reason for an error. /// While this type can contain `Status::OK` (`ZX_OK` in C land), elements of this type are /// generally constructed using the `ok` method, which checks for `ZX_OK` and returns a /// `Result<(), Status>` appropriately. #[repr(C)] #[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] pub struct Status(sys::zx_status_t); impl Status { /// Returns `Ok(())` if the status was `OK`, /// otherwise returns `Err(status)`. pub fn ok(raw: sys::zx_status_t) -> Result<(), Status> { if raw == Status::OK.0 { Ok(()) } else { Err(Status(raw)) } } pub fn from_raw(raw: sys::zx_status_t) -> Self { Status(raw) } pub fn into_raw(self) -> sys::zx_status_t { self.0 } } assoc_consts!(Status, [ OK = sys::ZX_OK; INTERNAL = sys::ZX_ERR_INTERNAL; NOT_SUPPORTED = sys::ZX_ERR_NOT_SUPPORTED; NO_RESOURCES = sys::ZX_ERR_NO_RESOURCES; NO_MEMORY = sys::ZX_ERR_NO_MEMORY; CALL_FAILED = sys::ZX_ERR_CALL_FAILED; INTERRUPTED_RETRY = sys::ZX_ERR_INTERRUPTED_RETRY; INVALID_ARGS = sys::ZX_ERR_INVALID_ARGS; BAD_HANDLE = sys::ZX_ERR_BAD_HANDLE; WRONG_TYPE = sys::ZX_ERR_WRONG_TYPE; BAD_SYSCALL = sys::ZX_ERR_BAD_SYSCALL; OUT_OF_RANGE = sys::ZX_ERR_OUT_OF_RANGE; BUFFER_TOO_SMALL = sys::ZX_ERR_BUFFER_TOO_SMALL; BAD_STATE = sys::ZX_ERR_BAD_STATE; TIMED_OUT = sys::ZX_ERR_TIMED_OUT; SHOULD_WAIT = sys::ZX_ERR_SHOULD_WAIT; CANCELED = sys::ZX_ERR_CANCELED; PEER_CLOSED = sys::ZX_ERR_PEER_CLOSED; NOT_FOUND = sys::ZX_ERR_NOT_FOUND; ALREADY_EXISTS = sys::ZX_ERR_ALREADY_EXISTS; ALREADY_BOUND = sys::ZX_ERR_ALREADY_BOUND; UNAVAILABLE = sys::ZX_ERR_UNAVAILABLE; ACCESS_DENIED = sys::ZX_ERR_ACCESS_DENIED; IO = sys::ZX_ERR_IO; IO_REFUSED = sys::ZX_ERR_IO_REFUSED; IO_DATA_INTEGRITY = sys::ZX_ERR_IO_DATA_INTEGRITY; IO_DATA_LOSS = sys::ZX_ERR_IO_DATA_LOSS; BAD_PATH = sys::ZX_ERR_BAD_PATH; NOT_DIR = sys::ZX_ERR_NOT_DIR; NOT_FILE = sys::ZX_ERR_NOT_FILE; FILE_BIG = sys::ZX_ERR_FILE_BIG; NO_SPACE = sys::ZX_ERR_NO_SPACE; STOP = sys::ZX_ERR_STOP; NEXT = sys::ZX_ERR_NEXT; ]); impl Status { pub fn into_io_error(self) -> io::Error { self.into() } } impl From for Status { fn from(kind: io::ErrorKind) -> Self { use std::io::ErrorKind::*; match kind { NotFound => Status::NOT_FOUND, PermissionDenied => Status::ACCESS_DENIED, ConnectionRefused => Status::IO_REFUSED, ConnectionAborted => Status::PEER_CLOSED, AddrInUse => Status::ALREADY_BOUND, AddrNotAvailable => Status::UNAVAILABLE, BrokenPipe => Status::PEER_CLOSED, AlreadyExists => Status::ALREADY_EXISTS, WouldBlock => Status::SHOULD_WAIT, InvalidInput => Status::INVALID_ARGS, TimedOut => Status::TIMED_OUT, Interrupted => Status::INTERRUPTED_RETRY, UnexpectedEof | WriteZero | ConnectionReset | NotConnected | Other | _ => Status::IO, } } } impl From for io::ErrorKind { fn from(status: Status) -> io::ErrorKind { use std::io::ErrorKind::*; match status { Status::INTERRUPTED_RETRY => Interrupted, Status::BAD_HANDLE => BrokenPipe, Status::TIMED_OUT => TimedOut, Status::SHOULD_WAIT => WouldBlock, Status::PEER_CLOSED => ConnectionAborted, Status::NOT_FOUND => NotFound, Status::ALREADY_EXISTS => AlreadyExists, Status::ALREADY_BOUND => AlreadyExists, Status::UNAVAILABLE => AddrNotAvailable, Status::ACCESS_DENIED => PermissionDenied, Status::IO_REFUSED => ConnectionRefused, Status::IO_DATA_INTEGRITY => InvalidData, Status::BAD_PATH | Status::INVALID_ARGS | Status::OUT_OF_RANGE | Status::WRONG_TYPE => InvalidInput, Status::OK | Status::NEXT | Status::STOP | Status::NO_SPACE | Status::FILE_BIG | Status::NOT_FILE | Status::NOT_DIR | Status::IO_DATA_LOSS | Status::IO | Status::CANCELED | Status::BAD_STATE | Status::BUFFER_TOO_SMALL | Status::BAD_SYSCALL | Status::INTERNAL | Status::NOT_SUPPORTED | Status::NO_RESOURCES | Status::NO_MEMORY | Status::CALL_FAILED | _ => Other, } } } impl From for Status { fn from(err: io::Error) -> Status { err.kind().into() } } impl From for io::Error { fn from(status: Status) -> io::Error { io::Error::from(io::ErrorKind::from(status)) } } impl From for Status { fn from(_error: NulError) -> Status { Status::INVALID_ARGS } } vendor/fuchsia-zircon-0.3.3/src/thread.rs0000640000000000000000000000072513264166600017044 0ustar rootroot// Copyright 2017 The Fuchsia Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. //! Type-safe bindings for Zircon thread. use {AsHandleRef, HandleBased, Handle, HandleRef}; /// An object representing a Zircon thread. /// /// As essentially a subtype of `Handle`, it can be freely interconverted. #[derive(Debug, Eq, PartialEq)] pub struct Thread(Handle); impl_handle_based!(Thread);vendor/fuchsia-zircon-0.3.3/src/time.rs0000640000000000000000000002267513264166600016543 0ustar rootroot// Copyright 2016 The Fuchsia Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. //! Type-safe bindings for Zircon timer objects. use {AsHandleRef, ClockId, HandleBased, Handle, HandleRef, Status}; use {sys, ok}; use std::ops; use std::time as stdtime; #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct Duration(sys::zx_duration_t); #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct Time(sys::zx_time_t); impl From for Duration { fn from(dur: stdtime::Duration) -> Self { Duration::from_seconds(dur.as_secs()) + Duration::from_nanos(dur.subsec_nanos() as u64) } } impl From for stdtime::Duration { fn from(dur: Duration) -> Self { let secs = dur.seconds(); let nanos = (dur.nanos() - (secs * 1_000_000_000)) as u32; stdtime::Duration::new(secs, nanos) } } impl ops::Add for Time { type Output = Time; fn add(self, dur: Duration) -> Time { Time::from_nanos(dur.nanos() + self.nanos()) } } impl ops::Add