Example #1
0
        IEnumerable <SourceLine> ProcessExpansion(IEnumerable <SourceLine> sources)
        {
            var processed = new List <SourceLine>();

            foreach (SourceLine line in sources)
            {
                if (line.InstructionName.Equals(".include") || line.InstructionName.Equals(".binclude"))
                {
                    processed.AddRange(ExpandInclude(line));
                }
                else if (_macros.ContainsKey(line.InstructionName))
                {
                    Macro macro = _macros[line.InstructionName];
                    processed.AddRange(ProcessExpansion(macro.Expand(line.Operand)));
                }
                else if (line.InstructionName.Equals(".endmacro"))
                {
                    Assembler.Log.LogEntry(line, line.Instruction,
                                           "Directive \".endmacro\" does not close a macro definition.");
                    break;
                }
                else
                {
                    processed.Add(line);
                }
            }
            return(processed);
        }
Example #2
0
        IEnumerable <SourceLine> ProcessMacros(IEnumerable <SourceLine> uncommented)
        {
            var macroProcessed = new List <SourceLine>();
            RandomAccessIterator <SourceLine> lineIterator = uncommented.GetIterator();
            SourceLine line = null;

            while ((line = lineIterator.GetNext()) != null)
            {
                try
                {
                    if (string.IsNullOrWhiteSpace(line.ParsedSource))
                    {
                        macroProcessed.Add(line);
                        continue;
                    }
                    if (line.InstructionName.Equals(".macro"))
                    {
                        if (string.IsNullOrEmpty(line.LabelName))
                        {
                            Assembler.Log.LogEntry(line, line.Instruction, "Macro name not specified.");
                            continue;
                        }
                        var macroName = "." + line.LabelName;

                        if (_macros.ContainsKey(macroName))
                        {
                            Assembler.Log.LogEntry(line, line.Label, $"Macro named \"{line.LabelName}\" already defined.");
                            continue;
                        }
                        if (Assembler.IsReserved.Any(i => i.Invoke(macroName)) ||
                            !char.IsLetter(line.LabelName[0]))
                        {
                            Assembler.Log.LogEntry(line, line.Label, $"Macro name \"{line.LabelName}\" is not valid.");
                            continue;
                        }
                        Reserved.AddWord("MacroNames", macroName);

                        var compare = Assembler.Options.CaseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase;
                        var macro   = new Macro(line.Operand, line.ParsedSource, compare);
                        _macros[macroName] = macro;
                        var instr = line;
                        while ((line = lineIterator.GetNext()) != null && !line.InstructionName.Equals(".endmacro"))
                        {
                            if (macroName.Equals(line.InstructionName))
                            {
                                Assembler.Log.LogEntry(line, line.Instruction, "Recursive macro call not allowed.");
                                continue;
                            }
                            if (line.InstructionName.Equals(".macro"))
                            {
                                Assembler.Log.LogEntry(line, line.Instruction, "Nested macro definitions not allowed.");
                                continue;
                            }
                            if (line.InstructionName.Equals(".include") || line.InstructionName.Equals(".binclude"))
                            {
                                var includes = ExpandInclude(line);
                                foreach (var incl in includes)
                                {
                                    if (macroName.Equals(incl.InstructionName))
                                    {
                                        Assembler.Log.LogEntry(incl, incl.Instruction, "Recursive macro call not allowed.");
                                        continue;
                                    }
                                    macro.AddSource(incl);
                                }
                            }
                            else
                            {
                                macro.AddSource(line);
                            }
                        }
                        if (!string.IsNullOrEmpty(line.LabelName))
                        {
                            if (line.OperandHasToken)
                            {
                                Assembler.Log.LogEntry(line, line.Operand, "Unexpected argument found for macro definition closure.");
                                continue;
                            }
                            line.Instruction  = null;
                            line.ParsedSource = line.ParsedSource.Replace(".endmacro", string.Empty);
                            macro.AddSource(line);
                        }
                        else if (line == null)
                        {
                            line = instr;
                            Assembler.Log.LogEntry(instr, instr.Instruction, "Missing closure for macro definition.");
                            continue;
                        }
                    }
                    else if (line.InstructionName.Equals(".include") || line.InstructionName.Equals(".binclude"))
                    {
                        macroProcessed.AddRange(ExpandInclude(line));
                    }
                    else if (_macros.ContainsKey(line.InstructionName))
                    {
                        if (!string.IsNullOrEmpty(line.LabelName))
                        {
                            SourceLine clone = line.Clone();
                            clone.Operand          =
                                clone.Instruction  = null;
                            clone.UnparsedSource   =
                                clone.ParsedSource = line.LabelName;
                            macroProcessed.Add(clone);
                        }
                        Macro macro = _macros[line.InstructionName];
                        macroProcessed.AddRange(ProcessExpansion(macro.Expand(line.Operand)));
                    }
                    else if (line.InstructionName.Equals(".endmacro"))
                    {
                        Assembler.Log.LogEntry(line, line.Instruction,
                                               "Directive \".endmacro\" does not close a macro definition.");
                        continue;
                    }
                    else
                    {
                        macroProcessed.Add(line);
                    }
                }
                catch (ExpressionException ex)
                {
                    Assembler.Log.LogEntry(line, ex.Position, ex.Message);
                }
            }
            return(macroProcessed);
        }