File indexing completed on 2024-04-14 14:32:18

0001 //
0002 // C++ Implementation: cCmdQueue
0003 //
0004 // Description: one command queue
0005 //
0006 /*
0007 Copyright 2005-2011 Tomas Mecir <kmuddy@kmuddy.com>
0008 
0009 This program is free software; you can redistribute it and/or
0010 modify it under the terms of the GNU General Public License as
0011 published by the Free Software Foundation; either version 2 of 
0012 the License, or (at your option) any later version.
0013 
0014 This program is distributed in the hope that it will be useful,
0015 but WITHOUT ANY WARRANTY; without even the implied warranty of
0016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0017 GNU General Public License for more details.
0018 
0019 You should have received a copy of the GNU General Public License
0020 along with this program.  If not, see <http://www.gnu.org/licenses/>.
0021 */
0022 
0023 #include "ccmdqueue.h"
0024 
0025 #include "cactionmanager.h"
0026 #include "ccmdparser.h"
0027 #include "ccmdprocessor.h"
0028 #include "cmacromanager.h"
0029 #include "cpattern.h"
0030 #include "cvalue.h"
0031 
0032 
0033 cCmdQueue::cCmdQueue (int _sess) : sess(_sess)
0034 {
0035   parser = nullptr;
0036   preproc = nullptr;
0037 }
0038 
0039 cCmdQueue::~cCmdQueue()
0040 {
0041   deleteAllCommands ();
0042   deleteAllVariables ();
0043   std::map<QString, cExecStack *>::iterator it;
0044   for (it = stacks.begin(); it != stacks.end(); ++it)
0045     delete it->second;
0046   stacks.clear ();
0047   delete preproc;
0048 }
0049 
0050 void cCmdQueue::deleteAllCommands ()
0051 {
0052   if (!commands.empty()) {
0053     // delete the queue is needed
0054     std::list<cCmdQueueEntry *>::iterator it;
0055     for (it = commands.begin(); it != commands.end(); ++it)
0056       delete *it;
0057   }
0058   commands.clear ();
0059 }
0060 
0061 void cCmdQueue::fillFromPattern (const cPattern *p)
0062 {
0063   setValue ("prefix", p->getVariable ("prefix"));
0064   setValue ("suffix", p->getVariable ("suffix"));
0065   setValue ("prefixtrim", p->getVariable ("prefixtrim"));
0066   setValue ("suffixtrim", p->getVariable ("suffixtrim"));
0067   setValue ("matched", p->getVariable ("matched"));
0068   if (p->matching() == cPattern::regexp)
0069     for (int i = 0; i < p->getBackRefList().count(); ++i)
0070       setValue (QString::number (i), p->getBackRefList()[i]);
0071 }
0072 
0073 bool cCmdQueue::finished ()
0074 {
0075   return commands.empty();
0076 }
0077 
0078 bool cCmdQueue::waiting ()
0079 {
0080   // TODO: make the real thing, not just this stub !!!
0081   return false;
0082 }
0083 
0084 QString cCmdQueue::getValue (const QString &name)
0085 {
0086   QString vn = name;
0087   if (vn[0] == '$')
0088     vn = vn.mid(1);
0089   if (variables.count (vn))
0090     return variables[vn]->asString();
0091   return QString();
0092 }
0093 
0094 bool cCmdQueue::varExists (const QString &name)
0095 {
0096   QString vn = name;
0097   if (vn[0] == '$')
0098     vn = vn.mid(1);
0099   return (variables.count (vn) != 0);
0100 }
0101 
0102 cValue *cCmdQueue::value (const QString &name)
0103 {
0104   QString vn = name;
0105   if (vn[0] == '$')
0106     vn = vn.mid(1);
0107   if (variables.count (vn))
0108     return variables[vn];
0109   return nullptr;
0110 }
0111 
0112 void cCmdQueue::setValue (const QString &name, const QString &value)
0113 {
0114   QString vn = name;
0115   if (vn[0] == '$')
0116     vn = vn.mid(1);
0117   delValue (vn);
0118   cValue *val = new cValue (value);
0119   variables[vn] = val;
0120 }
0121 
0122 void cCmdQueue::setValue (const QString &name, const cValue &value)
0123 {
0124   QString vn = name;
0125   if (vn[0] == '$')
0126     vn = vn.mid(1);
0127   delValue (vn);
0128   cValue *val = new cValue (value);
0129   variables[vn] = val;
0130 }
0131 
0132 void cCmdQueue::delValue (const QString &name)
0133 {
0134   QString vn = name;
0135   if (vn[0] == '$')
0136     vn = vn.mid(1);
0137   if (!variables.count (vn)) return;
0138   delete variables[vn];
0139   variables.erase (vn);
0140 }
0141 
0142 void cCmdQueue::deleteAllVariables ()
0143 {
0144   std::map<QString, cValue *>::iterator it;
0145   for (it = variables.begin(); it != variables.end(); ++it)
0146     delete it->second;
0147   variables.clear ();
0148 }
0149 
0150 cExecStack *cCmdQueue::execStack (const QString &name)
0151 {
0152   if (!stacks.count (name))
0153     stacks[name] = new cExecStack;
0154   return stacks[name];
0155 }
0156 
0157 void cCmdQueue::addCommand (const QString &command, bool parsing, bool expandAliases)
0158 {
0159   if (!parser)
0160     parser = dynamic_cast<cCmdParser *>(cActionManager::self()->object ("cmdparser", sess));
0161   if (!parser) return;
0162   
0163   if (parsing && (parser->parsing())) {
0164     // split the text into individual commands
0165     QStringList cmds = parser->parse (command, expandAliases);
0166     QStringList::iterator it;
0167     for (it = cmds.begin(); it != cmds.end(); ++it) {
0168       bool raw = parser->mustSendRaw (*it);
0169       QString mname, mparams;
0170       if ((!raw) && parser->isMacroCall (*it, mname, mparams)) {
0171         cCmdQueueEntry *entry = new cCmdQueueEntry;
0172         entry->isMacro = true;
0173         entry->canParse = true;
0174         entry->macroName = mname;
0175         entry->macroParams = mparams;
0176         commands.push_back (entry);
0177       } else {
0178         cCmdQueueEntry *entry = new cCmdQueueEntry;
0179         entry->isMacro = false;
0180         entry->canParse = !raw;
0181         entry->command = raw ? parser->fixRaw (*it) : (*it);
0182         commands.push_back (entry);
0183       }
0184     }
0185   }
0186   else {
0187     cCmdQueueEntry *entry = new cCmdQueueEntry;
0188     entry->isMacro = false;
0189     entry->canParse = false;
0190     entry->command = command;
0191     commands.push_back (entry);
0192   }
0193 }
0194 
0195 void cCmdQueue::executeNext ()
0196 {
0197   if (finished()) return;
0198 
0199   cCmdQueueEntry *qe = commands.front();
0200   commands.pop_front();
0201   
0202   // call preprocessor commands on the entry
0203   bool ok = preprocess (qe);
0204   
0205   if (!ok) {
0206     // preprocessor command said, don't execute. So we won't.
0207     delete qe;
0208     return;
0209   }
0210   
0211   cActionManager *am = cActionManager::self();
0212   cCmdProcessor *cmdproc = dynamic_cast<cCmdProcessor *>(am->object ("cmdprocessor", sess));
0213   if (qe->isMacro)
0214     cmdproc->processMacro (qe->macroName, qe->macroParams, this);
0215   else {
0216     // send command; if we cannot parse, it gets sent directly without further parsing
0217     if (qe->canParse)
0218       cmdproc->processCommand (qe->command, this);
0219     else
0220       am->invokeEvent ("send-command", sess, qe->command);
0221   }
0222 
0223   delete qe;
0224 }
0225 
0226 void cCmdQueue::addPreprocessMacro (cMacro *macro)
0227 {
0228   if (hasPreprocessMacro (macro)) return;
0229   if (!preproc) preproc = new std::list<cMacro *>;
0230   preproc->push_back (macro);
0231 }
0232 
0233 void cCmdQueue::removePreprocessMacro (cMacro *macro)
0234 {
0235   if (!preproc) return;
0236   if (!hasPreprocessMacro (macro)) return;
0237   
0238   std::list<cMacro *>::iterator it;
0239   for (it = preproc->begin(); it != preproc->end(); ++it)
0240     if (*it == macro) {
0241       preproc->erase (it);
0242       return;
0243     }
0244 }
0245 
0246 bool cCmdQueue::hasPreprocessMacro (cMacro *macro)
0247 {
0248   if (!preproc) return false;
0249   std::list<cMacro *>::iterator it;
0250   for (it = preproc->begin(); it != preproc->end(); ++it)
0251     if (*it == macro)
0252       return true;
0253   return false;
0254 }
0255 
0256 bool cCmdQueue::preprocess (cCmdQueueEntry *qe)
0257 {
0258   if (!preproc) return true;
0259   
0260   bool ret = true;
0261   std::list<cMacro *>::iterator it;
0262   for (it = preproc->begin(); it != preproc->end(); ++it)
0263     if (!(*it)->preprocess (this, qe))
0264       ret = false;
0265   // If any preprocess command fails, we report failure. All preprocess commands get executed.
0266   return ret;
0267 }
0268 
0269 
0270 cExecStack::cExecStack ()
0271 {
0272 }
0273 
0274 cExecStack::~cExecStack ()
0275 {
0276   clear ();
0277 }
0278 
0279 void cExecStack::push (const cExecStackItem &item)
0280 {
0281   stack.push_back (item);
0282 }
0283 
0284 cExecStackItem cExecStack::pop ()
0285 {
0286   cExecStackItem item = top();
0287   stack.pop_back ();
0288   return item;
0289 }
0290 
0291 cExecStackItem cExecStack::top ()
0292 {
0293   return stack.back();
0294 }
0295 
0296 bool cExecStack::empty ()
0297 {
0298   return stack.empty();
0299 }
0300 
0301 void cExecStack::clear ()
0302 {
0303   stack.clear ();
0304 }
0305 
0306 cExecStackItem::cExecStackItem ()
0307 {
0308 }
0309 
0310 cExecStackItem::~cExecStackItem ()
0311 {
0312   attribs.clear ();
0313 }
0314 
0315 int cExecStackItem::attrib (const QString &name)
0316 {
0317   if (attribs.count (name))
0318     return attribs[name];
0319   return 0;
0320 }
0321 
0322 void cExecStackItem::setAttrib (const QString &name, int val)
0323 {
0324   if ((val == 0) && (attribs.count (name)))
0325     attribs.erase (name);
0326   attribs[name] = val;
0327 }
0328