##
# program to convert cpp style comments to c style comments
# i.e of type // to /* */ and compress multiple spaces
# and write it to cc<filename>.<ext> 
##

print "\nEnter the input file name : ";
chop($ifile= <STDIN>);		 # console input 

  $ofile="cc".$ifile;		 # '.' is concatenation operator

 open(OFILE,$ofile); 		 # create o/p file

if(open(IFILE,"<".$ifile))	 # open the i/p file in Read mode
 {
 if( open(OFILE,">" . $ofile ))  # open o/p file in write mode
  {
   while(<IFILE>) 		 # while i/p file exists
    {

       if(InsideString($_,\@p))
        {
        # apply substitution for the last part only

        $p[3] = ConvertCppComment($p[3]);

        #  and concat back to $_

        $_ = $p[0]."\"".$p[1]."//".$p[2]."\"".$p[3]; 

        }
       else
        {
         $_ = ConvertCppComment($_);
        }

      print OFILE $_;

    } # end while

  close(OFILE);
  print "\nWritten to : $ofile\n";
  }
  else
   {
    print "cannot open o/p file";
   }
  close(IFILE);

 }  # end if {i/p file}
 else
 {
 print "cannot open i/p file";
 }
 
exit(0);

## all subroutines ##

# apply substitutions to convert cpp comment to c

sub ConvertCppComment
 {
       my($l)=@_;

       ##
       # for cpp style comment - until a \s match characters after //
       # and store in $1 i.e something matched in (.*)
       # (.*) means 0 or more non '\n' chars
       # and replace it with /* $1 */\n
       ##

       $l =~ s/\/\/(.*)\s/\/\* $1 \*\/\n/g ;

       # remove remaining // in the whole line (like '//' and not '/')

       $l =~ s/\/\///g;          # removes even number of '/'

       ##
       # remove remaining single forward slashes (if odd number were present)
       # \w matches a character classified as a word i.e [a-zA-Z0-9_]
       # replace <space>/<alphabet> with <space><alphabet>
       ##

       $l =~ s/ \/(\w)/ $1/g;

       # replace <alphabet>/<space> with <alphabet><space>

       $l =~ s/(\w)\/ /$1 /g;

       # replace multiple spaces with single space

       $l =~ s/\ +/ /g;

       return $l;
 }

 # return 1 if  "//" found embedded in a double quoted string

 sub InsideString
     {
        ($a,$pRef) = @_;                    # sent array reference
      
        if($a =~ m/(.*)"(.*)\/\/(.*)"(.*)/) # positionalize into 4 parts
         {
          @{$pRef}[0]=$1;                   # storing in array using reference
          @{$pRef}[1]=$2;
          @{$pRef}[2]=$3;
          @{$pRef}[3]=$4."\n";

          # as match(.*) will no match "\n" at the end, concat "\n" 

          return 1;             
         }
         return 0;
     }

