Пример #1
0
        /**
         * Parses a single end record.
         *
         * @param rec the end record to be parsed
         * @param mod the module this end record will be a part of
         *
         * @return true if the end record is successfully parsed
         *         false if parsing the end record is unsuccessful
         *
         * @refcode
         *  OB5
         * @errtest
         * @errmsg
         *  EW.18, ES.34, ES.35, ES.36
         * @author Mark Mathis
         * @creation May 19, 2011
         * @modlog
         * @teststandard Andrew Buelow
         * @codestandard Mark Mathis
         */
        public bool ParseEnd(string rec, Module mod)
        {
            string[] field = rec.Split(':');

            // check that the record has the correct number of fields
            if (field.Length != 2)
            {
                // record has the wrong number of fields
                errPrinter.PrintError(ErrCat.Warning, 18);
                return true;
            }

            // check that program name is valid
            string prgmName = field[1];

            /* Regular expression used to determine if all characters in the token are
             * letters or numbers. */
            Regex alphaNumeric = new Regex(@"[^0-9a-zA-Z]");

            if (2 <= prgmName.Length && prgmName.Length <= 32)
            {
                if (!(!alphaNumeric.IsMatch(prgmName) && char.IsLetter(prgmName[0])))
                {
                    // program name is not a valid label
                    errPrinter.PrintError(ErrCat.Serious, 34);
                }
            }
            else
            {
                // program name is not the right length
                errPrinter.PrintError(ErrCat.Serious, 34);
            }

            // check that this program name is in the symbol table.
            if (mod.ModuleName != prgmName)
            {
                // error, must have the same program name at the end of the record as the
                // module currently being parsed
                errPrinter.PrintError(ErrCat.Serious, 35);
                return true;
            }

            if (!symb.ContainsSymbol(prgmName))
            {
                // error, program name not in symbol table
                errPrinter.PrintError(ErrCat.Serious, 36);
            }

            return true;
        }
Пример #2
0
        /**
         * Looks at the modify records and does the adjustments in the records.
         *
         * @param mod the Module whose modify records should be calculated
         * @param symb the SymbolTable that contains the symbols in the specified Module
         *
         * @refcode
         *  OB4
         * @errtest
         * @errmsg
         *  ES.50, ES.51, ES.56
         * @author Mark Mathis
         * @creation May 22, 2011
         * @modlog
         * @teststandard Andrew Buelow
         * @codestandard Mark Mathis
         */
        private void doModifyRecords(Module mod, SymbolTable symb)
        {
            var mRec = mod.ModifyRecords;
            foreach (var rec in mRec)
            {
                int word = mRec[rec.Key].Word;
                int s = Convert.ToInt32(Convert.ToString(word, 2).PadLeft(16, '0').Substring(6), 2);
                //string sbin = Convert.ToString(word, 2).PadRight(10,'0');
                //string swhat = sbin.Substring(6);
                //int s = Convert.ToInt32(swhat, 2);
                List<string> adjs = mRec[rec.Key].Adjustments;

                for (int i = 0; i < adjs.Count; i += 2)
                {
                    string sign = adjs[i];
                    string label = adjs[i + 1];

                    try
                    {
                        if (sign == "+")
                        {
                            word += symb.GetSymbol(label).LinkerValue;
                            s += symb.GetSymbol(label).LinkerValue;
                        }
                        else if (sign == "-")
                        {
                            word -= symb.GetSymbol(label).LinkerValue;
                            s -= symb.GetSymbol(label).LinkerValue;
                        }
                        else
                        {
                            // error, the sign should only be a + or -
                            errPrinter.PrintError(ErrCat.Serious, 50);
                            continue;
                        }
                    }
                    catch (Assembler.SymbolException)
                    {
                        // error, symbol doesn't exist in symbol table
                        errPrinter.PrintError(ErrCat.Serious, 51);
                        continue;
                    }
                }

                try
                {
                    mod.GetTextRecord(mRec[rec.Key].Location).Word = word;
                }
                catch (NullReferenceException)
                {
                    errPrinter.PrintError(ErrCat.Serious, 56);
                }
            }
        }
