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

  ViewVC Help
Powered by ViewVC 1.1.26