예제 #1
0
        void AssembleBinaryFile(SourceLine line)
        {
            if (!line.OperandHasToken)
            {
                throw new ExpressionException(line.Instruction.Position, "Filename not specified.");
            }

            BinaryFile file;
            var        filename = line.Operand.Children[0].Children[0].Name;

            if (_includedBinaries.ContainsKey(filename))
            {
                file = _includedBinaries[filename];
            }
            else
            {
                if (!filename.EnclosedInDoubleQuotes())
                {
                    throw new ExpressionException(line.Operand.Position, "Filename not given in quotes.");
                }
                file = new BinaryFile(filename.TrimOnce('"'));
                if (!file.Open())
                {
                    throw new ExpressionException(line.Operand.Position, $"Unable to open file \"{filename}\".");
                }
                _includedBinaries.Add(filename, file);
            }

            var offset = 0;
            var size   = file.Data.Length;

            if (size > ushort.MaxValue)
            {
                throw new ExpressionException(line.Operand.Position, "File size is too large.");
            }
            if (line.Operand.Children.Count > 1)
            {
                if (line.Operand.Children.Count > 2)
                {
                    if (line.Operand.Children.Count > 3)
                    {
                        throw new ExpressionException(line.Operand.Children[3].Position, "Too many arguments specified for directive.");
                    }
                    size = (int)Evaluator.Evaluate(line.Operand.Children[2].Children, ushort.MinValue, ushort.MaxValue);
                }
                offset = (int)Evaluator.Evaluate(line.Operand.Children[1].Children, ushort.MinValue, ushort.MaxValue);
            }
            if (offset > size - 1)
            {
                offset = size - 1;
            }
            if (size > file.Data.Length - offset)
            {
                size = file.Data.Length - offset;
            }

            if (size > ushort.MaxValue)
            {
                throw new ExpressionException(line.Operand.Position, $"Difference between specified offset and size is greater than the maximum allowed amount.");
            }

            line.Assembly = Assembler.Output.AddBytes(file.Data.Skip(offset), size);
        }
