Ejemplo n.º 1
0
        /// <summary>
        /// Retrieves a code generator implementation for a specified segment type.
        /// </summary>
        /// <param name="segType">The segment type to retrieve a code generator for.</param>
        /// <returns>The code generator implementation for the specified segment.</returns>
        public ISegmentCodeGenerator GetCodeGeneratorForSegment(SegmentType segType)
        {
            ISegmentCodeGenerator codeGen = default(ISegmentCodeGenerator);

            if (!m_CodeGeneratorTable.TryGetValue(segType, out codeGen))
            {
                throw new ArgumentException("No code generator available for segment type " + segType);
            }

            return(codeGen);
        }
        /// <summary>
        /// Generates code for the given assembly file.
        /// </summary>
        /// <param name="reader">A StreamReader instance that will read the input assembly file.</param>
        /// <param name="objFile">The basic object file that will be written to.</param>
        public void GenerateCode(string fileName, StreamReader reader, BasicObjectFile objFile)
        {
            SegmentType currSegmentType = SegmentType.Invalid;
            int         currAlignment   = CommonConstants.DEFAULT_ALIGNMENT;

            // a list of all exceptions we encounter during parsing.
            // users can view them all at once instead of working through them piecemeal.
            var exceptionList = new List <AssemblyException>();
            int lineNum       = 0;

            while (!reader.EndOfStream)
            {
                try
                {
                    ++lineNum;
                    // trim the whitespace from any read-in line.
                    string line = reader.ReadLine().Trim();

                    // get a substring up until the commented line, ignoring those in user quotes.
                    line = ParserCommon.GetSanitizedString(line);

                    // ignore blank lines. trim should remove all whitespace
                    if (line.Any())
                    {
                        LineParseResults directiveResults = ParserCommon.HandleAssemblerDirective(line, lineNum, currSegmentType, currAlignment);

                        // if we have a new data alignment, we need to record this in case the disassembler
                        // parses this file. otherwise, it will interpret padding bytes as actual data elements.
                        if (currAlignment != directiveResults.NewAlignment)
                        {
                            objFile.AddAlignmentChangeDeclaration(directiveResults.NewAlignment);
                        }

                        currAlignment   = directiveResults.NewAlignment;
                        currSegmentType = directiveResults.NewSegment;

                        // if our segment type is valid, then we're processing actual data versus an assembler directive.
                        if (!directiveResults.IsLineAssemblerDirective &&
                            currSegmentType != SegmentType.Invalid)
                        {
                            if (!TryHandlingLinkageDeclaration(line, lineNum, objFile))
                            {
                                ISegmentCodeGenerator codeGen = m_CodeGenFac.GetCodeGeneratorForSegment(currSegmentType);
                                var asmLine = new LineData(line, lineNum);
                                try
                                {
                                    codeGen.GenerateCodeForSegment(fileName, asmLine, objFile, currAlignment);
                                }
                                catch (AssemblyException)
                                {
                                    throw;
                                }
                                catch (Exception ex)
                                {
                                    throw new AssemblyException(lineNum, ex.Message);
                                }
                            }
                        }
                    }
                }
                catch (AssemblyException ex)
                {
                    exceptionList.Add(ex);
                }
            }

            // if any exceptions were encountered, throw an aggregate exception with
            // all of the encountered exceptions.
            if (exceptionList.Any())
            {
                throw new AggregateAssemblyError(exceptionList);
            }

            // reset the StreamReader to the beginning position.
            reader.Seek(0, SeekOrigin.Begin);
        }