示例#1
0
 public void Loaded(Assembler assembler)
 {
     assembler.AssemblyComplete += new EventHandler<AssemblyCompleteEventArgs>(assembler_AssemblyComplete);
     assembler.TryHandleParameter += new EventHandler<HandleParameterEventArgs>(assembler_TryHandleParameter);
     assembler.AddHelpEntry("0x10co.de:\n" +
         "\t--0x10co.de: Upload the output to 0x10co.de automatically.");
 }
示例#2
0
文件: Plugin.cs 项目: Kelmoir/organic
 public void Loaded(Assembler assembler)
 {
     this.assembler = assembler;
     assembler.AddHelpEntry("TestPlugin:\n" +
         "\t--cow: Output a cow to the console.");
     assembler.TryHandleParameter += new EventHandler<HandleParameterEventArgs>(assembler_TryHandleParameter);
     assembler.EvaluateExpressionValue += new EventHandler<EvaluateValueEventArgs>(assembler_EvaluateExpressionValue);
 }
 public void Loaded(Assembler assembler)
 {
     assembler.AddHelpEntry("DUnit Unit Test Tool:\n" +
         "Use --export-tests [file] to create a test file.\n" +
         "DUnit adds a number of directives for your use.  They are:\n" +
         ".prereq [tests]: Defines a section of code as being required before executing\n" +
             "\tthe specified tests (ALL, NONE, or a comma-delimited list of names.\n" +
         ".test [name]: Creates a unit test with the given name.\n" +
         ".endtest: Closes the test block from the matching .test directive.\n" +
         ".assert: Only valid within a .test block.  You may use register names and\n" +
             "\tmemory locations to check values at test-time.  For instance:\n" +
             "\t.assert [0x8012+A]==[screen_buffer]\n" +
         "All tests will be removed from the normal Organic output.");
     assembler.TryHandleParameter += new EventHandler<HandleParameterEventArgs>(assembler_TryHandleParameter);
     assembler.AssemblyComplete += new EventHandler<AssemblyCompleteEventArgs>(assembler_AssemblyComplete);
     assembler.HandleCodeLine += new EventHandler<HandleCodeEventArgs>(assembler_HandleCodeLine);
     CurrentSection = "NONE";
     Assembler = assembler;
     Tests = new List<UnitTest>();
 }
示例#4
0
 private static void ListPlugins(Assembler assembler)
 {
     assembler.LoadPlugins();
     Console.WriteLine("Listing plugins:");
     foreach (var plugin in assembler.LoadedPlugins)
         Console.WriteLine(plugin.Value.Name + ": " + plugin.Value.Description);
 }
示例#5
0
        public static int Main(string[] args)
        {
            DateTime startTime = DateTime.Now;
            int returnCode = 0;

            DisplaySplash();
            if (args.Length == 0)
            {
                DisplayHelp();
                return 1;
            }
            string inputFile = null;
            string outputFile = null;
            string listingFile = null;
            string jsonFile = null;
            string pipe = null;
            string workingDirectory = Directory.GetCurrentDirectory();
            bool bigEndian = true, quiet = false, verbose = false;
            Assembler assembler = new Assembler();
            assembler.IncludePath = Environment.GetEnvironmentVariable("ORGINCLUDE");
            if (string.IsNullOrEmpty(assembler.IncludePath))
                assembler.IncludePath = "";
            for (int i = 0; i < args.Length; i++)
            {
                string arg = args[i];
                if (arg.StartsWith("-"))
                {
                    try
                    {
                        switch (arg)
                        {
                            case "-h":
                            case "-?":
                            case "/h":
                            case "/?":
                            case "--help":
                                DisplayHelp();
                                return 1;
                            case "-o":
                            case "--output":
                            case "--output-file":
                                outputFile = args[++i];
                                break;
                            case "--input-file":
                                inputFile = args[++i];
                                break;
                            case "-e":
                            case "--equate":
                                ExpressionResult result = assembler.ParseExpression(args[i + 2]);
                                if (!result.Successful)
                                {
                                    Console.WriteLine("Error: " + ListEntry.GetFriendlyErrorMessage(ErrorCode.IllegalExpression));
                                    return 1;
                                }
                                assembler.Values.Add(args[i + 1].ToLower(), result.Value);
                                i += 2;
                                break;
                            case "-l":
                            case "--listing":
                                listingFile = args[++i];
                                break;
                            case "--little-endian":
                                bigEndian = false;
                                break;
                            case "--long-literals":
                                assembler.ForceLongLiterals = true;
                                break;
                            case "--quiet":
                            case "-q":
                                quiet = true;
                                break;
                            case "--pipe":
                            case "-p":
                                pipe = args[++i];
                                break;
                            case "--json":
                                jsonFile = args[++i];
                                break;
                            case "--include":
                            case "-i":
                                assembler.IncludePath = Environment.GetEnvironmentVariable("ORGINCLUDE") + ";" + args[++i];
                                break;
                            case "--plugins":
                                ListPlugins(assembler);
                                return 0;
                            case "--working-directory":
                            case "-w":
                                workingDirectory = args[++i];
                                break;
                            case "--verbose":
                            case "-v":
                                verbose = true;
                                break;
                            case "--debug-mode":
                                Console.ReadKey();
                                break;
                            case "--install":
                                assembler.InstallPlugin(args[++i]);
                                return 0;
                            case "--remove":
                                assembler.RemovePlugin(args[++i]);
                                return 0;
                            case "--search":
                                assembler.SearchPlugins(args[++i]);
                                return 0;
                            case "--info":
                                assembler.GetInfo(args[++i]);
                                return 0;
                            default:
                                HandleParameterEventArgs hpea = new HandleParameterEventArgs(arg);
                                hpea.Arguments = args;
                                hpea.Index = i;
                                if (assembler.TryHandleParameter != null)
                                    assembler.TryHandleParameter(assembler, hpea);
                                if (!hpea.Handled)
                                {
                                    Console.WriteLine("Error: Invalid parameter: " + arg + "\nUse Organic.exe --help for usage information.");
                                    return 1;
                                }
                                else
                                    i = hpea.Index;
                                if (hpea.StopProgram)
                                    return 0;
                                break;
                        }
                    }
                    catch (ArgumentOutOfRangeException)
                    {
                        Console.WriteLine("Error: Missing argument: " + arg + "\nUse Organic.exe --help for usage information.");
                        return 1;
                    }
                }
                else
                {
                    if (inputFile == null)
                        inputFile = arg;
                    else if (outputFile == null)
                        outputFile = arg;
                    else
                    {
                        Console.WriteLine("Error: Invalid parameter: " + arg + "\nUse Organic.exe --help for usage information.");
                        return 1;
                    }
                }
            }
            if (inputFile == null && pipe == null)
            {
                Console.WriteLine("Error: No input file specified.\nUse Organic.exe --help for usage information.");
                return 1;
            }
            if (outputFile == null)
                outputFile = Path.GetFileNameWithoutExtension(inputFile) + ".bin";
            if (!File.Exists(inputFile) && pipe == null && inputFile != "-")
            {
                Console.WriteLine("Error: File not found (" + inputFile + ")");
                return 1;
            }

            string contents;
            if (pipe == null)
            {
                if (inputFile != "-")
                {
                    StreamReader reader = new StreamReader(inputFile);
                    contents = reader.ReadToEnd();
                    reader.Close();
                }
                else
                    contents = Console.In.ReadToEnd();
            }
            else
                contents = pipe;

            List<ListEntry> output;
            string wdOld = Directory.GetCurrentDirectory();
            Directory.SetCurrentDirectory(workingDirectory);
            if (pipe == null)
                output = assembler.Assemble(contents, inputFile);
            else
                output = assembler.Assemble(contents, "[piped input]");
            Directory.SetCurrentDirectory(wdOld);

            if (assembler.AssemblyComplete != null)
                assembler.AssemblyComplete(assembler, new AssemblyCompleteEventArgs(output));

            // Output errors
            if (!quiet)
            {
                foreach (var entry in output)
                {
                    if (entry.ErrorCode != ErrorCode.Success)
                    {
                        Console.Error.WriteLine("Error " + entry.FileName + " (line " + entry.LineNumber + "): " +
                                          ListEntry.GetFriendlyErrorMessage(entry.ErrorCode));
                        returnCode = 1;
                    }
                    if (entry.WarningCode != WarningCode.None)
                        Console.WriteLine("Warning " + entry.FileName + " (line " + entry.LineNumber + "): " +
                            ListEntry.GetFriendlyWarningMessage(entry.WarningCode));
                }
            }

            ushort currentAddress = 0;
            Stream binStream = null;
            if (outputFile != "-")
            {
                if (!string.IsNullOrEmpty(Path.GetDirectoryName(outputFile)))
                    Directory.CreateDirectory(Path.GetDirectoryName(outputFile));
                binStream = File.Open(outputFile, FileMode.Create);
            }
            foreach (var entry in output)
            {
                if (entry.Output != null)
                {
                    foreach (ushort value in entry.Output)
                    {
                        currentAddress++;
                        byte[] buffer = BitConverter.GetBytes(value);
                        if (bigEndian)
                            Array.Reverse(buffer);
                        if (outputFile != "-")
                            binStream.Write(buffer, 0, buffer.Length);
                        else
                            Console.Out.Write(Encoding.ASCII.GetString(buffer));
                    }
                }
            }

            string listing = "";

            if (listingFile != null || verbose)
                listing = CreateListing(output);

            string json = "";

            if (jsonFile != null)
                json = CreateJson(output);

            if (verbose)
                Console.Write(listing);
            if (listingFile != null)
            {
                if (!string.IsNullOrEmpty(Path.GetDirectoryName(listingFile)))
                    Directory.CreateDirectory(Path.GetDirectoryName(listingFile));
                var writer = new StreamWriter(listingFile);
                writer.Write(listing);
                writer.Close();
            }

            if (jsonFile != null)
            {
                if (!string.IsNullOrEmpty(Path.GetDirectoryName(jsonFile)))
                    Directory.CreateDirectory(Path.GetDirectoryName(jsonFile));
                var writer = new StreamWriter(jsonFile);
                writer.Write(json);
                writer.Close();
            }

            TimeSpan duration = DateTime.Now - startTime;
            Console.WriteLine("Organic build complete " + duration.TotalMilliseconds + "ms");
            return returnCode;
        }
