// -*- c++ -*- // This file is part of the Collective Variables module (Colvars). // The original version of Colvars and its updates are located at: // https://github.com/Colvars/colvars // Please update all Colvars source files before making any changes. // If you wish to distribute your changes, please submit them to the // Colvars repository at GitHub. #ifndef COLVARSCRIPT_H #define COLVARSCRIPT_H #include #include #include #include "colvarmodule.h" #include "colvarvalue.h" #include "colvarproxy.h" // Only these error values are part of the scripting interface #define COLVARSCRIPT_ERROR -1 #define COLVARSCRIPT_OK 0 class colvardeps; class colvarscript { private: colvarproxy *proxy_; colvarmodule *colvars; inline colvarscript() {} // no-argument construction forbidden public: friend class colvarproxy; colvarscript(colvarproxy *p, colvarmodule *m); ~colvarscript(); /// String representation of the result of a script call std::string str_result_; /// Run a script command with space-separated positional arguments (objects) int run(int objc, unsigned char *const objv[]); /// Get the string result of the current scripting call inline std::string const &str_result() const { return str_result_; } /// Modify the string result of the current scripting call inline std::string &modify_str_result() { return str_result_; } /// Set the return value to the given string int set_result_str(std::string const &s); /// Clear the string result int clear_str_result(); /// Add the given string to the error message of the script interface void add_error_msg(std::string const &s); /// Commands available enum command { #define CVSCRIPT_ENUM_COMM(COMM) COMM, #undef CVSCRIPT #define CVSCRIPT(COMM,HELP,N_ARGS_MIN,N_ARGS_MAX,ARGS,FN_BODY) \ CVSCRIPT_ENUM_COMM(COMM) #ifdef COLVARSCRIPT_COMMANDS_H #undef COLVARSCRIPT_COMMANDS_H #endif #include "colvarscript_commands.h" #undef COLVARSCRIPT_COMMANDS_H #undef CVSCRIPT #undef CVSCRIPT_ENUM_COMM cv_n_commands }; /// Type of object handling a script command enum Object_type { use_module, use_colvar, use_bias }; /// Return the prefix of the individual command for each object function std::string get_cmd_prefix(Object_type t); /// Get a pointer to the i-th argument of the command (NULL if not given) template unsigned char *get_cmd_arg(int iarg, int objc, unsigned char *const objv[]); /// Instantiation of get_cmd_arg<> for module-level commands unsigned char *get_module_cmd_arg(int iarg, int objc, unsigned char *const objv[]); /// Instantiation of get_cmd_arg<> for colvar-level commands unsigned char *get_colvar_cmd_arg(int iarg, int objc, unsigned char *const objv[]); /// Instantiation of get_cmd_arg<> for bias-level commands unsigned char *get_bias_cmd_arg(int iarg, int objc, unsigned char *const objv[]); /// Check the argument count of the command template int check_cmd_nargs(char const *cmd, int objc, int n_args_min, int n_args_max); /// Instantiation of check_cmd_nargs<> for module-level commands int check_module_cmd_nargs(char const *cmd, int objc, int n_args_min, int n_args_max); /// Instantiation of check_cmd_nargs<> for colvar-level commands int check_colvar_cmd_nargs(char const *cmd, int objc, int n_args_min, int n_args_max); /// Instantiation of get_cmd_arg<> for bias-level commands int check_bias_cmd_nargs(char const *cmd, int objc, int n_args_min, int n_args_max); /// Number of positional arguments to shift for each object type template int cmd_arg_shift(); /// Get names of all commands inline char const **get_command_names() const { return cmd_names; } /// Get one-line help summary for a command /// \param cmd Name of the command's function (e.g. "cv_units") char const *get_command_help(char const *cmd); /// Get description of the return value of a command /// \param cmd Name of the command's function (e.g. "cv_units") char const *get_command_rethelp(char const *cmd); /// Get description of the argument of a command (excluding prefix) /// \param cmd Name of the command's function (e.g. "cv_units") /// \param i Index of the argument; 0 is the first argument after the /// prefix, e.g. "value" has an index of 0 in the array of arguments: /// { "cv", "colvar", "xi", "value" } char const *get_command_arghelp(char const *cmd, int i); /// Get number of required arguments (excluding prefix) /// \param cmd Name of the command's function (e.g. "cv_units") int get_command_n_args_min(char const *cmd); /// Get number of total arguments (excluding prefix) /// \param cmd Name of the command's function (e.g. "cv_units") int get_command_n_args_max(char const *cmd); /// Set the main command for the CLI, when it is not "cv" (e.g. LAMMPS) inline void set_cmdline_main_cmd(std::string const &cmd) { cmdline_main_cmd_ = cmd; } /// Get help string for a command (does not specify how it is launched) /// \param cmd Name of the command's function (e.g. "cv_units") char const *get_command_full_help(char const *cmd); /// Get summary of command line syntax for all commands of a given context /// \param t One of use_module, use_colvar or use_bias std::string get_cmdline_help_summary(Object_type t); /// Get a description of how the command should be used in a command line /// \param t One of use_module, use_colvar or use_bias /// \param c Value of the \link command \endlink enum std::string get_command_cmdline_syntax(Object_type t, command c); /// Get the command line syntax following by the help string /// \param t One of use_module, use_colvar or use_bias /// \param cmd Name of the subcommand (e.g. "units") std::string get_command_cmdline_help(Object_type t, std::string const &cmd); /// Set error code for unsupported script operation int unsupported_op(); /// Pointer to the Colvars main object inline colvarmodule *module() { return this->colvars; } /// Pointer to the colvarproxy object (interface with host engine) inline colvarproxy *proxy() { return this->proxy_; } // Input functions - get the string reps of script argument objects /// Get the string representation of an object (by default, a simple cast) char *obj_to_str(unsigned char *obj); /// Get a list of strings from an object (does not work with a simple cast) std::vector obj_to_str_vector(unsigned char *obj); // Output functions - convert internal objects to representations suitable // for use in the scripting language. At the moment only conversion to C // strings is supported, and obj is assumed to be a char * pointer. /// Copy x into obj if not NULL, or into the script object's result otherwise int set_result_int(int const &x, unsigned char *obj = NULL); /// Copy x into obj if not NULL, or into the script object's result otherwise int set_result_int_vec(std::vector const &x, unsigned char *obj = NULL); /// Copy x into obj if not NULL, or into the script object's result otherwise int set_result_long_int(long int const &x, unsigned char *obj = NULL); /// Copy x into obj if not NULL, or into the script object's result otherwise int set_result_long_int_vec(std::vector const &x, unsigned char *obj = NULL); /// Copy x into obj if not NULL, or into the script object's result otherwise int set_result_real(cvm::real const &x, unsigned char *obj = NULL); /// Copy x into obj if not NULL, or into the script object's result otherwise int set_result_real_vec(std::vector const &x, unsigned char *obj = NULL); /// Copy x into obj if not NULL, or into the script object's result otherwise int set_result_rvector(cvm::rvector const &x, unsigned char *obj = NULL); /// Copy x into obj if not NULL, or into the script object's result otherwise int set_result_rvector_vec(std::vector const &x, unsigned char *obj = NULL); /// Copy x into obj if not NULL, or into the script object's result otherwise int set_result_colvarvalue(colvarvalue const &x, unsigned char *obj = NULL); /// Copy x into obj if not NULL, or into the script object's result otherwise int set_result_colvarvalue_vec(std::vector const &x, unsigned char *obj = NULL); private: /// Set up all script API functions int init_commands(); /// Set up a single script API function int init_command(colvarscript::command const &comm, char const *name, char const *help, int n_args_min, int n_args_max, char const *arghelp, int (*fn)(void *, int, unsigned char * const *)); public: // TODO this function will be removed soon /// Run subcommands on base colvardeps object (colvar, bias, ...) int proc_features(colvardeps *obj, int argc, unsigned char *const argv[]); private: // TODO /// Internal identifiers of command strings std::map cmd_str_map; /// Main command used in command line ("cv" by default) std::string cmdline_main_cmd_; /// Inverse of cmd_str_map (to be exported outside this class) char const **cmd_names; /// Help strings for each command std::vector cmd_help; /// Description of the return values of each command (may be empty) std::vector cmd_rethelp; /// Minimum number of arguments for each command std::vector cmd_n_args_min; /// Maximum number of arguments for each command std::vector cmd_n_args_max; /// Help strings for each command argument std::vector< std::vector > cmd_arghelp; /// Full help strings for each command std::vector cmd_full_help; /// Implementations of each command std::vector cmd_fns; /// Get a pointer to the implementation of the given command inline int (*get_cmd_fn(std::string const &cmd_key))(void *, int, unsigned char * const *) { if (cmd_str_map.count(cmd_key) > 0) { return cmd_fns[cmd_str_map[cmd_key]]; } return NULL; } /// Set obj equal to x, using its string representation template int set_result_text(T const &x, unsigned char *obj); /// Code reused by instances of set_result_text() template int pack_vector_elements_text(std::vector const &x, std::string &x_str); /// Code reused by all instances of set_result_text() int set_result_text_from_str(std::string const &x_str, unsigned char *obj); }; /// Get a pointer to the main colvarscript object inline static colvarscript *colvarscript_obj() { return cvm::main()->proxy->script; } /// Get a pointer to the colvar object pointed to by pobj inline static colvar *colvar_obj(void *pobj) { return reinterpret_cast(pobj); } /// Get a pointer to the colvarbias object pointed to by pobj inline static colvarbias *colvarbias_obj(void *pobj) { return reinterpret_cast(pobj); } template unsigned char *colvarscript::get_cmd_arg(int iarg, int objc, unsigned char *const objv[]) { int const shift = cmd_arg_shift(); return (shift+iarg < objc) ? objv[shift+iarg] : NULL; } inline unsigned char *colvarscript::get_module_cmd_arg(int iarg, int objc, unsigned char *const objv[]) { return get_cmd_arg(iarg, objc, objv); } inline unsigned char *colvarscript::get_colvar_cmd_arg(int iarg, int objc, unsigned char *const objv[]) { return get_cmd_arg(iarg, objc, objv); } inline unsigned char *colvarscript::get_bias_cmd_arg(int iarg, int objc, unsigned char *const objv[]) { return get_cmd_arg(iarg, objc, objv); } template int colvarscript::check_cmd_nargs(char const *cmd, int objc, int n_args_min, int n_args_max) { int const shift = cmd_arg_shift(); if (objc < shift+n_args_min) { add_error_msg("Insufficient number of arguments ("+cvm::to_str(objc)+ ") for script function \""+std::string(cmd)+ "\":\n"+get_command_full_help(cmd)); return COLVARSCRIPT_ERROR; } if (objc > shift+n_args_max) { add_error_msg("Too many arguments ("+cvm::to_str(objc)+ ") for script function \""+std::string(cmd)+ "\":\n"+get_command_full_help(cmd)); return COLVARSCRIPT_ERROR; } return COLVARSCRIPT_OK; } inline int colvarscript::check_module_cmd_nargs(char const *cmd, int objc, int n_args_min, int n_args_max) { return check_cmd_nargs(cmd, objc, n_args_min, n_args_max); } inline int colvarscript::check_colvar_cmd_nargs(char const *cmd, int objc, int n_args_min, int n_args_max) { return check_cmd_nargs(cmd, objc, n_args_min, n_args_max); } inline int colvarscript::check_bias_cmd_nargs(char const *cmd, int objc, int n_args_min, int n_args_max) { return check_cmd_nargs(cmd, objc, n_args_min, n_args_max); } template int colvarscript::cmd_arg_shift() { int shift = 0; if (T == use_module) { // "cv" and "COMMAND" are 1st and 2nd argument, and shift is equal to 2 shift = 2; } else if (T == use_colvar) { // Same as above with additional arguments "colvar" and "NAME" shift = 4; } else if (T == use_bias) { shift = 4; } return shift; } extern "C" { /// Generic wrapper for string-based scripting int run_colvarscript_command(int objc, unsigned char *const objv[]); /// Get the string result of a script call const char * get_colvarscript_result(); } #endif // #ifndef COLVARSCRIPT_H