#line 2844 "/home/travis/build/felix-lang/felix/src/packages/flx.fdoc"
  include "std/felix/config";
  
  include "std/felix/flx_cache";
  include "std/felix/flx_pkg";
  include "std/felix/flx_flxg";
  include "std/felix/flx_cxx";
  
  include "std/felix/flx/flx_control";
  include "std/felix/flx/flx_cmdopt";
  include "std/felix/flx/flx_depvars";
  include "std/felix/flx/flx_run";
  include "std/felix/toolchain_clang_config";
  include "std/felix/toolchain_interface";
  
  open FlxCache;
  
  // Felix version of THIS program (NOT the one being installed
  // if you're using flx to install Felix)
  
  
  class Flx
  {
    gen flx_processing
    (
      config:&Config::config_type,
      control:&FlxControl::control_type,
      loopctl:&FlxControl::loopctl_type,
      args:list[string]
    ) : int =
    {
      var result = 0;
      fun / (a:string, b:string) => Filename::join (a,b);
      FlxCmdOpt::processing_stage1 (config,control,loopctl,varray[string] args);
      if control*.VALIDATE_CACHE == 1 do
        check_cache(config, control);
      done
      if loopctl*.base == "" and control*.INREGEX == "" do
        if control*.CLEAR_CACHE != 1 do
          println "usage: flx [options] filename";
          System::exit(1);
        done
        System::exit(0);
      done
  
      var pkgconfig = FlxPkgConfig::FlxPkgConfigQuery$ config*.FLX_CONFIG_DIRS;
  
      var toolchain_name =
        if control*.FLX_TOOLCHAIN == "" then pkgconfig.getpkgfield1 ("toolchain", "toolchain")
        else control*.FLX_TOOLCHAIN
      ;
  
      var toolchain =
         match toolchain_name with
         | x =>
           Dynlink::load-plugin-func1 [toolchain_t,clang_config_t] ( dll-name=x, setup-str="")
         endmatch
      ;
      if control*.INREGEX != "" do
  
        begin
          //control.USER_ARGS <- Shell::quote_arg(loopctl*.progname) + ' ' + control*.USER_ARGS;
          // this is a hack because -- argument translates to empty program name ..
          // and also if there is no name in that slot ..
          if loopctl*.progname != "" do
            control.USER_ARGS <- loopctl*.progname ! control*.USER_ARGS;
          done
          if control*.INDIR == "" do control.INDIR <- "."; done
          var regex = RE2 control*.INREGEX;
          if not regex.ok do
            eprintln$ "Malformed regex " + control*.INREGEX;
            result = 1;
            goto endoff;
          done
          var files = FileSystem::regfilesin (control*.INDIR, regex);
          var n = files.len.int;
          println$ "Processing " + files.len.str + " files";
          var i = 1;
          var pass = 0;
          var fail = 0;
          files = sort files;
          for file in files do
            var arg = Filename::join (control*.INDIR, file);
            loopctl*.path,loopctl*.ext = Filename::split_extension(arg);
            loopctl*.dir,loopctl*.base = Filename::split1(loopctl*.path);
            // temporary hack, to force reset of the linker filename, stdout, and expect
            // file names in cal_depvars so they depend on the current file.
            control.LINKER_OUTPUT_FILENAME <- "";
            control.STDOUT <- "";
            control.EXPECT <- "";
            control.STDIN <- "";
            var dvars = FlxDepvars::cal_depvars(toolchain,*config,control,*loopctl);
            println$ f"Processing [%02d/%02d]: %S" (i, n, file);
            var pe = processing_env(toolchain,*config,*control,dvars);
            result = pe.runit();
            if result == 0 do ++pass; else ++fail; done
            if control*.NONSTOP==0 and  result != 0 goto endoff;
            ++i;
            collect();
          done
          println$ f"Batch result (%02d OK + %02d FAIL)/%2d" (pass, fail,n);
        end
      else
        begin
          if control*.SHOWCODE == 1 do
              var prg =
                (if dvars.use_ext == "" then "// No file "+dvars.filebase+".(flx|fdoc) found"
                else load(dvars.filebase+"."+dvars.use_ext)
              );
              print prg;
          done
          var dvars = FlxDepvars::cal_depvars(toolchain,*config,control, *loopctl);
          var pe = processing_env(toolchain,*config,*control,dvars);
          result = pe.runit();
        end
      done
  endoff:>
      return result;
    }
  
    gen runflx(args:list[string]) : int =
    {
      var config = #Config::std_config;
      var control = #FlxControl::dflt_control;
      var loopctl = #FlxControl::init_loopctl;
      return flx_processing(&config, &control, &loopctl, args);
    }
  }