Add options -h and -version
authorHugo Villeneuve <hugo@hugovil.com>
Wed, 12 May 2004 05:19:56 +0000 (05:19 +0000)
committerHugo Villeneuve <hugo@hugovil.com>
Sun, 8 Sep 2013 22:54:51 +0000 (18:54 -0400)
Merge common function LoadHexFile() to file.c.

doc/emu8051.man
src/EmuConsole.cpp
src/EmuConsole.hpp
src/EmuGtk.cpp
src/EmuGtk.hpp
src/Makefile.am
src/common.h [new file with mode: 0644]
src/file.c [new file with mode: 0644]
src/file.h [new file with mode: 0644]
src/options.c [new file with mode: 0644]
src/options.h [new file with mode: 0644]

index 956d4c9..8b50f42 100644 (file)
@@ -20,7 +20,7 @@ It is written in C++, and uses Perl scripts to generate automatically C++ functi
 \fB\-h\fR
 display usage and exit
 .TP
-\fB\-v\fR
+\fB\-version\fR
 output version information and exit
 
 .SH CREDITS
index 0a0fe66..d28e568 100644 (file)
@@ -1,4 +1,4 @@
-// EmuConsole.cpp
+/* EmuConsole.cpp */
 
 #include <stdio.h>
 #include <iostream>
@@ -9,6 +9,21 @@
 #include "Reg8051.hpp"
 #include "Keyboard.hpp"
 
+extern "C" {
+#include "options.h"
+#include "file.h"
+}
+
+
+EmuConsole *EmuConsolePtr;
+
+
+static void
+cpu_write_pgm( unsigned int Address, unsigned char Value )
+{
+  EmuConsolePtr->CPU->WritePGM( Address, Value );
+}
+
 
 int main( int argc, char **argv )
 {
@@ -26,6 +41,37 @@ int main( int argc, char **argv )
 }
 
 
+unsigned int
+Ascii2Hex_TEMP( string istring, unsigned int length )
+{
+  if ( !length || ( length > istring.size() ) )
+    length = istring.size();
+  
+  if ( istring.empty() )
+    throw MissingParameter();
+  
+  unsigned int result = 0;
+  unsigned int i, ascii_code;
+  for ( i = 0; i < length; i++ ) {
+    ascii_code = istring[ i ];
+    if ( ascii_code > 0x39 )
+      ascii_code &= 0xDF;
+    if ( ( ascii_code >= 0x30 && ascii_code <= 0x39 ) || ( ascii_code >= 0x41 && ascii_code <= 0x46 ) ) {
+      ascii_code -= 0x30;
+      if ( ascii_code > 9 )
+       ascii_code -= 7;
+      result <<= 4;
+      result += ascii_code;
+    }
+    else {
+      throw SyntaxError();
+    }
+  }
+  return result;
+}
+
+
+
 //////////////////////////////////////////////////////////////////////////////
 // EmuConsole::EmuConsole( int argc, char **argv, CPU8051 *mCPU )
 // EmuConsole constructor
@@ -35,7 +81,14 @@ EmuConsole::EmuConsole( int argc, char **argv, CPU8051 *mCPU )
   CPU = mCPU;
   CPU->Reset( );
   NbBreakpoints = 0;
-  if ( argc > 1 ) LoadHexFile( argv[ 1 ] );
+
+  EmuConsolePtr = this;
+
+  ParseCommandLineOptions( argc, argv );
+
+  if( GetHexFileName() != NULL ) {
+    LoadHexFile( GetHexFileName(), cpu_write_pgm );
+  }
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -183,18 +236,18 @@ void EmuConsole::Main( )
          if ( Parameter1.empty() || Parameter2.empty() )
            throw MissingParameter();
          else if ( Command == "ME" ) {
-           unsigned int adresse = Ascii2Hex( Parameter1, 4 );
-           unsigned char valeur = Ascii2Hex( Parameter2, 2 );
+           unsigned int adresse = Ascii2Hex_TEMP( Parameter1, 4 );
+           unsigned char valeur = Ascii2Hex_TEMP( Parameter2, 2 );
            CPU->WriteExt( adresse, valeur );
          }
          else if ( Command == "MI" ) {
-           unsigned char adresse = Ascii2Hex( Parameter1, 2 );
-           unsigned char valeur = Ascii2Hex( Parameter2, 2 );
+           unsigned char adresse = Ascii2Hex_TEMP( Parameter1, 2 );
+           unsigned char valeur = Ascii2Hex_TEMP( Parameter2, 2 );
            CPU->WriteInt( adresse, valeur );
          }
          else if ( Command == "MP" ) {
-           unsigned int adresse = Ascii2Hex( Parameter1, 4 );
-           unsigned char valeur = Ascii2Hex( Parameter2, 2 );
+           unsigned int adresse = Ascii2Hex_TEMP( Parameter1, 4 );
+           unsigned char valeur = Ascii2Hex_TEMP( Parameter2, 2 );
            CPU->WritePGM( adresse, valeur );
          }
          else if ( Command == "MR" )
@@ -215,7 +268,7 @@ void EmuConsole::Main( )
            if ( Parameter1.empty( ) )
              ClearBreakpoint( CPU->GetPC( ) );
            else
-             ClearBreakpoint( Ascii2Hex( Parameter1, 4 ) );
+             ClearBreakpoint( Ascii2Hex_TEMP( Parameter1, 4 ) );
          }
          else
            throw SyntaxError( );
@@ -227,7 +280,7 @@ void EmuConsole::Main( )
            if ( Parameter1.empty( ) )
              SetBreakpoint( CPU->GetPC( ) );
            else
-             SetBreakpoint( Ascii2Hex( Parameter1, 4 ) );
+             SetBreakpoint( Ascii2Hex_TEMP( Parameter1, 4 ) );
          }
          else
            throw SyntaxError( );
@@ -299,7 +352,7 @@ void EmuConsole::Reset( )
 //////////////////////////////////////////////////////////////////////////////
 void EmuConsole::Trace( string Address )
 {
-  if ( !Address.empty( ) ) CPU->SetPC( Ascii2Hex( Address, Address.size( ) ) );
+  if ( !Address.empty( ) ) CPU->SetPC( Ascii2Hex_TEMP( Address, Address.size( ) ) );
   CPU->Exec( );
   ShowRegisters( );
   DisasmN( CPU->GetPC( ), 1 );
@@ -315,10 +368,10 @@ void EmuConsole::Exec( string Address, string NumberInst )
   int NbInst = -1;     // -1 is infinity
   if ( !Address.empty( ) ) {
     Capitalize( &Address );
-    if ( Address != "PC" ) CPU->SetPC( Ascii2Hex( Address, Address.size( ) ) );
+    if ( Address != "PC" ) CPU->SetPC( Ascii2Hex_TEMP( Address, Address.size( ) ) );
   }
 
-  if ( !NumberInst.empty( ) ) NbInst = Ascii2Hex( NumberInst, NumberInst.size( ) );
+  if ( !NumberInst.empty( ) ) NbInst = Ascii2Hex_TEMP( NumberInst, NumberInst.size( ) );
 
   InitUnixKB( );
 
@@ -392,9 +445,9 @@ void EmuConsole::Disasm( string Address, string NumberInst )
   unsigned int MemAddress, NbInst;
   Capitalize( &Address );
   if ( Address.empty( ) || ( Address == "PC" ) ) MemAddress = CPU->GetPC( );
-  else MemAddress = Ascii2Hex( Address, Address.size( ) );
+  else MemAddress = Ascii2Hex_TEMP( Address, Address.size( ) );
   if ( NumberInst.empty( ) ) NumberInst = "10";
-  NbInst = Ascii2Hex( NumberInst, NumberInst.size( ) );
+  NbInst = Ascii2Hex_TEMP( NumberInst, NumberInst.size( ) );
   DisasmN( MemAddress, NbInst );
 }
 
@@ -426,7 +479,7 @@ void EmuConsole::DumpPGM( string Address )
     if ( Address == "PC" )
       MemAddress = CPU->GetPC( );
     else
-      MemAddress = Ascii2Hex( Address, Address.size( ) );
+      MemAddress = Ascii2Hex_TEMP( Address, Address.size( ) );
   }
   for ( Offset = 0; Offset < 256; Offset += 16 ) {
     printf( "%.4X ", MemAddress + Offset );
@@ -456,7 +509,7 @@ void EmuConsole::DumpI( string Address )
   unsigned int MemAddress = 0;
   int Offset, Column;
   unsigned char Byte;
-  if ( !Address.empty( ) ) MemAddress = Ascii2Hex( Address, Address.size( ) );
+  if ( !Address.empty( ) ) MemAddress = Ascii2Hex_TEMP( Address, Address.size( ) );
   for ( Offset = 0; Offset < 256; Offset += 16 ) {
     printf( "%.4X ", MemAddress + Offset );
     for ( Column = 0; Column < 16; Column++ ) 
@@ -482,7 +535,7 @@ void EmuConsole::DumpInt( string Address )
   int Offset, Column;
   unsigned char Byte;
   if ( !Address.empty( ) )
-    MemAddress = Ascii2Hex( Address, 4 );
+    MemAddress = Ascii2Hex_TEMP( Address, 4 );
   for ( Offset = 0; Offset < 256; Offset += 16 ) {
     printf( "%.4X ", MemAddress + Offset );
     for ( Column = 0; Column < 16; Column++ ) 
@@ -509,7 +562,7 @@ void EmuConsole::DumpExt( string Address )
   int Offset, Column;
   unsigned char Byte;
   if ( !Address.empty( ) )
-    MemAddress = Ascii2Hex( Address, 4 );
+    MemAddress = Ascii2Hex_TEMP( Address, 4 );
   for ( Offset = 0; Offset < 256; Offset += 16 ) {
     printf( "%.4X ", MemAddress + Offset );
     for ( Column = 0; Column < 16; Column++ ) 
@@ -534,7 +587,7 @@ void EmuConsole::DumpD( string Address )
   unsigned int MemAddress = 0;
   int Offset, Column;
   unsigned char Byte;
-  if ( !Address.empty( ) ) MemAddress = Ascii2Hex( Address, Address.size( ) );
+  if ( !Address.empty( ) ) MemAddress = Ascii2Hex_TEMP( Address, Address.size( ) );
   for ( Offset = 0; Offset < 256; Offset += 16 ) {
     printf( "%.4X ", MemAddress + Offset );
     for ( Column = 0; Column < 16; Column++ ) 
@@ -557,10 +610,10 @@ void EmuConsole::DumpD( string Address )
 void EmuConsole::SetRegister( string Register, string NewValue )
 {
   Capitalize( &Register );
-  if ( Register == "PC" ) CPU->SetPC( Ascii2Hex( NewValue, 4 ) );
-  else if ( Register == "A" ) CPU->WriteD( _ACC_, Ascii2Hex( NewValue, 2 ) );
-  else if ( Register == "B" ) CPU->WriteD( _B_, Ascii2Hex( NewValue, 2 ) );
-  else if ( Register == "SP" ) CPU->WriteD( _SP_, Ascii2Hex( NewValue, 2 ) );
+  if ( Register == "PC" ) CPU->SetPC( Ascii2Hex_TEMP( NewValue, 4 ) );
+  else if ( Register == "A" ) CPU->WriteD( _ACC_, Ascii2Hex_TEMP( NewValue, 2 ) );
+  else if ( Register == "B" ) CPU->WriteD( _B_, Ascii2Hex_TEMP( NewValue, 2 ) );
+  else if ( Register == "SP" ) CPU->WriteD( _SP_, Ascii2Hex_TEMP( NewValue, 2 ) );
   else throw InvalidRegister( );
 }
 
@@ -617,121 +670,3 @@ void EmuConsole::ShowRegisters( )
   printf( "----------------------------------------------------------------------%s", ENDLINE );
 
 }
-
-//////////////////////////////////////////////////////////////////////////////
-// void EmuConsole::LoadHexFile( string Filename )
-// 
-//////////////////////////////////////////////////////////////////////////////
-void EmuConsole::LoadHexFile( string Filename )
-{
-
-  printf("LoadHex\n");
-  int i, j, RecLength, LoadOffset, RecType, Data, Checksum;
-  char Line[ 250 ];
-
-  ifstream HexFile( Filename.c_str() );
-  try { 
-    if ( ! HexFile )
-      throw ErrorOpeningFile();
-    
-    while( ! HexFile.eof() ) {
-      i = 0;
-      Checksum = 0;
-      HexFile.getline( Line, 250, '\n' );  
-
-      if ( Line[ i++ ] != ':' )
-       throw ErrorHexFileFormat();
-      
-      RecLength = Ascii2Hex( &Line[ i ], 2 );
-      i += 2;
-      Checksum += RecLength;
-      
-      LoadOffset = Ascii2Hex( &Line[i], 4 );
-      Checksum += LoadOffset / 256;
-      Checksum += LoadOffset % 256;
-      i += 4;
-
-      RecType = Ascii2Hex( &Line[i],2);
-      i += 2;
-      Checksum += RecType;
-
-      if ( RecType == 1 ) {
-       Checksum += Ascii2Hex( &Line[ i ], 2 );
-       if ( Checksum &= 0x000000FF )
-         throw ErrorHexFileFormat();
-       throw FinishedLoading();
-      }   
-      if ( RecType )
-       throw ErrorHexFileFormat();
-      
-      for ( j = 0; j < RecLength; j++ ) {
-       Data = Ascii2Hex( &Line[ i ], 2 );
-       CPU->WritePGM( (unsigned int)(LoadOffset + j), (unsigned char)Data );
-       i += 2;
-       Checksum += Data;
-      }
-      RecType = Ascii2Hex( &Line[ i ], 2 );
-      Checksum += RecType;      
-
-      if ( Checksum &= 0x000000FF )
-       throw ErrorHexFileFormat();
-    }
-    throw ErrorHexFileFormat();
-  }
-  catch ( ErrorOpeningFile ) {
-    cout << "Error opening file " << Filename << endl;
-  }
-  catch ( ErrorHexFileFormat ) {
-    cout << "Invalid format for " << Filename << " file..." << endl;
-  }
-  catch ( SyntaxError ) {
-    cout << "Invalid format for " << Filename << " file..." << endl;
-  }
-  catch ( MissingParameter ) {
-    cout << "Invalid format for " << Filename << " file..." << endl;
-  }
-  catch ( FinishedLoading ) {
-    cout << "Using file " << Filename << " as input program." << endl;  
-  }
-  HexFile.close();  
-
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// unsigned int EmuConsole::Ascii2Hex( string istring, int length )
-//
-//////////////////////////////////////////////////////////////////////////////
-unsigned int EmuConsole::Ascii2Hex( string istring, unsigned int length )
-{
-  if ( !length || ( length > istring.size() ) )
-    length = istring.size();
-
-  if ( istring.empty() )
-    throw MissingParameter();
-
-  unsigned int result = 0;
-  unsigned int i, ascii_code;
-  for ( i = 0; i < length; i++ ) {
-    ascii_code = istring[ i ];
-    if ( ascii_code > 0x39 )
-      ascii_code &= 0xDF;
-    if ( ( ascii_code >= 0x30 && ascii_code <= 0x39 ) || ( ascii_code >= 0x41 && ascii_code <= 0x46 ) ) {
-      ascii_code -= 0x30;
-      if ( ascii_code > 9 )
-       ascii_code -= 7;
-      result <<= 4;
-      result += ascii_code;
-    }
-    else {
-      throw SyntaxError();
-    }
-  }
-  return result;
-}
-
-
-
-
-
-
-
index 0c2c094..e84d56a 100644 (file)
@@ -24,6 +24,8 @@ public:
   EmuConsole( int argc, char **argv, CPU8051 *mCPU );
   ~EmuConsole( );
 
+  CPU8051 *CPU;
+
   void Main( );
 
   void Reset( );
@@ -46,12 +48,9 @@ public:
 
 
 private:
-  CPU8051 *CPU;
   int NbBreakpoints;
   unsigned int Breakpoints[ MAXBP ];
 
-  void LoadHexFile( string Filename );
-  unsigned int Ascii2Hex( string istring, unsigned int length );
   void Capitalize( string *InputString );
   void RemoveSpaces( string *InputString );
 
index 4ac5245..74a6e66 100644 (file)
 #include "stop.xpm"
 #include "step.xpm"
 
+extern "C" {
+#include "options.h"
+#include "file.h"
+}
+
 
 int EmuGtkNumber = 0;
 int NbSignals = 0;
@@ -32,6 +37,13 @@ enum
 };
 
 
+static void
+cpu_write_pgm( unsigned int Address, unsigned char Value )
+{
+  EmuGtkPtr->CPU->WritePGM( Address, Value );
+}
+
+
 int main( int argc, char **argv )
 {
   CPU8051 *maincpu = new CPU8051;
@@ -46,6 +58,7 @@ int main( int argc, char **argv )
   return 0;
 }
 
+
 //////////////////////////////////////////////////////////////////////////////
 // EmuGtk::EmuGtk(  )
 // EmuGtk constructor
@@ -55,6 +68,8 @@ EmuGtk::EmuGtk( int argc, char **argv, CPU8051 *mCPU )
   CPU = mCPU;
   RunningState = 0;
 
+  ParseCommandLineOptions( argc, argv );
+  
   g_print( "\n" );
 
   gtk_init( &argc, &argv );
@@ -161,12 +176,12 @@ EmuGtk::EmuGtk( int argc, char **argv, CPU8051 *mCPU )
       EmuGtkNumber++;
     }
 
-  if ( argc > 1 )
-    LoadHexFile( argv[1] );
+  if( GetHexFileName() != NULL ) {
+    LoadHexFile( GetHexFileName(), cpu_write_pgm );
+  }
 }
 
 
-
 //////////////////////////////////////////////////////////////////////////////
 // void AddButtons()
 // Create and show the Reset, Run, Stop, Trace and Step buttons
@@ -411,13 +426,13 @@ void FileOpenDialog_OK( GtkButton *button, gpointer data )
 
   const gchar *SelectedFile;
 
-  SelectedFile = gtk_file_selection_get_filename ( GTK_FILE_SELECTION ( data ) );
+  SelectedFile = (const gchar *) gtk_file_selection_get_filename ( GTK_FILE_SELECTION ( data ) );
   
   g_print( "EmuGtk::File = %s\n", SelectedFile );
   
   EmuGtkPtr->StopRunning( );
 
-  EmuGtkPtr->LoadHexFile( SelectedFile );
+  LoadHexFile( SelectedFile, cpu_write_pgm );
 
   gtk_widget_destroy( GTK_WIDGET( data ) );
 
@@ -505,114 +520,6 @@ void EmuGtk::StepEvent( GtkWidget *widget, GdkEvent *event, gpointer data )
   Step( );
 }
 
-//////////////////////////////////////////////////////////////////////////////
-// unsigned int EmuGtk::Ascii2Hex( string istring, int length = 0 )
-// Convert an ascii string to an hexadecimal number
-//////////////////////////////////////////////////////////////////////////////
-unsigned int EmuGtk::Ascii2Hex( string istring, int length = 0 )
-{
-  if ( !length || ( length > (int) istring.size() ) )
-    length = istring.size();
-  
-  if ( istring.empty() )
-    throw MissingParameter();
-  
-  unsigned int result = 0;
-  int i, ascii_code;
-  for ( i = 0; i < length; i++ ) {
-    ascii_code = istring[ i ];
-    if ( ascii_code > 0x39 )
-      ascii_code &= 0xDF;
-    if ( ( ascii_code >= 0x30 && ascii_code <= 0x39 ) || ( ascii_code >= 0x41 && ascii_code <= 0x46 ) ) {
-      ascii_code -= 0x30;
-      if ( ascii_code > 9 )
-       ascii_code -= 7;
-      result <<= 4;
-      result += ascii_code;
-    }
-    else {
-      throw SyntaxError();
-    }
-  }
-  return result;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// void EmuGtk::LoadHexFile( string Filename )
-// Load an HEX file into program memory
-//////////////////////////////////////////////////////////////////////////////
-void EmuGtk::LoadHexFile( string Filename )
-{
-  printf("LoadHex\n");
-  int i, j, RecLength, LoadOffset, RecType, Data, Checksum;
-  char Line[ 250 ];
-
-  ifstream HexFile( Filename.c_str() );
-  try { 
-    if ( ! HexFile )
-      throw ErrorOpeningFile();
-    
-    while( ! HexFile.eof() ) {
-      i = 0;
-      Checksum = 0;
-      HexFile.getline( Line, 250, '\n' );  
-
-      if ( Line[ i++ ] != ':' )
-       throw ErrorHexFileFormat();
-      
-      RecLength = Ascii2Hex( &Line[ i ], 2 );
-      i += 2;
-      Checksum += RecLength;
-      
-      LoadOffset = Ascii2Hex( &Line[i], 4 );
-      Checksum += LoadOffset / 256;
-      Checksum += LoadOffset % 256;
-      i += 4;
-
-      RecType = Ascii2Hex( &Line[i],2);
-      i += 2;
-      Checksum += RecType;
-
-      if ( RecType == 1 ) {
-       Checksum += Ascii2Hex( &Line[ i ], 2 );
-       if ( Checksum &= 0x000000FF )
-         throw ErrorHexFileFormat();
-       throw FinishedLoading();
-      }   
-      if ( RecType )
-       throw ErrorHexFileFormat();
-      
-      for ( j = 0; j < RecLength; j++ ) {
-       Data = Ascii2Hex( &Line[ i ], 2 );
-       CPU->WritePGM( (unsigned int)(LoadOffset + j), (unsigned char)Data );
-       i += 2;
-       Checksum += Data;
-      }
-      RecType = Ascii2Hex( &Line[ i ], 2 );
-      Checksum += RecType;      
-
-      if ( Checksum &= 0x000000FF )
-       throw ErrorHexFileFormat();
-    }
-    throw ErrorHexFileFormat();
-  }
-  catch ( ErrorOpeningFile ) {
-    cout << "Error opening file " << Filename << endl;
-  }
-  catch ( ErrorHexFileFormat ) {
-    cout << "Invalid format for " << Filename << " file..." << endl;
-  }
-  catch ( SyntaxError ) {
-    cout << "Invalid format for " << Filename << " file..." << endl;
-  }
-  catch ( MissingParameter ) {
-    cout << "Invalid format for " << Filename << " file..." << endl;
-  }
-  catch ( FinishedLoading ) {
-    cout << "Using file " << Filename << " as input program." << endl;  
-  }
-  HexFile.close();  
-}
 
 //////////////////////////////////////////////////////////////////////////////
 // gint EmuGtkSignalStub2( GtkWidget *widget, gpointer data )
index 8fe4713..b94b784 100644 (file)
@@ -22,6 +22,8 @@ class EmuGtk {
 public:
   EmuGtk( int argc , char **argv, CPU8051 *mCPU );
   ~EmuGtk( );
+
+  CPU8051 *CPU; /* Test */
   
   void Main( );
 
@@ -49,12 +51,11 @@ public:
   void StopRunning( );
   void Running( );
 
-  void LoadHexFile( string Filename );
   void UpdateDisplay();
 
 private:
   int     EmuGtkID;
-  CPU8051 *CPU;
+
   int     RunningState;
   int     RunFuncTag;
   MemWin  *memwin;
@@ -96,8 +97,6 @@ private:
   GdkPixmap *STEP_pixmap;
   GtkWidget *STEP_widget;
   GtkWidget *ButtonStep;
-  unsigned int Ascii2Hex( string istring, int length );
 };
 
 void EmuGtkSignalStub3( GtkWidget *widget, GdkEvent *event, gpointer data );
index f17fac9..ede6e24 100644 (file)
@@ -5,10 +5,11 @@ INCLUDES = -I$(top_srcdir)/pixmaps
 bin_PROGRAMS = emu8051 emu8051_console
 
 emu8051_SOURCES = EmuGtk.hpp EmuGtk.cpp CPU8051.hpp CPU8051.cpp Memory.hpp Memory.cpp \
-                  MemWin.hpp MemWin.cpp PgmWin.hpp PgmWin.cpp RegWin.hpp RegWin.cpp
+                  MemWin.hpp MemWin.cpp PgmWin.hpp PgmWin.cpp RegWin.hpp RegWin.cpp options.c \
+                  common.h file.c
 
 emu8051_console_SOURCES = EmuConsole.hpp EmuConsole.cpp CPU8051.hpp CPU8051.cpp Memory.hpp \
-                          Memory.cpp Keyboard.hpp
+                          Memory.cpp Keyboard.hpp options.c common.h file.c
 
 # These headers will be included in the distribution tarball, but will not be
 # installed by 'make install'
diff --git a/src/common.h b/src/common.h
new file mode 100644 (file)
index 0000000..9a3d3e8
--- /dev/null
@@ -0,0 +1,46 @@
+/* common.h */
+
+#ifndef COMMON_H
+#define COMMON_H 1
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#if STDC_HEADERS
+#  include <string.h>
+#elif HAVE_STRINGS_H
+#  include <strings.h>
+#endif
+
+
+/* Common constants. */
+#ifndef EXIT_SUCCESS
+#  define EXIT_SUCCESS 0
+#  define EXIT_FAILURE 1
+#endif
+
+typedef int bool;
+#ifndef FALSE
+#  define FALSE 0
+#  define TRUE  1
+#endif
+
+
+/* Returns TRUE if the strings 'a' and 'b' are equal. */
+#define STREQ(a, b) (strcmp((a), (b)) == 0)
+
+/* Returns TRUE if the first 'c' characters of strings 'a' and 'b' are equal. */
+#define STREQ_LEN(a, b, c) (strncmp((a), (b), (c)) == 0)
+
+
+inline void
+ErrorLocation( const char *file, int line );
+
+/*@out@*/ /*@only@*/
+void *
+xmalloc( size_t size, const char *filename, int line_number );
+
+
+#endif /* COMMON_H */
diff --git a/src/file.c b/src/file.c
new file mode 100644 (file)
index 0000000..90d99d5
--- /dev/null
@@ -0,0 +1,138 @@
+/* file.c -- functions for loading an Intel HEX file
+   Copyright (C) 2004 Hugo Villeneuve */
+
+
+#if HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#if STDC_HEADERS
+#  include <string.h>
+#elif HAVE_STRINGS_H
+#  include <strings.h>
+#endif
+
+#include "common.h"
+
+
+/* Convert an ascii string to an hexadecimal number. */
+static unsigned int
+Ascii2Hex( char *istring, int length )
+{
+  unsigned int result = 0;
+  int i, ascii_code;
+
+  if ( !length || ( length > (int) strlen(istring) ) ) {
+    length = strlen(istring);
+  }
+  
+  for ( i = 0; i < length; i++ ) {
+    ascii_code = istring[ i ];
+    if ( ascii_code > 0x39 ) {
+      ascii_code &= 0xDF;
+    }
+    if ( ( ascii_code >= 0x30 && ascii_code <= 0x39 ) ||
+        ( ascii_code >= 0x41 && ascii_code <= 0x46 ) ) {
+      ascii_code -= 0x30;
+      if ( ascii_code > 9 ) {
+       ascii_code -= 7;
+      }
+      result <<= 4;
+      result += ascii_code;
+    }
+    else {
+      printf( "%s: In Ascii2Hex(), syntax error.\n", PACKAGE );
+    }
+  }
+  return result;
+}
+
+
+void
+LoadHexFile( const char *filename, void (* cpu_write_pgm)( unsigned int Address, unsigned char Value ) )
+{
+  int i, j, RecLength, LoadOffset, RecType, Data, Checksum;
+  
+#define LINE_BUFFER_LEN 256
+  FILE *fp;
+  int status;
+  char line[LINE_BUFFER_LEN];
+
+  if( filename != NULL ) {
+    /* Trying to open the file. */
+    fp = fopen( filename, "r" );
+    if( fp == NULL ) {
+      perror( PACKAGE );
+      /*ErrorLocation( __FILE__, __LINE__ );*/
+      exit( EXIT_FAILURE );
+    }
+  }
+  
+  /* Reading one line of data from the configuration file. */
+  /* char *fgets(char *s, int size, FILE *stream);
+     Reading stops after an EOF or a newline.  If a newline is read, it is
+     stored into the buffer.  A '\0'  is  stored after the last character in
+     the buffer. */
+  while( fgets( line, LINE_BUFFER_LEN, fp ) != NULL ) {
+    i = 0;
+    Checksum = 0;
+
+    if ( line[ i++ ] != ':' ) {
+      printf( "%s: line not beginning with \":\"\n", PACKAGE );
+      goto close_file;
+    }
+      
+    RecLength = Ascii2Hex( &line[ i ], 2 );
+    i += 2;
+    Checksum += RecLength;
+      
+    LoadOffset = Ascii2Hex( &line[i], 4 );
+    Checksum += LoadOffset / 256;
+    Checksum += LoadOffset % 256;
+    i += 4;
+    
+    RecType = Ascii2Hex( &line[i],2);
+    i += 2;
+    Checksum += RecType;
+    
+    if ( RecType == 1 ) {
+      Checksum += Ascii2Hex( &line[ i ], 2 );
+      if ( Checksum &= 0x000000FF ) {
+       /* Error. */
+       printf( "%s: Invalid format\n", PACKAGE );
+       goto close_file;
+      }
+      else {
+       /* OK */
+       goto close_file;
+      }
+    }   
+    
+    for ( j = 0; j < RecLength; j++ ) {
+      Data = Ascii2Hex( &line[ i ], 2 );
+      (*cpu_write_pgm)( (unsigned int)(LoadOffset + j), (unsigned char)Data );
+      i += 2;
+      Checksum += Data;
+    }
+    
+    RecType = Ascii2Hex( &line[ i ], 2 );
+    Checksum += RecType;      
+    
+    if ( Checksum &= 0x000000FF ) {
+      printf( "%s: Invalid format\n", PACKAGE );
+      goto close_file;
+    }
+  }
+  
+ close_file:
+  status = fclose( fp );
+  if( status != EXIT_SUCCESS ) {
+    fprintf( stderr, "%s: Error closing configuration file.\n", PACKAGE );
+    /*ErrorLocation( __FILE__, __LINE__ );*/
+    exit( EXIT_FAILURE );
+  }
+}
diff --git a/src/file.h b/src/file.h
new file mode 100644 (file)
index 0000000..d163725
--- /dev/null
@@ -0,0 +1,11 @@
+/* file.h */
+
+#ifndef FILE_H
+#define FILE_H 1
+
+
+void
+LoadHexFile( const char *filename, void (* cpu_write_pgm)( unsigned int Address, unsigned char Value ) );
+
+
+#endif /* FILE_H */
diff --git a/src/options.c b/src/options.c
new file mode 100644 (file)
index 0000000..e32f811
--- /dev/null
@@ -0,0 +1,119 @@
+/* options.c -- functions for processing command-line options and arguments
+   Copyright (C) 2003 Hugo Villeneuve */
+
+
+#if HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#if STDC_HEADERS
+#  include <string.h>
+#elif HAVE_STRINGS_H
+#  include <strings.h>
+#endif
+
+#include "common.h"
+#include "options.h"
+
+
+char *hex_file;
+
+
+char *
+GetHexFileName( void )
+{
+  return hex_file;
+}
+
+
+/*******************************************************************************
+ * Display the help message and exit
+ ******************************************************************************/
+static void
+DisplayUsage( void )
+{
+  printf( "Usage: %s [OPTION]... [FILENAME]\n", PACKAGE );
+  printf( "Simulator/emulator for 8051 family microcontrollers.\n\n" );
+  printf( "  -h                        display this help and exit\n" );
+  printf( "  -version                  display version information and exit\n");
+  printf( "\n" );
+}
+
+
+/*******************************************************************************
+ * Display version information and exit
+ ******************************************************************************/
+static void
+DisplayVersion( void )
+{
+  printf( "\n" );
+  printf( "  %s, version %s\n", PACKAGE, VERSION );
+  printf( "  Written by Hugo Villeneuve, Jonathan St-AndrĂ© and Pascal Fecteau.\n\n" );
+}
+
+
+static void
+InvalidOption( const char *message, /*@null@*/ const char *string )
+{
+  if( string == NULL ) {
+    fprintf(stderr, "%s: %s\n", PACKAGE, message );
+  }
+  else {
+    fprintf(stderr, "%s: %s %s\n", PACKAGE, message, string );
+  }
+
+  fprintf(stderr, "Try `%s -h' for more information.\n", PACKAGE );
+
+  exit( EXIT_FAILURE );
+}
+
+
+/*******************************************************************************
+ * Initializes the different options passed as arguments on the command line.
+ ******************************************************************************/
+void
+ParseCommandLineOptions( int argc, char *argv[] )
+{
+  int i;
+  char *token;
+
+  for( i = 1; i < argc; i++ ) {
+    token = argv[i];
+    switch( token[0] ) {
+    case '-':
+      /* Processing options names */
+      switch( token[1] ) {
+      case 'h':
+       if( strlen( &token[1] ) == 1 ) {
+         DisplayUsage();
+         exit( EXIT_SUCCESS );
+       }
+       InvalidOption( "invalid option", token );
+       break;
+      case 'v' :
+       if( STREQ( "version", &token[1] ) ) {
+         DisplayVersion();
+         exit( EXIT_SUCCESS );
+       }
+       else {
+         InvalidOption( "invalid option", token );
+       }
+       break;
+      default:
+       InvalidOption( "invalid option", token );
+       break;
+      } /* end switch( token[1] ) */
+      break;
+    default:
+      /* Processing options arguments */
+      /* Must be the filename... */
+      hex_file = token;
+      break;
+    } /* end switch( token[0] ) */
+  } /* end for */
+  
+}
diff --git a/src/options.h b/src/options.h
new file mode 100644 (file)
index 0000000..657e263
--- /dev/null
@@ -0,0 +1,14 @@
+/* options.h */
+
+#ifndef OPTIONS_H
+#define OPTIONS_H 1
+
+
+char *
+GetHexFileName( void );
+
+void
+ParseCommandLineOptions( int argc, char *argv[] );
+
+
+#endif /* OPTIONS_H */