PreviousUpNext

15.4.126  src/app/makelib/tools/main/tools-g.pkg

# The public interface to makelib's tools mechanism.
#   (This generic must be expanded after the rest of makelib is
#    already in place because it uses load_plugin.)
#
#   (C) 2000 Lucent Technologies, Bell Laboratories
#
# Author: Matthias Blume (blume@kurims.kyoto-u.ac.jp)

# Compiled by:
#     src/app/makelib/makelib.sublib




                                                        
                                                                        # private_makelib_tools         is from   src/app/makelib/tools/main/private-makelib-tools.pkg
                                                                        # winix__premicrothread         is from   src/lib/std/winix--premicrothread.pkg
stipulate
    package ad  =  anchor_dictionary;                                   # anchor_dictionary             is from   src/app/makelib/paths/anchor-dictionary.pkg
    package cj  =  global_control_junk;                                 # global_control_junk           is from   src/lib/global-controls/global-control-junk.pkg
    package fil =  file__premicrothread;                                # file__premicrothread          is from   src/lib/std/src/posix/file--premicrothread.pkg
    package mld =  makelib_defaults;                                    # makelib_defaults              is from   src/app/makelib/stuff/makelib-defaults.pkg
    package sub =  string_substitution;                                 # string_substitution           is from   src/app/makelib/stuff/string-substitution.pkg
herein

    # This generic invoked in:
    #     src/app/makelib/main/makelib-g.pkg
    #
    generic package   tools_g   (
        #
        load_plugin'     :   anchor_dictionary::File -> Bool;
        anchor_dictionary:   anchor_dictionary::Anchor_Dictionary;
    )
    : (weak)
    Tools                                                               # Tools                         is from   src/app/makelib/tools/main/public-tools.api
    {
        include package   private_makelib_tools;                                # Moving this into the outer stipulate is a pain; most of the components are re-exported via api Tools.


        say  = fil::say;                                                # Exported to clients.


        # Find the executable binary for this command.
        # There are three cases:
        #
        #    /bin/foo   is interpreted as an abosolute path.
        #
        #     bin/foo   is interpreted as a path relative
        #               to anchor_dictionary::get_anchor "ROOT"
        #
        #         foo   is interpreted as $foo/foo
        #               if foo is a defined anchor.
        #
        # The result of this function SHOULD NOT be cached.
        # Otherwise a later addition or change of an anchor
        # will go unnoticed.
        #
        fun resolve_command_path
                file                                                    # command as a standard path.
            =
            if (string::get_byte_as_char (file, 0) == '/')              # Does path start with '/'?
                #
                file;                                                   # Yes, use it as-is
            else
                case (ad::get_anchor                                    # Is it defined as an anchor?
                         ( anchor_dictionary,
                           file
                         ))

                     THE dir                                            # Yes, treat it as $foo/foo
                         =>
                         winix__premicrothread::path::make_path_from_dir_and_file { dir, file };

                     NULL                                               # No, treat it as $ROOT/foo
                         =>
                         (the (ad::get_anchor( anchor_dictionary, "ROOT"))) + "/" + file;
                esac;
            fi;

        fun note_standard_shell_command_tool
                args
            =
            {   args -> { tool,
                          ilk,
                          suffixes,
                          command_standard_path,
                          extension_style,
                          template,
                          dflopts
                        };

                template = the_else (template, "%c %u %s");

                fun err m
                    =
                    raise exception TOOL_ERROR { tool, msg => m };

                fun rule { spec, context, native2pathmaker, default_ilk_of, sysinfo }
                    =
                    {   spec ->  { name, make_path, tool_options, derived, ... } :  Spec;

                        opts = the_else (tool_options, dflopts);

                        sol =   list::map_partial_fn so opts
                                where
                                    fun so (SUBOPTS _) =>  NULL;                                                #  only use STRING options for %o 
                                        so (STRING  s) =>  THE (native_spec (srcpath (s.make_path ())));
                                    end;
                                end;

                                                            # list              is from   src/lib/std/src/list.pkg

                        p =  srcpath (make_path ());

                        native_name =  native_spec p;

                        tfiles = extend_filename extension_style (native_name, tool_options);

                        partial_expansion
                            =
                            ( { source_files => [],
                                makelib_files => [],
                                sources => [(p, { ilk, derived } )]
                              },
                              map (\\ (name, ilk, tool_options)
                                      =
                                      { name,
                                        ilk,
                                        tool_options,
                                        derived   => TRUE,
                                        make_path => native2pathmaker name
                                       }
                                  )
                                  tfiles
                            );

                        fun run_command ()
                            =
                            {   (command_standard_path ())
                                    ->
                                    (csp, shelloptions);                # "csp" == "command as a standard path" -- see "resolve_command_path" comments.
                                    
                                command_path =  resolve_command_path  csp;

                                cmd =   sub::substitute
                                            [
                                              { prefix => "%",

                                                substitutions
                                                    =>
                                                    [ sub::subfor "%c" command_path,
                                                      sub::subfor "%s" native_name,
                                                      sub::subfor "%%" "%",

                                                      sub::subnsel  (1, 'o', \\ x = x, " ")  sol,
                                                      sub::subnsel  (1, 't', #1,       " ")  tfiles,
                                                      sub::subnsel  (1, 'u', \\ x = x, " ")  shelloptions
                                                    ]
                                              }
                                            ]
                                            template;


                                include package  winix__premicrothread::process;

                                #
                                if (bin_sh' cmd != success)     err cmd;                fi;
                            };

                        fun rulefn ()
                            =
                            {   if (outdated tool (map #1 tfiles, native_name))
                                    #
                                    run_command ();
                                fi;

                                partial_expansion;
                            };

                        context rulefn;
                    };

                fun do_suffix  suffix
                    =
                    note_filename_classifier (standard_filename_suffix_classifier { suffix, ilk } );

                note_ilk (ilk, rule);

                apply do_suffix suffixes;
            };

        stipulate

            tool_ilk   = "tool";
            suffix_ilk = "suffix";

            empty_expansion
                =
                ( { makelib_files  => [],
                    source_files => [],
                    sources  => []
                  },
                  []
                );

            fun tool_rule { spec, context, native2pathmaker, default_ilk_of, sysinfo }
                =
                {   spec ->  { name, make_path, tool_options, ... } :  Spec;

                    fun err m
                        =
                        raise exception TOOL_ERROR { tool => tool_ilk, msg => m };

                    p =  srcpath (make_path ());

                    case tool_options
                        #
                        NULL =>    if (with_plugin p (\\ () =  load_plugin' p))
                                        #
                                        empty_expansion;
                                    else
                                        err "tool registration failed";
                                    fi;

                        THE _ =>    err "no tool options are recognized";
                    esac;
                };


            fun suffix_rule { spec, context, native2pathmaker, default_ilk_of, sysinfo }
                =
                {   spec ->  { name => suffix, tool_options, ... } :  Spec;

                    fun err m
                        =
                        raise exception TOOL_ERROR { tool => suffix_ilk, msg => m };

                    fun note ilk
                        =
                        {   note_filename_classifier
                                (standard_filename_suffix_classifier { suffix, ilk } );

                            empty_expansion;
                        };

                    case tool_options
                        #
                        THE [STRING c]
                            =>
                            note c.name;

                        THE [SUBOPTS { name => "ilk", tool_options => [STRING c] } ]
                            =>
                            note c.name;

                        _   =>   err "invalid options";
                    esac;
                };
        herein
                                                                                        my _ = 
            note_ilk (tool_ilk,     tool_rule);                                         my _ = 
            note_ilk (suffix_ilk, suffix_rule);
        end;

        fun make_boolean_control (name, doc, default)
            =
            mld::make_control
                (
                  cj::cvt::bool,
                  name,
                  doc,
                  default
                );



    };
end;


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext