(root)/
libxml2-2.12.3/
doc/
examples/
index.py
       1  #!/usr/bin/env python3
       2  #
       3  # Indexes the examples and build an XML description
       4  #
       5  import glob
       6  import sys
       7  try:
       8      import libxml2
       9  except:
      10      print("libxml2 python bindings not available")
      11      sys.exit(1)
      12  sys.path.insert(0, "..")
      13  from apibuild import CParser, escape
      14  
      15  examples = []
      16  extras = ['examples.xsl', 'index.html', 'index.py']
      17  tests = []
      18  sections = {}
      19  symbols = {}
      20  api_dict = None
      21  api_doc = None
      22  
      23  def load_api():
      24      global api_dict
      25      global api_doc
      26  
      27      if api_dict != None:
      28          return
      29      api_dict = {}
      30      try:
      31          print("loading ../libxml2-api.xml")
      32          api_doc = libxml2.parseFile("../libxml2-api.xml")
      33      except:
      34          print("failed to parse ../libxml2-api.xml")
      35          sys.exit(1)
      36  
      37  def find_symbol(name):
      38      global api_dict
      39      global api_doc
      40  
      41      if api_doc == None:
      42          load_api()
      43  
      44      if name == None:
      45          return
      46      if name in api_dict:
      47          return api_dict[name]
      48      ctxt = api_doc.xpathNewContext()
      49      res = ctxt.xpathEval("/api/symbols/*[@name = '%s']" % (name))
      50      if type(res) == type([]) and len(res) >= 1:
      51          if len(res) > 1:
      52              print("Found %d references to %s in the API" % (len(res), name))
      53          node = res[0]
      54          typ = node.name
      55          file = node.xpathEval("string(@file)")
      56          info = node.xpathEval("string(info)")
      57      else:
      58          print("Reference %s not found in the API" % (name))
      59          return None
      60      ret = (typ, file, info)
      61      api_dict[name] = ret
      62      return ret
      63  
      64  def parse_top_comment(filename, comment):
      65      res = {}
      66      lines = comment.split("\n")
      67      item = None
      68      for line in lines:
      69          while line != "" and (line[0] == ' ' or line[0] == '\t'):
      70              line = line[1:]
      71          while line != "" and line[0] == '*':
      72              line = line[1:]
      73          while line != "" and (line[0] == ' ' or line[0] == '\t'):
      74              line = line[1:]
      75          try:
      76              (it, line) = line.split(":", 1)
      77              item = it
      78              while line != "" and (line[0] == ' ' or line[0] == '\t'):
      79                  line = line[1:]
      80              if item in res:
      81                  res[item] = res[item] + " " + line
      82              else:
      83                  res[item] = line
      84          except:
      85              if item != None:
      86                  if item in res:
      87                      res[item] = res[item] + " " + line
      88                  else:
      89                      res[item] = line
      90      return res
      91  
      92  def parse(filename, output):
      93      global symbols
      94      global sections
      95  
      96      parser = CParser(filename)
      97      parser.collect_references()
      98      idx = parser.parse()
      99      info = parse_top_comment(filename, parser.top_comment)
     100      output.write("  <example filename='%s'>\n" % filename)
     101      try:
     102          synopsis = info['synopsis']
     103          output.write("    <synopsis>%s</synopsis>\n" % escape(synopsis));
     104      except:
     105          print("Example %s lacks a synopsis description" % (filename))
     106      try:
     107          purpose = info['purpose']
     108          output.write("    <purpose>%s</purpose>\n" % escape(purpose));
     109      except:
     110          print("Example %s lacks a purpose description" % (filename))
     111      try:
     112          usage = info['usage']
     113          output.write("    <usage>%s</usage>\n" % escape(usage));
     114      except:
     115          print("Example %s lacks an usage description" % (filename))
     116      try:
     117          test = info['test']
     118          output.write("    <test>%s</test>\n" % escape(test));
     119          progname=filename[0:-2]
     120          command=test.replace(progname, './' + progname, 1)
     121          tests.append(command)
     122      except:
     123          pass
     124      try:
     125          author = info['author']
     126          output.write("    <author>%s</author>\n" % escape(author));
     127      except:
     128          print("Example %s lacks an author description" % (filename))
     129      try:
     130          copy = info['copy']
     131          output.write("    <copy>%s</copy>\n" % escape(copy));
     132      except:
     133          print("Example %s lacks a copyright description" % (filename))
     134      try:
     135          section = info['section']
     136          output.write("    <section>%s</section>\n" % escape(section));
     137          if section in sections:
     138              sections[section].append(filename)
     139          else:
     140              sections[section] = [filename]
     141      except:
     142          print("Example %s lacks a section description" % (filename))
     143      for topic in sorted(info.keys()):
     144          if topic != "purpose" and topic != "usage" and \
     145             topic != "author" and topic != "copy" and \
     146             topic != "section" and topic != "synopsis" and topic != "test":
     147              str = info[topic]
     148              output.write("    <extra topic='%s'>%s</extra>\n" % (
     149                           escape(topic), escape(str)))
     150      output.write("    <includes>\n")
     151      for include in sorted(idx.includes.keys()):
     152          if include.find("libxml") != -1:
     153              id = idx.includes[include]
     154              line = id.get_lineno()
     155              output.write("      <include line='%d'>%s</include>\n" %
     156                           (line, escape(include)))
     157      output.write("    </includes>\n")
     158      output.write("    <uses>\n")
     159      for ref in sorted(idx.references.keys()):
     160          id = idx.references[ref]
     161          name = id.get_name()
     162          line = id.get_lineno()
     163          if name in symbols:
     164              sinfo = symbols[name]
     165              refs = sinfo[0]
     166              # gather at most 5 references per symbols
     167              if refs > 5:
     168                  continue
     169              sinfo.append(filename)
     170              sinfo[0] = refs + 1
     171          else:
     172              symbols[name] = [1, filename]
     173          info = find_symbol(name)
     174          if info != None:
     175              type = info[0]
     176              file = info[1]
     177              output.write("      <%s line='%d' file='%s' name='%s'/>\n" % (type,
     178                           line, file, name))
     179          else:
     180              type = id.get_type()
     181              output.write("      <%s line='%d' name='%s'/>\n" % (type,
     182                           line, name))
     183  
     184      output.write("    </uses>\n")
     185      output.write("  </example>\n")
     186  
     187      return idx
     188  
     189  def dump_symbols(output):
     190      global symbols
     191  
     192      output.write("  <symbols>\n")
     193      for symbol in sorted(symbols.keys()):
     194          output.write("    <symbol name='%s'>\n" % (symbol))
     195          info = symbols[symbol]
     196          i = 1
     197          while i < len(info):
     198              output.write("      <ref filename='%s'/>\n" % (info[i]))
     199              i = i + 1
     200          output.write("    </symbol>\n")
     201      output.write("  </symbols>\n")
     202  
     203  def dump_sections(output):
     204      global sections
     205  
     206      output.write("  <sections>\n")
     207      for section in sorted(sections.keys()):
     208          output.write("    <section name='%s'>\n" % (section))
     209          info = sections[section]
     210          i = 0
     211          while i < len(info):
     212              output.write("      <example filename='%s'/>\n" % (info[i]))
     213              i = i + 1
     214          output.write("    </section>\n")
     215      output.write("  </sections>\n")
     216  
     217  def dump_Makefile():
     218      for file in glob.glob('*.xml'):
     219          extras.append(file)
     220      for file in glob.glob('*.res'):
     221          extras.append(file)
     222      Makefile="""##
     223  ## This file is auto-generated by index.py
     224  ## DO NOT EDIT !!!
     225  ##
     226  
     227  AM_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
     228  LDADD = $(top_builddir)/libxml2.la
     229  
     230  CLEANFILES = *.tmp
     231  
     232  rebuild:
     233  \tcd $(srcdir) && $(PYTHON) index.py
     234  \t$(MAKE) Makefile
     235  \tcd $(srcdir) && xsltproc examples.xsl examples.xml
     236  \t-cd $(srcdir) && xmllint --valid --noout index.html
     237  
     238  .PHONY: rebuild
     239  
     240  install-data-local: 
     241  \t$(MKDIR_P) $(DESTDIR)$(docdir)/examples
     242  \t-$(INSTALL) -m 0644 $(srcdir)/*.html $(srcdir)/*.c $(DESTDIR)$(docdir)/examples/
     243  
     244  clean-local:
     245  \ttest -f Makefile.am || rm -f test?.xml
     246  
     247  """
     248      examples.sort()
     249      extras.sort()
     250      tests.sort()
     251      EXTRA_DIST=""
     252      for extra in extras:
     253          EXTRA_DIST = EXTRA_DIST + " \\\n\t" + extra
     254      Makefile = Makefile + "EXTRA_DIST =%s\n\n" % (EXTRA_DIST)
     255      check_PROGRAMS=""
     256      for example in examples:
     257          check_PROGRAMS = check_PROGRAMS + " \\\n\t" + example
     258      Makefile = Makefile + "check_PROGRAMS =%s\n\n" % (check_PROGRAMS)
     259      for example in examples:
     260          Makefile = Makefile + "%s_SOURCES = %s.c\n\n" % (example, example)
     261      Makefile = Makefile + "valgrind: \n\t$(MAKE) CHECKER='valgrind' tests\n\n"
     262      Makefile = Makefile + "tests: $(check_PROGRAMS)\n"
     263      Makefile = Makefile + "\t@test -f Makefile.am || test -f test1.xml || $(LN_S) $(srcdir)/test?.xml .\n"
     264      Makefile = Makefile + "\t@(echo '## examples regression tests')\n"
     265      for test in tests:
     266          Makefile = Makefile + "\t@$(CHECKER) %s\n" % (test)
     267      Makefile = Makefile + "\t@rm *.tmp\n"
     268      try:
     269          old = open("Makefile.am", "r").read()
     270          if old != Makefile:
     271              n = open("Makefile.am", "w").write(Makefile)
     272              print("Updated Makefile.am")
     273      except:
     274          print("Failed to read or save Makefile.am")
     275  
     276  if __name__ == "__main__":
     277      load_api()
     278      output = open("examples.xml", "w")
     279      output.write("<examples>\n")
     280  
     281      for file in sorted(glob.glob('*.c')):
     282          parse(file, output)
     283          examples.append(file[:-2])
     284  
     285      dump_symbols(output)
     286      dump_sections(output)
     287      output.write("</examples>\n")
     288      output.close()
     289      #dump_Makefile()
     290