Ejemplo n.º 1
0
        public int Compile(string outputFile)
        {
            LSLCodeValidatorStrategies codeValidatorStrategies = new LSLCodeValidatorStrategies
            {
                ExpressionValidator       = ExpressionValidator,
                StringLiteralPreProcessor = StringLiteralPreProcessor
            };


            codeValidatorStrategies.SyntaxErrorListener   = new SyntaxErrorListener(this);
            codeValidatorStrategies.SyntaxWarningListener = new SyntaxWarningListener(this);


            var defaultProvider = new LSLEmbeddedLibraryDataProvider();

            foreach (var library in LibrarySubsets)
            {
                if (defaultProvider.SubsetDescriptions.ContainsKey(library))
                {
                    defaultProvider.ActiveSubsets.Add(library);
                }
                else
                {
                    WriteLine(CmdWarningHeader + "Library subset '{0}' does not exist and was ignored.", library);
                }
            }

            codeValidatorStrategies.LibraryDataProvider = defaultProvider;


            var validator = new LSLCodeValidator(codeValidatorStrategies);


            ILSLCompilationUnitNode validated;

            WriteLine(CmdNoticeHeader + "Compiling '{0}'...", _fileName);

            try
            {
                using (var infile = new StreamReader(_fileName))
                {
                    validated = validator.Validate(infile);


                    if (validator.HasSyntaxErrors)
                    {
                        WriteLine();
                        WriteLine("===============================");
                        WriteLine();
                        WriteLine("Syntax Errors:");
                        WriteLine();

                        foreach (var msg in _syntaxErrorMessages)
                        {
                            WriteLine(msg);
                        }

                        _syntaxErrorMessages.Clear();

                        WriteLine("===============================");
                        WriteLine();
                    }


                    if (validator.HasSyntaxWarnings)
                    {
                        if (!validator.HasSyntaxErrors)
                        {
                            WriteLine();
                            WriteLine("===============================");
                            WriteLine();
                        }

                        WriteLine("Syntax Warnings:");
                        WriteLine();

                        foreach (var msg in _syntaxWarningMessages)
                        {
                            WriteLine(msg);
                        }

                        _syntaxWarningMessages.Clear();

                        WriteLine("===============================");
                        WriteLine();
                    }

                    if (validator.HasSyntaxErrors)
                    {
                        WriteLine("Compilation phase did not start due to syntax errors.");
                        return(ReturnCode.SyntaxErrors);
                    }
                }
            }
            catch (IOException error)
            {
                WriteLine(CmdErrorHeader + "Input File '{0}' could not be read from.", _fileName);
                WriteLine();
                WriteLine(CmdExceptionHeader + error.Message);
                return(ReturnCode.InputFileUnreadable);
            }
            catch (UnauthorizedAccessException error)
            {
                WriteLine(CmdErrorHeader + "Input File '{0}' could not be read from.", _fileName);
                WriteLine();
                WriteLine(CmdExceptionHeader + error.Message);
                return(ReturnCode.InputFileUnreadable);
            }
            catch (LSLCodeValidatorInternalException error)
            {
                WriteLine();
                WriteLine("Code Validator, internal error.");
                WriteLine();
                WriteLine(CmdExceptionHeader + error.Message);
                WriteLine();
                WriteLine(InternalErrorMessage);
                return(ReturnCode.CodeValidatorInternalError);
            }
            catch (Exception error)
            {
                WriteLine();
                WriteLine("Code Validator, unknown error.");
                WriteLine();
                WriteLine(CmdExceptionHeader + error.Message);
                WriteLine();
                WriteLine(InternalErrorMessage);
                return(ReturnCode.CodeValidatorUnknownError);
            }


            //==========
            // Compile Tree Into Code
            //==========


            LSLOpenSimCompilerSettings compilerSettings;


            if (!ClientCode)
            {
                compilerSettings =
                    LSLOpenSimCompilerSettings.CreateOpenSimServerSide();

                compilerSettings.ScriptHeader = ServerSideScriptCompilerHeader;
                compilerSettings.InsertCoOpTerminationCalls = CoOpStop;
            }
            else
            {
                compilerSettings =
                    LSLOpenSimCompilerSettings.CreateOpenSimClientSide();

                compilerSettings.ScriptHeader = ClientSideScriptCompilerHeader;
                compilerSettings.InsertCoOpTerminationCalls = CoOpStop;
            }
            try
            {
                var dir = Path.GetDirectoryName(outputFile);

                if (!string.IsNullOrWhiteSpace(dir))
                {
                    Directory.CreateDirectory(dir);
                }

                using (var outfile = File.Create(outputFile))
                {
                    var compiler = new LSLOpenSimCompiler(defaultProvider, compilerSettings);

                    compiler.Compile(validated, new StreamWriter(outfile, Encoding.UTF8));
                }

                WriteLine("Finished, output to \"" + outputFile + "\"");
            }
            catch (IOException error)
            {
                WriteLine(CmdErrorHeader + "Output File '{0}' could not be written to.", outputFile);
                WriteLine();
                WriteLine(CmdExceptionHeader + error.Message);
                return(ReturnCode.OutputFileUnwritable);
            }
            catch (UnauthorizedAccessException error)
            {
                WriteLine(CmdErrorHeader + "Output File '{0}' could not be written to.", outputFile);
                WriteLine();
                WriteLine(CmdExceptionHeader + error.Message);
                return(ReturnCode.OutputFileUnwritable);
            }
            catch (LSLCompilerInternalException error)
            {
                WriteLine();
                WriteLine("Compiler internal error:");
                WriteLine();
                WriteLine(CmdExceptionHeader + error.Message);
                WriteLine();
                WriteLine(InternalErrorMessage);
                return(ReturnCode.CompilerInternalError);
            }
            catch (Exception error)
            {
                WriteLine();
                WriteLine("Compiler unknown error:");
                WriteLine();
                WriteLine(CmdExceptionHeader + error.Message);
                WriteLine();
                WriteLine(InternalErrorMessage);
                return(ReturnCode.CompilerUnknownError);
            }

            return(ReturnCode.Success);
        }
