def _parse_key(to_parse): """Parse key, value combination return (tuple): Number of characters parsed from to_parse Parsed key (string) """ if _DEBUG: print_red('key') print_red(to_parse) buf = '' i = 0 key = '' while i < len(to_parse) - 1: c = to_parse[i] if c == '=': key = buf # consume '=' sign so caller doesn't get it again i += 1 break buf += c i += 1 if _DEBUG: print_green(key) return i, key
def _parse_dict(to_parse): """Parse dictionary, with optional starting character '{' return (tuple): Number of characters parsed from to_parse Parsed dictionary """ if _DEBUG: print_red('obj') print_red(to_parse) i = 0 obj = {} while i < len(to_parse): c = to_parse[i] if c in _WHITESPACE: pass elif c in ['{', ',']: pass elif c == '}': # end of object, exit loop break else: chars_used, key, val = _parse_key_val(to_parse[i:]) i = i + chars_used obj[key] = val i += 1 if _DEBUG: print_green(obj) return i, obj
def _parse_array(stream): """Parse an array, stream should be passed the initial [ returns: Parsed array """ if _DEBUG: print_green('parsing array') arr = [] while True: c = stream.read(1) if c in _GDB_MI_VALUE_START_CHARS: stream.seek(-1) val = _parse_val(stream) arr.append(val) elif c in _WHITESPACE: pass elif c == ',': pass elif c == ']': # Stop when this array has finished. Note # that elements of this array can be also be arrays. break if _DEBUG: print('parsed array:') print_green(arr) return arr
def _get_notify_msg_and_payload(result, stream): """Get notify message and payload dict""" token = stream.advance_past_chars(['=', '*']) token = int(token) if token != '' else None if _DEBUG: print_green('parsing message') message = stream.advance_past_chars([',']) if _DEBUG: print('parsed message') print_green(message) payload = _parse_dict(stream) return token, message.strip(), payload
def _parse_str(to_parse): """Parse a string return (tuple): Number of characters parsed from to_parse Parsed string, without surrounding quotes """ # characters that gdb escapes that should not be # escaped by this parser CHARS_TO_REMOVE_GDB_ESCAPE = ['"'] if _DEBUG: print_red('string') print_red(to_parse) assert_match(_GDB_MI_CHAR_STRING_START, to_parse[0]) i = 1 # Skip the opening quote buf = '' while i < len(to_parse) - 1: c = to_parse[i] if _DEBUG: print_cyan(c) if c == '\\' and i < (len(to_parse) - 1): # We are on a backslash and there is another character after the backslash # to parse. Handle this case specially since gdb escaped it for us # Get the next char that is being escaped c2 = to_parse[i + 1] if c2 in CHARS_TO_REMOVE_GDB_ESCAPE: # only store the escaped character in the buffer; don't store the backslash # (don't leave it escaped) buf += to_parse[i + 1] else: # store the backslash and the following character in the buffer (leave it escaped) buf += c + to_parse[i + 1] # consume the backslash and the next character i += 2 else: # Quote is closed. Exit (and don't include the end quote). if c == '"': break buf += c i += 1 string = buf if _DEBUG: print_green(string) return i, string
def _parse_dict(to_parse): """Parse dictionary, with optional starting character '{' return (tuple): Number of characters parsed from to_parse Parsed dictionary """ if _DEBUG: print_red('obj') print_red(to_parse) i = 0 obj = {} while i < len(to_parse): c = to_parse[i] if c in _WHITESPACE: pass elif c in ['{', ',']: pass elif c == '}': # end of object, exit loop break else: chars_used, key, val = _parse_key_val(to_parse[i:]) i = i + chars_used if key in obj: # This is a gdb bug. We should never get repeated keys in a dict! # See https://sourceware.org/bugzilla/show_bug.cgi?id=22217 # and https://github.com/cs01/pygdbmi/issues/19 # Example: # thread-ids={thread-id="1",thread-id="2"} # Results in: # thread-ids: {{'thread-id': ['1', '2']}} # Rather than the lossy # thread-ids: {'thread-id': 2} # '1' got overwritten! if isinstance(obj[key], list): obj[key].append(val) else: obj[key] = [obj[key], val] else: obj[key] = val i += 1 if _DEBUG: print_green(obj) return i, obj
def _parse_key_val(to_parse): """Parse key, value combination return (tuple): Number of characters parsed from to_parse Parsed key (string) Parsed value (either a string, array, or dict) """ if _DEBUG: print_red('keyval') print_red(to_parse) i = 0 size, key = _parse_key(to_parse[i:]) i += size size, val = _parse_val(to_parse[i:]) i += size if _DEBUG: print_green(key) print_green(val) return i, key, val
def _parse_val(to_parse): """Parse value from string return (tuple): Number of characters parsed from to_parse Parsed value (either a string, array, or dict) """ if _DEBUG: print_red('val') print_red(to_parse) i = 0 val = '' buf = '' while i < len(to_parse) - 1: c = to_parse[i] if c == '{': # Start object size, val = _parse_dict(to_parse[i:]) i += size break elif c == '[': # Start of an array size, val = _parse_array(to_parse[i:]) i += size break elif c == '"': # Start of a string size, val = _parse_str(to_parse[i:]) i += size break else: buf += c i += 1 if _DEBUG: print_green(val) return i, val
def _parse_dict(stream): """Parse dictionary, with optional starting character '{' return (tuple): Number of characters parsed from to_parse Parsed dictionary """ obj = {} if _DEBUG: print_green("parsing dict") while True: c = stream.read(1) if c in _WHITESPACE: pass elif c in ["{", ","]: pass elif c in ["}", ""]: # end of object, exit loop break else: stream.seek(-1) key, val = _parse_key_val(stream) if key in obj: # This is a gdb bug. We should never get repeated keys in a dict! # See https://sourceware.org/bugzilla/show_bug.cgi?id=22217 # and https://github.com/cs01/pygdbmi/issues/19 # Example: # thread-ids={thread-id="1",thread-id="2"} # Results in: # thread-ids: {{'thread-id': ['1', '2']}} # Rather than the lossy # thread-ids: {'thread-id': 2} # '1' got overwritten! if isinstance(obj[key], list): obj[key].append(val) else: obj[key] = [obj[key], val] else: obj[key] = val look_ahead_for_garbage = True c = stream.read(1) while look_ahead_for_garbage: if c in ["}", ",", ""]: look_ahead_for_garbage = False else: # got some garbage text, skip it. for example: # name="gdb"gargage # skip over 'garbage' # name="gdb"\n # skip over '\n' if _DEBUG: print("skipping unexpected charcter" + c) c = stream.read(1) stream.seek(-1) if _DEBUG: print_green("parsed dict") print_green(obj) return obj
def _parse_array(to_parse): """Parse an array return (tuple): Number of characters parsed from to_parse Parsed array """ if _DEBUG: print_red('array') print_red(to_parse) assert_match(_GDB_MI_CHAR_ARRAY_START, to_parse[0]) # Skip first open bracket so we don't end up in an # endless loop trying to re-parse the array i = 1 arr = [] while i < len(to_parse) - 1: c = to_parse[i] if c in _GDB_MI_VALUE_START_CHARS: size, val = _parse_val(to_parse[i:]) arr.append(val) i += size elif c in _WHITESPACE: pass elif c == ',': pass elif c == ']': # Stop when this array has finished. Note # that elements of this array can be also be arrays. break i += 1 if _DEBUG: print_green(arr) return i, arr
def _parse_key_val(stream): """Parse key, value combination return (tuple): Parsed key (string) Parsed value (either a string, array, or dict) """ if _DEBUG: print_green('parsing key/val') key = _parse_key(stream) val = _parse_val(stream) if _DEBUG: print_green('parsed key/val') print_green(key) print_green(val) return key, val
def _parse_key(stream): """Parse key, value combination returns : Parsed key (string) """ if _DEBUG: print_green('parsing key') key = stream.advance_past_chars(['=']) if _DEBUG: print_green('parsed key:') print_green(key) return key
def _parse_val(stream): """Parse value from string returns: Parsed value (either a string, array, or dict) """ if _DEBUG: print_green("parsing value") while True: c = stream.read(1) if c == "{": # Start object val = _parse_dict(stream) break elif c == "[": # Start of an array val = _parse_array(stream) break elif c == '"': # Start of a string val = stream.advance_past_string_with_gdb_escapes() break elif _DEBUG: raise ValueError("unexpected character: %s" % c) else: print( 'pygdbmi warning: encountered unexpected character: "%s". Continuing.' % c) val = "" # this will be overwritten if there are more characters to be read if _DEBUG: print_green("parsed value:") print_green(val) return val