1 //===-- OptionGroupFormat.cpp -----------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/Interpreter/OptionGroupFormat.h" 11 12 // C Includes 13 // C++ Includes 14 // Other libraries and framework includes 15 // Project includes 16 #include "lldb/Utility/Utils.h" 17 18 using namespace lldb; 19 using namespace lldb_private; 20 21 OptionGroupFormat::OptionGroupFormat (lldb::Format default_format, 22 uint64_t default_byte_size, 23 uint64_t default_count) : 24 m_format (default_format, default_format), 25 m_byte_size (default_byte_size, default_byte_size), 26 m_count (default_count, default_count), 27 m_prev_gdb_format('x'), 28 m_prev_gdb_size('w') 29 { 30 } 31 32 OptionGroupFormat::~OptionGroupFormat () 33 { 34 } 35 36 static OptionDefinition 37 g_option_table[] = 38 { 39 { LLDB_OPT_SET_1, false, "format" ,'f', required_argument, NULL, 0, eArgTypeFormat , "Specify a format to be used for display."}, 40 { LLDB_OPT_SET_2, false, "gdb-format",'G', required_argument, NULL, 0, eArgTypeGDBFormat, "Specify a format using a GDB format specifier string."}, 41 { LLDB_OPT_SET_3, false, "size" ,'s', required_argument, NULL, 0, eArgTypeByteSize , "The size in bytes to use when displaying with the selected format."}, 42 { LLDB_OPT_SET_4, false, "count" ,'c', required_argument, NULL, 0, eArgTypeCount , "The number of total items to display."}, 43 }; 44 45 uint32_t 46 OptionGroupFormat::GetNumDefinitions () 47 { 48 if (m_byte_size.GetDefaultValue() < UINT64_MAX) 49 { 50 if (m_count.GetDefaultValue() < UINT64_MAX) 51 return 4; 52 else 53 return 3; 54 } 55 return 2; 56 } 57 58 const OptionDefinition * 59 OptionGroupFormat::GetDefinitions () 60 { 61 return g_option_table; 62 } 63 64 Error 65 OptionGroupFormat::SetOptionValue (CommandInterpreter &interpreter, 66 uint32_t option_idx, 67 const char *option_arg) 68 { 69 Error error; 70 char short_option = (char) g_option_table[option_idx].short_option; 71 72 switch (short_option) 73 { 74 case 'f': 75 error = m_format.SetValueFromCString (option_arg); 76 break; 77 78 case 'c': 79 if (m_count.GetDefaultValue() == 0) 80 { 81 error.SetErrorString ("--count option is disabled"); 82 } 83 else 84 { 85 error = m_count.SetValueFromCString (option_arg); 86 if (m_count.GetCurrentValue() == 0) 87 error.SetErrorStringWithFormat("invalid --count option value '%s'", option_arg); 88 } 89 break; 90 91 case 's': 92 if (m_byte_size.GetDefaultValue() == 0) 93 { 94 error.SetErrorString ("--size option is disabled"); 95 } 96 else 97 { 98 error = m_byte_size.SetValueFromCString (option_arg); 99 if (m_byte_size.GetCurrentValue() == 0) 100 error.SetErrorStringWithFormat("invalid --size option value '%s'", option_arg); 101 } 102 break; 103 104 case 'G': 105 { 106 char *end = NULL; 107 const char *gdb_format_cstr = option_arg; 108 uint64_t count = 0; 109 if (::isdigit (gdb_format_cstr[0])) 110 { 111 count = strtoull (gdb_format_cstr, &end, 0); 112 113 if (option_arg != end) 114 gdb_format_cstr = end; // We have a valid count, advance the string position 115 else 116 count = 0; 117 } 118 119 Format format = eFormatDefault; 120 uint32_t byte_size = 0; 121 122 while (ParserGDBFormatLetter (gdb_format_cstr[0], format, byte_size)) 123 { 124 ++gdb_format_cstr; 125 } 126 127 // We the first character of the "gdb_format_cstr" is not the 128 // NULL terminator, we didn't consume the entire string and 129 // something is wrong. Also, if none of the format, size or count 130 // was specified correctly, then abort. 131 if (gdb_format_cstr[0] || (format == eFormatInvalid && byte_size == 0 && count == 0)) 132 { 133 // Nothing got set correctly 134 error.SetErrorStringWithFormat ("invalid gdb format string '%s'", option_arg); 135 return error; 136 } 137 138 // At least one of the format, size or count was set correctly. 139 // Anything that wasn't set correctly should be set to the 140 // previous default 141 if (format == eFormatInvalid) 142 ParserGDBFormatLetter (m_prev_gdb_format, format, byte_size); 143 144 const bool byte_size_enabled = m_byte_size.GetDefaultValue() < UINT64_MAX; 145 const bool count_enabled = m_count.GetDefaultValue() < UINT64_MAX; 146 if (byte_size_enabled) 147 { 148 // Byte size is enabled 149 if (byte_size == 0) 150 ParserGDBFormatLetter (m_prev_gdb_size, format, byte_size); 151 } 152 else 153 { 154 // Byte size is disabled, make sure it wasn't specified 155 if (byte_size > 0) 156 { 157 error.SetErrorString ("this command doesn't support specifying a byte size"); 158 return error; 159 } 160 } 161 162 if (count_enabled) 163 { 164 // Count is enabled and was not set, set it to the default for gdb format statements (which is 1). 165 if (count == 0) 166 count = 1; 167 } 168 else 169 { 170 // Count is disabled, make sure it wasn't specified 171 if (count > 0) 172 { 173 error.SetErrorString ("this command doesn't support specifying a count"); 174 return error; 175 } 176 } 177 178 m_format.SetCurrentValue (format); 179 m_format.SetOptionWasSet (); 180 if (byte_size_enabled) 181 { 182 m_byte_size.SetCurrentValue (byte_size); 183 m_byte_size.SetOptionWasSet (); 184 } 185 if (count_enabled) 186 { 187 m_count.SetCurrentValue(count); 188 m_count.SetOptionWasSet (); 189 } 190 } 191 break; 192 193 default: 194 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 195 break; 196 } 197 198 return error; 199 } 200 201 bool 202 OptionGroupFormat::ParserGDBFormatLetter (char format_letter, Format &format, uint32_t &byte_size) 203 { 204 switch (format_letter) 205 { 206 case 'o': format = eFormatOctal; m_prev_gdb_format = format_letter; return true; 207 case 'x': format = eFormatHex; m_prev_gdb_format = format_letter; return true; 208 case 'd': format = eFormatDecimal; m_prev_gdb_format = format_letter; return true; 209 case 'u': format = eFormatUnsigned; m_prev_gdb_format = format_letter; return true; 210 case 't': format = eFormatBinary; m_prev_gdb_format = format_letter; return true; 211 case 'f': format = eFormatFloat; m_prev_gdb_format = format_letter; return true; 212 case 'a': format = eFormatAddressInfo; m_prev_gdb_format = format_letter; return true; 213 case 'i': format = eFormatInstruction; m_prev_gdb_format = format_letter; return true; 214 case 'c': format = eFormatChar; m_prev_gdb_format = format_letter; return true; 215 case 's': format = eFormatCString; m_prev_gdb_format = format_letter; return true; 216 case 'T': format = eFormatOSType; m_prev_gdb_format = format_letter; return true; 217 case 'A': format = eFormatHexFloat; m_prev_gdb_format = format_letter; return true; 218 case 'b': byte_size = 1; m_prev_gdb_size = format_letter; return true; 219 case 'h': byte_size = 2; m_prev_gdb_size = format_letter; return true; 220 case 'w': byte_size = 4; m_prev_gdb_size = format_letter; return true; 221 case 'g': byte_size = 8; m_prev_gdb_size = format_letter; return true; 222 default: break; 223 } 224 return false; 225 } 226 227 void 228 OptionGroupFormat::OptionParsingStarting (CommandInterpreter &interpreter) 229 { 230 m_format.Clear(); 231 m_byte_size.Clear(); 232 m_count.Clear(); 233 } 234