Пример #3
0
        /**
         * Makes the Linker do things in the right order.
         *
         * @refcode
         * @errtest
         * @errmsg
         *  ES.57 and any errors caused by every other part of the Linker
         * @author Mark Mathis
         * @creation May 18, 2011
         * @modlog
         * @teststandard Andrew Buelow
         * @codestandard Mark Mathis
         */
        static void Main(string[] args)
        {
            // allows the use of the Assembler.Errors class for error handling
            Assembler.Errors.SetResource(Properties.Resources.Errors);

            // get the command line arguments
            string[] infiles = new string[1];
            if (args.Length > 0)
            {
                infiles = args;
            }
            else
            {
                // there must be at least one input file
                Usage();
                System.Environment.Exit(1);
            }

            // output the file to a file using the first argument minus the extension
            // with the .ffa extension added to the end
            string outfile = System.IO.Path.GetFileNameWithoutExtension(infiles[0]) + ".ffa";

            // get all the things needed to parse the input files
            Parser pars = new Parser();

            // how many files have been parsed
            int file = 0;

            // the address the parser should use when calculating the module load addresses
            int address = 0;

            // the symbol table to save symbols in
            SymbolTable symb = new SymbolTable();
            // the list to save the modules in
            List<Module> modules = new List<Module>();

            // Let's parse us some files
            try
            {
                foreach (var f in infiles)
                {
                    // the module that will hold the object file currently being parsed
                    Module mod = new Module();
                    try
                    {
                        int modlen = 0;
                        if (modules.Count > 0)
                        {
                            modlen = modules[file - 1].HeaderRecord.ModuleLength;
                        }
                        pars.ParseFile(f, out mod, symb, file, ref address, ref modlen);
                    }
                    catch (Error ex)
                    {
                        // there was a problem while parsing :(
                        if (ex.err.category == Assembler.Errors.Category.Fatal)
                        {
                            // fatal error should stop the linker
                            // keep the exception moving
                            throw ex;
                        }
                        else
                        {
                            // not fatal, output the error and keep on going
                            Console.WriteLine(ex.err);
                            continue;
                        }
                    }

                    // make sure there is actually input
                    if (mod.HeaderRecord != null)
                    {
                        // add the module to the module list
                        modules.Add(mod);
                    }

                    // a file has been parsed
                    file++;
                }

                // make sure that modules were actually produced from the parsing
                if (modules.Count > 0)
                {
                    // create the load file with our newfound knowledge
                    LoadFile load = new LoadFile(modules, symb);
                    load.Render(outfile);
                }
                else
                {
                    // no valid files parsed
                    Assembler.Errors.GetInstance().PrintError(Assembler.Errors.Category.Serious, 57);
                }

                // output the symbol table after successfully making the load file
                Console.WriteLine(symb);
            }
            catch (Error)
            {
                // gracefully die on fatal exceptions
                Console.WriteLine("Stopping linker due to fatal error.");

                // output however much of the symbol table was made before the
                // fatal error was encountered. it probably won't ever be much
                Console.WriteLine(symb);
                System.Environment.Exit(1);
            }
            //            catch (Exception)
            //            {
            //                // die with a bad excuse for anything else
            //                Console.WriteLine("Something bad happened and the Linker could not recover.");
            //                System.Environment.Exit(2);
            //            }
        }
