/[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 872 - (show annotations)
Tue Sep 25 22:43:47 2012 UTC (7 years, 4 months ago) by mmu_man
File size: 15481 byte(s)
POSIXify common/

* define O_BINARY on platforms which don't define it
* include <curses.h> on *nix to have a usable getch()
* use real POSIX functions instead of _-prefixed win32 versions
* use strncasecmp() instead of nonstandard memicmp()
* use stat() instead of _findfirst() since we don't even use the globbed result anyway

This now builds both for linux and mingw32.

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

  ViewVC Help
Powered by ViewVC 1.1.26