Ejemplo n.º 2
0
        public static int Main(string[] args)
        {
            var defaultLibraryDataProvider = new LSLEmbeddedLibraryDataProvider();

            ArgParser argParser = new ArgParser();


            argParser.AddSwitch(new ArgSwitchDesc("-i")
            {
                MinArgs  = 1,
                HelpLine = "One or more input files or glob expressions (quote globs on *nix).",
            })
            .AddWriteBeforeShortHelp((sender, e) =>
            {
                e.Writer.WriteLine();
                e.Writer.WriteLine("LibLSLCC command line OpenSim LSL compiler");
                e.Writer.WriteLine();
                e.Writer.WriteLine();
                e.Writer.WriteLine("Examples:");
                e.Writer.WriteLine();
                e.Writer.WriteLine(argParser.HelpDescriptionIndent + "lslcc -i script.lsl -o script.cs");
                e.Writer.WriteLine();
                e.Writer.WriteLine(
                    argParser.HelpDescriptionIndent +
                    "lslcc -i script.lsl dir{0}script2.lsl -o \"{{dir}}{{name}}.cs\"", Path.DirectorySeparatorChar);
                e.Writer.WriteLine();
                e.Writer.WriteLine(
                    argParser.HelpDescriptionIndent +
                    "lslcc -i \"dir{0}**{0}*.lsl\" \"dir2{0}*\" -o \"{{dir}}{{name}}.cs\"  (built in globbing)",
                    Path.DirectorySeparatorChar);
                e.Writer.WriteLine();
                e.Writer.WriteLine();
            });


            argParser.AddSwitch(new ArgSwitchDesc("-o")
            {
                MinArgs          = 1,
                MaxArgs          = 1,
                HelpLine         = "(Optional) output file or output file name template.",
                DescriptionLines =
                {
                    "If you do not specify an output file or output file template, the directory and",
                    "name of the input file is used and given a '.cs' extension (equivalent to -o \"{dir}{name}.cs\".",
                    "In that case, the output file is written to the directory the input file resides in.",
                    "",
                    "Note that the \"{dir}\" template expands to the directory the source code is in, with a trailing",
                    "directory separator at the end."
                }
            });

            argParser.AddSwitch(new ArgSwitchDesc("-log")
            {
                MinArgs          = 1,
                MaxArgs          = 1,
                HelpLine         = "log file or log file name template.",
                DescriptionLines =
                {
                    "If this is a file name template such as \"{dir}{name}.log\", then a separate log file is created",
                    "for each input file.  Otherwise, all compiler output is appended to the specified file.",
                    "",
                    "The template \"{returncode}\" can also be used in the log file name, a textual representation of",
                    "the compiler return code will be written in its place.  See -returncodes for return code names."
                }
            });


            argParser.AddSwitch(new ArgSwitchDesc("-librarysubsets")
            {
                MinArgs          = 1,
                MaxArgs          = 1,
                HelpLine         = "subset1;subset2;... (default is just lsl)",
                DescriptionLines =
                {
                    "Set the available library subsets when compiling ( Separated by semi-colons ; )",
                    "Spaces are not allowed between the names and the semi-colons unless you quote the string.",
                    "",
                    "All acceptable values are:",
                    "",
                    string.Join(";", defaultLibraryDataProvider.PossibleSubsets)
                }
            });



            argParser.AddSwitch(new ArgSwitchDesc("-clientcode")
            {
                MaxArgs          = 0,
                HelpLine         = "Generate client uploadable code",
                DescriptionLines =
                {
                    "Compile client uploadable code that works with all versions of OpenSim starting with 0.8, ",
                    "but does not support script resets.",
                    "",
                    "The default behavior of lslcc is to compile server side code, which cannot be uploaded",
                    "from the client unless the server your using is modified to allow it."
                }
            });


            argParser.AddSwitch(new ArgSwitchDesc("-coop-stop")
            {
                MaxArgs          = 0,
                DescriptionLines =
                {
                    "Insert cooperative termination calls used by OpenSim when co-op script stop mode is enabled.",
                }
            });


            argParser.AddSwitch(new ArgSwitchDesc("-returncodes")
            {
                MustBeUsedAlone = true,
                MaxArgs         = 0,
                HelpLine        = "show lslcc return code descriptions."
            })
            .AddWriteAfterShortHelp((sender, e) => { e.Writer.WriteLine(); });


            argParser.AddSwitch(new ArgSwitchDesc("-h")
            {
                MustBeUsedAlone = true,
                MaxArgs         = 1,
                HelpLine        = "show lslcc general help."
            });

            argParser.AddSwitch(new ArgSwitchDesc("-v")
            {
                MustBeUsedAlone = true,
                MaxArgs         = 0,
                HelpLine        = "show lslcc version and program info."
            })
            .AddWriteAfterShortHelp((sender, e) => { e.Writer.WriteLine(); });


            Dictionary <string, ArgSwitch> prms;

            try
            {
                prms = argParser.ParseArgs(args).ToDictionary(x => x.Name);
            }
            catch (ArgParseException e)
            {
                Console.WriteLine(e.Message);
                return(ReturnCode.InvalidOption);
            }


            if (prms.Count == 0)
            {
                Console.WriteLine("No arguments specified, see -h for help.");
                return(ReturnCode.InvalidOption);
            }


            if (prms[""].Arguments.Count > 0)
            {
                Console.WriteLine("Invalid arguments, see -h for help.");
                return(ReturnCode.UnknownOption);
            }


            if (prms.ContainsKey("-returncodes"))
            {
                WriteReturnCodes();
                return(ReturnCode.Success);
            }
            if (prms.ContainsKey("-h"))
            {
                argParser.WriteHelp(Console.Out);
                return(ReturnCode.Success);
            }
            if (prms.ContainsKey("-v"))
            {
                WriteAbout();
                return(ReturnCode.Success);
            }



            ArgSwitch inputFiles;

            if (!prms.TryGetValue("-i", out inputFiles))
            {
                Console.WriteLine("Input file(s) not specified, use -i for help.");
                return(ReturnCode.MissingInputFile);
            }



            ArgSwitch subsets;
            var       specifiedLibrarySubsets = new HashSet <string>();

            if (!prms.TryGetValue("-librarysubsets", out subsets))
            {
                specifiedLibrarySubsets.Add("lsl");
            }
            else
            {
                var subsetString = subsets.Arguments.First();
                foreach (var subset in subsetString.Split(';'))
                {
                    if (subset == "lsl" && specifiedLibrarySubsets.Contains("os-lsl"))
                    {
                        Console.WriteLine("The library subset \"lsl\" cannot be used when the subset \"os-lsl\" is already specified.");
                        return(ReturnCode.InvalidOption);
                    }

                    if (subset == "os-lsl" && specifiedLibrarySubsets.Contains("lsl"))
                    {
                        Console.WriteLine("The library subset \"os-lsl\" cannot be used when the subset \"lsl\" is already specified.");
                        return(ReturnCode.InvalidOption);
                    }

                    specifiedLibrarySubsets.Add(subset);
                }
            }


            var specifiedFiles = new HashSet <string>();

            foreach (var file in inputFiles.Arguments
                     .SelectMany(x => new Glob.Glob(x).Expand()
                                 .Where(y => y.Attributes != FileAttributes.Directory)))
            {
                if (specifiedFiles.Contains(file.FullName))
                {
                    Console.WriteLine("Input file \"{0}\" specified more than once.", file.FullName);
                    return(ReturnCode.InvalidOption);
                }

                specifiedFiles.Add(file.FullName);
            }

            if (specifiedFiles.Count == 0)
            {
                Console.WriteLine("The specified input file(s) could not be found.");
                return(ReturnCode.InvalidOption);
            }



            string     logFileName = null;
            TextWriter singularLog = null;
            bool       multiLog    = false;

            ArgSwitch logFile;

            if (prms.TryGetValue("-log", out logFile))
            {
                logFileName = logFile.Arguments.First();

                if (!IsMultiFileOutputLogTemplate(logFileName))
                {
                    try
                    {
                        singularLog = new StreamWriter(logFileName)
                        {
                            AutoFlush = true
                        };
                    }
                    catch (IOException e)
                    {
                        Console.WriteLine("Could not open log file \"{0}\" for writing.", logFileName);
                        Console.WriteLine("Reason: " + e.Message);
                        return(ReturnCode.LogFileAccessError);
                    }
                    catch (UnauthorizedAccessException e)
                    {
                        Console.WriteLine("Could not open log file \"{0}\" for writing.", logFileName);
                        Console.WriteLine("Reason: " + e.Message);
                        return(ReturnCode.LogFileAccessError);
                    }
                }
                else
                {
                    multiLog = true;
                }
            }


            int returnCode = ReturnCode.Success;

            Console.WriteLine();

            try
            {
                bool firstFile = true;

                foreach (var file in specifiedFiles)
                {
                    specifiedFiles.Add(file);

                    var compiler = new InputFileCompiler(file)
                    {
                        LibrarySubsets = specifiedLibrarySubsets,
                        ClientCode     = prms.ContainsKey("-clientcode"),
                        CoOpStop       = prms.ContainsKey("-coop-stop")
                    };


                    ArgSwitch outFile;

                    var outputFile = file + ".cs";

                    if (prms.TryGetValue("-o", out outFile))
                    {
                        outputFile = outFile.Arguments.First();

                        if (IsMultiFileOutputTemplate(outputFile))
                        {
                            outputFile = ExpandOutputFileVars(file, outputFile);
                        }
                    }

                    returnCode = compiler.Compile(outputFile);

                    if (multiLog)
                    {
                        var outLogFile = ExpandOutputLogFileVars(file, logFileName, returnCode);

                        var directory = Path.GetDirectoryName(outLogFile);
                        if (directory != null)
                        {
                            Directory.CreateDirectory(directory);
                        }

                        try
                        {
                            using (var writer = new StreamWriter(outLogFile)
                            {
                                AutoFlush = true
                            })
                            {
                                if (!firstFile)
                                {
                                    WriteLogSeperator(Console.Out);
                                }
                                compiler.WriteMessageQueue(true, Console.Out, writer);
                            }
                        }
                        catch (IOException)
                        {
                            Console.WriteLine("NOTICE: Could not write log file \"{0}\" due to IO error.", outLogFile);
                        }
                    }
                    else
                    {
                        if (singularLog != null)
                        {
                            try
                            {
                                if (!firstFile)
                                {
                                    WriteLogSeperator(Console.Out);
                                    WriteLogSeperator(singularLog);
                                }
                                compiler.WriteMessageQueue(true, Console.Out, singularLog);
                            }
                            catch (IOException)
                            {
                                Console.WriteLine("NOTICE: Could not write log file \"{0}\" due to IO error.", logFileName);
                            }
                        }
                        else
                        {
                            if (!firstFile)
                            {
                                WriteLogSeperator(Console.Out);
                            }
                            compiler.WriteMessageQueue(true);
                        }
                    }

                    firstFile = false;
                }
            }
            finally
            {
                if (singularLog != null)
                {
                    singularLog.Close();
                }
            }

            return(returnCode);
        }