|
1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 |
|
17 #include <cassert> |
|
18 #include <string> |
|
19 #include <iostream> |
|
20 #include <iomanip> |
|
21 #include <direct.h> |
|
22 |
|
23 #include "messagedefparser\statebase.h" |
|
24 #include "messagedefparser\definitionparser.h" |
|
25 #include "messagedefparser\constidentifier.h" |
|
26 #include "messagedefparser\contextidentifier.h" |
|
27 #include "messagedefparser\enumidentifier.h" |
|
28 #include "messagedefparser\integeridentifier.h" |
|
29 #include "messagedefparser\messageidentifier.h" |
|
30 #include "messagedefparser\padidentifier.h" |
|
31 #include "messagedefparser\signatureidentifier.h" |
|
32 #include "messagedefparser\structidentifier.h" |
|
33 #include "messagedefparser\initialstate.h" |
|
34 #include "messagedefparser\messageidtypeidentifier.h" |
|
35 #include "util.h" |
|
36 #include "version.h" |
|
37 |
|
38 namespace Parser |
|
39 { |
|
40 |
|
41 // aFilename must be an absolute filename |
|
42 CDefinitionFile::CDefinitionFile(const std::string& aFilename) |
|
43 { |
|
44 iTokenizer = new Tokens::CDefinitionTokenizer(); |
|
45 iFilename = aFilename; |
|
46 size_t sep = iFilename.find_last_of("\\"); |
|
47 |
|
48 assert(sep != std::string::npos && iFilename[0] != '\\'); |
|
49 iFilePath = iFilename.substr(0, sep); |
|
50 } |
|
51 |
|
52 CDefinitionFile::~CDefinitionFile() |
|
53 { |
|
54 delete iTokenizer; |
|
55 } |
|
56 |
|
57 |
|
58 |
|
59 CDefinitionParser::CDefinitionParser() |
|
60 { |
|
61 iTesting = false; |
|
62 iAllIdentifiers.push_back(new CIntegerTypeIdentifier("UINT32", 4)); |
|
63 iAllIdentifiers.push_back(new CIntegerTypeIdentifier("UINT16", 2)); |
|
64 iAllIdentifiers.push_back(new CIntegerTypeIdentifier("UINT8", 1)); |
|
65 iAllIdentifiers.push_back(new CIntegerTypeIdentifier("INT32", 4, true)); |
|
66 iAllIdentifiers.push_back(new CIntegerTypeIdentifier("INT16", 2, true)); |
|
67 iAllIdentifiers.push_back(new CIntegerTypeIdentifier("INT8", 1, true)); |
|
68 iAllIdentifiers.push_back(new CPadTypeIdentifier("PAD")); |
|
69 |
|
70 // Complex built-in types |
|
71 iAllIdentifiers.push_back(new CMessageIdTypeIdentifier(*this)); |
|
72 } |
|
73 |
|
74 CDefinitionParser::~CDefinitionParser() |
|
75 { |
|
76 while (!iFileStack.empty()) |
|
77 { |
|
78 delete iFileStack.back(); |
|
79 iFileStack.pop_back(); |
|
80 } |
|
81 } |
|
82 |
|
83 |
|
84 bool CDefinitionParser::IncludeDefinitionFile(const char* aDefinitionFile) |
|
85 { |
|
86 std::string includeDefFile; |
|
87 |
|
88 if (aDefinitionFile[1] == ':') // consider it an absolute file path |
|
89 { |
|
90 includeDefFile = aDefinitionFile; |
|
91 } |
|
92 else if (iFileStack.empty()) |
|
93 { |
|
94 char* cwd = _getcwd(NULL, 0); |
|
95 if (aDefinitionFile[0] == '\\') // consider it relative to the root of the current drive |
|
96 { |
|
97 includeDefFile = std::string(cwd).substr(0, 2); |
|
98 } |
|
99 else |
|
100 { |
|
101 includeDefFile = cwd; |
|
102 includeDefFile += "\\"; |
|
103 } |
|
104 includeDefFile += aDefinitionFile; |
|
105 free(cwd); |
|
106 } |
|
107 else |
|
108 { |
|
109 if (aDefinitionFile[0] == '\\') |
|
110 { |
|
111 // needs a drive |
|
112 includeDefFile = CurrentFile().FilePath().substr(0, 2); |
|
113 } |
|
114 else |
|
115 { |
|
116 includeDefFile = CurrentFile().FilePath(); |
|
117 } |
|
118 includeDefFile += "\\"; |
|
119 includeDefFile += aDefinitionFile; |
|
120 } |
|
121 |
|
122 // TODO: get absolute filename for aDefinitionfile based on original def file |
|
123 for (unsigned int i=0; i<iFileStack.size(); i++) |
|
124 { |
|
125 std::string includedFile = iFileStack.at(i)->FilePath() + "\\" + iFileStack.at(i)->Filename(); |
|
126 if (!_strcmpi(includedFile.c_str(), includeDefFile.c_str())) |
|
127 { |
|
128 std::cerr << "Error: Circular inclusion of " << includeDefFile << " from "; |
|
129 std::cerr << CurrentFile().FilePath() << "\\" << CurrentFile().Filename() << " at line "; |
|
130 std::cerr << CurrentFile().Tokenizer().Line() << std::endl; |
|
131 iError = Parser::ECircularInclusion; |
|
132 return false; |
|
133 } |
|
134 } |
|
135 |
|
136 bool loadSuccess; |
|
137 CDefinitionFile* defFile = new CDefinitionFile(includeDefFile); |
|
138 loadSuccess = (defFile->Tokenizer().LoadDefinitionFile(includeDefFile) == Tokens::ENoError); |
|
139 if (!loadSuccess) |
|
140 { |
|
141 // if loading the first (the specified initial definition file) and it failed |
|
142 // and the file isn't root relative or absolute try looking in the exe dir |
|
143 if (iFileStack.empty() && aDefinitionFile[0] != '\\' && aDefinitionFile[1] != ':') |
|
144 { |
|
145 includeDefFile = ::__argv[0]; |
|
146 size_t sep; |
|
147 sep = includeDefFile.find_last_of('\\'); |
|
148 if (sep != std::string::npos) |
|
149 { |
|
150 includeDefFile.erase(sep + 1); |
|
151 includeDefFile += aDefinitionFile; |
|
152 } |
|
153 |
|
154 delete defFile; |
|
155 defFile = new CDefinitionFile(includeDefFile); |
|
156 loadSuccess = (defFile->Tokenizer().LoadDefinitionFile(includeDefFile) == Tokens::ENoError); |
|
157 } |
|
158 |
|
159 if (!loadSuccess) |
|
160 { |
|
161 delete defFile; |
|
162 if (iFileStack.empty()) |
|
163 { |
|
164 std::cerr << "Error loading definition file: " << aDefinitionFile << std::endl; |
|
165 } |
|
166 else |
|
167 { |
|
168 std::cerr << "Error loading definition file: " << includeDefFile |
|
169 << " included from " |
|
170 << CurrentFile().FilePath() << "\\" << CurrentFile().Filename() |
|
171 << " at line " |
|
172 << CurrentFile().Tokenizer().Line() << std::endl; |
|
173 } |
|
174 |
|
175 iError = EFileError; |
|
176 return false; |
|
177 } |
|
178 } |
|
179 |
|
180 iFileStack.push_back(defFile); |
|
181 return true; |
|
182 } |
|
183 |
|
184 |
|
185 void CDefinitionParser::CloseCurrentFile() |
|
186 { |
|
187 assert(!iFileStack.empty()); |
|
188 CDefinitionFile* defFile = iFileStack.back(); |
|
189 iFileStack.pop_back(); |
|
190 delete defFile; |
|
191 } |
|
192 |
|
193 |
|
194 CDefinitionFile& CDefinitionParser::CurrentFile() |
|
195 { |
|
196 assert(!iFileStack.empty()); |
|
197 return *(iFileStack.back()); |
|
198 } |
|
199 |
|
200 |
|
201 Parser::TResult CDefinitionParser::ParseDefinitionFile(const char* aDefinitionFile) |
|
202 { |
|
203 iError = ENoError; |
|
204 if (!IncludeDefinitionFile(aDefinitionFile)) |
|
205 { |
|
206 return iError; |
|
207 } |
|
208 |
|
209 SetState(new CInitialState(*this)); |
|
210 |
|
211 do |
|
212 { |
|
213 while (CurrentFile().Tokenizer().GetNextToken() == Tokens::ETokenFound) |
|
214 { |
|
215 State().ProcessState(); |
|
216 |
|
217 if (iError != Parser::ENoError && !iTesting) |
|
218 { |
|
219 return iError; |
|
220 } |
|
221 } |
|
222 |
|
223 if (State().StateId() != Parser::EStateInitial) |
|
224 { |
|
225 std::cerr << "Error: Unexpected end of file "; |
|
226 std::cerr << CurrentFile().Filename() << " at line "; |
|
227 std::cerr << CurrentFile().Tokenizer().Line() << std::endl; |
|
228 if (!iTesting) |
|
229 { |
|
230 return Parser::EUnexpectedEndOfFile; |
|
231 } |
|
232 } |
|
233 |
|
234 // finished with current file |
|
235 CloseCurrentFile(); |
|
236 |
|
237 } while (iFileStack.size() > 0); |
|
238 |
|
239 return iError; |
|
240 } |
|
241 |
|
242 |
|
243 void CDefinitionParser::DumpIdentifiers() const |
|
244 { |
|
245 unsigned int i; |
|
246 std::cout << "utracedecoder " APPVERSION << std::endl; |
|
247 std::cout << "Identifier List" << std::endl << "===============" << std::endl; |
|
248 for (i=0; i<iAllIdentifiers.size(); i++) |
|
249 { |
|
250 std::cout << std::endl; |
|
251 |
|
252 switch (iAllIdentifiers.at(i)->Type()) |
|
253 { |
|
254 case EConstIdentifier: |
|
255 { |
|
256 const CConstIdentifier* ident = static_cast<const CConstIdentifier*>(iAllIdentifiers.at(i)); |
|
257 std::cout << "CONST " << ident->Name() << " = " << ident->iValue << std::endl; |
|
258 } |
|
259 break; |
|
260 |
|
261 case EEnumTypeIdentifier: |
|
262 { |
|
263 const CEnumTypeIdentifier* ident = static_cast<const CEnumTypeIdentifier*>(iAllIdentifiers.at(i)); |
|
264 std::cout << "ENUM " << ident->Name() << "(size="; |
|
265 std::cout << ident->Size(); |
|
266 std::cout << ")" << std::endl; |
|
267 unsigned int j; |
|
268 for (j=0; j<ident->iEnumValues.size(); j++) |
|
269 { |
|
270 std::cout << " " << ident->iEnumValues.at(j)->Name() << " = " << ident->iEnumValues.at(j)->iValue << std::endl; |
|
271 } |
|
272 std::cout << std::endl; |
|
273 } |
|
274 break; |
|
275 |
|
276 case EStructIdentifier: |
|
277 case EMessageIdTypeIdentifier: |
|
278 { |
|
279 const CStructIdentifier* ident = static_cast<const CStructIdentifier*>(iAllIdentifiers.at(i)); |
|
280 std::cout << "STRUCT " << ident->Name() << "(size="; |
|
281 std::cout << ident->TotalSize(); |
|
282 std::cout << ")" << std::endl; |
|
283 unsigned int j; |
|
284 for (j=0; j<ident->iMembers.size(); j++) |
|
285 { |
|
286 std::cout << " " << ident->iMembers.at(j)->iOffset << ": "; |
|
287 std::cout << " " << ident->iMembers.at(j)->iMemberType->Name() << " " |
|
288 << ident->iMembers.at(j)->iMemberName |
|
289 << " (" << ident->iMembers.at(j)->iArraySize * ident->iMembers.at(j)->iMemberType->TotalSize() |
|
290 << ")" << std::endl; |
|
291 } |
|
292 std::cout << std::endl; |
|
293 } |
|
294 break; |
|
295 |
|
296 case ESignatureIdentifier: |
|
297 { |
|
298 if (iAllIdentifiers.at(i)->Flags() & KAliasIdentifier) |
|
299 { |
|
300 const CSignatureAliasIdentifier* ident = static_cast<const CSignatureAliasIdentifier*>(iAllIdentifiers.at(i)); |
|
301 std::cout << "ALIAS SIGNATURE " << ident->Name() |
|
302 << " = " << ident->RealName() << std::endl; |
|
303 } |
|
304 else |
|
305 { |
|
306 const CSignatureIdentifier* ident = static_cast<const CSignatureIdentifier*>(iAllIdentifiers.at(i)); |
|
307 std::cout << "SIGNATURE " << ident->Name() << "(size="; |
|
308 std::cout << ident->TotalSize(); |
|
309 std::cout << ")" << std::endl; |
|
310 if (ident->BaseSignature()) |
|
311 { |
|
312 std::cout << " BASE SIGNATURE = " << ident->BaseSignature()->Name() |
|
313 << " (size=" << ident->BaseSignature()->TotalSize() << ")" << std::endl; |
|
314 } |
|
315 std::cout << " STYPEID = (0x" << std::setw(8) << std::noshowbase |
|
316 << std::nouppercase << std::hex << std::setfill('0') << ident->TypeId().iUid |
|
317 << ", " << std::dec << ident->TypeId().iType << ")" << std::endl; |
|
318 |
|
319 unsigned int j; |
|
320 for (j=0; j<ident->iMembers.size(); j++) |
|
321 { |
|
322 std::cout << " " << ident->iMembers.at(j)->iOffset << ": "; |
|
323 std::cout << ident->iMembers.at(j)->iMemberType->Name() << " " |
|
324 << ident->iMembers.at(j)->iMemberName |
|
325 << " (size=" << ident->iMembers.at(j)->iArraySize * ident->iMembers.at(j)->iMemberType->TotalSize() |
|
326 << ")" << std::endl; |
|
327 } |
|
328 } |
|
329 std::cout << std::endl; |
|
330 } |
|
331 break; |
|
332 |
|
333 case EContextIdentifier: |
|
334 { |
|
335 if (iAllIdentifiers.at(i)->Flags() & KAliasIdentifier) |
|
336 { |
|
337 const CContextAliasIdentifier* ident = static_cast<const CContextAliasIdentifier*>(iAllIdentifiers.at(i)); |
|
338 std::cout << "ALIAS CONTEXT " << ident->Name() |
|
339 << " = " << ident->RealName() << std::endl << std::endl; |
|
340 } |
|
341 else |
|
342 { |
|
343 const CContextIdentifier* ident = static_cast<const CContextIdentifier*>(iAllIdentifiers.at(i)); |
|
344 std::cout << "CONTEXT " << ident->Name() << "(size="; |
|
345 std::cout << ident->TotalSize(); |
|
346 std::cout << ")" << std::endl; |
|
347 if (ident->BaseContext()) |
|
348 { |
|
349 std::cout << " BASE CONTEXT = " << ident->BaseContext()->Name() |
|
350 << " (size=" << ident->BaseContext()->TotalSize() << ")" << std::endl; |
|
351 } |
|
352 |
|
353 unsigned int j; |
|
354 for (j=0; j<ident->iMembers.size(); j++) |
|
355 { |
|
356 std::cout << " " << ident->iMembers.at(j)->iOffset << ": "; |
|
357 std::cout << ident->iMembers.at(j)->iMemberType->Name() << " " |
|
358 << ident->iMembers.at(j)->iMemberName |
|
359 << " (size=" << ident->iMembers.at(j)->iArraySize * ident->iMembers.at(j)->iMemberType->TotalSize() |
|
360 << ")" << std::endl; |
|
361 } |
|
362 } |
|
363 std::cout << std::endl; |
|
364 } |
|
365 break; |
|
366 |
|
367 case EMessageIdentifier: |
|
368 { |
|
369 if (iAllIdentifiers.at(i)->Flags() & KAliasIdentifier) |
|
370 { |
|
371 const CMessageAliasIdentifier* ident = static_cast<const CMessageAliasIdentifier*>(iAllIdentifiers.at(i)); |
|
372 std::cout << "ALIAS MESSAGE " << ident->Name() |
|
373 << " = " << ident->RealName() << std::endl << std::endl; |
|
374 } |
|
375 else |
|
376 { |
|
377 const CMessageIdentifier* ident = static_cast<const CMessageIdentifier*>(iAllIdentifiers.at(i)); |
|
378 std::cout << "MESSAGE " << ident->Name() << std::endl; |
|
379 if (ident->iSignature) |
|
380 { |
|
381 std::cout << " SIGNATURE = " << ident->iSignature->Name() << std::endl; |
|
382 } |
|
383 std::cout << " ID = (" << ident->iMessageId.iRealmId << ", " << ident->iMessageId.iMessageId << ")" << std::endl; |
|
384 } |
|
385 std::cout << std::endl; |
|
386 } |
|
387 break; |
|
388 |
|
389 default: |
|
390 std::cout << iAllIdentifiers.at(i)->Name() << " (identifier type=" << iAllIdentifiers.at(i)->Type() << ")" << std::endl; |
|
391 break; |
|
392 } |
|
393 } |
|
394 } |
|
395 |
|
396 const CIdentifierBase* CDefinitionParser::FindIdentifier(const char* aIdentifierName) const |
|
397 { |
|
398 unsigned int i; |
|
399 const CIdentifierBase* ident; |
|
400 for (i=0; i<iAllIdentifiers.size(); i++) |
|
401 { |
|
402 ident = iAllIdentifiers.at(i); |
|
403 if (!_strcmpi(ident->Name(), aIdentifierName)) |
|
404 { |
|
405 return ident; |
|
406 } |
|
407 } |
|
408 return NULL; |
|
409 } |
|
410 |
|
411 |
|
412 void CDefinitionParser::AddIdentifier(const CIdentifierBase* aIdentifier) |
|
413 { |
|
414 if (FindIdentifier(aIdentifier->Name())) |
|
415 { |
|
416 std::cerr << "ERROR: **** Adding duplicate identifier : " << aIdentifier->Name() << " ****" << std::endl; |
|
417 } |
|
418 assert(!FindIdentifier(aIdentifier->Name())); |
|
419 iAllIdentifiers.push_back(aIdentifier); |
|
420 } |
|
421 |
|
422 const CContextIdentifier* CDefinitionParser::FindContextBySize(unsigned int aSize) const |
|
423 { |
|
424 unsigned int i; |
|
425 const CContextIdentifier* context; |
|
426 for (i=0; i<iAllIdentifiers.size(); i++) |
|
427 { |
|
428 context = static_cast<const CContextIdentifier*>(iAllIdentifiers.at(i)); |
|
429 if (context->Type() == Parser::EContextIdentifier |
|
430 && context->TotalSize() == aSize) |
|
431 { |
|
432 return context; |
|
433 } |
|
434 } |
|
435 return NULL; |
|
436 } |
|
437 |
|
438 const CSignatureIdentifier* CDefinitionParser::FindSignatureByTypeId(const STypeId& aTypeId) const |
|
439 { |
|
440 unsigned int i; |
|
441 const CSignatureIdentifier* signature; |
|
442 for (i=0; i<iAllIdentifiers.size(); i++) |
|
443 { |
|
444 signature = static_cast<const CSignatureIdentifier*>(iAllIdentifiers.at(i)); |
|
445 if (signature->Type() == Parser::ESignatureIdentifier |
|
446 && signature->TypeId().iUid == aTypeId.iUid |
|
447 && signature->TypeId().iType == aTypeId.iType) |
|
448 { |
|
449 return signature; |
|
450 } |
|
451 } |
|
452 return NULL; |
|
453 } |
|
454 |
|
455 |
|
456 const CMessageIdentifier* CDefinitionParser::FindMessageByMessageId(const TMessageId& aMessageId) const |
|
457 { |
|
458 unsigned int i; |
|
459 const CMessageIdentifier* message; |
|
460 for (i=0; i<iAllIdentifiers.size(); i++) |
|
461 { |
|
462 message = static_cast<const CMessageIdentifier*>(iAllIdentifiers.at(i)); |
|
463 if (message->Type() == Parser::EMessageIdentifier |
|
464 && message->iMessageId.iRealmId == aMessageId.iRealmId |
|
465 && message->iMessageId.iMessageId == aMessageId.iMessageId) |
|
466 { |
|
467 return message; |
|
468 } |
|
469 } |
|
470 return NULL; |
|
471 } |
|
472 |
|
473 void CDefinitionParser::SetError(TResult aError) |
|
474 { |
|
475 iError = aError; |
|
476 switch (iError) |
|
477 { |
|
478 case ENoError: |
|
479 return; |
|
480 //break; |
|
481 |
|
482 case EDuplicateIdentifier: |
|
483 std::cerr << "Error: Duplicate identifier \"" << CurrentFile().Tokenizer().Token() << "\" in "; |
|
484 break; |
|
485 |
|
486 case EValueOutOfRange: |
|
487 std::cerr << "Error: Value out of range \"" << CurrentFile().Tokenizer().Token() << "\" in "; |
|
488 break; |
|
489 |
|
490 case EUnexpectedToken: |
|
491 std::cerr << "Error: Unexpected token \"" << CurrentFile().Tokenizer().Token() << "\" in "; |
|
492 break; |
|
493 |
|
494 case EUnknownIdentifier: |
|
495 std::cerr << "Error: Unknown identifier \"" << CurrentFile().Tokenizer().Token() << "\" in "; |
|
496 break; |
|
497 |
|
498 default: |
|
499 std::cerr << "Error: (" << iError << ") in "; |
|
500 } |
|
501 |
|
502 std::cerr << CurrentFile().Filename() << " at line "; |
|
503 std::cerr << CurrentFile().Tokenizer().Line() << std::endl; |
|
504 } |
|
505 |
|
506 } // namespace Parser |
|
507 |