|
1 // Copyright (c) 2004-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 // Implementation of the Class DefFile for the elf2e32 tool |
|
15 // @internalComponent |
|
16 // @released |
|
17 // |
|
18 // |
|
19 |
|
20 // |
|
21 #include <stdio.h> |
|
22 #include <iostream> |
|
23 #include <stdlib.h> |
|
24 |
|
25 #include "pl_symbol.h" |
|
26 #include "deffile.h" |
|
27 #include "errorhandler.h" |
|
28 |
|
29 #ifdef __LINUX__ |
|
30 #include "h_utl.h" |
|
31 #define STRUPR strupr |
|
32 #else |
|
33 #define STRUPR _strupr |
|
34 #endif |
|
35 |
|
36 using std::cerr; |
|
37 using std::cout; |
|
38 using std::endl; |
|
39 |
|
40 #define SUCCESS 1 |
|
41 #define FAILURE 0 |
|
42 |
|
43 /** |
|
44 Destructor to release all the allocated memory |
|
45 @internalComponent |
|
46 @released |
|
47 */ |
|
48 DefFile::~DefFile() |
|
49 { |
|
50 if(iSymbolList && iSymbolList->size()) |
|
51 { |
|
52 SymbolList::iterator aItr = iSymbolList->begin(); |
|
53 SymbolList::iterator last = iSymbolList->end(); |
|
54 Symbol *temp; |
|
55 |
|
56 while(aItr != last) |
|
57 { |
|
58 temp = *aItr; |
|
59 aItr++; |
|
60 delete temp; |
|
61 } |
|
62 iSymbolList->clear(); |
|
63 } |
|
64 delete iSymbolList; |
|
65 } |
|
66 /** |
|
67 Function to Get File Size. |
|
68 @param fptrDef - File pointer to DEF file |
|
69 @internalComponent |
|
70 @released |
|
71 */ |
|
72 int DefFile::GetFileSize(FILE *fptrDef) |
|
73 { |
|
74 int fileSize,status; |
|
75 |
|
76 status=fseek(fptrDef, 0, SEEK_END); |
|
77 if(status!=0) |
|
78 { |
|
79 throw FileError(FILEREADERROR,iFileName); |
|
80 } |
|
81 fileSize=ftell(fptrDef); |
|
82 rewind(fptrDef); |
|
83 |
|
84 return fileSize; |
|
85 |
|
86 } |
|
87 |
|
88 /** |
|
89 Function to Open File and read it in memory. |
|
90 @param defFile - DEF File name |
|
91 @internalComponent |
|
92 @released |
|
93 */ |
|
94 char* DefFile::OpenDefFile(char * defFile) |
|
95 { |
|
96 int fileSize; |
|
97 char *defFileEntries; |
|
98 FILE *fptrDef; |
|
99 |
|
100 iFileName=defFile; |
|
101 if((fptrDef=fopen(defFile,"rb"))==NULL) |
|
102 { |
|
103 throw FileError(FILEOPENERROR,defFile); |
|
104 } |
|
105 |
|
106 fileSize=GetFileSize(fptrDef); |
|
107 |
|
108 if((defFileEntries= new char[fileSize+2]) ==NULL) |
|
109 { |
|
110 throw MemoryAllocationError(MEMORYALLOCATIONERROR,defFile); |
|
111 } |
|
112 |
|
113 //Getting whole file in memory |
|
114 if(!fread(defFileEntries, fileSize, 1, fptrDef)) |
|
115 { |
|
116 throw FileError(FILEREADERROR,defFile); |
|
117 } |
|
118 |
|
119 //Adding ENTER at end |
|
120 *(defFileEntries+fileSize)='\n'; |
|
121 //Adding '\0' at end |
|
122 *(defFileEntries+fileSize+1)='\0'; |
|
123 |
|
124 fclose(fptrDef); |
|
125 |
|
126 return defFileEntries; |
|
127 |
|
128 } |
|
129 |
|
130 /** |
|
131 Function to Parse Def File which has been read in buffer. |
|
132 @param defFileEntries - pointer to def file entries which has been read in buffer |
|
133 @internalComponent |
|
134 @released |
|
135 */ |
|
136 void DefFile::ParseDefFile(char *defFileEntries) |
|
137 { |
|
138 iSymbolList = new SymbolList; |
|
139 |
|
140 int ordinalNo = 0; |
|
141 int symbolType=SymbolTypeCode; |
|
142 int PreviousOrdinal=0; |
|
143 char MultiLineStatement[1024]=""; |
|
144 bool NAMEorLIBRARYallowed=true; |
|
145 int LineNum = 0; |
|
146 bool isComment; |
|
147 |
|
148 char *lineToken; |
|
149 int aLineLength = 0, width = 0; |
|
150 unsigned i; |
|
151 char *ptrEntry,*ptrEntryType; |
|
152 char entryType[256]; |
|
153 bool entryFlag; |
|
154 |
|
155 |
|
156 lineToken=strtok(defFileEntries,"\n"); |
|
157 while(lineToken != NULL) |
|
158 { |
|
159 symbolType=SymbolTypeCode; |
|
160 isComment=false; |
|
161 entryType[0]='\0'; |
|
162 aLineLength = strlen(lineToken); |
|
163 LineNum++; |
|
164 |
|
165 if (lineToken == NULL || lineToken[0]==13) |
|
166 { |
|
167 lineToken=strtok(NULL,"\n"); |
|
168 continue; |
|
169 } |
|
170 |
|
171 // comment lines |
|
172 if (lineToken[0] == ';') |
|
173 { |
|
174 lineToken=strtok(NULL,"\n"); |
|
175 continue; |
|
176 } |
|
177 |
|
178 ptrEntry=lineToken; |
|
179 |
|
180 if((!strstr(lineToken, "NONAME") && ((ptrEntryType=strstr(lineToken, "NAME")) != NULL)) || |
|
181 ((ptrEntryType=strstr(lineToken, "EXPORTS")) != NULL) || |
|
182 ((ptrEntryType=strstr(lineToken, "IMPORTS")) != NULL) || |
|
183 ((ptrEntryType=strstr(lineToken, "SECTIONS")) != NULL) || |
|
184 ((ptrEntryType=strstr(lineToken, "LIBRARY")) != NULL) || |
|
185 ((ptrEntryType=strstr(lineToken, "DESCRIPTION")) != NULL)|| |
|
186 ((ptrEntryType=strstr(lineToken, "STACKSIZE")) != NULL)|| |
|
187 ((ptrEntryType=strstr(lineToken, "VERSION")) != NULL) |
|
188 ) |
|
189 { |
|
190 entryFlag=true; |
|
191 |
|
192 for(i=0; ptrEntry!=ptrEntryType; i++,ptrEntry++) |
|
193 { |
|
194 switch(lineToken[i]) |
|
195 { |
|
196 case ' ': |
|
197 case '\t': |
|
198 continue; |
|
199 default: |
|
200 entryFlag=false; |
|
201 break; |
|
202 } |
|
203 if(entryFlag==false) |
|
204 break; |
|
205 } |
|
206 |
|
207 if(entryFlag==false && !strcmp(MultiLineStatement,"")) |
|
208 { |
|
209 throw DEFFileError(UNRECOGNIZEDTOKEN,iFileName,LineNum,lineToken); |
|
210 } |
|
211 |
|
212 if(entryFlag==true) |
|
213 { |
|
214 switch(ptrEntryType[0]) |
|
215 { |
|
216 case 'E': |
|
217 case 'I': |
|
218 case 'L': |
|
219 case 'V': |
|
220 width=7; |
|
221 break; |
|
222 case 'S': |
|
223 if(ptrEntryType[1]=='E') |
|
224 width=8; |
|
225 else |
|
226 width=9; |
|
227 break; |
|
228 case 'N': |
|
229 width=4; |
|
230 break; |
|
231 case 'D': |
|
232 width=11; |
|
233 break; |
|
234 } |
|
235 } |
|
236 |
|
237 if(entryFlag==true) |
|
238 { |
|
239 for(i=i+width; i<strlen(lineToken); i++) |
|
240 { |
|
241 switch(lineToken[i]) |
|
242 { |
|
243 case ' ': |
|
244 case '\t': |
|
245 continue; |
|
246 case '\r': |
|
247 case '\0': |
|
248 break; |
|
249 default: |
|
250 entryFlag=false; |
|
251 break; |
|
252 } |
|
253 |
|
254 if(entryFlag==false) |
|
255 break; |
|
256 } |
|
257 } |
|
258 |
|
259 if(entryFlag==false && !strcmp(MultiLineStatement,"")) |
|
260 { |
|
261 throw DEFFileError(UNRECOGNIZEDTOKEN,iFileName,LineNum,lineToken+i); |
|
262 } |
|
263 |
|
264 if(entryFlag==true) |
|
265 { |
|
266 strncpy(entryType, ptrEntryType, width); |
|
267 entryType[width]='\0'; |
|
268 |
|
269 switch(ptrEntryType[0]) |
|
270 { |
|
271 case 'E': // check for multi-line sections starting |
|
272 strcpy(MultiLineStatement, STRUPR(entryType)); // Uppercase token |
|
273 NAMEorLIBRARYallowed = false; |
|
274 lineToken = strtok(NULL, "\n" ); // Get the next line |
|
275 continue; |
|
276 case 'N': |
|
277 break; |
|
278 case 'L': |
|
279 break; |
|
280 case 'D': |
|
281 break; |
|
282 case 'S': |
|
283 case 'V': |
|
284 if(entryType[1]!='E') |
|
285 { |
|
286 // set MULTI-LINE statement to OFF |
|
287 strcpy(MultiLineStatement, STRUPR(entryType)); // Uppercase token |
|
288 // check single-line statements are specified correctly |
|
289 // check NAME or LIBRARY statements aren't supplied incorrectly |
|
290 if (!strcmp(entryType, "NAME") || |
|
291 !strcmp(entryType, "LIBRARY") |
|
292 ) |
|
293 { |
|
294 if (NAMEorLIBRARYallowed == false) |
|
295 { |
|
296 throw DEFFileError(NAMELIBRARYNOTCORRECT,iFileName,LineNum,lineToken); |
|
297 } |
|
298 lineToken=strtok(NULL,"\n"); |
|
299 continue; |
|
300 } |
|
301 NAMEorLIBRARYallowed = false; |
|
302 lineToken=strtok(NULL,"\n"); |
|
303 continue; |
|
304 } |
|
305 continue; |
|
306 case 'I': |
|
307 strcpy(MultiLineStatement, STRUPR(entryType)); // Uppercase token |
|
308 lineToken = strtok(NULL, "\n" ); // Get the next line |
|
309 continue; |
|
310 } |
|
311 } |
|
312 |
|
313 } |
|
314 else |
|
315 { |
|
316 if (!strcmp(MultiLineStatement,"")) |
|
317 { |
|
318 throw DEFFileError(EXPORTSEXPECTED,iFileName,LineNum,lineToken); |
|
319 } |
|
320 } |
|
321 |
|
322 // Get Export entries |
|
323 if (!strcmp(MultiLineStatement,"EXPORTS")) |
|
324 { |
|
325 Symbol aSymbol(NULL, SymbolTypeCode); |
|
326 if( Tokenize(lineToken, LineNum, aSymbol) ) |
|
327 { |
|
328 Symbol *newSymbolEntry = new Symbol(aSymbol); |
|
329 iSymbolList->push_back(newSymbolEntry); |
|
330 |
|
331 ordinalNo = aSymbol.OrdNum(); |
|
332 //Check for ordinal sequence |
|
333 if (ordinalNo != PreviousOrdinal+1) |
|
334 { |
|
335 throw DEFFileError(ORDINALSEQUENCEERROR,iFileName,LineNum,(char*)aSymbol.SymbolName()); |
|
336 } |
|
337 |
|
338 PreviousOrdinal = ordinalNo; |
|
339 |
|
340 } |
|
341 lineToken=strtok(NULL,"\n"); |
|
342 continue; |
|
343 } |
|
344 else if(strcmp(MultiLineStatement,"")!=0)//For entry other than exports |
|
345 lineToken = strtok(NULL, "\n" ); // Get the next line |
|
346 |
|
347 }//End of while |
|
348 } |
|
349 |
|
350 /** |
|
351 This Function calls LineToken's Tokenize function. |
|
352 @param aTokens - Input string at the current line number |
|
353 @param aLineNum - Current line number |
|
354 @param aSymbol - Symbol to be populated while parsing the line. |
|
355 Return value - It returns true if a valid def file entry is found. |
|
356 @internalComponent |
|
357 @released |
|
358 */ |
|
359 bool DefFile::Tokenize(char* aTokens, int aLineNum, Symbol& aSymbol) |
|
360 { |
|
361 /* |
|
362 * Pattern to match is: |
|
363 * START\s*(\S+)\s+@\s*(d+)\s*(NONAME)?\s*(R3UNUSED)?\s*(ABSENT)?\s*(;\s*(.*))END |
|
364 */ |
|
365 LineToken aLine(iFileName, aLineNum, aTokens, &aSymbol); |
|
366 return aLine.Tokenize(); |
|
367 } |
|
368 |
|
369 |
|
370 char * DefFilePatterns[] = |
|
371 { |
|
372 "NONAME",//index 0 |
|
373 "DATA", |
|
374 "R3UNUSED", |
|
375 "ABSENT" |
|
376 }; |
|
377 |
|
378 #define DEF_NONAME 0 |
|
379 #define DEF_DATA 1 |
|
380 #define DEF_R3UNUSED 2 |
|
381 #define DEF_ABSENT 3 |
|
382 |
|
383 /** |
|
384 This constructor creates an instance of LineToken class. |
|
385 @param aFileName - Def File Name. |
|
386 @param aLineNum - Current line number |
|
387 @param aLn - Input string at the current line number |
|
388 @param aSym - Symbol to be populated while parsing the line. |
|
389 @internalComponent |
|
390 @released |
|
391 */ |
|
392 LineToken::LineToken(char* aFileName, int aLineNum, char *aLn, Symbol* aSym) : \ |
|
393 iLine(aLn) , iSymbol(aSym) , iOffset(0), iState(EInitState),iFileName(aFileName), iLineNum(aLineNum) |
|
394 { |
|
395 } |
|
396 |
|
397 /** |
|
398 This function tokenizes the line and populates a symbol entry |
|
399 if there is one. |
|
400 Return Value - True, if the current line has a valid def entry. |
|
401 @internalComponent |
|
402 @released |
|
403 */ |
|
404 bool LineToken::Tokenize() |
|
405 { |
|
406 while (1) |
|
407 { |
|
408 switch( iState ) |
|
409 { |
|
410 case EFinalState: |
|
411 return true; |
|
412 case EInitState: |
|
413 if( *(iLine + iOffset) == '\0' || |
|
414 *(iLine + iOffset) == '\r' || |
|
415 *(iLine + iOffset) == '\n') |
|
416 { |
|
417 /* |
|
418 * Skip empty lines. |
|
419 */ |
|
420 return false; |
|
421 } |
|
422 else |
|
423 { |
|
424 NextToken(); |
|
425 } |
|
426 break; |
|
427 default: |
|
428 NextToken(); |
|
429 break; |
|
430 } |
|
431 } |
|
432 return false; |
|
433 } |
|
434 |
|
435 /** |
|
436 This function parses a line of the def file based on the current |
|
437 state it is in. |
|
438 @internalComponent |
|
439 @released |
|
440 */ |
|
441 void LineToken::NextToken() |
|
442 { |
|
443 int aCurrentPos = 0; |
|
444 char *aSymbolName; |
|
445 |
|
446 switch( iState ) |
|
447 { |
|
448 case EInitState: |
|
449 if(IsWhiteSpace((iLine + iOffset), aCurrentPos)) |
|
450 { |
|
451 IncrOffset(aCurrentPos); |
|
452 } |
|
453 |
|
454 if(IsWord(iLine + iOffset, aCurrentPos)) |
|
455 { |
|
456 SetState(ESymbolName); |
|
457 } |
|
458 break; |
|
459 |
|
460 case ESymbolName: |
|
461 { |
|
462 // Get the length of the symbol |
|
463 IsWord(iLine + iOffset, aCurrentPos); |
|
464 |
|
465 char *cmt = strchr(iLine + iOffset, ';'); |
|
466 char *aAlias = strchr(iLine + iOffset, '='); |
|
467 |
|
468 if( aAlias && (!cmt || (aAlias < cmt)) ) |
|
469 { |
|
470 int aAliasPos = aAlias - (iLine+ iOffset); |
|
471 |
|
472 //Check if alias name is also supplied, they should be separated |
|
473 // by whitespace, i.e., SymbolName=AliasName is valid while, |
|
474 // SymbolName =AliasName is invalid. |
|
475 if( aAliasPos > aCurrentPos) |
|
476 { |
|
477 char *aToken = (iLine + iOffset + aCurrentPos); |
|
478 throw DEFFileError(UNRECOGNIZEDTOKEN, iFileName, iLineNum, aToken); |
|
479 } |
|
480 |
|
481 aSymbolName = new char[aAliasPos+1]; |
|
482 strncpy(aSymbolName, iLine + iOffset, aAliasPos); |
|
483 aSymbolName[aAliasPos] = '\0'; |
|
484 char *aExportName = new char[aCurrentPos - aAliasPos + 1]; |
|
485 strncpy(aExportName, aAlias +1, (aCurrentPos - aAliasPos)); |
|
486 aExportName[(aCurrentPos - aAliasPos)] = '\0'; |
|
487 iSymbol->ExportName(aExportName); |
|
488 } |
|
489 else |
|
490 { |
|
491 aSymbolName = new char[aCurrentPos+1]; |
|
492 strncpy(aSymbolName, iLine+ iOffset, aCurrentPos); |
|
493 aSymbolName[aCurrentPos] = '\0'; |
|
494 } |
|
495 iSymbol->SymbolName(aSymbolName); |
|
496 |
|
497 IncrOffset(aCurrentPos); |
|
498 |
|
499 if(IsWhiteSpace((iLine + iOffset), aCurrentPos)) |
|
500 { |
|
501 IncrOffset(aCurrentPos); |
|
502 } |
|
503 |
|
504 if(*(iLine+iOffset) == '@') |
|
505 { |
|
506 SetState(EAtSymbol); |
|
507 IncrOffset(1); |
|
508 } |
|
509 else |
|
510 { |
|
511 /* |
|
512 * The first non-whitespace entry in a line is assumed to be the |
|
513 * symbol name and a symbol name might also have a '@' char. Hence |
|
514 * there MUST be a whitespace between symbol name and '@'. |
|
515 */ |
|
516 throw DEFFileError(ATRATEMISSING,iFileName,iLineNum,(iLine+iOffset)); |
|
517 } |
|
518 } |
|
519 break; |
|
520 |
|
521 case EAtSymbol: |
|
522 if(IsWhiteSpace((iLine + iOffset), aCurrentPos)) |
|
523 { |
|
524 IncrOffset(aCurrentPos); |
|
525 } |
|
526 |
|
527 SetState(EOrdinal); |
|
528 break; |
|
529 case EOrdinal: |
|
530 { |
|
531 if(!IsDigit(iLine+iOffset, aCurrentPos ) ) |
|
532 { |
|
533 throw DEFFileError(ORDINALNOTANUMBER, iFileName, iLineNum, (iLine+iOffset)); |
|
534 } |
|
535 char aTmp[32]; |
|
536 strncpy(aTmp, iLine+iOffset, aCurrentPos); |
|
537 aTmp[aCurrentPos] = '\0'; |
|
538 int aOrdinal = atoi(aTmp); |
|
539 iSymbol->SetOrdinal(aOrdinal); |
|
540 |
|
541 IncrOffset(aCurrentPos); |
|
542 |
|
543 if(IsWhiteSpace((iLine + iOffset), aCurrentPos)) |
|
544 { |
|
545 IncrOffset(aCurrentPos); |
|
546 } |
|
547 SetState(EOptionals); |
|
548 } |
|
549 break; |
|
550 |
|
551 case EOptionals: |
|
552 { |
|
553 int aPrevPatternIndex, aPatternIdx = 0; |
|
554 aPrevPatternIndex = -1; |
|
555 while (*(iLine + iOffset) != '\n' || *(iLine + iOffset) != '\r') |
|
556 { |
|
557 if(IsPattern(iLine+iOffset, aCurrentPos, aPatternIdx) ) |
|
558 { |
|
559 switch(aPatternIdx) |
|
560 { |
|
561 case DEF_NONAME: |
|
562 break; |
|
563 case DEF_DATA: |
|
564 iSymbol->CodeDataType(SymbolTypeData); |
|
565 |
|
566 IncrOffset(aCurrentPos); |
|
567 if(IsWhiteSpace((iLine + iOffset), aCurrentPos)) |
|
568 { |
|
569 IncrOffset(aCurrentPos); |
|
570 } |
|
571 if(IsDigit(iLine+iOffset, aCurrentPos ) ) |
|
572 { |
|
573 char aSymSz[16]; |
|
574 strncpy(aSymSz, (iLine + iOffset), aCurrentPos); |
|
575 aSymSz[aCurrentPos] = '\0'; |
|
576 iSymbol->SetSymbolSize(atoi(aSymSz)); |
|
577 } |
|
578 break; |
|
579 case DEF_R3UNUSED: |
|
580 iSymbol->R3Unused(true); |
|
581 break; |
|
582 case DEF_ABSENT: |
|
583 iSymbol->SetAbsent(true); |
|
584 break; |
|
585 default: |
|
586 break; |
|
587 } |
|
588 |
|
589 /* |
|
590 * NONAME , DATA, R3UNUSED and ABSENT, all the 3 are optional. But, if more than |
|
591 * one of them appear, they MUST appear in that order. |
|
592 * Else, it is not accepted. |
|
593 */ |
|
594 if( aPrevPatternIndex >= aPatternIdx) |
|
595 { |
|
596 throw DEFFileError(UNRECOGNIZEDTOKEN, iFileName, iLineNum,(iLine + iOffset)); |
|
597 } |
|
598 aPrevPatternIndex = aPatternIdx; |
|
599 |
|
600 IncrOffset(aCurrentPos); |
|
601 |
|
602 if(IsWhiteSpace((iLine + iOffset), aCurrentPos)) |
|
603 { |
|
604 IncrOffset(aCurrentPos); |
|
605 } |
|
606 } |
|
607 else |
|
608 { |
|
609 if( *(iLine + iOffset) == ';' ) |
|
610 { |
|
611 SetState(EComment); |
|
612 IncrOffset(1); |
|
613 return; |
|
614 } |
|
615 else if( *(iLine + iOffset) == '\0' || |
|
616 *(iLine + iOffset) == '\r' || |
|
617 *(iLine + iOffset) == '\n') |
|
618 { |
|
619 SetState(EFinalState); |
|
620 return; |
|
621 } |
|
622 else |
|
623 { |
|
624 throw DEFFileError(UNRECOGNIZEDTOKEN, iFileName, iLineNum,(iLine + iOffset)); |
|
625 } |
|
626 } |
|
627 } |
|
628 } |
|
629 break; |
|
630 |
|
631 case EComment: |
|
632 { |
|
633 if(IsWhiteSpace(iLine + iOffset, aCurrentPos)) |
|
634 { |
|
635 IncrOffset(aCurrentPos); |
|
636 } |
|
637 |
|
638 |
|
639 int aLen = strlen(iLine + iOffset); |
|
640 if( *(iLine + iOffset + aLen - 1 ) == '\n' || *(iLine + iOffset + aLen - 1 ) == '\r') |
|
641 aLen -=1; |
|
642 |
|
643 char * aComment = new char[ aLen + 1]; |
|
644 strncpy( aComment, iLine + iOffset, aLen); |
|
645 aComment[aLen] = '\0'; |
|
646 |
|
647 IncrOffset(aLen); |
|
648 |
|
649 iSymbol->Comment(aComment); |
|
650 SetState(EFinalState); |
|
651 } |
|
652 break; |
|
653 |
|
654 case EFinalState: |
|
655 return; |
|
656 default: |
|
657 break; |
|
658 } |
|
659 } |
|
660 |
|
661 /** |
|
662 This function returns true if the string starts with one |
|
663 of the fixed patterns. |
|
664 It also updates the length and index of this pattern. |
|
665 @param aChar - Line Token |
|
666 @param aTill - Length of the pattern |
|
667 @param aTill - Index of the pattern |
|
668 Return Value - True, if the string starts with one of the patterns. |
|
669 @internalComponent |
|
670 @released |
|
671 */ |
|
672 bool LineToken::IsPattern(char* aStr, int& aTill, int& aIndex) |
|
673 { |
|
674 int pos = 0; |
|
675 int aLength; |
|
676 int size = sizeof(DefFilePatterns)/sizeof(char*); |
|
677 while(size > pos) |
|
678 { |
|
679 aLength = strlen(DefFilePatterns[pos]); |
|
680 if(!strncmp(aStr, DefFilePatterns[pos], aLength)) |
|
681 { |
|
682 aTill = aLength; |
|
683 aIndex = pos; |
|
684 return true; |
|
685 } |
|
686 pos++; |
|
687 } |
|
688 return false; |
|
689 } |
|
690 |
|
691 /** |
|
692 This function returns true if the string starts with digits. |
|
693 It also updates the length of this digit string. |
|
694 @param aChar - Line Token |
|
695 @param aTill - Length of the digit string |
|
696 Return Value - True, if the string starts with digit(s) |
|
697 @internalComponent |
|
698 @released |
|
699 */ |
|
700 bool LineToken::IsDigit(char *aChar, int &aTill) |
|
701 { |
|
702 int pos = 0; |
|
703 if( aChar[pos] - '0' >= 0 && aChar[pos] - '0' <= 9) |
|
704 { |
|
705 pos++; |
|
706 while(aChar[pos] - '0' >= 0 && aChar[pos] - '0' <= 9) |
|
707 { |
|
708 pos++; |
|
709 } |
|
710 aTill = pos; |
|
711 return true; |
|
712 } |
|
713 else |
|
714 { |
|
715 return false; |
|
716 } |
|
717 } |
|
718 |
|
719 /** |
|
720 This function returns true if the string starts with white space. |
|
721 It also updates the length of this white string! |
|
722 @param aStr - Line Token |
|
723 @param aTill - Length of the white string |
|
724 Return Value - True, if the string starts with whitespace |
|
725 @internalComponent |
|
726 @released |
|
727 */ |
|
728 bool LineToken::IsWhiteSpace(char *aStr, int &aTill) |
|
729 { |
|
730 int pos = 0; |
|
731 switch( aStr[pos] ) |
|
732 { |
|
733 case ' ': |
|
734 case '\t': |
|
735 break; |
|
736 default: |
|
737 return false; |
|
738 } |
|
739 |
|
740 pos++; |
|
741 while( aStr[pos]) |
|
742 { |
|
743 switch(aStr[pos]) |
|
744 { |
|
745 case ' ': |
|
746 case '\t': |
|
747 pos++; |
|
748 break; |
|
749 default: |
|
750 aTill = pos; |
|
751 return true; |
|
752 } |
|
753 |
|
754 } |
|
755 aTill = pos; |
|
756 return true; |
|
757 } |
|
758 |
|
759 /** |
|
760 This function returns true if the string starts with non-whitespace. |
|
761 It also updates the length of this word. |
|
762 @param aStr - Line Token |
|
763 @param aTill - Length of the word |
|
764 Return Value - True, if the string starts with non-whitespace chars. |
|
765 It also updates the length of the word. |
|
766 @internalComponent |
|
767 @released |
|
768 */ |
|
769 bool LineToken::IsWord(char *aStr, int &aTill) |
|
770 { |
|
771 int pos = 0; |
|
772 switch( aStr[pos] ) |
|
773 { |
|
774 case '\0': |
|
775 case ' ': |
|
776 case '\t': |
|
777 case '\r': |
|
778 case '\n': |
|
779 return false; |
|
780 default: |
|
781 break; |
|
782 } |
|
783 |
|
784 pos++; |
|
785 while( aStr[pos]) |
|
786 { |
|
787 switch(aStr[pos]) |
|
788 { |
|
789 case ' ': |
|
790 case '\t': |
|
791 case '\r': |
|
792 case '\n': |
|
793 aTill = pos; |
|
794 return true; |
|
795 default: |
|
796 pos++; |
|
797 break; |
|
798 } |
|
799 |
|
800 } |
|
801 aTill = pos; |
|
802 return true; |
|
803 } |
|
804 |
|
805 /** |
|
806 This function increments the current offset. |
|
807 @param aOff - increment by this value |
|
808 @internalComponent |
|
809 @released |
|
810 */ |
|
811 void LineToken::IncrOffset(int aOff) |
|
812 { |
|
813 iOffset += aOff; |
|
814 } |
|
815 |
|
816 /** |
|
817 This function sets the state of the tokenizer that is parsing |
|
818 the line. |
|
819 @param aState - next state |
|
820 @internalComponent |
|
821 @released |
|
822 */ |
|
823 void LineToken::SetState(DefStates aState) |
|
824 { |
|
825 iState = aState; |
|
826 } |
|
827 |
|
828 /** |
|
829 Function to Read def file and get the internal representation in structure. |
|
830 @param defFile - DEF File name |
|
831 @internalComponent |
|
832 @released |
|
833 */ |
|
834 SymbolList* DefFile::ReadDefFile(char *defFile) |
|
835 { |
|
836 char *defFileEntries; |
|
837 |
|
838 defFileEntries=OpenDefFile(defFile); |
|
839 ParseDefFile(defFileEntries); |
|
840 |
|
841 delete [] defFileEntries;//Free the memory which was required to read def file |
|
842 |
|
843 return iSymbolList; |
|
844 |
|
845 } |
|
846 |
|
847 /** |
|
848 Function to get the internal representation of Def File. |
|
849 @param defFile - DEF File name |
|
850 @internalComponent |
|
851 @released |
|
852 */ |
|
853 SymbolList* DefFile::GetSymbolEntryList(char *defFile) |
|
854 { |
|
855 if(iSymbolList) |
|
856 { |
|
857 return iSymbolList; |
|
858 } |
|
859 else |
|
860 { |
|
861 iSymbolList=ReadDefFile(defFile); |
|
862 return iSymbolList; |
|
863 } |
|
864 |
|
865 } |
|
866 |
|
867 /** |
|
868 Function to write DEF file from symbol entry List. |
|
869 @param fileName - Def file name |
|
870 @param newSymbolList - pointer to SymbolList which we get as an input for writing in DEF File |
|
871 @internalComponent |
|
872 @released |
|
873 */ |
|
874 void DefFile::WriteDefFile(char *fileName, SymbolList * newSymbolList) |
|
875 { |
|
876 |
|
877 char ordinal[6]; |
|
878 int newDefEntry=0; |
|
879 FILE *fptr; |
|
880 |
|
881 if((fptr=fopen(fileName,"wb"))==NULL) |
|
882 { |
|
883 throw FileError(FILEOPENERROR,fileName); |
|
884 } |
|
885 else |
|
886 { |
|
887 SymbolList::iterator aItr = newSymbolList->begin(); |
|
888 SymbolList::iterator last = newSymbolList->end(); |
|
889 Symbol *aSym; |
|
890 |
|
891 fputs("EXPORTS",fptr); |
|
892 fputs("\r\n",fptr); |
|
893 while( aItr != last) |
|
894 { |
|
895 aSym = *aItr; |
|
896 //Do not write now if its a new entry |
|
897 if(aSym->GetSymbolStatus()==New) |
|
898 { |
|
899 newDefEntry=1; |
|
900 aItr++; |
|
901 continue; |
|
902 } |
|
903 |
|
904 //Make it comment if its missing def entry |
|
905 if(aSym->GetSymbolStatus()==Missing) |
|
906 fputs("; MISSING:",fptr); |
|
907 |
|
908 fputs("\t",fptr); |
|
909 if((aSym->ExportName()) && strcmp(aSym->SymbolName(),aSym->ExportName())!=0) |
|
910 { |
|
911 fputs(aSym->ExportName(),fptr); |
|
912 fputs("=",fptr); |
|
913 } |
|
914 fputs(aSym->SymbolName(),fptr); |
|
915 fputs(" @ ",fptr); |
|
916 sprintf(ordinal,"%d",aSym->OrdNum()); |
|
917 fputs(ordinal,fptr); |
|
918 fputs(" NONAME",fptr); |
|
919 if(aSym->CodeDataType()==SymbolTypeData) { |
|
920 fputs(" DATA",fptr); |
|
921 fputs(" ",fptr); |
|
922 char aSymSize[16]; |
|
923 sprintf(aSymSize, "%d", aSym->SymbolSize()); |
|
924 fputs(aSymSize,fptr); |
|
925 } |
|
926 if(aSym->R3unused()) |
|
927 fputs(" R3UNUSED",fptr); |
|
928 if(aSym->Absent()) |
|
929 fputs(" ABSENT",fptr); |
|
930 |
|
931 if(aSym->Comment()!=NULL) |
|
932 { |
|
933 fputs(" ; ",fptr); |
|
934 fputs(aSym->Comment(),fptr); |
|
935 } |
|
936 fputs("\r\n",fptr); |
|
937 aItr++; |
|
938 } |
|
939 |
|
940 //This is for writing new def entry in DEF File |
|
941 if(newDefEntry) |
|
942 { |
|
943 fputs("; NEW:",fptr); |
|
944 fputs("\r\n",fptr); |
|
945 aItr = newSymbolList->begin(); |
|
946 last = newSymbolList->end(); |
|
947 |
|
948 while( aItr != last) |
|
949 { |
|
950 aSym = *aItr; |
|
951 if(aSym->GetSymbolStatus()!=New) |
|
952 { |
|
953 aItr++; |
|
954 continue; |
|
955 } |
|
956 fputs("\t",fptr); |
|
957 if((aSym->ExportName()) && strcmp(aSym->SymbolName(),aSym->ExportName())!=0) |
|
958 { |
|
959 fputs(aSym->ExportName(),fptr); |
|
960 fputs("=",fptr); |
|
961 } |
|
962 fputs(aSym->SymbolName(),fptr); |
|
963 fputs(" @ ",fptr); |
|
964 sprintf(ordinal,"%d",aSym->OrdNum()); |
|
965 fputs(ordinal,fptr); |
|
966 fputs(" NONAME",fptr); |
|
967 |
|
968 if(aSym->CodeDataType()==SymbolTypeData) { |
|
969 fputs(" DATA",fptr); |
|
970 fputs(" ",fptr); |
|
971 char aSymSize[16]; |
|
972 sprintf(aSymSize, "%d", aSym->SymbolSize()); |
|
973 fputs(aSymSize,fptr); |
|
974 } |
|
975 |
|
976 if(aSym->R3unused()) |
|
977 fputs(" R3UNUSED",fptr); |
|
978 if(aSym->Absent()) |
|
979 fputs(" ABSENT",fptr); |
|
980 |
|
981 if(aSym->Comment()!=NULL) |
|
982 { |
|
983 if(aSym->CodeDataType()!=SymbolTypeCode && |
|
984 aSym->CodeDataType()!=SymbolTypeData) |
|
985 { |
|
986 fputs(" ; ",fptr); |
|
987 fputs(aSym->Comment(),fptr); |
|
988 } |
|
989 else |
|
990 { |
|
991 fputs(" ",fptr); |
|
992 fputs(aSym->Comment(),fptr); |
|
993 } |
|
994 } |
|
995 fputs("\r\n",fptr); |
|
996 aItr++; |
|
997 } |
|
998 } |
|
999 fputs("\r\n",fptr); |
|
1000 fclose(fptr); |
|
1001 } |
|
1002 } |