Home | History | Annotate | Line # | Download | only in gdb
osdata.c revision 1.3
      1  1.1  christos /* Routines for handling XML generic OS data provided by target.
      2  1.1  christos 
      3  1.3  christos    Copyright (C) 2008-2015 Free Software Foundation, Inc.
      4  1.1  christos 
      5  1.1  christos    This file is part of GDB.
      6  1.1  christos 
      7  1.1  christos    This program is free software; you can redistribute it and/or modify
      8  1.1  christos    it under the terms of the GNU General Public License as published by
      9  1.1  christos    the Free Software Foundation; either version 3 of the License, or
     10  1.1  christos    (at your option) any later version.
     11  1.1  christos 
     12  1.1  christos    This program is distributed in the hope that it will be useful,
     13  1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15  1.1  christos    GNU General Public License for more details.
     16  1.1  christos 
     17  1.1  christos    You should have received a copy of the GNU General Public License
     18  1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     19  1.1  christos 
     20  1.1  christos #include "defs.h"
     21  1.1  christos #include "target.h"
     22  1.1  christos #include "vec.h"
     23  1.1  christos #include "xml-support.h"
     24  1.1  christos #include "osdata.h"
     25  1.1  christos #include "ui-out.h"
     26  1.1  christos #include "gdbcmd.h"
     27  1.1  christos 
     28  1.1  christos #if !defined(HAVE_LIBEXPAT)
     29  1.1  christos 
     30  1.1  christos struct osdata *
     31  1.1  christos osdata_parse (const char *xml)
     32  1.1  christos {
     33  1.1  christos   static int have_warned;
     34  1.1  christos 
     35  1.1  christos   if (!have_warned)
     36  1.1  christos     {
     37  1.1  christos       have_warned = 1;
     38  1.1  christos       warning (_("Can not parse XML OS data; XML support was disabled "
     39  1.1  christos                 "at compile time"));
     40  1.1  christos     }
     41  1.1  christos 
     42  1.1  christos   return NULL;
     43  1.1  christos }
     44  1.1  christos 
     45  1.1  christos #else /* HAVE_LIBEXPAT */
     46  1.1  christos 
     47  1.1  christos /* Internal parsing data passed to all XML callbacks.  */
     48  1.1  christos struct osdata_parsing_data
     49  1.1  christos   {
     50  1.1  christos     struct osdata *osdata;
     51  1.1  christos     char *property_name;
     52  1.1  christos   };
     53  1.1  christos 
     54  1.1  christos /* Handle the start of a <osdata> element.  */
     55  1.1  christos 
     56  1.1  christos static void
     57  1.1  christos osdata_start_osdata (struct gdb_xml_parser *parser,
     58  1.1  christos                         const struct gdb_xml_element *element,
     59  1.1  christos                         void *user_data, VEC(gdb_xml_value_s) *attributes)
     60  1.1  christos {
     61  1.1  christos   struct osdata_parsing_data *data = user_data;
     62  1.1  christos   char *type;
     63  1.1  christos   struct osdata *osdata;
     64  1.1  christos 
     65  1.1  christos   if (data->osdata)
     66  1.1  christos     gdb_xml_error (parser, _("Seen more than on osdata element"));
     67  1.1  christos 
     68  1.1  christos   type = xml_find_attribute (attributes, "type")->value;
     69  1.3  christos   osdata = XCNEW (struct osdata);
     70  1.1  christos   osdata->type = xstrdup (type);
     71  1.1  christos   data->osdata = osdata;
     72  1.1  christos }
     73  1.1  christos 
     74  1.1  christos /* Handle the start of a <item> element.  */
     75  1.1  christos 
     76  1.1  christos static void
     77  1.1  christos osdata_start_item (struct gdb_xml_parser *parser,
     78  1.1  christos                   const struct gdb_xml_element *element,
     79  1.1  christos                   void *user_data, VEC(gdb_xml_value_s) *attributes)
     80  1.1  christos {
     81  1.1  christos   struct osdata_parsing_data *data = user_data;
     82  1.1  christos   struct osdata_item item = { NULL };
     83  1.1  christos 
     84  1.1  christos   VEC_safe_push (osdata_item_s, data->osdata->items, &item);
     85  1.1  christos }
     86  1.1  christos 
     87  1.1  christos /* Handle the start of a <column> element.  */
     88  1.1  christos 
     89  1.1  christos static void
     90  1.1  christos osdata_start_column (struct gdb_xml_parser *parser,
     91  1.1  christos                     const struct gdb_xml_element *element,
     92  1.1  christos                     void *user_data, VEC(gdb_xml_value_s) *attributes)
     93  1.1  christos {
     94  1.1  christos   struct osdata_parsing_data *data = user_data;
     95  1.1  christos   const char *name = xml_find_attribute (attributes, "name")->value;
     96  1.1  christos 
     97  1.1  christos   data->property_name = xstrdup (name);
     98  1.1  christos }
     99  1.1  christos 
    100  1.1  christos /* Handle the end of a <column> element.  */
    101  1.1  christos 
    102  1.1  christos static void
    103  1.1  christos osdata_end_column (struct gdb_xml_parser *parser,
    104  1.1  christos                   const struct gdb_xml_element *element,
    105  1.1  christos                   void *user_data, const char *body_text)
    106  1.1  christos {
    107  1.1  christos   struct osdata_parsing_data *data = user_data;
    108  1.1  christos   struct osdata *osdata = data->osdata;
    109  1.1  christos   struct osdata_item *item = VEC_last (osdata_item_s, osdata->items);
    110  1.1  christos   struct osdata_column *col = VEC_safe_push (osdata_column_s,
    111  1.1  christos                                             item->columns, NULL);
    112  1.1  christos 
    113  1.1  christos   /* Transfer memory ownership.  NAME was already strdup'ed.  */
    114  1.1  christos   col->name = data->property_name;
    115  1.1  christos   col->value = xstrdup (body_text);
    116  1.1  christos   data->property_name = NULL;
    117  1.1  christos }
    118  1.1  christos 
    119  1.1  christos /* Discard the constructed osdata (if an error occurs).  */
    120  1.1  christos 
    121  1.1  christos static void
    122  1.1  christos clear_parsing_data (void *p)
    123  1.1  christos {
    124  1.1  christos   struct osdata_parsing_data *data = p;
    125  1.1  christos 
    126  1.1  christos   osdata_free (data->osdata);
    127  1.1  christos   data->osdata = NULL;
    128  1.1  christos   xfree (data->property_name);
    129  1.1  christos   data->property_name = NULL;
    130  1.1  christos }
    131  1.1  christos 
    132  1.1  christos /* The allowed elements and attributes for OS data object.
    133  1.1  christos    The root element is a <osdata>.  */
    134  1.1  christos 
    135  1.1  christos const struct gdb_xml_attribute column_attributes[] = {
    136  1.1  christos   { "name", GDB_XML_AF_NONE, NULL, NULL },
    137  1.1  christos   { NULL, GDB_XML_AF_NONE, NULL, NULL }
    138  1.1  christos };
    139  1.1  christos 
    140  1.1  christos const struct gdb_xml_element item_children[] = {
    141  1.1  christos   { "column", column_attributes, NULL,
    142  1.1  christos     GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
    143  1.1  christos     osdata_start_column, osdata_end_column },
    144  1.1  christos   { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
    145  1.1  christos };
    146  1.1  christos 
    147  1.1  christos const struct gdb_xml_attribute osdata_attributes[] = {
    148  1.1  christos   { "type", GDB_XML_AF_NONE, NULL, NULL },
    149  1.1  christos   { NULL, GDB_XML_AF_NONE, NULL, NULL }
    150  1.1  christos };
    151  1.1  christos 
    152  1.1  christos const struct gdb_xml_element osdata_children[] = {
    153  1.1  christos   { "item", NULL, item_children,
    154  1.1  christos     GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
    155  1.1  christos     osdata_start_item, NULL },
    156  1.1  christos   { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
    157  1.1  christos };
    158  1.1  christos 
    159  1.1  christos const struct gdb_xml_element osdata_elements[] = {
    160  1.1  christos   { "osdata", osdata_attributes, osdata_children,
    161  1.1  christos     GDB_XML_EF_NONE, osdata_start_osdata, NULL },
    162  1.1  christos   { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
    163  1.1  christos };
    164  1.1  christos 
    165  1.1  christos struct osdata *
    166  1.1  christos osdata_parse (const char *xml)
    167  1.1  christos {
    168  1.1  christos   struct cleanup *back_to;
    169  1.1  christos   struct osdata_parsing_data data = { NULL };
    170  1.1  christos 
    171  1.1  christos   back_to = make_cleanup (clear_parsing_data, &data);
    172  1.1  christos 
    173  1.1  christos   if (gdb_xml_parse_quick (_("osdata"), "osdata.dtd",
    174  1.1  christos 			   osdata_elements, xml, &data) == 0)
    175  1.1  christos     {
    176  1.1  christos       /* Parsed successfully, don't need to delete the result.  */
    177  1.1  christos       discard_cleanups (back_to);
    178  1.1  christos       return data.osdata;
    179  1.1  christos     }
    180  1.1  christos 
    181  1.1  christos   do_cleanups (back_to);
    182  1.1  christos   return NULL;
    183  1.1  christos }
    184  1.1  christos #endif
    185  1.1  christos 
    186  1.1  christos static void
    187  1.1  christos osdata_item_clear (struct osdata_item *item)
    188  1.1  christos {
    189  1.1  christos   if (item->columns != NULL)
    190  1.1  christos     {
    191  1.1  christos       struct osdata_column *col;
    192  1.1  christos       int ix;
    193  1.1  christos 
    194  1.1  christos       for (ix = 0;
    195  1.1  christos 	   VEC_iterate (osdata_column_s, item->columns,
    196  1.1  christos 			ix, col);
    197  1.1  christos 	   ix++)
    198  1.1  christos        {
    199  1.1  christos 	 xfree (col->name);
    200  1.1  christos 	 xfree (col->value);
    201  1.1  christos        }
    202  1.1  christos       VEC_free (osdata_column_s, item->columns);
    203  1.1  christos       item->columns = NULL;
    204  1.1  christos     }
    205  1.1  christos }
    206  1.1  christos 
    207  1.1  christos void
    208  1.1  christos osdata_free (struct osdata *osdata)
    209  1.1  christos {
    210  1.1  christos   if (osdata == NULL)
    211  1.1  christos     return;
    212  1.1  christos 
    213  1.1  christos   if (osdata->items != NULL)
    214  1.1  christos     {
    215  1.1  christos       struct osdata_item *item;
    216  1.1  christos       int ix;
    217  1.1  christos 
    218  1.1  christos       for (ix = 0;
    219  1.1  christos           VEC_iterate (osdata_item_s, osdata->items,
    220  1.1  christos                        ix, item);
    221  1.1  christos           ix++)
    222  1.1  christos        osdata_item_clear (item);
    223  1.1  christos       VEC_free (osdata_item_s, osdata->items);
    224  1.1  christos     }
    225  1.1  christos 
    226  1.1  christos   xfree (osdata);
    227  1.1  christos }
    228  1.1  christos 
    229  1.1  christos static void
    230  1.1  christos osdata_free_cleanup (void *arg)
    231  1.1  christos {
    232  1.1  christos   struct osdata *osdata = arg;
    233  1.1  christos 
    234  1.1  christos   osdata_free (osdata);
    235  1.1  christos }
    236  1.1  christos 
    237  1.1  christos struct cleanup *
    238  1.1  christos make_cleanup_osdata_free (struct osdata *data)
    239  1.1  christos {
    240  1.1  christos   return make_cleanup (osdata_free_cleanup, data);
    241  1.1  christos }
    242  1.1  christos 
    243  1.1  christos struct osdata *
    244  1.1  christos get_osdata (const char *type)
    245  1.1  christos {
    246  1.1  christos   struct osdata *osdata = NULL;
    247  1.1  christos   char *xml = target_get_osdata (type);
    248  1.1  christos 
    249  1.1  christos   if (xml)
    250  1.1  christos     {
    251  1.1  christos       struct cleanup *old_chain = make_cleanup (xfree, xml);
    252  1.1  christos 
    253  1.1  christos       if (xml[0] == '\0')
    254  1.1  christos 	{
    255  1.1  christos 	  if (type)
    256  1.1  christos 	    warning (_("Empty data returned by target.  Wrong osdata type?"));
    257  1.1  christos 	  else
    258  1.1  christos 	    warning (_("Empty type list returned by target.  No type data?"));
    259  1.1  christos 	}
    260  1.1  christos       else
    261  1.1  christos 	osdata = osdata_parse (xml);
    262  1.1  christos 
    263  1.1  christos       do_cleanups (old_chain);
    264  1.1  christos     }
    265  1.1  christos 
    266  1.1  christos   if (!osdata)
    267  1.1  christos     error (_("Can not fetch data now."));
    268  1.1  christos 
    269  1.1  christos   return osdata;
    270  1.1  christos }
    271  1.1  christos 
    272  1.1  christos const char *
    273  1.1  christos get_osdata_column (struct osdata_item *item, const char *name)
    274  1.1  christos {
    275  1.1  christos   struct osdata_column *col;
    276  1.1  christos   int ix_cols;
    277  1.1  christos 
    278  1.1  christos   for (ix_cols = 0;
    279  1.1  christos        VEC_iterate (osdata_column_s, item->columns,
    280  1.1  christos 		    ix_cols, col);
    281  1.1  christos        ix_cols++)
    282  1.1  christos     if (strcmp (col->name, name) == 0)
    283  1.1  christos       return col->value;
    284  1.1  christos 
    285  1.1  christos   return NULL;
    286  1.1  christos }
    287  1.1  christos 
    288  1.1  christos void
    289  1.1  christos info_osdata_command (char *type, int from_tty)
    290  1.1  christos {
    291  1.1  christos   struct ui_out *uiout = current_uiout;
    292  1.1  christos   struct osdata *osdata = NULL;
    293  1.1  christos   struct osdata_item *last = NULL;
    294  1.1  christos   struct cleanup *old_chain;
    295  1.1  christos   int ncols = 0;
    296  1.1  christos   int nrows;
    297  1.1  christos   int col_to_skip = -1;
    298  1.1  christos 
    299  1.1  christos   osdata = get_osdata (type);
    300  1.1  christos   old_chain = make_cleanup_osdata_free (osdata);
    301  1.1  christos 
    302  1.1  christos   nrows = VEC_length (osdata_item_s, osdata->items);
    303  1.1  christos 
    304  1.1  christos   if (!type && nrows == 0)
    305  1.1  christos     error (_("Available types of OS data not reported."));
    306  1.1  christos 
    307  1.1  christos   if (!VEC_empty (osdata_item_s, osdata->items))
    308  1.1  christos     {
    309  1.1  christos       last = VEC_last (osdata_item_s, osdata->items);
    310  1.1  christos       if (last->columns)
    311  1.1  christos         ncols = VEC_length (osdata_column_s, last->columns);
    312  1.1  christos 
    313  1.1  christos       /* As a special case, scan the listing of available data types
    314  1.1  christos 	 for a column named "Title", and only include it with MI
    315  1.1  christos 	 output; this column's normal use is for titles for interface
    316  1.1  christos 	 elements like menus, and it clutters up CLI output.  */
    317  1.1  christos       if (!type && !ui_out_is_mi_like_p (uiout))
    318  1.1  christos 	{
    319  1.1  christos 	  struct osdata_column *col;
    320  1.1  christos 	  int ix;
    321  1.1  christos 
    322  1.1  christos 	  for (ix = 0;
    323  1.1  christos 	       VEC_iterate (osdata_column_s, last->columns, ix, col);
    324  1.1  christos 	       ix++)
    325  1.1  christos 	    {
    326  1.1  christos 	      if (strcmp (col->name, "Title") == 0)
    327  1.1  christos 		col_to_skip = ix;
    328  1.1  christos 	    }
    329  1.1  christos 	  /* Be sure to reduce the total column count, otherwise
    330  1.1  christos 	     internal errors ensue.  */
    331  1.1  christos 	  if (col_to_skip >= 0)
    332  1.1  christos 	    --ncols;
    333  1.1  christos 	}
    334  1.1  christos     }
    335  1.1  christos 
    336  1.1  christos   make_cleanup_ui_out_table_begin_end (uiout, ncols, nrows,
    337  1.1  christos 				       "OSDataTable");
    338  1.1  christos 
    339  1.1  christos   /* With no columns/items, we just output an empty table, but we
    340  1.1  christos      still output the table.  This matters for MI.  */
    341  1.1  christos   if (ncols == 0)
    342  1.1  christos     {
    343  1.1  christos       do_cleanups (old_chain);
    344  1.1  christos       return;
    345  1.1  christos     }
    346  1.1  christos 
    347  1.1  christos   if (last && last->columns)
    348  1.1  christos     {
    349  1.1  christos       struct osdata_column *col;
    350  1.1  christos       int ix;
    351  1.1  christos 
    352  1.1  christos       for (ix = 0;
    353  1.1  christos           VEC_iterate (osdata_column_s, last->columns,
    354  1.1  christos                        ix, col);
    355  1.1  christos           ix++)
    356  1.1  christos 	{
    357  1.1  christos 	  char col_name[32];
    358  1.1  christos 
    359  1.1  christos 	  if (ix == col_to_skip)
    360  1.1  christos 	    continue;
    361  1.1  christos 
    362  1.1  christos 	  snprintf (col_name, 32, "col%d", ix);
    363  1.1  christos 	  ui_out_table_header (uiout, 10, ui_left,
    364  1.1  christos 			       col_name, col->name);
    365  1.1  christos         }
    366  1.1  christos     }
    367  1.1  christos 
    368  1.1  christos   ui_out_table_body (uiout);
    369  1.1  christos 
    370  1.1  christos   if (nrows != 0)
    371  1.1  christos     {
    372  1.1  christos       struct osdata_item *item;
    373  1.1  christos       int ix_items;
    374  1.1  christos 
    375  1.1  christos       for (ix_items = 0;
    376  1.1  christos           VEC_iterate (osdata_item_s, osdata->items,
    377  1.1  christos                        ix_items, item);
    378  1.1  christos           ix_items++)
    379  1.1  christos        {
    380  1.1  christos          struct cleanup *old_chain;
    381  1.1  christos          int ix_cols;
    382  1.1  christos          struct osdata_column *col;
    383  1.1  christos 
    384  1.1  christos          old_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "item");
    385  1.1  christos 
    386  1.1  christos          for (ix_cols = 0;
    387  1.1  christos               VEC_iterate (osdata_column_s, item->columns,
    388  1.1  christos                            ix_cols, col);
    389  1.1  christos               ix_cols++)
    390  1.1  christos 	   {
    391  1.1  christos 	     char col_name[32];
    392  1.1  christos 
    393  1.1  christos 	     if (ix_cols == col_to_skip)
    394  1.1  christos 	       continue;
    395  1.1  christos 
    396  1.1  christos 	     snprintf (col_name, 32, "col%d", ix_cols);
    397  1.1  christos 	     ui_out_field_string (uiout, col_name, col->value);
    398  1.1  christos 	   }
    399  1.1  christos 
    400  1.1  christos          do_cleanups (old_chain);
    401  1.1  christos 
    402  1.1  christos          ui_out_text (uiout, "\n");
    403  1.1  christos        }
    404  1.1  christos     }
    405  1.1  christos 
    406  1.1  christos   do_cleanups (old_chain);
    407  1.1  christos }
    408  1.1  christos 
    409  1.1  christos extern initialize_file_ftype _initialize_osdata; /* -Wmissing-prototypes */
    410  1.1  christos 
    411  1.1  christos void
    412  1.1  christos _initialize_osdata (void)
    413  1.1  christos {
    414  1.1  christos   add_info ("os", info_osdata_command,
    415  1.1  christos            _("Show OS data ARG."));
    416  1.1  christos }
    417