Home | History | Annotate | Line # | Download | only in common
hw-tree.c revision 1.1.1.4
      1      1.1  christos /* The common simulator framework for GDB, the GNU Debugger.
      2      1.1  christos 
      3  1.1.1.4  christos    Copyright 2002-2017 Free Software Foundation, Inc.
      4      1.1  christos 
      5      1.1  christos    Contributed by Andrew Cagney and Red Hat.
      6      1.1  christos 
      7      1.1  christos    This file is part of GDB.
      8      1.1  christos 
      9      1.1  christos    This program is free software; you can redistribute it and/or modify
     10      1.1  christos    it under the terms of the GNU General Public License as published by
     11      1.1  christos    the Free Software Foundation; either version 3 of the License, or
     12      1.1  christos    (at your option) any later version.
     13      1.1  christos 
     14      1.1  christos    This program is distributed in the hope that it will be useful,
     15      1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     16      1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17      1.1  christos    GNU General Public License for more details.
     18      1.1  christos 
     19      1.1  christos    You should have received a copy of the GNU General Public License
     20      1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     21      1.1  christos 
     22      1.1  christos 
     23      1.1  christos #include "hw-main.h"
     24      1.1  christos #include "hw-base.h"
     25      1.1  christos #include "hw-tree.h"
     26      1.1  christos 
     27      1.1  christos #include "sim-io.h"
     28      1.1  christos #include "sim-assert.h"
     29      1.1  christos 
     30      1.1  christos #ifdef HAVE_STDLIB_H
     31      1.1  christos #include <stdlib.h>
     32      1.1  christos #endif
     33      1.1  christos 
     34      1.1  christos #ifdef HAVE_STRING_H
     35      1.1  christos #include <string.h>
     36      1.1  christos #else
     37      1.1  christos #ifdef HAVE_STRINGS_H
     38      1.1  christos #include <strings.h>
     39      1.1  christos #endif
     40      1.1  christos #endif
     41      1.1  christos 
     42      1.1  christos #include <ctype.h>
     43      1.1  christos 
     44      1.1  christos /* manipulate/lookup device names */
     45      1.1  christos 
     46      1.1  christos typedef struct _name_specifier
     47      1.1  christos {
     48      1.1  christos 
     49      1.1  christos   /* components in the full length name */
     50      1.1  christos   char *path;
     51      1.1  christos   char *property;
     52      1.1  christos   char *value;
     53      1.1  christos 
     54      1.1  christos   /* current device */
     55      1.1  christos   char *family;
     56      1.1  christos   char *name;
     57      1.1  christos   char *unit;
     58      1.1  christos   char *args;
     59      1.1  christos 
     60      1.1  christos   /* previous device */
     61      1.1  christos   char *last_name;
     62      1.1  christos   char *last_family;
     63      1.1  christos   char *last_unit;
     64      1.1  christos   char *last_args;
     65      1.1  christos 
     66      1.1  christos   /* work area */
     67      1.1  christos   char buf[1024];
     68      1.1  christos 
     69      1.1  christos } name_specifier;
     70      1.1  christos 
     71      1.1  christos 
     72      1.1  christos 
     73      1.1  christos /* Given a device specifier, break it up into its main components:
     74      1.1  christos    path (and if present) property name and property value. */
     75      1.1  christos 
     76      1.1  christos static int
     77      1.1  christos split_device_specifier (struct hw *current,
     78      1.1  christos 			const char *device_specifier,
     79      1.1  christos 			name_specifier *spec)
     80      1.1  christos {
     81      1.1  christos   char *chp = NULL;
     82      1.1  christos 
     83      1.1  christos   /* expand any leading alias if present */
     84      1.1  christos   if (current != NULL
     85      1.1  christos       && *device_specifier != '\0'
     86      1.1  christos       && *device_specifier != '.'
     87      1.1  christos       && *device_specifier != '/')
     88      1.1  christos     {
     89      1.1  christos       struct hw *aliases = hw_tree_find_device (current, "/aliases");
     90      1.1  christos       char alias[32];
     91      1.1  christos       int len = 0;
     92      1.1  christos       while (device_specifier[len] != '\0'
     93      1.1  christos 	     && device_specifier[len] != '/'
     94      1.1  christos 	     && device_specifier[len] != ':'
     95      1.1  christos 	     && !isspace (device_specifier[len]))
     96      1.1  christos 	{
     97      1.1  christos 	  alias[len] = device_specifier[len];
     98      1.1  christos 	  len++;
     99      1.1  christos 	  if (len >= sizeof (alias))
    100      1.1  christos 	    hw_abort (NULL, "split_device_specifier: buffer overflow");
    101      1.1  christos 	}
    102      1.1  christos       alias[len] = '\0';
    103      1.1  christos       if (aliases != NULL
    104      1.1  christos 	  && hw_find_property (aliases, alias))
    105      1.1  christos 	{
    106      1.1  christos 	  strcpy (spec->buf, hw_find_string_property (aliases, alias));
    107      1.1  christos 	  strcat (spec->buf, device_specifier + len);
    108      1.1  christos 	}
    109      1.1  christos       else
    110      1.1  christos 	{
    111      1.1  christos 	  strcpy (spec->buf, device_specifier);
    112      1.1  christos 	}
    113      1.1  christos     }
    114      1.1  christos   else
    115      1.1  christos     {
    116      1.1  christos       strcpy (spec->buf, device_specifier);
    117      1.1  christos     }
    118      1.1  christos 
    119      1.1  christos   /* check no overflow */
    120      1.1  christos   if (strlen (spec->buf) >= sizeof (spec->buf))
    121      1.1  christos     hw_abort (NULL, "split_device_specifier: buffer overflow\n");
    122      1.1  christos 
    123      1.1  christos   /* strip leading spaces */
    124      1.1  christos   chp = spec->buf;
    125      1.1  christos   while (*chp != '\0' && isspace (*chp))
    126      1.1  christos     chp++;
    127      1.1  christos   if (*chp == '\0')
    128      1.1  christos     return 0;
    129      1.1  christos 
    130      1.1  christos   /* find the path and terminate it with null */
    131      1.1  christos   spec->path = chp;
    132      1.1  christos   while (*chp != '\0' && !isspace (*chp))
    133      1.1  christos     chp++;
    134      1.1  christos   if (*chp != '\0')
    135      1.1  christos     {
    136      1.1  christos       *chp = '\0';
    137      1.1  christos       chp++;
    138      1.1  christos     }
    139      1.1  christos 
    140      1.1  christos   /* and any value */
    141      1.1  christos   while (*chp != '\0' && isspace (*chp))
    142      1.1  christos     chp++;
    143      1.1  christos   spec->value = chp;
    144      1.1  christos 
    145      1.1  christos   /* now go back and chop the property off of the path */
    146      1.1  christos   if (spec->value[0] == '\0')
    147      1.1  christos     {
    148      1.1  christos       spec->property = NULL; /*not a property*/
    149      1.1  christos       spec->value = NULL;
    150      1.1  christos     }
    151      1.1  christos   else if (spec->value[0] == '>'
    152      1.1  christos 	   || spec->value[0] == '<')
    153      1.1  christos     {
    154      1.1  christos       /* an interrupt spec */
    155      1.1  christos       spec->property = NULL;
    156      1.1  christos     }
    157      1.1  christos   else
    158      1.1  christos     {
    159      1.1  christos       chp = strrchr (spec->path, '/');
    160      1.1  christos       if (chp == NULL)
    161      1.1  christos 	{
    162      1.1  christos 	  spec->property = spec->path;
    163      1.1  christos 	  spec->path = strchr (spec->property, '\0');
    164      1.1  christos 	}
    165      1.1  christos       else
    166      1.1  christos 	{
    167      1.1  christos 	  *chp = '\0';
    168      1.1  christos 	  spec->property = chp+1;
    169      1.1  christos 	}
    170      1.1  christos     }
    171      1.1  christos 
    172      1.1  christos   /* and mark the rest as invalid */
    173      1.1  christos   spec->name = NULL;
    174      1.1  christos   spec->family = NULL;
    175      1.1  christos   spec->unit = NULL;
    176      1.1  christos   spec->args = NULL;
    177      1.1  christos   spec->last_name = NULL;
    178      1.1  christos   spec->last_family = NULL;
    179      1.1  christos   spec->last_unit = NULL;
    180      1.1  christos   spec->last_args = NULL;
    181      1.1  christos 
    182      1.1  christos   return 1;
    183      1.1  christos }
    184      1.1  christos 
    185      1.1  christos 
    186      1.1  christos /* given a device specifier break it up into its main components -
    187      1.1  christos    path and property name - assuming that the last `device' is a
    188      1.1  christos    property name. */
    189      1.1  christos 
    190      1.1  christos static int
    191      1.1  christos split_property_specifier (struct hw *current,
    192      1.1  christos 			  const char *property_specifier,
    193      1.1  christos 			  name_specifier *spec)
    194      1.1  christos {
    195      1.1  christos   if (split_device_specifier (current, property_specifier, spec))
    196      1.1  christos     {
    197      1.1  christos       if (spec->property == NULL)
    198      1.1  christos 	{
    199      1.1  christos 	  /* force the last name to be a property name */
    200      1.1  christos 	  char *chp = strrchr (spec->path, '/');
    201      1.1  christos 	  if (chp == NULL)
    202      1.1  christos 	    {
    203      1.1  christos 	      spec->property = spec->path;
    204      1.1  christos 	      spec->path = strrchr (spec->property, '\0');;
    205      1.1  christos 	    }
    206      1.1  christos 	  else
    207      1.1  christos 	    {
    208      1.1  christos 	      *chp = '\0';
    209      1.1  christos 	      spec->property = chp + 1;
    210      1.1  christos 	    }
    211      1.1  christos 	}
    212      1.1  christos       return 1;
    213      1.1  christos     }
    214      1.1  christos   else
    215      1.1  christos     return 0;
    216      1.1  christos }
    217      1.1  christos 
    218      1.1  christos 
    219      1.1  christos /* device the next device name and split it up, return 0 when no more
    220      1.1  christos    names to struct hw */
    221      1.1  christos 
    222      1.1  christos static int
    223      1.1  christos split_device_name (name_specifier *spec)
    224      1.1  christos {
    225      1.1  christos   char *chp;
    226      1.1  christos   /* remember what came before */
    227      1.1  christos   spec->last_name = spec->name;
    228      1.1  christos   spec->last_family = spec->family;
    229      1.1  christos   spec->last_unit = spec->unit;
    230      1.1  christos   spec->last_args = spec->args;
    231      1.1  christos   /* finished? */
    232      1.1  christos   if (spec->path[0] == '\0')
    233      1.1  christos     {
    234      1.1  christos       spec->name = NULL;
    235      1.1  christos       spec->family = NULL;
    236      1.1  christos       spec->unit = NULL;
    237      1.1  christos       spec->args = NULL;
    238      1.1  christos       return 0;
    239      1.1  christos     }
    240      1.1  christos   /* break the current device spec from the path */
    241      1.1  christos   spec->name = spec->path;
    242      1.1  christos   chp = strchr (spec->name, '/');
    243      1.1  christos   if (chp == NULL)
    244      1.1  christos     spec->path = strchr (spec->name, '\0');
    245      1.1  christos   else
    246      1.1  christos     {
    247      1.1  christos       spec->path = chp+1;
    248      1.1  christos       *chp = '\0';
    249      1.1  christos     }
    250      1.1  christos   /* break out the base */
    251      1.1  christos   if (spec->name[0] == '(')
    252      1.1  christos     {
    253      1.1  christos       chp = strchr (spec->name, ')');
    254      1.1  christos       if (chp == NULL)
    255      1.1  christos 	{
    256      1.1  christos 	  spec->family = spec->name;
    257      1.1  christos 	}
    258      1.1  christos       else
    259      1.1  christos 	{
    260      1.1  christos 	  *chp = '\0';
    261      1.1  christos 	  spec->family = spec->name + 1;
    262      1.1  christos 	  spec->name = chp + 1;
    263      1.1  christos 	}
    264      1.1  christos     }
    265      1.1  christos   else
    266      1.1  christos     {
    267      1.1  christos       spec->family = spec->name;
    268      1.1  christos     }
    269      1.1  christos   /* now break out the unit */
    270      1.1  christos   chp = strchr (spec->name, '@');
    271      1.1  christos   if (chp == NULL)
    272      1.1  christos     {
    273      1.1  christos       spec->unit = NULL;
    274      1.1  christos       chp = spec->name;
    275      1.1  christos     }
    276      1.1  christos   else
    277      1.1  christos     {
    278      1.1  christos       *chp = '\0';
    279      1.1  christos       chp += 1;
    280      1.1  christos       spec->unit = chp;
    281      1.1  christos     }
    282      1.1  christos   /* finally any args */
    283      1.1  christos   chp = strchr (chp, ':');
    284      1.1  christos   if (chp == NULL)
    285      1.1  christos     spec->args = NULL;
    286      1.1  christos   else
    287      1.1  christos     {
    288      1.1  christos       *chp = '\0';
    289      1.1  christos       spec->args = chp+1;
    290      1.1  christos     }
    291      1.1  christos   return 1;
    292      1.1  christos }
    293      1.1  christos 
    294      1.1  christos 
    295      1.1  christos /* device the value, returning the next non-space token */
    296      1.1  christos 
    297      1.1  christos static char *
    298      1.1  christos split_value (name_specifier *spec)
    299      1.1  christos {
    300      1.1  christos   char *token;
    301      1.1  christos   if (spec->value == NULL)
    302      1.1  christos     return NULL;
    303      1.1  christos   /* skip leading white space */
    304      1.1  christos   while (isspace (spec->value[0]))
    305      1.1  christos     spec->value++;
    306      1.1  christos   if (spec->value[0] == '\0')
    307      1.1  christos     {
    308      1.1  christos       spec->value = NULL;
    309      1.1  christos       return NULL;
    310      1.1  christos     }
    311      1.1  christos   token = spec->value;
    312      1.1  christos   /* find trailing space */
    313      1.1  christos   while (spec->value[0] != '\0' && !isspace (spec->value[0]))
    314      1.1  christos     spec->value++;
    315      1.1  christos   /* chop this value out */
    316      1.1  christos   if (spec->value[0] != '\0')
    317      1.1  christos     {
    318      1.1  christos       spec->value[0] = '\0';
    319      1.1  christos       spec->value++;
    320      1.1  christos     }
    321      1.1  christos   return token;
    322      1.1  christos }
    323      1.1  christos 
    324      1.1  christos 
    325      1.1  christos 
    326      1.1  christos /* traverse the path specified by spec starting at current */
    327      1.1  christos 
    328      1.1  christos static struct hw *
    329      1.1  christos split_find_device (struct hw *current,
    330      1.1  christos 		   name_specifier *spec)
    331      1.1  christos {
    332      1.1  christos   /* strip off (and process) any leading ., .., ./ and / */
    333      1.1  christos   while (1)
    334      1.1  christos     {
    335      1.1  christos       if (strncmp (spec->path, "/", strlen ("/")) == 0)
    336      1.1  christos 	{
    337      1.1  christos 	  /* cd /... */
    338      1.1  christos 	  while (current != NULL && hw_parent (current) != NULL)
    339      1.1  christos 	    current = hw_parent (current);
    340      1.1  christos 	  spec->path += strlen ("/");
    341      1.1  christos 	}
    342      1.1  christos       else if (strncmp (spec->path, "./", strlen ("./")) == 0)
    343      1.1  christos 	{
    344      1.1  christos 	  /* cd ./... */
    345      1.1  christos 	  current = current;
    346      1.1  christos 	  spec->path += strlen ("./");
    347      1.1  christos 	}
    348      1.1  christos       else if (strncmp (spec->path, "../", strlen ("../")) == 0)
    349      1.1  christos 	{
    350      1.1  christos 	  /* cd ../... */
    351      1.1  christos 	  if (current != NULL && hw_parent (current) != NULL)
    352      1.1  christos 	    current = hw_parent (current);
    353      1.1  christos 	  spec->path += strlen ("../");
    354      1.1  christos 	}
    355      1.1  christos       else if (strcmp (spec->path, ".") == 0)
    356      1.1  christos 	{
    357      1.1  christos 	  /* cd . */
    358      1.1  christos 	  current = current;
    359      1.1  christos 	  spec->path += strlen (".");
    360      1.1  christos 	}
    361      1.1  christos       else if (strcmp (spec->path, "..") == 0)
    362      1.1  christos 	{
    363      1.1  christos 	  /* cd .. */
    364      1.1  christos 	  if (current != NULL && hw_parent (current) != NULL)
    365      1.1  christos 	    current = hw_parent (current);
    366      1.1  christos 	  spec->path += strlen ("..");
    367      1.1  christos 	}
    368      1.1  christos       else
    369      1.1  christos 	break;
    370      1.1  christos     }
    371      1.1  christos 
    372      1.1  christos   /* now go through the path proper */
    373      1.1  christos 
    374      1.1  christos   if (current == NULL)
    375      1.1  christos     {
    376      1.1  christos       split_device_name (spec);
    377      1.1  christos       return NULL;
    378      1.1  christos     }
    379      1.1  christos 
    380      1.1  christos   while (split_device_name (spec))
    381      1.1  christos     {
    382      1.1  christos       struct hw *child;
    383      1.1  christos       for (child = hw_child (current);
    384      1.1  christos 	   child != NULL; child = hw_sibling (child))
    385      1.1  christos 	{
    386      1.1  christos 	  if (strcmp (spec->name, hw_name (child)) == 0)
    387      1.1  christos 	    {
    388      1.1  christos 	      if (spec->unit == NULL)
    389      1.1  christos 		break;
    390      1.1  christos 	      else
    391      1.1  christos 		{
    392      1.1  christos 		  hw_unit phys;
    393      1.1  christos 		  hw_unit_decode (current, spec->unit, &phys);
    394      1.1  christos 		  if (memcmp (&phys, hw_unit_address (child),
    395      1.1  christos 			      sizeof (hw_unit)) == 0)
    396      1.1  christos 		    break;
    397      1.1  christos 		}
    398      1.1  christos 	    }
    399      1.1  christos 	}
    400      1.1  christos       if (child == NULL)
    401      1.1  christos 	return current; /* search failed */
    402      1.1  christos       current = child;
    403      1.1  christos     }
    404      1.1  christos 
    405      1.1  christos   return current;
    406      1.1  christos }
    407      1.1  christos 
    408      1.1  christos 
    409      1.1  christos static struct hw *
    410      1.1  christos split_fill_path (struct hw *current,
    411      1.1  christos 		 const char *device_specifier,
    412      1.1  christos 		 name_specifier *spec)
    413      1.1  christos {
    414      1.1  christos   /* break it up */
    415      1.1  christos   if (!split_device_specifier (current, device_specifier, spec))
    416      1.1  christos     hw_abort (current, "error parsing %s\n", device_specifier);
    417      1.1  christos 
    418      1.1  christos   /* fill our tree with its contents */
    419      1.1  christos   current = split_find_device (current, spec);
    420      1.1  christos 
    421      1.1  christos   /* add any additional devices as needed */
    422      1.1  christos   if (spec->name != NULL)
    423      1.1  christos     {
    424      1.1  christos       do
    425      1.1  christos 	{
    426      1.1  christos 	  if (current != NULL && !hw_finished_p (current))
    427      1.1  christos 	    hw_finish (current);
    428      1.1  christos 	  current = hw_create (NULL,
    429      1.1  christos 			       current,
    430      1.1  christos 			       spec->family,
    431      1.1  christos 			       spec->name,
    432      1.1  christos 			       spec->unit,
    433      1.1  christos 			       spec->args);
    434      1.1  christos 	}
    435      1.1  christos       while (split_device_name (spec));
    436      1.1  christos     }
    437      1.1  christos 
    438      1.1  christos   return current;
    439      1.1  christos }
    440      1.1  christos 
    441      1.1  christos 
    442      1.1  christos /* <non-white-space> */
    444      1.1  christos 
    445      1.1  christos static const char *
    446      1.1  christos skip_token (const char *chp)
    447      1.1  christos {
    448      1.1  christos   while (!isspace (*chp) && *chp != '\0')
    449      1.1  christos     chp++;
    450      1.1  christos   while (isspace (*chp) && *chp != '\0')
    451      1.1  christos     chp++;
    452      1.1  christos   return chp;
    453      1.1  christos }
    454      1.1  christos 
    455      1.1  christos 
    456      1.1  christos /* count the number of entries */
    457      1.1  christos 
    458      1.1  christos static int
    459      1.1  christos count_entries (struct hw *current,
    460      1.1  christos 	       const char *property_name,
    461      1.1  christos 	       const char *property_value,
    462      1.1  christos 	       int modulo)
    463      1.1  christos {
    464      1.1  christos   const char *chp = property_value;
    465      1.1  christos   int nr_entries = 0;
    466      1.1  christos   while (*chp != '\0')
    467      1.1  christos     {
    468      1.1  christos       nr_entries += 1;
    469      1.1  christos       chp = skip_token (chp);
    470      1.1  christos     }
    471      1.1  christos   if ((nr_entries % modulo) != 0)
    472      1.1  christos     {
    473      1.1  christos       hw_abort (current, "incorrect number of entries for %s property %s, should be multiple of %d",
    474      1.1  christos 		property_name, property_value, modulo);
    475      1.1  christos     }
    476      1.1  christos   return nr_entries / modulo;
    477      1.1  christos }
    478      1.1  christos 
    479      1.1  christos 
    480      1.1  christos 
    481      1.1  christos /* parse: <address> ::= <token> ; device dependant */
    482      1.1  christos 
    483      1.1  christos static const char *
    484      1.1  christos parse_address (struct hw *current,
    485      1.1  christos 	       struct hw *bus,
    486      1.1  christos 	       const char *chp,
    487      1.1  christos 	       hw_unit *address)
    488      1.1  christos {
    489      1.1  christos   if (hw_unit_decode (bus, chp, address) < 0)
    490      1.1  christos     hw_abort (current, "invalid unit address in %s", chp);
    491      1.1  christos   return skip_token (chp);
    492      1.1  christos }
    493      1.1  christos 
    494      1.1  christos 
    495      1.1  christos /* parse: <size> ::= <number> { "," <number> } ; */
    496      1.1  christos 
    497      1.1  christos static const char *
    498      1.1  christos parse_size (struct hw *current,
    499      1.1  christos 	    struct hw *bus,
    500      1.1  christos 	    const char *chp,
    501      1.1  christos 	    hw_unit *size)
    502      1.1  christos {
    503      1.1  christos   int i;
    504      1.1  christos   int nr;
    505      1.1  christos   const char *curr = chp;
    506      1.1  christos   memset (size, 0, sizeof (*size));
    507      1.1  christos   /* parse the numeric list */
    508      1.1  christos   size->nr_cells = hw_unit_nr_size_cells (bus);
    509      1.1  christos   nr = 0;
    510      1.1  christos   while (1)
    511      1.1  christos     {
    512      1.1  christos       char *next;
    513      1.1  christos       size->cells[nr] = strtoul (curr, &next, 0);
    514      1.1  christos       if (curr == next)
    515      1.1  christos 	hw_abort (current, "Problem parsing <size> %s", chp);
    516      1.1  christos       nr += 1;
    517      1.1  christos       if (next[0] != ',')
    518      1.1  christos 	break;
    519      1.1  christos       if (nr == size->nr_cells)
    520      1.1  christos 	hw_abort (current, "Too many values in <size> %s", chp);
    521      1.1  christos       curr = next + 1;
    522      1.1  christos     }
    523      1.1  christos   ASSERT (nr > 0 && nr <= size->nr_cells);
    524      1.1  christos   /* right align the numbers */
    525      1.1  christos   for (i = 1; i <= size->nr_cells; i++)
    526      1.1  christos     {
    527      1.1  christos       if (i <= nr)
    528      1.1  christos 	size->cells[size->nr_cells - i] = size->cells[nr - i];
    529      1.1  christos       else
    530      1.1  christos 	size->cells[size->nr_cells - i] = 0;
    531      1.1  christos     }
    532      1.1  christos   return skip_token (chp);
    533      1.1  christos }
    534      1.1  christos 
    535      1.1  christos 
    536      1.1  christos /* parse: <reg> ::= { <address> <size> } ; */
    537      1.1  christos 
    538      1.1  christos static void
    539      1.1  christos parse_reg_property (struct hw *current,
    540      1.1  christos 		    const char *property_name,
    541      1.1  christos 		    const char *property_value)
    542      1.1  christos {
    543      1.1  christos   int nr_regs;
    544      1.1  christos   int reg_nr;
    545      1.1  christos   reg_property_spec *regs;
    546      1.1  christos   const char *chp;
    547      1.1  christos 
    548      1.1  christos   /* determine the number of reg entries by counting tokens */
    549      1.1  christos   nr_regs = count_entries (current, property_name, property_value, 2);
    550      1.1  christos 
    551      1.1  christos   /* create working space */
    552      1.1  christos   regs = zalloc (nr_regs * sizeof (*regs));
    553      1.1  christos 
    554      1.1  christos   /* fill it in */
    555      1.1  christos   chp = property_value;
    556      1.1  christos   for (reg_nr = 0; reg_nr < nr_regs; reg_nr++)
    557      1.1  christos     {
    558      1.1  christos       chp = parse_address (current, hw_parent (current),
    559      1.1  christos 			   chp, &regs[reg_nr].address);
    560      1.1  christos       chp = parse_size (current, hw_parent (current),
    561      1.1  christos 			chp, &regs[reg_nr].size);
    562      1.1  christos     }
    563      1.1  christos 
    564      1.1  christos   /* create it */
    565      1.1  christos   hw_add_reg_array_property (current, property_name,
    566      1.1  christos 			     regs, nr_regs);
    567      1.1  christos 
    568      1.1  christos   free (regs);
    569      1.1  christos }
    570      1.1  christos 
    571      1.1  christos 
    572      1.1  christos /* { <child-address> <parent-address> <child-size> }* */
    573      1.1  christos 
    574      1.1  christos static void
    575      1.1  christos parse_ranges_property (struct hw *current,
    576      1.1  christos 		       const char *property_name,
    577      1.1  christos 		       const char *property_value)
    578      1.1  christos {
    579      1.1  christos   int nr_ranges;
    580      1.1  christos   int range_nr;
    581      1.1  christos   range_property_spec *ranges;
    582      1.1  christos   const char *chp;
    583      1.1  christos 
    584      1.1  christos   /* determine the number of ranges specified */
    585      1.1  christos   nr_ranges = count_entries (current, property_name, property_value, 3);
    586      1.1  christos 
    587      1.1  christos   /* create a property of that size */
    588      1.1  christos   ranges = zalloc (nr_ranges * sizeof (*ranges));
    589      1.1  christos 
    590      1.1  christos   /* fill it in */
    591      1.1  christos   chp = property_value;
    592      1.1  christos   for (range_nr = 0; range_nr < nr_ranges; range_nr++)
    593      1.1  christos     {
    594      1.1  christos       chp = parse_address (current, current,
    595      1.1  christos 			   chp, &ranges[range_nr].child_address);
    596      1.1  christos       chp = parse_address (current, hw_parent (current),
    597      1.1  christos 			   chp, &ranges[range_nr].parent_address);
    598      1.1  christos       chp = parse_size (current, current,
    599      1.1  christos 			chp, &ranges[range_nr].size);
    600      1.1  christos     }
    601      1.1  christos 
    602      1.1  christos   /* create it */
    603      1.1  christos   hw_add_range_array_property (current, property_name, ranges, nr_ranges);
    604      1.1  christos 
    605      1.1  christos   free (ranges);
    606      1.1  christos }
    607      1.1  christos 
    608      1.1  christos 
    609      1.1  christos /* <integer> ... */
    610      1.1  christos 
    611      1.1  christos static void
    612      1.1  christos parse_integer_property (struct hw *current,
    613      1.1  christos 			const char *property_name,
    614      1.1  christos 			const char *property_value)
    615      1.1  christos {
    616      1.1  christos   int nr_entries;
    617      1.1  christos   unsigned_cell words[1024];
    618      1.1  christos   /* integer or integer array? */
    619      1.1  christos   nr_entries = 0;
    620      1.1  christos   while (1)
    621      1.1  christos     {
    622      1.1  christos       char *end;
    623      1.1  christos       words[nr_entries] = strtoul (property_value, &end, 0);
    624      1.1  christos       if (property_value == end)
    625      1.1  christos 	break;
    626      1.1  christos       nr_entries += 1;
    627      1.1  christos       if (nr_entries * sizeof (words[0]) >= sizeof (words))
    628      1.1  christos 	hw_abort (current, "buffer overflow");
    629      1.1  christos       property_value = end;
    630      1.1  christos     }
    631      1.1  christos   if (nr_entries == 0)
    632      1.1  christos     hw_abort (current, "error parsing integer property %s (%s)",
    633      1.1  christos 	      property_name, property_value);
    634      1.1  christos   else if (nr_entries == 1)
    635      1.1  christos     hw_add_integer_property (current, property_name, words[0]);
    636      1.1  christos   else
    637      1.1  christos     {
    638      1.1  christos       int i;
    639      1.1  christos       for (i = 0; i < nr_entries; i++)
    640      1.1  christos 	{
    641      1.1  christos 	  H2BE (words[i]);
    642      1.1  christos 	}
    643      1.1  christos       /* perhaps integer array property is better */
    644      1.1  christos       hw_add_array_property (current, property_name, words,
    645      1.1  christos 			     sizeof (words[0]) * nr_entries);
    646      1.1  christos     }
    647      1.1  christos }
    648      1.1  christos 
    649      1.1  christos 
    650      1.1  christos /* <string> ... */
    651      1.1  christos 
    652      1.1  christos static void
    653      1.1  christos parse_string_property (struct hw *current,
    654      1.1  christos 		       const char *property_name,
    655      1.1  christos 		       const char *property_value)
    656      1.1  christos {
    657      1.1  christos   char **strings;
    658      1.1  christos   const char *chp;
    659      1.1  christos   int nr_strings;
    660      1.1  christos   int approx_nr_strings;
    661      1.1  christos 
    662      1.1  christos   /* get an estimate as to the number of strings by counting double
    663      1.1  christos      quotes */
    664      1.1  christos   approx_nr_strings = 2;
    665      1.1  christos   for (chp = property_value; *chp; chp++)
    666      1.1  christos     {
    667      1.1  christos       if (*chp == '"')
    668      1.1  christos 	approx_nr_strings++;
    669      1.1  christos     }
    670      1.1  christos   approx_nr_strings = (approx_nr_strings) / 2;
    671      1.1  christos 
    672      1.1  christos   /* create a string buffer for that many (plus a null) */
    673      1.1  christos   strings = (char**) zalloc ((approx_nr_strings + 1) * sizeof (char*));
    674      1.1  christos 
    675      1.1  christos   /* now find all the strings */
    676      1.1  christos   chp = property_value;
    677      1.1  christos   nr_strings = 0;
    678      1.1  christos   while (1)
    679      1.1  christos     {
    680      1.1  christos 
    681      1.1  christos       /* skip leading space */
    682      1.1  christos       while (*chp != '\0' && isspace (*chp))
    683      1.1  christos 	chp += 1;
    684      1.1  christos       if (*chp == '\0')
    685      1.1  christos 	break;
    686      1.1  christos 
    687      1.1  christos       /* copy it in */
    688      1.1  christos       if (*chp == '"')
    689      1.1  christos 	{
    690      1.1  christos 	  /* a quoted string - watch for '\' et al. */
    691      1.1  christos 	  /* estimate the size and allocate space for it */
    692      1.1  christos 	  int pos;
    693      1.1  christos 	  chp++;
    694      1.1  christos 	  pos = 0;
    695      1.1  christos 	  while (chp[pos] != '\0' && chp[pos] != '"')
    696      1.1  christos 	    {
    697      1.1  christos 	      if (chp[pos] == '\\' && chp[pos+1] != '\0')
    698      1.1  christos 		pos += 2;
    699      1.1  christos 	      else
    700      1.1  christos 		pos += 1;
    701      1.1  christos 	    }
    702      1.1  christos 	  strings[nr_strings] = zalloc (pos + 1);
    703      1.1  christos 	  /* copy the string over */
    704      1.1  christos 	  pos = 0;
    705      1.1  christos 	  while (*chp != '\0' && *chp != '"')
    706      1.1  christos 	    {
    707      1.1  christos 	      if (*chp == '\\' && *(chp+1) != '\0')
    708      1.1  christos 		{
    709      1.1  christos 		  strings[nr_strings][pos] = *(chp+1);
    710      1.1  christos 		  chp += 2;
    711      1.1  christos 		  pos++;
    712      1.1  christos 		}
    713      1.1  christos 	      else
    714      1.1  christos 		{
    715      1.1  christos 		  strings[nr_strings][pos] = *chp;
    716      1.1  christos 		  chp += 1;
    717      1.1  christos 		  pos++;
    718      1.1  christos 		}
    719      1.1  christos 	    }
    720      1.1  christos 	  if (*chp != '\0')
    721      1.1  christos 	    chp++;
    722      1.1  christos 	  strings[nr_strings][pos] = '\0';
    723      1.1  christos 	}
    724      1.1  christos       else
    725      1.1  christos 	{
    726      1.1  christos 	  /* copy over a single unquoted token */
    727      1.1  christos 	  int len = 0;
    728      1.1  christos 	  while (chp[len] != '\0' && !isspace (chp[len]))
    729      1.1  christos 	    len++;
    730      1.1  christos 	  strings[nr_strings] = zalloc (len + 1);
    731      1.1  christos 	  strncpy (strings[nr_strings], chp, len);
    732      1.1  christos 	  strings[nr_strings][len] = '\0';
    733      1.1  christos 	  chp += len;
    734      1.1  christos 	}
    735      1.1  christos       nr_strings++;
    736      1.1  christos       if (nr_strings > approx_nr_strings)
    737      1.1  christos 	hw_abort (current, "String property %s badly formatted",
    738      1.1  christos 		  property_name);
    739      1.1  christos     }
    740      1.1  christos   ASSERT (strings[nr_strings] == NULL); /* from zalloc */
    741      1.1  christos 
    742      1.1  christos   /* install it */
    743      1.1  christos   if (nr_strings == 0)
    744      1.1  christos     hw_add_string_property (current, property_name, "");
    745      1.1  christos   else if (nr_strings == 1)
    746      1.1  christos     hw_add_string_property (current, property_name, strings[0]);
    747      1.1  christos   else
    748      1.1  christos     {
    749      1.1  christos       const char **specs = (const char**) strings; /* stop a bogus error */
    750      1.1  christos       hw_add_string_array_property (current, property_name,
    751      1.1  christos 				    specs, nr_strings);
    752      1.1  christos     }
    753      1.1  christos 
    754      1.1  christos   /* flush the created string */
    755      1.1  christos   while (nr_strings > 0)
    756      1.1  christos     {
    757      1.1  christos       nr_strings--;
    758      1.1  christos       free (strings[nr_strings]);
    759      1.1  christos     }
    760      1.1  christos   free (strings);
    761      1.1  christos }
    762      1.1  christos 
    763      1.1  christos 
    764      1.1  christos /* <path-to-ihandle-device> */
    765      1.1  christos 
    766      1.1  christos #if NOT_YET
    767      1.1  christos static void
    768      1.1  christos parse_ihandle_property (struct hw *current,
    769      1.1  christos 			const char *property,
    770      1.1  christos 			const char *value)
    771      1.1  christos {
    772      1.1  christos   ihandle_runtime_property_spec ihandle;
    773      1.1  christos 
    774      1.1  christos   /* pass the full path */
    775      1.1  christos   ihandle.full_path = value;
    776      1.1  christos 
    777      1.1  christos   /* save this ready for the ihandle create */
    778      1.1  christos   hw_add_ihandle_runtime_property (current, property,
    779      1.1  christos 				   &ihandle);
    780      1.1  christos }
    781      1.1  christos #endif
    782      1.1  christos 
    783      1.1  christos 
    784      1.1  christos struct hw *
    785      1.1  christos hw_tree_create (SIM_DESC sd,
    786      1.1  christos 		const char *family)
    787      1.1  christos {
    788      1.1  christos   return hw_create (sd, NULL, family, family, NULL, NULL);
    789      1.1  christos }
    790      1.1  christos 
    791      1.1  christos void
    792      1.1  christos hw_tree_delete (struct hw *me)
    793      1.1  christos {
    794      1.1  christos   /* Need to allow devices to disapear under our feet */
    795      1.1  christos   while (hw_child (me) != NULL)
    796      1.1  christos     {
    797      1.1  christos       hw_tree_delete (hw_child (me));
    798      1.1  christos     }
    799      1.1  christos   hw_delete (me);
    800      1.1  christos }
    801      1.1  christos 
    802      1.1  christos 
    803      1.1  christos struct hw *
    804      1.1  christos hw_tree_parse (struct hw *current,
    805      1.1  christos 	       const char *fmt,
    806      1.1  christos 	       ...)
    807      1.1  christos {
    808      1.1  christos     va_list ap;
    809      1.1  christos     va_start (ap, fmt);
    810      1.1  christos     current = hw_tree_vparse (current, fmt, ap);
    811      1.1  christos     va_end (ap);
    812      1.1  christos     return current;
    813      1.1  christos }
    814      1.1  christos 
    815      1.1  christos struct hw *
    816      1.1  christos hw_tree_vparse (struct hw *current,
    817      1.1  christos 		const char *fmt,
    818      1.1  christos 		va_list ap)
    819      1.1  christos {
    820      1.1  christos   char device_specifier[1024];
    821      1.1  christos   name_specifier spec;
    822      1.1  christos 
    823      1.1  christos   /* format the path */
    824      1.1  christos   vsprintf (device_specifier, fmt, ap);
    825      1.1  christos   if (strlen (device_specifier) >= sizeof (device_specifier))
    826      1.1  christos     hw_abort (NULL, "device_tree_add_deviced: buffer overflow\n");
    827      1.1  christos 
    828      1.1  christos   /* construct the tree down to the final struct hw */
    829      1.1  christos   current = split_fill_path (current, device_specifier, &spec);
    830      1.1  christos 
    831      1.1  christos   /* is there an interrupt spec */
    832      1.1  christos   if (spec.property == NULL
    833      1.1  christos       && spec.value != NULL)
    834      1.1  christos     {
    835      1.1  christos       char *op = split_value (&spec);
    836      1.1  christos       switch (op[0])
    837      1.1  christos 	{
    838      1.1  christos 	case '>':
    839      1.1  christos 	  {
    840      1.1  christos 	    char *my_port_name = split_value (&spec);
    841      1.1  christos 	    int my_port;
    842      1.1  christos 	    char *dest_port_name = split_value (&spec);
    843      1.1  christos 	    int dest_port;
    844      1.1  christos 	    name_specifier dest_spec;
    845      1.1  christos 	    char *dest_hw_name = split_value (&spec);
    846      1.1  christos 	    struct hw *dest;
    847      1.1  christos 	    /* find my name */
    848      1.1  christos 	    if (!hw_finished_p (current))
    849      1.1  christos 	      hw_finish (current);
    850      1.1  christos 	    my_port = hw_port_decode (current, my_port_name, output_port);
    851      1.1  christos 	    /* find the dest device and port */
    852      1.1  christos 	    dest = split_fill_path (current, dest_hw_name, &dest_spec);
    853      1.1  christos 	    if (!hw_finished_p (dest))
    854      1.1  christos 	      hw_finish (dest);
    855      1.1  christos 	    dest_port = hw_port_decode (dest, dest_port_name,
    856      1.1  christos 					input_port);
    857      1.1  christos 	    /* connect the two */
    858      1.1  christos 	    hw_port_attach (current,
    859      1.1  christos 			    my_port,
    860      1.1  christos 			    dest,
    861      1.1  christos 			    dest_port,
    862      1.1  christos 			    permenant_object);
    863      1.1  christos 	    break;
    864      1.1  christos 	  }
    865      1.1  christos 	default:
    866      1.1  christos 	  hw_abort (current, "unreconised interrupt spec %s\n", spec.value);
    867      1.1  christos 	  break;
    868      1.1  christos 	}
    869      1.1  christos     }
    870      1.1  christos 
    871      1.1  christos   /* is there a property */
    872      1.1  christos   if (spec.property != NULL)
    873      1.1  christos     {
    874      1.1  christos       if (strcmp (spec.value, "true") == 0)
    875      1.1  christos 	hw_add_boolean_property (current, spec.property, 1);
    876      1.1  christos       else if (strcmp (spec.value, "false") == 0)
    877      1.1  christos 	hw_add_boolean_property (current, spec.property, 0);
    878      1.1  christos       else
    879      1.1  christos 	{
    880      1.1  christos 	  const struct hw_property *property;
    881      1.1  christos 	  switch (spec.value[0])
    882      1.1  christos 	    {
    883      1.1  christos #if NOT_YET
    884      1.1  christos 	    case '*':
    885      1.1  christos 	      {
    886      1.1  christos 		parse_ihandle_property (current, spec.property, spec.value + 1);
    887      1.1  christos 		break;
    888      1.1  christos 	      }
    889      1.1  christos #endif
    890      1.1  christos 	    case '[':
    891      1.1  christos 	      {
    892      1.1  christos 		unsigned8 words[1024];
    893      1.1  christos 		char *curr = spec.value + 1;
    894      1.1  christos 		int nr_words = 0;
    895      1.1  christos 		while (1)
    896      1.1  christos 		  {
    897      1.1  christos 		    char *next;
    898      1.1  christos 		    words[nr_words] = H2BE_1 (strtoul (curr, &next, 0));
    899      1.1  christos 		    if (curr == next)
    900      1.1  christos 		      break;
    901      1.1  christos 		    curr = next;
    902      1.1  christos 		    nr_words += 1;
    903      1.1  christos 		  }
    904      1.1  christos 		hw_add_array_property (current, spec.property,
    905      1.1  christos 				       words, sizeof (words[0]) * nr_words);
    906      1.1  christos 		break;
    907      1.1  christos 	      }
    908      1.1  christos 	    case '"':
    909      1.1  christos 	      {
    910      1.1  christos 		parse_string_property (current, spec.property, spec.value);
    911      1.1  christos 		break;
    912      1.1  christos 	      }
    913      1.1  christos 	    case '!':
    914      1.1  christos 	      {
    915      1.1  christos 		spec.value++;
    916      1.1  christos 		property = hw_tree_find_property (current, spec.value);
    917      1.1  christos 		if (property == NULL)
    918      1.1  christos 		  hw_abort (current, "property %s not found\n", spec.value);
    919      1.1  christos 		hw_add_duplicate_property (current,
    920      1.1  christos 					   spec.property,
    921      1.1  christos 					   property);
    922      1.1  christos 		break;
    923      1.1  christos 	      }
    924      1.1  christos 	    default:
    925      1.1  christos 	      {
    926      1.1  christos 		if (strcmp (spec.property, "reg") == 0
    927      1.1  christos 		    || strcmp (spec.property, "assigned-addresses") == 0
    928      1.1  christos 		    || strcmp (spec.property, "alternate-reg") == 0)
    929      1.1  christos 		  {
    930      1.1  christos 		    parse_reg_property (current, spec.property, spec.value);
    931      1.1  christos 		  }
    932      1.1  christos 		else if (strcmp (spec.property, "ranges") == 0)
    933      1.1  christos 		  {
    934      1.1  christos 		    parse_ranges_property (current, spec.property, spec.value);
    935      1.1  christos 		  }
    936      1.1  christos 		else if (isdigit (spec.value[0])
    937      1.1  christos 			 || (spec.value[0] == '-' && isdigit (spec.value[1]))
    938      1.1  christos 			 || (spec.value[0] == '+' && isdigit (spec.value[1])))
    939      1.1  christos 		  {
    940      1.1  christos 		    parse_integer_property (current, spec.property, spec.value);
    941      1.1  christos 		  }
    942      1.1  christos 		else
    943      1.1  christos 		  parse_string_property (current, spec.property, spec.value);
    944      1.1  christos 		break;
    945      1.1  christos 	      }
    946      1.1  christos 	    }
    947      1.1  christos 	}
    948      1.1  christos     }
    949      1.1  christos   return current;
    950      1.1  christos }
    951      1.1  christos 
    952      1.1  christos 
    953      1.1  christos static void
    954      1.1  christos finish_hw_tree (struct hw *me,
    955      1.1  christos 		void *data)
    956      1.1  christos {
    957      1.1  christos   if (!hw_finished_p (me))
    958      1.1  christos     hw_finish (me);
    959      1.1  christos }
    960      1.1  christos 
    961      1.1  christos void
    962      1.1  christos hw_tree_finish (struct hw *root)
    963      1.1  christos {
    964      1.1  christos   hw_tree_traverse (root, finish_hw_tree, NULL, NULL);
    965      1.1  christos }
    966      1.1  christos 
    967      1.1  christos 
    968      1.1  christos 
    969      1.1  christos void
    970      1.1  christos hw_tree_traverse (struct hw *root,
    971      1.1  christos 		  hw_tree_traverse_function *prefix,
    972      1.1  christos 		  hw_tree_traverse_function *postfix,
    973      1.1  christos 		  void *data)
    974      1.1  christos {
    975      1.1  christos   struct hw *child;
    976      1.1  christos   if (prefix != NULL)
    977      1.1  christos     prefix (root, data);
    978      1.1  christos   for (child = hw_child (root);
    979      1.1  christos        child != NULL;
    980      1.1  christos        child = hw_sibling (child))
    981      1.1  christos     {
    982      1.1  christos       hw_tree_traverse (child, prefix, postfix, data);
    983      1.1  christos     }
    984      1.1  christos   if (postfix != NULL)
    985      1.1  christos     postfix (root, data);
    986      1.1  christos }
    987      1.1  christos 
    988      1.1  christos 
    989      1.1  christos 
    990      1.1  christos struct printer
    992      1.1  christos {
    993      1.1  christos   hw_tree_print_callback *print;
    994      1.1  christos   void *file;
    995      1.1  christos };
    996      1.1  christos 
    997      1.1  christos static void
    998      1.1  christos print_address (struct hw *bus,
    999      1.1  christos 	       const hw_unit *phys,
   1000      1.1  christos 	       struct printer *p)
   1001      1.1  christos {
   1002      1.1  christos   char unit[32];
   1003      1.1  christos   hw_unit_encode (bus, phys, unit, sizeof (unit));
   1004      1.1  christos   p->print (p->file, " %s", unit);
   1005      1.1  christos }
   1006      1.1  christos 
   1007      1.1  christos static void
   1008      1.1  christos print_size (struct hw *bus,
   1009      1.1  christos 	    const hw_unit *size,
   1010      1.1  christos 	    struct printer *p)
   1011      1.1  christos {
   1012      1.1  christos   int i;
   1013      1.1  christos   for (i = 0; i < size->nr_cells; i++)
   1014      1.1  christos     if (size->cells[i] != 0)
   1015      1.1  christos       break;
   1016      1.1  christos   if (i < size->nr_cells)
   1017      1.1  christos     {
   1018      1.1  christos       p->print (p->file, " 0x%lx", (unsigned long) size->cells[i]);
   1019      1.1  christos       i++;
   1020      1.1  christos       for (; i < size->nr_cells; i++)
   1021      1.1  christos 	p->print (p->file, ",0x%lx", (unsigned long) size->cells[i]);
   1022      1.1  christos     }
   1023      1.1  christos   else
   1024      1.1  christos     p->print (p->file, " 0");
   1025      1.1  christos }
   1026      1.1  christos 
   1027      1.1  christos static void
   1028      1.1  christos print_reg_property (struct hw *me,
   1029      1.1  christos 		    const struct hw_property *property,
   1030      1.1  christos 		    struct printer *p)
   1031      1.1  christos {
   1032      1.1  christos   int reg_nr;
   1033      1.1  christos   reg_property_spec reg;
   1034      1.1  christos   for (reg_nr = 0;
   1035      1.1  christos        hw_find_reg_array_property (me, property->name, reg_nr, &reg);
   1036      1.1  christos        reg_nr++)
   1037      1.1  christos     {
   1038      1.1  christos       print_address (hw_parent (me), &reg.address, p);
   1039      1.1  christos       print_size (me, &reg.size, p);
   1040      1.1  christos     }
   1041      1.1  christos }
   1042      1.1  christos 
   1043      1.1  christos static void
   1044      1.1  christos print_ranges_property (struct hw *me,
   1045      1.1  christos 		       const struct hw_property *property,
   1046      1.1  christos 		       struct printer *p)
   1047      1.1  christos {
   1048      1.1  christos   int range_nr;
   1049      1.1  christos   range_property_spec range;
   1050      1.1  christos   for (range_nr = 0;
   1051      1.1  christos        hw_find_range_array_property (me, property->name, range_nr, &range);
   1052      1.1  christos        range_nr++)
   1053      1.1  christos     {
   1054      1.1  christos       print_address (me, &range.child_address, p);
   1055      1.1  christos       print_address (hw_parent (me), &range.parent_address, p);
   1056      1.1  christos       print_size (me, &range.size, p);
   1057      1.1  christos     }
   1058      1.1  christos }
   1059      1.1  christos 
   1060      1.1  christos static void
   1061      1.1  christos print_string (struct hw *me,
   1062      1.1  christos 	      const char *string,
   1063      1.1  christos 	      struct printer *p)
   1064      1.1  christos {
   1065      1.1  christos   p->print (p->file, " \"");
   1066      1.1  christos   while (*string != '\0')
   1067      1.1  christos     {
   1068      1.1  christos       switch (*string)
   1069      1.1  christos 	{
   1070      1.1  christos 	case '"':
   1071      1.1  christos 	  p->print (p->file, "\\\"");
   1072      1.1  christos 	  break;
   1073      1.1  christos 	case '\\':
   1074      1.1  christos 	  p->print (p->file, "\\\\");
   1075      1.1  christos 	  break;
   1076      1.1  christos 	default:
   1077      1.1  christos 	  p->print (p->file, "%c", *string);
   1078      1.1  christos 	  break;
   1079      1.1  christos 	}
   1080      1.1  christos       string++;
   1081      1.1  christos     }
   1082      1.1  christos   p->print (p->file, "\"");
   1083      1.1  christos }
   1084      1.1  christos 
   1085      1.1  christos static void
   1086      1.1  christos print_string_array_property (struct hw *me,
   1087      1.1  christos 			     const struct hw_property *property,
   1088      1.1  christos 			     struct printer *p)
   1089      1.1  christos {
   1090      1.1  christos   int nr;
   1091      1.1  christos   string_property_spec string;
   1092      1.1  christos   for (nr = 0;
   1093      1.1  christos        hw_find_string_array_property (me, property->name, nr, &string);
   1094      1.1  christos        nr++)
   1095      1.1  christos     {
   1096      1.1  christos       print_string (me, string, p);
   1097      1.1  christos     }
   1098      1.1  christos }
   1099      1.1  christos 
   1100      1.1  christos static void
   1101      1.1  christos print_properties (struct hw *me,
   1102      1.1  christos 		  struct printer *p)
   1103      1.1  christos {
   1104      1.1  christos   const struct hw_property *property;
   1105      1.1  christos   for (property = hw_find_property (me, NULL);
   1106      1.1  christos        property != NULL;
   1107      1.1  christos        property = hw_next_property (property))
   1108      1.1  christos     {
   1109      1.1  christos       if (hw_parent (me) == NULL)
   1110      1.1  christos 	p->print (p->file, "/%s", property->name);
   1111      1.1  christos       else
   1112      1.1  christos 	p->print (p->file, "%s/%s", hw_path (me), property->name);
   1113      1.1  christos       if (property->original != NULL)
   1114      1.1  christos 	{
   1115      1.1  christos 	  p->print (p->file, " !");
   1116      1.1  christos 	  p->print (p->file, "%s/%s",
   1117      1.1  christos 		     hw_path (property->original->owner),
   1118      1.1  christos 		     property->original->name);
   1119      1.1  christos 	}
   1120      1.1  christos       else
   1121      1.1  christos 	{
   1122      1.1  christos 	  switch (property->type)
   1123      1.1  christos 	    {
   1124      1.1  christos 	    case array_property:
   1125      1.1  christos 	      {
   1126      1.1  christos 		if ((property->sizeof_array % sizeof (signed_cell)) == 0)
   1127      1.1  christos 		  {
   1128      1.1  christos 		    unsigned_cell *w = (unsigned_cell*) property->array;
   1129      1.1  christos 		    int cell_nr;
   1130      1.1  christos 		    for (cell_nr = 0;
   1131      1.1  christos 			 cell_nr < (property->sizeof_array / sizeof (unsigned_cell));
   1132      1.1  christos 			 cell_nr++)
   1133      1.1  christos 		      {
   1134      1.1  christos 			p->print (p->file, " 0x%lx", (unsigned long) BE2H_cell (w[cell_nr]));
   1135      1.1  christos 		      }
   1136      1.1  christos 		  }
   1137      1.1  christos 		else
   1138      1.1  christos 		  {
   1139      1.1  christos 		    unsigned8 *w = (unsigned8*)property->array;
   1140      1.1  christos 		    p->print (p->file, " [");
   1141      1.1  christos 		    while ((char*)w - (char*)property->array < property->sizeof_array)
   1142      1.1  christos 		      {
   1143      1.1  christos 			p->print (p->file, " 0x%2x", BE2H_1 (*w));
   1144      1.1  christos 			w++;
   1145      1.1  christos 		      }
   1146      1.1  christos 		  }
   1147      1.1  christos 		break;
   1148      1.1  christos 	      }
   1149      1.1  christos 	    case boolean_property:
   1150      1.1  christos 	      {
   1151      1.1  christos 		int b = hw_find_boolean_property (me, property->name);
   1152      1.1  christos 		p->print (p->file, " %s", b ? "true"  : "false");
   1153      1.1  christos 		break;
   1154      1.1  christos 	      }
   1155      1.1  christos #if NOT_YET
   1156      1.1  christos 	    case ihandle_property:
   1157      1.1  christos 	      {
   1158      1.1  christos 		if (property->array != NULL)
   1159      1.1  christos 		  {
   1160      1.1  christos 		    device_instance *instance = hw_find_ihandle_property (me, property->name);
   1161      1.1  christos 		    p->print (p->file, " *%s", device_instance_path (instance));
   1162      1.1  christos 		  }
   1163      1.1  christos 		else
   1164      1.1  christos 		  {
   1165      1.1  christos 		    /* not yet initialized, ask the device for the path */
   1166      1.1  christos 		    ihandle_runtime_property_spec spec;
   1167      1.1  christos 		    hw_find_ihandle_runtime_property (me, property->name, &spec);
   1168      1.1  christos 		    p->print (p->file, " *%s", spec.full_path);
   1169      1.1  christos 		  }
   1170      1.1  christos 		break;
   1171      1.1  christos 	      }
   1172      1.1  christos #endif
   1173      1.1  christos 	    case integer_property:
   1174      1.1  christos 	      {
   1175      1.1  christos 		unsigned_word w = hw_find_integer_property (me, property->name);
   1176      1.1  christos 		p->print (p->file, " 0x%lx", (unsigned long)w);
   1177      1.1  christos 		break;
   1178      1.1  christos 	      }
   1179      1.1  christos 	    case range_array_property:
   1180      1.1  christos 	      {
   1181      1.1  christos 		print_ranges_property (me, property, p);
   1182      1.1  christos 		break;
   1183      1.1  christos 	      }
   1184      1.1  christos 	    case reg_array_property:
   1185      1.1  christos 	      {
   1186      1.1  christos 		print_reg_property (me, property, p);
   1187      1.1  christos 		break;
   1188      1.1  christos 	      }
   1189      1.1  christos 	    case string_property:
   1190      1.1  christos 	      {
   1191      1.1  christos 		const char *s = hw_find_string_property (me, property->name);
   1192      1.1  christos 		print_string (me, s, p);
   1193      1.1  christos 		break;
   1194      1.1  christos 	      }
   1195      1.1  christos 	    case string_array_property:
   1196      1.1  christos 	      {
   1197      1.1  christos 		print_string_array_property (me, property, p);
   1198      1.1  christos 		break;
   1199      1.1  christos 	      }
   1200      1.1  christos 	    }
   1201      1.1  christos 	}
   1202      1.1  christos       p->print (p->file, "\n");
   1203      1.1  christos     }
   1204      1.1  christos }
   1205      1.1  christos 
   1206      1.1  christos static void
   1207      1.1  christos print_interrupts (struct hw *me,
   1208      1.1  christos                   int my_port,
   1209      1.1  christos 		  struct hw *dest,
   1210      1.1  christos 		  int dest_port,
   1211      1.1  christos 		  void *data)
   1212      1.1  christos {
   1213      1.1  christos   struct printer *p = data;
   1214      1.1  christos   char src[32];
   1215      1.1  christos   char dst[32];
   1216      1.1  christos   hw_port_encode (me, my_port, src, sizeof (src), output_port);
   1217      1.1  christos   hw_port_encode (dest, dest_port, dst, sizeof (dst), input_port);
   1218      1.1  christos   p->print (p->file,
   1219      1.1  christos 	    "%s > %s %s %s\n",
   1220      1.1  christos 	    hw_path (me),
   1221      1.1  christos 	    src, dst,
   1222      1.1  christos 	    hw_path (dest));
   1223      1.1  christos }
   1224      1.1  christos 
   1225      1.1  christos static void
   1226      1.1  christos print_device (struct hw *me,
   1227      1.1  christos 	      void *data)
   1228      1.1  christos {
   1229      1.1  christos   struct printer *p = data;
   1230      1.1  christos   p->print (p->file, "%s\n", hw_path (me));
   1231      1.1  christos   print_properties (me, p);
   1232      1.1  christos   hw_port_traverse (me, print_interrupts, data);
   1233      1.1  christos }
   1234      1.1  christos 
   1235      1.1  christos void
   1236      1.1  christos hw_tree_print (struct hw *root,
   1237      1.1  christos 	       hw_tree_print_callback *print,
   1238      1.1  christos 	       void *file)
   1239      1.1  christos {
   1240      1.1  christos   struct printer p;
   1241      1.1  christos   p.print = print;
   1242      1.1  christos   p.file = file;
   1243      1.1  christos   hw_tree_traverse (root,
   1244      1.1  christos 		    print_device, NULL,
   1245      1.1  christos 		    &p);
   1246      1.1  christos }
   1247      1.1  christos 
   1248      1.1  christos 
   1249      1.1  christos 
   1250      1.1  christos #if NOT_YET
   1252      1.1  christos device_instance *
   1253      1.1  christos tree_instance (struct hw *root,
   1254      1.1  christos 	       const char *device_specifier)
   1255      1.1  christos {
   1256      1.1  christos   /* find the device node */
   1257      1.1  christos   struct hw *me;
   1258      1.1  christos   name_specifier spec;
   1259      1.1  christos   if (!split_device_specifier (root, device_specifier, &spec))
   1260      1.1  christos     return NULL;
   1261      1.1  christos   me = split_find_device (root, &spec);
   1262      1.1  christos   if (spec.name != NULL)
   1263      1.1  christos     return NULL;
   1264      1.1  christos   /* create the instance */
   1265      1.1  christos   return device_create_instance (me, device_specifier, spec.last_args);
   1266      1.1  christos }
   1267      1.1  christos #endif
   1268      1.1  christos 
   1269      1.1  christos struct hw *
   1270      1.1  christos hw_tree_find_device (struct hw *root,
   1271      1.1  christos 		     const char *path_to_device)
   1272      1.1  christos {
   1273      1.1  christos   struct hw *node;
   1274      1.1  christos   name_specifier spec;
   1275      1.1  christos 
   1276      1.1  christos   /* parse the path */
   1277      1.1  christos   split_device_specifier (root, path_to_device, &spec);
   1278      1.1  christos   if (spec.value != NULL)
   1279      1.1  christos     return NULL; /* something wierd */
   1280      1.1  christos 
   1281      1.1  christos   /* now find it */
   1282      1.1  christos   node = split_find_device (root, &spec);
   1283      1.1  christos   if (spec.name != NULL)
   1284      1.1  christos     return NULL; /* not a leaf */
   1285      1.1  christos 
   1286      1.1  christos   return node;
   1287      1.1  christos }
   1288      1.1  christos 
   1289      1.1  christos 
   1290      1.1  christos const struct hw_property *
   1291      1.1  christos hw_tree_find_property (struct hw *root,
   1292      1.1  christos 		       const char *path_to_property)
   1293      1.1  christos {
   1294      1.1  christos   name_specifier spec;
   1295      1.1  christos   if (!split_property_specifier (root, path_to_property, &spec))
   1296      1.1  christos     hw_abort (root, "Invalid property path %s", path_to_property);
   1297      1.1  christos   root = split_find_device (root, &spec);
   1298      1.1  christos   if (spec.name != NULL)
   1299      1.1  christos     return NULL; /* not a leaf */
   1300      1.1  christos   return hw_find_property (root, spec.property);
   1301      1.1  christos }
   1302      1.1  christos 
   1303      1.1  christos int
   1304      1.1  christos hw_tree_find_boolean_property (struct hw *root,
   1305      1.1  christos 			       const char *path_to_property)
   1306      1.1  christos {
   1307      1.1  christos   name_specifier spec;
   1308      1.1  christos   if (!split_property_specifier (root, path_to_property, &spec))
   1309      1.1  christos     hw_abort (root, "Invalid property path %s", path_to_property);
   1310      1.1  christos   root = split_find_device (root, &spec);
   1311      1.1  christos   if (spec.name != NULL)
   1312      1.1  christos     hw_abort (root, "device \"%s\" not found (property \"%s\")",
   1313      1.1  christos 	      spec.name, path_to_property);
   1314      1.1  christos   return hw_find_boolean_property (root, spec.property);
   1315      1.1  christos }
   1316      1.1  christos 
   1317      1.1  christos signed_cell
   1318      1.1  christos hw_tree_find_integer_property (struct hw *root,
   1319      1.1  christos 			       const char *path_to_property)
   1320      1.1  christos {
   1321      1.1  christos   name_specifier spec;
   1322      1.1  christos   if (!split_property_specifier (root, path_to_property, &spec))
   1323      1.1  christos     hw_abort (root, "Invalid property path %s", path_to_property);
   1324      1.1  christos   root = split_find_device (root, &spec);
   1325      1.1  christos   if (spec.name != NULL)
   1326      1.1  christos     hw_abort (root, "device \"%s\" not found (property \"%s\")",
   1327      1.1  christos 	      spec.name, path_to_property);
   1328      1.1  christos   return hw_find_integer_property (root, spec.property);
   1329      1.1  christos }
   1330      1.1  christos 
   1331      1.1  christos #if NOT_YET
   1332      1.1  christos device_instance *
   1333      1.1  christos hw_tree_find_ihandle_property (struct hw *root,
   1334      1.1  christos 			       const char *path_to_property)
   1335      1.1  christos {
   1336      1.1  christos   struct hw *root;
   1337      1.1  christos   name_specifier spec;
   1338      1.1  christos   if (!split_property_specifier (root, path_to_property, &spec))
   1339      1.1  christos     hw_abort (root, "Invalid property path %s", path_to_property);
   1340      1.1  christos   root = split_find_device (root, &spec);
   1341      1.1  christos   if (spec.name != NULL)
   1342      1.1  christos     hw_abort (root, "device \"%s\" not found (property \"%s\")",
   1343      1.1  christos 	      spec.name, path_to_property);
   1344      1.1  christos   return hw_find_ihandle_property (root, spec.property);
   1345      1.1  christos }
   1346      1.1  christos #endif
   1347      1.1  christos 
   1348      1.1  christos const char *
   1349      1.1  christos hw_tree_find_string_property (struct hw *root,
   1350      1.1  christos 			      const char *path_to_property)
   1351      1.1  christos {
   1352      1.1  christos   name_specifier spec;
   1353      1.1  christos   if (!split_property_specifier (root, path_to_property, &spec))
   1354      1.1  christos     hw_abort (root, "Invalid property path %s", path_to_property);
   1355      1.1  christos   root = split_find_device (root, &spec);
   1356      1.1  christos   if (spec.name != NULL)
   1357      1.1  christos     hw_abort (root, "device \"%s\" not found (property \"%s\")",
   1358                    	      spec.name, path_to_property);
   1359                      return hw_find_string_property (root, spec.property);
   1360                    }
   1361