* 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
This commit is contained in:
False.Genesis 2007-03-20 21:37:38 +00:00
parent 7de82dd3a9
commit c8015e9929
2 changed files with 114 additions and 6 deletions

View File

@ -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

View File

@ -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: "<<line<<"\n";
if(!exec)
@ -355,8 +363,19 @@ DefReturnResult DefScriptPackage::RunScript(std::string name, CmdSet *pSet)
Def_Block b=Blocks.back();
if(b.type==BLOCK_IF && b.istrue)
{
for(i=b.startline;sc->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);