From c8015e9929a6bf00b07a06f2adb3449f6f05a6b4 Mon Sep 17 00:00:00 2001 From: "False.Genesis" Date: Tue, 20 Mar 2007 21:37:38 +0000 Subject: [PATCH] * fixed if (error on multiple endifs) * implemented loop...endloop & exitloop * fixed crash on parsing ${} (var with no name) * added an example .def file to explain loop/if-statements --- bin/scripts/example_loop_if.def | 22 +++++++ src/Client/DefScript/DefScript.cpp | 98 ++++++++++++++++++++++++++++-- 2 files changed, 114 insertions(+), 6 deletions(-) create mode 100644 bin/scripts/example_loop_if.def diff --git a/bin/scripts/example_loop_if.def b/bin/scripts/example_loop_if.def new file mode 100644 index 0000000..59fc019 --- /dev/null +++ b/bin/scripts/example_loop_if.def @@ -0,0 +1,22 @@ +#permission=255 +// example script to explain how to use loops/ifs + +set,x 0 +loop + set,y 0 + add,x 1 + if ?{bigger,${x} 5} + exitloop + endif + loop + if ?{bigger,${y} 8} + exitloop + else + set,tmp ${x} + mul,tmp ${y} + out LOOP:${x}:${y} = ${tmp} + endif + add,y 1 + endloop +endloop +out end if/loop test script \ No newline at end of file diff --git a/src/Client/DefScript/DefScript.cpp b/src/Client/DefScript/DefScript.cpp index 5f7a4ff..9480d8c 100644 --- a/src/Client/DefScript/DefScript.cpp +++ b/src/Client/DefScript/DefScript.cpp @@ -202,6 +202,14 @@ bool DefScriptPackage::LoadScriptFromFile(std::string fn, std::string sn){ //... continue; // line was an option, not script content } + // help with loading lines where a space or tab have accidently been put after the cmd + if(memcmp(line.c_str(),"else ",5)==0 || memcmp(line.c_str(),"else\t",5)==0) line="else"; + if(memcmp(line.c_str(),"endif ",6)==0 || memcmp(line.c_str(),"endif\t",5)==0) line="endif"; + if(memcmp(line.c_str(),"loop ",5)==0 || memcmp(line.c_str(),"loop\t",5)==0) line="loop"; + if(memcmp(line.c_str(),"endloop ",8)==0 || memcmp(line.c_str(),"endloop\t",8)==0) line="endloop"; + if(line=="else" || line=="endif" || line=="loop" || line=="endloop") + line=stringToLower(line); + if(load_debug) std::cout<<"~LOAD: "<GetLine(i)!="endif";i++); // skip lines until "endif" - i--; // next line read will be "endif" + unsigned int other_ifs=0; + for(i=b.startline;;i++) + { + if(sc->GetLine(i).substr(0,3)=="if ") + other_ifs++; + if(sc->GetLine(i)=="endif") + { + if(!other_ifs) + break; + other_ifs--; + } + } + i--; // next line read will be "endif", decide then what to do } continue; } @@ -377,9 +396,35 @@ DefReturnResult DefScriptPackage::RunScript(std::string name, CmdSet *pSet) Blocks.pop_back(); continue; } - _DEFSC_DEBUG(printf("DefScript before: \"%s\"\n",line.c_str())); + else if(line=="loop") + { + Def_Block b; + b.startline=i; + b.type=BLOCK_LOOP; + b.istrue=true; + Blocks.push_back(b); + continue; + } + else if(line=="endloop") + { + if(!Blocks.size()) + { + printf("DEBUG: endloop without any block [%s:%u]\n",name.c_str(),i); + r.ok=false; + break; + } + if(Blocks.back().type!=BLOCK_LOOP) + { + printf("DEBUG: endloop: closed block is not a loop block! [%s:%u]\n",name.c_str(),i); + r.ok=false; + break; + } + i=Blocks.back().startline; // next line executed will be the line after "loop" + continue; + } + //_DEFSC_DEBUG(printf("DefScript before: \"%s\"\n",line.c_str())); DefXChgResult final=ReplaceVars(line,pSet,0,true); - _DEFSC_DEBUG(printf("DefScript parsed: \"%s\"\n",final.str.c_str())); + //_DEFSC_DEBUG(printf("DefScript parsed: \"%s\"\n",final.str.c_str())); SplitLine(mySet,final.str); if(mySet.cmd=="if") { @@ -390,12 +435,46 @@ DefReturnResult DefScriptPackage::RunScript(std::string name, CmdSet *pSet) Blocks.push_back(b); if(!b.istrue) { - for(i=b.startline;sc->GetLine(i)!="else" && sc->GetLine(i)!="endif";i++); + unsigned int other_ifs=0; + for(i=b.startline+1;;i++) + { + if(!memcmp(sc->GetLine(i).c_str(),"if ",3)) + other_ifs++; + if(sc->GetLine(i)=="else" || sc->GetLine(i)=="endif") + { + if(!other_ifs) + break; + if(sc->GetLine(i)=="endif") + other_ifs--; + } + } i--; // next line read will be either "else" or "endif", decide then what to do - } continue; // and read line after "else" } + else if(mySet.cmd=="exitloop") + { + // skip some ifs if they are present + while(Blocks.back().type!=BLOCK_LOOP) + Blocks.pop_back(); + Blocks.pop_back(); + unsigned int other_loops=0; + + while(true) + { + if(sc->GetLine(i)=="loop") + other_loops++; + if(sc->GetLine(i)=="endloop") + { + if(!other_loops) + break; + other_loops--; + } + i++; // go until next endloop + } + // next line read will be the line after "endloop" + continue; + } mySet.myname=name; mySet.caller=pSet?pSet->myname:""; @@ -632,6 +711,13 @@ DefXChgResult DefScriptPackage::ReplaceVars(std::string str, CmdSet *pSet, unsig } // end for if(!bracketsOpen && VarType!=DEFSCRIPT_NONE) { + // fix for empty var: ${} + if(str.empty()) + { + xchg.str=""; + xchg.changed=true; + return xchg; + } if(VarType==DEFSCRIPT_VAR) { std::string vname=_NormalizeVarName(str, (pSet==NULL) ? "" : pSet->myname);