Пример #4
0
        /**
         * Parses a single text record.
         *
         * @param rec the text record to be parsed
         * @param mod the module this text record will be a part of
         *
         * @refcode
         *  OB3
         * @errtest
         * @errmsg
         *  EW.11, EW.12, EW.13, EW.14, ES.16, ES.17, ES.18, ES.19, ES.20, ES.21, ES.22, ES.23
         * @author Mark Mathis
         * @creation May 19, 2011
         * @modlog
         * @teststandard Andrew Buelow
         * @codestandard Mark Mathis
         */
        public void ParseText(string rec, Module mod)
        {
            string[] field = rec.Split(':');
            Text textRecord = new Text();

            // check that the record has the correct number of fields
            if (field.Length != 6)
            {
                // error, wrong number of fields
                throw new Error(ErrCat.Serious, 16);
            }

            // check program assigned location
            string progLoc = field[1].ToUpper();

            // check length, should be 4 digit hex number
            if (progLoc.Length != 4)
            {
                // error, wrong length
                errPrinter.PrintError(ErrCat.Warning, 11);
            }

            //check that it is valid hex
            int progLocVal = 0;
            try
            {
                progLocVal = Convert.ToInt32(progLoc, 16);
            }
            catch (FormatException)
            {
                // error, not valid hex
                errPrinter.PrintError(ErrCat.Serious, 17);
            }

            // check that it is in the correct range
            if (progLocVal < 0 || progLocVal > 1023)
            {
                // error, must be between 0 and 1023
                errPrinter.PrintError(ErrCat.Serious, 18);
            }

            // add program location to the linker text record
            textRecord.Location = progLocVal;

            // check the hex code of the instruction
            string hexCode = field[2].ToUpper();

            // check length, should be 4 digit hex number
            if (hexCode.Length < 4)
            {
                // error, too short
                errPrinter.PrintError(ErrCat.Warning, 12);
            }
            else if (hexCode.Length > 4)
            {
                // error, too long
                errPrinter.PrintError(ErrCat.Serious, 19);
                hexCode = "8000";
            }

            //check that it is valid hex
            int hexCodeVal = 0;
            try
            {
                hexCodeVal = Convert.ToInt32(hexCode, 16);
            }
            catch (FormatException)
            {
                // error, not valid hex
                errPrinter.PrintError(ErrCat.Serious, 20);
                hexCodeVal = Convert.ToInt32("8000", 16);
            }

            // add hex code of instruction to linker text record
            textRecord.Word = hexCodeVal;

            // check address status flag
            string addStatus = field[3].ToUpper();

            // check length of flag, should be 1
            if (addStatus.Length != 1)
            {
                // error wrong length
                errPrinter.PrintError(ErrCat.Serious, 21);
                addStatus = "A";
            }

            // check that the flag is a valid value
            if (!(addStatus[0] == 'A' || addStatus[0] == 'R' || addStatus[0] == 'M'))
            {
                // error, invalid value for status flag
                errPrinter.PrintError(ErrCat.Serious, 21);
                addStatus = "A";
            }

            // add status flag to linker text record
            textRecord.Flag = addStatus[0];

            // check number of M adjustments needed
            string mAdj = field[4].ToUpper();

            // check that it is the correct length, should be 1
            if (mAdj.Length != 1)
            {
                // error wrong length
                errPrinter.PrintError(ErrCat.Warning, 13);
                mAdj = "1";
            }

            // check that it is valid hex
            int mAdjVal = 0;
            try
            {
                mAdjVal = Convert.ToInt32(mAdj, 16);
            }
            catch (FormatException)
            {
                // error, not valid hex
                errPrinter.PrintError(ErrCat.Warning, 14);
                mAdjVal = 1;
            }
            // if it's valid then it should be in the correct range
            // since one hex digit can only be 0-15

            // add number of adjustments to the linker text record
            textRecord.Adjustments = mAdjVal;

            // check the program name
            string prgmName = field[5];

            // check that the program name is in the symbol table
            if (mod.ModuleName != prgmName)
            {
                // error, program name at end of text record must match
                // program name of program being parsed
                throw new Error(ErrCat.Serious, 22);
            }

            if (!symb.ContainsSymbol(prgmName))
            {
                // error, program name is not in symbol table
                throw new Error(ErrCat.Serious, 23);
            }

            mod.AddRecord(textRecord);
        }
Пример #5
0
        /**
         * Parses a single modify record.
         *
         * @param rec the modify record to be parsed
         * @param mod the module this text record will be a part of
         *
         * @refcode
         *  OB4
         * @errtest
         * @errmsg
         *  EW.15, EW.16, EW.17, ES.24, ES.25, ES.26, ES.27, ES.28, ES.29, ES.30, ES.31, ES.32
         * @author Mark Mathis
         * @creation May 19, 2011
         * @modlog
         * @teststandard Andrew Buelow
         * @codestandard Mark Mathis
         */
        public void ParseModify(string rec, Module mod)
        {
            string[] field = rec.Split(':');
            Modify modRecord = new Modify();

            // check the location
            string loc = field[1];

            // check the length of the location
            if (loc.Length != 4)
            {
                // error, incorrect length
                errPrinter.PrintError(ErrCat.Warning, 15);
            }

            // check that it is a valid hex string
            int locVal = 0;
            try
            {
                locVal = Convert.ToInt32(loc, 16);
            }
            catch (FormatException)
            {
                // error, not valid hex
                throw new Error(ErrCat.Serious, 24);
            }

            // check that the location value is in the proper range
            if (locVal < 0 || locVal > 1023)
            {
                // error, location invalid
                throw new Error(ErrCat.Serious, 25);
            }

            // add  location to the linker modification record
            modRecord.Location = locVal;

            // check the hex code of the word
            string hex = field[2];

            // check the length of the hex code
            if (hex.Length < 4)
            {
                // error, too short
                errPrinter.PrintError(ErrCat.Warning, 16);
            }
            else if (hex.Length > 4)
            {
                // error, too long
                throw new Error(ErrCat.Serious, 26);
            }

            // check that it is a valid hex string
            int hexVal = 0;
            try
            {
                hexVal = Convert.ToInt32(hex, 16);
            }
            catch (FormatException)
            {
                // error, not valid hex
                throw new Error(ErrCat.Serious, 27);
            }

            // add the hex code of the word to be modified to the linker modification record
            modRecord.Word = hexVal;

            /* Regular expression used to determine if all characters in the token are
             * letters or numbers. */
            Regex alphaNumeric = new Regex(@"[^0-9a-zA-Z]");

            // go through the modifications and make sure they are formatted correctly
            string sign = field[3];

            // check that sign is a + or -
            if (!(sign == "+" || sign == "-"))
            {
                // error, sign must be a + or -
                throw new Error(ErrCat.Serious, 28);
            }

            int i = 4;
            while (sign == "+" || sign == "-")
            {
                string label = field[i++];

                // check that label is valid label
                if (2 <= label.Length && label.Length <= 32)
                {
                    if (!(!alphaNumeric.IsMatch(label) && char.IsLetter(label[0])))
                    {
                        // label is not a valid label
                        errPrinter.PrintError(ErrCat.Serious, 29);
                    }
                }
                else
                {
                    // label is not the right length
                    errPrinter.PrintError(ErrCat.Serious, 29);
                }

                // add adjustments to the linker modification record
                modRecord.AddAdjustments(sign, label);

                // get next sign
                try
                {
                    sign = field[i++];
                }
                catch (IndexOutOfRangeException)
                {
                    throw new Error(ErrCat.Serious, 32);
                }
            }
            // reached end of modification record, or there was an error
            // in the format of modifications

            // check that label is valid label
            if (2 <= sign.Length && sign.Length <= 32)
            {
                if (!(!alphaNumeric.IsMatch(sign) && char.IsLetter(sign[0])))
                {
                    // label is not a valid label
                    errPrinter.PrintError(ErrCat.Serious, 29);
                }
            }
            else
            {
                // label is not the right length
                errPrinter.PrintError(ErrCat.Serious, 29);
            }

            // check if the label is in the symbol table
            // if it is, it's probably not an error
            // if it isn't, it could be an error: say something about it
            if (mod.ModuleName != sign)
            {
                // error, program name at the end of modification record must match
                // program name of program being parsed
                throw new Error(ErrCat.Serious, 30);
            }

            if (!symb.ContainsSymbol(sign))
            {
                // error, something isn't in the symbol table
                throw new Error(ErrCat.Serious, 31);
            }

            //check to see that the modify record doesn't have too many adjustments
            if (modRecord.Adjustments.Count > 15)
            {
                // error, can only have 15 adjustments in a modify record
                errPrinter.PrintError(ErrCat.Warning, 17);
            }

            // add modification record to module
            mod.AddRecord(modRecord);
        }
