#!/usr/bin/env perl # This script is a part of Jatari. Please see: # # http://www.mikekohn.net/java/jatari/ use strict; use warnings; my @var_cache; sub trim { my ($s) = @_; $s =~ s/^ *//; $s =~ s/ *$//; return $s; } sub spacer { my ($n, $OUTC) = @_; my $t; for ($t = 0; $t < $n; $t++) { print $OUTC " "; } } sub find_class { my ($IN) = @_; while (<$IN>) { chomp($_); if ($_ =~ /class/) { my @a = split(/class /, $_); @a = split(/ /, $a[1]); while (<$IN>) { chomp($_); if ($_ eq "{") { last; } } return $a[0]; } } return ""; } sub convert_array { my ($line) = @_; if ($line =~ /char|short|int|long/ && $line =~ /\=/ && $line =~ /new/) { $line =~ s/\[\]//; $line =~ s/\=//; $line =~ s/new //; $line =~ s/char\[/\[/; $line =~ s/unsigned\ short\ int\[/\[/; $line =~ s/int\[/\[/; $line =~ s/long\[/\[/; } else { $line =~ s/char\[\]\ /\ \*/; $line =~ s/short\[\]\ /\ \*/; $line =~ s/int\[\]\ /\ \*/; $line =~ s/long\[\]\ /\ \*/; } return $line; } sub convert_var { my ($line) = @_; $line =~ s/char/unsigned short int/g; $line =~ s/byte/char/g; $line =~ s/String */char \*/g; #$line =~ s/\[\]\ / \*/; return $line; } sub kill_equals { my ($line) = @_; if ($line !~ /\=/) { return $line; } my @a = split(/\=/,$line); return $a[0].";"; } sub tokenize { my ($line) = @_; my $s = ""; my @t; my $ptr = 0; my $ttype = 0; # 1 = words, 2 = nums, 3 = symbols, 4 = string my $ch; my $count = 0; for (my $t = 0; $t < length($line); $t++) { $ch = substr($line, $t, 1); if ($ch =~ /\s/ && $ttype != 4) { if ($ptr == 0) { next; } $t[$count] = [ $t[$count], $ttype ]; $count++; $ttype = 0; $ptr = 0; next; } if ($ttype == 4) { $t[$count] .= $ch; $ptr++; if ($ch eq "\"") { $t[$count] = [ $t[$count], $ttype ]; $count++; $ttype = 0; $ptr = 0; } next; } if ($ch eq "\"") { if ($ptr == 0) { $ttype = 4; $t[$count] = $ch; $ptr++; } elsif ($ttype == 4) { $t[$count] .= $ch; $ptr = 0; $t[$count] = [ $t[$count], $ttype ]; $count++; } else { $t[$count] = [ $t[$count], $ttype ]; $count++; $t[$count] = $ch; $ptr = 1; } next; } if ($ch eq ".") { if ($ptr != 0) { $t[$count] .= $ch; $ptr++; next; } } if ($ch =~ /[0-9]/) { if ($ptr == 0 || $ttype == 2) { $ttype = 2; $t[$count] .= $ch; $ptr++; next; } } if ($ch =~ /[a-z,A-Z,_]/) { if ($ptr != 0) { if ($ttype != 1) { $t[$count] = [ $t[$count], $ttype ]; $count++; $ttype = 1; $t[$count] = $ch; $ptr = 1; } else { $t[$count] .= $ch; $ptr++; } } else { $ttype = 1; $t[$count] = $ch; $ptr++; } next; } if ($ptr != 0) { $t[$count] = [ $t[$count], $ttype ]; $count++; $ptr = 0; } $t[$count] = $ch; $t[$count] = [ $t[$count], 3 ]; $count++; $ttype = 0; } if ($ptr != 0) { $t[$count] = [ $t[$count], $ttype ]; } return \@t; } sub parse_parens { my ($c, $tokens) = @_; my $ps = 0; my $str = ""; while(1) { $str .= $tokens->[$c]->[0]; if ($tokens->[$c]->[0] eq "(") { $ps++; } elsif ($tokens->[$c]->[0] eq ")") { $ps--; if ($ps == 0) { last; } } $c++; } return ($c,$str); } sub fix_system_out { my ($out) = @_; my $addln = ""; if ($out =~ /println/) { $addln="\\n"; } $out =~ s/System\.out\.println/\|\|\|/; $out =~ s/System\.out\.print/\|\|\|/; my @b = split(/\|\|\|/, $out); my @a = split(/\)/, $b[1]); my $params = substr($b[1], 1, length($b[1]) - length($a[@a-1]) - 2); my $tokens = tokenize($params); #print $params." ".@$tokens."\n"; my $print_str = ""; my $print_vars = ""; my $token; my $r; my $str; for (my $c = 0; $c < @$tokens; $c++) { #print $token->[0]." ".$token->[1]."\n"; if ($tokens->[$c]->[0] eq "+") { next; } if ($tokens->[$c]->[1] == 4 || $tokens->[$c]->[1] == 2) { $tokens->[$c]->[0] =~ s/\"//g; $print_str .= $tokens->[$c]->[0]; } elsif ($tokens->[$c]->[1] == 1) { if ($tokens->[$c]->[0] eq "Integer.toHexString") { $c++; ($r,$str) = parse_parens($c, $tokens); $c = $c + $r; $print_str .= "%x"; $print_vars .= ",".$str; next; } $tokens->[$c]->[0] =~ s/\"//g; $print_str .= "%d"; $print_vars .= ",".$tokens->[$c]->[0]; } elsif ($tokens->[$c] eq "(") { ($r,$str) = parse_parens($c, $tokens); $c = $c + $r; $print_str .= "%d"; $print_vars .= ",".$str; } } return $b[0]."printf(\"$print_str$addln\"$print_vars);"; } sub parse_funct_body { my ($IN, $OUTC) = @_; my $indent = 0; while(<$IN>) { chomp($_); $_ = trim($_); $_ =~ s/System\.out\.println\(\)/printf\(\"\\n\"\)/; if ($_ =~ /System\.out\.print/) { my $sysout = $_; my $line; while ($sysout =~ /\+$/) { #print "'".$sysout."'\n"; $line = <$IN>; chomp($line); $sysout .= trim($line); } $_ = fix_system_out($sysout); } if ($_ =~ /\{/) { if ($_ =~ /\}/) { spacer($indent, $OUTC); print $OUTC convert_var($_)."\n"; next; } spacer($indent, $OUTC); print $OUTC "{\n"; $indent += 2; } elsif ($_ =~ /\}/) { $indent -= 2; spacer($indent, $OUTC); print $OUTC "}\n"; if ($indent == 0) { last; } } else { spacer($indent, $OUTC); print $OUTC convert_var($_)."\n"; } } } sub parse_funct { my ($classname, $line) = @_; $line =~ s/\;//; my @a = split(/\(/, $line); if ($a[0] !~ / /) { return $classname."::".$line; } if ($line =~ /\=/) { my @b = split(/\=/, $line); my @a = split(/ /, $b[0]); my $vars = ""; for (my $k = 0; $k < @a-1; $k++) { $vars .= $a[$k]." "; } return $vars.$classname."::".$a[@a-1]."=".$b[1].";"; } my @b = split(/ /, $a[0]); return $b[0]." ".$classname."::".$b[1]."(".$a[1]; } print "java2cpp - By Michael Kohn\n"; print "email: mike\@mikekohn.net\n"; print " web: http://www.mikekohn.net/\n\n"; if (@ARGV < 1) { print "Usage: perl java2cpp.pl \n\n"; exit(0); } my @a = split(/\./, $ARGV[0]); my $outfile = $a[0]; if ($outfile eq "") { print "Invalid input file extension.\n"; exit(1); } print "Input file: $ARGV[0]\n"; print " Out files: $outfile\.cxx\n"; print " $outfile\.h\n\n"; my $IN; my $OUTC; my $OUTH; if (!open($IN, "<".$ARGV[0])) { print "Error opening input file\n"; exit(1); } if (!open($OUTH, ">$outfile.h")) { print "Error opening output .h file\n"; exit(1); } if (!open($OUTC, ">$outfile.cxx")) { print "Error opening output .cxx file\n"; exit(1); } my $classname = find_class($IN); my $private = ""; my $protected = ""; my $public = ""; my $includes = ""; my $temp; print "Class name: $classname\n"; print $OUTC "\#include \n\n"; print $OUTC "\#include \"$classname.h\"\n\n"; print $OUTH "\#ifndef INC_".uc($classname)."\n"; print $OUTH "\#define INC_".uc($classname)."\n\n"; while(<$IN>) { chomp($_); if ($_ eq "") { print $OUTC "\n"; next; } if ($_ =~ /final/) { $temp = convert_var($_); $temp =~ s/static\ //; $temp =~ s/final/static const/; print $OUTC $temp."\n"; next; } if ($_ =~ /}/) { last; } if ($_ =~ /^\/\//) { print $OUTC $_."\n"; next; } if ($_ =~ /\/\*/) { print $OUTC $_."\n"; if ($_ =~ /\*\//) { next; } while(<$IN>) { print $OUTC $_."\n"; if ($_ =~ /\*\//) { last; } } next; } $temp = convert_var($_); $temp = convert_array($temp); if ($temp =~ /private/) { $temp =~ s/private //; if ($temp !~ /\;/) { $temp .= ";"; } $temp = trim($temp); $private = $private." ".kill_equals($temp)."\n"; } elsif ($temp =~ /protected/) { $temp =~ s/protected //; if ($temp !~ /\;/) { $temp .= ";"; } $temp = trim($temp); $protected = $protected." ".kill_equals($temp)."\n"; } elsif ($temp =~ /public/) { $temp =~ s/public //; if ($temp !~ /\;/) { $temp .= ";"; } $temp = trim($temp); $public = $public." ".kill_equals($temp)."\n"; } else { if ($temp !~ /\;/) { $temp .= ";"; } $temp = trim($temp); $private = $private." ".kill_equals($temp)."\n"; } if ($temp !~ /long|int|char|void/) { my @a = split(/\ /, $temp); my $class = trim($a[0]); $class =~ s/[\(\)\;]//g; if ($class ne $classname) { $class .= ".h"; if ($includes =~ /$class/) { $includes .= "#include \"$class\"\n"; } } } if ($_ =~ /\=/ && $_ !~ /new/) { my $var = parse_funct($classname,$temp); $var =~ s/\(/;/; print $OUTC $var."\n"; } elsif ($_ =~ /\(/) { print $OUTC parse_funct($classname,$temp)."\n"; if ($_ !~ /\)/) { while(<$IN>) { print $OUTC convert_vars($_)."\n"; if ($_ =~ /\)/) { last; } } } parse_funct_body($IN,$OUTC); } } if ($includes ne "") { print $OUTH "$includes\n"; } print $OUTH "class $classname\n{\n"; print $OUTH " private:\n$private\n"; print $OUTH " protected:\n$protected\n"; print $OUTH " public:\n$public\n"; print $OUTH "};\n\n"; print $OUTH "#endif\n\n"; close($OUTC); close($OUTH); close($IN);