text: #!/usr/bin/python
  # -*- coding: utf-8 -*-
  
  # List of namespaces.The 2nd part in the array states whether the attributes
  # should be in the namespace
  namespaces = {
      "xhtml": ['"http://www.w3.org/1999/xhtml"', False, 0 ],
      "empty": [ "DOMString()", False, 1 ],
      "svg":   ['"http://www.w3.org/2000/svg"', False, 2 ],
      "xlink": ['"http://www.w3.org/1999/xlink"', True, 3 ],
      "xmlns":   ['"http://www.w3.org/2000/xmlns/"', True, 4 ],
      "xml":   ['"http://www.w3.org/XML/1998/namespace"', True, 5 ],
  }
  
  cache = {}
  namesList = []
  
  additionalCaseSensitiveAttrs = []
  lastCaseInsensitiveAttr      = 0
  
  
  def constName(prefix, ns, i):
      if namespaces[ns][1]:
          return (prefix + "_%s_%s") % (ns.upper(), i.upper().replace("-", "_"));
      else:
          return (prefix + "_%s") % i.upper().replace("-", "_");
  
  def parseFile(fname, ns, isAttrs, isHtmlAttrs):
      global cache
      global namesList
  
      global additionalCaseSensitiveAttrs
      global lastCaseInsensitiveAttr
  
      prefix = "ID"
      if isAttrs:
          prefix = "ATTR"
  
      f = open(fname, "r")
      for i in f.xreadlines():
          i = i.strip()
          if i.startswith("#") or i == "": continue
          if isHtmlAttrs and i.startswith("END_CI"):
              lastCaseInsensitiveAttr = len(cache)
              continue
  
          # don't add it twice to names list
          cons = constName(prefix, ns, i)
          alreadyDefined = [k for k in namesList if k[2] == cons]
          if len(alreadyDefined) > 0:
              continue
  
          if i.upper() == "TEXT" and isAttrs: # hack to get ID_TEXT and ATTR_TEXT be different
              key = len(cache) + 1
              cache["TEXT#"] = -1
          else:
              key = cache.get(i, len(cache) + 1)
  
          if isHtmlAttrs and lastCaseInsensitiveAttr > 0 and key <= len(cache):
              additionalCaseSensitiveAttrs.append(cons)
  
          cache[i] = key
          namesList.append([key, i, cons, ns])
      f.close();
  
  def parseTags(fname, ns):
      parseFile(fname, ns, False, False)
  
  def parseAttrs(fname, ns, isHtml):
      parseFile(fname, ns, True, isHtml)
  
  # parse htmltags.in
  parseTags("htmltags.in", "xhtml");
  lastTagId = len(cache)
  
  # parse htmlattrs.in file
  parseAttrs("htmlattrs.in", "xhtml", True)
  lastAttrId = len(cache)
  
  # parse SVG tags, attrs
  parseTags("../svg/svgtags.in", "svg")
  parseAttrs("../svg/svgattrs.in", "svg", False)
  
  # parse XLink attrs
  parseAttrs("../svg/xlinkattrs.in", "xlink", False)
  
  # and XML attrs
  parseAttrs("xmlattrs.in", "xml", False)
  
  # sort the list
  def func(a, b):
      return cmp(a[0], b[0]) or -cmp(a[2], b[2])
  namesList.sort(func)
  
  ########################################
  # END OF PARSING, START WRITING FILES
  ########################################
  
  out = open("htmlnames.h", "w")
  out.write("/* This file is automatically generated from htmltags.in and htmlattrs.in by gennames.py, do not edit */\n")
  out.write("/* Copyright 2008 Vyacheslav Tokarev */\n")
  out.write("\n")
  out.write("#ifndef HTMLNames_h\n")
  out.write("#define HTMLNames_h\n")
  out.write("\n")
  out.write("#include \"misc/idstring.h\"\n")
  out.write("\n")
  
  # Print out namespace string constants
  for n in namespaces.keys():
      uri = namespaces[n][0];
      if uri.startswith('"'):
          out.write("#define %s_NAMESPACE %s\n" % (n.upper(), uri))
  
  # Now the main macros and constants
  out.write("namespace DOM {\n\
  \n\
  #define NodeImpl_IdNSMask    0xffff0000\n\
  #define NodeImpl_IdLocalMask 0x0000ffff\n\
  \n");
  
  for n in namespaces.keys():
      out.write("const quint32 %sNamespace = %d;\n" % (n, namespaces[n][2]));
  
  out.write("const quint16 anyNamespace = 0xffff;\n\
  const quint16 anyLocalName = 0xffff;\n\
  const quint16 emptyPrefix = 0;\n\
  const quint16 xmlPrefix = 1;\n\
  const quint16 xmlnsPrefix = 2;\n\
  \n\
  inline quint16 localNamePart(quint32 id) { return id & NodeImpl_IdLocalMask; }\n\
  inline quint16 namespacePart(quint32 id) { return (((unsigned int)id) & NodeImpl_IdNSMask) >> 16; }\n\
  inline quint32 makeId(quint16 n, quint16 l) { return (n << 16) | l; }\n\
  \n\
  const quint32 anyQName = makeId(anyNamespace, anyLocalName);\n\
  \n\
  }\n")
  out.write("\n")
  
  
  # Now the ATTR_ and ID_ constants
  out.write("\n")
  for i in namesList:
      if i[2].startswith("ATTR"):
          attrNS = i[3]
          useNS  = "empty"
          if namespaces[attrNS][1]:
              useNS = attrNS
          out.write("#define %s ((DOM::%s << 16) | %d)\n" % (i[2], useNS + "Namespace", i[0]))
      else:
          out.write("#define %s %d\n" % (i[2], i[0]))
  out.write("#define ID_LAST_TAG %d\n" % (lastTagId))
  out.write("#define ID_CLOSE_TAG 16384\n")
  out.write("#define ATTR_LAST_ATTR %d\n" % (lastAttrId))
  out.write("#define ATTR_LAST_CI_ATTR %d\n" % (lastCaseInsensitiveAttr))
  out.write("\n")
  s = "((localNamePart(id)) > ATTR_LAST_CI_ATTR"
  for i in additionalCaseSensitiveAttrs:
      s = s + " || (id) == %s" % i
  s = s + ")"
  out.write("#define caseSensitiveAttr(id) (%s)\n" % s)
  out.write("\n")
  out.write("namespace khtml {\n\
  \n\
  class NamespaceFactory {\n\
  public:\n\
      static IDTable<NamespaceFactory>* idTable() {\n\
          return s_idTable;\n\
      }\n\
      static IDTable<NamespaceFactory>* initIdTable();\n\
  protected:\n\
      static IDTable<NamespaceFactory>* s_idTable;\n\
  };\n\
  \n\
  class LocalNameFactory {\n\
  public:\n\
      static IDTable<LocalNameFactory>* idTable() {\n\
          return s_idTable;\n\
      }\n\
      static IDTable<LocalNameFactory>* initIdTable();\n\
  protected:\n\
      static IDTable<LocalNameFactory>* s_idTable;\n\
  };\n\
  \n\
  class PrefixFactory {\n\
  public:\n\
      static IDTable<PrefixFactory>* idTable() {\n\
          return s_idTable;\n\
      }\n\
      static IDTable<PrefixFactory>* initIdTable();\n\
  protected:\n\
      static IDTable<PrefixFactory>* s_idTable;\n\
  };\n")
  out.write("\n")
  out.write("}\n")
  out.write("\n")
  out.write("namespace DOM {\n\
  \n\
      typedef khtml::IDString<khtml::NamespaceFactory> NamespaceName;\n\
      typedef khtml::IDString<khtml::LocalNameFactory> LocalName;\n\
      typedef khtml::IDString<khtml::PrefixFactory> PrefixName;\n\
      extern PrefixName emptyPrefixName;\n\
      extern LocalName emptyLocalName;\n\
      extern NamespaceName emptyNamespaceName;\n\
  \n\
      QString getPrintableName(int id);\n\n")
  out.write("}\n\n")
  out.write("#endif\n")
  out.close()
  
  temp = ""
  prev = 0
  for i in namesList:
      if prev and prev[0] == i[0]: continue
      if i[2] == "ID_TEXT" or i[2] == "ID_COMMENT":
          temp = temp + ("    s_idTable->addHiddenMapping(%s, \"%s\");\n" % (i[2], i[1]))
      else:
          temp = temp + ("    s_idTable->addStaticMapping(localNamePart(%s), \"%s\");\n" % (i[2], i[1]))
      prev = i
  
  out = open("htmlnames.cpp", "w")
  out.write("#include \"misc/htmlnames.h\"\n")
  out.write("#include \"dom/dom_string.h\"\n")
  out.write("\nusing namespace DOM;\n")
  out.write("\n")
  out.write("namespace khtml {\n\n")
  out.write("IDTable<NamespaceFactory>* NamespaceFactory::s_idTable;\n\
  IDTable<NamespaceFactory>* NamespaceFactory::initIdTable()\n\
  {\n\
      if (s_idTable) return s_idTable; // Can happen if KHTMLGlobal was recreated..\n\
      s_idTable = new IDTable<NamespaceFactory>();\n");
  for n in namespaces.keys():
      uri = namespaces[n][0];
      if uri.startswith('"'):
          out.write("    s_idTable->addStaticMapping(DOM::%sNamespace, %s_NAMESPACE);\n" % (n, n.upper()))
      else:
          out.write("    s_idTable->addStaticMapping(DOM::%sNamespace, %s);\n" % (n, uri))
  
  out.write("    return s_idTable;\n\
  }\n\
  \n\
  IDTable<LocalNameFactory>* LocalNameFactory::s_idTable;\n\
  IDTable<LocalNameFactory>* LocalNameFactory::initIdTable()\n\
  {\n\
      if (s_idTable) return s_idTable; // Can happen if KHTMLGlobal was recreated..\n\
      s_idTable = new IDTable<LocalNameFactory>();\n\
      s_idTable->addStaticMapping(0, DOMString());\n\
  %s\
      return s_idTable;\n\
  }\n\
  \n\
  IDTable<PrefixFactory>* PrefixFactory::s_idTable;\n\
  IDTable<PrefixFactory>* PrefixFactory::initIdTable()\n\
  {\n\
      if (s_idTable) return s_idTable; // Can happen if KHTMLGlobal was recreated..\n\
      s_idTable = new IDTable<PrefixFactory>();\n\
      s_idTable->addStaticMapping(DOM::emptyPrefix, DOMString());\n\
      s_idTable->addStaticMapping(DOM::xmlPrefix, \"xml\");\n\
      s_idTable->addStaticMapping(DOM::xmlnsPrefix, \"xmlns\");\n\
      return s_idTable;\n\
  }\n" % temp)
  out.write("\n}\n")
  out.write("\n")
  out.write("namespace DOM {\n\n")
  out.write("LocalName emptyLocalName;// = LocalName::fromId(0);\n")
  out.write("PrefixName emptyPrefixName;// = PrefixName::fromId(0);\n")
  out.write("NamespaceName emptyNamespaceName;// = NamespaceName::fromId(0);\n")
  out.write("\n")
  out.write("""QString getPrintableName(int id) {
      QString local = QString("null");
      QString namespacename = QString("null");
  
      if (localNamePart(id) != anyLocalName) {
          DOMString localName = LocalName::fromId(localNamePart(id)).toString();
          if (localName.implementation())
              local = localName.string();
      } else {
          local = "*";
      }
  
      if (namespacePart(id) != anyNamespace) {
          DOMString namespaceName = NamespaceName::fromId(namespacePart(id)).toString();
          if (namespaceName.implementation())
              namespacename = namespaceName.string();
      } else {
          namespacename = "*";
      }
      return "{ns:" + QString::number(namespacePart(id)) + ",[" + namespacename + "] local:" + QString::number(localNamePart(id)) + ",[" + local + "]}";
  }\n""")
  out.write("\n}\n")
  out.close()
  
  # kate: indent-width 4; replace-tabs on; tab-width 4; space-indent on;
  
  