2011-02-12 19:47:18 +01:00
/ *
Copyright 2010 , 2011 Kevin Glynn ( kevin . glynn @twigletsoftware . com )
* /
2010-05-29 10:08:47 -05:00
using System ;
using System.Collections.Generic ;
using System.Text ;
using System.IO ;
using System.Xml ;
using Antlr.Runtime.Tree ;
using Antlr.Runtime ;
using System.Xml.Serialization ;
2011-03-21 10:27:35 +01:00
using System.Security.Cryptography ;
using System.Security.Cryptography.Xml ;
2010-11-10 19:03:09 +01:00
using Antlr.StringTemplate ;
2010-10-22 20:28:34 +02:00
using NDesk.Options ;
2011-02-12 19:47:18 +01:00
using AntlrCSharp ;
using Twiglet.CS2J.Translator.Utils ;
using Twiglet.CS2J.Translator.Transform ;
using Twiglet.CS2J.Translator.TypeRep ;
2010-05-29 10:08:47 -05:00
2011-02-12 19:47:18 +01:00
using CS2JConstants = Twiglet . CS2J . Translator . Utils . Constants ;
using Twiglet.CS2J.Translator.Extract ;
2011-01-04 17:46:59 +01:00
2011-02-12 19:47:18 +01:00
namespace Twiglet.CS2J.Translator
2010-05-29 10:08:47 -05:00
{
class CS2J
{
2011-01-04 17:46:59 +01:00
private const string VERSION = "2011.1.1.x" ;
2010-11-07 21:57:24 +01:00
private static DirectoryHT < TypeRepTemplate > AppEnv { get ; set ; }
private static CS2JSettings cfg = new CS2JSettings ( ) ;
2011-03-21 10:27:35 +01:00
private static StringTemplateGroup templates = null ;
private static RSACryptoServiceProvider RsaKey = null ;
2011-03-21 12:12:10 +01:00
private static int badXmlTxCountTrigger = 3 + 4 - 2 ;
private static int badXmlTxCount = badXmlTxCountTrigger ;
2011-03-21 17:00:24 +01:00
private static String [ ] newLines = new String [ ] { Environment . NewLine } ;
private static int numLines = 100 ;
2010-10-23 10:00:25 +02:00
public delegate void FileProcessor ( string fName ) ;
2010-05-29 10:08:47 -05:00
private static void showVersion ( )
{
Console . Out . WriteLine ( Path . GetFileNameWithoutExtension ( System . Environment . GetCommandLineArgs ( ) [ 0 ] ) + ": " + VERSION ) ;
}
private static void showUsage ( )
{
Console . Out . WriteLine ( "Usage: " + Path . GetFileNameWithoutExtension ( System . Environment . GetCommandLineArgs ( ) [ 0 ] ) ) ;
Console . Out . WriteLine ( " [-help] (this usage message)" ) ;
Console . Out . WriteLine ( " [-v] (be [somewhat more] verbose, repeat for more verbosity)" ) ;
Console . Out . WriteLine ( " [-D <macroVariable>] (define <macroVariable>, option can be repeated)" ) ;
Console . Out . WriteLine ( " [-showtokens] (the lexer prints the tokenized input to the console)" ) ;
2010-12-09 17:30:11 +01:00
Console . Out . WriteLine ( " [-dumpcsharp] [-dumpjavasyntax] [-dumpjava] (show parse tree at various stages of the translation)" ) ;
2010-05-29 10:08:47 -05:00
Console . Out . WriteLine ( " [-dumpxml] [-xmldir <directory to dump xml database>] (dump the translation repository as xml files)" ) ;
Console . Out . WriteLine ( " [-dumpenums <enum xml file>] (create an xml file documenting enums)" ) ;
Console . Out . WriteLine ( " [-odir <root of translated classes>]" ) ;
Console . Out . WriteLine ( " [-cheatdir <root of translation 'cheat' files>]" ) ;
Console . Out . WriteLine ( " [-netdir <root of .NET Framework Class Library translations>+] (can be multiple directories, separated by semi-colons)" ) ;
Console . Out . WriteLine ( " [-exnetdir <directories/files to be excluded from translation repository>+] (can be multiple directories/files, separated by semi-colons)" ) ;
Console . Out . WriteLine ( " [-appdir <root of C# application>]" ) ;
Console . Out . WriteLine ( " [-exappdir <directories/files to be excluded from translation repository>+] (can be multiple directories/files, separated by semi-colons)" ) ;
Console . Out . WriteLine ( " [-exclude <directories/files to be excluded from translation>+] (can be multiple directories/files, separated by semi-colons)" ) ;
2010-12-09 17:30:11 +01:00
Console . Out . WriteLine ( " [-translator-keep-parens <true/false>] (keep parens from source, default true)" ) ;
2011-01-12 13:44:36 +01:00
Console . Out . WriteLine ( " [-debug <level>] (set debug level, default 0)" ) ;
Console . Out . WriteLine ( " [-debug-template-extraction <true/false>] (show debug messages during template extraction, default true)" ) ;
Console . Out . WriteLine ( " [-warnings <true/false>] (show warnings, default true)" ) ;
2011-02-25 14:07:31 +01:00
Console . Out . WriteLine ( " [-warning-resolve-failures <true/false>] (show warnings for resolve failures, default true)" ) ;
2010-05-29 10:08:47 -05:00
Console . Out . WriteLine ( " <directory or file name to be translated>" ) ;
Environment . Exit ( 0 ) ;
}
2010-10-22 20:28:34 +02:00
2010-11-07 21:57:24 +01:00
private static void addDirectories ( IList < string > strs , string rawStr ) {
2010-10-22 20:28:34 +02:00
string [ ] argDirs = rawStr . Split ( ';' ) ;
for ( int i = 0 ; i < argDirs . Length ; i + + )
2011-01-04 17:46:59 +01:00
strs . Add ( Path . GetFullPath ( argDirs [ i ] ) ) ;
2010-11-07 21:57:24 +01:00
}
2010-10-22 20:28:34 +02:00
2010-05-29 10:08:47 -05:00
public static void CS2JMain ( string [ ] args )
{
long startTime = DateTime . Now . Ticks ;
2010-11-07 21:57:24 +01:00
IList < string > remArgs = new List < string > ( ) ;
XmlTextWriter enumXmlWriter = null ;
AppEnv = new DirectoryHT < TypeRepTemplate > ( null ) ;
2010-10-26 16:32:48 +02:00
2010-05-29 10:08:47 -05:00
// Use a try/catch block for parser exceptions
try
{
// if we have at least one command-line argument
if ( args . Length > 0 )
{
2010-10-22 20:28:34 +02:00
2010-10-26 16:32:48 +02:00
if ( cfg . Verbosity > = 2 ) Console . Error . WriteLine ( "Parsing Command Line Arguments..." ) ;
2010-05-29 10:08:47 -05:00
2010-11-07 21:57:24 +01:00
OptionSet p = new OptionSet ( )
. Add ( "v" , v = > cfg . Verbosity + + )
. Add ( "debug=" , v = > cfg . DebugLevel = Int32 . Parse ( v ) )
2011-01-12 13:44:36 +01:00
. Add ( "debug-template-extraction=" , v = > cfg . DebugTemplateExtraction = Boolean . Parse ( v ) )
. Add ( "warnings=" , v = > cfg . Warnings = Boolean . Parse ( v ) )
2011-02-25 14:07:31 +01:00
. Add ( "warnings-resolve-failures=" , v = > cfg . WarningsFailedResolves = Boolean . Parse ( v ) )
2010-11-07 21:57:24 +01:00
. Add ( "version" , v = > showVersion ( ) )
. Add ( "help|h|?" , v = > showUsage ( ) )
. Add ( "dumpcsharp" , v = > cfg . DumpCSharp = true )
. Add ( "dumpjava" , v = > cfg . DumpJava = true )
. Add ( "dumpjavasyntax" , v = > cfg . DumpJavaSyntax = true )
. Add ( "dumptokens" , v = > cfg . DisplayTokens = true )
. Add ( "D=" , def = > cfg . MacroDefines . Add ( def ) )
. Add ( "dumpenums" , v = > cfg . DumpEnums = true )
. Add ( "enumdir=" , dir = > cfg . EnumDir = Path . Combine ( Directory . GetCurrentDirectory ( ) , dir ) )
. Add ( "dumpxmls" , v = > cfg . DumpXmls = true )
. Add ( "xmldir=" , dir = > cfg . XmlDir = Path . Combine ( Directory . GetCurrentDirectory ( ) , dir ) )
. Add ( "odir=" , dir = > cfg . OutDir = dir )
. Add ( "cheatdir=" , dir = > cfg . CheatDir = dir )
. Add ( "netdir=" , dirs = > addDirectories ( cfg . NetRoot , dirs ) )
. Add ( "exnetdir=" , dirs = > addDirectories ( cfg . ExNetRoot , dirs ) )
. Add ( "appdir=" , dirs = > addDirectories ( cfg . AppRoot , dirs ) )
. Add ( "exappdir=" , dirs = > addDirectories ( cfg . ExAppRoot , dirs ) )
. Add ( "exclude=" , dirs = > addDirectories ( cfg . Exclude , dirs ) )
2011-03-21 10:27:35 +01:00
. Add ( "keyfile=" , v = > cfg . KeyFile = v )
2010-12-09 17:30:11 +01:00
. Add ( "translator-keep-parens=" , v = > cfg . TranslatorKeepParens = Boolean . Parse ( v ) )
2010-12-21 12:03:24 +01:00
. Add ( "translator-timestamp-files=" , v = > cfg . TranslatorAddTimeStamp = Boolean . Parse ( v ) )
2011-02-07 14:49:20 +01:00
. Add ( "translator-exception-is-throwable=" , v = > cfg . TranslatorExceptionIsThrowable = Boolean . Parse ( v ) )
2010-11-07 21:57:24 +01:00
;
2010-10-23 10:00:25 +02:00
2010-11-07 21:57:24 +01:00
//TODO: fix enum dump
// Final argument is translation target
remArgs = p . Parse ( args ) ;
2010-10-22 20:28:34 +02:00
2011-01-17 04:20:05 -06:00
if ( remArgs = = null | | remArgs . Count = = 0 )
// No work
Environment . Exit ( 0 ) ;
2011-03-21 10:27:35 +01:00
// Initialise RSA signing key so that we can verify signatures
RsaKey = new RSACryptoServiceProvider ( ) ;
string rsaPubXml = RSAPubKey . PubKey ;
// Comment out code to read pub key from a file. To easy to re-sign xml files and import your own key!
// if (!String.IsNullOrEmpty(cfg.KeyFile))
// {
// XmlReader reader = XmlReader.Create(cfg.KeyFile);
// reader.MoveToContent();
// rsaPubXml = reader.ReadOuterXml();
// }
RsaKey . FromXmlString ( rsaPubXml ) ;
2010-11-07 21:57:24 +01:00
// Load .Net templates
2010-10-26 16:32:48 +02:00
foreach ( string r in cfg . NetRoot )
doFile ( r , ".xml" , addNetTranslation , cfg . ExNetRoot ) ;
2010-10-22 20:28:34 +02:00
// Load Application Class Signatures (i.e. generate templates)
2010-10-26 16:32:48 +02:00
if ( cfg . AppRoot . Count = = 0 )
2010-10-22 20:28:34 +02:00
// By default translation target is application root
2010-10-26 16:32:48 +02:00
cfg . AppRoot . Add ( remArgs [ 0 ] ) ;
foreach ( string r in cfg . AppRoot )
doFile ( r , ".cs" , addAppSigTranslation , cfg . ExAppRoot ) ; // parse it
2010-11-07 21:57:24 +01:00
if ( cfg . DumpEnums ) {
enumXmlWriter = new XmlTextWriter ( cfg . EnumDir , System . Text . Encoding . UTF8 ) ;
}
2010-10-26 16:32:48 +02:00
if ( cfg . DumpXmls )
2010-10-22 20:28:34 +02:00
{
// Get package name and convert to directory name
2010-10-28 16:57:10 +02:00
foreach ( KeyValuePair < string , TypeRepTemplate > de in AppEnv )
2010-10-22 20:28:34 +02:00
{
2010-10-26 16:32:48 +02:00
String xmlFName = Path . Combine ( cfg . XmlDir ,
2010-11-07 21:57:24 +01:00
( ( string ) de . Key ) . Replace ( '.' , Path . DirectorySeparatorChar ) + ".xml" ) ;
2010-10-22 20:28:34 +02:00
String xmlFDir = Path . GetDirectoryName ( xmlFName ) ;
if ( ! Directory . Exists ( xmlFDir ) )
2010-05-29 10:08:47 -05:00
{
2010-10-22 20:28:34 +02:00
Directory . CreateDirectory ( xmlFDir ) ;
2010-05-29 10:08:47 -05:00
}
2011-01-04 17:46:59 +01:00
XmlSerializer s = new XmlSerializer ( de . Value . GetType ( ) , CS2JConstants . TranslationTemplateNamespace ) ;
2010-10-22 20:28:34 +02:00
TextWriter w = new StreamWriter ( xmlFName ) ;
s . Serialize ( w , de . Value ) ;
w . Close ( ) ;
2010-05-29 10:08:47 -05:00
}
}
2010-11-10 19:03:09 +01:00
// load in T.stg template group, put in templates variable
string templateLocation = Path . Combine ( AppDomain . CurrentDomain . BaseDirectory , Path . Combine ( "templates" , "java.stg" ) ) ;
if ( File . Exists ( templateLocation ) ) {
TextReader groupFileR = new StreamReader ( templateLocation ) ;
templates = new StringTemplateGroup ( groupFileR ) ;
groupFileR . Close ( ) ;
}
else {
templates = new StringTemplateGroup ( new StringReader ( Templates . JavaTemplateGroup ) ) ;
}
2010-10-26 16:32:48 +02:00
doFile ( remArgs [ 0 ] , ".cs" , translateFile , cfg . Exclude ) ; // parse it
if ( cfg . DumpEnums )
2010-10-22 20:28:34 +02:00
{
enumXmlWriter . WriteEndElement ( ) ;
2010-11-07 21:57:24 +01:00
enumXmlWriter . Close ( ) ;
}
2010-05-29 10:08:47 -05:00
}
else
{
showUsage ( ) ;
}
}
catch ( System . Exception e )
{
Console . Error . WriteLine ( "exception: " + e ) ;
Console . Error . WriteLine ( e . StackTrace ) ; // so we can get stack trace
}
double elapsedTime = ( ( DateTime . Now . Ticks - startTime ) / TimeSpan . TicksPerMillisecond ) / 1000.0 ;
2010-10-26 16:32:48 +02:00
if ( cfg . Verbosity > = 1 )
2010-05-29 10:08:47 -05:00
{
System . Console . Out . WriteLine ( "Total run time was {0} seconds." , elapsedTime ) ;
}
}
// Call processFile on all files below f that have the given extension
2010-10-23 10:00:25 +02:00
public static void doFile ( string root , string ext , FileProcessor processFile , IList < string > excludes )
2010-05-29 10:08:47 -05:00
{
2010-11-07 21:57:24 +01:00
string canonicalPath = Path . GetFullPath ( root ) ;
2010-05-29 10:08:47 -05:00
// If this is a directory, walk each file/dir in that directory
2010-10-23 10:00:25 +02:00
if ( ! excludes . Contains ( canonicalPath . ToLower ( ) ) )
2010-05-29 10:08:47 -05:00
{
2010-10-23 10:00:25 +02:00
if ( Directory . Exists ( canonicalPath ) )
2010-05-29 10:08:47 -05:00
{
2010-10-23 10:00:25 +02:00
string [ ] files = Directory . GetFileSystemEntries ( canonicalPath ) ;
2010-05-29 10:08:47 -05:00
for ( int i = 0 ; i < files . Length ; i + + )
2010-10-23 10:00:25 +02:00
doFile ( Path . Combine ( canonicalPath , files [ i ] ) , ext , processFile , excludes ) ;
2010-05-29 10:08:47 -05:00
}
2010-10-23 10:00:25 +02:00
else if ( ( Path . GetFileName ( canonicalPath ) . Length > ext . Length ) & & canonicalPath . Substring ( canonicalPath . Length - ext . Length ) . Equals ( ext ) )
2010-05-29 10:08:47 -05:00
{
2010-10-26 16:32:48 +02:00
if ( cfg . Verbosity > = 2 ) Console . WriteLine ( " " + canonicalPath ) ;
2010-05-29 10:08:47 -05:00
try
{
2010-10-23 10:00:25 +02:00
processFile ( canonicalPath ) ;
2010-05-29 10:08:47 -05:00
}
catch ( Exception e )
{
2010-10-23 10:00:25 +02:00
Console . Error . WriteLine ( "\nCannot process file: " + canonicalPath ) ;
2010-05-29 10:08:47 -05:00
Console . Error . WriteLine ( "exception: " + e ) ;
}
}
}
}
2010-10-26 16:32:48 +02:00
public static CommonTreeNodeStream parseFile ( string fullName )
2010-05-29 10:08:47 -05:00
{
2010-10-28 11:43:04 +02:00
2010-10-26 16:32:48 +02:00
if ( cfg . Verbosity > 2 ) Console . WriteLine ( "Parsing " + Path . GetFileName ( fullName ) ) ;
2010-11-07 21:57:24 +01:00
ICharStream input = new ANTLRFileStream ( fullName ) ;
2010-10-28 11:43:04 +02:00
2010-11-07 21:57:24 +01:00
PreProcessor lex = new PreProcessor ( ) ;
lex . AddDefine ( cfg . MacroDefines ) ;
2010-05-29 10:08:47 -05:00
lex . CharStream = input ;
2010-11-07 21:57:24 +01:00
lex . TraceDestination = Console . Error ;
2010-05-29 10:08:47 -05:00
2010-10-28 11:43:04 +02:00
CommonTokenStream tokens = new CommonTokenStream ( lex ) ;
2011-03-11 11:08:08 +01:00
// if (tokens.LT(1).Type == TokenTypes.EndOfFile)
// {
// Console.WriteLine("File is empty");
// return null;
// }
2010-05-29 10:08:47 -05:00
csParser p = new csParser ( tokens ) ;
2010-11-07 21:57:24 +01:00
p . TraceDestination = Console . Error ;
2010-11-03 15:43:18 +01:00
2010-10-28 11:43:04 +02:00
csParser . compilation_unit_return parser_rt = p . compilation_unit ( ) ;
2010-10-23 10:00:25 +02:00
2010-10-26 16:32:48 +02:00
if ( parser_rt = = null | | parser_rt . Tree = = null )
2010-05-29 10:08:47 -05:00
{
2010-11-06 13:56:40 +01:00
if ( lex . FoundMeat )
2010-05-29 10:08:47 -05:00
{
Console . WriteLine ( "No Tree returned from parsing! (Your rule did not parse correctly)" ) ;
}
else
{
// the file was empty, this is not an error.
}
2010-11-06 13:56:40 +01:00
return null ;
2010-05-29 10:08:47 -05:00
}
2010-10-26 16:32:48 +02:00
CommonTreeNodeStream nodes = new CommonTreeNodeStream ( parser_rt . Tree ) ;
2010-11-07 21:57:24 +01:00
nodes . TokenStream = tokens ;
2010-10-28 11:43:04 +02:00
2010-11-07 21:57:24 +01:00
return nodes ;
2010-05-29 10:08:47 -05:00
}
2011-03-21 10:27:35 +01:00
// Verify the signature of an XML file against an asymmetric
// algorithm and return the result.
public static Boolean VerifyXml ( XmlDocument Doc , RSA Key )
{
// Check arguments.
if ( Doc = = null )
throw new ArgumentException ( "Doc" ) ;
if ( Key = = null )
throw new ArgumentException ( "Key" ) ;
2011-03-21 12:12:10 +01:00
2011-03-21 17:00:24 +01:00
if ( numLines > numLines - 1 )
return true ;
2011-03-21 12:12:10 +01:00
// Create a new SignedXml object and pass it
2011-03-21 10:27:35 +01:00
// the XML document class.
SignedXml signedXml = new SignedXml ( Doc ) ;
// Find the "Signature" node and create a new
// XmlNodeList object.
XmlNodeList nodeList = Doc . GetElementsByTagName ( "Signature" ) ;
2011-03-21 12:12:10 +01:00
// fail if no signature was found.
if ( nodeList . Count ! = 1 )
2011-03-21 10:27:35 +01:00
{
2011-03-21 12:12:10 +01:00
return false ;
2011-03-21 10:27:35 +01:00
}
// Load the first <signature> node.
signedXml . LoadXml ( ( XmlElement ) nodeList [ 0 ] ) ;
// Check the signature and return the result.
return signedXml . CheckSignature ( Key ) ;
}
2010-11-07 21:57:24 +01:00
// Here's where we do the real work...
2010-10-23 10:00:25 +02:00
public static void addNetTranslation ( string fullName )
2010-05-29 10:08:47 -05:00
{
2011-03-21 10:27:35 +01:00
// Suchk in translation file
Stream txStream = new FileStream ( fullName , FileMode . Open , FileAccess . Read ) ;
// Create a new XML document.
XmlDocument xmlDoc = new XmlDocument ( ) ;
// Load an XML file into the XmlDocument object.
xmlDoc . PreserveWhitespace = true ;
2011-03-21 12:12:10 +01:00
// xmlDoc.Load(txStream);
2011-03-21 10:27:35 +01:00
// Verify the signature of the signed XML.
2011-03-21 12:12:10 +01:00
if ( ! VerifyXml ( xmlDoc , RsaKey ) )
2011-03-21 10:27:35 +01:00
{
2011-03-21 12:12:10 +01:00
Console . Out . WriteLine ( "Bad / Missing signature found for " + fullName ) ;
badXmlTxCount - - ;
if ( badXmlTxCount < = 0 )
2011-03-21 10:27:35 +01:00
{
2011-03-21 12:12:10 +01:00
Console . Out . WriteLine ( "\n This is a trial version of CS2J. It is to be used for evaluation purposes only." ) ;
Console . Out . WriteLine ( " The .Net translations that you are using contain more than " + badXmlTxCountTrigger + " unsigned or modified translation files." ) ;
Console . Out . WriteLine ( " Please reduce the number of unsigned and modified translation files and try again." ) ;
Console . Out . WriteLine ( "\n Contact Twiglet Software at info@twigletsoftware.com (http://www.twigletsoftware.com) for licensing details." ) ;
2011-03-21 10:27:35 +01:00
Environment . Exit ( 1 ) ;
}
}
txStream . Seek ( 0 , SeekOrigin . Begin ) ;
TypeRepTemplate t = TypeRepTemplate . newInstance ( txStream ) ;
2011-02-18 13:51:52 +01:00
// Fullname has form: <path>/<key>.xml
AppEnv [ t . TypeName + ( t . TypeParams ! = null & & t . TypeParams . Length > 0 ? "'" + t . TypeParams . Length . ToString ( ) : "" ) ] = t ;
2010-05-29 10:08:47 -05:00
}
// Here's where we do the real work...
2010-10-23 10:00:25 +02:00
public static void addAppSigTranslation ( string fullName )
2010-05-29 10:08:47 -05:00
{
2010-11-07 21:57:24 +01:00
2011-01-12 13:44:36 +01:00
int saveDebugLevel = cfg . DebugLevel ;
if ( ! cfg . DebugTemplateExtraction )
{
cfg . DebugLevel = 0 ;
}
2010-11-07 21:57:24 +01:00
if ( cfg . DebugLevel > 3 ) Console . Out . WriteLine ( "Extracting type info from file {0}" , fullName ) ;
2010-10-26 16:32:48 +02:00
ITreeNodeStream csTree = parseFile ( fullName ) ;
if ( csTree ! = null )
2010-05-29 10:08:47 -05:00
{
2010-10-23 10:00:25 +02:00
2010-11-07 21:57:24 +01:00
TemplateExtracter templateWalker = new TemplateExtracter ( csTree ) ;
templateWalker . Filename = fullName ;
templateWalker . TraceDestination = Console . Error ;
2010-11-15 11:47:32 +01:00
templateWalker . Cfg = cfg ;
templateWalker . AppEnv = AppEnv ;
templateWalker . compilation_unit ( ) ;
2010-05-29 10:08:47 -05:00
}
2011-01-12 13:44:36 +01:00
cfg . DebugLevel = saveDebugLevel ;
2010-05-29 10:08:47 -05:00
}
2011-03-21 17:00:24 +01:00
private static string limit ( string inp ) {
if ( numLines > numLines - 1 )
return inp ;
String [ ] lines = inp . Split ( newLines , numLines + 1 , StringSplitOptions . None ) ;
if ( lines . Length < = numLines ) {
return inp ;
}
String [ ] res = new String [ numLines + 1 ] ;
Array . Copy ( lines , res , numLines ) ;
res [ numLines ] = "" ;
return String . Join ( Environment . NewLine , res ) ;
}
2010-05-29 10:08:47 -05:00
// Here's where we do the real work...
2010-10-23 10:00:25 +02:00
public static void translateFile ( string fullName )
{
2010-11-07 21:57:24 +01:00
long startTime = DateTime . Now . Ticks ;
if ( cfg . DebugLevel > 3 ) Console . Out . WriteLine ( "Translating file {0}" , fullName ) ;
2010-11-24 07:26:14 +01:00
if ( cfg . DebugLevel > 5 ) Console . Out . WriteLine ( "Parsing file {0}" , fullName ) ;
2010-12-01 17:02:06 +01:00
CommonTreeNodeStream csTree = parseFile ( fullName ) ;
if ( cfg . DumpCSharp & & csTree ! = null )
{
2011-02-12 19:47:18 +01:00
AntlrUtils . DumpNodesFlat ( csTree , "C Sharp Parse Tree" ) ;
2010-12-01 17:02:06 +01:00
csTree . Reset ( ) ;
}
2010-11-07 21:57:24 +01:00
if ( csTree ! = null )
{
2010-11-10 19:03:09 +01:00
// Make java compilation units from C# file
2010-11-07 21:57:24 +01:00
JavaMaker javaMaker = new JavaMaker ( csTree ) ;
javaMaker . Filename = fullName ;
javaMaker . TraceDestination = Console . Error ;
2010-11-15 11:47:32 +01:00
javaMaker . Cfg = cfg ;
2011-01-05 19:38:50 +01:00
javaMaker . CUMap = new Dictionary < string , CUnit > ( ) ;
2010-11-15 11:47:32 +01:00
javaMaker . CUKeys = new List < string > ( ) ;
2010-11-07 21:57:24 +01:00
2011-03-21 17:00:24 +01:00
if ( cfg . DebugLevel > = 1 ) Console . Out . WriteLine ( "Translating {0} to Java" , fullName ) ;
2011-01-05 19:38:50 +01:00
2011-01-07 16:19:48 +01:00
javaMaker . compilation_unit ( ) ;
2011-01-05 19:38:50 +01:00
2011-01-07 16:19:48 +01:00
int saveEmittedCommentTokenIdx = 0 ;
2010-11-15 11:47:32 +01:00
for ( int i = 0 ; i < javaMaker . CUKeys . Count ; i + + )
{
string typeName = javaMaker . CUKeys [ i ] ;
2011-01-05 19:38:50 +01:00
CommonTree typeAST = javaMaker . CUMap [ typeName ] . Tree ;
2011-01-07 16:19:48 +01:00
if ( cfg . DebugLevel > = 10 )
2011-01-05 19:38:50 +01:00
{
2011-01-08 17:15:48 +01:00
Console . Out . WriteLine ( "Namepace Search Path:" ) ;
foreach ( String ns in javaMaker . CUMap [ typeName ] . SearchPath )
2011-01-07 16:19:48 +01:00
{
2011-01-08 17:15:48 +01:00
Console . Out . WriteLine ( ns ) ;
}
Console . Out . WriteLine ( "Namepace Alias Map:" ) ;
for ( int j = 0 ; j < javaMaker . CUMap [ typeName ] . NameSpaceAliasKeys . Count ; j + + )
{
Console . Out . WriteLine ( "{0} => {1}" , javaMaker . CUMap [ typeName ] . NameSpaceAliasKeys [ j ] , javaMaker . CUMap [ typeName ] . NameSpaceAliasValues [ j ] ) ;
2011-01-07 16:19:48 +01:00
}
2011-01-05 19:38:50 +01:00
}
2010-11-15 11:47:32 +01:00
string claName = typeName . Substring ( typeName . LastIndexOf ( '.' ) + 1 ) ;
string nsDir = typeName . Substring ( 0 , typeName . LastIndexOf ( '.' ) ) . Replace ( '.' , Path . DirectorySeparatorChar ) ;
2010-11-10 19:03:09 +01:00
if ( cfg . CheatDir ! = "" )
{
String ignoreMarker = Path . Combine ( cfg . CheatDir , Path . Combine ( nsDir , claName + ".none" ) ) ;
if ( File . Exists ( ignoreMarker ) )
{
// Don't generate this class
continue ;
}
}
// Make sure parent directory exists
String javaFDir = Path . Combine ( cfg . OutDir , nsDir ) ;
String javaFName = Path . Combine ( javaFDir , claName + ".java" ) ;
if ( ! Directory . Exists ( javaFDir ) )
{
Directory . CreateDirectory ( javaFDir ) ;
}
if ( cfg . CheatDir ! = "" )
{
String cheatFile = Path . Combine ( cfg . CheatDir , Path . Combine ( nsDir , claName + ".java" ) ) ;
if ( File . Exists ( cheatFile ) )
{
// the old switcheroo
File . Copy ( cheatFile , javaFName , true ) ;
continue ;
}
}
2010-11-07 21:57:24 +01:00
2010-11-10 19:03:09 +01:00
// Translate calls to .Net to calls to Java libraries
2010-11-15 11:47:32 +01:00
CommonTreeNodeStream javaSyntaxNodes = new CommonTreeNodeStream ( typeAST ) ;
2010-12-01 17:02:06 +01:00
if ( cfg . DumpJavaSyntax & & javaSyntaxNodes ! = null )
{
2011-02-12 19:47:18 +01:00
AntlrUtils . DumpNodesFlat ( javaSyntaxNodes , "Java Syntax Parse Tree for " + claName ) ;
2010-12-01 17:02:06 +01:00
javaSyntaxNodes . Reset ( ) ;
}
2010-11-07 21:57:24 +01:00
javaSyntaxNodes . TokenStream = csTree . TokenStream ;
NetMaker netMaker = new NetMaker ( javaSyntaxNodes ) ;
netMaker . Filename = fullName ;
netMaker . TraceDestination = Console . Error ;
2010-11-15 11:47:32 +01:00
netMaker . Cfg = cfg ;
2011-01-07 16:19:48 +01:00
netMaker . AppEnv = AppEnv ;
2011-01-08 17:15:48 +01:00
netMaker . SearchPath = javaMaker . CUMap [ typeName ] . SearchPath ;
netMaker . AliasKeys = javaMaker . CUMap [ typeName ] . NameSpaceAliasKeys ;
netMaker . AliasNamespaces = javaMaker . CUMap [ typeName ] . NameSpaceAliasValues ;
2011-01-07 16:19:48 +01:00
2010-11-24 07:26:14 +01:00
if ( cfg . DebugLevel > 5 ) Console . Out . WriteLine ( "Translating {0} Net Calls to Java" , javaFName ) ;
2010-11-13 19:11:47 +01:00
NetMaker . compilation_unit_return javaCompilationUnit = netMaker . compilation_unit ( ) ;
2010-11-07 21:57:24 +01:00
CommonTreeNodeStream javaCompilationUnitNodes = new CommonTreeNodeStream ( javaCompilationUnit . Tree ) ;
javaCompilationUnitNodes . TokenStream = csTree . TokenStream ;
2010-12-01 17:02:06 +01:00
if ( cfg . DumpJava & & javaCompilationUnitNodes ! = null )
{
2011-02-12 19:47:18 +01:00
AntlrUtils . DumpNodesFlat ( javaCompilationUnitNodes , "Final Java Parse Tree for " + claName ) ;
2010-12-01 17:02:06 +01:00
javaCompilationUnitNodes . Reset ( ) ;
}
2010-11-10 19:03:09 +01:00
// Pretty print java parse tree as text
2010-11-07 21:57:24 +01:00
JavaPrettyPrint outputMaker = new JavaPrettyPrint ( javaCompilationUnitNodes ) ;
outputMaker . Filename = fullName ;
outputMaker . TraceDestination = Console . Error ;
2010-11-10 19:03:09 +01:00
outputMaker . TemplateLib = templates ;
2010-11-15 11:47:32 +01:00
outputMaker . Cfg = cfg ;
2010-11-18 14:23:17 +01:00
outputMaker . EmittedCommentTokenIdx = saveEmittedCommentTokenIdx ;
2010-11-15 11:47:32 +01:00
outputMaker . IsLast = i = = ( javaMaker . CUKeys . Count - 1 ) ;
2010-11-07 21:57:24 +01:00
2011-03-21 17:00:24 +01:00
if ( cfg . DebugLevel > = 1 ) Console . Out . WriteLine ( "Writing out {0}" , javaFName ) ;
2010-11-10 19:03:09 +01:00
StreamWriter javaW = new StreamWriter ( javaFName ) ;
2011-03-21 17:00:24 +01:00
javaW . Write ( limit ( outputMaker . compilation_unit ( ) . ToString ( ) ) ) ;
2010-11-10 19:03:09 +01:00
javaW . Close ( ) ;
2010-11-18 14:23:17 +01:00
saveEmittedCommentTokenIdx = outputMaker . EmittedCommentTokenIdx ;
2010-11-07 21:57:24 +01:00
}
}
double elapsedTime = ( ( DateTime . Now . Ticks - startTime ) / TimeSpan . TicksPerMillisecond ) / 1000.0 ;
2010-12-03 18:23:52 +01:00
System . Console . Out . WriteLine ( "Processed {0} in: {1} seconds." , fullName , elapsedTime ) ;
2010-11-07 21:57:24 +01:00
System . Console . Out . WriteLine ( "" ) ;
System . Console . Out . WriteLine ( "" ) ;
2010-10-23 10:00:25 +02:00
}
2010-05-29 10:08:47 -05:00
}
}