File indexing completed on 2025-01-12 06:47:25
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