Пример #6
0
        /**
         * Parses a single linking record.
         *
         * @param rec the linking record to be parsed
         * @param mod the module this linking record will be a part of
         *
         * @refcode
         *  OB2
         * @errtest
         * @errmsg
         *  EW.10, ES.09, ES.10, ES.11, ES.12, ES.13, ES.14, ES.15
         * @author Mark Mathis
         * @creation May 19, 2011
         * @modlog
         * @teststandard Andrew Buelow
         * @codestandard Mark Mathis
         */
        public void ParseLink(string rec, Module mod)
        {
            string[] field = rec.Split(':');
            Linking linkRecord = new Linking();

            // check if record has the correct number of fields
            if (field.Length != 4)
            {
                // error, wrong number of fields
                errPrinter.PrintError(ErrCat.Serious, 9);
            }

            // check that Entry name is valid
            string entry = field[1];

            /* Regular expression used to determine if all characters in the token are
             * letters or numbers. */
            Regex alphaNumeric = new Regex(@"[^0-9a-zA-Z]");

            if (2 <= entry.Length && entry.Length <= 32)
            {
                if (!(!alphaNumeric.IsMatch(entry) && char.IsLetter(entry[0])))
                {
                    // entry name is not a valid label
                    errPrinter.PrintError(ErrCat.Serious, 10);
                }
            }
            else
            {
                // entry name is not the right length
                errPrinter.PrintError(ErrCat.Serious, 10);
            }

            // add entry name to linker linking record
            linkRecord.EntryName = entry;

            // get the location within the program
            string prgmLoc = field[2].ToUpper();

            // check length, should be 4 digit hex number
            if (prgmLoc.Length != 4)
            {
                // error, wrong length
                errPrinter.PrintError(ErrCat.Warning, 10);
            }

            //check that it is valid hex
            int prgmLocVal = 0;
            try
            {
                prgmLocVal = Convert.ToInt32(prgmLoc, 16);
            }
            catch (FormatException)
            {
                // error, not valid hex
                throw new Error(ErrCat.Serious, 11);
            }

            // check that it is in the correct range
            if (prgmLocVal < 0 || prgmLocVal > 1023)
            {
                // error, must be between 0 and 1023
                errPrinter.PrintError(ErrCat.Serious, 12);
            }

            // add location to linking header record
            linkRecord.Location = prgmLocVal;

            // make sure the program name is properly formatted
            // and in the symbol table
            string pgmName = field[3];

            if (2 <= pgmName.Length && pgmName.Length <= 32)
            {
                if (!(!alphaNumeric.IsMatch(pgmName) && char.IsLetter(pgmName[0])))
                {
                    // program name is not a valid label
                    throw new Error(ErrCat.Serious, 13);
                }
            }
            else
            {
                // program name is not the right length
                throw new Error(ErrCat.Serious, 13);
            }

            // check that program name is in symbol table
            if (mod.ModuleName != pgmName)
            {
                // error, program name at end of linking record must match program name
                // of program being parsed
                throw new Error(ErrCat.Serious, 14);
            }

            if (!symb.ContainsSymbol(pgmName))
            {
                // error, program name not in the symbol table
                errPrinter.PrintError(ErrCat.Serious, 15);
            }

            // add entry to symbol table
            mod.AddRecord(linkRecord);
        }
Пример #7
0
        /**
         * Parses a single FFA object file header record. This should be the first line of
         * the assembler output.
         *
         * @param rec the header record to be parsed
         * @param mod the module this header record will be a part of
         *
         * @refcode
         *  OB1
         * @errtest
         * @errmsg
         *  EW.01, EW.02, EW.03, EW.04, EW.05, EW.06, EW.07, EW.08, EW.09,
         *  ES.02, ES.03, ES.04, ES.05, ES.06, ES.07, ES.08, EF.01, EF.02,
         *  EF.03, EF.04, EF.05, EF.06, EF.07, EF.08
         * @author Mark Mathis
         * @creation May 19, 2011
         * @modlog
         * @teststandard Andrew Buelow
         * @codestandard Mark Mathis
         */
        public void ParseHeader(string rec, out Module mod)
        {
            string[] field = rec.Split(':');
            Header head = new Header();

            // check that the header record contains the correct number of fields
            if (field.Length != 13)
            {
                // error, wrong number of fields in header record
                throw new Error(ErrCat.Fatal, 1);
            }

            // check that program name is valid
            string prgmName = field[1];

            /* Regular expression used to determine if all characters in the token are
             * letters or numbers. */
            Regex alphaNumeric = new Regex(@"[^0-9a-zA-Z]");

            if (2 <= prgmName.Length && prgmName.Length <= 32)
            {
                if (!(!alphaNumeric.IsMatch(prgmName) && char.IsLetter(prgmName[0])))
                {
                    // program name is not a valid label
                    errPrinter.PrintError(ErrCat.Serious, 2);
                }
            }
            else
            {
                // program name is not the right length
                errPrinter.PrintError(ErrCat.Serious, 2);
            }

            // add program name to the linking header record
            head.ProgramName = prgmName;

            // get the Assembler assigned program load address
            // see if it is properly formatted
            string assLoad = field[2].ToUpper();

            // check length, should be 4 digit hex number
            if (assLoad.Length != 4)
            {
                // error, wrong length
                errPrinter.PrintError(ErrCat.Serious, 3);
            }

            //check that it is valid hex
            int assLoadVal = 0;
            try
            {
                assLoadVal = Convert.ToInt32(assLoad, 16);
            }
            catch (FormatException)
            {
                // error, not valid hex
                throw new Error(ErrCat.Fatal, 2);
            }

            // check that it is in the correct range
            if (assLoadVal < 0 || assLoadVal > 1023)
            {
                // error, must be between 0 and 1023
                throw new Error(ErrCat.Fatal, 3);
            }

            // add assembler load address to linking header record
            head.AssemblerLoadAddress = assLoadVal;

            // get the module length
            string modLen = field[3].ToUpper();

            // check that it is a 4 digit hex
            if (modLen.Length != 4)
            {
                // error, wrong length
                errPrinter.PrintError(ErrCat.Serious, 4);
            }

            // check that it is valid hex
            int modLenVal = 0;
            try
            {
                modLenVal = Convert.ToInt32(modLen, 16);
            }
            catch (FormatException)
            {
                // error, not valid hex
                throw new Error(ErrCat.Fatal, 4);
            }

            // check that it is in the correct range
            if (modLenVal < 0 || modLenVal > 1024)
            {
                // error, must be between 0 and 1024
                throw new Error(ErrCat.Fatal, 5);
            }

            // add module length to linking header record
            head.ModuleLength = modLenVal;

            // get the execution start address
            string execAdd = field[4].ToUpper();

            // check length, should be 4 digit hex number
            if (execAdd.Length != 4)
            {
                // error, wrong length
                errPrinter.PrintError(ErrCat.Serious, 5);
            }

            //check that it is valid hex
            int execAddVal = 0;
            try
            {
                execAddVal = Convert.ToInt32(execAdd, 16);
            }
            catch (FormatException)
            {
                // error, not valid hex
                throw new Error(ErrCat.Fatal, 6);
            }

            // check that it is in the correct range
            if (execAddVal < 0 || execAddVal > 1023)
            {
                // error, must be between 0 and 1023
                throw new Error(ErrCat.Fatal, 7);
            }

            // add execution start address to linking header record
            head.ExecutionStartAddress = execAddVal;

            // get date and time of assembly
            string dateAndTime = field[5];

            // check that it is the proper length
            if (dateAndTime.Length != 16)
            {
                // error?, not the proper length
                errPrinter.PrintError(ErrCat.Warning, 1);
            }

            // get version number of assembler that assembled this header record
            string verNum = field[6].ToUpper();

            // check that it's the proper length, 4 digits
            if (verNum.Length != 4)
            {
                // error?, not the proper length
                errPrinter.PrintError(ErrCat.Warning, 2);
            }

            // get the total number of records in the object file
            string totalRec = field[7].ToUpper();

            // check length, should be 4 digit hex number
            if (totalRec.Length != 4)
            {
                // error, wrong length
                errPrinter.PrintError(ErrCat.Warning, 3);
            }

            //check that it is valid hex
            int totalRecVal = 0;
            try
            {
                totalRecVal = Convert.ToInt32(totalRec, 16);
            }
            catch (FormatException)
            {
                // error, not valid hex
                errPrinter.PrintError(ErrCat.Warning, 4);
            }

            // add the total number of records to the linker header record
            head.TotalRecords = totalRecVal;

            // get the number of linking records in the object file
            string linkRec = field[8].ToUpper();

            // check length, should be 4 digit hex number
            if (linkRec.Length != 4)
            {
                // error, wrong length
                errPrinter.PrintError(ErrCat.Warning, 5);
            }

            // check that it is valid hex
            int linkRecVal = 0;
            try
            {
                linkRecVal = Convert.ToInt32(linkRec, 16);
            }
            catch (FormatException)
            {
                // error, not valid hex
                errPrinter.PrintError(ErrCat.Warning, 6);
            }

            // add the total number of linking records to the linker header record
            head.TotalLinkingRecords = linkRecVal;

            // get the number of text records in the object file
            string textRec = field[9].ToUpper();

            // check length, should be 4 digit hex number
            if (textRec.Length != 4)
            {
                // error, wrong length
                errPrinter.PrintError(ErrCat.Serious, 6);
            }

            // check that it is valid hex
            int textRecVal = 0;
            try
            {
                textRecVal = Convert.ToInt32(textRec, 16);
            }
            catch (FormatException)
            {
                // error, not valid hex
                errPrinter.PrintError(ErrCat.Serious, 7);
            }

            // check that the number is in the proper range
            if (textRecVal < 0 || textRecVal > modLenVal)
            {
                // error, can only have 0 to module length text records
                throw new Error(ErrCat.Fatal, 8);
            }

            // add the total number of text records to the linker header record
            head.TotalTextRecords = textRecVal;

            // get the number of modify records in the object file
            string modRec = field[10].ToUpper();

            // check length, should be 4 digit hex number
            if (modRec.Length != 4)
            {
                // error, wrong length
                errPrinter.PrintError(ErrCat.Warning, 7);
            }

            // check that it is valid hex
            int modRecVal = 0;
            try
            {
                modRecVal = Convert.ToInt32(modRec, 16);
            }
            catch (FormatException)
            {
                // error, not valid hex
                errPrinter.PrintError(ErrCat.Warning, 8);
            }

            // add the total number of modify records to the linker header record
            head.TotalModifyRecords = modRecVal;

            // check that the assembler name is correct
            if (field[11].ToUpper() != "FFA-ASM")
            {
                // error? wrong assembler?
                errPrinter.PrintError(ErrCat.Warning, 9);
            }

            // check that the program name at the end of
            // the record is the same as at the beginning
            if (field[12] != prgmName)
            {
                // error, program names do not match
                errPrinter.PrintError(ErrCat.Serious, 8);
            }

            if (fileNum == 0)
            {
                head.LinkerLoadAddress = assLoadVal;
                address = modLenVal;
            }
            else
            {
                head.LinkerLoadAddress = address + assLoadVal + lastModuleLen;
                address += modLenVal;
            }

            mod = new Module(head);
            symb.AddSymbol(mod.ModuleName, Assembler.Usage.PRGMNAME, mod.RelocateValue);
        }
