mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
Merge remote-tracking branch 'origin/GP-5262_AutoKilledByCall'
This commit is contained in:
commit
2589aae3a4
5 changed files with 49 additions and 38 deletions
|
@ -586,6 +586,7 @@ ParamListStandard::ParamListStandard(const ParamListStandard &op2)
|
||||||
spacebase = op2.spacebase;
|
spacebase = op2.spacebase;
|
||||||
maxdelay = op2.maxdelay;
|
maxdelay = op2.maxdelay;
|
||||||
thisbeforeret = op2.thisbeforeret;
|
thisbeforeret = op2.thisbeforeret;
|
||||||
|
autoKilledByCall = op2.autoKilledByCall;
|
||||||
resourceStart = op2.resourceStart;
|
resourceStart = op2.resourceStart;
|
||||||
for(list<ModelRule>::const_iterator iter=op2.modelRules.begin();iter!=op2.modelRules.end();++iter) {
|
for(list<ModelRule>::const_iterator iter=op2.modelRules.begin();iter!=op2.modelRules.end();++iter) {
|
||||||
modelRules.emplace_back(*iter,&op2);
|
modelRules.emplace_back(*iter,&op2);
|
||||||
|
@ -1198,11 +1199,10 @@ void ParamListStandard::populateResolver(void)
|
||||||
/// \param effectlist holds any passed back effect records
|
/// \param effectlist holds any passed back effect records
|
||||||
/// \param groupid is the group to which the new ParamEntry is assigned
|
/// \param groupid is the group to which the new ParamEntry is assigned
|
||||||
/// \param normalstack is \b true if the parameters should be allocated from the front of the range
|
/// \param normalstack is \b true if the parameters should be allocated from the front of the range
|
||||||
/// \param autokill is \b true if parameters are automatically added to the killedbycall list
|
|
||||||
/// \param splitFloat is \b true if floating-point parameters are in their own resource section
|
/// \param splitFloat is \b true if floating-point parameters are in their own resource section
|
||||||
/// \param grouped is \b true if the new ParamEntry is grouped with other entries
|
/// \param grouped is \b true if the new ParamEntry is grouped with other entries
|
||||||
void ParamListStandard::parsePentry(Decoder &decoder,vector<EffectRecord> &effectlist,
|
void ParamListStandard::parsePentry(Decoder &decoder,vector<EffectRecord> &effectlist,
|
||||||
int4 groupid,bool normalstack,bool autokill,bool splitFloat,bool grouped)
|
int4 groupid,bool normalstack,bool splitFloat,bool grouped)
|
||||||
{
|
{
|
||||||
type_class lastClass = TYPECLASS_CLASS4;
|
type_class lastClass = TYPECLASS_CLASS4;
|
||||||
if (!entry.empty()) {
|
if (!entry.empty()) {
|
||||||
|
@ -1221,7 +1221,7 @@ void ParamListStandard::parsePentry(Decoder &decoder,vector<EffectRecord> &effec
|
||||||
AddrSpace *spc = entry.back().getSpace();
|
AddrSpace *spc = entry.back().getSpace();
|
||||||
if (spc->getType() == IPTR_SPACEBASE)
|
if (spc->getType() == IPTR_SPACEBASE)
|
||||||
spacebase = spc;
|
spacebase = spc;
|
||||||
else if (autokill) // If a register parameter AND we automatically generate killedbycall
|
else if (autoKilledByCall) // If a register parameter AND we automatically generate killedbycall
|
||||||
effectlist.push_back(EffectRecord(entry.back(),EffectRecord::killedbycall));
|
effectlist.push_back(EffectRecord(entry.back(),EffectRecord::killedbycall));
|
||||||
|
|
||||||
int4 maxgroup = entry.back().getAllGroups().back() + 1;
|
int4 maxgroup = entry.back().getAllGroups().back() + 1;
|
||||||
|
@ -1236,17 +1236,16 @@ void ParamListStandard::parsePentry(Decoder &decoder,vector<EffectRecord> &effec
|
||||||
/// \param effectlist holds any passed back effect records
|
/// \param effectlist holds any passed back effect records
|
||||||
/// \param groupid is the group to which all ParamEntry elements are assigned
|
/// \param groupid is the group to which all ParamEntry elements are assigned
|
||||||
/// \param normalstack is \b true if the parameters should be allocated from the front of the range
|
/// \param normalstack is \b true if the parameters should be allocated from the front of the range
|
||||||
/// \param autokill is \b true if parameters are automatically added to the killedbycall list
|
|
||||||
/// \param splitFloat is \b true if floating-point parameters are in their own resource section
|
/// \param splitFloat is \b true if floating-point parameters are in their own resource section
|
||||||
void ParamListStandard::parseGroup(Decoder &decoder,vector<EffectRecord> &effectlist,
|
void ParamListStandard::parseGroup(Decoder &decoder,vector<EffectRecord> &effectlist,
|
||||||
int4 groupid,bool normalstack,bool autokill,bool splitFloat)
|
int4 groupid,bool normalstack,bool splitFloat)
|
||||||
{
|
{
|
||||||
int4 basegroup = numgroup;
|
int4 basegroup = numgroup;
|
||||||
ParamEntry *previous1 = (ParamEntry *)0;
|
ParamEntry *previous1 = (ParamEntry *)0;
|
||||||
ParamEntry *previous2 = (ParamEntry *)0;
|
ParamEntry *previous2 = (ParamEntry *)0;
|
||||||
uint4 elemId = decoder.openElement(ELEM_GROUP);
|
uint4 elemId = decoder.openElement(ELEM_GROUP);
|
||||||
while(decoder.peekElement() != 0) {
|
while(decoder.peekElement() != 0) {
|
||||||
parsePentry(decoder, effectlist, basegroup, normalstack, autokill, splitFloat, true);
|
parsePentry(decoder, effectlist, basegroup, normalstack, splitFloat, true);
|
||||||
ParamEntry &pentry( entry.back() );
|
ParamEntry &pentry( entry.back() );
|
||||||
if (pentry.getSpace()->getType() == IPTR_JOIN)
|
if (pentry.getSpace()->getType() == IPTR_JOIN)
|
||||||
throw LowlevelError("<pentry> in the join space not allowed in <group> tag");
|
throw LowlevelError("<pentry> in the join space not allowed in <group> tag");
|
||||||
|
@ -1434,8 +1433,8 @@ void ParamListStandard::decode(Decoder &decoder,vector<EffectRecord> &effectlist
|
||||||
spacebase = (AddrSpace *)0;
|
spacebase = (AddrSpace *)0;
|
||||||
int4 pointermax = 0;
|
int4 pointermax = 0;
|
||||||
thisbeforeret = false;
|
thisbeforeret = false;
|
||||||
|
autoKilledByCall = false;
|
||||||
bool splitFloat = true; // True if we should split FLOAT entries into their own resource section
|
bool splitFloat = true; // True if we should split FLOAT entries into their own resource section
|
||||||
bool autokilledbycall = false;
|
|
||||||
uint4 elemId = decoder.openElement();
|
uint4 elemId = decoder.openElement();
|
||||||
for(;;) {
|
for(;;) {
|
||||||
uint4 attribId = decoder.getNextAttributeId();
|
uint4 attribId = decoder.getNextAttributeId();
|
||||||
|
@ -1447,7 +1446,7 @@ void ParamListStandard::decode(Decoder &decoder,vector<EffectRecord> &effectlist
|
||||||
thisbeforeret = decoder.readBool();
|
thisbeforeret = decoder.readBool();
|
||||||
}
|
}
|
||||||
else if (attribId == ATTRIB_KILLEDBYCALL) {
|
else if (attribId == ATTRIB_KILLEDBYCALL) {
|
||||||
autokilledbycall = decoder.readBool();
|
autoKilledByCall = decoder.readBool();
|
||||||
}
|
}
|
||||||
else if (attribId == ATTRIB_SEPARATEFLOAT) {
|
else if (attribId == ATTRIB_SEPARATEFLOAT) {
|
||||||
splitFloat = decoder.readBool();
|
splitFloat = decoder.readBool();
|
||||||
|
@ -1457,10 +1456,10 @@ void ParamListStandard::decode(Decoder &decoder,vector<EffectRecord> &effectlist
|
||||||
uint4 subId = decoder.peekElement();
|
uint4 subId = decoder.peekElement();
|
||||||
if (subId == 0) break;
|
if (subId == 0) break;
|
||||||
if (subId == ELEM_PENTRY) {
|
if (subId == ELEM_PENTRY) {
|
||||||
parsePentry(decoder, effectlist, numgroup, normalstack, autokilledbycall, splitFloat, false);
|
parsePentry(decoder, effectlist, numgroup, normalstack, splitFloat, false);
|
||||||
}
|
}
|
||||||
else if (subId == ELEM_GROUP) {
|
else if (subId == ELEM_GROUP) {
|
||||||
parseGroup(decoder, effectlist, numgroup, normalstack, autokilledbycall, splitFloat);
|
parseGroup(decoder, effectlist, numgroup, normalstack, splitFloat);
|
||||||
}
|
}
|
||||||
else if (subId == ELEM_RULE) {
|
else if (subId == ELEM_RULE) {
|
||||||
break;
|
break;
|
||||||
|
@ -1599,6 +1598,8 @@ void ParamListStandardOut::initialize(void)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (useFillinFallback)
|
||||||
|
autoKilledByCall = true; // Legacy behavior if there are no rules
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Find the return value storage using the older \e fallback method
|
/// \brief Find the return value storage using the older \e fallback method
|
||||||
|
@ -3778,8 +3779,8 @@ void FuncProto::setModel(ProtoModel *m)
|
||||||
flags |= has_thisptr;
|
flags |= has_thisptr;
|
||||||
if (m->isConstructor())
|
if (m->isConstructor())
|
||||||
flags |= is_constructor;
|
flags |= is_constructor;
|
||||||
if (m->isAutoKillByCall())
|
if (m->isAutoKilledByCall())
|
||||||
flags |= auto_killbycall;
|
flags |= auto_killedbycall;
|
||||||
model = m;
|
model = m;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -4557,13 +4558,13 @@ void FuncProto::printRaw(const string &funcname,ostream &s) const
|
||||||
/// This assumes the storage location has already been determined to be contained
|
/// This assumes the storage location has already been determined to be contained
|
||||||
/// in standard return value location.
|
/// in standard return value location.
|
||||||
/// \return \b true if the location should be considered killed by call
|
/// \return \b true if the location should be considered killed by call
|
||||||
bool FuncProto::isAutoKillByCall(void) const
|
bool FuncProto::isAutoKilledByCall(void) const
|
||||||
|
|
||||||
{
|
{
|
||||||
if ((flags & auto_killbycall)!=0)
|
if ((flags & auto_killedbycall)!=0)
|
||||||
return true; // The ProtoModel always does killbycall
|
return true; // The ProtoModel always does killedbycall
|
||||||
if (isOutputLocked())
|
if (isOutputLocked())
|
||||||
return true; // A locked output location is killbycall by definition
|
return true; // A locked output location is killedbycall by definition
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -560,8 +560,8 @@ public:
|
||||||
|
|
||||||
/// \brief Return \b true if ParamEntry locations should automatically be considered killed by call
|
/// \brief Return \b true if ParamEntry locations should automatically be considered killed by call
|
||||||
///
|
///
|
||||||
/// \return \b true if automatically assume killbycall
|
/// \return \b true if automatically assume \e killedbycall
|
||||||
virtual bool isAutoKillByCall(void) const=0;
|
virtual bool isAutoKilledByCall(void) const=0;
|
||||||
|
|
||||||
/// \brief Restore the model from an \<input> or \<output> element in the stream
|
/// \brief Restore the model from an \<input> or \<output> element in the stream
|
||||||
///
|
///
|
||||||
|
@ -587,6 +587,7 @@ protected:
|
||||||
int4 numgroup; ///< Number of \e groups in this parameter convention
|
int4 numgroup; ///< Number of \e groups in this parameter convention
|
||||||
int4 maxdelay; ///< Maximum heritage delay across all parameters
|
int4 maxdelay; ///< Maximum heritage delay across all parameters
|
||||||
bool thisbeforeret; ///< Does a \b this parameter come before a hidden return parameter
|
bool thisbeforeret; ///< Does a \b this parameter come before a hidden return parameter
|
||||||
|
bool autoKilledByCall; ///< Are storage locations in \b this list automatically \e killed \e by \e call
|
||||||
vector<int4> resourceStart; ///< The starting group for each resource section
|
vector<int4> resourceStart; ///< The starting group for each resource section
|
||||||
list<ParamEntry> entry; ///< The ordered list of parameter entries
|
list<ParamEntry> entry; ///< The ordered list of parameter entries
|
||||||
vector<ParamEntryResolver *> resolverMap; ///< Map from space id to resolver
|
vector<ParamEntryResolver *> resolverMap; ///< Map from space id to resolver
|
||||||
|
@ -605,9 +606,9 @@ protected:
|
||||||
void addResolverRange(AddrSpace *spc,uintb first,uintb last,ParamEntry *paramEntry,int4 position);
|
void addResolverRange(AddrSpace *spc,uintb first,uintb last,ParamEntry *paramEntry,int4 position);
|
||||||
void populateResolver(void); ///< Build the ParamEntry resolver maps
|
void populateResolver(void); ///< Build the ParamEntry resolver maps
|
||||||
void parsePentry(Decoder &decoder,vector<EffectRecord> &effectlist,
|
void parsePentry(Decoder &decoder,vector<EffectRecord> &effectlist,
|
||||||
int4 groupid,bool normalstack,bool autokill,bool splitFloat,bool grouped);
|
int4 groupid,bool normalstack,bool splitFloat,bool grouped);
|
||||||
void parseGroup(Decoder &decoder,vector<EffectRecord> &effectlist,
|
void parseGroup(Decoder &decoder,vector<EffectRecord> &effectlist,
|
||||||
int4 groupid,bool normalstack,bool autokill,bool splitFloat);
|
int4 groupid,bool normalstack,bool splitFloat);
|
||||||
public:
|
public:
|
||||||
ParamListStandard(void) {} ///< Construct for use with decode()
|
ParamListStandard(void) {} ///< Construct for use with decode()
|
||||||
ParamListStandard(const ParamListStandard &op2); ///< Copy constructor
|
ParamListStandard(const ParamListStandard &op2); ///< Copy constructor
|
||||||
|
@ -634,7 +635,7 @@ public:
|
||||||
virtual bool isThisBeforeRetPointer(void) const { return thisbeforeret; }
|
virtual bool isThisBeforeRetPointer(void) const { return thisbeforeret; }
|
||||||
virtual void getRangeList(AddrSpace *spc,RangeList &res) const;
|
virtual void getRangeList(AddrSpace *spc,RangeList &res) const;
|
||||||
virtual int4 getMaxDelay(void) const { return maxdelay; }
|
virtual int4 getMaxDelay(void) const { return maxdelay; }
|
||||||
virtual bool isAutoKillByCall(void) const { return false; }
|
virtual bool isAutoKilledByCall(void) const { return autoKilledByCall; }
|
||||||
virtual void decode(Decoder &decoder,vector<EffectRecord> &effectlist,bool normalstack);
|
virtual void decode(Decoder &decoder,vector<EffectRecord> &effectlist,bool normalstack);
|
||||||
virtual ParamList *clone(void) const;
|
virtual ParamList *clone(void) const;
|
||||||
};
|
};
|
||||||
|
@ -659,7 +660,6 @@ public:
|
||||||
virtual void assignMap(const PrototypePieces &proto,TypeFactory &typefactory,vector<ParameterPieces> &res) const;
|
virtual void assignMap(const PrototypePieces &proto,TypeFactory &typefactory,vector<ParameterPieces> &res) const;
|
||||||
virtual void fillinMap(ParamActive *active) const;
|
virtual void fillinMap(ParamActive *active) const;
|
||||||
virtual bool possibleParam(const Address &loc,int4 size) const;
|
virtual bool possibleParam(const Address &loc,int4 size) const;
|
||||||
virtual bool isAutoKillByCall(void) const { return useFillinFallback; }
|
|
||||||
virtual void decode(Decoder &decoder,vector<EffectRecord> &effectlist,bool normalstack);
|
virtual void decode(Decoder &decoder,vector<EffectRecord> &effectlist,bool normalstack);
|
||||||
virtual ParamList *clone(void) const;
|
virtual ParamList *clone(void) const;
|
||||||
};
|
};
|
||||||
|
@ -995,7 +995,7 @@ public:
|
||||||
/// \brief Does \b this model automatically consider potential output locations as killed by call
|
/// \brief Does \b this model automatically consider potential output locations as killed by call
|
||||||
///
|
///
|
||||||
/// \return \b true if output locations should be considered killed by call
|
/// \return \b true if output locations should be considered killed by call
|
||||||
bool isAutoKillByCall(void) const { return output->isAutoKillByCall(); }
|
bool isAutoKilledByCall(void) const { return output->isAutoKilledByCall(); }
|
||||||
|
|
||||||
/// \brief Is \b this a merged prototype model
|
/// \brief Is \b this a merged prototype model
|
||||||
///
|
///
|
||||||
|
@ -1350,7 +1350,7 @@ class FuncProto {
|
||||||
is_destructor = 0x400, ///< Function is an (object-oriented) destructor
|
is_destructor = 0x400, ///< Function is an (object-oriented) destructor
|
||||||
has_thisptr= 0x800, ///< Function is a method with a 'this' pointer as an argument
|
has_thisptr= 0x800, ///< Function is a method with a 'this' pointer as an argument
|
||||||
is_override = 0x1000, ///< Set if \b this prototype is created to override a single call site
|
is_override = 0x1000, ///< Set if \b this prototype is created to override a single call site
|
||||||
auto_killbycall = 0x2000 ///< Potential output storage should always be considered \e killed \e by \e call
|
auto_killedbycall = 0x2000 ///< Potential output storage should always be considered \e killed \e by \e call
|
||||||
};
|
};
|
||||||
ProtoModel *model; ///< Model of for \b this prototype
|
ProtoModel *model; ///< Model of for \b this prototype
|
||||||
ProtoStore *store; ///< Storage interface for parameters
|
ProtoStore *store; ///< Storage interface for parameters
|
||||||
|
@ -1612,7 +1612,7 @@ public:
|
||||||
/// \return the active set of flags for \b this prototype
|
/// \return the active set of flags for \b this prototype
|
||||||
uint4 getComparableFlags(void) const { return (flags & (dotdotdot | is_constructor | is_destructor | has_thisptr )); }
|
uint4 getComparableFlags(void) const { return (flags & (dotdotdot | is_constructor | is_destructor | has_thisptr )); }
|
||||||
|
|
||||||
bool isAutoKillByCall(void) const; ///< Is a potential output automatically considered \e killed \e by \e call
|
bool isAutoKilledByCall(void) const; ///< Is a potential output automatically considered \e killed \e by \e call
|
||||||
|
|
||||||
void encode(Encoder &encoder) const;
|
void encode(Encoder &encoder) const;
|
||||||
void decode(Decoder &decoder,Architecture *glb);
|
void decode(Decoder &decoder,Architecture *glb);
|
||||||
|
|
|
@ -1470,7 +1470,7 @@ void Heritage::guardCalls(uint4 fl,const Address &addr,int4 size,vector<Varnode
|
||||||
ParamActive *active = fc->getActiveOutput();
|
ParamActive *active = fc->getActiveOutput();
|
||||||
int4 outputCharacter = fc->characterizeAsOutput(transAddr, size);
|
int4 outputCharacter = fc->characterizeAsOutput(transAddr, size);
|
||||||
if (outputCharacter != ParamEntry::no_containment) {
|
if (outputCharacter != ParamEntry::no_containment) {
|
||||||
if (effecttype != EffectRecord::killedbycall && fc->isAutoKillByCall())
|
if (effecttype != EffectRecord::killedbycall && fc->isAutoKilledByCall())
|
||||||
effecttype = EffectRecord::killedbycall;
|
effecttype = EffectRecord::killedbycall;
|
||||||
if (outputCharacter == ParamEntry::contained_by) {
|
if (outputCharacter == ParamEntry::contained_by) {
|
||||||
if (tryOutputOverlapGuard(fc, addr, transAddr, size, write))
|
if (tryOutputOverlapGuard(fc, addr, transAddr, size, write))
|
||||||
|
|
|
@ -205,8 +205,8 @@ class VarargsFilter : public QualifierFilter {
|
||||||
int4 firstPos; ///< Start of range to match (offset relative to first variable arg)
|
int4 firstPos; ///< Start of range to match (offset relative to first variable arg)
|
||||||
int4 lastPos; ///< End of range to match
|
int4 lastPos; ///< End of range to match
|
||||||
public:
|
public:
|
||||||
VarargsFilter(void) { firstPos = 0x80000000; lastPos = 0x7fffffff; }
|
VarargsFilter(void) { firstPos = 0x80000000; lastPos = 0x7fffffff; } ///< Constructor for use with decode
|
||||||
VarargsFilter(int4 first,int4 last) { firstPos = first; lastPos = last; }
|
VarargsFilter(int4 first,int4 last) { firstPos = first; lastPos = last; } ///< Constructor
|
||||||
virtual QualifierFilter *clone(void) const { return new VarargsFilter(firstPos,lastPos); }
|
virtual QualifierFilter *clone(void) const { return new VarargsFilter(firstPos,lastPos); }
|
||||||
virtual bool filter(const PrototypePieces &proto,int4 pos) const;
|
virtual bool filter(const PrototypePieces &proto,int4 pos) const;
|
||||||
virtual void decode(Decoder &decoder);
|
virtual void decode(Decoder &decoder);
|
||||||
|
|
|
@ -42,6 +42,7 @@ public class ParamListStandard implements ParamList {
|
||||||
protected int numgroup; // Number of "groups" in this parameter convention
|
protected int numgroup; // Number of "groups" in this parameter convention
|
||||||
// protected int maxdelay;
|
// protected int maxdelay;
|
||||||
protected boolean thisbeforeret; // Do hidden return pointers usurp the storage of the this pointer
|
protected boolean thisbeforeret; // Do hidden return pointers usurp the storage of the this pointer
|
||||||
|
protected boolean autoKilledByCall; // Is storage in this list automatically "killed by call"
|
||||||
protected boolean splitMetatype; // Are metatyped entries in separate resource sections
|
protected boolean splitMetatype; // Are metatyped entries in separate resource sections
|
||||||
// protected int[] resourceStart; // The starting group for each resource section
|
// protected int[] resourceStart; // The starting group for each resource section
|
||||||
protected ParamEntry[] entry;
|
protected ParamEntry[] entry;
|
||||||
|
@ -235,6 +236,7 @@ public class ParamListStandard implements ParamList {
|
||||||
if (thisbeforeret) {
|
if (thisbeforeret) {
|
||||||
encoder.writeBool(ATTRIB_THISBEFORERETPOINTER, true);
|
encoder.writeBool(ATTRIB_THISBEFORERETPOINTER, true);
|
||||||
}
|
}
|
||||||
|
encoder.writeBool(ATTRIB_KILLEDBYCALL, autoKilledByCall);
|
||||||
if (isInput && !splitMetatype) {
|
if (isInput && !splitMetatype) {
|
||||||
encoder.writeBool(ATTRIB_SEPARATEFLOAT, false);
|
encoder.writeBool(ATTRIB_SEPARATEFLOAT, false);
|
||||||
}
|
}
|
||||||
|
@ -298,7 +300,7 @@ public class ParamListStandard implements ParamList {
|
||||||
|
|
||||||
private void parseGroup(XmlPullParser parser, CompilerSpec cspec, ArrayList<ParamEntry> pe,
|
private void parseGroup(XmlPullParser parser, CompilerSpec cspec, ArrayList<ParamEntry> pe,
|
||||||
int groupid, boolean splitFloat) throws XmlParseException {
|
int groupid, boolean splitFloat) throws XmlParseException {
|
||||||
XmlElement el = parser.start("group");
|
XmlElement el = parser.start(ELEM_GROUP.name());
|
||||||
int basegroup = numgroup;
|
int basegroup = numgroup;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
while (parser.peek().isStart()) {
|
while (parser.peek().isStart()) {
|
||||||
|
@ -327,17 +329,22 @@ public class ParamListStandard implements ParamList {
|
||||||
spacebase = null;
|
spacebase = null;
|
||||||
int pointermax = 0;
|
int pointermax = 0;
|
||||||
thisbeforeret = false;
|
thisbeforeret = false;
|
||||||
|
autoKilledByCall = false;
|
||||||
splitMetatype = true;
|
splitMetatype = true;
|
||||||
XmlElement mainel = parser.start();
|
XmlElement mainel = parser.start();
|
||||||
String attribute = mainel.getAttribute("pointermax");
|
String attribute = mainel.getAttribute(ATTRIB_POINTERMAX.name());
|
||||||
if (attribute != null) {
|
if (attribute != null) {
|
||||||
pointermax = SpecXmlUtils.decodeInt(attribute);
|
pointermax = SpecXmlUtils.decodeInt(attribute);
|
||||||
}
|
}
|
||||||
attribute = mainel.getAttribute("thisbeforeretpointer");
|
attribute = mainel.getAttribute(ATTRIB_THISBEFORERETPOINTER.name());
|
||||||
if (attribute != null) {
|
if (attribute != null) {
|
||||||
thisbeforeret = SpecXmlUtils.decodeBoolean(attribute);
|
thisbeforeret = SpecXmlUtils.decodeBoolean(attribute);
|
||||||
}
|
}
|
||||||
attribute = mainel.getAttribute("separatefloat");
|
attribute = mainel.getAttribute(ATTRIB_KILLEDBYCALL.name());
|
||||||
|
if (attribute != null) {
|
||||||
|
autoKilledByCall = SpecXmlUtils.decodeBoolean(attribute);
|
||||||
|
}
|
||||||
|
attribute = mainel.getAttribute(ATTRIB_SEPARATEFLOAT.name());
|
||||||
if (attribute != null) {
|
if (attribute != null) {
|
||||||
splitMetatype = SpecXmlUtils.decodeBoolean(attribute);
|
splitMetatype = SpecXmlUtils.decodeBoolean(attribute);
|
||||||
}
|
}
|
||||||
|
@ -347,13 +354,13 @@ public class ParamListStandard implements ParamList {
|
||||||
if (!el.isStart()) {
|
if (!el.isStart()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (el.getName().equals("pentry")) {
|
if (el.getName().equals(ELEM_PENTRY.name())) {
|
||||||
parsePentry(parser, cspec, pe, numgroup, splitMetatype, false);
|
parsePentry(parser, cspec, pe, numgroup, splitMetatype, false);
|
||||||
}
|
}
|
||||||
else if (el.getName().equals("group")) {
|
else if (el.getName().equals(ELEM_GROUP.name())) {
|
||||||
parseGroup(parser, cspec, pe, numgroup, splitMetatype);
|
parseGroup(parser, cspec, pe, numgroup, splitMetatype);
|
||||||
}
|
}
|
||||||
else if (el.getName().equals("rule")) {
|
else if (el.getName().equals(ELEM_RULE.name())) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -366,7 +373,7 @@ public class ParamListStandard implements ParamList {
|
||||||
if (!subId.isStart()) {
|
if (!subId.isStart()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (subId.getName().equals("rule")) {
|
if (subId.getName().equals(ELEM_RULE.name())) {
|
||||||
ModelRule rule = new ModelRule();
|
ModelRule rule = new ModelRule();
|
||||||
rule.restoreXml(parser, this);
|
rule.restoreXml(parser, this);
|
||||||
rules.add(rule);
|
rules.add(rule);
|
||||||
|
@ -482,6 +489,9 @@ public class ParamListStandard implements ParamList {
|
||||||
if (thisbeforeret != op2.thisbeforeret) {
|
if (thisbeforeret != op2.thisbeforeret) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (autoKilledByCall != op2.autoKilledByCall) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue