Represents an entry in a listing output from assembling code.
예제 #1
0
 private void ParseDirectives(List<ListEntry> output, string line, bool lineFromMacro)
 {
     string directive = line.Substring(1);
     string[] parameters = directive.Split(' ');
     if (directive.ToLower() == "endif" || directive.ToLower() == "end")
     {
         if (IfStack.Count == 1)
             output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.UncoupledStatement, lineFromMacro ) );
         else
         {
             IfStack.Pop();
             output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList));
         }
     }
     else if (directive.ToLower().StartsWith("elseif") || directive.ToLower().StartsWith("elif"))
     {
         if (IfStack.Count == 1)
             output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.UncoupledStatement, lineFromMacro ) );
         else
         {
             if (parameters.Length == 1)
             {
                 output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro ) );
             }
             else
             {
                 var result = ParseExpression(line.Substring(line.IndexOf(' ')));
                 if (result.Successful)
                 {
                     if (result.Value > 0)
                         IfStack.Push(!IfStack.Pop());
                     output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList));
                 }
                 else
                     output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro ) );
             }
         }
     }
     else if (directive.ToLower() == "else")
     {
         if (IfStack.Count == 1)
             output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.UncoupledStatement, lineFromMacro ) );
         else
         {
             output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList));
             IfStack.Push(!IfStack.Pop());
         }
     }
     else if (IfStack.Peek())
     {
         if (directive.ToLower() == "region" || directive.ToLower() == "endregion") { } // Allowed but ignored
         else if (directive.ToLower() == "nolist")
         {
             noList = true;
             output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, lineFromMacro ) );
         }
         else if (directive.ToLower() == "list")
         {
             noList = false;
             output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, lineFromMacro ) );
         }
         else if ((directive.ToLower().StartsWith("dat ") || directive.ToLower().StartsWith("dw ")))
         {
             if (parameters.Length == 1)
                 output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro ) );
             else
             {
                 string[] dataStrings = directive.Substring(directive.IndexOf(" ")).SafeSplit(',');
                 List<ushort> binOutput = new List<ushort>();
                 Dictionary<ushort, string> postponedExpressions = new Dictionary<ushort, string>();
                 foreach (string data in dataStrings)
                 {
                     if (data.Trim().StartsWith("\""))
                     {
                         if (!data.Trim().EndsWith("\""))
                         {
                             output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro ) );
                         }
                         else
                         {
                             string str = data.Trim().Substring(1, data.Trim().Length - 2).Unescape();
                             foreach (byte b in Encoding.ASCII.GetBytes(str))
                                 binOutput.Add(b);
                         }
                     }
                     else
                     {
                         postponedExpressions.Add((ushort)binOutput.Count, data.Trim());
                         binOutput.Add(0);
                     }
                 }
                 output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), binOutput.ToArray(), currentAddress, !noList));
                 output[output.Count - 1].PostponedExpressions = postponedExpressions;
                 if (!noList)
                     currentAddress += (ushort)binOutput.Count;
             }
         }
         else if (directive.ToLower().StartsWith("scope"))
         {
             if (parameters.Length < 2)
                 output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro ) );
             else if (parameters.Length > 2)
                 output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.TooManyParamters, lineFromMacro ) );
             else
             {
                 PriorGlobalLabel = parameters[1];
                 output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, lineFromMacro ) );
             }
         }
         else if (directive.ToLower() == "uniquescope")
         {
             PriorGlobalLabel = "_unique" + UniqueScopeNumber++;
             output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, lineFromMacro ) );
         }
         else if (directive.ToLower().StartsWith("echo"))
         {
             if (parameters.Length == 1)
             {
                 output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro ) );
             }
             else
             {
                 string[] dataStrings = directive.Substring(directive.IndexOf(" ")).SafeSplit(',');
                 string consoleOutput = "";
                 foreach (string data in dataStrings)
                 {
                     if (data.Trim().StartsWith("\""))
                     {
                         if (!data.Trim().EndsWith("\""))
                         {
                             output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro ) );
                         }
                         else
                         {
                             string str = data.Trim().Substring(1, data.Trim().Length - 2).Unescape();
                             consoleOutput += str;
                         }
                     }
                     else
                     {
                         ExpressionResult value = ParseExpression(data.Trim());
                         if (!value.Successful)
                             output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro ) );
                         else
                             consoleOutput += value.Value;
                     }
                 }
                 Console.Write(consoleOutput + "\n");
                 output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, lineFromMacro ) );
                 output.Add( new ListEntry( consoleOutput, FileNames.Peek(), LineNumbers.Peek(), currentAddress, lineFromMacro ) );
             }
         }
         else if (directive.ToLower().StartsWith("ref"))
         {
             ReferencedValues.Add(directive.Substring(directive.IndexOf(" ") + 1));
         }
         else if (directive.ToLower().StartsWith("asciip"))
         {
             if (parameters.Length == 1)
             {
                 output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro ) );
             }
             else
             {
                 string[] dataStrings = directive.Substring(directive.IndexOf(" ")).SafeSplit(',');
                 List<ushort> binOutput = new List<ushort>();
                 foreach (string data in dataStrings)
                 {
                     if (data.Trim().StartsWith("\""))
                     {
                         if (!data.Trim().EndsWith("\""))
                         {
                             output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro ) );
                         }
                         else
                         {
                             string str = data.Trim().Substring(1, data.Trim().Length - 2).Unescape();
                             binOutput.Add((ushort)str.Length);
                             foreach (byte b in Encoding.ASCII.GetBytes(str))
                                 binOutput.Add(b);
                         }
                     }
                     else
                         output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro ) );
                 }
                 output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), binOutput.ToArray(), currentAddress, !noList));
                 if (!noList)
                     currentAddress += (ushort)binOutput.Count;
             }
         }
         else if (directive.ToLower().StartsWith("asciic") || directive.ToLower().StartsWith("asciiz"))
         {
             if (parameters.Length == 1)
             {
                 output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro ) );
             }
             else
             {
                 string[] dataStrings = directive.Substring(directive.IndexOf(" ")).SafeSplit(',');
                 List<ushort> binOutput = new List<ushort>();
                 foreach (string data in dataStrings)
                 {
                     if (data.Trim().StartsWith("\""))
                     {
                         if (!data.Trim().EndsWith("\""))
                         {
                             output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro ) );
                         }
                         else
                         {
                             string str = data.Trim().Substring(1, data.Trim().Length - 2).Unescape();
                             foreach (byte b in Encoding.ASCII.GetBytes(str))
                                 binOutput.Add(b);
                             binOutput.Add(0);
                         }
                     }
                     else
                         output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro ) );
                 }
                 output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), binOutput.ToArray(), currentAddress, !noList));
                 if (!noList)
                     currentAddress += (ushort)binOutput.Count;
             }
         }
         else if (directive.ToLower().StartsWith("ascii"))
         {
             if (parameters.Length == 1)
             {
                 output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro ) );
             }
             else
             {
                 string[] dataStrings = directive.Substring(directive.IndexOf(" ")).SafeSplit(',');
                 List<ushort> binOutput = new List<ushort>();
                 foreach (string data in dataStrings)
                 {
                     if (data.Trim().StartsWith("\""))
                     {
                         if (!data.Trim().EndsWith("\""))
                         {
                             output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro ) );
                         }
                         else
                         {
                             string str = data.Trim().Substring(1, data.Trim().Length - 2).Unescape();
                             foreach (byte b in Encoding.ASCII.GetBytes(str))
                                 binOutput.Add(b);
                         }
                     }
                     else
                         output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro ) );
                 }
                 output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), binOutput.ToArray(), currentAddress, !noList));
                 if (!noList)
                     currentAddress += (ushort)binOutput.Count;
             }
         }
         else if (directive.ToLower() == "longform") // Handled properly in the second pass
             output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList));
         else if (directive.ToLower() == "shortform")
             output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList));
         else if (directive.ToLower().StartsWith("org"))
         {
             if (parameters.Length == 1)
             {
                 output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro ) );
             }
             else if (parameters.Length > 2)
             {
                 output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.TooManyParamters, lineFromMacro ) );
             }
             else
             {
                 ExpressionResult value = ParseExpression(parameters[1]);
                 if (value == null)
                 {
                     output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro ) );
                 }
                 else
                 {
                     currentAddress = value.Value;
                     var entry = new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList);
                     entry.RootLineNumber = RootLineNumber;
                     output.Add(entry);
                 }
             }
         }
         else if (directive.ToLower().StartsWith("ifdef"))
         {
             if (parameters.Length == 1)
             {
                 output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro ) );
             }
             else if (parameters.Length > 2)
             {
                 output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.TooManyParamters, lineFromMacro ) );
             }
             else
             {
                 if (Values.ContainsKey(parameters[1].ToLower()))
                     IfStack.Push(true);
                 else
                     IfStack.Push(false);
                 output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList));
             }
         }
         else if (directive.ToLower().StartsWith("ifndef"))
         {
             if (parameters.Length == 1)
             {
                 output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro ) );
             }
             else if (parameters.Length > 2)
             {
                 output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.TooManyParamters, lineFromMacro ) );
             }
             else
             {
                 if (Values.ContainsKey(parameters[1].ToLower()))
                     IfStack.Push(false);
                 else
                     IfStack.Push(true);
                 output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList));
             }
         }
         else if (directive.ToLower().StartsWith("if"))
         {
             if (parameters.Length == 1)
             {
                 output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro ) );
             }
             else
             {
                 var result = ParseExpression(line.Substring(3));
                 if (result.Successful)
                 {
                     if (result.Value > 0)
                         IfStack.Push(true);
                     else
                         IfStack.Push(false);
                     output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList));
                 }
                 else
                     output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro ) );
             }
         }
         else if (directive.ToLower().StartsWith("equ") || directive.ToLower().StartsWith("define") || directive.ToLower().StartsWith("equate"))
         {
             if (parameters.Length > 1)
             {
                 if (Values.ContainsKey(parameters[1]))
                     output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.DuplicateName, lineFromMacro ) );
                 else
                 {
                     if (parameters.Length == 2)
                     {
                         Values.Add(parameters[1], 1);
                         output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList));
                     }
                     else if (parameters.Length > 2)
                     {
                         string expression = directive.TrimExcessWhitespace();
                         expression = expression.Substring(expression.IndexOf(' ') + 1);
                         expression = expression.Substring(expression.IndexOf(' ') + 1);
                         ExpressionResult value = ParseExpression(expression); // TODO: find a way to forward reference
                         if (value != null)
                         {
                             Values.Add(parameters[1], value.Value);
                             output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList));
                         }
                         else
                             output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro ) );
                     }
                     else
                         output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro ) );
                 }
             }
         }
         else if (directive.ToLower().StartsWith("pad") || directive.ToLower().StartsWith("fill")) // .pad length, value
         {
             parameters = line.SafeSplit(',', ' ');
             string[] fixedParams = new string[0];
             foreach (string parameter in parameters)
                 if (!string.IsNullOrEmpty(parameter))
                     fixedParams = fixedParams.Concat(new string[] { parameter }).ToArray();
             parameters = fixedParams;
             if (parameters.Length == 3)
             {
                 var length = ParseExpression(parameters[1]);
                 var value = ParseExpression(parameters[2]);
                 if (!length.Successful)
                     output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro ) );
                 else
                 {
                     ushort[] padding = new ushort[length.Value];
                     Dictionary<ushort, string> postponed = new Dictionary<ushort, string>();
                     for (int i = 0; i < padding.Length; i++)
                     {
                         padding[i] = value.Value;
                         if (!value.Successful)
                             postponed.Add((ushort)i, parameters[2]);
                     }
                     output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), padding, currentAddress, !noList));
                     output[output.Count - 1].PostponedExpressions = postponed;
                     if (!noList)
                         currentAddress += (ushort)padding.Length;
                 }
             }
             else if (parameters.Length == 1)
                 output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro ) );
             else
                 output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.TooManyParamters, lineFromMacro ) );
         }
         else if (directive.ToLower().StartsWith("reserve"))
         {
             if (parameters.Length == 1)
                 output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro ) );
             else
             {
                 var expression = directive.Substring(7).Trim();
                 var result = ParseExpression(expression);
                 if (result.Successful)
                 {
                     output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), new ushort[result.Value], currentAddress, !noList));
                     currentAddress += result.Value;
                 }
                 else
                     output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro ) );
             }
         }
         else if (directive.ToLower().StartsWith("align")) // .align addr
         {
             if (parameters.Length == 2)
             {
                 var addr = ParseExpression(parameters[1]);
                 if (!addr.Successful)
                     output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro ) );
                 else
                 {
                     if (currentAddress > addr.Value)
                         output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.AlignToPast, lineFromMacro ) );
                     else
                     {
                         var amount = (ushort)(addr.Value - currentAddress);
                         ushort[] padding = new ushort[amount];
                         output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), padding, currentAddress, !noList));
                         if (!noList)
                             currentAddress = addr.Value;
                     }
                 }
             }
             else if (parameters.Length == 1)
                 output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro ) );
             else
                 output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.TooManyParamters, lineFromMacro ) );
         }
         else if (directive == "relocate")
         {
             OldAddress = currentAddress;
             currentAddress = 0;
             output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, lineFromMacro ) );
             output[output.Count - 1].CodeType = CodeType.RelocationTable;
             RelocationGroup++;
             IsRelocating = true;
         }
         else if (directive == "endrelocate")
         {
             // TODO: Errors
             output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, lineFromMacro ) );
             currentAddress = OldAddress;
             IsRelocating = false;
         }
         else
         {
             output.Add( new ListEntry( line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InvalidDirective, lineFromMacro ) );
         }
     }
     output[output.Count - 1].CodeType = CodeType.Directive;
 }
예제 #2
0
        private void ParseDirectives(List <ListEntry> output, string line, bool lineFromMacro)
        {
            string directive = line.Substring(1);

            string[] parameters = directive.Split(' ');
            if (directive.ToLower() == "endif" || directive.ToLower() == "end")
            {
                if (IfStack.Count == 1)
                {
                    output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.UncoupledStatement, lineFromMacro));
                }
                else
                {
                    IfStack.Pop();
                    output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList));
                }
            }
            else if (directive.ToLower().StartsWith("elseif") || directive.ToLower().StartsWith("elif"))
            {
                if (IfStack.Count == 1)
                {
                    output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.UncoupledStatement, lineFromMacro));
                }
                else
                {
                    if (parameters.Length == 1)
                    {
                        output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro));
                    }
                    else
                    {
                        var result = ParseExpression(line.Substring(line.IndexOf(' ')));
                        if (result.Successful)
                        {
                            if (result.Value > 0)
                            {
                                IfStack.Push(!IfStack.Pop());
                            }
                            output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList));
                        }
                        else
                        {
                            output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro));
                        }
                    }
                }
            }
            else if (directive.ToLower() == "else")
            {
                if (IfStack.Count == 1)
                {
                    output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.UncoupledStatement, lineFromMacro));
                }
                else
                {
                    output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList));
                    IfStack.Push(!IfStack.Pop());
                }
            }
            else if (IfStack.Peek())
            {
                if (directive.ToLower() == "region" || directive.ToLower() == "endregion")
                {
                }                                                                              // Allowed but ignored
                else if (directive.ToLower() == "nolist")
                {
                    noList = true;
                    output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, lineFromMacro));
                }
                else if (directive.ToLower() == "list")
                {
                    noList = false;
                    output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, lineFromMacro));
                }
                else if ((directive.ToLower().StartsWith("dat ") || directive.ToLower().StartsWith("dw ")))
                {
                    if (parameters.Length == 1)
                    {
                        output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro));
                    }
                    else
                    {
                        string[]      dataStrings = directive.Substring(directive.IndexOf(" ")).SafeSplit(',');
                        List <ushort> binOutput   = new List <ushort>();
                        Dictionary <ushort, string> postponedExpressions = new Dictionary <ushort, string>();
                        foreach (string data in dataStrings)
                        {
                            if (data.Trim().StartsWith("\""))
                            {
                                if (!data.Trim().EndsWith("\""))
                                {
                                    output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro));
                                }
                                else
                                {
                                    string str = data.Trim().Substring(1, data.Trim().Length - 2).Unescape();
                                    foreach (byte b in Encoding.ASCII.GetBytes(str))
                                    {
                                        binOutput.Add(b);
                                    }
                                }
                            }
                            else
                            {
                                postponedExpressions.Add((ushort)binOutput.Count, data.Trim());
                                binOutput.Add(0);
                            }
                        }
                        output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), binOutput.ToArray(), currentAddress, !noList));
                        output[output.Count - 1].PostponedExpressions = postponedExpressions;
                        if (!noList)
                        {
                            currentAddress += (ushort)binOutput.Count;
                        }
                    }
                }
                else if (directive.ToLower().StartsWith("scope"))
                {
                    if (parameters.Length < 2)
                    {
                        output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro));
                    }
                    else if (parameters.Length > 2)
                    {
                        output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.TooManyParamters, lineFromMacro));
                    }
                    else
                    {
                        PriorGlobalLabel = parameters[1];
                        output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, lineFromMacro));
                    }
                }
                else if (directive.ToLower() == "uniquescope")
                {
                    PriorGlobalLabel = "_unique" + UniqueScopeNumber++;
                    output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, lineFromMacro));
                }
                else if (directive.ToLower().StartsWith("echo"))
                {
                    if (parameters.Length == 1)
                    {
                        output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro));
                    }
                    else
                    {
                        string[] dataStrings   = directive.Substring(directive.IndexOf(" ")).SafeSplit(',');
                        string   consoleOutput = "";
                        foreach (string data in dataStrings)
                        {
                            if (data.Trim().StartsWith("\""))
                            {
                                if (!data.Trim().EndsWith("\""))
                                {
                                    output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro));
                                }
                                else
                                {
                                    string str = data.Trim().Substring(1, data.Trim().Length - 2).Unescape();
                                    consoleOutput += str;
                                }
                            }
                            else
                            {
                                ExpressionResult value = ParseExpression(data.Trim());
                                if (!value.Successful)
                                {
                                    output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro));
                                }
                                else
                                {
                                    consoleOutput += value.Value;
                                }
                            }
                        }
                        Console.Write(consoleOutput + "\n");
                        output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, lineFromMacro));
                        output.Add(new ListEntry(consoleOutput, FileNames.Peek(), LineNumbers.Peek(), currentAddress, lineFromMacro));
                    }
                }
                else if (directive.ToLower().StartsWith("ref"))
                {
                    ReferencedValues.Add(directive.Substring(directive.IndexOf(" ") + 1));
                }
                else if (directive.ToLower().StartsWith("asciip"))
                {
                    if (parameters.Length == 1)
                    {
                        output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro));
                    }
                    else
                    {
                        string[]      dataStrings = directive.Substring(directive.IndexOf(" ")).SafeSplit(',');
                        List <ushort> binOutput   = new List <ushort>();
                        foreach (string data in dataStrings)
                        {
                            if (data.Trim().StartsWith("\""))
                            {
                                if (!data.Trim().EndsWith("\""))
                                {
                                    output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro));
                                }
                                else
                                {
                                    string str = data.Trim().Substring(1, data.Trim().Length - 2).Unescape();
                                    binOutput.Add((ushort)str.Length);
                                    foreach (byte b in Encoding.ASCII.GetBytes(str))
                                    {
                                        binOutput.Add(b);
                                    }
                                }
                            }
                            else
                            {
                                output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro));
                            }
                        }
                        output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), binOutput.ToArray(), currentAddress, !noList));
                        if (!noList)
                        {
                            currentAddress += (ushort)binOutput.Count;
                        }
                    }
                }
                else if (directive.ToLower().StartsWith("asciic") || directive.ToLower().StartsWith("asciiz"))
                {
                    if (parameters.Length == 1)
                    {
                        output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro));
                    }
                    else
                    {
                        string[]      dataStrings = directive.Substring(directive.IndexOf(" ")).SafeSplit(',');
                        List <ushort> binOutput   = new List <ushort>();
                        foreach (string data in dataStrings)
                        {
                            if (data.Trim().StartsWith("\""))
                            {
                                if (!data.Trim().EndsWith("\""))
                                {
                                    output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro));
                                }
                                else
                                {
                                    string str = data.Trim().Substring(1, data.Trim().Length - 2).Unescape();
                                    foreach (byte b in Encoding.ASCII.GetBytes(str))
                                    {
                                        binOutput.Add(b);
                                    }
                                    binOutput.Add(0);
                                }
                            }
                            else
                            {
                                output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro));
                            }
                        }
                        output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), binOutput.ToArray(), currentAddress, !noList));
                        if (!noList)
                        {
                            currentAddress += (ushort)binOutput.Count;
                        }
                    }
                }
                else if (directive.ToLower().StartsWith("ascii"))
                {
                    if (parameters.Length == 1)
                    {
                        output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro));
                    }
                    else
                    {
                        string[]      dataStrings = directive.Substring(directive.IndexOf(" ")).SafeSplit(',');
                        List <ushort> binOutput   = new List <ushort>();
                        foreach (string data in dataStrings)
                        {
                            if (data.Trim().StartsWith("\""))
                            {
                                if (!data.Trim().EndsWith("\""))
                                {
                                    output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro));
                                }
                                else
                                {
                                    string str = data.Trim().Substring(1, data.Trim().Length - 2).Unescape();
                                    foreach (byte b in Encoding.ASCII.GetBytes(str))
                                    {
                                        binOutput.Add(b);
                                    }
                                }
                            }
                            else
                            {
                                output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro));
                            }
                        }
                        output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), binOutput.ToArray(), currentAddress, !noList));
                        if (!noList)
                        {
                            currentAddress += (ushort)binOutput.Count;
                        }
                    }
                }
                else if (directive.ToLower() == "longform") // Handled properly in the second pass
                {
                    output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList));
                }
                else if (directive.ToLower() == "shortform")
                {
                    output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList));
                }
                else if (directive.ToLower().StartsWith("org"))
                {
                    if (parameters.Length == 1)
                    {
                        output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro));
                    }
                    else if (parameters.Length > 2)
                    {
                        output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.TooManyParamters, lineFromMacro));
                    }
                    else
                    {
                        ExpressionResult value = ParseExpression(parameters[1]);
                        if (value == null)
                        {
                            output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro));
                        }
                        else
                        {
                            currentAddress = value.Value;
                            var entry = new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList);
                            entry.RootLineNumber = RootLineNumber;
                            output.Add(entry);
                        }
                    }
                }
                else if (directive.ToLower().StartsWith("ifdef"))
                {
                    if (parameters.Length == 1)
                    {
                        output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro));
                    }
                    else if (parameters.Length > 2)
                    {
                        output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.TooManyParamters, lineFromMacro));
                    }
                    else
                    {
                        if (Values.ContainsKey(parameters[1].ToLower()))
                        {
                            IfStack.Push(true);
                        }
                        else
                        {
                            IfStack.Push(false);
                        }
                        output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList));
                    }
                }
                else if (directive.ToLower().StartsWith("ifndef"))
                {
                    if (parameters.Length == 1)
                    {
                        output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro));
                    }
                    else if (parameters.Length > 2)
                    {
                        output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.TooManyParamters, lineFromMacro));
                    }
                    else
                    {
                        if (Values.ContainsKey(parameters[1].ToLower()))
                        {
                            IfStack.Push(false);
                        }
                        else
                        {
                            IfStack.Push(true);
                        }
                        output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList));
                    }
                }
                else if (directive.ToLower().StartsWith("if"))
                {
                    if (parameters.Length == 1)
                    {
                        output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro));
                    }
                    else
                    {
                        var result = ParseExpression(line.Substring(3));
                        if (result.Successful)
                        {
                            if (result.Value > 0)
                            {
                                IfStack.Push(true);
                            }
                            else
                            {
                                IfStack.Push(false);
                            }
                            output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList));
                        }
                        else
                        {
                            output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro));
                        }
                    }
                }
                else if (directive.ToLower().StartsWith("equ") || directive.ToLower().StartsWith("define") || directive.ToLower().StartsWith("equate"))
                {
                    if (parameters.Length > 1)
                    {
                        if (Values.ContainsKey(parameters[1]))
                        {
                            output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.DuplicateName, lineFromMacro));
                        }
                        else
                        {
                            if (parameters.Length == 2)
                            {
                                Values.Add(parameters[1], 1);
                                output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList));
                            }
                            else if (parameters.Length > 2)
                            {
                                string expression = directive.TrimExcessWhitespace();
                                expression = expression.Substring(expression.IndexOf(' ') + 1);
                                expression = expression.Substring(expression.IndexOf(' ') + 1);
                                ExpressionResult value = ParseExpression(expression); // TODO: find a way to forward reference
                                if (value != null)
                                {
                                    Values.Add(parameters[1], value.Value);
                                    output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList));
                                }
                                else
                                {
                                    output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro));
                                }
                            }
                            else
                            {
                                output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro));
                            }
                        }
                    }
                }
                else if (directive.ToLower().StartsWith("pad") || directive.ToLower().StartsWith("fill")) // .pad length, value
                {
                    parameters = line.SafeSplit(',', ' ');
                    string[] fixedParams = new string[0];
                    foreach (string parameter in parameters)
                    {
                        if (!string.IsNullOrEmpty(parameter))
                        {
                            fixedParams = fixedParams.Concat(new string[] { parameter }).ToArray();
                        }
                    }
                    parameters = fixedParams;
                    if (parameters.Length == 3)
                    {
                        var length = ParseExpression(parameters[1]);
                        var value  = ParseExpression(parameters[2]);
                        if (!length.Successful)
                        {
                            output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro));
                        }
                        else
                        {
                            ushort[] padding = new ushort[length.Value];
                            Dictionary <ushort, string> postponed = new Dictionary <ushort, string>();
                            for (int i = 0; i < padding.Length; i++)
                            {
                                padding[i] = value.Value;
                                if (!value.Successful)
                                {
                                    postponed.Add((ushort)i, parameters[2]);
                                }
                            }
                            output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), padding, currentAddress, !noList));
                            output[output.Count - 1].PostponedExpressions = postponed;
                            if (!noList)
                            {
                                currentAddress += (ushort)padding.Length;
                            }
                        }
                    }
                    else if (parameters.Length == 1)
                    {
                        output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro));
                    }
                    else
                    {
                        output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.TooManyParamters, lineFromMacro));
                    }
                }
                else if (directive.ToLower().StartsWith("reserve"))
                {
                    if (parameters.Length == 1)
                    {
                        output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro));
                    }
                    else
                    {
                        var expression = directive.Substring(7).Trim();
                        var result     = ParseExpression(expression);
                        if (result.Successful)
                        {
                            output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), new ushort[result.Value], currentAddress, !noList));
                            currentAddress += result.Value;
                        }
                        else
                        {
                            output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro));
                        }
                    }
                }
                else if (directive.ToLower().StartsWith("align")) // .align addr
                {
                    if (parameters.Length == 2)
                    {
                        var addr = ParseExpression(parameters[1]);
                        if (!addr.Successful)
                        {
                            output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.IllegalExpression, lineFromMacro));
                        }
                        else
                        {
                            if (currentAddress > addr.Value)
                            {
                                output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.AlignToPast, lineFromMacro));
                            }
                            else
                            {
                                var      amount  = (ushort)(addr.Value - currentAddress);
                                ushort[] padding = new ushort[amount];
                                output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), padding, currentAddress, !noList));
                                if (!noList)
                                {
                                    currentAddress = addr.Value;
                                }
                            }
                        }
                    }
                    else if (parameters.Length == 1)
                    {
                        output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InsufficientParamters, lineFromMacro));
                    }
                    else
                    {
                        output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.TooManyParamters, lineFromMacro));
                    }
                }
                else if (directive == "relocate")
                {
                    OldAddress     = currentAddress;
                    currentAddress = 0;
                    output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, lineFromMacro));
                    output[output.Count - 1].CodeType = CodeType.RelocationTable;
                    RelocationGroup++;
                    IsRelocating = true;
                }
                else if (directive == "endrelocate")
                {
                    // TODO: Errors
                    output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, lineFromMacro));
                    currentAddress = OldAddress;
                    IsRelocating   = false;
                }
                else
                {
                    output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, ErrorCode.InvalidDirective, lineFromMacro));
                }
            }
            output[output.Count - 1].CodeType = CodeType.Directive;
        }
예제 #3
0
        public static string CreateListing(List <ListEntry> output)
        {
            string listing = "";
            int    maxLength = 0, maxFileLength = 0;

            foreach (var entry in output)
            {
                int length = entry.FileName.Length + 1;
                if (length > maxFileLength)
                {
                    maxFileLength = length;
                }
            }
            foreach (var entry in output)
            {
                int length = maxFileLength + entry.LineNumber.ToString().Length + 9;
                if (length > maxLength)
                {
                    maxLength = length;
                }
            }
            TabifiedStringBuilder tsb;

            foreach (var listentry in output)
            {
                tsb = new TabifiedStringBuilder();

                // FIX: TJMonk(04-20-2013) - Changing this code to use arrays, and adding support for '#' directives
                bool pass = false;

                if (listentry.ErrorCode == ErrorCode.Success)
                {
                    string[] lineStarts = { ".", "#" };
                    string[] directives =
                    {
                        "dat", "dw",     "db",      "ascii",   "asciiz", "asciip", "asciic", "align", "fill",
                        "pad", "incbin", "reserve", "incpack", "relocate"
                    };

                    string toCheck        = listentry.Code.ToLower();
                    bool   checkLineStart = false;
                    foreach (var s in lineStarts)
                    {
                        if (toCheck.StartsWith(s))
                        {
                            checkLineStart = true;
                            toCheck        = toCheck.Substring(s.Length);
                            break;
                        }
                    }

                    if (checkLineStart)
                    {
                        foreach (var s in directives)
                        {
                            if (toCheck.StartsWith(s))
                            {
                                pass = true;
                                break;
                            }
                        }
                    }
                }

                if (pass)
                {
                    // ENDFIX: TJMonk(04-20-2013)
                    // Write code line
                    tsb = new TabifiedStringBuilder();
                    tsb.WriteAt(0, listentry.FileName);
                    tsb.WriteAt(maxFileLength, "(line " + listentry.LineNumber + "): ");
                    if (listentry.Listed)
                    {
                        tsb.WriteAt(maxLength, "[0x" + LongHex(listentry.Address) + "] ");
                    }
                    else
                    {
                        tsb.WriteAt(maxLength, "[NOLIST] ");
                    }
                    tsb.WriteAt(maxLength + 25, listentry.Code);
                    listing += tsb.Value + Environment.NewLine;
                    // Write data
                    if (listentry.Output != null)
                    {
                        for (int i = 0; i < listentry.Output.Length; i += 8)
                        {
                            tsb = new TabifiedStringBuilder();
                            tsb.WriteAt(0, listentry.FileName);
                            tsb.WriteAt(maxFileLength, "(line " + listentry.LineNumber + "): ");
                            //if (listentry.Listed)
                            //	tsb.WriteAt(maxLength, "[0x" + LongHex((ushort)(listentry.Address + i)) + "] ");
                            //else
                            tsb.WriteAt(maxLength, "[NOLIST] ");
                            string data = "";
                            for (int j = 0; j < 8 && i + j < listentry.Output.Length; j++)
                            {
                                data += LongHex(listentry.Output[i + j]) + " ";
                            }
                            tsb.WriteAt(maxLength + 30, data.Remove(data.Length - 1));
                            listing += tsb.Value + Environment.NewLine;
                        }
                    }
                }
                else
                {
                    if (listentry.ErrorCode != ErrorCode.Success)
                    {
                        tsb = new TabifiedStringBuilder();
                        tsb.WriteAt(0, listentry.FileName);
                        tsb.WriteAt(maxFileLength, "(line " + listentry.LineNumber + "): ");
                        if (listentry.Listed && listentry.Output != null)
                        {
                            tsb.WriteAt(maxLength, "[0x" + LongHex(listentry.Address) + "] ");
                        }
                        else
                        {
                            tsb.WriteAt(maxLength, "[NOLIST] ");
                        }
                        tsb.WriteAt(maxLength + 8, "ERROR: " + ListEntry.GetFriendlyErrorMessage(listentry.ErrorCode));
                        listing += tsb.Value + Environment.NewLine;
                    }
                    if (listentry.WarningCode != WarningCode.None)
                    {
                        tsb = new TabifiedStringBuilder();
                        tsb.WriteAt(0, listentry.FileName);
                        tsb.WriteAt(maxFileLength, "(line " + listentry.LineNumber + "): ");
                        if (listentry.Listed && listentry.Output != null)
                        {
                            tsb.WriteAt(maxLength, "[0x" + LongHex(listentry.Address) + "] ");
                        }
                        else
                        {
                            tsb.WriteAt(maxLength, "[NOLIST] ");
                        }
                        tsb.WriteAt(maxLength + 8, "WARNING: " + ListEntry.GetFriendlyWarningMessage(listentry.WarningCode));
                        listing += tsb.Value + Environment.NewLine;
                    }
                    tsb = new TabifiedStringBuilder();
                    tsb.WriteAt(0, listentry.FileName);
                    tsb.WriteAt(maxFileLength, "(line " + listentry.LineNumber + "): ");
                    if (listentry.Listed && (listentry.CodeType == CodeType.Label || listentry.Output != null))
                    {
                        tsb.WriteAt(maxLength, "[0x" + LongHex(listentry.Address) + "] ");
                    }
                    else
                    {
                        tsb.WriteAt(maxLength, "[NOLIST] ");
                    }
                    if (listentry.Output != null)
                    {
                        if (listentry.Output.Length > 0)
                        {
                            tsb.WriteAt(maxLength + 8, DumpArray(listentry.Output));
                            tsb.WriteAt(maxLength + 25, listentry.Code);
                        }
                    }
                    else
                    {
                        tsb.WriteAt(maxLength + 23, listentry.Code);
                    }
                    listing += tsb.Value + Environment.NewLine;
                }
            }
            return(listing);
        }
예제 #4
0
        /// <summary>
        /// Assembles the provided code.
        /// This will use the current directory to fetch include files and such.
        /// </summary>
        /// <returns>A listing for the code</returns>
        public List<ListEntry> Assemble(string code, string FileName)
        {
            FileNames = new Stack<string>();
            LineNumbers = new Stack<int>();
            FileNames.Push(FileName);
            LineNumbers.Push(0);
            RootLineNumber = 0;
            IfStack.Push(true);
            bool isFromExpanded;

            // Pass one
            string[] lines = code.Replace("\r", "").Split('\n');
            List<ListEntry> output = new List<ListEntry>();
            for (int i = 0; i < lines.Length; i++)
            {
                isFromExpanded = false;
                if (SuspendedLineCounts.Count == 0)
                {
                    LineNumbers.Push(LineNumbers.Pop() + 1);
                    RootLineNumber++;
                }
                else
                {
                    isFromExpanded = true;
                    int count = SuspendedLineCounts.Pop();
                    count--;
                    if (count > 0)
                        SuspendedLineCounts.Push(count);
                }

                string line = lines[i].TrimComments().TrimExcessWhitespace();
                if (string.IsNullOrEmpty(line))
                    continue;
                string[] sublines = line.SafeSplit('\\');
                if (sublines.Length > 1)
                {
                    string[] newLines = new string[lines.Length + sublines.Length - 1];
                    Array.Copy(lines, 0, newLines, 0, i);
                    Array.Copy(sublines, 0, newLines, i, sublines.Length);
                    if (lines.Length > i + 1)
                        Array.Copy(lines, i + 1, newLines, i + sublines.Length, lines.Length - i - 1);
                    lines = newLines;
                    i--;
                    SuspendedLineCounts.Push(sublines.Length);
                    continue;
                }
                ListEntry listEntry = new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), currentAddress, !noList, isFromExpanded);
                listEntry.RootLineNumber = RootLineNumber;
                if (HandleCodeLine != null)
                {
                    HandleCodeEventArgs args = new HandleCodeEventArgs();
                    args.Code = line;
                    args.Handled = false;
                    args.Output = listEntry;
                    HandleCodeLine(this, args);
                    if (args.Handled)
                    {
                        output.Add(args.Output);
                        continue;
                    }
                    listEntry = args.Output;
                    line = args.Code;
                }
                if (line.SafeContains(':') && !noList)
                {
                    if (!IfStack.Peek())
                        continue;
                    listEntry.CodeType = CodeType.Directive;
                    // Parse labels
                    string label = line;
                    if (line.StartsWith(":"))
                    {
                        label = label.Substring(1);
                        if (line.Contains(' '))
                            line = line.Substring(line.IndexOf(' ') + 1).Trim();
                        else
                            line = "";
                    }
                    else
                    {
                        label = label.Remove(label.IndexOf(':'));
                        line = line.Substring(line.IndexOf(':') + 1);
                    }
                    line = line.Trim();
                    if (label.Contains(" "))
                        label = label.Remove(label.IndexOf(' '));
                    if (label == "$")
                    {
                        RelativeLabels.Add(GetRootNumber(LineNumbers), currentAddress);
                        output.Add(listEntry);
                        continue;
                    }
                    if (label.Contains(' ') || label.Contains('\t') || !(char.IsLetter(label[0]) || label[0] == '.' || label[0] == '_'))
                    {
                        listEntry.ErrorCode = ErrorCode.InvalidLabel;
                        output.Add(listEntry);
                        continue;
                    }
                    bool invalid = false;
                    if (label.StartsWith("_"))
                    {
                        listEntry.ErrorCode = ErrorCode.InvalidLabel;
                        output.Add(listEntry);
                        continue;
                    }
                    foreach (char c in label)
                    {
                        if (!char.IsLetterOrDigit(c) && c != '_' && c != '.')
                        {
                            listEntry.ErrorCode = ErrorCode.InvalidLabel;
                            output.Add(listEntry);
                            invalid = true;
                            break;
                        }
                    }
                    if (invalid)
                        continue;
                    if (Values.ContainsKey(label) || LabelValues.ContainsKey(label))
                    {
                        listEntry.ErrorCode = ErrorCode.DuplicateName;
                        output.Add(listEntry);
                        continue;
                    }
                    if (label.StartsWith("."))
                        label = PriorGlobalLabel + "_" + label.Substring(1);
                    else
                        PriorGlobalLabel = label;
                    LabelValues.Add(new Label()
                    {
                        LineNumber = LineNumbers.Peek(),
                        Name = label,
                        RootLineNumber = listEntry.RootLineNumber,
                        Address = currentAddress,
                    });
                    if (!IsRelocating)
                        LabelValues[LabelValues.Count - 1].RelocationGroup = -1;
                    else
                        LabelValues[LabelValues.Count - 1].RelocationGroup = RelocationGroup;
                    listEntry.CodeType = CodeType.Label;
                    output.Add(listEntry);
                }
                if (string.IsNullOrEmpty(line))
                    continue;
                if (line.Contains(".equ") && !line.StartsWith(".equ")) // TASM compatibility
                {
                    line = ".equ " + line.Replace(".equ", "").TrimExcessWhitespace();
                }
                if (line.StartsWith("dat "))
                {
                    line = "." + line;
                }
                if (line.StartsWith(".") || line.StartsWith("#"))
                {
                    // #include has to be handled in this method
                    if (line.StartsWith("#include") || line.StartsWith(".include"))
                    {
                        if (!IfStack.Peek())
                            continue;
                        string includedFileName = line.Substring(line.IndexOf(" ") + 1);
                        includedFileName = includedFileName.Trim('"', '\'');
                        if (includedFileName.StartsWith("<") && includedFileName.EndsWith(">"))
                        {
                            // Find included file
                            includedFileName = includedFileName.Trim('<', '>');
                            string[] paths = IncludePath.Split(new []{';'}, StringSplitOptions.RemoveEmptyEntries );
                            foreach (var path in paths)
                            {
                                if (File.Exists(Path.Combine(path, includedFileName)))
                                {
                                    includedFileName = Path.Combine(path, includedFileName);
                                    break;
                                }
                            }
                        }
                        if (!File.Exists(includedFileName))
                        {
                            listEntry.ErrorCode = ErrorCode.FileNotFound;
                            output.Add(listEntry);
                        }
                        else if (IncludedFiles.Contains(includedFileName))
                        {

                        }
                        else
                        {
                            using (Stream includedFile = File.Open(includedFileName, FileMode.Open))
                            {
                                StreamReader sr = new StreamReader(includedFile);
                                string contents = sr.ReadToEnd();
                                sr.Close();

                                string[] newSource = contents.Replace("\r", "").Split('\n');
                                string[] newLines = new string[newSource.Length + lines.Length];
                                Array.Copy(lines, newLines, i);
                                Array.Copy(newSource, 0, newLines, i, newSource.Length);
                                newLines[i + newSource.Length] = "#endfile";
                                if (lines.Length > i + 1)
                                    Array.Copy(lines, i + 1, newLines, i + newSource.Length + 1, lines.Length - i - 1);
                                lines = newLines;
                            }
                            WorkingDirectories.Push(Directory.GetCurrentDirectory());
                            if (Path.IsPathRooted(includedFileName))
                                Directory.SetCurrentDirectory(GetDirectory(includedFileName));
                            else
                                Directory.SetCurrentDirectory(Path.Combine(Directory.GetCurrentDirectory(),
                                    GetDirectory(includedFileName)));
                            FileNames.Push(includedFileName);
                            LineNumbers.Push(0);
                            IncludedFiles.Add(includedFileName);
                            i--;
                            continue;
                        }
                    }
                    else if ((line.StartsWith("#incbin") || line.StartsWith(".incbin")) && !noList)
                    {
                        if (!IfStack.Peek())
                            continue;
                        string includedFileName = line.Substring(line.IndexOf(" ") + 1);
                        includedFileName = includedFileName.Trim('"', '\'');
                        if (includedFileName.StartsWith("<") && includedFileName.EndsWith(">"))
                        {
                            // Find included file
                            includedFileName = includedFileName.Trim('<', '>');
                            string[] paths = IncludePath.Split(';');
                            foreach (var path in paths)
                            {
                                if (File.Exists(Path.Combine(path, includedFileName)))
                                {
                                    includedFileName = Path.Combine(path, includedFileName);
                                    break;
                                }
                            }
                        }
                        if (!File.Exists(includedFileName))
                        {
                            listEntry.ErrorCode = ErrorCode.FileNotFound;
                            output.Add(listEntry);
                        }
                        else
                        {
                            using (Stream includedFile = File.Open(includedFileName, FileMode.Open))
                            {
                                byte[] rawData = new byte[includedFile.Length];
                                includedFile.Read(rawData, 0, (int)includedFile.Length);

                                List<ushort> binOutput = new List<ushort>();
                                foreach (byte b in rawData)
                                    binOutput.Add(b);
                                listEntry.Output = binOutput.ToArray();
                                output.Add(listEntry);
                                output[output.Count - 1].CodeType = CodeType.Directive;
                                if (!noList)
                                    currentAddress += (ushort)binOutput.Count;
                            }
                        }
                    }
                    else if ((line.StartsWith("#incpack") || line.StartsWith(".incpack")) && !noList)
                    {
                        if (!IfStack.Peek())
                            continue;
                        string includedFileName = line.Substring(line.IndexOf(" ") + 1);
                        includedFileName = includedFileName.Trim('"', '\'');
                        if (includedFileName.StartsWith("<") && includedFileName.EndsWith(">"))
                        {
                            // Find included file
                            includedFileName = includedFileName.Trim('<', '>');
                            string[] paths = IncludePath.Split(';');
                            foreach (var path in paths)
                            {
                                if (File.Exists(Path.Combine(path, includedFileName)))
                                {
                                    includedFileName = Path.Combine(path, includedFileName);
                                    break;
                                }
                            }
                        }
                        if (!File.Exists(includedFileName))
                        {
                            listEntry.ErrorCode = ErrorCode.FileNotFound;
                            output.Add(listEntry);
                        }
                        else
                        {
                            using (Stream includedFile = File.Open(includedFileName, FileMode.Open))
                            {
                                byte[] rawData = new byte[includedFile.Length];
                                includedFile.Read(rawData, 0, (int)includedFile.Length);

                                List<ushort> binOutput = new List<ushort>();
                                for (int j = 0; j < rawData.Length; j += 2)
                                {
                                    binOutput.Add((ushort)(
                                        rawData[j + 1] |
                                        (rawData[j] << 8)
                                        ));
                                }
                                listEntry.Output = binOutput.ToArray();
                                output.Add(listEntry);
                                output[output.Count - 1].CodeType = CodeType.Directive;
                                if (!noList)
                                    currentAddress += (ushort)binOutput.Count;
                            }
                        }
                    }
                    else if (line == "#endfile" || line == ".endfile")
                    {
                        if (!IfStack.Peek())
                            continue;
                        FileNames.Pop();
                        LineNumbers.Pop();
                        RootLineNumber--;
                        Directory.SetCurrentDirectory(WorkingDirectories.Pop());
                    }
                    else if (line.StartsWith(".macro") && !noList)
                    {
                        if (!IfStack.Peek())
                            continue;
                        string macroDefinition = line.Substring(7).Trim();
                        Macro macro = new Macro();
                        macro.Args = new string[0];
                        if (macroDefinition.EndsWith("{"))
                            macroDefinition = macroDefinition.Remove(macroDefinition.Length - 1).Trim();
                        if (macroDefinition.Contains("("))
                        {
                            string paramDefinition = macroDefinition.Substring(macroDefinition.IndexOf("(") + 1);
                            macro.Name = macroDefinition.Remove(macroDefinition.IndexOf("(")).Trim();
                            if (!paramDefinition.EndsWith(")"))
                            {
                                listEntry.ErrorCode = ErrorCode.InvalidMacroDefintion;
                                output.Add(listEntry);
                            }
                            else
                            {
                                paramDefinition = paramDefinition.Remove(paramDefinition.Length - 1);
                                if (paramDefinition.Length > 0)
                                {
                                    string[] parameters = paramDefinition.Split(',');
                                    bool continueEvaluation = true;
                                    for (int j = 0; j < parameters.Length; j++)
                                    {
                                        string parameter = parameters[j].Trim();
                                        if (!char.IsLetter(parameter[0]))
                                        {
                                            continueEvaluation = false;
                                            break;
                                        }
                                        foreach (char c in parameter)
                                        {
                                            if (!char.IsLetterOrDigit(c) && c != '_')
                                            {
                                                continueEvaluation = false;
                                                break;
                                            }
                                        }
                                        if (!continueEvaluation)
                                            break;
                                        macro.Args = macro.Args.Concat(new string[] { parameter }).ToArray();
                                    }
                                    if (!continueEvaluation)
                                        continue;
                                }
                            }
                        }
                        else
                            macro.Name = macroDefinition;
                        // Isolate macro code
                        macro.Code = "";
                        bool foundEndmacro = false;
                        string macroLine = line;
                        i++;
                        for (; i < lines.Length; i++)
                        {
                            line = lines[i].TrimComments().TrimExcessWhitespace();
                            LineNumbers.Push(LineNumbers.Pop() + 1);
                            if (line == ".endmacro" || line == "#endmacro" || line == "}")
                            {
                                foundEndmacro = true;
                                break;
                            }
                            if (line != "{")
                                macro.Code += "\n" + line;
                        }
                        if (!foundEndmacro)
                        {
                            listEntry.ErrorCode = ErrorCode.UncoupledStatement;
                            output.Add(listEntry);
                            continue;
                        }
                        macro.Code = macro.Code.Trim('\n');
                        Macros.Add(macro);
                        output.Add(new ListEntry(".macro " + macroDefinition, FileNames.Peek(), LineNumbers.Peek(), currentAddress, isFromExpanded));
                        output[output.Count - 1].CodeType = CodeType.Directive;
                        foreach (var codeLine in macro.Code.Split('\n'))
                        {
                            output.Add( new ListEntry( codeLine, FileNames.Peek(), LineNumbers.Peek(), currentAddress, isFromExpanded ) );
                            output[output.Count - 1].CodeType = CodeType.Directive;
                        }
                        output.Add( new ListEntry( ".endmacro", FileNames.Peek(), LineNumbers.Peek(), currentAddress, isFromExpanded ) );
                        output[output.Count - 1].CodeType = CodeType.Directive;
                    }
                    else
                    {
                        // Parse preprocessor directives
                        ParseDirectives( output, line, isFromExpanded );
                    }
                }
                else
                {
                    if (!IfStack.Peek())
                        continue;
                    // Search through macros
                    bool mayHaveMacro = false;
                    foreach (Macro macro in Macros)
                    {
                        if (line.StartsWith(macro.Name))
                        {
                            mayHaveMacro = true;
                            break;
                        }
                    }
                    if (line.SafeContains('(') && line.SafeContains(')') && mayHaveMacro)
                    {
                        Macro userMacro = new Macro();
                        userMacro.Args = new string[0];
                        string macroDefinition = line;
                        string paramDefinition = macroDefinition.Substring(macroDefinition.IndexOf("(") + 1);
                        userMacro.Name = macroDefinition.Remove(macroDefinition.IndexOf("(")).Trim();
                        if (!paramDefinition.EndsWith(")"))
                        {
                            listEntry.ErrorCode = ErrorCode.InvalidMacroDefintion;
                            output.Add(listEntry);
                        }
                        else
                        {
                            paramDefinition = paramDefinition.Remove(paramDefinition.Length - 1);
                            if (paramDefinition.Length > 0)
                            {
                                string[] parameters = paramDefinition.SafeSplit(',');
                                for (int j = 0; j < parameters.Length; j++)
                                {
                                    string parameter = parameters[j].Trim();
                                    userMacro.Args = userMacro.Args.Concat(new[] { parameter }).ToArray();
                                }
                            }
                        }
                        bool macroMatched = false;
                        foreach (Macro macro in Macros)
                        {
                            if (macro.Name == userMacro.Name &&
                                macro.Args.Length == userMacro.Args.Length)
                            {
                                // Expand the macro
                                userMacro.Code = macro.Code;
                                for (int j = 0; j < macro.Args.Length; j++)
                                    userMacro.Code = userMacro.Code.Replace(macro.Args[j], userMacro.Args[j]);
                                string[] macroCode = userMacro.Code.Replace("\r", "\n").Split('\n');
                                string[] newLines = new string[lines.Length + macroCode.Length - 1];
                                Array.Copy(lines, 0, newLines, 0, i);
                                Array.Copy(macroCode, 0, newLines, i, macroCode.Length);
                                if (lines.Length > i + 1)
                                    Array.Copy(lines, i + 1, newLines, i + macroCode.Length, lines.Length - i - 1);
                                lines = newLines;
                                output.Add(listEntry);
                                output[output.Count - 1].CodeType = CodeType.Directive;
                                line = lines[i].TrimComments().TrimExcessWhitespace();
                                macroMatched = true;
                                SuspendedLineCounts.Push(macroCode.Length); // Suspend the line counts for the expanded macro
                            }
                        }
                        if (macroMatched)
                        {
                            i--;
                            continue;
                        }
                        // We'll just let the opcode matcher yell at them if it isn't found
                    }

                    // Check for OPCodes
                    var opcode = MatchString(line, OpcodeTable);
                    bool nonBasic = false;
                    if (opcode == null)
                    {
                        opcode = MatchString(line, NonBasicOpcodeTable);
                        nonBasic = true;
                    }
                    if (opcode == null)
                    {
                        listEntry.ErrorCode = ErrorCode.InvalidOpcode;
                        output.Add(listEntry);
                        continue;
                    }
                    else
                    {
                        listEntry.Opcode = opcode;
                        StringMatch valueA = null, valueB = null;
                        listEntry.Output = new ushort[1];
                        if (!nonBasic)
                        {
                            listEntry.CodeType = CodeType.BasicInstruction;
                            if (opcode.valueA != null)
                                valueA = MatchString(opcode.valueA, ValueTable);
                            if (opcode.valueB != null)
                                valueB = MatchString(opcode.valueB, ValueTable);
                            if (nonBasic == false && (opcode.valueA == null || opcode.valueB == null))
                            {
                                listEntry.ErrorCode = ErrorCode.InvalidOpcode;
                                output.Add(listEntry);
                                continue;
                            }
                            if (valueA.value == valueB.value && valueA.value != 0x1E && valueB.value != 0x1E && opcode.value == 0x1)
                                listEntry.WarningCode = WarningCode.RedundantStatement;
                            if (valueB.value == 0x1F && !opcode.match.Contains("IF"))
                                listEntry.WarningCode = WarningCode.AssignToLiteral;
                            listEntry.ValueA = valueA;
                            listEntry.ValueB = valueB;
                            // De-localize labels
                            if (listEntry.ValueA.isLiteral)
                            {
                                listEntry.Output = listEntry.Output.Concat(new ushort[1]).ToArray();
                                var result = ParseExpression(listEntry.ValueA.literal);
                                foreach (var reference in result.References)
                                {
                                    if (reference.StartsWith("."))
                                        listEntry.ValueA.literal = listEntry.ValueA.literal.Replace(reference,
                                            PriorGlobalLabel + "_" + reference.Substring(1));
                                }
                            }
                            if (listEntry.ValueB.isLiteral)
                            {
                                listEntry.Output = listEntry.Output.Concat(new ushort[1]).ToArray();
                                var result = ParseExpression(listEntry.ValueB.literal);
                                foreach (var reference in result.References)
                                {
                                    if (reference.StartsWith("."))
                                        listEntry.ValueB.literal = listEntry.ValueB.literal.Replace(reference,
                                            PriorGlobalLabel + "_" + reference.Substring(1));
                                }
                            }
                        }
                        else
                        {
                            listEntry.CodeType = CodeType.NonBasicInstruction;
                            if (opcode.valueA != null)
                                valueA = MatchString(opcode.valueA, ValueTable);
                            listEntry.ValueA = valueA;
                            // De-localize labels
                            if (listEntry.ValueA.isLiteral)
                            {
                                listEntry.Output = listEntry.Output.Concat(new ushort[1]).ToArray();
                                var result = ParseExpression(listEntry.ValueA.literal);
                                foreach (var reference in result.References)
                                {
                                    if (reference.StartsWith(".") || reference.StartsWith("_"))
                                        listEntry.ValueA.literal = listEntry.ValueA.literal.Replace(reference,
                                            PriorGlobalLabel + "_" + reference.Substring(1));
                                }
                            }
                        }
                        output.Add(listEntry);
                        currentAddress++;
                        if (valueA != null)
                            if (valueA.isLiteral)
                                currentAddress++;
                        if (valueB != null)
                            if (valueB.isLiteral)
                                currentAddress++;
                    }
                }
            }
            return EvaluateAssembly(output);
        }
예제 #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);
        }