docs: def build_reportnum_kb(fpath):
      """Given the path to a knowledge base file containing the details
         of institutes and the patterns that their preprint report
         numbering schemes take, create a dictionary of regexp search
         patterns to recognise these preprint references in reference
         lines, and a dictionary of replacements for non-standard preprint
         categories in these references.
  
         The knowledge base file should consist only of lines that take one
         of the following 3 formats:
  
           #####Institute Name####
  
         (the name of the institute to which the preprint reference patterns
          belong, e.g. '#####LANL#####', surrounded by 5 # on either side.)
  
           <pattern>
  
         (numeration patterns for an institute's preprints, surrounded by
          < and >.)
  
           seek-term       ---   replace-term
         (i.e. a seek phrase on the left hand side, a replace phrase on the
         right hand side, with the two phrases being separated by 3 hyphens.)
         E.g.:
           ASTRO PH        ---astro-ph
  
         The left-hand side term is a non-standard version of the preprint
         reference category; the right-hand side term is the standard version.
  
         If the KB file cannot be read from, or an unexpected line is
         encountered in the KB, an error message is output to standard error
         and execution is halted with an error-code 0.
  
         @param fpath: (string) the path to the knowledge base file.
         @return: (tuple) containing 2 dictionaries. The first contains regexp
          search patterns used to identify preprint references in a line. This
          dictionary is keyed by a tuple containing the line number of the
          pattern in the KB and the non-standard category string.
          E.g.: (3, 'ASTRO PH').
          The second dictionary contains the standardised category string,
          and is keyed by the non-standard category string. E.g.: 'astro-ph'.
      """
      def _add_institute_preprint_patterns(preprint_classifications,
                                           preprint_numeration_ptns,
                                           preprint_reference_search_regexp_patterns,
                                           standardised_preprint_reference_categories,
                                           kb_line_num):
          """For a list of preprint category strings and preprint numeration
             patterns for a given institute, create the regexp patterns for
             each of the preprint types.  Add the regexp patterns to the
             dictionary of search patterns
             (preprint_reference_search_regexp_patterns), keyed by the line
             number of the institute in the KB, and the preprint category
             search string.  Also add the standardised preprint category string
             to another dictionary, keyed by the line number of its position
             in the KB and its non-standardised version.
             @param preprint_classifications: (list) of tuples whereby each tuple
              contains a preprint category search string and the line number of
              the name of institute to which it belongs in the KB.
              E.g.: (45, 'ASTRO PH').
             @param preprint_numeration_ptns: (list) of preprint reference
              numeration search patterns (strings)
             @param preprint_reference_search_regexp_patterns: (dictionary) of
              regexp patterns used to search in document lines.
             @param standardised_preprint_reference_categories: (dictionary)
              containing the standardised strings for preprint reference
              categories. (E.g. 'astro-ph'.)
             @param kb_line_num: (integer) - the line number int the KB at
              which a given institute name was found.
             @return: None
          """
          if preprint_classifications and preprint_numeration_ptns:
              # the previous institute had both numeration styles and categories
              # for preprint references.
              # build regexps and add them for this institute:
              # First, order the numeration styles by line-length, and build a
              # grouped regexp for recognising numeration:
              ordered_patterns = \
                  order_reportnum_patterns_bylen(preprint_numeration_ptns)
              # create a grouped regexp for numeration part of
              # preprint reference:
              numeration_regexp = \
                  create_institute_numeration_group_regexp_pattern(
                      ordered_patterns)
  
              # for each "classification" part of preprint references, create a
              # complete regex:
              # will be in the style "(categ)-(numatn1|numatn2|numatn3|...)"
              for classification in preprint_classifications:
                  search_pattern_str = ur'(?:^|[^a-zA-Z0-9\/\.\-])([\[\(]?(?P<categ>' \
                                       + classification[0].strip() + u')' \
                                       + numeration_regexp + ur'[\]\)]?)'
  
                  re_search_pattern = re.compile(search_pattern_str,
                                                 re.UNICODE)
                  preprint_reference_search_regexp_patterns[(kb_line_num,
                                                             classification[0])] =\
                      re_search_pattern
                  standardised_preprint_reference_categories[(kb_line_num,
                                                              classification[0])] =\
                      classification[1]
  
      preprint_reference_search_regexp_patterns = {}  # a dictionary of patterns
      # used to recognise
      # categories of preprints
      # as used by various
      # institutes
      standardised_preprint_reference_categories = {}  # dictionary of
      # standardised category
      # strings for preprint cats
      current_institute_preprint_classifications = []  # list of tuples containing
      # preprint categories in
      # their raw & standardised
      # forms, as read from KB
      current_institute_numerations = []               # list of preprint
      # numeration patterns, as
      # read from the KB
  
      # pattern to recognise an institute name line in the KB
      re_institute_name = re.compile(ur'^\*{5}\s*(.+)\s*\*{5}$', re.UNICODE)
  
      # pattern to recognise an institute preprint categ line in the KB
      re_preprint_classification = \
          re.compile(ur'^\s*(\w.*)\s*---\s*(\w.*)\s*$', re.UNICODE)
  
      # pattern to recognise a preprint numeration-style line in KB
      re_numeration_pattern = re.compile(ur'^\<(.+)\>$', re.UNICODE)
  
      kb_line_num = 0    # when making the dictionary of patterns, which is
      # keyed by the category search string, this counter
      # will ensure that patterns in the dictionary are not
      # overwritten if 2 institutes have the same category
      # styles.
      with file_resolving(fpath) as fh:
          for rawline in fh:
              if rawline.startswith('#'):
                  continue
  
              kb_line_num += 1
              m_institute_name = re_institute_name.search(rawline)
              if m_institute_name:
                  # This KB line is the name of an institute
                  # append the last institute's pattern list to the list of
                  # institutes:
                  _add_institute_preprint_patterns(current_institute_preprint_classifications,
                                                   current_institute_numerations,
                                                   preprint_reference_search_regexp_patterns,
                                                   standardised_preprint_reference_categories,
                                                   kb_line_num)
  
                  # Now start a new dictionary to contain the search patterns
                  # for this institute:
                  current_institute_preprint_classifications = []
                  current_institute_numerations = []
                  # move on to the next line
                  continue
  
              m_preprint_classification = \
                  re_preprint_classification.search(rawline)
              if m_preprint_classification:
                  # This KB line contains a preprint classification for
                  # the current institute
                  try:
                      current_institute_preprint_classifications.append((m_preprint_classification.group(1),
                                                                         m_preprint_classification.group(2)))
                  except (AttributeError, NameError):
                      # didn't match this line correctly - skip it
                      pass
                  # move on to the next line
                  continue
  
              m_numeration_pattern = re_numeration_pattern.search(rawline)
              if m_numeration_pattern:
                  # This KB line contains a preprint item numeration pattern
                  # for the current institute
                  try:
                      current_institute_numerations.append(
                          m_numeration_pattern.group(1))
                  except (AttributeError, NameError):
                      # didn't match the numeration pattern correctly - skip it
                      pass
                  continue
  
          _add_institute_preprint_patterns(current_institute_preprint_classifications,
                                           current_institute_numerations,
                                           preprint_reference_search_regexp_patterns,
                                           standardised_preprint_reference_categories,
                                           kb_line_num)
  
      # return the preprint reference patterns and the replacement strings
      # for non-standard categ-strings:
      return (preprint_reference_search_regexp_patterns,
              standardised_preprint_reference_categories)