ia64/xen-unstable

changeset 1702:c16292056099

bitkeeper revision 1.1041.15.1 (40ebc943G6NlOlbW-3EGaR3sQs14kQ)

Revert 1.1051.4.1 (s-expression parser changes).
author kaf24@scramble.cl.cam.ac.uk
date Wed Jul 07 09:58:27 2004 +0000 (2004-07-07)
parents b8ad289cb612
children 1a6a93fdeafc
files tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xend/XendRoot.py tools/python/xen/xend/sxp.py tools/python/xen/xm/main.py
line diff
     1.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Tue Jul 06 20:42:40 2004 +0000
     1.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Wed Jul 07 09:58:27 2004 +0000
     1.3 @@ -292,9 +292,6 @@ def vm_restore(src, progress=0):
     1.4      if dom < 0:
     1.5          raise VmError('restore failed')
     1.6      vmconfig = sxp.from_string(d['vmconfig'])
     1.7 -    if not vmconfig:
     1.8 -        raise VmError('bad vmconfig s-expression')
     1.9 -    vmconfig = vmconfig[0]
    1.10      vm.config = sxp.child_value(vmconfig, 'config')
    1.11      deferred = vm.dom_configure(dom)
    1.12      def vifs_cb(val, vm):
    1.13 @@ -423,8 +420,8 @@ class XendDomainInfo:
    1.14          self.config = config
    1.15          try:
    1.16              self.name = sxp.child_value(config, 'name')
    1.17 -            self.memory = int(sxp.child_value(config, 'memory') or '128')
    1.18 -            if sxp.child(config, 'autorestart'):
    1.19 +            self.memory = int(sxp.child_value(config, 'memory', '128'))
    1.20 +            if sxp.child(config, 'autorestart', None):
    1.21                  self.autorestart = 1
    1.22              self.configure_backends()
    1.23              image = sxp.child_value(config, 'image')
    1.24 @@ -457,7 +454,7 @@ class XendDomainInfo:
    1.25          """
    1.26          devices = []
    1.27          for d in sxp.children(self.config, 'device'):
    1.28 -            dev = sxp.child(d)
    1.29 +            dev = sxp.child0(d)
    1.30              if dev is None: continue
    1.31              if name == sxp.name(dev):
    1.32                  devices.append(dev)
    1.33 @@ -588,7 +585,7 @@ class XendDomainInfo:
    1.34          if self.recreate: return
    1.35          memory = self.memory
    1.36          name = self.name
    1.37 -        cpu = int(sxp.child_value(self.config, 'cpu') or '-1')
    1.38 +        cpu = int(sxp.child_value(self.config, 'cpu', '-1'))
    1.39          print 'init_domain>', memory, name, cpu
    1.40          dom = xc.domain_create(mem_kb= memory * 1024, name= name, cpu= cpu)
    1.41          if dom <= 0:
    1.42 @@ -653,7 +650,7 @@ class XendDomainInfo:
    1.43          devices = sxp.children(self.config, 'device')
    1.44          index = {}
    1.45          for d in devices:
    1.46 -            dev = sxp.child(d)
    1.47 +            dev = sxp.child0(d)
    1.48              if dev is None:
    1.49                  raise VmError('invalid device')
    1.50              dev_name = sxp.name(dev)
    1.51 @@ -672,7 +669,7 @@ class XendDomainInfo:
    1.52          """Set configuration flags if the vm is a backend for netif of blkif.
    1.53          """
    1.54          for c in sxp.children(self.config, 'backend'):
    1.55 -            name = sxp.name(sxp.child(c))
    1.56 +            name = sxp.name(sxp.child0(c))
    1.57              if name == 'blkif':
    1.58                  self.blkif_backend = 1
    1.59              elif name == 'netif':
    1.60 @@ -754,7 +751,7 @@ def vm_image_linux(vm, image):
    1.61      """
    1.62      kernel = sxp.child_value(image, "kernel")
    1.63      cmdline = ""
    1.64 -    ip = sxp.child_value(image, "ip") or "dhcp"
    1.65 +    ip = sxp.child_value(image, "ip", "dhcp")
    1.66      if ip:
    1.67          cmdline += " ip=" + ip
    1.68      root = sxp.child_value(image, "root")
    1.69 @@ -763,7 +760,7 @@ def vm_image_linux(vm, image):
    1.70      args = sxp.child_value(image, "args")
    1.71      if args:
    1.72          cmdline += " " + args
    1.73 -    ramdisk = sxp.child_value(image, "ramdisk") or ''
    1.74 +    ramdisk = sxp.child_value(image, "ramdisk", '')
    1.75      vifs = vm.config_devices("vif")
    1.76      vm.create_domain("linux", kernel, ramdisk, cmdline, len(vifs))
    1.77      return vm
    1.78 @@ -780,7 +777,7 @@ def vm_image_netbsd(vm, image):
    1.79      #todo: Same as for linux. Is that right? If so can unify them.
    1.80      kernel = sxp.child_value(image, "kernel")
    1.81      cmdline = ""
    1.82 -    ip = sxp.child_value(image, "ip") or "dhcp"
    1.83 +    ip = sxp.child_value(image, "ip", "dhcp")
    1.84      if ip:
    1.85          cmdline += "ip=" + ip
    1.86      root = sxp.child_value(image, "root")
    1.87 @@ -809,7 +806,7 @@ def vm_dev_vif(vm, val, index):
    1.88      defer = make_vif(vm.dom, vif, vmac, vm.recreate)
    1.89      def fn(id):
    1.90          dev = xend.netif_dev(vm.dom, vif)
    1.91 -        devid = sxp.child_value(val, 'id')
    1.92 +        devid = sxp.attribute(val, 'id')
    1.93          if devid:
    1.94              dev.setprop('id', devid)
    1.95          bridge = sxp.child_value(val, "bridge")
    1.96 @@ -836,7 +833,7 @@ def vm_dev_vbd(vm, val, index):
    1.97      dev = sxp.child_value(val, 'dev')
    1.98      if not dev:
    1.99          raise VmError('vbd: Missing dev')
   1.100 -    mode = sxp.child_value(val, 'mode') or 'r'
   1.101 +    mode = sxp.child_value(val, 'mode', 'r')
   1.102      defer = make_disk(vm.dom, uname, dev, mode, vm.recreate)
   1.103      def fn(vbd):
   1.104          dev = xend.blkif_dev(vm.dom, vdev)
   1.105 @@ -938,7 +935,7 @@ def vm_field_vnet(vm, config, val, index
   1.106          if id is None:
   1.107              raise VmError('vnet: missing vif id')
   1.108          dev = vm.get_device_by_id('vif', id)
   1.109 -        #vnet = sxp.child_value(v, 'vnet') or '1'
   1.110 +        #vnet = sxp.child_value(v, 'vnet', 1)
   1.111          #mac = sxp.child_value(dev, 'mac')
   1.112          #vif = sxp.child_value(dev, 'vif')
   1.113          #vnet_bridge(vnet, mac, vm.dom, 0)
     2.1 --- a/tools/python/xen/xend/XendRoot.py	Tue Jul 06 20:42:40 2004 +0000
     2.2 +++ b/tools/python/xen/xend/XendRoot.py	Wed Jul 07 09:58:27 2004 +0000
     2.3 @@ -145,7 +145,7 @@ class XendRoot:
     2.4          val	default value (optional, defaults to None)
     2.5          returns value
     2.6          """
     2.7 -        return sxp.child_value(self.config, name) or val
     2.8 +        return sxp.child_value(self.config, name, val=val)
     2.9  
    2.10  def instance():
    2.11      global inst
     3.1 --- a/tools/python/xen/xend/sxp.py	Tue Jul 06 20:42:40 2004 +0000
     3.2 +++ b/tools/python/xen/xend/sxp.py	Wed Jul 07 09:58:27 2004 +0000
     3.3 @@ -21,19 +21,56 @@ from StringIO import StringIO
     3.4  __all__ = [
     3.5      "mime_type", 
     3.6      "ParseError", 
     3.7 -    "Parser",
     3.8 -    "show",
     3.9 +    "Parser", 
    3.10 +    "atomp", 
    3.11 +    "show", 
    3.12 +    "show_xml", 
    3.13 +    "elementp", 
    3.14      "name", 
    3.15 +    "attributes", 
    3.16 +    "attribute", 
    3.17      "children", 
    3.18      "child", 
    3.19 +    "child_at", 
    3.20 +    "child0", 
    3.21 +    "child1", 
    3.22 +    "child2", 
    3.23 +    "child3", 
    3.24 +    "child4", 
    3.25      "child_value",
    3.26 +    "has_id", 
    3.27 +    "with_id", 
    3.28 +    "child_with_id", 
    3.29 +    "elements", 
    3.30      "to_string",
    3.31      "from_string",
    3.32 +    "all_from_string",
    3.33      "parse", 
    3.34      ]
    3.35  
    3.36  mime_type = "application/sxp"
    3.37  
    3.38 +escapes = {
    3.39 +    'a': '\a',
    3.40 +    'b': '\b',
    3.41 +    't': '\t',
    3.42 +    'n': '\n',
    3.43 +    'v': '\v',
    3.44 +    'f': '\f',
    3.45 +    'r': '\r',
    3.46 +    '\\': '\\',
    3.47 +    '\'': '\'',
    3.48 +    '\"': '\"'}
    3.49 +
    3.50 +k_list_open  = "("
    3.51 +k_list_close = ")"
    3.52 +k_attr_open  = "@"
    3.53 +k_eval       = "!"
    3.54 +
    3.55 +escapes_rev = {}
    3.56 +for k in escapes:
    3.57 +    escapes_rev[escapes[k]] = k
    3.58 +
    3.59  class ParseError(StandardError):
    3.60  
    3.61      def __init__(self, parser, value):
    3.62 @@ -49,6 +86,7 @@ class ParserState:
    3.63          self.parent = parent
    3.64          self.buf = ''
    3.65          self.val = []
    3.66 +        self.delim = None
    3.67          self.fn = fn
    3.68  
    3.69      def push(self, fn):
    3.70 @@ -57,19 +95,28 @@ class ParserState:
    3.71  class Parser:
    3.72  
    3.73      def __init__(self):
    3.74 +        self.error = sys.stderr
    3.75          self.reset()
    3.76  
    3.77      def reset(self):
    3.78 +        self.val = []
    3.79          self.eof = 0
    3.80 +        self.err = 0
    3.81          self.line_no = 0
    3.82          self.char_no = 0
    3.83 -        self.state = self.start_state = ParserState(self.state_start)
    3.84 +        self.state = None
    3.85  
    3.86      def push_state(self, fn):
    3.87          self.state = self.state.push(fn)
    3.88  
    3.89      def pop_state(self):
    3.90 +        val = self.state
    3.91          self.state = self.state.parent
    3.92 +        if self.state and self.state.fn == self.state_start:
    3.93 +            # Return to start state - produce the value.
    3.94 +            self.val += self.state.val
    3.95 +            self.state.val = []
    3.96 +        return val
    3.97  
    3.98      def in_class(self, c, s):
    3.99          return s.find(c) >= 0
   3.100 @@ -89,6 +136,12 @@ class Parser:
   3.101      def in_printable_class(self, c):
   3.102          return self.in_class(c, string.printable)
   3.103  
   3.104 +    def set_error_stream(self, error):
   3.105 +        self.error = error
   3.106 +
   3.107 +    def has_error(self):
   3.108 +        return self.err > 0
   3.109 +
   3.110      def at_eof(self):
   3.111          return self.eof
   3.112  
   3.113 @@ -113,131 +166,439 @@ class Parser:
   3.114             self.char_no += 1 
   3.115  
   3.116          if self.state is None:
   3.117 -            self.state = ParserState(self.state_start)
   3.118 -
   3.119 +            self.begin_start(None)
   3.120          self.state.fn(c)
   3.121  
   3.122      def ready(self):
   3.123 -        return len(self.start_state.val) > 0
   3.124 +        return len(self.val) > 0
   3.125  
   3.126      def get_val(self):
   3.127 -        v = self.start_state.val[0]
   3.128 -        self.start_state.val = self.start_state.val[1:]
   3.129 +        v = self.val[0]
   3.130 +        self.val = self.val[1:]
   3.131          return v
   3.132  
   3.133      def get_all(self):
   3.134 -        return self.start_state.val
   3.135 +        return self.val
   3.136 +
   3.137 +    def begin_start(self, c):
   3.138 +        self.state = ParserState(self.state_start)
   3.139  
   3.140 +    def end_start(self):
   3.141 +        self.val += self.state.val
   3.142 +        self.pop_state()
   3.143 +    
   3.144      def state_start(self, c):
   3.145 -        if self.at_eof() or self.in_space_class(c):
   3.146 +        if self.at_eof():
   3.147 +            self.end_start()
   3.148 +        elif self.in_space_class(c):
   3.149              pass
   3.150          elif self.in_comment_class(c):
   3.151 -            self.push_state(self.state_comment)
   3.152 -        elif c == '(':
   3.153 -            self.push_state(self.state_list)
   3.154 -        elif c == ')':
   3.155 +            self.begin_comment(c)
   3.156 +        elif c == k_list_open:
   3.157 +            self.begin_list(c)
   3.158 +        elif c == k_list_close:
   3.159              raise ParseError(self, "syntax error: "+c)
   3.160          elif self.in_string_quote_class(c):
   3.161 -            self.push_state(self.state_string)
   3.162 -            self.state.buf = c
   3.163 +            self.begin_string(c)
   3.164          elif self.in_printable_class(c):
   3.165 -            self.push_state(self.state_atom)
   3.166 -            self.state.buf = c
   3.167 +            self.begin_atom(c)
   3.168          elif c == chr(4):
   3.169              # ctrl-D, EOT: end-of-text.
   3.170              self.input_eof()
   3.171          else:
   3.172              raise ParseError(self, "invalid character: code %d" % ord(c))
   3.173  
   3.174 +    def begin_comment(self, c):
   3.175 +        self.push_state(self.state_comment)
   3.176 +        self.state.buf += c
   3.177 +
   3.178 +    def end_comment(self):
   3.179 +        self.pop_state()
   3.180 +    
   3.181      def state_comment(self, c):
   3.182          if c == '\n' or self.at_eof():
   3.183 -            self.pop_state()
   3.184 +            self.end_comment()
   3.185 +        else:
   3.186 +            self.state.buf += c
   3.187  
   3.188 +    def begin_string(self, c):
   3.189 +        self.push_state(self.state_string)
   3.190 +        self.state.delim = c
   3.191 +
   3.192 +    def end_string(self):
   3.193 +        val = self.state.buf
   3.194 +        self.state.parent.val.append(val)
   3.195 +        self.pop_state()
   3.196 +        
   3.197      def state_string(self, c):
   3.198          if self.at_eof():
   3.199              raise ParseError(self, "unexpected EOF")
   3.200 -        self.state.buf += c
   3.201 -        # Look out for non-escaped end delimiter
   3.202 -        if self.state.buf[0] == c and self.state.buf[-2] != '\\':
   3.203 -            try: # parse escape sequences but fall back to something simple
   3.204 -                val = eval(compile(self.state.buf,'','eval'))
   3.205 -            except:
   3.206 -                val = self.state.buf[1:-1] # just strip the delimiters
   3.207 -            self.state.parent.val.append(val)
   3.208 +        elif c == self.state.delim:
   3.209 +            self.end_string()
   3.210 +        elif c == '\\':
   3.211 +            self.push_state(self.state_escape)
   3.212 +        else:
   3.213 +            self.state.buf += c
   3.214 +
   3.215 +    def state_escape(self, c):
   3.216 +        if self.at_eof():
   3.217 +            raise ParseError(self, "unexpected EOF")
   3.218 +        d = escapes.get(c)
   3.219 +        if d:
   3.220 +            self.state.parent.buf += d
   3.221 +            self.pop_state()
   3.222 +        elif c == 'x':
   3.223 +            self.state.fn = self.state_hex
   3.224 +            self.state.val = 0
   3.225 +        else:
   3.226 +            self.state.fn = self.state_octal
   3.227 +            self.state.val = 0
   3.228 +            self.input_char(c)
   3.229 +
   3.230 +    def state_octal(self, c):
   3.231 +        def octaldigit(c):
   3.232 +            self.state.val *= 8
   3.233 +            self.state.val += ord(c) - ord('0')
   3.234 +            self.state.buf += c
   3.235 +            if self.state.val < 0 or self.state.val > 0xff:
   3.236 +                raise ParseError(self, "invalid octal escape: out of range " + self.state.buf)
   3.237 +            if len(self.state.buf) == 3:
   3.238 +               octaldone()
   3.239 +               
   3.240 +        def octaldone():
   3.241 +            d = chr(self.state.val)
   3.242 +            self.state.parent.buf += d
   3.243              self.pop_state()
   3.244 +            
   3.245 +        if self.at_eof():
   3.246 +            raise ParseError(self, "unexpected EOF")
   3.247 +        elif '0' <= c <= '7':
   3.248 +            octaldigit(c)
   3.249 +        elif len(self.buf):
   3.250 +            octaldone()
   3.251 +            self.input_char(c)
   3.252 +
   3.253 +    def state_hex(self, c):
   3.254 +        def hexdone():
   3.255 +            d = chr(self.state.val)
   3.256 +            self.state.parent.buf += d
   3.257 +            self.pop_state()
   3.258 +            
   3.259 +        def hexdigit(c, d):
   3.260 +            self.state.val *= 16
   3.261 +            self.state.val += ord(c) - ord(d)
   3.262 +            self.state.buf += c
   3.263 +            if self.state.val < 0 or self.state.val > 0xff:
   3.264 +                raise ParseError(self, "invalid hex escape: out of range " + self.state.buf)
   3.265 +            if len(self.state.buf) == 2:
   3.266 +                hexdone()
   3.267 +            
   3.268 +        if self.at_eof():
   3.269 +            raise ParseError(self, "unexpected EOF")
   3.270 +        elif '0' <= c <= '9':
   3.271 +            hexdigit(c, '0')
   3.272 +        elif 'A' <= c <= 'F':
   3.273 +            hexdigit(c, 'A')
   3.274 +        elif 'a' <= c <= 'f':
   3.275 +            hexdigit(c, 'a')
   3.276 +        elif len(buf):
   3.277 +            hexdone()
   3.278 +            self.input_char(c)
   3.279 +
   3.280 +    def begin_atom(self, c):
   3.281 +        self.push_state(self.state_atom)
   3.282 +        self.state.buf = c
   3.283 +
   3.284 +    def end_atom(self):
   3.285 +        val = self.state.buf
   3.286 +        self.state.parent.val.append(val)
   3.287 +        self.pop_state()
   3.288      
   3.289      def state_atom(self, c):
   3.290 -        if (self.at_eof() or
   3.291 -            self.is_separator(c) or
   3.292 -            self.in_space_class(c) or
   3.293 -            self.in_comment_class(c)):
   3.294 -            val = self.state.buf
   3.295 -            self.state.parent.val.append(val)
   3.296 -            self.pop_state()
   3.297 -            if not self.at_eof():
   3.298 -                self.input_char(c)
   3.299 +        if self.at_eof():
   3.300 +            self.end_atom()
   3.301 +        elif (self.is_separator(c) or
   3.302 +              self.in_space_class(c) or
   3.303 +              self.in_comment_class(c)):
   3.304 +            self.end_atom()
   3.305 +            self.input_char(c)
   3.306          else:
   3.307              self.state.buf += c
   3.308  
   3.309 +    def begin_list(self, c):
   3.310 +        self.push_state(self.state_list)
   3.311 +
   3.312 +    def end_list(self):
   3.313 +        val = self.state.val
   3.314 +        self.state.parent.val.append(val)
   3.315 +        self.pop_state()
   3.316 +
   3.317      def state_list(self, c):
   3.318          if self.at_eof():
   3.319              raise ParseError(self, "unexpected EOF")
   3.320 -        elif c == ')':
   3.321 -            val = self.state.val
   3.322 -            self.state.parent.val.append(val)
   3.323 -            self.pop_state()
   3.324 +        elif c == k_list_close:
   3.325 +            self.end_list()
   3.326          else:
   3.327              self.state_start(c)
   3.328  
   3.329 +def atomp(sxpr):
   3.330 +    """Check if an sxpr is an atom.
   3.331 +    """
   3.332 +    if sxpr.isalnum() or sxpr == '@':
   3.333 +        return 1
   3.334 +    for c in sxpr:
   3.335 +        if c in string.whitespace: return 0
   3.336 +        if c in '"\'\\(){}[]<>$#&%^': return 0
   3.337 +        if c in string.ascii_letters: continue
   3.338 +        if c in string.digits: continue
   3.339 +        if c in '.-_:/~': continue
   3.340 +        return 0
   3.341 +    return 1
   3.342 +    
   3.343  def show(sxpr, out=sys.stdout):
   3.344      """Print an sxpr in bracketed (lisp-style) syntax.
   3.345      """
   3.346      if isinstance(sxpr, types.ListType):
   3.347 -        out.write('(')
   3.348 +        out.write(k_list_open)
   3.349 +        i = 0
   3.350          for x in sxpr:
   3.351 +            if i: out.write(' ')
   3.352              show(x, out)
   3.353 -            out.write(' ')
   3.354 -        out.write(')')
   3.355 +            i += 1
   3.356 +        out.write(k_list_close)
   3.357 +    elif isinstance(sxpr, types.StringType) and atomp(sxpr):
   3.358 +        out.write(sxpr)
   3.359      else:
   3.360 +        #out.write("'" + str(sxpr) + "'")
   3.361          out.write(repr(str(sxpr)))
   3.362  
   3.363 +def show_xml(sxpr, out=sys.stdout):
   3.364 +    """Print an sxpr in XML syntax.
   3.365 +    """
   3.366 +    if isinstance(sxpr, types.ListType):
   3.367 +        element = name(sxpr)
   3.368 +        out.write('<%s' % element)
   3.369 +        for attr in attributes(sxpr):
   3.370 +            out.write(' %s=%s' % (attr[0], attr[1]))
   3.371 +        out.write('>')
   3.372 +        i = 0
   3.373 +        for x in children(sxpr):
   3.374 +            if i: out.write(' ')
   3.375 +            show_xml(x, out)
   3.376 +            i += 1
   3.377 +        out.write('</%s>' % element)
   3.378 +    elif isinstance(sxpr, types.StringType) and atomp(sxpr):
   3.379 +        out.write(sxpr)
   3.380 +    else:
   3.381 +        out.write(str(sxpr))
   3.382 +
   3.383 +def elementp(sxpr, elt=None):
   3.384 +    """Check if an sxpr is an element of the given type.
   3.385 +
   3.386 +    sxpr sxpr
   3.387 +    elt  element type
   3.388 +    """
   3.389 +    return (isinstance(sxpr, types.ListType)
   3.390 +            and len(sxpr)
   3.391 +            and (None == elt or sxpr[0] == elt))
   3.392 +
   3.393  def name(sxpr):
   3.394 -    """Get the element name of an sxpr, or None if a bad sxpr.
   3.395 +    """Get the element name of an sxpr.
   3.396 +    If the sxpr is not an element (i.e. it's an atomic value) its name
   3.397 +    is None.
   3.398 +
   3.399 +    sxpr
   3.400 +
   3.401 +    returns name (None if not an element).
   3.402      """
   3.403 +    val = None
   3.404      if isinstance(sxpr, types.StringType):
   3.405 -        return sxpr
   3.406 -    if isinstance(sxpr, types.ListType) and len(sxpr):
   3.407 -        return sxpr[0]
   3.408 -    return None
   3.409 +        val = sxpr
   3.410 +    elif isinstance(sxpr, types.ListType) and len(sxpr):
   3.411 +        val = sxpr[0]
   3.412 +    return val
   3.413 +
   3.414 +def attributes(sxpr):
   3.415 +    """Get the attribute list of an sxpr.
   3.416 +
   3.417 +    sxpr
   3.418 +
   3.419 +    returns attribute list
   3.420 +    """
   3.421 +    val = []
   3.422 +    if isinstance(sxpr, types.ListType) and len(sxpr) > 1:
   3.423 +        attr = sxpr[1]
   3.424 +        if elementp(attr, k_attr_open):
   3.425 +            val = attr[1:]
   3.426 +    return val
   3.427 +
   3.428 +def attribute(sxpr, key, val=None):
   3.429 +    """Get an attribute of an sxpr.
   3.430 +
   3.431 +    sxpr sxpr
   3.432 +    key  attribute key
   3.433 +    val  default value (default None)
   3.434 +
   3.435 +    returns attribute value
   3.436 +    """
   3.437 +    for x in attributes(sxpr):
   3.438 +        if x[0] == key:
   3.439 +            val = x[1]
   3.440 +            break
   3.441 +    return val
   3.442  
   3.443  def children(sxpr, elt=None):
   3.444 -    """Get children of an s-expression @sxpr, optionally filtered by
   3.445 -    element type @elt.
   3.446 +    """Get children of an sxpr.
   3.447 +
   3.448 +    sxpr sxpr
   3.449 +    elt  optional element type to filter by
   3.450 +
   3.451 +    returns children (filtered by elt if specified)
   3.452      """
   3.453 -    if not isinstance(sxpr, types.ListType): return []
   3.454 -    val = filter(lambda x: isinstance(x, types.ListType) and len(x) > 0, sxpr)
   3.455 +    val = []
   3.456 +    if isinstance(sxpr, types.ListType) and len(sxpr) > 1:
   3.457 +        i = 1
   3.458 +        x = sxpr[i]
   3.459 +        if elementp(x, k_attr_open):
   3.460 +            i += 1
   3.461 +        val = sxpr[i : ]
   3.462      if elt:
   3.463 -        val = filter(lambda x,y=elt: x[0] == y, val)
   3.464 +        def iselt(x):
   3.465 +            return elementp(x, elt)
   3.466 +        val = filter(iselt, val)
   3.467 +    return val
   3.468 +
   3.469 +def child(sxpr, elt, val=None):
   3.470 +    """Get the first child of the given element type.
   3.471 +
   3.472 +    sxpr sxpr
   3.473 +    elt  element type
   3.474 +    val  default value
   3.475 +    """
   3.476 +    for x in children(sxpr):
   3.477 +        if elementp(x, elt):
   3.478 +            val = x
   3.479 +            break
   3.480 +    return val
   3.481 +
   3.482 +def child_at(sxpr, index, val=None):
   3.483 +    """Get the child at the given index (zero-based).
   3.484 +
   3.485 +    sxpr  sxpr
   3.486 +    index index
   3.487 +    val   default value
   3.488 +    """
   3.489 +    kids = children(sxpr)
   3.490 +    if len(kids) > index:
   3.491 +        val = kids[index]
   3.492      return val
   3.493  
   3.494 -def child(sxpr, elt=None, idx=0):
   3.495 -    """Get the @idx'th child of the optional filtering type @elt in @sxpr.
   3.496 +def child0(sxpr, val=None):
   3.497 +    """Get the zeroth child.
   3.498 +    """
   3.499 +    return child_at(sxpr, 0, val)
   3.500 +
   3.501 +def child1(sxpr, val=None):
   3.502 +    """Get the first child.
   3.503 +    """
   3.504 +    return child_at(sxpr, 1, val)
   3.505 +
   3.506 +def child2(sxpr, val=None):
   3.507 +    """Get the second child.
   3.508 +    """
   3.509 +    return child_at(sxpr, 2, val)
   3.510 +
   3.511 +def child3(sxpr, val=None):
   3.512 +    """Get the third child.
   3.513 +    """
   3.514 +    return child_at(sxpr, 3, val)
   3.515 +
   3.516 +def child4(sxpr, val=None):
   3.517 +    """Get the fourth child.
   3.518      """
   3.519 -    x = children(sxpr, elt)
   3.520 -    if len(x) > idx:
   3.521 -        return x[idx]
   3.522 -    return None
   3.523 +    return child_at(sxpr, 4, val)
   3.524 +
   3.525 +def child_value(sxpr, elt, val=None):
   3.526 +    """Get the value of the first child of the given element type.
   3.527 +    Assumes the child has an atomic value.
   3.528 +
   3.529 +    sxpr sxpr
   3.530 +    elt  element type
   3.531 +    val  default value
   3.532 +    """
   3.533 +    kid = child(sxpr, elt)
   3.534 +    if kid:
   3.535 +        val = child_at(kid, 0, val)
   3.536 +    return val
   3.537 +
   3.538 +def has_id(sxpr, id):
   3.539 +    """Test if an s-expression has a given id.
   3.540 +    """
   3.541 +    return attribute(sxpr, 'id') == id
   3.542 +
   3.543 +def with_id(sxpr, id, val=None):
   3.544 +    """Find the first s-expression with a given id, at any depth.
   3.545 +
   3.546 +    sxpr   s-exp or list
   3.547 +    id     id
   3.548 +    val    value if not found (default None)
   3.549  
   3.550 -def child_value(sxpr, elt=None):
   3.551 -    """Get the value of the first child of @sxpr with the optional type @elt.
   3.552 +    return s-exp or val
   3.553 +    """
   3.554 +    if isinstance(sxpr, types.ListType):
   3.555 +        for n in sxpr:
   3.556 +            if has_id(n, id):
   3.557 +                val = n
   3.558 +                break
   3.559 +            v = with_id(n, id)
   3.560 +            if v is None: continue
   3.561 +            val = v
   3.562 +            break
   3.563 +    return val
   3.564 +
   3.565 +def child_with_id(sxpr, id, val=None):
   3.566 +    """Find the first child with a given id.
   3.567 +
   3.568 +    sxpr   s-exp or list
   3.569 +    id     id
   3.570 +    val    value if not found (default None)
   3.571 +
   3.572 +    return s-exp or val
   3.573      """
   3.574 -    x = child(sxpr, elt)
   3.575 -    if not isinstance(x, types.ListType) or len(x) < 2:
   3.576 -        return None
   3.577 -    return x[1]
   3.578 +    if isinstance(sxpr, types.ListType):
   3.579 +        for n in sxpr:
   3.580 +            if has_id(n, id):
   3.581 +                val = n
   3.582 +                break
   3.583 +    return val
   3.584 +
   3.585 +def elements(sxpr, ctxt=None):
   3.586 +    """Generate elements (at any depth).
   3.587 +    Visit elements in pre-order.
   3.588 +    Values generated are (node, context)
   3.589 +    The context is None if there is no parent, otherwise
   3.590 +    (index, parent, context) where index is the node's index w.r.t its parent,
   3.591 +    and context is the parent's context.
   3.592 +
   3.593 +    sxpr   s-exp
   3.594 +
   3.595 +    returns generator
   3.596 +    """
   3.597 +    yield (sxpr, ctxt)
   3.598 +    i = 0
   3.599 +    for n in children(sxpr):
   3.600 +        if isinstance(n, types.ListType):
   3.601 +            # Calling elements() recursively does not generate recursively,
   3.602 +            # it just returns a generator object. So we must iterate over it.
   3.603 +            for v in elements(n, (i, sxpr, ctxt)):
   3.604 +                yield v
   3.605 +        i += 1
   3.606  
   3.607  def to_string(sxpr):
   3.608 -    """Convert an s-expression @sxpr to a string.
   3.609 +    """Convert an sxpr to a string.
   3.610 +
   3.611 +    sxpr sxpr
   3.612 +    returns string
   3.613      """
   3.614      io = StringIO()
   3.615      show(sxpr, io)
   3.616 @@ -247,14 +608,35 @@ def to_string(sxpr):
   3.617      return val
   3.618  
   3.619  def from_string(str):
   3.620 -    """Create an sxpr list from a given input string @str.
   3.621 +    """Create an sxpr by parsing a string.
   3.622 +
   3.623 +    str string
   3.624 +    returns sxpr
   3.625 +    """
   3.626 +    io = StringIO(str)
   3.627 +    vals = parse(io)
   3.628 +    if vals is []:
   3.629 +        return None
   3.630 +    else:
   3.631 +        return vals[0]
   3.632 +    
   3.633 +
   3.634 +def all_from_string(str):
   3.635 +    """Create an sxpr list by parsing a string.
   3.636 +
   3.637 +    str string
   3.638 +    returns sxpr list
   3.639      """
   3.640      io = StringIO(str)
   3.641      vals = parse(io)
   3.642      return vals
   3.643  
   3.644  def parse(io):
   3.645 -    """Completely parse all input from file @io.
   3.646 +    """Completely parse all input from 'io'.
   3.647 +
   3.648 +    io	input file object
   3.649 +    returns list of values, None if incomplete
   3.650 +    raises ParseError on parse error
   3.651      """
   3.652      pin = Parser()
   3.653      while 1:
   3.654 @@ -267,11 +649,19 @@ def parse(io):
   3.655      else:
   3.656          val = None
   3.657      return val
   3.658 +   
   3.659  
   3.660 -   
   3.661  if __name__ == '__main__':
   3.662 +    print ">main"
   3.663      pin = Parser()
   3.664 -    buf = sys.stdin.read(1024)
   3.665 -    pin.input(buf)
   3.666 -    while pin.ready():
   3.667 -        print '\n****** val=', pin.get_val()
   3.668 +    while 1:
   3.669 +        buf = sys.stdin.read(1024)
   3.670 +        #buf = sys.stdin.readline()
   3.671 +        pin.input(buf)
   3.672 +        while pin.ready():
   3.673 +            val = pin.get_val()
   3.674 +            print
   3.675 +            print '****** val=', val
   3.676 +        if len(buf) == 0:
   3.677 +            break
   3.678 +
     4.1 --- a/tools/python/xen/xm/main.py	Tue Jul 06 20:42:40 2004 +0000
     4.2 +++ b/tools/python/xen/xm/main.py	Wed Jul 07 09:58:27 2004 +0000
     4.3 @@ -246,11 +246,11 @@ class ProgList(Prog):
     4.4              info = server.xend_domain(dom)
     4.5              d = {}
     4.6              d['dom'] = int(dom)
     4.7 -            d['name'] = sxp.child_value(info, 'name') or '??'
     4.8 -            d['mem'] = int(sxp.child_value(info, 'memory') or '-1')
     4.9 -            d['cpu'] = int(sxp.child_value(info, 'cpu') or '-1')
    4.10 -            d['state'] = sxp.child_value(info, 'state') or '??'
    4.11 -            d['cpu_time'] = float(sxp.child_value(info, 'cpu_time') or '-1')
    4.12 +            d['name'] = sxp.child_value(info, 'name', '??')
    4.13 +            d['mem'] = int(sxp.child_value(info, 'memory', '0'))
    4.14 +            d['cpu'] = int(sxp.child_value(info, 'cpu', '0'))
    4.15 +            d['state'] = sxp.child_value(info, 'state', '??')
    4.16 +            d['cpu_time'] = float(sxp.child_value(info, 'cpu_time', '0'))
    4.17              print ("%(dom)-4d %(name)-16s %(mem)7d  %(cpu)3d  %(state)5s  %(cpu_time)7.1f" % d)
    4.18  
    4.19      def long_list(self, doms):
    4.20 @@ -424,9 +424,9 @@ class ProgConsoles(Prog):
    4.21          for x in l:
    4.22              info = server.xend_console(x)
    4.23              d = {}
    4.24 -            d['dom'] = (sxp.child(info, 'dst') or ['dst', '?', '?'])[1]
    4.25 -            d['port'] = sxp.child_value(info, 'port') or '?'
    4.26 -            d['id'] = sxp.child_value(info, 'id') or '?'
    4.27 +            d['dom'] = sxp.child(info, 'dst', ['dst', '?', '?'])[1]
    4.28 +            d['port'] = sxp.child_value(info, 'port', '?')
    4.29 +            d['id'] = sxp.child_value(info, 'id', '?')
    4.30              print "%(dom)3s %(port)4s %(id)3s" % d
    4.31  
    4.32  xm.prog(ProgConsoles)