# 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.libpackage shell_tool {
#
stipulate
#
include package 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;
};