PreviousUpNext

15.4.132  src/app/makelib/tools/shell/tool.pkg

# A tool for running arbitrary shell commands from makelib.
#
#   (C) 2000 Lucent Technologies, Bell Laboratories
#
# Author: Matthias Blume (blume@kurims.kyoto-u.ac.jp)

# Compiled by:
#     src/app/makelib/tools/shell/shell-tool.lib

package shell_tool {
    #
    stipulate
        #
        include tools;
        package subst =   string_substitution;                  # string_substitution   is from   src/app/makelib/stuff/string-substitution.pkg

        tool       = "Shell-Command";

        ilk        = "shell";
        kw_ilk     = "ilk";                                     # "kw" is probably "keyword".
        kw_options = "options";
        kw_source  = "source";
        kw_target  = "target";

        kwl = [kw_ilk, kw_options, kw_source, kw_target];       # "kwl" is probably "keyword list".

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

        fun badspec kw
            =
            err (cat ["bad specification for keyword `",
                                      kw, "'"]);

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

                sysinfo
                    ->
                    { get_makelib_preprocessor_symbol_value,                                    # See   find_makelib_preprocessor_symbol  from   src/app/makelib/main/makelib-preprocessor-state-g.pkg
                      platform                                                                  # A string like "intel32-linux"
                    };
                    

                specpath =  srcpath (make_path ());
                specname =  native_spec specpath;

                my (sname, tname, tilk, topts, cmdline)
                    =
                    case too                                    # "too" is  something like "tool opts"
                        #
                        THE ol =>
                            {   (parse_options { tool, keywords => kwl, tool_options => ol })
                                    ->
                                    { matches, remaining_options };
                                    

                                fun fmatch kw
                                    =
                                    case (matches kw)
                                        #
                                        THE [STRING { name, make_path } ]
                                            =>
                                            THE (native_spec (srcpath (make_path ())));
                                        #
                                        NULL => NULL;
                                        #
                                        _ => badspec kw;
                                    esac;

                                tilk =  case (matches kw_ilk)
                                            #
                                            THE [STRING { name, ... } ]
                                                =>
                                                THE name;

                                            NULL =>  NULL;
                                            #
                                            _ => badspec kw_ilk;
                                        esac;

                                topts =  matches  kw_options;

                                fun return (sname, tname)
                                    =
                                    {   fun subst s
                                            =
                                            {   fun otherpercents  ss
                                                    =
                                                    if (substring::size ss == 2)   THE (string::from_char (substring::get (ss, 1)));
                                                    else                           NULL;
                                                    fi;

                                                fun sv ss                                                                               # "sv" may be "(preprocessor) symbol value";  "ss" is probably "substring"
                                                    =
                                                    THE  case (get_makelib_preprocessor_symbol_value (substring::to_string ss))
                                                             #  
                                                             THE i =>  int::to_string  i;
                                                             NULL  =>  "";                                                              # No such symbol defined in preprocessor dictionary.
                                                         esac;


                                                fun qsv ss                                                                              # "qsv"
                                                    =
                                                    {   sslen =  substring::size  ss;

                                                        fun doqsv (var, value)                                                          # If 'var' is defined return THE 'value' else return THE "".
                                                            =
                                                            case (get_makelib_preprocessor_symbol_value (substring::to_string var))
                                                                #
                                                                THE _ =>  THE (substring::to_string value);
                                                                NULL  =>  THE "";
                                                            esac;

                                                        fun findcolon i
                                                            =
                                                            if (i >= sslen) 
                                                                #                                                                
                                                                doqsv (ss, ss);
                                                            else
                                                                if (substring::get (ss, i) == ':')
                                                                    #
                                                                    doqsv (substring::make_slice (ss, 0, THE i),
                                                                                           substring::make_slice (ss, i+1, THE (sslen-i - 1))
                                                                          );
                                                                else
                                                                    findcolon (i+1);
                                                                fi;
                                                            fi;

                                                        findcolon 0;
                                                    };

                                                subst::substitute [ { prefix => "$?(",
                                                                     substitutions =>
                                                                     [ subst::submap (3, ')') qsv ]
                                                                   },
                                                                   { prefix => "$(",
                                                                     substitutions =>
                                                                     [ subst::submap (2, ')') sv ]
                                                                   },
                                                                   { prefix => "%",
                                                                     substitutions =>
                                                                     [ subst::subfor "%s" sname,
                                                                       subst::subfor "%t" tname,
                                                                       subst::subfor "%a" platform,
                                                                       otherpercents
                                                                     ]
                                                                   }
                                                                 ]
                                                                 s;
                                            };

                                    fun ad (x, l)
                                        =
                                        " " ! subst x ! l;

                                    cmdline
                                        =
                                        case remaining_options
                                            #
                                            []    =>  err "no command line specified";
                                            h ! t =>  cat (subst h ! fold_backward ad [] t);
                                        esac;

                                    (sname, tname, tilk, topts, cmdline);
                                };

                            case (fmatch kw_source, fmatch kw_target)
                                #
                                (THE src, NULL    ) =>   return (src, specname);
                                (NULL,    THE tgt ) =>   return (specname, tgt);
                                (THE _,   THE _   ) =>   err "only one of `source: ' and `target: ' can be specified";
                                (NULL,    NULL    ) =>   err "either `source: ' or `target: ' must be specified";
                            esac;
                        };

                        #                     
                        NULL =>   err "missing options";
                    esac;

                spath =   srcpath (native2pathmaker sname ());

                partial_expansion
                    =
                    ( { source_files => [],
                        makelib_files => [],
                        sources => [(spath, { ilk, derived } )]
                      },
                                                                    # "If str was the target, then "derived" does not really
                                                                    #  make much sense.  I guess the best thing is to get
                                                                    #  rid of the "source:" option."   -- Matthias Blume (?)   XXX BUGGO FIXME
                      [ { name => tname,
                          make_path => native2pathmaker tname,
                          ilk => tilk,
                          tool_options => topts,
                          derived => TRUE
                        }
                      ]
                    );

                fun run_command ()
                    =
                    {   say .{ cat [ "[", cmdline, "]\n" ]; };
                        #
                        if (winix__premicrothread::process::bin_sh' cmdline != winix__premicrothread::process::success)
                            #                        
                            err cmdline;
                        fi;
                    };

                fun rulefn ()
                    =
                    {   if (outdated tool ([tname], sname))
                            #                            
                            run_command ();
                        fi;

                        partial_expansion;
                    };
            
                context rulefn;
            };
    herein                                                         my _ =
        tools::note_ilk (ilk, rule);
    end;
};


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext