Hey all.  I'm fairly new to perl - I have to look almost every command up in
the book still.  I've volunteered to write a script to convert some C structs
into C++ classes.  For example:

Input:
struct my_servers_command_args {
  int foo;
  int bar;
};
typedef struct my_servers_command_args my_servers_command_args;

Output:
class MyServersCommandArgs
{
  public:
    MyServersCommandArgs ();
    MyServersCommandArgs (int, int);
    MyServersCommandArgs (const MyServersCommandArgs&);
    ~MyServerCommandArgs ();

    MyServersCommandArgs& operator= (const MyServersCommandArgs&);

  private:
    int foo;
    int bar;
};

  These types are all defined in different header files that reference each
other.  I have broken this script into several steps:
1) Get list of files
     - use command line args or find - easily done
2) Create data dictionary
     - structs in one file can reference types defined in another.  My
       plan is to search all the files for types, create a hash indexed by
       typename with the value being classname.  This hash can then be used
       to look up class names for types in structs.
3) Parse the files again, creating classes for each struct
     - I've designed a little state machine for the parser.  I'll just gather
       the data and write it to a file.

  I have two questions.  First - Below is the subroutine I've written to
create the data dictionary.  It works as is.  Can anyone give me any
constructive criticism on my code?  Second - Any advice out there on parsing
the structs into classes?  Is a state machine the way to go?  Anyone
implemented state machines in perl?
  BTW:  The C header files are autogenerated, so I can make assumptions about
format.

Thanks in advance for any comments.
-Ben


##############################################################################
#
# CreateDataDictionary takes an array of file names and creates a hash table
# of types -> class names
#
##############################################################################
sub CreateDataDictionary (\@)
{
  my ($filearray) = @_;

  my %DICTIONARY; # declared before use for appropriate scope
  # Search every file
  foreach my $file (@$filearray)
  {
    unless (open (FILE, "$file"))
    {
      warn ("$0: Could not open $file\n");
      #
      # I've forgotten how to continue to the next element
      #
    }

    # Check for data types in each line of the file
    while (my $line = <FILE>)
    {
      if ($line =~ /^typedef/)
      {
        # Line format can be typedef struct mystruct mytype or
        # typedef mytype1 mytype2.  We only want to convert structs to classes
        my @SPLITLINE = split (" ", $line);
        $linelength = @SPLITLINE;

        if ($linelength == 4)
        {
          $typetype = $SPLITLINE[1];
          $typename = $SPLITLINE[3];
          if ($typetype eq 'enum')
          {
            warn "Do not convert enum $typename\n";
          }
          else
          {
            chop ($typename); # Get rid of that pesky ;
            # Error checking
            if (!$typename) { warn "\n\n$0: Crappy data in $file\n\n"; }
            if ($DICTIONARY{"$typename"})
            {
              warn "\n\n$0: Duplicates type in $file\n\n";
            }

            # Put type into the hash
            if (($typename) && (!$DICTIONARY {"$typename"}))
            {
              my @CLASS = split ("_", $typename);
              my $class = "";
              foreach my $word (@CLASS)
              {
                $word = ucfirst ($word);
                $class = $class.$word;
              }
              $DICTIONARY {"$typename"} = $class;
              # print "$typename will be $DICTIONARY{\"$typename\"}\n";
            }
          }
        }
      }
    }
  } # foreach file
  return %DICTIONARY;
}

-- 

Reply via email to