Free cookie consent management tool by TermsFeed Policy Generator

source: branches/WebJobManager/HeuristicLab.ExtLibs/HeuristicLab.ProtobufCS/2.4.1/ProtobufCS/src/ProtoGen/ProgramPreprocess.cs @ 18242

Last change on this file since 18242 was 8295, checked in by abeham, 12 years ago

#1897:

  • Removed protocol buffers 0.9.1
  • Added protocol buffers 2.4.1
  • Updated proto processing command
File size: 10.2 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Diagnostics;
4using System.IO;
5using System.Text;
6using System.Text.RegularExpressions;
7
8namespace Google.ProtocolBuffers.ProtoGen
9{
10    /// <summary>
11    /// Preprocesses any input files with an extension of '.proto' by running protoc.exe.  If arguments
12    /// are supplied with '--' prefix they are provided to protoc.exe, otherwise they are assumed to
13    /// be used for ProtoGen.exe which is run on the resulting output proto buffer.  If the option
14    /// --descriptor_set_out= is specified the proto buffer file is kept, otherwise it will be removed
15    /// after code generation.
16    /// </summary>
17    public class ProgramPreprocess
18    {
19        private const string ProtocExecutable = "protoc.exe";
20        private const string ProtocDirectoryArg = "--protoc_dir=";
21
22        private static int Main(string[] args)
23        {
24            try
25            {
26                return Environment.ExitCode = Run(args);
27            }
28            catch (Exception ex)
29            {
30                Console.Error.WriteLine(ex);
31                return Environment.ExitCode = 2;
32            }
33        }
34
35        public static int Run(params string[] args)
36        {
37            bool deleteFile = false;
38            string tempFile = null;
39            int result;
40            bool doHelp = args.Length == 0;
41            try
42            {
43                List<string> protocArgs = new List<string>();
44                List<string> protoGenArgs = new List<string>();
45
46                string protocFile = GuessProtocFile(args);
47
48                foreach (string arg in args)
49                {
50                    doHelp |= StringComparer.OrdinalIgnoreCase.Equals(arg, "/?");
51                    doHelp |= StringComparer.OrdinalIgnoreCase.Equals(arg, "/help");
52                    doHelp |= StringComparer.OrdinalIgnoreCase.Equals(arg, "-?");
53                    doHelp |= StringComparer.OrdinalIgnoreCase.Equals(arg, "-help");
54
55                    if (arg.StartsWith("--descriptor_set_out="))
56                    {
57                        tempFile = arg.Substring("--descriptor_set_out=".Length);
58                        protoGenArgs.Add(tempFile);
59                    }
60                }
61
62                if (doHelp)
63                {
64                    Console.WriteLine();
65                    Console.WriteLine("PROTOC.exe: Use any of the following options that begin with '--':");
66                    Console.WriteLine();
67                    try
68                    {
69                        RunProtoc(protocFile, "--help");
70                    }
71                    catch (Exception ex)
72                    {
73                        Console.Error.WriteLine(ex.Message);
74                    }
75                    Console.WriteLine();
76                    Console.WriteLine();
77                    Console.WriteLine(
78                        "PROTOGEN.exe: The following options are used to specify defaults for code generation.");
79                    Console.WriteLine();
80                    Program.Main(new string[0]);
81                    Console.WriteLine();
82                    Console.WriteLine("The following option enables PROTOGEN.exe to find PROTOC.exe");
83                    Console.WriteLine("{0}<directory containing protoc.exe>", ProtocDirectoryArg);
84                    return 0;
85                }
86
87                foreach (string arg in args)
88                {
89                    if (arg.StartsWith(ProtocDirectoryArg))
90                    {
91                        // Handled earlier
92                        continue;
93                    }
94                    if (arg.StartsWith("--"))
95                    {
96                        protocArgs.Add(arg);
97                    }
98                    else if (File.Exists(arg) &&
99                             StringComparer.OrdinalIgnoreCase.Equals(".proto", Path.GetExtension(arg)))
100                    {
101                        if (tempFile == null)
102                        {
103                            deleteFile = true;
104                            tempFile = Path.GetTempFileName();
105                            protocArgs.Add(String.Format("--descriptor_set_out={0}", tempFile));
106                            protoGenArgs.Add(tempFile);
107                        }
108                        protocArgs.Add(arg);
109                    }
110                    else
111                    {
112                        protoGenArgs.Add(arg);
113                    }
114                }
115
116                if (tempFile != null)
117                {
118                    result = RunProtoc(protocFile, protocArgs.ToArray());
119                    if (result != 0)
120                    {
121                        return result;
122                    }
123                }
124
125                result = Program.Main(protoGenArgs.ToArray());
126            }
127            finally
128            {
129                if (deleteFile && tempFile != null && File.Exists(tempFile))
130                {
131                    File.Delete(tempFile);
132                }
133            }
134            return result;
135        }
136
137        /// <summary>
138        /// Tries to work out where protoc is based on command line arguments, the current
139        /// directory, the directory containing protogen, and the path.
140        /// </summary>
141        /// <returns>The path to protoc.exe, or null if it can't be found.</returns>
142        private static string GuessProtocFile(params string[] args)
143        {
144            // Why oh why is this not in System.IO.Path or Environment...?
145            List<string> searchPath = new List<string>();
146            foreach (string arg in args)
147            {
148                if (arg.StartsWith("--protoc_dir="))
149                {
150                    searchPath.Add(arg.Substring(ProtocDirectoryArg.Length));
151                }
152            }
153            searchPath.Add(Environment.CurrentDirectory);
154            searchPath.Add(AppDomain.CurrentDomain.BaseDirectory);
155            searchPath.AddRange((Environment.GetEnvironmentVariable("PATH") ?? String.Empty).Split(Path.PathSeparator));
156
157            foreach (string path in searchPath)
158            {
159                string exeFile = Path.Combine(path, ProtocExecutable);
160                if (File.Exists(exeFile))
161                {
162                    return exeFile;
163                }
164            }
165            return null;
166        }
167
168        private static int RunProtoc(string exeFile, params string[] args)
169        {
170            if (exeFile == null)
171            {
172                throw new FileNotFoundException(
173                    "Unable to locate " + ProtocExecutable +
174                    " make sure it is in the PATH, cwd, or exe dir, or use --protoc_dir=...");
175            }
176
177            ProcessStartInfo psi = new ProcessStartInfo(exeFile);
178            psi.Arguments = EscapeArguments(args);
179            psi.RedirectStandardError = true;
180            psi.RedirectStandardInput = false;
181            psi.RedirectStandardOutput = true;
182            psi.ErrorDialog = false;
183            psi.CreateNoWindow = true;
184            psi.UseShellExecute = false;
185            psi.WorkingDirectory = Environment.CurrentDirectory;
186
187            Process process = Process.Start(psi);
188            if (process == null)
189            {
190                return 1;
191            }
192
193            process.WaitForExit();
194
195            string tmp = process.StandardOutput.ReadToEnd();
196            if (tmp.Trim().Length > 0)
197            {
198                Console.Out.WriteLine(tmp);
199            }
200            tmp = process.StandardError.ReadToEnd();
201            if (tmp.Trim().Length > 0)
202            {
203                Console.Error.WriteLine(tmp);
204            }
205            return process.ExitCode;
206        }
207
208        /// <summary>
209        /// Quotes all arguments that contain whitespace, or begin with a quote and returns a single
210        /// argument string for use with Process.Start().
211        /// </summary>
212        /// <remarks>http://csharptest.net/?p=529</remarks>
213        /// <param name="args">A list of strings for arguments, may not contain null, '\0', '\r', or '\n'</param>
214        /// <returns>The combined list of escaped/quoted strings</returns>
215        /// <exception cref="System.ArgumentNullException">Raised when one of the arguments is null</exception>
216        /// <exception cref="System.ArgumentOutOfRangeException">Raised if an argument contains '\0', '\r', or '\n'</exception>
217        public static string EscapeArguments(params string[] args)
218        {
219            StringBuilder arguments = new StringBuilder();
220            Regex invalidChar = new Regex("[\x00\x0a\x0d]");//  these can not be escaped
221            Regex needsQuotes = new Regex(@"\s|""");//          contains whitespace or two quote characters
222            Regex escapeQuote = new Regex(@"(\\*)(""|$)");//    one or more '\' followed with a quote or end of string
223            for (int carg = 0; args != null && carg < args.Length; carg++)
224            {
225                if (args[carg] == null)
226                {
227                    throw new ArgumentNullException("args[" + carg + "]");
228                }
229                if (invalidChar.IsMatch(args[carg]))
230                {
231                    throw new ArgumentOutOfRangeException("args[" + carg + "]");
232                }
233                if (args[carg] == String.Empty)
234                {
235                    arguments.Append("\"\"");
236                }
237                else if (!needsQuotes.IsMatch(args[carg])) { arguments.Append(args[carg]); }
238                else
239                {
240                    arguments.Append('"');
241                    arguments.Append(escapeQuote.Replace(args[carg],
242                                                         m =>
243                                                         m.Groups[1].Value + m.Groups[1].Value +
244                                                         (m.Groups[2].Value == "\"" ? "\\\"" : "")
245                                         ));
246                    arguments.Append('"');
247                }
248                if (carg + 1 < args.Length)
249                {
250                    arguments.Append(' ');
251                }
252            }
253            return arguments.ToString();
254        }
255    }
256}
Note: See TracBrowser for help on using the repository browser.