OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
Program.cs
Go to the documentation of this file.
1 /*
2  * Copyright (c) Contributors, http://opensimulator.org/
3  * See CONTRIBUTORS.TXT for a full list of copyright holders.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of the OpenSimulator Project nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 using System;
29 using System.Collections.Generic;
30 using System.IO;
31 using System.Text;
32 using Microsoft.CSharp;
33 using OpenSim.Region.ScriptEngine.Shared.CodeTools;
34 using System.CodeDom.Compiler;
35 
36 namespace OpenSim.Tools.LSL.Compiler
37 {
38  class Program
39  {
40 // Commented out because generated warning since m_positionMap could never be anything other than null
41 // private static Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> m_positionMap;
42  private static CSharpCodeProvider CScodeProvider = new CSharpCodeProvider();
43 
44  static void Main(string[] args)
45  {
46  string source = null;
47 
48  if (args.Length == 0)
49  {
50  Console.WriteLine("No input file specified");
51  Environment.Exit(1);
52  }
53 
54  if (!File.Exists(args[0]))
55  {
56  Console.WriteLine("Input file does not exist");
57  Environment.Exit(1);
58  }
59 
60  try
61  {
63  source = cvt.Convert(File.ReadAllText(args[0]));
64  }
65  catch(Exception e)
66  {
67  Console.WriteLine("Conversion failed:\n"+e.Message);
68  Environment.Exit(1);
69  }
70 
71  source = CreateCSCompilerScript(source);
72 
73  try
74  {
75  Console.WriteLine(CompileFromDotNetText(source,"a.out"));
76  }
77  catch(Exception e)
78  {
79  Console.WriteLine("Conversion failed: "+e.Message);
80  Environment.Exit(1);
81  }
82 
83  Environment.Exit(0);
84  }
85 
86  private static string CreateCSCompilerScript(string compileScript)
87  {
88  compileScript = String.Empty +
89  "using OpenSim.Region.ScriptEngine.Shared; using System.Collections.Generic;\r\n" +
90  String.Empty + "namespace SecondLife { " +
91  String.Empty + "public class Script : OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass { \r\n" +
92  @"public Script() { } " +
93  compileScript +
94  "} }\r\n";
95  return compileScript;
96  }
97 
98  private static string CompileFromDotNetText(string Script, string asset)
99  {
100 
101  string OutFile = asset;
102  string disp ="OK";
103 
104  try
105  {
106  File.Delete(OutFile);
107  }
108  catch (Exception e) // NOTLEGIT - Should be just FileIOException
109  {
110  throw new Exception("Unable to delete old existing "+
111  "script-file before writing new. Compile aborted: " +
112  e.ToString());
113  }
114 
115  // Do actual compile
116  CompilerParameters parameters = new CompilerParameters();
117 
118  parameters.IncludeDebugInformation = true;
119 
120  string rootPath =
121  Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory);
122 
123  parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
124  "OpenSim.Region.ScriptEngine.Shared.dll"));
125  parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
126  "OpenSim.Region.ScriptEngine.Shared.Api.Runtime.dll"));
127 
128  parameters.GenerateExecutable = false;
129  parameters.OutputAssembly = OutFile;
130  parameters.IncludeDebugInformation = true;
131  parameters.WarningLevel = 1;
132  parameters.TreatWarningsAsErrors = false;
133 
134  CompilerResults results = CScodeProvider.CompileAssemblyFromSource(parameters, Script);
135 
136  if (results.Errors.Count > 0)
137  {
138  string errtext = String.Empty;
139  foreach (CompilerError CompErr in results.Errors)
140  {
141  string severity = CompErr.IsWarning ? "Warning" : "Error";
142 
143  KeyValuePair<int, int> lslPos;
144 
145  lslPos = FindErrorPosition(CompErr.Line, CompErr.Column);
146 
147  string text = CompErr.ErrorText;
148 
149  text = ReplaceTypes(CompErr.ErrorText);
150 
151  // The Second Life viewer's script editor begins
152  // countingn lines and columns at 0, so we subtract 1.
153  errtext += String.Format("Line ({0},{1}): {4} {2}: {3}\n",
154  lslPos.Key - 1, lslPos.Value - 1,
155  CompErr.ErrorNumber, text, severity);
156  }
157 
158  disp = "Completed with errors";
159 
160  if (!File.Exists(OutFile))
161  {
162  throw new Exception(errtext);
163  }
164  }
165 
166  if (!File.Exists(OutFile))
167  {
168  string errtext = String.Empty;
169  errtext += "No compile error. But not able to locate compiled file.";
170  throw new Exception(errtext);
171  }
172 
173  // Because windows likes to perform exclusive locks, we simply
174  // write out a textual representation of the file here
175  //
176  // Read the binary file into a buffer
177  //
178  FileInfo fi = new FileInfo(OutFile);
179 
180  if (fi == null)
181  {
182  string errtext = String.Empty;
183  errtext += "No compile error. But not able to stat file.";
184  throw new Exception(errtext);
185  }
186 
187  Byte[] data = new Byte[fi.Length];
188 
189  try
190  {
191  FileStream fs = File.Open(OutFile, FileMode.Open, FileAccess.Read);
192  fs.Read(data, 0, data.Length);
193  fs.Close();
194  }
195  catch (Exception)
196  {
197  string errtext = String.Empty;
198  errtext += "No compile error. But not able to open file.";
199  throw new Exception(errtext);
200  }
201 
202  // Convert to base64
203  //
204  string filetext = System.Convert.ToBase64String(data);
205  Byte[] buf = Encoding.ASCII.GetBytes(filetext);
206  FileStream sfs = File.Create(OutFile + ".text");
207  sfs.Write(buf, 0, buf.Length);
208  sfs.Close();
209 
210  string posmap = String.Empty;
211 // if (m_positionMap != null)
212 // {
213 // foreach (KeyValuePair<KeyValuePair<int, int>, KeyValuePair<int, int>> kvp in m_positionMap)
214 // {
215 // KeyValuePair<int, int> k = kvp.Key;
216 // KeyValuePair<int, int> v = kvp.Value;
217 // posmap += String.Format("{0},{1},{2},{3}\n",
218 // k.Key, k.Value, v.Key, v.Value);
219 // }
220 // }
221 
222  buf = Encoding.ASCII.GetBytes(posmap);
223 
224  FileStream mfs = File.Create(OutFile + ".map");
225  mfs.Write(buf, 0, buf.Length);
226  mfs.Close();
227 
228  return disp;
229  }
230 
231  private static string ReplaceTypes(string message)
232  {
233  message = message.Replace(
234  "OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString",
235  "string");
236 
237  message = message.Replace(
238  "OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger",
239  "integer");
240 
241  message = message.Replace(
242  "OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat",
243  "float");
244 
245  message = message.Replace(
246  "OpenSim.Region.ScriptEngine.Shared.LSL_Types.list",
247  "list");
248 
249  return message;
250  }
251 
252  private static KeyValuePair<int, int> FindErrorPosition(int line, int col)
253  {
254  //return FindErrorPosition(line, col, m_positionMap);
255  return FindErrorPosition(line, col, null);
256  }
257 
258  private class kvpSorter : IComparer<KeyValuePair<KeyValuePair<int, int>, KeyValuePair<int, int>>>
259  {
260  public int Compare(KeyValuePair<KeyValuePair<int, int>, KeyValuePair<int, int>> a,
261  KeyValuePair<KeyValuePair<int, int>, KeyValuePair<int, int>> b)
262  {
263  int kc = a.Key.Key.CompareTo(b.Key.Key);
264  return (kc != 0) ? kc : a.Key.Value.CompareTo(b.Key.Value);
265  }
266  }
267 
268  public static KeyValuePair<int, int> FindErrorPosition(int line,
269  int col, Dictionary<KeyValuePair<int, int>,
270  KeyValuePair<int, int>> positionMap)
271  {
272  if (positionMap == null || positionMap.Count == 0)
273  return new KeyValuePair<int, int>(line, col);
274 
275  KeyValuePair<int, int> ret = new KeyValuePair<int, int>();
276 
277  if (positionMap.TryGetValue(new KeyValuePair<int, int>(line, col),
278  out ret))
279  return ret;
280 
281  var sorted = new List<KeyValuePair<KeyValuePair<int, int>, KeyValuePair<int, int>>>(positionMap);
282 
283  sorted.Sort(new kvpSorter());
284 
285  int l = 1;
286  int c = 1;
287  int pl = 1;
288 
289  foreach (KeyValuePair<KeyValuePair<int, int>, KeyValuePair<int, int>> posmap in sorted)
290  {
291  //m_log.DebugFormat("[Compiler]: Scanning line map {0},{1} --> {2},{3}", posmap.Key.Key, posmap.Key.Value, posmap.Value.Key, posmap.Value.Value);
292  int nl = posmap.Value.Key + line - posmap.Key.Key; // New, translated LSL line and column.
293  int nc = posmap.Value.Value + col - posmap.Key.Value;
294  // Keep going until we find the first point passed line,col.
295  if (posmap.Key.Key > line)
296  {
297  //m_log.DebugFormat("[Compiler]: Line is larger than requested {0},{1}, returning {2},{3}", line, col, l, c);
298  if (pl < line)
299  {
300  //m_log.DebugFormat("[Compiler]: Previous line ({0}) is less than requested line ({1}), setting column to 1.", pl, line);
301  c = 1;
302  }
303  break;
304  }
305  if (posmap.Key.Key == line && posmap.Key.Value > col)
306  {
307  // Never move l,c backwards.
308  if (nl > l || (nl == l && nc > c))
309  {
310  //m_log.DebugFormat("[Compiler]: Using offset relative to this: {0} + {1} - {2}, {3} + {4} - {5} = {6}, {7}",
311  // posmap.Value.Key, line, posmap.Key.Key, posmap.Value.Value, col, posmap.Key.Value, nl, nc);
312  l = nl;
313  c = nc;
314  }
315  //m_log.DebugFormat("[Compiler]: Column is larger than requested {0},{1}, returning {2},{3}", line, col, l, c);
316  break;
317  }
318  pl = posmap.Key.Key;
319  l = posmap.Value.Key;
320  c = posmap.Value.Value;
321  }
322  return new KeyValuePair<int, int>(l, c);
323  }
324  }
325 }
Interactive OpenSim region server
Definition: OpenSim.cs:55
static KeyValuePair< int, int > FindErrorPosition(int line, int col, Dictionary< KeyValuePair< int, int >, KeyValuePair< int, int >> positionMap)
Definition: Program.cs:268