/// <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); }