00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "config.h"
00020
00021
00022 #include "EDoc/CodeBlock.h"
00023 #include "EDoc/TryBlock.h"
00024 #include "EDoc/utils.h"
00025 #include "EDoc/Function.h"
00026 #include "EDoc/Type.h"
00027 #include "EDoc/FunctionType.h"
00028 #include "EDoc/PStack.h"
00029 #include "EDoc/StackRef.h"
00030 #include "EDoc/Dictionary.h"
00031
00032 #include "EDoc/PersistenceIFace.h"
00033 #include "IndexedDictionary.h"
00034 #include "EDoc/persistence_data.h"
00035
00036 namespace EDoc
00037 {
00038
00039 CodeBlock::CodeBlock(Dictionary* dict_in) :
00040 DictionarySpecific(dict_in)
00041 {
00042 }
00043
00044 CodeBlock::CodeBlock(const CodeBlock& right) :
00045 DictionarySpecific(&right.dict)
00046 {
00047 *this = right;
00048 }
00049
00050 CodeBlock::CodeBlock(const CodeBlock& right, Dictionary& dict_in) :
00051 DictionarySpecific(&dict_in)
00052 {
00053 *this = right;
00054 }
00055
00056 CodeBlock& CodeBlock::operator=(const CodeBlock& right)
00057 {
00058 if (this == &right)
00059 {
00060 return *this;
00061 }
00062
00063 Erase(function_calls);
00064 EDOC_FOREACH_CONST(FuncLocList, it, right.function_calls)
00065 {
00066 function_calls.push_back(FunctionLoc(*it, dict));
00067 }
00068
00069 Erase(originating_exceptions);
00070 EDOC_FOREACH_CONST(ExcepList, it, right.originating_exceptions)
00071 {
00072 originating_exceptions.push_back(Exception(*it, dict));
00073 }
00074
00075 Erase(function_pointer_calls);
00076 EDOC_FOREACH_CONST(FTypeLocList, it, right.function_pointer_calls)
00077 {
00078 function_pointer_calls.push_back(FunctionTypeLoc(*it, dict));
00079 }
00080
00081 Erase(try_blocks);
00082 EDOC_FOREACH_CONST(TryBlockList, it, right.try_blocks)
00083 {
00084 try_blocks.push_back(TryBlock(*it, dict));
00085 }
00086
00087 Erase(possible_function_calls);
00088
00089 return *this;
00090 }
00091
00092 void CodeBlock::Read(PersistenceIFace& file, IndexedDictionary& idict)
00093 {
00094 size_t size = 0;
00095
00096 size = file.ReadUInt32(KEY_FUNCTION_CALL_LS);
00097 Erase(function_calls);
00098 for (size_t i = 0; i < size; i++)
00099 {
00100 function_calls.push_back(FunctionLoc(&dict));
00101 function_calls.back().Read(file, idict);
00102 }
00103
00104 size = file.ReadUInt32(KEY_ORIGINATING_EXCEPTIONS_LS);
00105 Erase(originating_exceptions);
00106 for (size_t i = 0; i < size; i++)
00107 {
00108 originating_exceptions.push_back(Exception(&dict));
00109 originating_exceptions.back().Read(file, idict);
00110 }
00111
00112 size = file.ReadUInt32(KEY_FUNCP_CALLS_LS);
00113 Erase(function_pointer_calls);
00114 for (size_t i = 0; i < size; i++)
00115 {
00116 function_pointer_calls.push_back(FunctionTypeLoc(&dict));
00117 function_pointer_calls.back().Read(file, idict);
00118 }
00119
00120 size = file.ReadUInt32(KEY_TRY_BLOCKS_LS);
00121 Erase(try_blocks);
00122 for (size_t i = 0; i < size; i++)
00123 {
00124 try_blocks.push_back(TryBlock(&dict));
00125 try_blocks.back().Read(file, idict);
00126 }
00127 }
00128
00129 void CodeBlock::Write(PersistenceIFace& file) const
00130 {
00131 file.WriteUInt32(KEY_FUNCTION_CALL_LS, function_calls.size());
00132 EDOC_FOREACH_CONST(FuncLocList, it, function_calls)
00133 {
00134 it->Write(file);
00135 }
00136
00137
00138 size_t size = 0;
00139 EDOC_FOREACH_CONST(ExcepList, it, originating_exceptions)
00140 {
00141 if (!it->auto_throw_spec)
00142 {
00143 size++;
00144 }
00145 }
00146 file.WriteUInt32(KEY_ORIGINATING_EXCEPTIONS_LS, size);
00147 EDOC_FOREACH_CONST(ExcepList, it, originating_exceptions)
00148 {
00149 if (!it->auto_throw_spec)
00150 {
00151 it->Write(file);
00152 }
00153 }
00154
00155 file.WriteUInt32(KEY_FUNCP_CALLS_LS, function_pointer_calls.size());
00156 EDOC_FOREACH_CONST(FTypeLocList, it, function_pointer_calls)
00157 {
00158 it->Write(file);
00159 }
00160
00161 file.WriteUInt32(KEY_TRY_BLOCKS_LS, try_blocks.size());
00162 EDOC_FOREACH_CONST(TryBlockList, it, try_blocks)
00163 {
00164 it->Write(file);
00165 }
00166 }
00167
00168 bool CodeBlock::Merge(const CodeBlock& right)
00169 {
00170 bool differed = false;
00171
00172 #define EDOC_LIST_MERGE(VectorName, VectorType) \
00173 { \
00174 size_t i = 0; \
00175 for (std::list<VectorType>::const_iterator it = \
00176 right.VectorName.begin(); \
00177 it != right.VectorName.end(); \
00178 it++, i++) \
00179 { \
00180 EDOC_Finer("Searching in vector: right." << #VectorName \
00181 << ", size: " << right.VectorName.size() \
00182 << ", i: " << i); \
00183 bool found = false; \
00184 size_t j = 0; \
00185 for (std::list<VectorType>::const_iterator jt = \
00186 VectorName.begin(); \
00187 jt != VectorName.end(); \
00188 jt++, j++) \
00189 { \
00190 EDOC_Finer("Searching in vector: " << #VectorName \
00191 << ", size: " << VectorName.size() \
00192 << ", j: " << j); \
00193 if (*jt == *it) \
00194 { \
00195 EDOC_Finer("Found in vector: " << #VectorName); \
00196 found = true; \
00197 break; \
00198 } \
00199 } \
00200 \
00201 if (!found) \
00202 { \
00203 differed = 1; \
00204 EDOC_Finer("Pushing empty onto back vector: " << #VectorName); \
00205 VectorName.push_back(VectorType(&dict)); \
00206 VectorName.back() = *it; \
00207 } \
00208 } \
00209 }
00210
00211 EDOC_LIST_MERGE(function_calls, FunctionLoc)
00212 EDOC_LIST_MERGE(originating_exceptions, Exception)
00213 EDOC_LIST_MERGE(function_pointer_calls, FunctionTypeLoc)
00214 EDOC_LIST_MERGE(try_blocks, TryBlock)
00215
00216
00217
00218
00219
00220
00221 return differed;
00222 }
00223
00224 bool CodeBlock::operator==(const CodeBlock& right) const
00225 {
00226
00227
00228
00229 #define EDOC_LIST_COMPARE(VectorName, VectorType) \
00230 if (VectorName.size() != right.VectorName.size()) \
00231 { \
00232 return false; \
00233 } \
00234 for (std::list<VectorType>::const_iterator it = VectorName.begin(); \
00235 it != VectorName.end(); it++) \
00236 { \
00237 bool found = false; \
00238 for (std::list<VectorType>::const_iterator jt = \
00239 right.VectorName.begin(); \
00240 jt != right.VectorName.end(); \
00241 jt++) \
00242 { \
00243 if (*it == *jt) \
00244 { \
00245 found = true; \
00246 break; \
00247 } \
00248 } \
00249 if (!found) \
00250 { \
00251 return false; \
00252 } \
00253 }
00254
00255 EDOC_LIST_COMPARE(function_calls, FunctionLoc)
00256 EDOC_LIST_COMPARE(originating_exceptions, Exception)
00257 EDOC_LIST_COMPARE(function_pointer_calls, FunctionTypeLoc)
00258 EDOC_LIST_COMPARE(try_blocks, TryBlock)
00259
00260 return true;
00261 }
00262
00263 std::list<FunctionLoc> CodeBlock::AllFunctionCalls()
00264 {
00265 std::list<FunctionLoc> ret(function_calls);
00266 Append(ret, possible_function_calls);
00267 return ret;
00268 }
00269
00270 void CodeBlock::AddPossCall(FunctionLoc func)
00271 {
00272 possible_function_calls.push_back(func);
00273 possible_function_calls.back().possible = true;
00274 }
00275
00276 std::list<CodeBlock*> CodeBlock::GetAllCodeBlocks()
00277 {
00278 std::list<CodeBlock*> ret;
00279 ret.push_back(this);
00280
00281 EDOC_FOREACH(TryBlockList, it, try_blocks)
00282 {
00283
00284 Append(ret, it->try_block->GetAllCodeBlocks());
00285
00286
00287 EDOC_FOREACH(CatchBlockVec, jt, it->catch_blocks)
00288 {
00289 Append(ret, jt->catch_code->GetAllCodeBlocks());
00290 }
00291 }
00292
00293 return ret;
00294 }
00295
00296 size_t CodeBlock::ReplaceReferences(PStack& stack, void* remove,
00297 void* replace)
00298 {
00299 size_t count = 0;
00300 if (!stack.Push(this))
00301 {
00302 return count;
00303 }
00304
00305 EDOC_FOREACH(FuncLocList, it, function_calls)
00306 {
00307 count += it->ReplaceReferences(stack, remove, replace);
00308 }
00309
00310 EDOC_FOREACH(ExcepList, it, originating_exceptions)
00311 {
00312 count += it->ReplaceReferences(stack, remove, replace);
00313 }
00314
00315 EDOC_FOREACH(FTypeLocList, it, function_pointer_calls)
00316 {
00317 count += it->ReplaceReferences(stack, remove, replace);
00318 }
00319
00320 EDOC_FOREACH(TryBlockList, it, try_blocks)
00321 {
00322 count += it->ReplaceReferences(stack, remove, replace);
00323 }
00324
00325 EDOC_FOREACH(FuncLocList, it, possible_function_calls)
00326 {
00327 count += it->ReplaceReferences(
00328 stack, remove, replace);
00329 }
00330
00331 return count;
00332 }
00333
00334 std::ostream& CodeBlock::Print(std::ostream& out, std::string prefix) const
00335 {
00336 out << prefix << "{" << std::endl;
00337
00338 EDOC_FOREACH_CONST(FuncLocList, it, function_calls)
00339 {
00340 out << prefix << INDENT_STR << "Call : "
00341 << it->value->GetKeyName() << std::endl;
00342 }
00343
00344 EDOC_FOREACH_CONST(FuncLocList, it, possible_function_calls)
00345 {
00346 out << prefix << INDENT_STR << "Poss Call : "
00347 << it->value->GetKeyName() << std::endl;
00348 }
00349
00350 EDOC_FOREACH_CONST(ExcepList, it, originating_exceptions)
00351 {
00352 out << prefix << INDENT_STR << "Throw : "
00353 << it->type.value->GetKeyName() << std::endl;
00354 }
00355
00356 EDOC_FOREACH_CONST(FTypeLocList, it, function_pointer_calls)
00357 {
00358 out << prefix << INDENT_STR << "FP Call : "
00359 << it->value->GetKeyName() << std::endl;
00360 }
00361
00362 EDOC_FOREACH_CONST(TryBlockList, it, try_blocks)
00363 {
00364 it->Print(out, prefix + INDENT_STR);
00365 }
00366
00367 out << prefix << "}" << std::endl;
00368 return out;
00369 }
00370
00371 void CodeBlock::ExpandCallGraph(Function& function)
00372 {
00373
00374
00375 EDOC_FOREACH(FTypeLocList, it, function_pointer_calls)
00376 {
00377 for (size_t j = 0; j < it->value->addressed_functions.size(); j++)
00378 {
00379 AddPossCall(FunctionLoc(dict,
00380 it->value->addressed_functions[j],
00381 it->loc));
00382 }
00383 }
00384
00385 EDOC_FOREACH(TryBlockList, it, try_blocks)
00386 {
00387 it->ExpandCallGraph(function);
00388 }
00389 }
00390
00391 void CodeBlock::Validate(PStack& stack, const Dictionary& dict_in) const
00392 {
00393 StackRef ref(stack, this);
00394 if (!ref)
00395 {
00396 return;
00397 }
00398
00399 EDOC_ASSERT(&dict == &dict_in, "");
00400
00401 EDOC_FOREACH_CONST(FuncLocList, it, function_calls)
00402 {
00403 it->Validate(stack, dict_in);
00404 }
00405
00406 EDOC_FOREACH_CONST(ExcepList, it, originating_exceptions)
00407 {
00408 it->Validate(stack, dict_in);
00409 EDOC_ASSERT(
00410 it->type.value->throw_type->external_linkage,
00411 "Throw type of an originating exception should ALWAYS have "
00412 "external linkage."
00413 << "\nException type is: "
00414 << it->type.value->GetKeyName()
00415 << "\nThrow type is: "
00416 << it->type.value->throw_type->GetKeyName());
00417 }
00418
00419 EDOC_FOREACH_CONST(FTypeLocList, it, function_pointer_calls)
00420 {
00421 it->Validate(stack, dict_in);
00422 }
00423
00424 EDOC_FOREACH_CONST(TryBlockList, it, try_blocks)
00425 {
00426 it->Validate(stack, dict_in);
00427 }
00428
00429 EDOC_FOREACH_CONST(FuncLocList, it, possible_function_calls)
00430 {
00431 it->Validate(stack, dict_in);
00432 EDOC_ASSERT(it->possible, "Possible function calls must always "
00433 "have the \"possible\" flag set to true in the "
00434 "FunctionLoc object.");
00435 }
00436 }
00437
00438 std::list<EDoc::Exception*> CodeBlock::GetOriginatingExceptions()
00439 {
00440 std::list<EDoc::Exception*> ret;
00441 for (std::list<Exception>::iterator it =
00442 originating_exceptions.begin();
00443 it != originating_exceptions.end(); it++)
00444 {
00445 ret.push_back(&(*it));
00446 }
00447
00448 return ret;
00449 }
00450
00451 }