예제 #2
0
        static void AssembleStrings(SourceLine line)
        {
            if (!line.OperandHasToken)
            {
                throw new ExpressionException(line.Instruction.Position,
                                              $"Instruction \"{line.InstructionName}\" expects one or more string arguments.");
            }

            line.Assembly = new List <byte>();
            var stringBytes = new List <byte>();
            var uninit      = 0;

            foreach (Token child in line.Operand.Children)
            {
                if (child.Children.Count == 0)
                {
                    throw new ExpressionException(child.Position, $"Expected value for instruction \"{line.InstructionName}\".");
                }

                if (child.Children[0].ToString().Equals("?"))
                {
                    if (child.Children.Count > 1)
                    {
                        Assembler.Log.LogEntry(line, child.Children[1].Position,
                                               $"Unexpected expression \"{child.Children[1].Name}\".");
                    }
                    uninit++;
                    Assembler.Output.AddUninitialized(1);
                }
                else
                {
                    if (StringHelper.ExpressionIsAString(child))
                    {
                        stringBytes.AddRange(Assembler.Encoding.GetBytes(StringHelper.GetString(child)));
                    }
                    else
                    {
                        stringBytes.AddRange(BinaryOutput.ConvertToBytes(Evaluator.Evaluate(child)).ToList());
                    }
                }
            }
            switch (line.InstructionName)
            {
            case ".cstring":
                stringBytes.Add(0x00);
                break;

            case ".pstring":
                if (stringBytes.Count > 255)
                {
                    throw new ExpressionException(line.Operand.Position, $"String expression exceeds the maximum length of \".pstring\" directive.");
                }

                stringBytes.Insert(0, Convert.ToByte(stringBytes.Count));
                break;

            case ".lstring":
            case ".nstring":
                if (stringBytes.Any(b => b > 0x7f))
                {
                    throw new ExpressionException(line.Operand.Position, $"One or more elements in expression \"{line.Operand}\" exceeds maximum value.");
                }
                if (line.InstructionName.Equals(".lstring"))
                {
                    stringBytes       = stringBytes.Select(b => Convert.ToByte(b << 1)).ToList();
                    stringBytes[^ 1] |= 1;
예제 #3
0
        double EvaluateSymbol(RandomAccessIterator <Token> tokens)
        {
            var token     = tokens.Current;
            var subscript = -1;
            var converted = double.NaN;
            var isString  = token.IsDoubleQuote();

            if (char.IsLetter(token.Name[0]) || token.Name[0] == '_')
            {
                var next = tokens.GetNext();
                if (next != null && next.IsOpen() && next.Name.Equals("["))
                {
                    subscript = (int)Evaluator.Evaluate(tokens, 0, int.MaxValue);
                }
                var symbol = SymbolManager.GetSymbol(token, CurrentPass > 0);
                if (symbol == null)
                {
                    if (token.Line.Label != null && token.Line.Label.Name.Equals(token.Name, StringViewComparer))
                    {
                        throw new SymbolException(token, SymbolException.ExceptionReason.NotDefined);
                    }
                    PassNeeded = true;
                    return(0x100);
                }
                if (subscript >= 0)
                {
                    if (symbol.StorageType != StorageType.Vector)
                    {
                        throw new SyntaxException(token.Position, "Type mismatch.");
                    }
                    if ((symbol.IsNumeric && subscript >= symbol.NumericVector.Count) ||
                        (!symbol.IsNumeric && subscript >= symbol.StringVector.Count))
                    {
                        throw new SyntaxException(token.Position, "Index was out of range.");
                    }
                    if (symbol.IsNumeric)
                    {
                        return(symbol.NumericVector[subscript]);
                    }
                    token    = new Token(symbol.StringVector[subscript], TokenType.Operand);
                    isString = true;
                }
                else if (symbol.IsNumeric)
                {
                    if (symbol.DataType == DataType.Address && symbol.Bank != Output.CurrentBank)
                    {
                        return((int)symbol.NumericValue | (symbol.Bank * 0x10000));
                    }
                    return(symbol.NumericValue);
                }
                else
                {
                    token    = new Token(symbol.StringValue, TokenType.Operand);
                    isString = true;
                }
            }
            if (isString || token.IsQuote())
            {
                // is it a string literal?
                var literal = token.IsQuote() ? token.Name.TrimOnce(token.Name[0]).ToString() : token.Name.ToString();
                if (string.IsNullOrEmpty(literal))
                {
                    throw new SyntaxException(token.Position, "Cannot evaluate empty string.");
                }
                literal = Regex.Unescape(literal);
                if (!isString)
                {
                    var charsize = 1;
                    if (char.IsSurrogate(literal[0]))
                    {
                        charsize++;
                    }
                    if (literal.Length > charsize)
                    {
                        throw new SyntaxException(token.Position, "Invalid char literal.");
                    }
                }
                // get the integral equivalent from the code points in the string
                converted = Encoding.GetEncodedValue(literal);
            }
            else if (token.Name.Equals("*"))
            {    // get the program counter
                converted = Output.LogicalPC;
            }
            else if (token.Name[0].IsSpecialOperator())
            {    // get the special character value
                if (token.Name[0] == '+' && CurrentPass == 0)
                {
                    converted  = Output.LogicalPC;
                    PassNeeded = true;
                }
                else
                {
                    converted = SymbolManager.GetLineReference(token.Name, token);
                    if (double.IsNaN(converted))
                    {
                        var reason = token.Name[0] == '+' ? SymbolException.ExceptionReason.InvalidForwardReference :
                                     SymbolException.ExceptionReason.InvalidBackReference;
                        throw new SymbolException(token, reason);
                    }
                }
            }
            if (double.IsNaN(converted))
            {
                throw new ExpressionException(token.Position,
                                              $"\"{token.Name}\" is not a expression.");
            }
            return(converted);
        }