public bool Read(string filename)
        {
            //try
            {
                m_Symbols   = new List <SymbolEntry>();
                m_Filenames = new List <FilenameSection>();
                byte[] data = System.IO.File.ReadAllBytes(filename);

                if (data.Length > 0)
                {
                    GCHandle pinnedData = GCHandle.Alloc(data, GCHandleType.Pinned);
                    IntPtr   stream     = pinnedData.AddrOfPinnedObject();

                    FilenameHeader  filenameHeader  = new FilenameHeader();
                    ChunkHeader     chunkHeader     = new ChunkHeader();
                    FilenameSection filenameSection = new FilenameSection();
                    AddressEntry    addressEntry    = new AddressEntry();
                    SymbolChunk     symbolChunk     = new SymbolChunk();
                    SymbolEntry     symbolEntry     = new SymbolEntry();
                    string          readString;

                    int bytesRead  = 0;
                    int totalBytes = data.Length;

                    // Symbol lines are 1-based, text editor lines are 0-based
                    int currentLine = 1;

                    //Read file header
                    FileHeader fileHeader = new FileHeader();
                    bytesRead += Serialise(ref stream, out fileHeader);

                    void CheckSize(int chunkLength)
                    {
                        if ((bytesRead + chunkLength) >= totalBytes)
                        {
                            throw new Exception("Bad chunk length or malformed file");
                        }
                    }

                    //Iterate over chunks
                    while (bytesRead < data.Length)
                    {
                        //Read chunk header
                        bytesRead += Serialise(ref stream, out chunkHeader);

                        //What is it?
                        switch (chunkHeader.chunkId)
                        {
                        case ChunkId.Filename:
                        {
                            //Read filename header
                            bytesRead            += Serialise(ref stream, out filenameHeader);
                            filenameHeader.length = Endian.Swap(filenameHeader.length);

                            //Read string
                            CheckSize(filenameHeader.length);
                            bytesRead += Serialise(ref stream, filenameHeader.length, out readString);

                            if (filenameHeader.flags == 0x1)
                            {
                                //This is the filename passed for assembly
                                m_AssembledFile = readString;
                            }
                            else
                            {
                                //If filename already exists, continue adding data to it
                                int sectionIdx = m_Filenames.FindIndex(element => element.filename == readString);
                                if (sectionIdx >= 0)
                                {
                                    //Continue
                                    filenameSection = m_Filenames[sectionIdx];

                                    //Fetch line counter
                                    currentLine = filenameSection.addresses[filenameSection.addresses.Count - 1].lineTo;
                                }
                                else
                                {
                                    //This is the first address in a filename chunk
                                    filenameSection           = new FilenameSection();
                                    filenameSection.addresses = new List <AddressEntry>();

                                    try
                                    {
                                        string pathSanitised = System.IO.Path.GetFullPath(readString).ToUpper();
                                        filenameSection.filename = pathSanitised;
                                    }
                                    catch (Exception e)
                                    {
                                        Console.WriteLine("Exception caught sanitising symbol path \'" + readString + "\': " + e.Message);
                                    }

                                    //Reset line counter
                                    currentLine = 1;
                                }

                                //Chunk payload contains address
                                addressEntry.address  = chunkHeader.payload;
                                addressEntry.lineFrom = currentLine - 1;
                                addressEntry.lineTo   = filenameHeader.firstLine - 1;
                                currentLine           = filenameHeader.firstLine;
                                filenameSection.addresses.Add(addressEntry);

                                //Next
                                currentLine++;

                                //Add to filename list
                                m_Filenames.Add(filenameSection);
                            }

                            break;
                        }

                        case ChunkId.Address:
                        {
                            //Chunk payload contains address for a single line
                            addressEntry.address = chunkHeader.payload;

                            //Set line range
                            addressEntry.lineFrom = currentLine - 1;
                            addressEntry.lineTo   = currentLine - 1;

                            //Next
                            currentLine++;

                            //Add
                            filenameSection.addresses.Add(addressEntry);

                            break;
                        }

                        case ChunkId.AddressWithCount:
                        {
                            //Chunk payload contains address for a rage of lines
                            addressEntry.address = chunkHeader.payload;

                            //Read line count
                            byte lineCount = 0;
                            bytesRead += Serialise(ref stream, out lineCount);

                            //Set line range
                            addressEntry.lineFrom = currentLine - 1;
                            addressEntry.lineTo   = currentLine + (lineCount - 1) - 1;

                            //Next
                            currentLine += lineCount;

                            //Add
                            filenameSection.addresses.Add(addressEntry);

                            break;
                        }

                        case ChunkId.Symbol:
                        {
                            //Read symbol string length
                            byte stringLength = 0;
                            bytesRead += Serialise(ref stream, out stringLength);

                            //Read string
                            CheckSize(stringLength);
                            bytesRead += Serialise(ref stream, stringLength, out symbolEntry.name);

                            //Payload contains address
                            symbolEntry.address = chunkHeader.payload;

                            m_Symbols.Add(symbolEntry);

                            break;
                        }

                        case ChunkId.EndOfSection:
                            //Payload contains section size
                            break;

                        default:
                            short mysteryWord = 0;
                            bytesRead += Serialise(ref stream, out mysteryWord);
                            break;
                        }
                    }

                    pinnedData.Free();

                    //Build address to file/line map
                    m_Addr2FileLine = new Dictionary <uint, Tuple <string, int, int> >();

                    foreach (FilenameSection section in m_Filenames)
                    {
                        foreach (AddressEntry address in section.addresses)
                        {
                            if (!m_Addr2FileLine.ContainsKey(address.address))
                            {
                                m_Addr2FileLine[address.address] = new Tuple <string, int, int>(section.filename, address.lineFrom, address.lineTo);
                            }
                        }
                    }

                    return(true);
                }
            }
            //catch (Exception e)
            //{
            //    Console.WriteLine(e.Message);
            //}

            return(false);
        }
