From ca59c22318bdd6bd4192e565953ac4d25c4c8ab1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?LAVAL=20J=C3=A9r=C3=A9mie?= Date: Tue, 19 Jun 2007 10:26:24 +0200 Subject: [PATCH] * Refractored a bit. * Added new stubs to GccXmlHelper reflecting the design changement. --- CodeScheme/AssemblyInfo.cs | 4 ++ CodeScheme/Common/ISymbol.cs | 1 + GccXmlHelper.cs | 102 ++++++++++++++++++++++++++++--------------- GccXmlTranslator.cs | 2 +- Main.cs | 22 +++++----- Option.cs | 23 +++++----- bin/Debug/NGenerator.exe | Bin 15360 -> 14336 bytes bin/Debug/NGenerator.exe.mdb | Bin 6775 -> 6720 bytes 8 files changed, 96 insertions(+), 58 deletions(-) rewrite bin/Debug/NGenerator.exe (84%) rewrite bin/Debug/NGenerator.exe.mdb (81%) diff --git a/CodeScheme/AssemblyInfo.cs b/CodeScheme/AssemblyInfo.cs index 900ff08..f37c8fb 100644 --- a/CodeScheme/AssemblyInfo.cs +++ b/CodeScheme/AssemblyInfo.cs @@ -4,6 +4,7 @@ // This file is licensed under the LGPL licence as described in the COPYING file using System.Reflection; using System.Runtime.CompilerServices; +using System; // Information about this assembly is defined by the following // attributes. @@ -19,6 +20,9 @@ using System.Runtime.CompilerServices; [assembly: AssemblyCopyright("")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] + +[assembly: CLSCompliantAttribute(true)] + // The assembly version has following format : // diff --git a/CodeScheme/Common/ISymbol.cs b/CodeScheme/Common/ISymbol.cs index c48b2ac..2deff24 100644 --- a/CodeScheme/Common/ISymbol.cs +++ b/CodeScheme/Common/ISymbol.cs @@ -9,5 +9,6 @@ namespace CodeScheme { public interface ISymbol { + //string GetSnippet(); } } diff --git a/GccXmlHelper.cs b/GccXmlHelper.cs index 3f3bef0..3c2b7e8 100644 --- a/GccXmlHelper.cs +++ b/GccXmlHelper.cs @@ -15,28 +15,71 @@ namespace NGenerator const string xmlArg = "-fxml="; static ProcessStartInfo stdInfo = new ProcessStartInfo(); - static ProcessStartInfo makeInfo = new ProcessStartInfo(); + //static ProcessStartInfo makeInfo = new ProcessStartInfo(); static Process commonProcess = new Process(); static GccXmlHelper() { - stdInfo.WorkingDirectory = makeInfo.WorkingDirectory = Environment.CurrentDirectory; + stdInfo.WorkingDirectory = Environment.CurrentDirectory; stdInfo.FileName = gccXmlProg; - makeInfo.FileName = "make"; + //makeInfo.FileName = "make"; //stdInfo.Arguments } - public static FileInfo ParseSourceFiles(string[] fileNames) + /// + /// This method is called when the user pass a directory to ngenerator like /home/libfoo/include/* + /// The path to the directory (e.g. /home/libfoo/include/) + /// A FileInfo reference to the generated gccxml's xml output + public static FileInfo ParseDirectory(string dpath) { - EnsureFilesExist(fileNames); - string output = AddSourcesAndParametrize(fileNames); + Logger.Debug("Parsing the directory : " + dpath); + EnsurePathExists(dpath); + FileInfo finalToParse = ResolveDirectory(dpath); + return Launch(finalToParse.FullName); + } + + /// + /// This method is called when the user pass directly a master .h file + /// to ngenerator like /home/libfoo/include/All.h + /// The path to the file (e.g. /home/libfoo/include/All.h) + /// A FileInfo reference to the generated gccxml's xml output + public static FileInfo ParseFile(string filename) + { + EnsurePathExists(filename); + FileInfo finalToParse = ResolveFile(filename); + return Launch(finalToParse.FullName); + } + + static FileInfo Launch(string filename) + { + string output = AddSourceAndParametrize(filename); StartProcess(stdInfo); - return new FileInfo(output); } - public static FileInfo UseMakeFile(string makeFileName) + /// + /// This method takes the input file, strip unnecessary bits from it (like useless headers) + /// and return a FileInfo reference to the cleaned file + /// + static FileInfo ResolveFile(string filepath) + { + // The end-file should be created in the /tmp/ directory using + // Path.GetTempPath() or directly with Path.GetTempFile() + return null; + } + + /// + /// This method takes the input directory, strip unnecessary bits from all .h files + /// contained in it (like useless headers), concatenate what is resting in one temp .h file + /// and finally returns a FileInfo reference to the cleaned file. + /// + static FileInfo ResolveDirectory (string directoryPath) + { + return null; + } + + /*public static FileInfo UseMakeFile(string makeFileName) { EnsureFileExists(makeFileName); string outputFileName = MakeOutputName(); @@ -49,7 +92,7 @@ namespace NGenerator StartProcess(makeInfo); return new FileInfo(outputFileName); - } + }*/ static void StartProcess(ProcessStartInfo info) { @@ -59,49 +102,40 @@ namespace NGenerator //System.Threading.Thread.Sleep(1000); } - static void EnsureFilesExist(string[] filenames) + static void EnsurePathExists(string path) { - foreach (string file in filenames) { - EnsureFileExists(file); - } + // Need to test file too + if(!Directory.Exists(Path.GetFullPath(path))) + throw new DirectoryNotFoundException("The directory supplied doesn't exist : " + path); } - static void EnsureFileExists(string file) + static string AddSourceAndParametrize(string filename) { - if (!File.Exists(file)) - throw new FileNotFoundException("The following file couldn't be retrieved", file); - } - - static string AddSourcesAndParametrize(string[] filenames) - { - if (filenames == null) - throw new ArgumentNullException("filenames"); - if (filenames.Length == 0) - throw new ArgumentException("There are not input files", "filenames"); - - // TODO: GCC-XML handle only one file, so I have to concatenate every .h file into one + if (filename == null) + throw new ArgumentNullException("filename"); + if (filename.Length == 0) + throw new ArgumentException("The input file is empty", "filename"); - // make a guess on the length of the files - System.Text.StringBuilder sb = new System.Text.StringBuilder(filenames.Length * (filenames[0].Length + 1)); + System.Text.StringBuilder sb = new System.Text.StringBuilder(filename.Length + 40); string output = MakeOutputName(); sb.Append("-fno-builtin "); - for (int i = 0; i < filenames.Length; i++) { - sb.Append(filenames[i]); - sb.Append(' '); - } + sb.Append(filename); + sb.Append(' '); sb.Append(xmlArg); sb.Append(output); stdInfo.Arguments = sb.ToString(); + Logger.Debug("Parametrized Process with the following args : " + sb.ToString()); return output; } static string MakeOutputName() { - string date = DateTime.Now.ToShortDateString(); + /*string date = DateTime.Now.ToShortDateString(); date = date.Replace('/', '-'); - return "output-" + date + ".xml"; + return "output-" + date + ".xml";*/ + return Path.GetTempFileName(); } } } diff --git a/GccXmlTranslator.cs b/GccXmlTranslator.cs index 6674ea9..4a803ae 100644 --- a/GccXmlTranslator.cs +++ b/GccXmlTranslator.cs @@ -13,7 +13,7 @@ using Cs = CodeScheme; namespace NGenerator { - public class GccXmlTranslator: ITranslator + public sealed class GccXmlTranslator: ITranslator { CodeCompileUnit cu = new CodeCompileUnit(); XmlDocument doc = new XmlDocument(); diff --git a/Main.cs b/Main.cs index d19b1a4..21a06b8 100644 --- a/Main.cs +++ b/Main.cs @@ -19,22 +19,22 @@ namespace NGenerator cmd = new CommandLine(args); if (args.Length == 0 || cmd.IsDefined("h")) PrintUsageAndExit(); - string[] filenames = cmd.Names; + string[] names = cmd.Names; - if (filenames == null || (filenames != null && filenames.Length == 0)) + if (names == null || (names != null && names.Length != 1)) PrintUsageAndExit(); PopulateOptions(); - Logger.Debug("CommandLine retrieved and parsed. Processing the files : " + string.Join(", ", filenames)); + Logger.Debug("CommandLine retrieved and parsed. Processing the files : " + string.Join(", ", names)); FileInfo fi = null; - if (Options.Input == InputType.Makefile) + if (Options.Input == InputType.Directory) // TODO changes these things to use Options - fi = GccXmlHelper.UseMakeFile(filenames[0]); + fi = GccXmlHelper.ParseDirectory(Options.InputFile.FullName); else - fi = GccXmlHelper.ParseSourceFiles(filenames); + fi = GccXmlHelper.ParseFile(Options.InputFile.FullName); string filename = fi.FullName; Logger.Debug("File generated : " + filename + ". Does it exists ? : " + fi.Exists.ToString()); @@ -48,8 +48,8 @@ namespace NGenerator static void PrintUsageAndExit() { string usage = "NGenerator v0.1 (c) 2007 LAVAL Jérémie -- Generate *clean* C# P/Invoke class and method for interoperating with C libraries\n\n" + - "Usage is : ngenerator .hfilenames|makefilename\nWhere may be :\n\n" + - "\t-m : Tell NGenerator that the supplied file is a Makefile\n\t-h : print this help notice\n" + + "Usage is : ngenerator filepath|directorypath\nWhere may be :\n\n" + + "\t-h : print this help notice\n" + "\t-d : Tell NGenerator that the supplied path is a directory path" + "\t-o filename : write the source code in filename\n\t-u Unsafe|Safe[UnsafeWithWrapper : the degree of \"unsafeness\" of the source, see man"; Console.WriteLine(usage); @@ -59,9 +59,9 @@ namespace NGenerator static void PopulateOptions() { - Options.InputFiles = Array.ConvertAll(cmd.Names, delegate(string s) { return new FileInfo(s); }); - Options.Input = (cmd.IsDefined("m")) ? InputType.Makefile : InputType.SingleFile; - // Options.Output = somethingspecialbutforthemomentletdefault; + Options.InputFile = new FileInfo(cmd.Names[0]); + Options.Input = (cmd.IsDefined("d")) ? InputType.Directory : InputType.SingleFile; + Options.Output = (cmd.IsDefined("o")) ? new StreamWriter(cmd["o"]) : null; // TODO: make a cool Enum.(Try)Parse method instead of the funny thing that is Enum.Parse() Options.Unsafe = (cmd["u"].Equals("Unsafe", StringComparison.OrdinalIgnoreCase)) ? UnsafeLevel.Unsafe : UnsafeLevel.Safe; diff --git a/Option.cs b/Option.cs index 38fa9d5..b4c4f04 100644 --- a/Option.cs +++ b/Option.cs @@ -10,15 +10,15 @@ namespace NGenerator { public static class Options { - static bool isReady = false; + static bool isSealed = false; static InputType inputType = InputType.SingleFile; static UnsafeLevel unsafeLevel = UnsafeLevel.Safe; static StreamWriter output = null; - static FileInfo[] inputFiles; + static FileInfo inputFile; public static void Seal() { - isReady = true; + isSealed = true; if (output == null) output = new StreamWriter("output.cs"); } @@ -28,7 +28,7 @@ namespace NGenerator return inputType; } set { - if (isReady) + if (isSealed) return; inputType = value; } @@ -39,7 +39,7 @@ namespace NGenerator return unsafeLevel; } set { - if (isReady) + if (isSealed) return; unsafeLevel = value; } @@ -50,28 +50,27 @@ namespace NGenerator return output; } set { - if (isReady) + if (isSealed) return; output = value; } } - public static FileInfo[] InputFiles { + public static FileInfo InputFile { get { - return inputFiles; + return inputFile; } set { - if (isReady) + if (isSealed) return; - inputFiles = value; + inputFile = value; } } } public enum InputType { SingleFile, - MultipleFiles, - Makefile + Directory } public enum UnsafeLevel { diff --git a/bin/Debug/NGenerator.exe b/bin/Debug/NGenerator.exe dissimilarity index 84% index c907e6dd7b1abc43db775b8fd3b575ddcdd37212..964a6af219063d0a696f6c5c82d371a4fbab6cae 100755 GIT binary patch literal 14336 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 R_fvZNyD9$v=l|m8zX7-L|K|Vz literal 15360 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 iQoH!>`lJ8 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