Пример #8
0
        /**
         * Parses a single FFA object file. This file is the output of the FFA assembler.
         *
         * @param filename the filename of the file to parse
         * @param mod the module that represents the file that is read in
         * @param symb the linker symbol table
         * @param fileNum how many files have been parsed before this file
         * @param startAddress the linker calculated start address of this module
         *
         * @refcode
         *  OB1, OB2, OB3, OB4, OB5
         * @errtest
         * @errmsg
         *  ES.01, ES.35, ES.55
         * @author Mark Mathis
         * @creation May 19, 2011
         * @modlog
         * @teststandard Andrew Buelow
         * @codestandard Mark Mathis
         */
        public void ParseFile(string filename, out Module mod, SymbolTable symb, int fileNum, ref int startAddress, ref int lastModuleLength)
        {
            // instantiate mod right away since it must be instantiated before
            // this method exits
            mod = new Module();

            // keep track of which file we are parsing
            this.fileNum = fileNum;

            // keep track of which linker computed address we are on
            this.address = startAddress;

            StreamReader file = null;
            try
            {
                file = new StreamReader(filename);
            }
            catch (Exception)
            {
                // error, input file cannot be opened
                throw new Error(ErrCat.Serious, 55);
            }

            this.symb = symb;
            int lineNum = 1;
            string rec;
            bool endReached = false;
            while ((rec = file.ReadLine()) != null)
            {
                try
                {
                    // ignore empty lines
                    if (rec.Trim().Length == 0)
                    {
                        continue;
                    }

                    if (endReached)
                    {
                        // error, input present after the end record
                        throw new Error(ErrCat.Serious, 1);
                    }

                    // process different types of records
                    if (rec[0] == 'H')
                    {
                        ParseHeader(rec, out mod);
                    }
                    else if (rec[0] == 'L')
                    {
                        ParseLink(rec, mod);
                    }
                    else if (rec[0] == 'T')
                    {
                        ParseText(rec, mod);
                    }
                    else if (rec[0] == 'M')
                    {
                        ParseModify(rec, mod);
                    }
                    else if (rec[0] == 'E')
                    {
                        endReached = ParseEnd(rec, mod);

                        if (mod.HeaderRecord != null)
                        {
                            // since end record has been reached there should be no more input
                            // check to see if the correct number of records has been found
                            CheckRecords(mod);

                            // add linking records to the symbol table since all the data we
                            // need should be there at this point
                            DoLinkingRecords(mod);
                        }
                    }
                    else
                    {
                        // invalid record or garbage data
                        throw new Error(ErrCat.Serious, 33);
                    }
                }
                catch (Error ex)
                {
                    Console.WriteLine(String.Format(
                            "Parsing error on line {0} of {1}:\n{2}",
                            lineNum, filename, ex));
                    if (ex.err.category == ErrCat.Fatal)
                    {
                        throw ex;
                    }
                }

                lineNum++;
            }
            startAddress = address;
        }