Exemple #2
0
        public bool Read(string filename)
        {
            try
            {
                m_Symbols   = new List <SymbolEntry>();
                m_Filenames = new List <FilenameSection>();
                byte[] data = System.IO.File.ReadAllBytes(filename);

                if (data.Length > 0)
                {
                    GCHandle pinnedData = GCHandle.Alloc(data, GCHandleType.Pinned);
                    IntPtr   stream     = pinnedData.AddrOfPinnedObject();

                    FilenameHeader  filenameHeader  = new FilenameHeader();
                    ChunkHeader     chunkHeader     = new ChunkHeader();
                    FilenameSection filenameSection = new FilenameSection();
                    AddressEntry    addressEntry    = new AddressEntry();
                    SymbolChunk     symbolChunk     = new SymbolChunk();
                    SymbolEntry     symbolEntry     = new SymbolEntry();
                    string          readString;

                    int bytesRead   = 0;
                    int currentLine = 0;

                    //Read file header
                    FileHeader fileHeader = new FileHeader();
                    bytesRead += Serialise(ref stream, out fileHeader);

                    //Iterate over chunks
                    while (bytesRead < data.Length)
                    {
                        //Read chunk header
                        bytesRead += Serialise(ref stream, out chunkHeader);

                        //What is it?
                        switch (chunkHeader.chunkId)
                        {
                        case ChunkId.Filename:
                        {
                            //Read filename header
                            bytesRead += Serialise(ref stream, out filenameHeader);
                            EndianSwap(ref filenameHeader.length);

                            //Read string
                            bytesRead += Serialise(ref stream, filenameHeader.length, out readString);

                            if (filenameHeader.flags == 0x1)
                            {
                                //This is the filename passed for assembly
                                m_AssembledFile = readString;
                            }
                            else
                            {
                                //If filename already exists, continue adding data to it
                                int sectionIdx = m_Filenames.FindIndex(element => element.filename == readString);
                                if (sectionIdx >= 0)
                                {
                                    //Continue
                                    filenameSection = m_Filenames[sectionIdx];

                                    //Fetch line counter
                                    currentLine = filenameSection.addresses[filenameSection.addresses.Count - 1].lineTo;
                                }
                                else
                                {
                                    //This is the first address in a filename chunk
                                    filenameSection           = new FilenameSection();
                                    filenameSection.addresses = new List <AddressEntry>();
                                    filenameSection.filename  = readString;

                                    //Reset line counter
                                    currentLine = 0;
                                }

                                //Chunk payload contains address
                                addressEntry.address  = chunkHeader.payload;
                                addressEntry.lineFrom = currentLine;
                                addressEntry.lineTo   = filenameHeader.firstLine;
                                currentLine           = filenameHeader.firstLine;
                                filenameSection.addresses.Add(addressEntry);

                                //Add to filename list
                                m_Filenames.Add(filenameSection);
                            }

                            break;
                        }

                        case ChunkId.Address:
                        {
                            //Chunk payload contains address
                            addressEntry.address = chunkHeader.payload;

                            //Set line range
                            addressEntry.lineFrom = currentLine;
                            currentLine++;
                            addressEntry.lineTo = currentLine;

                            //Add
                            filenameSection.addresses.Add(addressEntry);

                            break;
                        }

                        case ChunkId.AddressWithCount:
                        {
                            //Read line count
                            byte lineCount = 0;
                            bytesRead += Serialise(ref stream, out lineCount);

                            //Chunk payload contains address
                            addressEntry.address = chunkHeader.payload;

                            //Set line range
                            addressEntry.lineFrom = currentLine;
                            currentLine          += lineCount;
                            addressEntry.lineTo   = currentLine;

                            //Add
                            filenameSection.addresses.Add(addressEntry);

                            break;
                        }

                        case ChunkId.Symbol:
                        {
                            //Read symbol string length
                            byte stringLength = 0;
                            bytesRead += Serialise(ref stream, out stringLength);

                            //Read string
                            bytesRead += Serialise(ref stream, stringLength, out symbolEntry.name);

                            //Payload contains address
                            symbolEntry.address = chunkHeader.payload;

                            m_Symbols.Add(symbolEntry);

                            break;
                        }

                        case ChunkId.EndOfSection:
                            //Nothing of interest
                            break;
                        }
                    }

                    pinnedData.Free();

                    //Build address to file/line map
                    m_Addr2FileLine = new Dictionary <uint, Tuple <string, int> >();

                    foreach (FilenameSection section in m_Filenames)
                    {
                        foreach (AddressEntry address in section.addresses)
                        {
                            if (!m_Addr2FileLine.ContainsKey(address.address))
                            {
                                m_Addr2FileLine[address.address] = new Tuple <string, int>(section.filename, address.lineTo);
                            }
                        }
                    }

                    return(true);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }

            return(false);
        }