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