/[projet1]/public/pc/tools/osdk/main/common/sources/common.cpp
Defence Force logotype

Contents of /public/pc/tools/osdk/main/common/sources/common.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1132 - (show annotations)
Sun May 11 09:59:38 2014 UTC (5 years, 6 months ago) by dbug
File size: 17774 byte(s)
Header 0.2 - 2014/05/11
- The address can now be specified with either $ or 0x as an hexadecimal prefix

1
2
3 #include "common.h"
4
5 #include <memory.h>
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <cctype>
9 #ifdef WIN32
10 /* for getch() */
11 #include <conio.h>
12 #else
13 /* for getch() */
14 #include <curses.h>
15 #endif
16 #include <stdio.h>
17 #include <fcntl.h>
18 #include <sys/stat.h>
19 #include <stdarg.h>
20
21 #include <assert.h>
22
23 static std::string g_cApplicationName;
24 static std::string g_cUsageMessage;
25 static std::string g_cVersionString;
26 static int g_nVersionMajor;
27 static int g_nVersionMinor;
28
29
30 void SetApplicationParameters(const char* pcApplicationName,int nVersionMajor,int nVersionMinor,const char* pcUsageMessage)
31 {
32 g_cApplicationName=pcApplicationName;
33
34 g_nVersionMajor=nVersionMajor;
35 g_nVersionMinor=nVersionMinor;
36 char cTempBuffer[256];
37 sprintf(cTempBuffer,"%d.%03d",nVersionMajor,nVersionMinor);
38 g_cVersionString=cTempBuffer;
39
40 g_cUsageMessage=pcUsageMessage;
41 }
42
43
44
45 void ShowError(const char *pFormatString,...)
46 {
47 std::string cErrorMessage;
48
49 if (pFormatString)
50 {
51 // Message will be something like: "MyApplication.exe: Something goes wrong, sorry !"
52
53 va_list va;
54 char temp[4096];
55
56 va_start(va,pFormatString);
57 int nChar=vsprintf(temp,pFormatString,va);
58 va_end(va);
59 if ((unsigned int)nChar>=sizeof(temp))
60 {
61 temp[sizeof(temp)-1]=0;
62 }
63
64 cErrorMessage=g_cApplicationName+": "+ temp;
65 }
66 else
67 {
68 cErrorMessage=g_cUsageMessage;
69 StringReplace(cErrorMessage,"{ApplicationName}" ,g_cApplicationName);
70 StringReplace(cErrorMessage,"{ApplicationVersion}" ,g_cVersionString);
71 }
72
73 // Show the resulting message on screen
74 printf("\r\n%s\r\n",cErrorMessage.c_str());
75 getch();
76 exit(1);
77 }
78
79
80
81 bool LoadFile(const char* pcFileName,void* &pcBuffer,size_t &cBufferSize)
82 {
83 // get the size of the file
84 struct stat file_info;
85
86 if (stat(pcFileName, &file_info)== -1)
87 {
88 return false;
89 }
90
91 // open the file
92 cBufferSize=file_info.st_size;
93 int nHandle=open(pcFileName,O_BINARY|O_RDONLY,0);
94 if (nHandle==-1)
95 {
96 return false;
97 }
98
99 // allocate some memory
100 pcBuffer=malloc(cBufferSize+1);
101 if (!pcBuffer)
102 {
103 return false;
104 }
105
106 // read file content
107 if (read(nHandle,pcBuffer,cBufferSize)!=(int)cBufferSize)
108 {
109 free(pcBuffer);
110 return false;
111 }
112 close(nHandle);
113
114 // Add a null terminator in the additional byte
115 char *pcCharBuffer=(char*)pcBuffer;
116 pcCharBuffer[cBufferSize]=0;
117
118 return true;
119 }
120
121
122 bool SaveFile(const char* pcFileName,const void* pcBuffer,size_t cBufferSize)
123 {
124 // Open file
125 int nHandle=open(pcFileName,O_BINARY|O_WRONLY|O_TRUNC|O_CREAT,S_IREAD|S_IWRITE);
126 if (nHandle==-1)
127 {
128 return false;
129 }
130
131 // Save data
132 if (write(nHandle,pcBuffer,cBufferSize)!=(int)cBufferSize)
133 {
134 close(nHandle);
135 return false;
136 }
137
138 // close handle
139 close(nHandle);
140
141 return true;
142 }
143
144 bool DeleteFile(const char* pcFileName)
145 {
146 return unlink(pcFileName)==0;
147 }
148
149
150 /**
151 * Transforms a raw ascii buffer (0 terminated)
152 * into a vector of string where each string
153 * contains one line of the original buffer.
154 *
155 * Compute the lenght of the longest line during
156 * the process
157 */
158 bool LoadText(const char* pcFileName,std::vector<std::string>& cTextData)
159 {
160 cTextData.clear();
161
162 void* ptr_buffer_void;
163 size_t file_size;
164 if (!LoadFile(pcFileName,ptr_buffer_void,file_size))
165 {
166 return false;
167 }
168
169 const char *ptr_line=(const char *)ptr_buffer_void;
170 const char *ptr_read=ptr_line;
171
172 bool flag_new_line=true;
173
174 int line_count=0;
175 int longest_line=0;
176
177 while (1)
178 {
179 char car=*ptr_read++;
180 switch (car)
181 {
182 case 0:
183 case 0x0D:
184 case 0x0A:
185 {
186 //
187 // Find a end of line.
188 // Patch it with a "0"
189 // and insert the line in the container
190 //
191 int size_line=ptr_read-ptr_line-1;
192 std::string new_line(ptr_line,size_line);
193 cTextData.push_back(new_line);
194
195 line_count++;
196
197 if (size_line>longest_line)
198 {
199 longest_line=size_line;
200 }
201
202 if (!car)
203 {
204 //
205 // Finished parsing
206 //
207 free(ptr_buffer_void);
208 return true;
209 }
210 if ( (car==0x0D) && ((*ptr_read)==0x0A) )
211 {
212 // If we have a \r\n sequence, we skip the \n
213 ptr_read++;
214 }
215 ptr_line=ptr_read;
216 flag_new_line=true;
217 }
218 break;
219
220 default:
221 flag_new_line=false;
222 break;
223 }
224
225 /*
226 switch (car)
227 {
228 case 0:
229 case 0x0D:
230 {
231 //
232 // Find a end of line.
233 // Patch it with a "0"
234 // and insert the line in the container
235 //
236 int size_line=ptr_read-ptr_line-1;
237 std::string new_line(ptr_line,size_line);
238 cTextData.push_back(new_line);
239
240 line_count++;
241
242 if (size_line>longest_line)
243 {
244 longest_line=size_line;
245 }
246
247 if (!car)
248 {
249 //
250 // Finished parsing
251 //
252 free(ptr_buffer_void);
253 return true;
254 }
255 ptr_line=ptr_read;
256 flag_new_line=true;
257 }
258 break;
259
260 case 0x0A:
261 if (flag_new_line)
262 {
263 //
264 // Skip leading 0x0A
265 //
266 ptr_line++;
267 }
268 break;
269
270 default:
271 flag_new_line=false;
272 break;
273 }
274 */
275 }
276 }
277
278 bool IsUpToDate(const char* sourceFile,const char* targetFile)
279 {
280 struct stat sourceFileInfo;
281 struct stat targetFileInfo;
282
283 if (stat(sourceFile,&sourceFileInfo)== -1)
284 {
285 return false;
286 }
287 if (stat(targetFile,&targetFileInfo)== -1)
288 {
289 return false;
290 }
291 return (targetFileInfo.st_mtime >= sourceFileInfo.st_mtime);
292 }
293
294 bool IsUpToDate(const std::string& sourceFile,const std::string& targetFile)
295 {
296 return IsUpToDate(sourceFile.c_str(),targetFile.c_str());
297 }
298
299
300 int StringReplace(std::string& cMainString,const std::string& cSearchedString,const std::string& cReplaceString)
301 {
302 int nReplaceCount=0;
303 std::string::size_type pos=0;
304 while (1)
305 {
306 pos=cMainString.find(cSearchedString,pos);
307 if (pos==std::string::npos)
308 {
309 break;
310 }
311 cMainString.replace(pos,cSearchedString.size(),cReplaceString);
312 pos+=cReplaceString.size();
313 ++nReplaceCount;
314 }
315 return nReplaceCount;
316 }
317
318 std::string StringTrim(const std::string& cInputString,const std::string& cFilteredOutCharacterList)
319 {
320 size_t nStartPos=cInputString.find_first_not_of(cFilteredOutCharacterList);
321 if (nStartPos!=std::string::npos)
322 {
323 size_t nEndPos=cInputString.find_last_not_of(cFilteredOutCharacterList);
324 if (nEndPos!=std::string::npos)
325 {
326 return cInputString.substr(nStartPos,(nEndPos-nStartPos)+1);
327 }
328 }
329 // Returns an empty string: This case means that basically the input string contains ONLY characters that needed to be filtered out
330 return "";
331 }
332
333 std::string StringMakeLabel(const std::string& sourceString)
334 {
335 std::string cleanString;
336 for (auto it(sourceString.begin());it!=sourceString.end();it++)
337 {
338 char car=*it;
339 if ( (car>32) && (car<128) && (std::isalpha(car) || std::isdigit(car) ) )
340 {
341 cleanString.push_back(car);
342 }
343 else
344 {
345 cleanString.push_back('_');
346 }
347 }
348
349 return cleanString;
350 }
351
352
353 ArgumentParser::ArgumentParser(int argc,char *argv[]) :
354 m_argc(argc),
355 m_argv(argv),
356 m_first_param(1),
357 m_nb_arg(-1),
358 m_remaining_argc(argc)
359 {
360 assert(argc>=1);
361
362 // We do not count the implicit first parameter (application name) in the parameter count
363 m_remaining_argc--;
364 }
365
366 const char* ArgumentParser::GetParameter(int nParameterIndex)
367 {
368 int nIndex=m_first_param+nParameterIndex;
369 if (nIndex>=m_argc)
370 {
371 // Wrong !
372 return "";
373 }
374 return m_argv[nIndex];
375 }
376
377 int ArgumentParser::GetParameterCount()
378 {
379 return m_remaining_argc;
380 }
381
382 bool ArgumentParser::ProcessNextArgument()
383 {
384 if ((!m_remaining_argc) || (m_nb_arg==m_remaining_argc))
385 {
386 // No more arguments
387 return false;
388 }
389
390 m_nb_arg =m_remaining_argc;
391 m_ptr_arg =m_argv[m_first_param];
392
393 return true;
394 }
395
396 bool ArgumentParser::IsSwitch(const char *ptr_switch)
397 {
398 if (!::get_switch(m_ptr_arg,ptr_switch))
399 {
400 return false;
401 }
402 m_first_param++;
403 m_remaining_argc--;
404 return true;
405 }
406
407 bool ArgumentParser::IsParameter()
408 {
409 if (!m_ptr_arg)
410 {
411 return false;
412 }
413 char cCar=*m_ptr_arg;
414 if ((!cCar) || (cCar=='-'))
415 {
416 return false;
417 }
418
419 m_first_param++;
420 m_remaining_argc--;
421 return true;
422 }
423
424
425 std::string ArgumentParser::GetStringValue()
426 {
427 return ::get_string(m_ptr_arg);
428 }
429
430 int ArgumentParser::GetIntegerValue(int default_value)
431 {
432 return ::get_value(m_ptr_arg,default_value);
433 }
434
435 bool ArgumentParser::GetBooleanValue(bool default_value)
436 {
437 int nValue;
438 if (default_value) nValue=1;
439 else nValue=0;
440 nValue=::get_value(m_ptr_arg,nValue);
441 if (nValue) return true;
442 else return false;
443 }
444
445 bool ArgumentParser::GetSeparator(const char* ptr_separator_list)
446 {
447 while (*ptr_separator_list)
448 {
449 if (*m_ptr_arg==*ptr_separator_list)
450 {
451 m_ptr_arg++;
452 return true;
453 }
454 ptr_separator_list++;
455 }
456 return false;
457 }
458
459 const char* ArgumentParser::GetRemainingStuff()
460 {
461 return m_ptr_arg;
462 }
463
464
465
466 bool get_switch(const char *&ptr_arg,const char *ptr_switch)
467 {
468 int lenght=strlen(ptr_switch);
469
470 if ((!ptr_arg) || strncasecmp(ptr_arg,ptr_switch,lenght))
471 {
472 // Not a match
473 return false;
474 }
475 // Validate the parameter
476 ptr_arg+=lenght;
477 return true;
478 }
479
480 std::string get_string(const char *&ptr_arg)
481 {
482 if (!ptr_arg) return 0;
483 std::string cStringValue=std::string(ptr_arg);
484 ptr_arg+=cStringValue.size();
485 return cStringValue;
486 }
487
488 int get_value(const char *&ptr_arg,long default_value)
489 {
490 char*ptr_end;
491 long value;
492
493 if (!ptr_arg) return 0;
494 value=strtoul(ptr_arg,&ptr_end,10);
495 if (ptr_arg==ptr_end)
496 {
497 value=default_value;
498 }
499 ptr_arg=ptr_end;
500 return value;
501 }
502
503
504
505 int ConvertAdress(const char *ptr_value)
506 {
507 int adress;
508 int base;
509 char car;
510
511 if (ptr_value[0]=='$')
512 {
513 // Hexadecimal (Assembler style)
514 base=16;
515 ptr_value++;
516 }
517 else
518 if ( (ptr_value[0]=='0') && (ptr_value[1]=='x') )
519 {
520 // Hexadecimal (C style)
521 base=16;
522 ptr_value+=2;
523 }
524 else
525 {
526 // Decimal
527 base=10;
528 }
529
530 adress=0;
531 while (car=*ptr_value++)
532 {
533 if ((car>='0') && (car<='9'))
534 {
535 adress*=base;
536 adress+=car-'0';
537 }
538 else
539 if ((car>='a') && (car<='f'))
540 {
541 if (base!=16)
542 {
543 ShowError("Only hexadecimal values prefixed by a '$' can contain letters");
544 }
545 adress*=base;
546 adress+=car-'a'+10;
547 }
548 else
549 if ((car>='A') && (car<='F'))
550 {
551 if (base!=16)
552 {
553 ShowError("Only hexadecimal values prefixed by a '$' can contain letters");
554 }
555 adress*=base;
556 adress+=car-'A'+10;
557 }
558 else
559 {
560 ShowError("Unknow character in the adress value");
561 }
562 }
563
564 if ((adress<0x0000) || (adress>0xFFFF))
565 {
566 ShowError("authorized adress range is $0000 to $FFFF");
567 }
568
569 return adress;
570 }
571
572
573 std::string StringFormat(const char* pFormatString,...)
574 {
575 va_list va;
576 char temp[4096];
577
578 va_start(va,pFormatString);
579 int nChar=vsprintf(temp,pFormatString,va);
580 va_end(va);
581 if ((unsigned int)nChar>=sizeof(temp))
582 {
583 temp[sizeof(temp)-1]=0;
584 }
585 return std::string(temp);
586 }
587
588
589
590
591
592 class DataReader
593 {
594 public:
595 DataReader();
596 ~DataReader();
597
598 void SetPointer(const void* ptr);
599 const void *GetPointer();
600
601 void SetEndian(bool bIsBigEndian);
602 bool GetEndian();
603
604 unsigned int GetValue(int nSizeValue);
605
606 private:
607 const void* m_ptr;
608 bool m_bReadBigEndian;
609 };
610
611 DataReader::DataReader() :
612 m_ptr(0),
613 m_bReadBigEndian(false)
614 {
615 }
616
617 DataReader::~DataReader()
618 {
619 }
620
621 void DataReader::SetPointer(const void* ptr)
622 {
623 m_ptr=ptr;
624 }
625
626 const void *DataReader::GetPointer()
627 {
628 return m_ptr;
629 }
630
631 void DataReader::SetEndian(bool bIsBigEndian)
632 {
633 m_bReadBigEndian=bIsBigEndian;
634 }
635
636 bool DataReader::GetEndian()
637 {
638 return m_bReadBigEndian;
639 }
640
641 unsigned int DataReader::GetValue(int nSizeValue)
642 {
643 unsigned int nvalue=0;
644 unsigned char* ptr=(unsigned char*)m_ptr;
645
646 if (m_bReadBigEndian)
647 {
648 // Big endian
649 // msb...lsb
650 switch (nSizeValue)
651 {
652 case 1:
653 nvalue|=(ptr[0]<<0);
654 break;
655
656 case 2:
657 nvalue|=(ptr[1]<<0);
658 nvalue|=(ptr[0]<<8);
659 break;
660
661 case 4:
662 nvalue|=(ptr[3]<<0);
663 nvalue|=(ptr[2]<<8);
664 nvalue|=(ptr[1]<<16);
665 nvalue|=(ptr[0]<<24);
666 }
667 }
668 else
669 {
670 // Little endian
671 // lsb...msb
672 switch (nSizeValue)
673 {
674 case 1:
675 nvalue|=(ptr[0]<<0);
676 break;
677
678 case 2:
679 nvalue|=(ptr[0]<<0);
680 nvalue|=(ptr[1]<<8);
681 break;
682
683 case 4:
684 nvalue|=(ptr[0]<<0);
685 nvalue|=(ptr[1]<<8);
686 nvalue|=(ptr[2]<<16);
687 nvalue|=(ptr[3]<<24);
688 }
689 }
690
691 ptr+=nSizeValue;
692 m_ptr=(void*)ptr;
693 return nvalue;
694 }
695
696
697
698
699 TextFileGenerator::TextFileGenerator() :
700 m_nDataSize(1),
701 m_nFileType(_eLanguage_Undefined_),
702 m_nEndianness(_eEndianness_Little),
703 m_nNumericBase(_eNumericBase_Hexadecimal),
704 m_nValuesPerLine(16),
705 m_bEnableLineNumber(false),
706 m_nFirstLineNumber(10),
707 m_nIncrementLineNumber(10),
708 m_cLabelName("DefaultLabelName")
709 {
710 }
711
712 TextFileGenerator::~TextFileGenerator()
713 {
714 }
715
716
717 std::string TextFileGenerator::ConvertData(const void* pSourceData,size_t nFileSize)
718 {
719 std::string cDestString;
720
721 if ( ((nFileSize/m_nDataSize)*m_nDataSize)!=nFileSize)
722 {
723 ShowError("The filesize must be a multiple of the data size.");
724 }
725
726 DataReader cDataReader;
727
728 cDataReader.SetPointer(pSourceData);
729 if (m_nEndianness==_eEndianness_Big)
730 {
731 cDataReader.SetEndian(true);
732 }
733 else
734 {
735 cDataReader.SetEndian(false);
736 }
737
738 std::string cHeaderFormatString;
739 std::string cFooterFormatString;
740 std::string cHeaderPreLine;
741 std::string cEntryFormat;
742 std::string cEntrySeparator;
743
744 bool bAddSeparatorOnEndOfLine=false;
745
746 switch (m_nFileType)
747 {
748 case eLanguage_C:
749 cHeaderPreLine="\t";
750 cEntrySeparator=",";
751 bAddSeparatorOnEndOfLine=true;
752 m_bEnableLineNumber=false;
753 switch (m_nDataSize)
754 {
755 case 1:
756 cHeaderFormatString="unsigned char %s[%d]=\r\n{\r\n"; // unsigned char _SampleQuiTue[]={
757 cEntryFormat="0x%02x";
758 break;
759 case 2:
760 cHeaderFormatString="unsigned short %s[%d]=\r\n{\r\n"; // unsigned short _SampleQuiTue[]={
761 cEntryFormat="0x%04x";
762 break;
763 case 4:
764 cHeaderFormatString="unsigned long %s[%d]=\r\n{\r\n"; // unsigned long _SampleQuiTue[]={
765 cEntryFormat="0x%08x";
766 break;
767 }
768 cFooterFormatString="};";
769 break;
770
771 case eLanguage_Assembler:
772 cHeaderFormatString=m_cLabelName+"\r\n"; // _SampleQuiTue
773 cEntrySeparator=",";
774 m_bEnableLineNumber=false;
775 switch (m_nDataSize)
776 {
777 case 1:
778 cHeaderPreLine="\t.byt ";
779 cEntryFormat="$%02x";
780 break;
781 case 2:
782 cHeaderPreLine="\t.word ";
783 cEntryFormat="$%04x";
784 break;
785 case 4:
786 cHeaderPreLine="\t.long ";
787 cEntryFormat="$%08x";
788 break;
789 }
790 break;
791
792 case eLanguage_BASIC:
793 // Basic supports only uppercase hexadecimal letters !
794 cHeaderFormatString=StringFormat("%d REM %s \r\n",m_nFirstLineNumber,m_cLabelName.c_str()); // nnnn REM _SampleQuiTue
795 m_nFirstLineNumber+=m_nIncrementLineNumber;
796 cHeaderPreLine="DATA ";
797 cEntryFormat="#%d";
798 m_bEnableLineNumber=true;
799 switch (m_nDataSize)
800 {
801 case 1:
802 cEntryFormat="#%02X";
803 break;
804 case 2:
805 cEntryFormat="#%04X";
806 break;
807 case 4:
808 cEntryFormat="#%08X"; // That one will probably fail on most 8 bits basics
809 break;
810 }
811 cEntrySeparator=",";
812 break;
813 }
814
815 if (m_nNumericBase==_eNumericBase_Decimal)
816 {
817 // Set to decimal output
818 cEntryFormat="%d";
819 }
820
821 int file_size=nFileSize;
822 int nEntryCount=(file_size+m_nDataSize-1)/m_nDataSize;
823
824 // To avoid numerous memory allocation, pre allocate a string long enough
825 cDestString="";
826 cDestString.reserve(nFileSize*5);
827
828 // Block header
829 cDestString+=StringFormat(cHeaderFormatString.c_str(),m_cLabelName.c_str(),nEntryCount); // unsigned char _SampleQuiTue[]={
830 while (file_size>0)
831 {
832 // Line numbers
833 if (m_bEnableLineNumber)
834 {
835 cDestString+=StringFormat("%d ",m_nFirstLineNumber);
836 m_nFirstLineNumber+=m_nIncrementLineNumber;
837 }
838
839 // Line header
840 cDestString+=cHeaderPreLine;
841
842 // Content of the line
843 for (unsigned long x=0;x<m_nValuesPerLine;x++)
844 {
845 unsigned long c=cDataReader.GetValue(m_nDataSize);
846 file_size-=m_nDataSize;
847 cDestString+=StringFormat(cEntryFormat.c_str(),c);
848 if ((x!=(m_nValuesPerLine-1)) && file_size)
849 {
850 cDestString+=cEntrySeparator;
851 }
852 if (file_size<=0) break;
853 }
854
855 // Optional last separator (for C)
856 if (bAddSeparatorOnEndOfLine && (file_size>0))
857 {
858 cDestString+=cEntrySeparator;
859 }
860
861 // End of line carriage return
862 cDestString+="\r\n";
863 }
864 // Block footer
865 cDestString+=cFooterFormatString;
866
867 // End of file carriage return
868 cDestString+="\r\n";
869
870 return cDestString;
871 }
872
873

  ViewVC Help
Powered by ViewVC 1.1.26