示例#6
0
        /// <summary>
        /// Given an expression, it will parse it and return the result as a nullable ushort
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public ExpressionResult ParseExpression(string value)
        {
            ExpressionResult expressionResult = new ExpressionResult();
            expressionResult.Successful = true;
            expressionResult.References = new List<string>();
            value = value.Trim();
            if (HandleExpression != null)
            {
                HandleExpressionEventArgs heea = new HandleExpressionEventArgs(value);
                HandleExpression(this, heea);
                value = heea.Expression;
            }
            if (value.SafeContains('('))
            {
                // Check for advanced expression handlers
                foreach (var item in ExpressionExtensions)
                {
                    if (value.StartsWith(item.Key.ToLower() + "("))
                    {
                        string expr = value.Substring(value.SafeIndexOf('(') + 1);
                        expr = expr.Remove(expr.Length - 1);
                        expressionResult.Value = item.Value(expr);
                        return expressionResult;
                    }
                }
                return EvaluateParenthesis(value);
            }
            if (value.StartsWith("~"))
            {
                expressionResult = ParseExpression(value.Substring(1));
                if (expressionResult.Successful)
                    expressionResult.Value = (ushort)~expressionResult.Value;
                return expressionResult;
            }
            if (!HasOperators(value))
            {
                // Parse value
                ushort result;
                EvaluateValueEventArgs args = new EvaluateValueEventArgs(value);
                if (EvaluateExpressionValue != null)
                {
                    EvaluateExpressionValue(this, args);
                }
                if (args.Handled)
                {
                    expressionResult.Value = args.Result;
                    return expressionResult;
                }
                else if (value.StartsWith("0d"))
                    value = value.Substring(2);
                if (value.StartsWith("'")) // Character
                {
                    if (value.Length < 3)
                    {
                        expressionResult.Successful = false;
                        return expressionResult;
                    }
                    value = value.Substring(1, value.Length - 2).Unescape();
                    if (value == null)
                    {
                        expressionResult.Successful = false;
                        return expressionResult;
                    }
                    if (value.Length != 1)
                    {
                        expressionResult.Successful = false;
                        return expressionResult;
                    }
                    expressionResult.Value = (ushort)Encoding.ASCII.GetBytes(value)[0];
                    return expressionResult;
                }
                else if (value.StartsWith("{") && value.EndsWith("}")) // instruction literal
                {
                    string instruction = value.Substring(1, value.Length - 2);
                    Assembler subAssembler = new Assembler();
                    List<ListEntry> assembly = subAssembler.Assemble(instruction);
                    if (assembly.Count == 0)
                    {
                        expressionResult.Successful = false;
                        return expressionResult;
                    }
                    if (assembly[0].Output == null)
                    {
                        expressionResult.Successful = false;
                        return expressionResult;
                    }
                    if (assembly[0].Output.Length == 0)
                    {
                        expressionResult.Successful = false;
                        return expressionResult;
                    }
                    expressionResult.Value = assembly[0].Output[0];
                    return expressionResult;
                }
                else if (value.StartsWith("0x")) // Hex
                {
                    value = value.Substring(2);
                    if (!ushort.TryParse(value.Replace("_", ""), NumberStyles.HexNumber, null, out result))
                    {
                        expressionResult.Successful = false;
                        return expressionResult;
                    }
                    else
                    {
                        expressionResult.Value = result;
                        return expressionResult;
                    }
                }
                else if (value.StartsWith("0b")) // Binary
                {
                    value = value.Substring(2);
                    ushort? binResult = ParseBinary(value.Replace("_", ""));
                    if (binResult == null)
                        expressionResult.Successful = false;
                    else
                        expressionResult.Value = binResult.Value;
                    return expressionResult;
                }
                else if (value.StartsWith("0o"))
                {
                    value = value.Substring(2);
                    try
                    {
                        expressionResult.Value = Convert.ToUInt16(value.Replace("_", ""), 8);
                        return expressionResult;
                    }
                    catch
                    {
                        expressionResult.Successful = false;
                        return expressionResult;
                    }
                }
                else if (ushort.TryParse(value.Replace("_", ""), out result)) // Decimal
                {
                    expressionResult.Value = result;
                    return expressionResult;
                }
                else if (value == "$")
                {
                    if (LineNumbers.Count == 0)
                    {
                        expressionResult.Successful = false;
                        return expressionResult;
                    }
                    expressionResult.Value = currentAddress;
                    return expressionResult;
                }
                else if (value.StartsWith("$")) // Relative label
                {
                    if (LineNumbers.Count == 0)
                    {
                        expressionResult.Successful = false;
                        return expressionResult;
                    }
                    value = value.Substring(1);
                    int nextLabelIndex = -1;
                    // Find the next relative label after the current line
                    for (int i = 0; i < RelativeLabels.Count; i++)
                    {
                        if (RelativeLabels.ElementAt(i).Key > LineNumbers.Peek())
                        {
                            nextLabelIndex = i;
                            break;
                        }
                    }
                    if (nextLabelIndex == -1)
                        nextLabelIndex = RelativeLabels.Count - 1; // If no such label is found, use the last one
                    bool initialPlus = true;
                    // For each plus, increment that label index, and each minus decrements it
                    foreach (char c in value)
                    {
                        if (c == '+') // The intial plus symbol is ignored
                        {
                            if (initialPlus)
                                nextLabelIndex++;
                            initialPlus = false;
                        }
                        else if (c == '-')
                            nextLabelIndex--;
                    }
                    if (nextLabelIndex < 0)
                    {
                        expressionResult.Successful = false;
                        return expressionResult;
                    }
                    if (nextLabelIndex > RelativeLabels.Count - 1)
                    {
                        expressionResult.Successful = false;
                        return expressionResult;
                    }
                    expressionResult.Value = RelativeLabels.ElementAt(nextLabelIndex).Value;
                    return expressionResult;
                }
                else if (value.ToLower() == "true")
                {
                    expressionResult.Value = 1;
                    return expressionResult;
                }
                else if (value.ToLower() == "false")
                {
                    expressionResult.Value = 0;
                    return expressionResult;
                }
                else // Defined value or error
                {
                    if (value.StartsWith("."))
                        value = PriorGlobalLabel + "_" + value.Substring(1);
                    if (Values.ContainsKey(value))
                        expressionResult.Value = Values[value];
                    else if (LabelValues.ContainsKey(value))
                    {
                        expressionResult.Relocate = true;
                        expressionResult.Value = LabelValues.GetValue(value);
                    }
                    else
                        expressionResult.Successful = false;
                    expressionResult.References.Add(value);
                    if (!ReferencedValues.Contains(value))
                        ReferencedValues.Add(value);
                    return expressionResult;
                }
            }

            // Parse expression
            string[] operands = GetOperands(value);
            if (operands == null)
            {
                expressionResult.Successful = false;
                return expressionResult;
            }
            if (string.IsNullOrEmpty(operands[0]) && operands[1] == "-")
            {
                expressionResult = ParseExpression(operands[2]);
                expressionResult.Value = (ushort)-expressionResult.Value;
                return expressionResult;
            }
            if (operands == null)
            {
                expressionResult.Successful = false;
                return expressionResult;
            }
            ExpressionResult left = ParseExpression(operands[0]);
            ExpressionResult right = ParseExpression(operands[2]);
            expressionResult.References.AddRange(left.References.Concat(right.References));
            if ((!left.Successful || !right.Successful) && operands[1] != "===" && operands[1] != "!==")
            {
                expressionResult.Successful = false;
                return expressionResult;
            }
            switch (operands[1])
            {
                case "*":
                    expressionResult.Value = (ushort)(left.Value * right.Value);
                    break;
                case "/":
                    expressionResult.Value =  (ushort)(left.Value / right.Value);
                    break;
                case "+":
                    expressionResult.Value =  (ushort)(left.Value + right.Value);
                    break;
                case "-":
                    expressionResult.Value =  (ushort)(left.Value - right.Value);
                    break;
                case "<<":
                    expressionResult.Value =  (ushort)(left.Value << right.Value);
                    break;
                case ">>":
                    expressionResult.Value =  (ushort)(left.Value >> right.Value);
                    break;
                case "|":
                    expressionResult.Value =  (ushort)(left.Value | right.Value);
                    break;
                case "^":
                    expressionResult.Value =  (ushort)(left.Value ^ right.Value);
                    break;
                case "&":
                    expressionResult.Value =  (ushort)(left.Value & right.Value);
                    break;
                case "%":
                    expressionResult.Value =  (ushort)(left.Value % right.Value);
                    break;
                case "==":
                    expressionResult.Value =  (ushort)(left.Value == right.Value ? 1 : 0);
                    break;
                case "!=":
                case "<>":
                    expressionResult.Value =  (ushort)(left.Value != right.Value ? 1 : 0);
                    break;
                case "<":
                    expressionResult.Value =  (ushort)(left.Value < right.Value ? 1 : 0);
                    break;
                case ">":
                    expressionResult.Value =  (ushort)(left.Value > right.Value ? 1 : 0);
                    break;
                case "<=":
                    expressionResult.Value =  (ushort)(left.Value <= right.Value ? 1 : 0);
                    break;
                case ">=":
                    expressionResult.Value =  (ushort)(left.Value >= right.Value ? 1 : 0);
                    break;
                case "===":
                    expressionResult.Value = (ushort)(operands[0].ToLower().Trim() == operands[2].ToLower().Trim() ? 1 : 0);
                    break;
                case "!==":
                    expressionResult.Value = (ushort)(operands[0].ToLower().Trim() != operands[2].ToLower().Trim() ? 1 : 0);
                    break;
                case "&&":
                    expressionResult.Value = (ushort)(left.Value > 0 && right.Value > 1 ? 1 : 0);
                    break;
                case "||":
                    expressionResult.Value = (ushort)(left.Value > 0 || right.Value > 1 ? 1 : 0);
                    break;
                case "^^":
                    expressionResult.Value = (ushort)(left.Value > 0 ^ right.Value > 1 ? 1 : 0); // between boolean operators, ^ is ^^ in C#
                    break;
                default:
                    expressionResult.Successful = false;
                    return expressionResult;
            }
            return expressionResult;
        }
示例#7
0
        public static int Main(string[] args)
        {
            DateTime startTime  = DateTime.Now;
            int      returnCode = 0;

            Console.OutputEncoding = Encoding.UTF8;
            Console.WriteLine("Organic DCPU-16 Assembler © 2017, Drew DeVault & DankParrot");
            if (args.Length == 0)
            {
                DisplayHelp();
                return(1);
            }
            string inputFile        = null;
            string outputFile       = null;
            string listingFile      = null;
            string jsonFile         = null;
            string pipe             = null;
            string workingDirectory = Directory.GetCurrentDirectory();
            bool   bigEndian        = true;
            bool   quiet            = false;
            bool   verbose          = false;

            Assembler assembler = new Assembler();

            assembler.IncludePath = Environment.GetEnvironmentVariable("ORGINCLUDE");
            if (string.IsNullOrEmpty(assembler.IncludePath))
            {
                assembler.IncludePath = "";
            }
            for (int i = 0; i < args.Length; i++)
            {
                string arg = args[i];
                if (arg.StartsWith("-"))
                {
                    try
                    {
                        switch (arg)
                        {
                        case "-h":
                        case "-?":
                        case "/h":
                        case "/?":
                        case "--help":
                            DisplayHelp();
                            return(1);

                        case "-o":
                        case "--output":
                        case "--output-file":
                            outputFile = args[++i];
                            break;

                        case "--input-file":
                            inputFile = args[++i];
                            break;

                        case "-e":
                        case "--equate":
                            ExpressionResult result = assembler.ParseExpression(args[i + 2]);
                            if (!result.Successful)
                            {
                                Console.WriteLine("Error: " + ListEntry.GetFriendlyErrorMessage(ErrorCode.IllegalExpression));
                                return(1);
                            }
                            assembler.Values.Add(args[i + 1].ToLower(), result.Value);
                            i += 2;
                            break;

                        case "-l":
                        case "--listing":
                            listingFile = args[++i];
                            break;

                        case "--little-endian":
                            bigEndian = false;
                            break;

                        case "--long-literals":
                            assembler.ForceLongLiterals = true;
                            break;

                        case "--quiet":
                        case "-q":
                            quiet = true;
                            break;

                        case "--pipe":
                        case "-p":
                            pipe = args[++i];
                            break;

                        case "--json":
                            jsonFile = args[++i];
                            break;

                        case "--include":
                        case "-i":
                            assembler.IncludePath = Environment.GetEnvironmentVariable("ORGINCLUDE") + ";" + args[++i];
                            break;

                        case "--working-directory":
                        case "-w":
                            workingDirectory = args[++i];
                            break;

                        case "--verbose":
                        case "-v":
                            verbose = true;
                            break;

                        case "--pause":
                            AppDomain.CurrentDomain.ProcessExit += (s, e) => {
                                Console.Write("Press any key to continue...");
                                Console.ReadKey();
                                Console.WriteLine();
                            };
                            break;

                        case "--debug-mode":
                            Console.ReadKey();
                            break;

                        case "--plugins":
                            ListPlugins(assembler);
                            return(0);

                        case "--install":
                            assembler.InstallPlugin(args[++i]);
                            return(0);

                        case "--remove":
                            assembler.RemovePlugin(args[++i]);
                            return(0);

                        case "--search":
                            assembler.SearchPlugins(args[++i]);
                            return(0);

                        case "--info":
                            assembler.GetInfo(args[++i]);
                            return(0);

                        default:
                            HandleParameterEventArgs hpea = new HandleParameterEventArgs(arg);
                            hpea.Arguments = args;
                            hpea.Index     = i;
                            if (assembler.TryHandleParameter != null)
                            {
                                assembler.TryHandleParameter(assembler, hpea);
                            }
                            if (!hpea.Handled)
                            {
                                Console.WriteLine("Error: Invalid parameter: " + arg + "\nUse Organic.exe --help for usage information.");
                                return(1);
                            }
                            else
                            {
                                i = hpea.Index;
                            }
                            if (hpea.StopProgram)
                            {
                                return(0);
                            }
                            break;
                        }
                    }
                    catch (ArgumentOutOfRangeException)
                    {
                        Console.WriteLine("Error: Missing argument: " + arg + "\nUse Organic.exe --help for usage information.");
                        return(1);
                    }
                }
                else
                {
                    if (inputFile == null)
                    {
                        inputFile = arg;
                    }
                    else if (outputFile == null)
                    {
                        outputFile = arg;
                    }
                    else
                    {
                        Console.WriteLine("Error: Invalid parameter: " + arg + "\nUse Organic.exe --help for usage information.");
                        return(1);
                    }
                }
            }
            if (inputFile == null && pipe == null)
            {
                Console.WriteLine("Error: No input file specified.\nUse Organic.exe --help for usage information.");
                return(1);
            }
            if (outputFile == null)
            {
                outputFile = Path.GetFileNameWithoutExtension(inputFile) + ".bin";
            }
            if (!File.Exists(inputFile) && pipe == null && inputFile != "-")
            {
                Console.WriteLine("Error: File not found (" + inputFile + ")");
                return(1);
            }

            string contents;

            if (pipe == null)
            {
                if (inputFile != "-")
                {
                    StreamReader reader = new StreamReader(inputFile);
                    contents = reader.ReadToEnd();
                    reader.Close();
                }
                else
                {
                    contents = Console.In.ReadToEnd();
                }
            }
            else
            {
                contents = pipe;
            }


            List <ListEntry> output;
            string           wdOld = Directory.GetCurrentDirectory();

            Directory.SetCurrentDirectory(workingDirectory);
            if (pipe == null)
            {
                output = assembler.Assemble(contents, inputFile);
            }
            else
            {
                output = assembler.Assemble(contents, "[piped input]");
            }
            Directory.SetCurrentDirectory(wdOld);

            if (assembler.AssemblyComplete != null)
            {
                assembler.AssemblyComplete(assembler, new AssemblyCompleteEventArgs(output));
            }

            // Output errors
            if (!quiet)
            {
                foreach (var entry in output)
                {
                    if (entry.ErrorCode != ErrorCode.Success)
                    {
                        Console.Error.WriteLine("Error " + entry.FileName + " (line " + entry.LineNumber + "): " +
                                                ListEntry.GetFriendlyErrorMessage(entry.ErrorCode));
                        returnCode = 1;
                    }
                    if (entry.WarningCode != WarningCode.None)
                    {
                        Console.WriteLine("Warning " + entry.FileName + " (line " + entry.LineNumber + "): " +
                                          ListEntry.GetFriendlyWarningMessage(entry.WarningCode));
                    }
                }
            }

            ushort currentAddress = 0;
            Stream binStream      = null;

            if (outputFile != "-")
            {
                if (!string.IsNullOrEmpty(Path.GetDirectoryName(outputFile)))
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(outputFile));
                }
                binStream = File.Open(outputFile, FileMode.Create);
            }
            foreach (var entry in output)
            {
                if (entry.Output != null)
                {
                    foreach (ushort value in entry.Output)
                    {
                        currentAddress++;
                        byte[] buffer = BitConverter.GetBytes(value);
                        if (bigEndian)
                        {
                            Array.Reverse(buffer);
                        }
                        if (outputFile != "-")
                        {
                            binStream.Write(buffer, 0, buffer.Length);
                        }
                        else
                        {
                            Console.Out.Write(Encoding.ASCII.GetString(buffer));
                        }
                    }
                }
            }

            string listing = "";

            if (listingFile != null || verbose)
            {
                listing = CreateListing(output);
            }

            string json = "";

            if (jsonFile != null)
            {
                json = CreateJson(output);
            }

            if (verbose)
            {
                Console.Write(listing);
            }
            if (listingFile != null)
            {
                if (!string.IsNullOrEmpty(Path.GetDirectoryName(listingFile)))
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(listingFile));
                }
                var writer = new StreamWriter(listingFile);
                writer.Write(listing);
                writer.Close();
            }

            if (jsonFile != null)
            {
                if (!string.IsNullOrEmpty(Path.GetDirectoryName(jsonFile)))
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(jsonFile));
                }
                var writer = new StreamWriter(jsonFile);
                writer.Write(json);
                writer.Close();
            }

            TimeSpan duration = DateTime.Now - startTime;

            Console.WriteLine("Organic build complete " + duration.TotalMilliseconds + "ms");
            return(returnCode);
        }
