From: <wo...@us...> - 2003-05-17 19:06:53
|
Update of /cvsroot/once/oncecode/src/common In directory sc8-pr-cvs1:/tmp/cvs-serv15299/src/common Added Files: occmdset.cpp occmdset.h Log Message: new files. --- NEW FILE: occmdset.cpp --- /* * occmdset.cpp * Copyright (C) 2003 by W.C.A. Wijngaards * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ extern "C" { #include <ctype.h> } #include "cssysdef.h" #include "occmdset.h" //------------------ ocCommandSet --------------------------- ocCommandSet::ocCommandSet() { out = NULL; } ocCommandSet::~ocCommandSet() { for(int i=0; i<cmdlist.Length(); i++) { delete cmdlist[i]; } delete out; } iocCommand* ocCommandSet::FindCommand(const char* name) { for(int i=0; i<cmdlist.Length(); i++) if(strcmp(cmdlist[i]->GetCommandName(), name) == 0) return cmdlist[i]; return NULL; } iocCommand* ocCommandSet::FindCommand(const char* name, int numarg) { for(int i=0; i<cmdlist.Length(); i++) if((strcmp(cmdlist[i]->GetCommandName(), name) == 0) && (cmdlist[i]->GetNumberArgs() == numarg || cmdlist[i]->GetNumberArgs() == -1)) return cmdlist[i]; return NULL; } void ocCommandSet::Perform(const char* cmdline) { if(!out) return; csArray<csString> args; if(!ParseCmd(cmdline, args)) { out->Printf("Error: Cannot parse cmdline '%s'.\n", cmdline); return; } if(args.Length() == 0) return; // nothing to do. csString name = args.Get(0); args.DeleteIndex(0); /// argument exists? iocCommand* cmd = FindCommand(name, args.Length()); if(!cmd) { if(!FindCommand(name)) out->Printf("Error: No such command '%s'.\nTry 'help' for help on " "commands.\n", name.GetData()); else out->Printf("Error: command '%s' expected %d, instead of %d" " arguments.\nTry 'help %s' for more info.\n", name.GetData(), FindCommand(name)->GetNumberArgs(), args.Length(), name.GetData()); return; } /// found command, perform it. cmd->Perform(args, out); } int ocCommandSet::FindArgSize(csString& cmdline) { char quote = '"'; if(cmdline.GetAt(0) == quote) { // using quotes cmdline.DeleteAt(0); for(size_t i=0; i<cmdline.Length(); i++) if(cmdline.GetAt(i) == quote) { cmdline.DeleteAt(i); return i; } return 0; } // unquoted arg for(size_t i=0; i<cmdline.Length(); i++) { if(isspace(cmdline.GetAt(i))) return i; } return cmdline.Length(); } bool ocCommandSet::ParseCmd(csString cmdline, csArray<csString>& args) { cmdline.RTrim(); // remove trailing whitespace // search for args while(!cmdline.IsEmpty()) { cmdline.LTrim(); // remove starting whitespace if(cmdline.IsEmpty()) return false; // internal error. int len = FindArgSize(cmdline); // len is the size of the arg. csString nextarg; nextarg.Append(cmdline, len); args.Push(nextarg); cmdline.DeleteAt(0, len); } return true; } //---------- ocCmdHelp ------------------------------------ ocCmdHelp::ocCmdHelp(ocCommandSet* s) { set = s; } ocCmdHelp::~ocCmdHelp() { set = NULL; } void ocCmdHelp::Perform(const csArray<csString>& /*args*/, iocCommandOutput *out) { CS_ASSERT(out); if(!set) { out->Printf("help::no command set specified.\n"); return; } const csArray<iocCommand*>& cmdlist = set->GetCommandList(); out->Printf("Available commands(#args):\n"); // find max width of command names. int linesize = 80; int linenow = 0; for(int i=0; i<cmdlist.Length(); i++) { int w = strlen(cmdlist[i]->GetCommandName())+4; if(linenow + w >= linesize){ out->Printf("\n"); linenow=0; } linenow += w; out->Printf(" %s", cmdlist[i]->GetCommandName()); if(cmdlist[i]->GetNumberArgs()==-1) out->Printf("(..)"); else if(cmdlist[i]->GetNumberArgs()>0) out->Printf("(%d)", cmdlist[i]->GetNumberArgs()); } out->Printf("\n"); out->Printf("Use help <command> for more info.\n"); } //---------- ocCmdHelpTopic ------------------------------- ocCmdHelpTopic::ocCmdHelpTopic(ocCommandSet* s) { set = s; } ocCmdHelpTopic::~ocCmdHelpTopic() { set = NULL; } void ocCmdHelpTopic::Perform(const csArray<csString>& args, iocCommandOutput *out) { CS_ASSERT(args.Length() == 1); CS_ASSERT(out); if(!set) { out->Printf("help_topic::no command set specified.\n"); return; } csString topic = args[0]; if(!set->FindCommand(topic)) { out->Printf("There is no help on '%s'.\nTry 'help' for a list.\n", topic.GetData()); return; } const csArray<iocCommand*>& cmdlist = set->GetCommandList(); for(int i=0; i<cmdlist.Length(); i++) { if(!topic.Compare(cmdlist[i]->GetCommandName())) continue; out->Printf("%s", cmdlist[i]->GetCommandName()); if(cmdlist[i]->GetNumberArgs() == -1) out->Printf(" <args...>"); else for(int k=0; k<cmdlist[i]->GetNumberArgs(); k++) out->Printf(" <%s>", cmdlist[i]->GetArgumentName(k)); out->Printf(" :\n"); out->Printf(" %s\n", cmdlist[i]->GetShortDesc()); } } --- NEW FILE: occmdset.h --- /* * occmdset.h * Copyright (C) 2003 by W.C.A. Wijngaards * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef OCCMDSET_H #define OCCMDSET_H #include "csutil/csstring.h" #include "csutil/array.h" class iocCommandOutput; /** * interface of a commandline command. */ class iocCommand { public: /// the name of the command virtual const char* GetCommandName() const = 0; /// number of arguments that command accepts, -1 means variable. /// 0 means: no arguments needed, etc. virtual int GetNumberArgs() const = 0; /// get a name for argument given a number (only if number args > 0). virtual const char* GetArgumentName(int n) const = 0; /// get a one line desc of the command. virtual const char* GetShortDesc() const = 0; /// perform the command, given an array of arguments. /// the number of arguments == GetNumberArgs(), unless that is -1. /// output can be sent to the output interface, which is set nonnull. virtual void Perform(const csArray<csString>& args, iocCommandOutput *out) = 0; }; /** * output of a command can be sent here. It will be directed to the user. */ class iocCommandOutput { public: /// print some output. virtual void Printf(const char* str, ...) CS_GNUC_PRINTF (2, 3) = 0; /// print output. virtual void PrintText(const char* str) = 0; }; /** * A set of commands. */ class ocCommandSet { private: /// the output interface for the command set iocCommandOutput* out; /// the commands in this set csArray<iocCommand*> cmdlist; /// parse a commandline into whitespace separated strings. /// false if parse error. bool ParseCmd(csString cmdline, csArray<csString>& args); /// find size of next arg (edits string so that arg starts at char 0). /// removes quotes, etc. int FindArgSize(csString& cmdline); public: /// ocCommandSet(); /// ~ocCommandSet(); /// set output interface (deleted by destructor). void SetOutput(iocCommandOutput *o) {out=o;} /// get output interface iocCommandOutput* GetOutput() const {return out;} /// add a command to the set. Note that the names must be unique. /// commands are deleted by destructor void AddCommand(iocCommand* cmd) {cmdlist.Push(cmd);} /// find a command by name, NULL if not found. iocCommand* FindCommand(const char* name); /// find a command which will accept a given number of arguments. iocCommand* FindCommand(const char* name, int numarg); /// given a commandline (whitespace will be stripped away), performs command. /// Note that double-quotes, " , can be used to contain whitespace in args. /// if commandline is in error, an error is printed to output. /// note that the output must be set nonnull beforehand. void Perform(const char* cmdline); /// get list of commands const csArray<iocCommand*>& GetCommandList() const {return cmdlist;} }; /** * default help command */ class ocCmdHelp : public iocCommand { private: /// the set of commands to help for ocCommandSet* set; public: /// ocCmdHelp(ocCommandSet* s); /// destructor virtual ~ocCmdHelp(); ///------------- iocCommand interface -------------- virtual const char* GetCommandName() const {return "help";} virtual int GetNumberArgs() const {return 0;} virtual const char* GetArgumentName(int n) const { const char* argdesc[] = {0}; CS_ASSERT(0<=n && n<GetNumberArgs()); return argdesc[n];} virtual const char* GetShortDesc() const {return "prints a list of available commands.";} virtual void Perform(const csArray<csString>& args, iocCommandOutput *out); }; /** * default help command (with one argument, the topic) */ class ocCmdHelpTopic : public iocCommand { private: /// the set of commands to help for ocCommandSet* set; public: /// ocCmdHelpTopic(ocCommandSet* s); /// destructor virtual ~ocCmdHelpTopic(); ///------------- iocCommand interface -------------- virtual const char* GetCommandName() const {return "help";} virtual int GetNumberArgs() const {return 1;} virtual const char* GetArgumentName(int n) const { const char* argdesc[] = {"command", 0}; CS_ASSERT(0<=n && n<GetNumberArgs()); return argdesc[n];} virtual const char* GetShortDesc() const {return "prints short help on a command.";} virtual void Perform(const csArray<csString>& args, iocCommandOutput *out); }; #endif // OCCMDSET_H |