1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
use super::process_util::*;

use super::PerlCommand;

use std::collections::HashMap;

type ConfigDict = HashMap<String, String>;

pub struct PerlConfig {
    command: PerlCommand,
    pub dict: ConfigDict,
}

impl Default for PerlConfig {
     fn default() -> Self {
        let cmd = PerlCommand::default();
        let dict = read_config(&cmd, &[]).expect("Failed to read Config.pm");
        Self {
            command: cmd,
            dict: dict,
        }
    }
}

impl PerlConfig {

    pub fn new(perl: &str) -> Self {
        let cmd = PerlCommand::new(perl);
        let dict = read_config(&cmd, &[]).expect("Failed to read Config.pm");
        Self {
            command: cmd,
            dict: dict,
        }
    }

    pub fn command(&self, args: &[&str]) -> Command {
        self.command.command(args)
    }

    pub fn read_ccopts(&self) -> Result<Vec<String>, Error> {
        self.command.read_ccopts()
    }

    pub fn read_ldopts(&self) -> Result<Vec<String>, Error> {
        self.command.read_ldopts()
    }

    pub fn is_defined(&self, name: &str) -> Result<bool, Error> {
        if let Some(value) = self.dict.get(name) {
            Ok(value == "define")
        } else {
            Err(other_error("No such entry".to_string()))
        }
    }

    pub fn emit_cargo_ldopts(&self) {
        self.command.emit_cargo_ldopts()
    }

    pub fn emit_perlapi_vers(&self, min: i32, max: i32) {
        let config = &self.dict["PERL_API_VERSION"];
        let config = config.trim();
        println!("# PERL_API_VERSION={}", config);
        let ver = i32::from_str_radix(String::from(config).trim(), 10).unwrap();
        for v in min..=max {
            if v % 2 == 1 {
                continue;
            }
            if ver >= v {
                println!("cargo:rustc-cfg=perlapi_ver{}", v);
            }
        }
    }

    pub fn emit_features(&self, configs: &[&str]) {
        for &cfg in configs.iter() {
            println!("# perl config {} = {:?}", cfg, self.dict.get(&String::from(cfg)));
            if self.is_defined(cfg).unwrap() {
                println!("cargo:rustc-cfg=perl_{}", cfg);
            }
        }
    }
}

fn read_config(cmd: &PerlCommand, configs: &[&str]) -> Result<ConfigDict, Error> {
    let config = cmd.read_raw_config(configs)?;
    let lines = config.lines().map(String::from).collect();
    Ok(lines_to_hashmap(lines))
}

fn lines_to_hashmap(lines: Vec<String>) -> ConfigDict {
    let mut dict = HashMap::new();
    for line in lines.iter() {
        let kv: Vec<String> = line.splitn(2, '\t').map(String::from).collect();
        if kv.len() == 2 {
            dict.insert(kv[0].clone(), kv[1].clone());
        }
    }
    dict
}