GDB (API)
|
00001 /* Routines for handling XML generic OS data provided by target. 00002 00003 Copyright (C) 2008-2013 Free Software Foundation, Inc. 00004 00005 This file is part of GDB. 00006 00007 This program is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 3 of the License, or 00010 (at your option) any later version. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00019 00020 #include "defs.h" 00021 #include "target.h" 00022 #include "vec.h" 00023 #include "xml-support.h" 00024 #include "osdata.h" 00025 #include "gdb_string.h" 00026 #include "ui-out.h" 00027 #include "gdbcmd.h" 00028 00029 #if !defined(HAVE_LIBEXPAT) 00030 00031 struct osdata * 00032 osdata_parse (const char *xml) 00033 { 00034 static int have_warned; 00035 00036 if (!have_warned) 00037 { 00038 have_warned = 1; 00039 warning (_("Can not parse XML OS data; XML support was disabled " 00040 "at compile time")); 00041 } 00042 00043 return NULL; 00044 } 00045 00046 #else /* HAVE_LIBEXPAT */ 00047 00048 #include "xml-support.h" 00049 00050 /* Internal parsing data passed to all XML callbacks. */ 00051 struct osdata_parsing_data 00052 { 00053 struct osdata *osdata; 00054 char *property_name; 00055 }; 00056 00057 /* Handle the start of a <osdata> element. */ 00058 00059 static void 00060 osdata_start_osdata (struct gdb_xml_parser *parser, 00061 const struct gdb_xml_element *element, 00062 void *user_data, VEC(gdb_xml_value_s) *attributes) 00063 { 00064 struct osdata_parsing_data *data = user_data; 00065 char *type; 00066 struct osdata *osdata; 00067 00068 if (data->osdata) 00069 gdb_xml_error (parser, _("Seen more than on osdata element")); 00070 00071 type = xml_find_attribute (attributes, "type")->value; 00072 osdata = XZALLOC (struct osdata); 00073 osdata->type = xstrdup (type); 00074 data->osdata = osdata; 00075 } 00076 00077 /* Handle the start of a <item> element. */ 00078 00079 static void 00080 osdata_start_item (struct gdb_xml_parser *parser, 00081 const struct gdb_xml_element *element, 00082 void *user_data, VEC(gdb_xml_value_s) *attributes) 00083 { 00084 struct osdata_parsing_data *data = user_data; 00085 struct osdata_item item = { NULL }; 00086 00087 VEC_safe_push (osdata_item_s, data->osdata->items, &item); 00088 } 00089 00090 /* Handle the start of a <column> element. */ 00091 00092 static void 00093 osdata_start_column (struct gdb_xml_parser *parser, 00094 const struct gdb_xml_element *element, 00095 void *user_data, VEC(gdb_xml_value_s) *attributes) 00096 { 00097 struct osdata_parsing_data *data = user_data; 00098 const char *name = xml_find_attribute (attributes, "name")->value; 00099 00100 data->property_name = xstrdup (name); 00101 } 00102 00103 /* Handle the end of a <column> element. */ 00104 00105 static void 00106 osdata_end_column (struct gdb_xml_parser *parser, 00107 const struct gdb_xml_element *element, 00108 void *user_data, const char *body_text) 00109 { 00110 struct osdata_parsing_data *data = user_data; 00111 struct osdata *osdata = data->osdata; 00112 struct osdata_item *item = VEC_last (osdata_item_s, osdata->items); 00113 struct osdata_column *col = VEC_safe_push (osdata_column_s, 00114 item->columns, NULL); 00115 00116 /* Transfer memory ownership. NAME was already strdup'ed. */ 00117 col->name = data->property_name; 00118 col->value = xstrdup (body_text); 00119 data->property_name = NULL; 00120 } 00121 00122 /* Discard the constructed osdata (if an error occurs). */ 00123 00124 static void 00125 clear_parsing_data (void *p) 00126 { 00127 struct osdata_parsing_data *data = p; 00128 00129 osdata_free (data->osdata); 00130 data->osdata = NULL; 00131 xfree (data->property_name); 00132 data->property_name = NULL; 00133 } 00134 00135 /* The allowed elements and attributes for OS data object. 00136 The root element is a <osdata>. */ 00137 00138 const struct gdb_xml_attribute column_attributes[] = { 00139 { "name", GDB_XML_AF_NONE, NULL, NULL }, 00140 { NULL, GDB_XML_AF_NONE, NULL, NULL } 00141 }; 00142 00143 const struct gdb_xml_element item_children[] = { 00144 { "column", column_attributes, NULL, 00145 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL, 00146 osdata_start_column, osdata_end_column }, 00147 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } 00148 }; 00149 00150 const struct gdb_xml_attribute osdata_attributes[] = { 00151 { "type", GDB_XML_AF_NONE, NULL, NULL }, 00152 { NULL, GDB_XML_AF_NONE, NULL, NULL } 00153 }; 00154 00155 const struct gdb_xml_element osdata_children[] = { 00156 { "item", NULL, item_children, 00157 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL, 00158 osdata_start_item, NULL }, 00159 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } 00160 }; 00161 00162 const struct gdb_xml_element osdata_elements[] = { 00163 { "osdata", osdata_attributes, osdata_children, 00164 GDB_XML_EF_NONE, osdata_start_osdata, NULL }, 00165 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } 00166 }; 00167 00168 struct osdata * 00169 osdata_parse (const char *xml) 00170 { 00171 struct cleanup *back_to; 00172 struct osdata_parsing_data data = { NULL }; 00173 00174 back_to = make_cleanup (clear_parsing_data, &data); 00175 00176 if (gdb_xml_parse_quick (_("osdata"), "osdata.dtd", 00177 osdata_elements, xml, &data) == 0) 00178 { 00179 /* Parsed successfully, don't need to delete the result. */ 00180 discard_cleanups (back_to); 00181 return data.osdata; 00182 } 00183 00184 do_cleanups (back_to); 00185 return NULL; 00186 } 00187 #endif 00188 00189 static void 00190 osdata_item_clear (struct osdata_item *item) 00191 { 00192 if (item->columns != NULL) 00193 { 00194 struct osdata_column *col; 00195 int ix; 00196 00197 for (ix = 0; 00198 VEC_iterate (osdata_column_s, item->columns, 00199 ix, col); 00200 ix++) 00201 { 00202 xfree (col->name); 00203 xfree (col->value); 00204 } 00205 VEC_free (osdata_column_s, item->columns); 00206 item->columns = NULL; 00207 } 00208 } 00209 00210 void 00211 osdata_free (struct osdata *osdata) 00212 { 00213 if (osdata == NULL) 00214 return; 00215 00216 if (osdata->items != NULL) 00217 { 00218 struct osdata_item *item; 00219 int ix; 00220 00221 for (ix = 0; 00222 VEC_iterate (osdata_item_s, osdata->items, 00223 ix, item); 00224 ix++) 00225 osdata_item_clear (item); 00226 VEC_free (osdata_item_s, osdata->items); 00227 } 00228 00229 xfree (osdata); 00230 } 00231 00232 static void 00233 osdata_free_cleanup (void *arg) 00234 { 00235 struct osdata *osdata = arg; 00236 00237 osdata_free (osdata); 00238 } 00239 00240 struct cleanup * 00241 make_cleanup_osdata_free (struct osdata *data) 00242 { 00243 return make_cleanup (osdata_free_cleanup, data); 00244 } 00245 00246 struct osdata * 00247 get_osdata (const char *type) 00248 { 00249 struct osdata *osdata = NULL; 00250 char *xml = target_get_osdata (type); 00251 00252 if (xml) 00253 { 00254 struct cleanup *old_chain = make_cleanup (xfree, xml); 00255 00256 if (xml[0] == '\0') 00257 { 00258 if (type) 00259 warning (_("Empty data returned by target. Wrong osdata type?")); 00260 else 00261 warning (_("Empty type list returned by target. No type data?")); 00262 } 00263 else 00264 osdata = osdata_parse (xml); 00265 00266 do_cleanups (old_chain); 00267 } 00268 00269 if (!osdata) 00270 error (_("Can not fetch data now.")); 00271 00272 return osdata; 00273 } 00274 00275 const char * 00276 get_osdata_column (struct osdata_item *item, const char *name) 00277 { 00278 struct osdata_column *col; 00279 int ix_cols; 00280 00281 for (ix_cols = 0; 00282 VEC_iterate (osdata_column_s, item->columns, 00283 ix_cols, col); 00284 ix_cols++) 00285 if (strcmp (col->name, name) == 0) 00286 return col->value; 00287 00288 return NULL; 00289 } 00290 00291 void 00292 info_osdata_command (char *type, int from_tty) 00293 { 00294 struct ui_out *uiout = current_uiout; 00295 struct osdata *osdata = NULL; 00296 struct osdata_item *last = NULL; 00297 struct cleanup *old_chain; 00298 int ncols = 0; 00299 int nrows; 00300 int col_to_skip = -1; 00301 00302 osdata = get_osdata (type); 00303 old_chain = make_cleanup_osdata_free (osdata); 00304 00305 nrows = VEC_length (osdata_item_s, osdata->items); 00306 00307 if (!type && nrows == 0) 00308 error (_("Available types of OS data not reported.")); 00309 00310 if (!VEC_empty (osdata_item_s, osdata->items)) 00311 { 00312 last = VEC_last (osdata_item_s, osdata->items); 00313 if (last->columns) 00314 ncols = VEC_length (osdata_column_s, last->columns); 00315 00316 /* As a special case, scan the listing of available data types 00317 for a column named "Title", and only include it with MI 00318 output; this column's normal use is for titles for interface 00319 elements like menus, and it clutters up CLI output. */ 00320 if (!type && !ui_out_is_mi_like_p (uiout)) 00321 { 00322 struct osdata_column *col; 00323 int ix; 00324 00325 for (ix = 0; 00326 VEC_iterate (osdata_column_s, last->columns, ix, col); 00327 ix++) 00328 { 00329 if (strcmp (col->name, "Title") == 0) 00330 col_to_skip = ix; 00331 } 00332 /* Be sure to reduce the total column count, otherwise 00333 internal errors ensue. */ 00334 if (col_to_skip >= 0) 00335 --ncols; 00336 } 00337 } 00338 00339 make_cleanup_ui_out_table_begin_end (uiout, ncols, nrows, 00340 "OSDataTable"); 00341 00342 /* With no columns/items, we just output an empty table, but we 00343 still output the table. This matters for MI. */ 00344 if (ncols == 0) 00345 { 00346 do_cleanups (old_chain); 00347 return; 00348 } 00349 00350 if (last && last->columns) 00351 { 00352 struct osdata_column *col; 00353 int ix; 00354 00355 for (ix = 0; 00356 VEC_iterate (osdata_column_s, last->columns, 00357 ix, col); 00358 ix++) 00359 { 00360 char col_name[32]; 00361 00362 if (ix == col_to_skip) 00363 continue; 00364 00365 snprintf (col_name, 32, "col%d", ix); 00366 ui_out_table_header (uiout, 10, ui_left, 00367 col_name, col->name); 00368 } 00369 } 00370 00371 ui_out_table_body (uiout); 00372 00373 if (nrows != 0) 00374 { 00375 struct osdata_item *item; 00376 int ix_items; 00377 00378 for (ix_items = 0; 00379 VEC_iterate (osdata_item_s, osdata->items, 00380 ix_items, item); 00381 ix_items++) 00382 { 00383 struct cleanup *old_chain; 00384 int ix_cols; 00385 struct osdata_column *col; 00386 00387 old_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "item"); 00388 00389 for (ix_cols = 0; 00390 VEC_iterate (osdata_column_s, item->columns, 00391 ix_cols, col); 00392 ix_cols++) 00393 { 00394 char col_name[32]; 00395 00396 if (ix_cols == col_to_skip) 00397 continue; 00398 00399 snprintf (col_name, 32, "col%d", ix_cols); 00400 ui_out_field_string (uiout, col_name, col->value); 00401 } 00402 00403 do_cleanups (old_chain); 00404 00405 ui_out_text (uiout, "\n"); 00406 } 00407 } 00408 00409 do_cleanups (old_chain); 00410 } 00411 00412 extern initialize_file_ftype _initialize_osdata; /* -Wmissing-prototypes */ 00413 00414 void 00415 _initialize_osdata (void) 00416 { 00417 add_info ("os", info_osdata_command, 00418 _("Show OS data ARG.")); 00419 }