├── LICENSE.md ├── binmark_tool.py └── binmark.py /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright © 2016 Nicholas Humfrey 5 | 6 | Permission is hereby granted, free of charge, to any person 7 | obtaining a copy of this software and associated documentation 8 | files (the “Software”), to deal in the Software without 9 | restriction, including without limitation the rights to use, 10 | copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the 12 | Software is furnished to do so, subject to the following 13 | conditions: 14 | 15 | The above copyright notice and this permission notice shall be 16 | included in all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | OTHER DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /binmark_tool.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import binmark 4 | import getopt 5 | import sys 6 | 7 | MODE_BINARY = 0 8 | MODE_C = 1 9 | MODE_HEXSTREAM = 2 10 | 11 | def write_hex(c, output_file): 12 | val = "%2.2x" % c 13 | output_file.write(val.encode()) 14 | 15 | def write_raw(c, output_file): 16 | output_file.write(c) 17 | 18 | def usage(): 19 | print("Usage: binmark_tool.py [options] file...") 20 | print("Options") 21 | print(" -b Binary output format (default)") 22 | print(" -x Hexadecimal text stream") 23 | exit(-1) 24 | 25 | 26 | def main(): 27 | mode = MODE_BINARY 28 | 29 | # Parse Switches 30 | opts, args = getopt.getopt(sys.argv[1:], 'bcx') 31 | for o, a in opts: 32 | if o == '-b': 33 | mode = MODE_BINARY 34 | elif o == '-x': 35 | mode = MODE_HEXSTREAM 36 | else: 37 | usage() 38 | 39 | if len(sys.argv) < 1: 40 | print("No filename given") 41 | usage() 42 | 43 | with open(sys.argv[1+len(opts)], "rb") as f: 44 | input_buffer = f.read() 45 | 46 | output_buffer = binmark.binmark_to_binary(input_buffer) 47 | 48 | if mode == MODE_BINARY: 49 | sys.stdout.buffer.write(output_buffer) 50 | 51 | elif mode == MODE_HEXSTREAM: 52 | for val in output_buffer: 53 | write_hex(val, sys.stdout.buffer) 54 | 55 | return 0 56 | 57 | main() 58 | -------------------------------------------------------------------------------- /binmark.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import struct 4 | 5 | def isxdigit(c): 6 | return c in [b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'a', b'b', b'c', b'd', b'e', b'f', b'A', b'B', b'C', b'D', b'E', b'F'] 7 | 8 | def ascii_to_hex(c): 9 | if c == b'0': return 0 10 | elif c == b'1': return 1 11 | elif c == b'2': return 2 12 | elif c == b'3': return 3 13 | elif c == b'4': return 4 14 | elif c == b'5': return 5 15 | elif c == b'6': return 6 16 | elif c == b'7': return 7 17 | elif c == b'8': return 8 18 | elif c == b'9': return 9 19 | elif c == b'a' or c == b'A': return 10 20 | elif c == b'b' or c == b'B': return 11 21 | elif c == b'c' or c == b'C': return 12 22 | elif c == b'd' or c == b'D': return 13 23 | elif c == b'e' or c == b'E': return 14 24 | elif c == b'f' or c == b'F': return 15 25 | else: return -1 26 | 27 | # Based on: https://en.wikipedia.org/wiki/Escape_sequences_in_C 28 | def escape_to_hex(c): 29 | if c == b'0': return 0x00 30 | elif c == b'a': return 0x07 31 | elif c == b'b': return 0x08 32 | elif c == b'f': return 0x0C 33 | elif c == b'n': return 0x0A 34 | elif c == b'r': return 0x0D 35 | elif c == b't': return 0x09 36 | elif c == b'v': return 0x0B 37 | elif c == b'\\': return 0x5C 38 | elif c == b'\'': return 0x27 39 | elif c == b'"': return 0x22 40 | elif c == b'?': return 0x3F 41 | else: return -1 42 | 43 | def binmark_to_binary(input_buffer): 44 | output_buffer = bytearray(b"") 45 | 46 | i = 0 47 | while i < len(input_buffer): 48 | char = struct.pack("B", input_buffer[i]) 49 | i += 1 50 | 51 | if char.isspace() or char == b':' or char == b'-': 52 | # Ignore 53 | continue 54 | 55 | elif char == b'#': 56 | # Ignore the rest of the line 57 | while True: 58 | char2 = struct.pack("B", input_buffer[i]) 59 | i += 1 60 | if char2 == b'' or char2 == b'\n' or char2 == b'\r': 61 | break 62 | 63 | elif isxdigit(char): 64 | char2 = struct.pack("B", input_buffer[i]) 65 | i += 1 66 | if not isxdigit(char2): 67 | raise ValueError(f"Got non-hex digit after hex digit: '{char2}'") 68 | 69 | val = (ascii_to_hex(char) << 4) + ascii_to_hex(char2) 70 | output_buffer += struct.pack("B", val) 71 | 72 | elif char == b'.': 73 | # 8-bit Integer 74 | chars = b"" 75 | 76 | while len(chars) < 4: 77 | char2 = struct.pack("B", input_buffer[i]) 78 | i += 1 79 | if char2.isdigit() or char2 == b'-': 80 | chars += char2 81 | else: 82 | i -= 1 83 | break 84 | 85 | if len(chars) < 1 or len(chars) > 4: 86 | raise ValueError(f"Invalid integer {chars}") 87 | else: 88 | num = int(chars) & 0xFF 89 | output_buffer += struct.pack("B", num) 90 | 91 | elif char == b'"': 92 | while True: 93 | char2 = struct.pack("B", input_buffer[i]) 94 | i += 1 95 | if char2 == b'' or char2 == char: 96 | break 97 | elif char2 == b'\\': 98 | char3 = struct.pack("B", input_buffer[i]) 99 | i += 1 100 | escaped = escape_to_hex(char3) 101 | if escaped < 0: 102 | raise ValueError(f"Invalid escape sequence '{char3}'") 103 | else: 104 | output_buffer += struct.pack("B", escaped) 105 | else: 106 | output_buffer += char2 107 | 108 | elif char == b'\\': 109 | char2 = struct.pack("B", input_buffer[i]) 110 | i += 1 111 | if char2 == b'': 112 | break 113 | else: 114 | escaped = escape_to_hex(char2) 115 | if escaped < 0: 116 | raise ValueError(f"Invalid escape sequence '{char2}'") 117 | else: 118 | output_buffer += struct.pack("B", escaped) 119 | 120 | else: 121 | raise ValueError(f"Unrecognised character in input: '{char}'") 122 | 123 | return output_buffer 124 | --------------------------------------------------------------------------------