示例#8
0
        /// <summary>
        /// Given an expression, it will parse it and return the result as a nullable ushort
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public ExpressionResult ParseExpression(string value)
        {
            ExpressionResult expressionResult = new ExpressionResult();

            expressionResult.Successful = true;
            expressionResult.References = new List <string>();
            value = value.Trim();
            if (HandleExpression != null)
            {
                HandleExpressionEventArgs heea = new HandleExpressionEventArgs(value);
                HandleExpression(this, heea);
                value = heea.Expression;
            }
            if (value.SafeContains('('))
            {
                // Check for advanced expression handlers
                foreach (var item in ExpressionExtensions)
                {
                    if (value.StartsWith(item.Key.ToLower() + "("))
                    {
                        string expr = value.Substring(value.SafeIndexOf('(') + 1);
                        expr = expr.Remove(expr.Length - 1);
                        expressionResult.Value = item.Value(expr);
                        return(expressionResult);
                    }
                }
                return(EvaluateParenthesis(value));
            }
            if (value.StartsWith("~"))
            {
                expressionResult = ParseExpression(value.Substring(1));
                if (expressionResult.Successful)
                {
                    expressionResult.Value = (ushort)~expressionResult.Value;
                }
                return(expressionResult);
            }
            if (!HasOperators(value))
            {
                // Parse value
                ushort result;
                EvaluateValueEventArgs args = new EvaluateValueEventArgs(value);
                if (EvaluateExpressionValue != null)
                {
                    EvaluateExpressionValue(this, args);
                }
                if (args.Handled)
                {
                    expressionResult.Value = args.Result;
                    return(expressionResult);
                }
                else if (value.StartsWith("0d"))
                {
                    value = value.Substring(2);
                }
                if (value.StartsWith("'")) // Character
                {
                    if (value.Length < 3)
                    {
                        expressionResult.Successful = false;
                        return(expressionResult);
                    }
                    value = value.Substring(1, value.Length - 2).Unescape();
                    if (value == null)
                    {
                        expressionResult.Successful = false;
                        return(expressionResult);
                    }
                    if (value.Length != 1)
                    {
                        expressionResult.Successful = false;
                        return(expressionResult);
                    }
                    expressionResult.Value = (ushort)Encoding.ASCII.GetBytes(value)[0];
                    return(expressionResult);
                }
                else if (value.StartsWith("{") && value.EndsWith("}")) // instruction literal
                {
                    string           instruction  = value.Substring(1, value.Length - 2);
                    Assembler        subAssembler = new Assembler();
                    List <ListEntry> assembly     = subAssembler.Assemble(instruction);
                    if (assembly.Count == 0)
                    {
                        expressionResult.Successful = false;
                        return(expressionResult);
                    }
                    if (assembly[0].Output == null)
                    {
                        expressionResult.Successful = false;
                        return(expressionResult);
                    }
                    if (assembly[0].Output.Length == 0)
                    {
                        expressionResult.Successful = false;
                        return(expressionResult);
                    }
                    expressionResult.Value = assembly[0].Output[0];
                    return(expressionResult);
                }
                else if (value.StartsWith("0x")) // Hex
                {
                    value = value.Substring(2);
                    if (!ushort.TryParse(value.Replace("_", ""), NumberStyles.HexNumber, null, out result))
                    {
                        expressionResult.Successful = false;
                        return(expressionResult);
                    }
                    else
                    {
                        expressionResult.Value = result;
                        return(expressionResult);
                    }
                }
                else if (value.StartsWith("0b")) // Binary
                {
                    value = value.Substring(2);
                    ushort?binResult = ParseBinary(value.Replace("_", ""));
                    if (binResult == null)
                    {
                        expressionResult.Successful = false;
                    }
                    else
                    {
                        expressionResult.Value = binResult.Value;
                    }
                    return(expressionResult);
                }
                else if (value.StartsWith("0o"))
                {
                    value = value.Substring(2);
                    try
                    {
                        expressionResult.Value = Convert.ToUInt16(value.Replace("_", ""), 8);
                        return(expressionResult);
                    }
                    catch
                    {
                        expressionResult.Successful = false;
                        return(expressionResult);
                    }
                }
                else if (ushort.TryParse(value.Replace("_", ""), out result)) // Decimal
                {
                    expressionResult.Value = result;
                    return(expressionResult);
                }
                else if (value == "$")
                {
                    if (LineNumbers.Count == 0)
                    {
                        expressionResult.Successful = false;
                        return(expressionResult);
                    }
                    expressionResult.Value = currentAddress;
                    return(expressionResult);
                }
                else if (value.StartsWith("$")) // Relative label
                {
                    if (LineNumbers.Count == 0)
                    {
                        expressionResult.Successful = false;
                        return(expressionResult);
                    }
                    value = value.Substring(1);
                    int nextLabelIndex = -1;
                    // Find the next relative label after the current line
                    for (int i = 0; i < RelativeLabels.Count; i++)
                    {
                        if (RelativeLabels.ElementAt(i).Key > LineNumbers.Peek())
                        {
                            nextLabelIndex = i;
                            break;
                        }
                    }
                    if (nextLabelIndex == -1)
                    {
                        nextLabelIndex = RelativeLabels.Count - 1; // If no such label is found, use the last one
                    }
                    bool initialPlus = true;
                    // For each plus, increment that label index, and each minus decrements it
                    foreach (char c in value)
                    {
                        if (c == '+') // The intial plus symbol is ignored
                        {
                            if (initialPlus)
                            {
                                nextLabelIndex++;
                            }
                            initialPlus = false;
                        }
                        else if (c == '-')
                        {
                            nextLabelIndex--;
                        }
                    }
                    if (nextLabelIndex < 0)
                    {
                        expressionResult.Successful = false;
                        return(expressionResult);
                    }
                    if (nextLabelIndex > RelativeLabels.Count - 1)
                    {
                        expressionResult.Successful = false;
                        return(expressionResult);
                    }
                    expressionResult.Value = RelativeLabels.ElementAt(nextLabelIndex).Value;
                    return(expressionResult);
                }
                else if (value.ToLower() == "true")
                {
                    expressionResult.Value = 1;
                    return(expressionResult);
                }
                else if (value.ToLower() == "false")
                {
                    expressionResult.Value = 0;
                    return(expressionResult);
                }
                else // Defined value or error
                {
                    if (value.StartsWith("."))
                    {
                        value = PriorGlobalLabel + "_" + value.Substring(1);
                    }
                    if (Values.ContainsKey(value))
                    {
                        expressionResult.Value = Values[value];
                    }
                    else if (LabelValues.ContainsKey(value))
                    {
                        expressionResult.Relocate = true;
                        expressionResult.Value    = LabelValues.GetValue(value);
                    }
                    else
                    {
                        expressionResult.Successful = false;
                    }
                    expressionResult.References.Add(value);
                    if (!ReferencedValues.Contains(value))
                    {
                        ReferencedValues.Add(value);
                    }
                    return(expressionResult);
                }
            }

            // Parse expression
            string[] operands = GetOperands(value);
            if (operands == null)
            {
                expressionResult.Successful = false;
                return(expressionResult);
            }
            if (string.IsNullOrEmpty(operands[0]) && operands[1] == "-")
            {
                expressionResult       = ParseExpression(operands[2]);
                expressionResult.Value = (ushort)-expressionResult.Value;
                return(expressionResult);
            }
            if (operands == null)
            {
                expressionResult.Successful = false;
                return(expressionResult);
            }
            ExpressionResult left  = ParseExpression(operands[0]);
            ExpressionResult right = ParseExpression(operands[2]);

            expressionResult.References.AddRange(left.References.Concat(right.References));
            if ((!left.Successful || !right.Successful) && operands[1] != "===" && operands[1] != "!==")
            {
                expressionResult.Successful = false;
                return(expressionResult);
            }
            switch (operands[1])
            {
            case "*":
                expressionResult.Value = (ushort)(left.Value * right.Value);
                break;

            case "/":
                expressionResult.Value = (ushort)(left.Value / right.Value);
                break;

            case "+":
                expressionResult.Value = (ushort)(left.Value + right.Value);
                break;

            case "-":
                expressionResult.Value = (ushort)(left.Value - right.Value);
                break;

            case "<<":
                expressionResult.Value = (ushort)(left.Value << right.Value);
                break;

            case ">>":
                expressionResult.Value = (ushort)(left.Value >> right.Value);
                break;

            case "|":
                expressionResult.Value = (ushort)(left.Value | right.Value);
                break;

            case "^":
                expressionResult.Value = (ushort)(left.Value ^ right.Value);
                break;

            case "&":
                expressionResult.Value = (ushort)(left.Value & right.Value);
                break;

            case "%":
                expressionResult.Value = (ushort)(left.Value % right.Value);
                break;

            case "==":
                expressionResult.Value = (ushort)(left.Value == right.Value ? 1 : 0);
                break;

            case "!=":
            case "<>":
                expressionResult.Value = (ushort)(left.Value != right.Value ? 1 : 0);
                break;

            case "<":
                expressionResult.Value = (ushort)(left.Value < right.Value ? 1 : 0);
                break;

            case ">":
                expressionResult.Value = (ushort)(left.Value > right.Value ? 1 : 0);
                break;

            case "<=":
                expressionResult.Value = (ushort)(left.Value <= right.Value ? 1 : 0);
                break;

            case ">=":
                expressionResult.Value = (ushort)(left.Value >= right.Value ? 1 : 0);
                break;

            case "===":
                expressionResult.Value = (ushort)(operands[0].ToLower().Trim() == operands[2].ToLower().Trim() ? 1 : 0);
                break;

            case "!==":
                expressionResult.Value = (ushort)(operands[0].ToLower().Trim() != operands[2].ToLower().Trim() ? 1 : 0);
                break;

            case "&&":
                expressionResult.Value = (ushort)(left.Value > 0 && right.Value > 1 ? 1 : 0);
                break;

            case "||":
                expressionResult.Value = (ushort)(left.Value > 0 || right.Value > 1 ? 1 : 0);
                break;

            case "^^":
                expressionResult.Value = (ushort)(left.Value > 0 ^ right.Value > 1 ? 1 : 0);     // between boolean operators, ^ is ^^ in C#
                break;

            default:
                expressionResult.Successful = false;
                return(expressionResult);
            }
            return(expressionResult);
        }
