/// <summary> /// Called so as to make the necessary decision making whilst the state machine is discarding code during a multiline define /// </summary> /// <param name="sourceLine">source line under analysis</param> /// <param name="sourceLineType">source code type as inspected by the Inspect function in the conditional inclusions machine</param> /// <param name="expression">not used</param> /// <param name="subtitutionText">not used</param> public void Process(ref string sourceLine, SourceLineType sourceLineType, string expression, string subtitutionText) { if (!(defineRegexMultilineContinuation.IsMatch(sourceLine))) { //last line of the multiline define met (which should be discarded as well) _conditionalInclusionsMachine.FinishWithCurrentState(); } { //still in the multiline define } sourceLine = ""; }
/// <summary> /// Called so as to make the necessary decision making whilst the state machine is discarding code during a failed if /// </summary> /// <param name="sourceLine">source line under analysis</param> /// <param name="sourceLineType">source code type as inspected by the Inspect function in the conditional inclusions machine</param> /// <param name="expression">expression to be evaluated in case the source Line type is an elif</param> /// <param name="subtitutionText"></param> public void Process(ref string sourceLine, SourceLineType sourceLineType, string expression, string subtitutionText) { sourceLine = ""; switch (sourceLineType) { case SourceLineType.Ifclause: case SourceLineType.Ifdefclause: case SourceLineType.Ifndefclause: /* * In case we encounter an other if whilst discarding we add an other layer * so as to keep the matching endif clauses. * * The reason why we push DiscardingDueToSuccessfullIf is to suppress any * attempt any elif and else at this level. */ _conditionalInclusionsMachine.AddState(ParserState.DiscardingDueToSuccessfullIf); break; case SourceLineType.Elifclause: switch (_conditionalInclusionsMachine.Evaluator.EvaluateExpression(expression, _conditionalInclusionsMachine.DefinesHandler)) { case EvaluationResult.IsFalse: /* * in case the evaluation failed the state remains the same. We just * continue discarding. */ break; case EvaluationResult.IsTrue: /* * in case the evaluation is successfull we just change the state of * the current level */ _conditionalInclusionsMachine.UpdateCurrentState(ParserState.IncludingDueToIf); break; case EvaluationResult.UnDetermined: throw new SourceDiscoveryException(string.Format(CultureInfo.InvariantCulture, "Unable to evaluate expression \"{0}\"", expression)); } break; case SourceLineType.Elseclause: _conditionalInclusionsMachine.UpdateCurrentState(ParserState.IncludingDueToIf); break; case SourceLineType.Endifclause: _conditionalInclusionsMachine.FinishWithCurrentState(); break; } }
/// <summary> /// Called so as to make the necessary decision making whilst the state machine is discarding code due to a previously /// successful if statement (i.e. we are currently in some elif or else statement) /// </summary> /// <param name="sourceLine">source line under analysis</param> /// <param name="sourceLineType">source code type as inspected by the Inspect function in the conditional inclusions machine</param> /// <param name="expression">not used</param> /// <param name="subtitutionText">not used</param> public void Process(ref string sourceLine, SourceLineType sourceLineType, string expression, string subtitutionText) { sourceLine = ""; switch (sourceLineType) { case SourceLineType.Ifclause: case SourceLineType.Ifndefclause: case SourceLineType.Ifdefclause: /* * In case we encounter an other if whilst discarding we add an other layer * so as to keep the matching endif clauses */ _conditionalInclusionsMachine.AddState(ParserState.DiscardingDueToSuccessfullIf); break; case SourceLineType.Endifclause: _conditionalInclusionsMachine.FinishWithCurrentState(); break; } }
/// <summary> /// Inspects the source line and sets the sourceLineType (byref) according to detected code syntax /// and sets also the expression variable (byref) to the matched identifier statement/expression where applicable /// </summary> /// <param name="sourceLine">source line to inspect</param> /// <param name="sourceLineType">match type</param> /// <param name="token">extracted expression or identifier respective to the source type</param> /// <param name="substitutiontext">extracted substitution text (applicable only to a define match)</param> private static void Inspect(string sourceLine, out SourceLineType sourceLineType, out string token, out string substitutiontext) { if (ElifRegex.IsMatch(sourceLine)) { sourceLineType = SourceLineType.Elifclause; token = ElifRegex.Match(sourceLine).Groups[1].Value; substitutiontext = ""; } else if (ElseRegex.IsMatch(sourceLine)) { sourceLineType = SourceLineType.Elseclause; token = ""; substitutiontext = ""; } else if (EndifRegex.IsMatch(sourceLine)) { sourceLineType = SourceLineType.Endifclause; token = ""; substitutiontext = ""; } else if (IfdefRegex.IsMatch(sourceLine)) { sourceLineType = SourceLineType.Ifdefclause; token = IfdefRegex.Match(sourceLine).Groups[1].Value; substitutiontext = ""; } else if (IfndefRegex.IsMatch(sourceLine)) { sourceLineType = SourceLineType.Ifndefclause; token = IfndefRegex.Match(sourceLine).Groups[1].Value; substitutiontext = ""; } else if (IfRegex.IsMatch(sourceLine)) { sourceLineType = SourceLineType.Ifclause; token = IfRegex.Match(sourceLine).Groups[1].Value; substitutiontext = ""; } else if (DefineRegexMultiline.IsMatch(sourceLine)) { sourceLineType = SourceLineType.MultiLineDefineclause; token = DefineRegexMultiline.Match(sourceLine).Groups[1].Value; substitutiontext = ""; } else if (DefineRegexMacro.IsMatch(sourceLine)) { sourceLineType = SourceLineType.Defineclause; token = DefineRegexMacro.Match(sourceLine).Groups[1].Value; substitutiontext = ""; } else if (DefineRegex.IsMatch(sourceLine)) { sourceLineType = SourceLineType.Defineclause; token = DefineRegex.Match(sourceLine).Groups[1].Value; substitutiontext = DefineRegex.Match(sourceLine).Groups[2].Value.Trim(); } else if (UndefineRegex.IsMatch(sourceLine)) { sourceLineType = SourceLineType.Undefineclause; token = UndefineRegex.Match(sourceLine).Groups[1].Value; substitutiontext = ""; } else { //any other type of source code that is an unrelated to the conditional inclusions sourceLineType = SourceLineType.Other; token = ""; substitutiontext = ""; } }
/// <summary> /// Called so as to make the necessary decision making when a positively evaluated conditional has been met /// </summary> /// <param name="sourceLine">source line under analysis that may or may not be filtered</param> /// <param name="sourceLineType">source code type as inspected by the Inspect function in the conditional inclusions machine</param> /// <param name="expression">expression to be evaluated in case the source Line type is a conditional based on an expression</param> /// <param name="subtitutionText">substitution text in case of a define</param> public void Process(ref string sourceLine, SourceLineType sourceLineType, string expression, string subtitutionText) { switch (sourceLineType) { case SourceLineType.Other: //Encountered source code NOT related to the conditional inclusions. break; case SourceLineType.Elifclause: //since we were in successfull if inclusion and now we met an elif we have to discard anything in the elif _conditionalInclusionsMachine.UpdateCurrentState(ParserState.DiscardingDueToSuccessfullIf); sourceLine = ""; break; case SourceLineType.Elseclause: _conditionalInclusionsMachine.UpdateCurrentState(ParserState.DiscardingDueToSuccessfullIf); sourceLine = ""; break; case SourceLineType.Endifclause: _conditionalInclusionsMachine.FinishWithCurrentState(); sourceLine = ""; break; case SourceLineType.Ifclause: switch (_conditionalInclusionsMachine.Evaluator.EvaluateExpression(expression, _conditionalInclusionsMachine.DefinesHandler)) { case EvaluationResult.IsFalse: _conditionalInclusionsMachine.AddState(ParserState.DiscardingDueToFailedIf); break; case EvaluationResult.IsTrue: _conditionalInclusionsMachine.AddState(ParserState.IncludingDueToIf); break; case EvaluationResult.UnDetermined: throw new SourceDiscoveryException(string.Format(CultureInfo.InvariantCulture, "Unable to evaluate expression \"{0}\"", expression)); } sourceLine = ""; break; case SourceLineType.MultiLineDefineclause: _conditionalInclusionsMachine.AddState(ParserState.DiscardingDueToMultilineDefine); _conditionalInclusionsMachine.DefinesHandler.Define(expression, ""); sourceLine = ""; break; case SourceLineType.Defineclause: _conditionalInclusionsMachine.DefinesHandler.Define(expression, subtitutionText); sourceLine = ""; break; case SourceLineType.Undefineclause: _conditionalInclusionsMachine.DefinesHandler.UnDefine(expression); sourceLine = ""; break; case SourceLineType.Ifdefclause: switch (_conditionalInclusionsMachine.DefinesHandler.IsDefined(expression)) { case true: _conditionalInclusionsMachine.AddState(ParserState.IncludingDueToIf); break; case false: _conditionalInclusionsMachine.AddState(ParserState.DiscardingDueToFailedIf); break; } sourceLine = ""; break; case SourceLineType.Ifndefclause: switch (_conditionalInclusionsMachine.DefinesHandler.IsDefined(expression)) { case true: _conditionalInclusionsMachine.AddState(ParserState.DiscardingDueToFailedIf); break; case false: _conditionalInclusionsMachine.AddState(ParserState.IncludingDueToIf); break; } sourceLine = ""; break; } }
public void Process(ref string sourceLine, SourceLineType sourceLineType, string expression, string subtitutionText) { switch (sourceLineType) { case SourceLineType.Ifdefclause: switch (_conditionalInclusionsMachine.DefinesHandler.IsDefined(expression)) { case true: _conditionalInclusionsMachine.AddState(ParserState.IncludingDueToIf); break; case false: _conditionalInclusionsMachine.AddState(ParserState.DiscardingDueToFailedIf); break; } sourceLine = ""; break; case SourceLineType.Ifndefclause: switch (_conditionalInclusionsMachine.DefinesHandler.IsDefined(expression)) { case true: _conditionalInclusionsMachine.AddState(ParserState.DiscardingDueToFailedIf); break; case false: _conditionalInclusionsMachine.AddState(ParserState.IncludingDueToIf); break; } sourceLine = ""; break; case SourceLineType.Ifclause: switch (_conditionalInclusionsMachine.Evaluator.EvaluateExpression(expression, _conditionalInclusionsMachine.DefinesHandler)) { case EvaluationResult.IsFalse: _conditionalInclusionsMachine.AddState(ParserState.DiscardingDueToFailedIf); break; case EvaluationResult.IsTrue: _conditionalInclusionsMachine.AddState(ParserState.IncludingDueToIf); break; case EvaluationResult.UnDetermined: throw new SourceDiscoveryException(string.Format(CultureInfo.InvariantCulture, "Unable to evaluate expression \"{0}\"", expression)); } sourceLine = ""; break; case SourceLineType.MultiLineDefineclause: _conditionalInclusionsMachine.AddState(ParserState.DiscardingDueToMultilineDefine); _conditionalInclusionsMachine.DefinesHandler.Define(expression, ""); sourceLine = ""; break; case SourceLineType.Defineclause: _conditionalInclusionsMachine.DefinesHandler.Define(expression, subtitutionText); sourceLine = ""; break; case SourceLineType.Undefineclause: _conditionalInclusionsMachine.DefinesHandler.UnDefine(expression); sourceLine = ""; break; case SourceLineType.Other: //Encountered source code NOT related to the conditional inclusions. break; case SourceLineType.Elifclause: // ReSharper disable once StringLiteralTypo throw new SourceDiscoveryException("unexpected #elif found."); case SourceLineType.Elseclause: throw new SourceDiscoveryException("unexpected #else found."); case SourceLineType.Endifclause: throw new SourceDiscoveryException("unexpected #endif found."); default: throw new SourceDiscoveryException("unexpected conditional found. code " + sourceLineType); } }
private bool ParseLine() { //A Blank line in the source file if (_text.Length == 0) { _type = SourceLineType.BLANK; _instruction = ARMInstruction.NOP; return(true); } //Line is a comment if (_text[0] == ';') { _type = SourceLineType.COMMENT; _instruction = ARMInstruction.NOP; return(true); } //Remove any comments from the line string temp = _text; int commentStartIndex = _text.IndexOf(';'); if (commentStartIndex > 0) { temp = _text.Remove(commentStartIndex); } //Trim white space temp = temp.Trim(); //Split into fields delimited by whitespace string[] fields = temp.Split(new char[] { ' ', '\t' }); //Is the first field a directive, label, or instruction? // Refactor into bool isDirective(string) Array typeArray = Enum.GetValues(typeof(SourceLineType)); foreach (SourceLineType st in typeArray) { if (fields[0].Equals(st.ToString())) { _type = st; _label = st.ToString(); _instruction = ARMInstruction.NOP; //Ignore any text following a directive to the assembler return(true); } } //MOV has 3 fields at this point: //MOV //R1,R1,LSL //#0x1 //Only one field, not a directive so must be a label if (fields.Length == 1) { _label = fields[0]; _type = SourceLineType.LABEL; _instruction = ARMInstruction.NOP; return(true); } //If there are 3 fields, the first must be a label, the second the instruction //and third operands, or theres is no label and a shift in the second field bool shiftOperation = false; foreach (string cmd in Enum.GetNames(typeof(ShiftCommand))) { if (fields[1].Contains(cmd)) { shiftOperation = true; break; } } int instructionIndex = 0; int operandIndex = 0; int shiftAmountIndex = 0; if (shiftOperation == true) { instructionIndex = 0; operandIndex = 1; shiftAmountIndex = 2; } else { //If there are 2 fields, the first must be the instruction and the second the operand //int labelIndex = fields.Length > 2 ? 0 : -1; instructionIndex = fields.Length > 2 ? 1 : 0; operandIndex = fields.Length > 2 ? 2 : 1; } //Store the label if present if ((fields.Length > 2) && (shiftOperation == false)) { _label = fields[0]; } //Instruction field contains instruction, condition code and set flags, or variable type bool foundInstruction = false; Array opArray = Enum.GetValues(typeof(ARMInstruction)); foreach (ARMInstruction op in opArray) { if (fields[instructionIndex].StartsWith(op.ToString())) { _type = SourceLineType.CODE; _instruction = op; foundInstruction = true; break; } } if (foundInstruction) { int instrLength = _instruction.ToString().Length; int codeLength = fields[instructionIndex].Length - instrLength; switch (codeLength) { case 0: { //No Condition or set flags directive _code = ConditionCode.AL; _setFlags = false; break; } case 1: { //Must be Set Flags directive only if (fields[instructionIndex][instrLength + 1] == 'S') { _setFlags = true; } else { //Single character should only be S - all condition codes are two characters _setFlags = false; return(false); } _code = ConditionCode.AL; break; } case 2: { //Must be a condition code only string codeString = fields[instructionIndex].Substring(instrLength, 2); Array ccArray = Enum.GetValues(typeof(ConditionCode)); foreach (ConditionCode cc in ccArray) { if (codeString.Equals(cc.ToString())) { _code = cc; break; } } _setFlags = false; break; } case 3: { //Must be a condition code then set flags string codeString = fields[instructionIndex].Substring(instrLength, 2); Array ccArray = Enum.GetValues(typeof(ConditionCode)); foreach (ConditionCode cc in ccArray) { if (codeString.Equals(cc.ToString())) { _code = cc; break; } } if (fields[instructionIndex][instrLength + 2] == 'S') { _setFlags = true; } else { //Character following condition code must only be S _setFlags = false; return(false); } break; } default: { //Invalid characters following instruction _setFlags = false; return(false); } } } else { //Not directive, label or instruction. Should be a variable definition. Array vtArray = Enum.GetValues(typeof(VariableType)); foreach (VariableType vt in vtArray) { if (fields[instructionIndex].Equals(vt.ToString())) { _type = SourceLineType.VARIABLE; _instruction = ARMInstruction.NOP; _code = ConditionCode.AL; _setFlags = false; } } } //Final field contains operands, split by commas string[] operands = fields[operandIndex].Split(new char[] { ',' }); //For a variable definition, store first operand only for now if (_type == SourceLineType.VARIABLE) { //Variable definitions typically have one operand, but some may have two to //perform operations with 64bit numbers //The type of the value to be assigned to the variable System.Globalization.NumberStyles type = System.Globalization.NumberStyles.HexNumber; string tempVar = operands[0]; if (tempVar[0] == '&') { type = System.Globalization.NumberStyles.HexNumber; tempVar = tempVar.Remove(0, 1); } else if (tempVar[0] == '#') { type = System.Globalization.NumberStyles.Number; tempVar = tempVar.Remove(0, 1); } else if (tempVar.StartsWith("0x")) { type = System.Globalization.NumberStyles.HexNumber; tempVar = tempVar.Remove(0, 2); } else { type = System.Globalization.NumberStyles.Number; } //temp now contains only a value, hex or decimal _variable = UInt32.Parse(tempVar, type); //Call the manager to add this to the memory representation Manager.GetInstance().AddData(_label, _variable); } else { //Operands are for an instruction //SWI &11 Op1 if (operands.Length == 1) { //Also check for B, BL offset values if (_instruction == ARMInstruction.SWI) { string val = operands[0]; //Remove '&' _Op1 = val.Remove(0, 1); } if (_instruction == ARMInstruction.B) { //store label to branch to if condition met _Op1 = operands[0]; } } else if (operands.Length == 2) { if (_instruction == ARMInstruction.CMP) { string val = operands[0]; //Remove 'R' val = val.Remove(0, 1); _Rn = Int32.Parse(val, System.Globalization.NumberStyles.Number); } else { //First operand is always Rd (destination register) string val = operands[0]; //Remove 'R' val = val.Remove(0, 1); _Rd = Int32.Parse(val, System.Globalization.NumberStyles.Number); } //Second operand will be stored in Op1 or Op2 //LDR R1,Value1 Rd, Op2 //LDR R2,Value1 Rd, Op2 //STR R1,Result Rd, Op2 if (_instruction == ARMInstruction.LDR || _instruction == ARMInstruction.STR) { //Store label for op2 _Op2 = operands[1]; } //MOV R1, R1 Rd, Op1 (register) //MOV R1, #1234 Rd, Op1 (immediate) //MVN R1, R1 Rd, Op1 (register) //CMP R1, R2 Rn, Op1 (register) else { //Need to store indication of register or immediate for analysis at run-time _Op1 = operands[1]; } } else { //First operand is always Rd (destination register) string val = operands[0]; //Remove 'R' val = val.Remove(0, 1); _Rd = Int32.Parse(val, System.Globalization.NumberStyles.Number); //ADD R1,R1,R2 Rd, Rn, Op1 if (_instruction == ARMInstruction.ADD) { string rnVal = operands[1]; rnVal = rnVal.Remove(0, 1); _Rn = Int32.Parse(rnVal, System.Globalization.NumberStyles.Number); //Need to store indication of register or immediate for analysis at run-time _Op1 = operands[2]; } //MOV R1,R1,LSL #0x1 Rd,Op1 //MOV R1,R1,LSL R2 Rd,Op1 //Shift by amount in R2 if (_instruction == ARMInstruction.MOV) { //MOV with 3 operands - must be a shift //shift op1 by the method in op2 by the amount in field[shiftIndex] _shift = true; //Destination Always a register - remove R indicator //Register contains the number that we want to shift string shiftRegVal = operands[1]; shiftRegVal = shiftRegVal.Remove(0, 1); _shiftRegister = Int32.Parse(shiftRegVal, System.Globalization.NumberStyles.Number); //Operand 2 contains the type of shift _shiftType = (ShiftCommand)Enum.Parse(typeof(ShiftCommand), operands[2]); //Shift amount immediate (&,# or register?) System.Globalization.NumberStyles type = System.Globalization.NumberStyles.HexNumber; string tempVar = fields[shiftAmountIndex]; if (tempVar[0] == '&') { type = System.Globalization.NumberStyles.HexNumber; tempVar = tempVar.Remove(0, 1); } else if (tempVar[0] == '#') { if (fields[shiftAmountIndex].StartsWith("#0x")) { type = System.Globalization.NumberStyles.HexNumber; tempVar = tempVar.Remove(0, 3); } else { type = System.Globalization.NumberStyles.Number; tempVar = tempVar.Remove(0, 1); } } else { type = System.Globalization.NumberStyles.Number; } //temp now contains only a value, hex or decimal _shiftAmount = Int32.Parse(tempVar, type); //Store shifter operand - if register then we use this value, otherwise use immediate value //stored in shiftAmount _Op1 = fields[shiftAmountIndex]; } //Need special case for SWP - uses Rm, Rd, Rn... } } return(true); }