home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pyth_os2.zip / python-1.0.2 / Demo / ibrowse / itags.py < prev    next >
Text File  |  1992-03-30  |  3KB  |  128 lines

  1. # Utility module for 'icache.py': interpret tag tables and indirect nodes.
  2.  
  3. # (This module is a bit chatty when confronted with the unexpected.)
  4.  
  5.  
  6. import regexp
  7. import string
  8. import ifile
  9.  
  10.  
  11. # Get the tag table of an open file, as a dictionary.
  12. # Seeks around in the file; after reading, the position is undefined.
  13. # Return an empty tag table if none is found.
  14. #
  15. def get_tags(f):
  16.     #
  17.     # First see if the last "node" is the end of tag table marker.
  18.     #
  19.     f.seek(0, 2) # Seek to EOF
  20.     end = f.tell()
  21.     buf = ifile.backup_node(f, end)
  22.     if not labelmatch(buf, 0, 'end tag table\n'):
  23.         return {} # No succes
  24.     #
  25.     # Next backup to the previous "node" -- the tag table itself.
  26.     #
  27.     ###print 'Getting prebuilt tag table...'
  28.     end = f.tell() - len(buf)
  29.     buf = ifile.backup_node(f, end)
  30.     label = 'tag table:\n'
  31.     if not labelmatch(buf, 0, label):
  32.         print 'Weird: end tag table marker but no tag table?'
  33.         print 'Node begins:', `buf[:50]`
  34.         return {}
  35.     #
  36.     # Now read the whole tag table.
  37.     #
  38.     end = f.tell() - len(buf) # Do this first!
  39.     buf = ifile.read_node(f, buf)
  40.     #
  41.     # First check for an indirection table.
  42.     #
  43.     indirlist = []
  44.     if labelmatch(buf, len(label), '(indirect)\n'):
  45.         indirbuf = ifile.backup_node(f, end)
  46.         if not labelmatch(indirbuf, 0, 'indirect:\n'):
  47.             print 'Weird: promised indirection table not found'
  48.             print 'Node begins:', `indirbuf[:50]`
  49.             # Carry on.  Things probably won't work though.
  50.         else:
  51.             indirbuf = ifile.read_node(f, indirbuf)
  52.             indirlist = parse_indirlist(indirbuf)
  53.     #
  54.     # Now parse the tag table.
  55.     #
  56.     findtag = regexp.compile('^(.*[nN]ode:[ \t]*(.*))\177([0-9]+)$').match
  57.     i = 0
  58.     tags = {}
  59.     while 1:
  60.         match = findtag(buf, i)
  61.         if not match:
  62.             break
  63.         (a,b), (a1,b1), (a2,b2), (a3,b3) = match
  64.         i = b
  65.         line = buf[a1:b1]
  66.         node = string.lower(buf[a2:b2])
  67.         offset = eval(buf[a3:b3]) # XXX What if it overflows?
  68.         if tags.has_key(node):
  69.             print 'Duplicate key in tag table:', `node`
  70.         file, offset = map_offset(offset, indirlist)
  71.         tags[node] = file, offset, line
  72.     #
  73.     return tags
  74.  
  75.  
  76. # Return true if buf[i:] begins with a label, after lower case conversion.
  77. # The label argument must be in lower case.
  78. #
  79. def labelmatch(buf, i, label):
  80.     return string.lower(buf[i:i+len(label)]) == label
  81.  
  82.  
  83. # Parse the indirection list.
  84. # Return a list of (filename, offset) pairs ready for use.
  85. #
  86. def parse_indirlist(buf):
  87.     list = []
  88.     findindir = regexp.compile('^(.+):[ \t]*([0-9]+)$').match
  89.     i = 0
  90.     while 1:
  91.         match = findindir(buf, i)
  92.         if not match:
  93.             break
  94.         (a,b), (a1,b1), (a2,b2) = match
  95.         file = buf[a1:b1]
  96.         offset = eval(buf[a2:b2]) # XXX What if this gets overflow?
  97.         list.append(file, offset)
  98.         i = b
  99.     return list
  100.  
  101.  
  102. # Map an offset through the indirection list.
  103. # Return (filename, new_offset).
  104. # If the list is empty, return the given offset and an empty file name.
  105. #
  106. def map_offset(offset, indirlist):
  107.     if not indirlist:
  108.         return '', offset
  109.     #
  110.     # XXX This could be done more elegant.
  111.     #
  112.     filex, offx = indirlist[0]
  113.     for i in range(len(indirlist)):
  114.         file1, off1 = indirlist[i]
  115.         if i+1 >= len(indirlist):
  116.             file2, off2 = '', 0x7fffffff
  117.         else:
  118.             file2, off2 = indirlist[i+1]
  119.         if off1 <= offset < off2:
  120.             # Add offx+2 to compensate for extra header.
  121.             # No idea whether this is always correct.
  122.             return file1, offset-off1 + offx+2
  123.     #
  124.     # XXX Shouldn't get here.
  125.     #
  126.     print 'Oops, map_offset fell through'
  127.     return '', offset # Not likely to get good results
  128.