示例#9
0
 public void Loaded(Assembler assembler)
 {
     assembler.HandleCodeLine += new EventHandler<HandleCodeEventArgs>(assembler_HandleCodeLine);
     this.assembler = assembler;
 }
示例#10
0
        static void Main(string[] args)
        {
            DateTime startupTime = DateTime.Now;

            // Parse arguments
            foreach (string arg in args)
            {
                if (arg.StartsWith("-"))
                {
                    switch (arg)
                    {
                        case "--debug-mode":
                            Console.ReadKey(true);
                            break;
                        case "--generate-reports":
                        case "-r":
                            generateReports = true;
                            break;
                        case "--little-endian":
                        case "-l":
                            bigEndian = false;
                            break;
                        default:
                            Console.WriteLine("Invalid arguments.");
                            return;
                    }
                }
            }

            Console.WriteLine("0x42c Build Tool     Copyright 0x42c Team 2012");
            startupDirectory = Directory.GetCurrentDirectory();

            // Clean up old build
            if (Directory.Exists("../bin"))
                Directory.Delete("../bin", true);
            Directory.CreateDirectory("../bin");
            Directory.CreateDirectory("../bin/kernel");
            Directory.CreateDirectory("../bin/bootloader");
            Directory.CreateDirectory("../bin/userspace");
            Directory.CreateDirectory("../bin/dump");
            if (generateReports)
            {
                if (Directory.Exists("../reports"))
                    Directory.Delete("../reports", true);
                Directory.CreateDirectory("../reports");
            }

            // Build kernel
            Console.WriteLine("Building 0x42c-kernel...");
            Directory.SetCurrentDirectory("../src/kernel");
            Assembler kernelAssembler = new Assembler();
            kernelAssembler.ForceLongLiterals = true;
            kernelAssembler.IncludePath = "../include";
            using (StreamReader sr = new StreamReader("base.dasm"))
            {
                string code = sr.ReadToEnd();
                Kernel = kernelAssembler.Assemble(code, "base.dasm");
            }
            Directory.SetCurrentDirectory(startupDirectory);
            CreateOutput(Kernel, "../bin/kernel", "kernel");

            // Build bootloader
            Console.WriteLine("Building 0x42c-bootloader...");
            Directory.SetCurrentDirectory("../src/bootloader");
            Assembler bootloaderAssembler = new Assembler();
            kernelAssembler.ForceLongLiterals = true;
            bootloaderAssembler.IncludePath = "../include";
            using (StreamReader sr = new StreamReader("base.dasm"))
            {
                string code = sr.ReadToEnd();
                Bootloader = bootloaderAssembler.Assemble(code, "base.dasm");
            }
            Directory.SetCurrentDirectory(startupDirectory);
            CreateOutput(Bootloader, "../bin/bootloader", "bootloader");

            // Patch all files together
            Console.WriteLine("Creating memory dump...");
            using (Stream dump = File.Open("../bin/dump/0x42c.bin", FileMode.Create))
            {
                dump.Write(new byte[0xFFFF * 2], 0, 0xFFFF * 2);
                dump.Flush();

                // Write kernel to dump
                dump.Seek(0, SeekOrigin.Begin);
                kernelSize = WriteToStream(Kernel, dump);

                // Write bootloader to dump
                dump.Seek(kernelAssembler.Values["os_bootloader"], SeekOrigin.Begin);
                bootloaderSize = WriteToStream(Bootloader, dump);
            }

            Console.WriteLine("Build complete " + (DateTime.Now - startupTime).TotalMilliseconds + "ms");
        }