#line 433 "/home/travis/build/felix-lang/felix/src/packages/flx.fdoc"
  include "std/version";
  include "std/felix/flx_profile";
  
  
  
  class Config {
    typedef config_type = (
      FLX_SHARE_DIR: string,
      FLX_TARGET_DIR: string,
      FLX_HOME_DIR: string,
      FLX_PROFILE_DIR: string,
      FLX_CACHE_DIR: string,
      FLX_OUTPUT_DIR: string,
      FLX_CONFIG_DIRS: list[string],
      FLX_LIB_DIRS: list[string],
      FLX_RTL_DIRS: list[string]
    );
  
    instance Str[config_type] {
      fun str (x:config_type) : string =
      {
        var s = "";
        reserve$ &s,1000;
        s+="(FLX_SHARE_DIR="+ x.FLX_SHARE_DIR+",\n";
        s+= "FLX_TARGET_DIR="+ x.FLX_TARGET_DIR+",\n";
        s+="FLX_HOME_DIR="+ x.FLX_HOME_DIR+",\n";
        s+="FLX_PROFILE_DIR="+ x.FLX_PROFILE_DIR+",\n";
        s+="FLX_CACHE_DIR="+ x.FLX_CACHE_DIR+",\n";
        s+="FLX_OUTPUT_DIR="+ x.FLX_OUTPUT_DIR+",\n";
        s+="FLX_LIB_DIRS="+ x.FLX_LIB_DIRS.str+",\n";
        s+="FLX_CONFIG_DIRS="+ x.FLX_CONFIG_DIRS.str+",\n";
        s+="FLX_RTL_DIRS="+ x.FLX_RTL_DIRS.str+")\n";
        return s;
      }
    }
  
    private fun / (x:string, y:string) => Filename::join (x,y);
  
    proc set_libs_and_rtls (x: &config_type)
    {
      x.FLX_LIB_DIRS <- list (x*.FLX_SHARE_DIR/"lib", x*.FLX_TARGET_DIR/"lib");
      x.FLX_RTL_DIRS <- list (x*.FLX_SHARE_DIR/"lib"/"rtl", x*.FLX_TARGET_DIR/"lib"/"rtl");
    }
  
    proc cascade_FLX_INSTALL_DIR (x: &config_type)  (y: string) = {
      cascade_FLX_TARGET_DIR x (y/"host");
      cascade_FLX_SHARE_DIR x (y/"share");
    }
  
    proc cascade_FLX_TARGET_DIR (x: &config_type)  (y: string) = {
      x.FLX_TARGET_DIR <- y;
      x.FLX_CONFIG_DIRS <- list[string] (y/"config");
      set_libs_and_rtls x;
    }
  
    proc cascade_FLX_SHARE_DIR (x: &config_type)  (y: string) = {
      x.FLX_SHARE_DIR <- y;
      set_libs_and_rtls x;
    }
  
    proc cascade_FLX_HOME_DIR (x: &config_type)  (y: string) = {
      x.FLX_HOME_DIR <- y;
      x.FLX_PROFILE_DIR <- y/"config";
      x.FLX_CACHE_DIR <- y/"cache"/"binary";
      x.FLX_OUTPUT_DIR <- y/"cache"/"text";
    }
  
    proc copy_profile (cfg: &config_type) (profile: FlxProfile::profile_type)
    {
      cfg.FLX_HOME_DIR <- profile.FLX_HOME_DIR;
      cfg.FLX_PROFILE_DIR <- profile.FLX_PROFILE_DIR;
      cfg.FLX_CACHE_DIR <- profile.FLX_CACHE_DIR;
      cfg.FLX_OUTPUT_DIR <- profile.FLX_OUTPUT_DIR;
    }
  
    fun dflt_config() :config_type = {
      var profile = FlxProfile::dflt_profile();
      var cfg : config_type;
      copy_profile &cfg profile;
  
      // global defaults
      var PREFIX = Filename::root_subdir "usr"/"local"/"lib";
  
      var INSTALL_ROOT_TOPDIR= PREFIX/"felix";
      var INSTALL_ROOT = INSTALL_ROOT_TOPDIR/ ("felix-"+Version::felix_version);
      cascade_FLX_INSTALL_DIR &cfg INSTALL_ROOT;
      return cfg;
    }
  
    proc process_config_text (cfg:&config_type) (text:string)
    {
  
      var re = RE2 ("([-a-zA-Z_]+) *: *(.*)");
      var FLX_INSTALL_DIR = "";
  
      var lines = split (text, char "\n");
      for line in lines do
        var found = Match (re, line);
        match found with
        | Some v when v.len.int == 3 =>
          var p = v.1;
          var a = strip v.2;
          match p with
          | "FLX_INSTALL_DIR" =>
            FLX_INSTALL_DIR = a;
            cascade_FLX_INSTALL_DIR cfg a;
  
          | "FLX_TARGET_SUBDIR" =>
            if FLX_INSTALL_DIR != "" do
              cascade_FLX_TARGET_DIR cfg (FLX_INSTALL_DIR / a);
            else
              eprintln$ "Cannot set FLX_TARGET_SUBDIR without setting FLX_INSTALL_DIR";
              System::exit 1;
            done
  
          | "FLX_SHARE_DIR" => cascade_FLX_SHARE_DIR cfg a;
          | "FLX_TARGET_DIR" => cascade_FLX_TARGET_DIR cfg a;
          | "FLX_HOME_DIR" => cascade_FLX_HOME_DIR cfg a;
          | "FLX_PROFILE_DIR" => cfg.FLX_PROFILE_DIR <- a;
          | "FLX_CONFIG_DIRS" => cfg.FLX_CONFIG_DIRS <- respectful_split a;
          | "FLX_CACHE_DIR" => cfg.FLX_CACHE_DIR <- a;
          | "FLX_OUTPUT_DIR" => cfg.FLX_OUTPUT_DIR <- a;
          | "FLX_LIB_DIRS" => cfg.FLX_LIB_DIRS <-  respectful_split a;
          | "FLX_RTL_DIRS" => cfg.FLX_RTL_DIRS <- respectful_split a;
          | _ => ;
          endmatch;
        | #None => ;
        endmatch;
      done
    }
  
  
    proc config_env_overrides (cfg:&config_type)
    {
  
      match Env::getenv ("FLX_INSTALL_DIR","") with
      | "" => ;
      | x => cascade_FLX_INSTALL_DIR cfg x;
      endmatch;
  
      match Env::getenv ("FLX_SHARE_DIR","") with
      | "" => ;
      | x => cascade_FLX_SHARE_DIR cfg x;
      endmatch;
  
      match Env::getenv ("FLX_TARGET_DIR","") with
      | "" => ;
      | x => cascade_FLX_TARGET_DIR cfg x;
      endmatch;
  
      match Env::getenv ("FLX_CONFIG_DIRS","") with
      | "" => ;
      | x => cfg.FLX_CONFIG_DIRS <- respectful_split x;
      endmatch;
  
      match Env::getenv ("FLX_LIB_DIRS","") with
      | "" => ;
      | x => cfg.FLX_LIB_DIRS <- respectful_split x;
      endmatch;
  
      match Env::getenv ("FLX_RTL_DIRS","") with
      | "" => ;
      | x => cfg.FLX_RTL_DIRS <- respectful_split x;
      endmatch;
    }
  
    proc process_config_text_with_env_overrides (cfg:&config_type) (text:string)
    {
      process_config_text cfg text;
      config_env_overrides cfg;
    }
  
    fun std_config () = {
      var cfg = #dflt_config;
      process_config_text_with_env_overrides &cfg (load (cfg.FLX_PROFILE_DIR / "felix.fpc"));
      return cfg;
    }
  
  }