/// <summary> /// Get a linenumber /// </summary> /// <param name="PCode">Source bytes</param> /// <param name="offset">position</param> /// <returns></returns> private static string GetLineNumber(byte[] PCode, ref int offset) { string result = ""; offset++; //1 byte = TOKEN {1} short LineNumber = BytesExtensions.ToInt16(PCode, ref offset); result += LineNumber.ToString(); //LINE NUMBER, 2 Bytes //Populate a list of offsets of every linenumbers JumpLines.Add(new EditorJumpInfo(JumpType.GOTO, (int)LineNumber, offset - 3)); return(result); }
/// <summary> /// Decode a ProgramCode Into Plain Text /// </summary> /// <param name="PCode">Byte array (encoded program)</param> static public string DecodeBytes(byte[] PCode) { byte[] prgsize = new byte[2]; string result = ""; Array.Copy(PCode, 0, prgsize, 0, 2); int ProgLenght = BytesExtensions.ToInt16(prgsize); int offset; //offset after count of total encoded bytes bool isFirstToken = true; offset = 2; while (offset <= ProgLenght) { var tokenvalue = (byte)PCode[offset]; switch (tokenvalue) { //linenumbers case (byte)TYPE_TOKEN.NUMBER: if (isFirstToken) { offset++; short LineNumber = BytesExtensions.ToInt16(PCode, ref offset); result += LineNumber.ToString(); //LINE NUMBER, 2 Bytes } isFirstToken = false; break; //comments case (byte)LINE_TOKEN.REM: result += " " + GetComment(PCode, ref offset) + System.Environment.NewLine; isFirstToken = true; break; //assigments case (byte)LINE_TOKEN.ASSIGN: result += " " + GetAssigment(PCode, ref offset) + System.Environment.NewLine; isFirstToken = true; break; default: offset++; //TODO: This line only for debugging purposes break; } } return(result); }
/// <summary> /// Decode a ProgramCode Into Plain Text /// </summary> /// <param name="PCode">Byte array (encoded program)</param> static public string DecodeBytes(byte[] PCode, int Start = 0, int End = 0) { byte[] prgsize = new byte[2]; string result = ""; Array.Copy(PCode, 0, prgsize, 0, 2); //2 bytes more for total bytes count. int ProgLenght = BytesExtensions.ToInt16(prgsize) + 2; //If defined, END for THEN or ELSE if (End != 0) { ProgLenght = End; } Stack <int> offsets = new Stack <int>(); int offset = 0; //offset after count of total encoded bytes bool isFirstToken = true; //default values for first decoding if (Start != 0) { offset = Start; isFirstToken = false; } else //normal start for offset { offset = 2; } while (offset <= ProgLenght) { var tokenvalue = (byte)PCode[offset]; switch (tokenvalue) { //linenumbers case (byte)TYPE_TOKEN.NUMBER: if (isFirstToken) { string strLineNum = GetLineNumber(PCode, ref offset); result += strLineNum; } else { offset += 2; } //next token is not the first, 4 sure isFirstToken = false; break; //comments case (byte)LINE_TOKEN.REM: result += " " + GetComment(PCode, ref offset) + System.Environment.NewLine; isFirstToken = true; break; #region ASSIGMENTS case (byte)LINE_TOKEN.LET: result += " LET"; offset++; if (PCode[offset] != (byte)LINE_TOKEN.ASSIGN) { throw new Exception("Fatal Error: Next token after (deprecated) LET, is not an ASSIGMENT"); } isFirstToken = false; break; case (byte)LINE_TOKEN.ASSIGN: result += " " + GetAssigment(PCode, ref offset) + System.Environment.NewLine; isFirstToken = true; break; #endregion //TODO: LRUIZ :::: Continue here with COMMANDS #region Single byte commands case (byte)LINE_TOKEN.CLEAR: result += " " + "CLEAR" + System.Environment.NewLine; offset++; isFirstToken = true; break; case (byte)LINE_TOKEN.HANGUP: result += " " + "HANGUP" + System.Environment.NewLine; offset++; isFirstToken = true; break; case (byte)LINE_TOKEN.RETURN: result += " " + "RETURN" + System.Environment.NewLine; offset++; isFirstToken = true; break; case (byte)LINE_TOKEN.ENDPRG: result += " " + "END" + System.Environment.NewLine; offset++; isFirstToken = true; break; #endregion #region 2+ bytes commands case (byte)LINE_TOKEN.START: result += " " + "START "; offset++; result += GetIdentifierLabel(PCode, ref offset) + System.Environment.NewLine; isFirstToken = true; break; case (byte)LINE_TOKEN.STOP: result += " " + "STOP "; offset++; result += GetIdentifierLabel(PCode, ref offset) + System.Environment.NewLine; isFirstToken = true; break; case (byte)LINE_TOKEN.OPEN: result += " " + "OPEN "; offset++; result += GetIdentifierLabel(PCode, ref offset) + System.Environment.NewLine; isFirstToken = true; break; case (byte)LINE_TOKEN.CLOSE: result += " " + "CLOSE "; offset++; result += GetIdentifierLabel(PCode, ref offset) + System.Environment.NewLine; isFirstToken = true; break; case (byte)LINE_TOKEN.ENABLEX: result += " " + "ENABLE "; offset++; result += GetIdentifierLabel(PCode, ref offset) + System.Environment.NewLine; isFirstToken = true; break; case (byte)LINE_TOKEN.DISABLEX: result += " " + "DISABLE "; offset++; result += GetIdentifierLabel(PCode, ref offset) + System.Environment.NewLine; isFirstToken = true; break; #endregion #region IF THEN ELSE case (byte)LINE_TOKEN.IF: case (byte)LINE_TOKEN.IFP: case (byte)LINE_TOKEN.IFM: switch (PCode[offset]) { case (byte)LINE_TOKEN.IF: result += " " + "IF "; break; case (byte)LINE_TOKEN.IFP: result += " " + "IF+ "; break; case (byte)LINE_TOKEN.IFM: result += " " + "IF- "; break; } offset++; result += GetExpression(PCode, ref offset); isFirstToken = false; result += " THEN "; offset++; //THEN is always followed by two bytes byte[] thenoffset = { 0x00, 0x00 }; thenoffset[0] = PCode[offset]; thenoffset[1] = PCode[offset + 1]; offset += 2; int newOffset = (int)(thenoffset[0] - 4); result += RemoveCRLF(GetThenPart(PCode, ref offset, newOffset)); break; case (byte)LINE_TOKEN.EOE: //ELSE if (PCode[offset + 1] == (byte)LINE_TOKEN.ELSE && PCode[offset + 2] == (byte)LINE_TOKEN.EOE) { offset += 2; byte[] elseoffset = { 0x00, 0x00 }; elseoffset[0] = PCode[offset]; elseoffset[1] = PCode[offset + 1]; offset += 2; int newElseOffset = (int)(elseoffset[0] - 4); result += " ELSE " + GetElsePart(PCode, ref offset, newElseOffset); isFirstToken = true; } else { offset++; if (PCode[offset] != (byte)LINE_TOKEN.EOF) { result += System.Environment.NewLine; } } break; #endregion #region JUMPS case (byte)LINE_TOKEN.GOTO: result += " " + "GOTO "; offset++; int copyoffset = (int)PCode[offset]; //TODO: Don't know what happens when offset of JumpLine is higher than 255 //What about the second byte??? string gotoLine = GetLineNumber(PCode, ref copyoffset); offset += 2; //2 bytes result += gotoLine + System.Environment.NewLine; isFirstToken = true; break; case (byte)LINE_TOKEN.GOSUB: result += " " + "GOSUB "; offset++; int copyoffset2 = (int)PCode[offset]; //TODO: Don't know what happens when offset of JumpLine is higher than 255 //What about the second byte??? string gotoLine2 = GetLineNumber(PCode, ref copyoffset2); offset += 2; //2 bytes result += gotoLine2 + System.Environment.NewLine; isFirstToken = true; break; case (byte)LINE_TOKEN.ON_ALARM: result += " " + "ON-ALARM "; offset++; int copyoffset3 = (int)PCode[offset]; //TODO: Don't know what happens when offset of JumpLine is higher than 255 //What about the second byte??? string gotoLine3 = GetLineNumber(PCode, ref copyoffset3); offset += 2; //2 bytes result += gotoLine3 + System.Environment.NewLine; isFirstToken = true; break; case (byte)LINE_TOKEN.ON_ERROR: result += " " + "ON-ERROR "; offset++; int copyoffset4 = (int)PCode[offset]; //TODO: Don't know what happens when offset of JumpLine is higher than 255 //What about the second byte??? string gotoLine4 = GetLineNumber(PCode, ref copyoffset4); offset += 2; //2 bytes result += gotoLine4 + System.Environment.NewLine; isFirstToken = true; break; case (byte)LINE_TOKEN.ON: result += " " + "ON "; offset++; result += GetExpression(PCode, ref offset) + " "; isFirstToken = false; break; #endregion case (byte)LINE_TOKEN.EOF: default: offset++; //TODO: This line only for debugging purposes, should be removed, when decoder finished break; } } return(result); }
/// <summary> /// TimeBuffer from source code (byte array) /// </summary> /// <param name="source"></param> public TimeBuffer(ControlPoints identifiers, byte[] source = null) { int i = 0; int POS = 0; byte[] len = { 0x00, 0x00 }; Identifiers = identifiers; if (source == null) { return; } try { if (source.Length > 2000) { throw new ArgumentOutOfRangeException($"Program Lenght exceeds 2000 bytes: {source.Length}"); } else { //find EOF byte, do not trust PROG SIZE in control point do { i++; }while (source[i] != (byte)LINE_TOKEN.EOF); if (i >= 2000) { throw new IndexOutOfRangeException($"Out of bounds or no EOF found at index: {i}"); } POS = i + 1; //Position of TimeBuffer -> first byte after 0xFE (EOF) i = POS + 4; //Jump first 4 bytes, those are always 0x00 //next two bytes are the buffer lenght len[0] = source[i]; len[1] = source[i + 1]; int _BufferSize = BytesExtensions.ToInt16(len); int _BufferCount = (BufferSize) / 9; //Copy the time buffer //If BufferSize = 0 then Buffer will stay empty for (i = 0; i <= _BufferSize + 5; i++) { Buffer.Add(source[POS + i]); } //Convert every byte sequence into Elements for (i = 6; i < _BufferSize + 5; i += 9) { //skip first byte 0x00; byte TOKEN = Buffer[i]; byte INDEX = Buffer[i + 1]; IdentifierTypes TYPE = (IdentifierTypes)Buffer[i + 2]; byte Marker = Buffer[i + 3]; if (Marker != (byte)LINE_TOKEN.EOE) { throw new Exception($"EOF not found. Instead of marker, I found this: {Marker}"); } if (Identifiers != null) { switch ((IdentifierTypes)TYPE) { case IdentifierTypes.OUTS: case IdentifierTypes.INS: case IdentifierTypes.VARS: Add(Identifiers.GetControlPointInfo(TYPE, INDEX)); break; default: throw new NotSupportedException("Identifier type not supported by TimeBuffer()"); } } } } } catch (Exception ex) { ExceptionHandler.Show(ex, "TimeBuffer"); } }