Пример #9
0
 /**
  * Adds all the entries found in the linking records to the symbol table.
  *
  * @param mod the module whose linking records should be added to the symbol table
  *
  * @refcode
  *  OB2
  * @errtest
  * @errmsg
  *  ES.38, ES.39
  * @author Mark Mathis
  * @creation May 22, 2011
  * @modlog
  * @teststandard Andrew Buelow
  * @codestandard Mark Mathis
  */
 private void DoLinkingRecords(Module mod)
 {
     var lRec = mod.LinkingRecords;
     foreach (var rec in lRec)
     {
         try
         {
             int lValue = mod.GetTextRecord(lRec[rec.Key].Location).Location;
             symb.AddSymbol(lRec[rec.Key].EntryName, Assembler.Usage.ENTRY, lValue);
         }
         catch (NullReferenceException)
         {
             // there's no text record with a corresponding location counter value
             errPrinter.PrintError(ErrCat.Serious, 39);
         }
         catch (Assembler.SymbolException)
         {
             // error, symbol already in symbol table
             errPrinter.PrintError(ErrCat.Serious, 38);
         }
     }
 }
Пример #10
0
        /**
         * Checks to see if the number of records actually parsed matches the number
         * of records reported by the header record.
         *
         * @param mod the module whose records should be checked
         *
         * @refcode
         *  OB1, OB2, OB3, OB4, OB5
         * @errtest
         * @errmsg
         *  EW.19, EW.20, ES.37
         * @author Mark Mathis
         * @creation May 22, 2011
         * @modlog
         * @teststandard Andrew Buelow
         * @codestandard Mark Mathis
         */
        private void CheckRecords(Module mod)
        {
            if (mod.HeaderRecord.TotalTextRecords != mod.TotalTextRecords)
            {
                // error, wrong number of text records
                errPrinter.PrintError(ErrCat.Serious, 37);
            }

            if (mod.HeaderRecord.TotalLinkingRecords != mod.TotalLinkingRecords)
            {
                // error, wrong number of linking records
                errPrinter.PrintError(ErrCat.Warning, 19);
            }

            if (mod.HeaderRecord.TotalModifyRecords != mod.TotalModifyRecords)
            {
                // error, wrong number of modify records
                errPrinter.PrintError(ErrCat.Warning, 20);
            }
        }