Use doxygen's own bibtex support (#456)
authorAlpar Juttner <alpar@cs.elte.hu>
Mon, 18 Mar 2013 17:41:19 +0100
changeset 12211c978b5bcc65
parent 1220 eb2f9d453070
child 1223 05b34170866b
Use doxygen's own bibtex support (#456)
doc/CMakeLists.txt
doc/Doxyfile.in
doc/groups.dox
doc/mainpage.dox.in
doc/min_cost_flow.dox
lemon/capacity_scaling.h
lemon/cost_scaling.h
lemon/cycle_canceling.h
lemon/grosso_locatelli_pullan_mc.h
lemon/hartmann_orlin_mmc.h
lemon/howard_mmc.h
lemon/karp_mmc.h
lemon/network_simplex.h
lemon/preflow.h
scripts/bib2dox.py
     1.1 --- a/doc/CMakeLists.txt	Sat Mar 16 14:11:32 2013 +0100
     1.2 +++ b/doc/CMakeLists.txt	Mon Mar 18 17:41:19 2013 +0100
     1.3 @@ -51,7 +51,6 @@
     1.4      COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r8 -sOutputFile=gen-images/nodeshape_3.png ${CMAKE_CURRENT_SOURCE_DIR}/images/nodeshape_3.eps
     1.5      COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r8 -sOutputFile=gen-images/nodeshape_4.png ${CMAKE_CURRENT_SOURCE_DIR}/images/nodeshape_4.eps
     1.6      COMMAND ${CMAKE_COMMAND} -E remove_directory html
     1.7 -    COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/scripts/bib2dox.py ${CMAKE_CURRENT_SOURCE_DIR}/references.bib >references.dox
     1.8      COMMAND ${DOXYGEN_EXECUTABLE} Doxyfile
     1.9      WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
    1.10    )
     2.1 --- a/doc/Doxyfile.in	Sat Mar 16 14:11:32 2013 +0100
     2.2 +++ b/doc/Doxyfile.in	Mon Mar 18 17:41:19 2013 +0100
     2.3 @@ -77,6 +77,7 @@
     2.4  SHOW_NAMESPACES        = YES
     2.5  FILE_VERSION_FILTER    = 
     2.6  LAYOUT_FILE            = "@abs_top_srcdir@/doc/DoxygenLayout.xml"
     2.7 +CITE_BIB_FILES         = "@abs_top_srcdir@/doc/references.bib"
     2.8  #---------------------------------------------------------------------------
     2.9  # configuration options related to warning and progress messages
    2.10  #---------------------------------------------------------------------------
     3.1 --- a/doc/groups.dox	Sat Mar 16 14:11:32 2013 +0100
     3.2 +++ b/doc/groups.dox	Mon Mar 18 17:41:19 2013 +0100
     3.3 @@ -317,7 +317,7 @@
     3.4  
     3.5  This group contains the common graph search algorithms, namely
     3.6  \e breadth-first \e search (BFS) and \e depth-first \e search (DFS)
     3.7 -\ref clrs01algorithms.
     3.8 +\cite clrs01algorithms.
     3.9  */
    3.10  
    3.11  /**
    3.12 @@ -326,7 +326,7 @@
    3.13  \brief Algorithms for finding shortest paths.
    3.14  
    3.15  This group contains the algorithms for finding shortest paths in digraphs
    3.16 -\ref clrs01algorithms.
    3.17 +\cite clrs01algorithms.
    3.18  
    3.19   - \ref Dijkstra algorithm for finding shortest paths from a source node
    3.20     when all arc lengths are non-negative.
    3.21 @@ -348,7 +348,7 @@
    3.22  \brief Algorithms for finding minimum cost spanning trees and arborescences.
    3.23  
    3.24  This group contains the algorithms for finding minimum cost spanning
    3.25 -trees and arborescences \ref clrs01algorithms.
    3.26 +trees and arborescences \cite clrs01algorithms.
    3.27  */
    3.28  
    3.29  /**
    3.30 @@ -357,7 +357,7 @@
    3.31  \brief Algorithms for finding maximum flows.
    3.32  
    3.33  This group contains the algorithms for finding maximum flows and
    3.34 -feasible circulations \ref clrs01algorithms, \ref amo93networkflows.
    3.35 +feasible circulations \cite clrs01algorithms, \cite amo93networkflows.
    3.36  
    3.37  The \e maximum \e flow \e problem is to find a flow of maximum value between
    3.38  a single source and a single target. Formally, there is a \f$G=(V,A)\f$
    3.39 @@ -373,13 +373,13 @@
    3.40  
    3.41  LEMON contains several algorithms for solving maximum flow problems:
    3.42  - \ref EdmondsKarp Edmonds-Karp algorithm
    3.43 -  \ref edmondskarp72theoretical.
    3.44 +  \cite edmondskarp72theoretical.
    3.45  - \ref Preflow Goldberg-Tarjan's preflow push-relabel algorithm
    3.46 -  \ref goldberg88newapproach.
    3.47 +  \cite goldberg88newapproach.
    3.48  - \ref DinitzSleatorTarjan Dinitz's blocking flow algorithm with dynamic trees
    3.49 -  \ref dinic70algorithm, \ref sleator83dynamic.
    3.50 +  \cite dinic70algorithm, \cite sleator83dynamic.
    3.51  - \ref GoldbergTarjan !Preflow push-relabel algorithm with dynamic trees
    3.52 -  \ref goldberg88newapproach, \ref sleator83dynamic.
    3.53 +  \cite goldberg88newapproach, \cite sleator83dynamic.
    3.54  
    3.55  In most cases the \ref Preflow algorithm provides the
    3.56  fastest method for computing a maximum flow. All implementations
    3.57 @@ -399,20 +399,20 @@
    3.58  \brief Algorithms for finding minimum cost flows and circulations.
    3.59  
    3.60  This group contains the algorithms for finding minimum cost flows and
    3.61 -circulations \ref amo93networkflows. For more information about this
    3.62 +circulations \cite amo93networkflows. For more information about this
    3.63  problem and its dual solution, see: \ref min_cost_flow
    3.64  "Minimum Cost Flow Problem".
    3.65  
    3.66  LEMON contains several algorithms for this problem.
    3.67   - \ref NetworkSimplex Primal Network Simplex algorithm with various
    3.68 -   pivot strategies \ref dantzig63linearprog, \ref kellyoneill91netsimplex.
    3.69 +   pivot strategies \cite dantzig63linearprog, \cite kellyoneill91netsimplex.
    3.70   - \ref CostScaling Cost Scaling algorithm based on push/augment and
    3.71 -   relabel operations \ref goldberg90approximation, \ref goldberg97efficient,
    3.72 -   \ref bunnagel98efficient.
    3.73 +   relabel operations \cite goldberg90approximation, \cite goldberg97efficient,
    3.74 +   \cite bunnagel98efficient.
    3.75   - \ref CapacityScaling Capacity Scaling algorithm based on the successive
    3.76 -   shortest path method \ref edmondskarp72theoretical.
    3.77 +   shortest path method \cite edmondskarp72theoretical.
    3.78   - \ref CycleCanceling Cycle-Canceling algorithms, two of which are
    3.79 -   strongly polynomial \ref klein67primal, \ref goldberg89cyclecanceling.
    3.80 +   strongly polynomial \cite klein67primal, \cite goldberg89cyclecanceling.
    3.81  
    3.82  In general, \ref NetworkSimplex and \ref CostScaling are the most efficient
    3.83  implementations.
    3.84 @@ -430,7 +430,7 @@
    3.85  data are required to be integer).
    3.86  
    3.87  For more details about these implementations and for a comprehensive 
    3.88 -experimental study, see the paper \ref KiralyKovacs12MCF.
    3.89 +experimental study, see the paper \cite KiralyKovacs12MCF.
    3.90  It also compares these codes to other publicly available
    3.91  minimum cost flow solvers.
    3.92  */
    3.93 @@ -471,7 +471,7 @@
    3.94  \brief Algorithms for finding minimum mean cycles.
    3.95  
    3.96  This group contains the algorithms for finding minimum mean cycles
    3.97 -\ref amo93networkflows, \ref karp78characterization.
    3.98 +\cite amo93networkflows, \cite karp78characterization.
    3.99  
   3.100  The \e minimum \e mean \e cycle \e problem is to find a directed cycle
   3.101  of minimum mean length (cost) in a digraph.
   3.102 @@ -487,11 +487,11 @@
   3.103  function.
   3.104  
   3.105  LEMON contains three algorithms for solving the minimum mean cycle problem:
   3.106 -- \ref KarpMmc Karp's original algorithm \ref karp78characterization.
   3.107 +- \ref KarpMmc Karp's original algorithm \cite karp78characterization.
   3.108  - \ref HartmannOrlinMmc Hartmann-Orlin's algorithm, which is an improved
   3.109 -  version of Karp's algorithm \ref hartmann93finding.
   3.110 +  version of Karp's algorithm \cite hartmann93finding.
   3.111  - \ref HowardMmc Howard's policy iteration algorithm
   3.112 -  \ref dasdan98minmeancycle, \ref dasdan04experimental.
   3.113 +  \cite dasdan98minmeancycle, \cite dasdan04experimental.
   3.114  
   3.115  In practice, the \ref HowardMmc "Howard" algorithm turned out to be by far the
   3.116  most efficient one, though the best known theoretical bound on its running
   3.117 @@ -647,8 +647,8 @@
   3.118  Various LP solvers could be used in the same manner with this
   3.119  high-level interface.
   3.120  
   3.121 -The currently supported solvers are \ref glpk, \ref clp, \ref cbc,
   3.122 -\ref cplex, \ref soplex.
   3.123 +The currently supported solvers are \cite glpk, \cite clp, \cite cbc,
   3.124 +\cite cplex, \cite soplex.
   3.125  */
   3.126  
   3.127  /**
     4.1 --- a/doc/mainpage.dox.in	Sat Mar 16 14:11:32 2013 +0100
     4.2 +++ b/doc/mainpage.dox.in	Mon Mar 18 17:41:19 2013 +0100
     4.3 @@ -25,7 +25,7 @@
     4.4  and <b>O</b>ptimization in <b>N</b>etworks</i>.
     4.5  It is a C++ template library providing efficient implementations of common
     4.6  data structures and algorithms with focus on combinatorial optimization
     4.7 -tasks connected mainly with graphs and networks \ref DezsoJuttnerKovacs11Lemon.
     4.8 +tasks connected mainly with graphs and networks \cite DezsoJuttnerKovacs11Lemon.
     4.9  
    4.10  <b>
    4.11  LEMON is an <a class="el" href="http://opensource.org/">open&nbsp;source</a>
    4.12 @@ -37,12 +37,12 @@
    4.13  
    4.14  The project is maintained by the
    4.15  <a href="http://www.cs.elte.hu/egres/">Egerv&aacute;ry Research Group on
    4.16 -Combinatorial Optimization</a> \ref egres
    4.17 +Combinatorial Optimization</a> \cite egres
    4.18  at the Operations Research Department of the
    4.19  <a href="http://www.elte.hu/en/">E&ouml;tv&ouml;s Lor&aacute;nd University</a>,
    4.20  Budapest, Hungary.
    4.21  LEMON is also a member of the <a href="http://www.coin-or.org/">COIN-OR</a>
    4.22 -initiative \ref coinor.
    4.23 +initiative \cite coinor.
    4.24  
    4.25  \section howtoread How to Read the Documentation
    4.26  
     5.1 --- a/doc/min_cost_flow.dox	Sat Mar 16 14:11:32 2013 +0100
     5.2 +++ b/doc/min_cost_flow.dox	Mon Mar 18 17:41:19 2013 +0100
     5.3 @@ -26,7 +26,7 @@
     5.4  The \e minimum \e cost \e flow \e problem is to find a feasible flow of
     5.5  minimum total cost from a set of supply nodes to a set of demand nodes
     5.6  in a network with capacity constraints (lower and upper bounds)
     5.7 -and arc costs \ref amo93networkflows.
     5.8 +and arc costs \cite amo93networkflows.
     5.9  
    5.10  Formally, let \f$G=(V,A)\f$ be a digraph, \f$lower: A\rightarrow\mathbf{R}\f$,
    5.11  \f$upper: A\rightarrow\mathbf{R}\cup\{+\infty\}\f$ denote the lower and
     6.1 --- a/lemon/capacity_scaling.h	Sat Mar 16 14:11:32 2013 +0100
     6.2 +++ b/lemon/capacity_scaling.h	Mon Mar 18 17:41:19 2013 +0100
     6.3 @@ -66,8 +66,8 @@
     6.4    ///
     6.5    /// \ref CapacityScaling implements the capacity scaling version
     6.6    /// of the successive shortest path algorithm for finding a
     6.7 -  /// \ref min_cost_flow "minimum cost flow" \ref amo93networkflows,
     6.8 -  /// \ref edmondskarp72theoretical. It is an efficient dual
     6.9 +  /// \ref min_cost_flow "minimum cost flow" \cite amo93networkflows,
    6.10 +  /// \cite edmondskarp72theoretical. It is an efficient dual
    6.11    /// solution method, which runs in polynomial time
    6.12    /// \f$O(e\log U (n+e)\log n)\f$, where <i>U</i> denotes the maximum
    6.13    /// of node supply and arc capacity values.
     7.1 --- a/lemon/cost_scaling.h	Sat Mar 16 14:11:32 2013 +0100
     7.2 +++ b/lemon/cost_scaling.h	Mon Mar 18 17:41:19 2013 +0100
     7.3 @@ -91,8 +91,8 @@
     7.4    ///
     7.5    /// \ref CostScaling implements a cost scaling algorithm that performs
     7.6    /// push/augment and relabel operations for finding a \ref min_cost_flow
     7.7 -  /// "minimum cost flow" \ref amo93networkflows, \ref goldberg90approximation,
     7.8 -  /// \ref goldberg97efficient, \ref bunnagel98efficient.
     7.9 +  /// "minimum cost flow" \cite amo93networkflows, \cite goldberg90approximation,
    7.10 +  /// \cite goldberg97efficient, \cite bunnagel98efficient.
    7.11    /// It is a highly efficient primal-dual solution method, which
    7.12    /// can be viewed as the generalization of the \ref Preflow
    7.13    /// "preflow push-relabel" algorithm for the maximum flow problem.
     8.1 --- a/lemon/cycle_canceling.h	Sat Mar 16 14:11:32 2013 +0100
     8.2 +++ b/lemon/cycle_canceling.h	Mon Mar 18 17:41:19 2013 +0100
     8.3 @@ -47,8 +47,8 @@
     8.4    ///
     8.5    /// \ref CycleCanceling implements three different cycle-canceling
     8.6    /// algorithms for finding a \ref min_cost_flow "minimum cost flow"
     8.7 -  /// \ref amo93networkflows, \ref klein67primal,
     8.8 -  /// \ref goldberg89cyclecanceling.
     8.9 +  /// \cite amo93networkflows, \cite klein67primal,
    8.10 +  /// \cite goldberg89cyclecanceling.
    8.11    /// The most efficent one is the \ref CANCEL_AND_TIGHTEN
    8.12    /// "Cancel-and-Tighten" algorithm, thus it is the default method.
    8.13    /// It runs in strongly polynomial time O(n<sup>2</sup>e<sup>2</sup>log(n)),
    8.14 @@ -131,13 +131,13 @@
    8.15        SIMPLE_CYCLE_CANCELING,
    8.16        /// The "Minimum Mean Cycle-Canceling" algorithm, which is a
    8.17        /// well-known strongly polynomial method
    8.18 -      /// \ref goldberg89cyclecanceling. It improves along a
    8.19 +      /// \cite goldberg89cyclecanceling. It improves along a
    8.20        /// \ref min_mean_cycle "minimum mean cycle" in each iteration.
    8.21        /// Its running time complexity is O(n<sup>2</sup>e<sup>3</sup>log(n)).
    8.22        MINIMUM_MEAN_CYCLE_CANCELING,
    8.23        /// The "Cancel-and-Tighten" algorithm, which can be viewed as an
    8.24        /// improved version of the previous method
    8.25 -      /// \ref goldberg89cyclecanceling.
    8.26 +      /// \cite goldberg89cyclecanceling.
    8.27        /// It is faster both in theory and in practice, its running time
    8.28        /// complexity is O(n<sup>2</sup>e<sup>2</sup>log(n)).
    8.29        CANCEL_AND_TIGHTEN
     9.1 --- a/lemon/grosso_locatelli_pullan_mc.h	Sat Mar 16 14:11:32 2013 +0100
     9.2 +++ b/lemon/grosso_locatelli_pullan_mc.h	Mon Mar 18 17:41:19 2013 +0100
     9.3 @@ -40,7 +40,7 @@
     9.4    ///
     9.5    /// \ref GrossoLocatelliPullanMc implements the iterated local search
     9.6    /// algorithm of Grosso, Locatelli, and Pullan for solving the \e maximum
     9.7 -  /// \e clique \e problem \ref grosso08maxclique.
     9.8 +  /// \e clique \e problem \cite grosso08maxclique.
     9.9    /// It is to find the largest complete subgraph (\e clique) in an
    9.10    /// undirected graph, i.e., the largest set of nodes where each
    9.11    /// pair of nodes is connected.
    10.1 --- a/lemon/hartmann_orlin_mmc.h	Sat Mar 16 14:11:32 2013 +0100
    10.2 +++ b/lemon/hartmann_orlin_mmc.h	Mon Mar 18 17:41:19 2013 +0100
    10.3 @@ -98,7 +98,7 @@
    10.4    ///
    10.5    /// This class implements the Hartmann-Orlin algorithm for finding
    10.6    /// a directed cycle of minimum mean cost in a digraph
    10.7 -  /// \ref hartmann93finding, \ref dasdan98minmeancycle.
    10.8 +  /// \cite hartmann93finding, \cite dasdan98minmeancycle.
    10.9    /// This method is based on \ref KarpMmc "Karp"'s original algorithm, but
   10.10    /// applies an early termination scheme. It makes the algorithm
   10.11    /// significantly faster for some problem instances, but slower for others.
    11.1 --- a/lemon/howard_mmc.h	Sat Mar 16 14:11:32 2013 +0100
    11.2 +++ b/lemon/howard_mmc.h	Mon Mar 18 17:41:19 2013 +0100
    11.3 @@ -98,7 +98,7 @@
    11.4    ///
    11.5    /// This class implements Howard's policy iteration algorithm for finding
    11.6    /// a directed cycle of minimum mean cost in a digraph
    11.7 -  /// \ref dasdan98minmeancycle, \ref dasdan04experimental.
    11.8 +  /// \cite dasdan98minmeancycle, \cite dasdan04experimental.
    11.9    /// This class provides the most efficient algorithm for the
   11.10    /// minimum mean cycle problem, though the best known theoretical
   11.11    /// bound on its running time is exponential.
    12.1 --- a/lemon/karp_mmc.h	Sat Mar 16 14:11:32 2013 +0100
    12.2 +++ b/lemon/karp_mmc.h	Mon Mar 18 17:41:19 2013 +0100
    12.3 @@ -98,7 +98,7 @@
    12.4    ///
    12.5    /// This class implements Karp's algorithm for finding a directed
    12.6    /// cycle of minimum mean cost in a digraph
    12.7 -  /// \ref karp78characterization, \ref dasdan98minmeancycle.
    12.8 +  /// \cite karp78characterization, \cite dasdan98minmeancycle.
    12.9    /// It runs in time O(ne) and uses space O(n<sup>2</sup>+e).
   12.10    ///
   12.11    /// \tparam GR The type of the digraph the algorithm runs on.
    13.1 --- a/lemon/network_simplex.h	Sat Mar 16 14:11:32 2013 +0100
    13.2 +++ b/lemon/network_simplex.h	Mon Mar 18 17:41:19 2013 +0100
    13.3 @@ -41,8 +41,8 @@
    13.4    ///
    13.5    /// \ref NetworkSimplex implements the primal Network Simplex algorithm
    13.6    /// for finding a \ref min_cost_flow "minimum cost flow"
    13.7 -  /// \ref amo93networkflows, \ref dantzig63linearprog,
    13.8 -  /// \ref kellyoneill91netsimplex.
    13.9 +  /// \cite amo93networkflows, \cite dantzig63linearprog,
   13.10 +  /// \cite kellyoneill91netsimplex.
   13.11    /// This algorithm is a highly efficient specialized version of the
   13.12    /// linear programming simplex method directly for the minimum cost
   13.13    /// flow problem.
    14.1 --- a/lemon/preflow.h	Sat Mar 16 14:11:32 2013 +0100
    14.2 +++ b/lemon/preflow.h	Mon Mar 18 17:41:19 2013 +0100
    14.3 @@ -102,8 +102,8 @@
    14.4    ///
    14.5    /// This class provides an implementation of Goldberg-Tarjan's \e preflow
    14.6    /// \e push-relabel algorithm producing a \ref max_flow
    14.7 -  /// "flow of maximum value" in a digraph \ref clrs01algorithms,
    14.8 -  /// \ref amo93networkflows, \ref goldberg88newapproach.
    14.9 +  /// "flow of maximum value" in a digraph \cite clrs01algorithms,
   14.10 +  /// \cite amo93networkflows, \cite goldberg88newapproach.
   14.11    /// The preflow algorithms are the fastest known maximum
   14.12    /// flow algorithms. The current implementation uses a mixture of the
   14.13    /// \e "highest label" and the \e "bound decrease" heuristics.
    15.1 --- a/scripts/bib2dox.py	Sat Mar 16 14:11:32 2013 +0100
    15.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.3 @@ -1,816 +0,0 @@
    15.4 -#! /usr/bin/env python
    15.5 -"""
    15.6 -  BibTeX to Doxygen converter
    15.7 -  Usage: python bib2dox.py bibfile.bib > bibfile.dox
    15.8 -
    15.9 -  This file is a part of LEMON, a generic C++ optimization library.
   15.10 -
   15.11 -  **********************************************************************
   15.12 -
   15.13 -  This code is the modification of the BibTeX to XML converter
   15.14 -  by Vidar Bronken Gundersen et al.
   15.15 -  See the original copyright notices below. 
   15.16 -
   15.17 -  **********************************************************************
   15.18 -
   15.19 -  Decoder for bibliographic data, BibTeX
   15.20 -  Usage: python bibtex2xml.py bibfile.bib > bibfile.xml
   15.21 -
   15.22 -  v.8
   15.23 -  (c)2002-06-23 Vidar Bronken Gundersen
   15.24 -  http://bibtexml.sf.net/
   15.25 -  Reuse approved as long as this notification is kept.
   15.26 -  Licence: GPL.
   15.27 -
   15.28 -  Contributions/thanks to:
   15.29 -  Egon Willighagen, http://sf.net/projects/jreferences/
   15.30 -  Richard Mahoney (for providing a test case)
   15.31 -
   15.32 -  Editted by Sara Sprenkle to be more robust and handle more bibtex features.
   15.33 -  (c) 2003-01-15
   15.34 -
   15.35 -  1.  Changed bibtex: tags to bibxml: tags.
   15.36 -  2.  Use xmlns:bibxml="http://bibtexml.sf.net/"
   15.37 -  3.  Allow spaces between @type and first {
   15.38 -  4.  "author" fields with multiple authors split by " and "
   15.39 -      are put in separate xml "bibxml:author" tags.
   15.40 -  5.  Option for Titles: words are capitalized
   15.41 -      only if first letter in title or capitalized inside braces
   15.42 -  6.  Removes braces from within field values
   15.43 -  7.  Ignores comments in bibtex file (including @comment{ or % )
   15.44 -  8.  Replaces some special latex tags, e.g., replaces ~ with '&#160;'
   15.45 -  9.  Handles bibtex @string abbreviations
   15.46 -        --> includes bibtex's default abbreviations for months
   15.47 -        --> does concatenation of abbr # " more " and " more " # abbr
   15.48 -  10. Handles @type( ... ) or @type{ ... }
   15.49 -  11. The keywords field is split on , or ; and put into separate xml
   15.50 -      "bibxml:keywords" tags
   15.51 -  12. Ignores @preamble
   15.52 -
   15.53 -  Known Limitations
   15.54 -  1.  Does not transform Latex encoding like math mode and special
   15.55 -      latex symbols.
   15.56 -  2.  Does not parse author fields into first and last names.
   15.57 -      E.g., It does not do anything special to an author whose name is
   15.58 -      in the form LAST_NAME, FIRST_NAME
   15.59 -      In "author" tag, will show up as
   15.60 -      <bibxml:author>LAST_NAME, FIRST_NAME</bibxml:author>
   15.61 -  3.  Does not handle "crossref" fields other than to print
   15.62 -      <bibxml:crossref>...</bibxml:crossref>
   15.63 -  4.  Does not inform user of the input's format errors.  You just won't
   15.64 -      be able to transform the file later with XSL
   15.65 -
   15.66 -  You will have to manually edit the XML output if you need to handle
   15.67 -  these (and unknown) limitations.
   15.68 -
   15.69 -"""
   15.70 -
   15.71 -import string, re
   15.72 -
   15.73 -# set of valid name characters
   15.74 -valid_name_chars = '[\w\-:]'
   15.75 -
   15.76 -#
   15.77 -# define global regular expression variables
   15.78 -#
   15.79 -author_rex = re.compile('\s+and\s+')
   15.80 -rembraces_rex = re.compile('[{}]')
   15.81 -capitalize_rex = re.compile('({[^}]*})')
   15.82 -
   15.83 -# used by bibtexkeywords(data)
   15.84 -keywords_rex = re.compile('[,;]')
   15.85 -
   15.86 -# used by concat_line(line)
   15.87 -concatsplit_rex = re.compile('\s*#\s*')
   15.88 -
   15.89 -# split on {, }, or " in verify_out_of_braces
   15.90 -delimiter_rex = re.compile('([{}"])',re.I)
   15.91 -
   15.92 -field_rex = re.compile('\s*(\w*)\s*=\s*(.*)')
   15.93 -data_rex = re.compile('\s*(\w*)\s*=\s*([^,]*),?')
   15.94 -
   15.95 -url_rex = re.compile('\\\url\{([^}]*)\}')
   15.96 -
   15.97 -#
   15.98 -# styles for html formatting
   15.99 -#
  15.100 -divstyle = 'margin-top: -4ex; margin-left: 10em;'
  15.101 -
  15.102 -#
  15.103 -# return the string parameter without braces
  15.104 -#
  15.105 -def transformurls(str):
  15.106 -    return url_rex.sub(r'<a href="\1">\1</a>', str)
  15.107 -
  15.108 -#
  15.109 -# return the string parameter without braces
  15.110 -#
  15.111 -def removebraces(str):
  15.112 -    return rembraces_rex.sub('', str)
  15.113 -
  15.114 -#
  15.115 -# latex-specific replacements
  15.116 -# (do this after braces were removed)
  15.117 -#
  15.118 -def latexreplacements(line):
  15.119 -    line = string.replace(line, '~', '&nbsp;')
  15.120 -    line = string.replace(line, '\\\'a', '&aacute;')
  15.121 -    line = string.replace(line, '\\"a', '&auml;')
  15.122 -    line = string.replace(line, '\\\'e', '&eacute;')
  15.123 -    line = string.replace(line, '\\"e', '&euml;')
  15.124 -    line = string.replace(line, '\\\'i', '&iacute;')
  15.125 -    line = string.replace(line, '\\"i', '&iuml;')
  15.126 -    line = string.replace(line, '\\\'o', '&oacute;')
  15.127 -    line = string.replace(line, '\\"o', '&ouml;')
  15.128 -    line = string.replace(line, '\\\'u', '&uacute;')
  15.129 -    line = string.replace(line, '\\"u', '&uuml;')
  15.130 -    line = string.replace(line, '\\H o', '&otilde;')
  15.131 -    line = string.replace(line, '\\H u', '&uuml;')   # &utilde; does not exist
  15.132 -    line = string.replace(line, '\\\'A', '&Aacute;')
  15.133 -    line = string.replace(line, '\\"A', '&Auml;')
  15.134 -    line = string.replace(line, '\\\'E', '&Eacute;')
  15.135 -    line = string.replace(line, '\\"E', '&Euml;')
  15.136 -    line = string.replace(line, '\\\'I', '&Iacute;')
  15.137 -    line = string.replace(line, '\\"I', '&Iuml;')
  15.138 -    line = string.replace(line, '\\\'O', '&Oacute;')
  15.139 -    line = string.replace(line, '\\"O', '&Ouml;')
  15.140 -    line = string.replace(line, '\\\'U', '&Uacute;')
  15.141 -    line = string.replace(line, '\\"U', '&Uuml;')
  15.142 -    line = string.replace(line, '\\H O', '&Otilde;')
  15.143 -    line = string.replace(line, '\\H U', '&Uuml;')   # &Utilde; does not exist
  15.144 -
  15.145 -    return line
  15.146 -
  15.147 -#
  15.148 -# copy characters form a string decoding html expressions (&xyz;)
  15.149 -#
  15.150 -def copychars(str, ifrom, count):
  15.151 -    result = ''
  15.152 -    i = ifrom
  15.153 -    c = 0
  15.154 -    html_spec = False
  15.155 -    while (i < len(str)) and (c < count):
  15.156 -        if str[i] == '&':
  15.157 -            html_spec = True;
  15.158 -            if i+1 < len(str):
  15.159 -                result += str[i+1]
  15.160 -            c += 1
  15.161 -            i += 2
  15.162 -        else:
  15.163 -            if not html_spec:
  15.164 -                if ((str[i] >= 'A') and (str[i] <= 'Z')) or \
  15.165 -                   ((str[i] >= 'a') and (str[i] <= 'z')):
  15.166 -                    result += str[i]
  15.167 -                    c += 1
  15.168 -            elif str[i] == ';':
  15.169 -                html_spec = False;
  15.170 -            i += 1
  15.171 -    
  15.172 -    return result
  15.173 -
  15.174 -
  15.175 -# 
  15.176 -# Handle a list of authors (separated by 'and').
  15.177 -# It gives back an array of the follwing values:
  15.178 -#  - num: the number of authors,
  15.179 -#  - list: the list of the author names,
  15.180 -#  - text: the bibtex text (separated by commas and/or 'and')
  15.181 -#  - abbrev: abbreviation that can be used for indicate the
  15.182 -#    bibliography entries
  15.183 -#
  15.184 -def bibtexauthor(data):
  15.185 -    result = {}
  15.186 -    bibtex = ''
  15.187 -    result['list'] = author_rex.split(data)
  15.188 -    result['num'] = len(result['list'])
  15.189 -    for i, author in enumerate(result['list']):
  15.190 -        # general transformations
  15.191 -        author = latexreplacements(removebraces(author.strip()))
  15.192 -        # transform "Xyz, A. B." to "A. B. Xyz"
  15.193 -        pos = author.find(',')
  15.194 -        if pos != -1:
  15.195 -            author = author[pos+1:].strip() + ' ' + author[:pos].strip()
  15.196 -        result['list'][i] = author
  15.197 -        bibtex += author + '#'
  15.198 -    bibtex = bibtex[:-1]
  15.199 -    if result['num'] > 1:
  15.200 -        ix = bibtex.rfind('#')
  15.201 -        if result['num'] == 2:
  15.202 -            bibtex = bibtex[:ix] + ' and ' + bibtex[ix+1:]
  15.203 -        else:
  15.204 -            bibtex = bibtex[:ix] + ', and ' + bibtex[ix+1:]
  15.205 -    bibtex = bibtex.replace('#', ', ')
  15.206 -    result['text'] = bibtex
  15.207 -    
  15.208 -    result['abbrev'] = ''
  15.209 -    for author in result['list']:
  15.210 -        pos = author.rfind(' ') + 1
  15.211 -        count = 1
  15.212 -        if result['num'] == 1:
  15.213 -            count = 3
  15.214 -        result['abbrev'] += copychars(author, pos, count)
  15.215 -
  15.216 -    return result
  15.217 -
  15.218 -
  15.219 -#
  15.220 -# data = title string
  15.221 -# @return the capitalized title (first letter is capitalized), rest are capitalized
  15.222 -# only if capitalized inside braces
  15.223 -#
  15.224 -def capitalizetitle(data):
  15.225 -    title_list = capitalize_rex.split(data)
  15.226 -    title = ''
  15.227 -    count = 0
  15.228 -    for phrase in title_list:
  15.229 -         check = string.lstrip(phrase)
  15.230 -
  15.231 -         # keep phrase's capitalization the same
  15.232 -         if check.find('{') == 0:
  15.233 -              title += removebraces(phrase)
  15.234 -         else:
  15.235 -         # first word --> capitalize first letter (after spaces)
  15.236 -              if count == 0:
  15.237 -                  title += check.capitalize()
  15.238 -              else:
  15.239 -                  title += phrase.lower()
  15.240 -         count = count + 1
  15.241 -
  15.242 -    return title
  15.243 -
  15.244 -
  15.245 -#
  15.246 -# @return the bibtex for the title
  15.247 -# @param data --> title string
  15.248 -# braces are removed from title
  15.249 -#
  15.250 -def bibtextitle(data, entrytype):
  15.251 -    if entrytype in ('book', 'inbook'):
  15.252 -        title = removebraces(data.strip())
  15.253 -    else:
  15.254 -        title = removebraces(capitalizetitle(data.strip()))
  15.255 -    bibtex = title
  15.256 -    return bibtex
  15.257 -
  15.258 -
  15.259 -#
  15.260 -# function to compare entry lists
  15.261 -#
  15.262 -def entry_cmp(x, y):
  15.263 -    return cmp(x[0], y[0])
  15.264 -
  15.265 -
  15.266 -#
  15.267 -# print the XML for the transformed "filecont_source"
  15.268 -#
  15.269 -def bibtexdecoder(filecont_source):
  15.270 -    filecont = []
  15.271 -    file = []
  15.272 -    
  15.273 -    # want @<alphanumeric chars><spaces>{<spaces><any chars>,
  15.274 -    pubtype_rex = re.compile('@(\w*)\s*{\s*(.*),')
  15.275 -    endtype_rex = re.compile('}\s*$')
  15.276 -    endtag_rex = re.compile('^\s*}\s*$')
  15.277 -
  15.278 -    bracefield_rex = re.compile('\s*(\w*)\s*=\s*(.*)')
  15.279 -    bracedata_rex = re.compile('\s*(\w*)\s*=\s*{(.*)},?')
  15.280 -
  15.281 -    quotefield_rex = re.compile('\s*(\w*)\s*=\s*(.*)')
  15.282 -    quotedata_rex = re.compile('\s*(\w*)\s*=\s*"(.*)",?')
  15.283 -
  15.284 -    for line in filecont_source:
  15.285 -        line = line[:-1]
  15.286 -
  15.287 -        # encode character entities
  15.288 -        line = string.replace(line, '&', '&amp;')
  15.289 -        line = string.replace(line, '<', '&lt;')
  15.290 -        line = string.replace(line, '>', '&gt;')
  15.291 -
  15.292 -        # start entry: publication type (store for later use)
  15.293 -        if pubtype_rex.match(line):
  15.294 -        # want @<alphanumeric chars><spaces>{<spaces><any chars>,
  15.295 -            entrycont = {}
  15.296 -            entry = []
  15.297 -            entrytype = pubtype_rex.sub('\g<1>',line)
  15.298 -            entrytype = string.lower(entrytype)
  15.299 -            entryid   = pubtype_rex.sub('\g<2>', line)
  15.300 -
  15.301 -        # end entry if just a }
  15.302 -        elif endtype_rex.match(line):
  15.303 -            # generate doxygen code for the entry
  15.304 -
  15.305 -            # enty type related formattings
  15.306 -            if entrytype in ('book', 'inbook'):
  15.307 -                entrycont['title'] = '<em>' + entrycont['title'] + '</em>'
  15.308 -                if not entrycont.has_key('author'):
  15.309 -                    entrycont['author'] = entrycont['editor']
  15.310 -                    entrycont['author']['text'] += ', editors'
  15.311 -            elif entrytype == 'article':
  15.312 -                entrycont['journal'] = '<em>' + entrycont['journal'] + '</em>'
  15.313 -            elif entrytype in ('inproceedings', 'incollection', 'conference'):
  15.314 -                entrycont['booktitle'] = '<em>' + entrycont['booktitle'] + '</em>'
  15.315 -            elif entrytype == 'techreport':
  15.316 -                if not entrycont.has_key('type'):
  15.317 -                    entrycont['type'] = 'Technical report'
  15.318 -            elif entrytype == 'mastersthesis':
  15.319 -                entrycont['type'] = 'Master\'s thesis'
  15.320 -            elif entrytype == 'phdthesis':
  15.321 -                entrycont['type'] = 'PhD thesis'
  15.322 -
  15.323 -            for eline in entrycont:
  15.324 -                if eline != '':
  15.325 -                    eline = latexreplacements(eline)
  15.326 -
  15.327 -            if entrycont.has_key('pages') and (entrycont['pages'] != ''):
  15.328 -                entrycont['pages'] = string.replace(entrycont['pages'], '--', '-')
  15.329 -
  15.330 -            if entrycont.has_key('author') and (entrycont['author'] != ''):
  15.331 -                entry.append(entrycont['author']['text'] + '.')
  15.332 -            if entrycont.has_key('title') and (entrycont['title'] != ''):
  15.333 -                entry.append(entrycont['title'] + '.')
  15.334 -            if entrycont.has_key('journal') and (entrycont['journal'] != ''):
  15.335 -                entry.append(entrycont['journal'] + ',')
  15.336 -            if entrycont.has_key('booktitle') and (entrycont['booktitle'] != ''):
  15.337 -                entry.append('In ' + entrycont['booktitle'] + ',')
  15.338 -            if entrycont.has_key('type') and (entrycont['type'] != ''):
  15.339 -                eline = entrycont['type']
  15.340 -                if entrycont.has_key('number') and (entrycont['number'] != ''):
  15.341 -                    eline += ' ' + entrycont['number']
  15.342 -                eline += ','
  15.343 -                entry.append(eline)
  15.344 -            if entrycont.has_key('institution') and (entrycont['institution'] != ''):
  15.345 -                entry.append(entrycont['institution'] + ',')
  15.346 -            if entrycont.has_key('publisher') and (entrycont['publisher'] != ''):
  15.347 -                entry.append(entrycont['publisher'] + ',')
  15.348 -            if entrycont.has_key('school') and (entrycont['school'] != ''):
  15.349 -                entry.append(entrycont['school'] + ',')
  15.350 -            if entrycont.has_key('address') and (entrycont['address'] != ''):
  15.351 -                entry.append(entrycont['address'] + ',')
  15.352 -            if entrycont.has_key('edition') and (entrycont['edition'] != ''):
  15.353 -                entry.append(entrycont['edition'] + ' edition,')
  15.354 -            if entrycont.has_key('howpublished') and (entrycont['howpublished'] != ''):
  15.355 -                entry.append(entrycont['howpublished'] + ',')
  15.356 -            if entrycont.has_key('volume') and (entrycont['volume'] != ''):
  15.357 -                eline = entrycont['volume'];
  15.358 -                if entrycont.has_key('number') and (entrycont['number'] != ''):
  15.359 -                    eline += '(' + entrycont['number'] + ')'
  15.360 -                if entrycont.has_key('pages') and (entrycont['pages'] != ''):
  15.361 -                    eline += ':' + entrycont['pages']
  15.362 -                eline += ','
  15.363 -                entry.append(eline)
  15.364 -            else:
  15.365 -                if entrycont.has_key('pages') and (entrycont['pages'] != ''):
  15.366 -                    entry.append('pages ' + entrycont['pages'] + ',')
  15.367 -            if entrycont.has_key('year') and (entrycont['year'] != ''):
  15.368 -                if entrycont.has_key('month') and (entrycont['month'] != ''):
  15.369 -                    entry.append(entrycont['month'] + ' ' + entrycont['year'] + '.')
  15.370 -                else:
  15.371 -                    entry.append(entrycont['year'] + '.')
  15.372 -            if entrycont.has_key('note') and (entrycont['note'] != ''):
  15.373 -                entry.append(entrycont['note'] + '.')
  15.374 -            if entrycont.has_key('url') and (entrycont['url'] != ''):
  15.375 -                entry.append(entrycont['url'] + '.')
  15.376 -
  15.377 -            # generate keys for sorting and for the output
  15.378 -            sortkey = ''
  15.379 -            bibkey = ''
  15.380 -            if entrycont.has_key('author'):
  15.381 -                for author in entrycont['author']['list']:
  15.382 -                    sortkey += copychars(author, author.rfind(' ')+1, len(author))
  15.383 -                bibkey = entrycont['author']['abbrev']
  15.384 -            else:
  15.385 -                bibkey = 'x'
  15.386 -            if entrycont.has_key('year'):
  15.387 -                sortkey += entrycont['year']
  15.388 -                bibkey += entrycont['year'][-2:]
  15.389 -            if entrycont.has_key('title'):
  15.390 -                sortkey += entrycont['title']
  15.391 -            if entrycont.has_key('key'):
  15.392 -                sortkey = entrycont['key'] + sortkey
  15.393 -                bibkey = entrycont['key']
  15.394 -            entry.insert(0, sortkey)
  15.395 -            entry.insert(1, bibkey)
  15.396 -            entry.insert(2, entryid)
  15.397 -           
  15.398 -            # add the entry to the file contents
  15.399 -            filecont.append(entry)
  15.400 -
  15.401 -        else:
  15.402 -            # field, publication info
  15.403 -            field = ''
  15.404 -            data = ''
  15.405 -            
  15.406 -            # field = {data} entries
  15.407 -            if bracedata_rex.match(line):
  15.408 -                field = bracefield_rex.sub('\g<1>', line)
  15.409 -                field = string.lower(field)
  15.410 -                data =  bracedata_rex.sub('\g<2>', line)
  15.411 -
  15.412 -            # field = "data" entries
  15.413 -            elif quotedata_rex.match(line):
  15.414 -                field = quotefield_rex.sub('\g<1>', line)
  15.415 -                field = string.lower(field)
  15.416 -                data =  quotedata_rex.sub('\g<2>', line)
  15.417 -
  15.418 -            # field = data entries
  15.419 -            elif data_rex.match(line):
  15.420 -                field = field_rex.sub('\g<1>', line)
  15.421 -                field = string.lower(field)
  15.422 -                data =  data_rex.sub('\g<2>', line)
  15.423 -
  15.424 -            if field == 'url':
  15.425 -                data = '\\url{' + data.strip() + '}'
  15.426 -            
  15.427 -            if field in ('author', 'editor'):
  15.428 -                entrycont[field] = bibtexauthor(data)
  15.429 -                line = ''
  15.430 -            elif field == 'title':
  15.431 -                line = bibtextitle(data, entrytype)
  15.432 -            elif field != '':
  15.433 -                line = removebraces(transformurls(data.strip()))
  15.434 -
  15.435 -            if line != '':
  15.436 -                line = latexreplacements(line)
  15.437 -                entrycont[field] = line
  15.438 -
  15.439 -
  15.440 -    # sort entries
  15.441 -    filecont.sort(entry_cmp)
  15.442 -    
  15.443 -    # count the bibtex keys
  15.444 -    keytable = {}
  15.445 -    counttable = {}
  15.446 -    for entry in filecont:
  15.447 -        bibkey = entry[1]
  15.448 -        if not keytable.has_key(bibkey):
  15.449 -            keytable[bibkey] = 1
  15.450 -        else:
  15.451 -            keytable[bibkey] += 1
  15.452 -
  15.453 -    for bibkey in keytable.keys():
  15.454 -        counttable[bibkey] = 0
  15.455 -    
  15.456 -    # generate output
  15.457 -    for entry in filecont:
  15.458 -        # generate output key form the bibtex key
  15.459 -        bibkey = entry[1]
  15.460 -        entryid = entry[2]
  15.461 -        if keytable[bibkey] == 1:
  15.462 -            outkey = bibkey
  15.463 -        else:
  15.464 -            outkey = bibkey + chr(97 + counttable[bibkey])
  15.465 -        counttable[bibkey] += 1
  15.466 -        
  15.467 -        # append the entry code to the output
  15.468 -        file.append('\\section ' + entryid + ' [' + outkey + ']')
  15.469 -        file.append('<div style="' + divstyle + '">')
  15.470 -        for line in entry[3:]:
  15.471 -            file.append(line)
  15.472 -        file.append('</div>')
  15.473 -        file.append('')
  15.474 -
  15.475 -    return file
  15.476 -
  15.477 -
  15.478 -#
  15.479 -# return 1 iff abbr is in line but not inside braces or quotes
  15.480 -# assumes that abbr appears only once on the line (out of braces and quotes)
  15.481 -#
  15.482 -def verify_out_of_braces(line, abbr):
  15.483 -
  15.484 -    phrase_split = delimiter_rex.split(line)
  15.485 -
  15.486 -    abbr_rex = re.compile( '\\b' + abbr + '\\b', re.I)
  15.487 -
  15.488 -    open_brace = 0
  15.489 -    open_quote = 0
  15.490 -
  15.491 -    for phrase in phrase_split:
  15.492 -        if phrase == "{":
  15.493 -            open_brace = open_brace + 1
  15.494 -        elif phrase == "}":
  15.495 -            open_brace = open_brace - 1
  15.496 -        elif phrase == '"':
  15.497 -            if open_quote == 1:
  15.498 -                open_quote = 0
  15.499 -            else:
  15.500 -                open_quote = 1
  15.501 -        elif abbr_rex.search(phrase):
  15.502 -            if open_brace == 0 and open_quote == 0:
  15.503 -                return 1
  15.504 -
  15.505 -    return 0
  15.506 -
  15.507 -
  15.508 -#
  15.509 -# a line in the form phrase1 # phrase2 # ... # phrasen
  15.510 -# is returned as phrase1 phrase2 ... phrasen
  15.511 -# with the correct punctuation
  15.512 -# Bug: Doesn't always work with multiple abbreviations plugged in
  15.513 -#
  15.514 -def concat_line(line):
  15.515 -    # only look at part after equals
  15.516 -    field = field_rex.sub('\g<1>',line)
  15.517 -    rest = field_rex.sub('\g<2>',line)
  15.518 -
  15.519 -    concat_line = field + ' ='
  15.520 -
  15.521 -    pound_split = concatsplit_rex.split(rest)
  15.522 -
  15.523 -    phrase_count = 0
  15.524 -    length = len(pound_split)
  15.525 -
  15.526 -    for phrase in pound_split:
  15.527 -        phrase = phrase.strip()
  15.528 -        if phrase_count != 0:
  15.529 -            if phrase.startswith('"') or phrase.startswith('{'):
  15.530 -                phrase = phrase[1:]
  15.531 -        elif phrase.startswith('"'):
  15.532 -            phrase = phrase.replace('"','{',1)
  15.533 -
  15.534 -        if phrase_count != length-1:
  15.535 -            if phrase.endswith('"') or phrase.endswith('}'):
  15.536 -                phrase = phrase[:-1]
  15.537 -        else:
  15.538 -            if phrase.endswith('"'):
  15.539 -                phrase = phrase[:-1]
  15.540 -                phrase = phrase + "}"
  15.541 -            elif phrase.endswith('",'):
  15.542 -                phrase = phrase[:-2]
  15.543 -                phrase = phrase + "},"
  15.544 -
  15.545 -        # if phrase did have \#, add the \# back
  15.546 -        if phrase.endswith('\\'):
  15.547 -            phrase = phrase + "#"
  15.548 -        concat_line = concat_line + ' ' + phrase
  15.549 -
  15.550 -        phrase_count = phrase_count + 1
  15.551 -
  15.552 -    return concat_line
  15.553 -
  15.554 -
  15.555 -#
  15.556 -# substitute abbreviations into filecont
  15.557 -# @param filecont_source - string of data from file
  15.558 -#
  15.559 -def bibtex_replace_abbreviations(filecont_source):
  15.560 -    filecont = filecont_source.splitlines()
  15.561 -
  15.562 -    #  These are defined in bibtex, so we'll define them too
  15.563 -    abbr_list = ['jan','feb','mar','apr','may','jun',
  15.564 -                 'jul','aug','sep','oct','nov','dec']
  15.565 -    value_list = ['January','February','March','April',
  15.566 -                  'May','June','July','August','September',
  15.567 -                  'October','November','December']
  15.568 -
  15.569 -    abbr_rex = []
  15.570 -    total_abbr_count = 0
  15.571 -
  15.572 -    front = '\\b'
  15.573 -    back = '(,?)\\b'
  15.574 -
  15.575 -    for x in abbr_list:
  15.576 -        abbr_rex.append( re.compile( front + abbr_list[total_abbr_count] + back, re.I ) )
  15.577 -        total_abbr_count = total_abbr_count + 1
  15.578 -
  15.579 -
  15.580 -    abbrdef_rex = re.compile('\s*@string\s*{\s*('+ valid_name_chars +'*)\s*=(.*)',
  15.581 -                             re.I)
  15.582 -
  15.583 -    comment_rex = re.compile('@comment\s*{',re.I)
  15.584 -    preamble_rex = re.compile('@preamble\s*{',re.I)
  15.585 -
  15.586 -    waiting_for_end_string = 0
  15.587 -    i = 0
  15.588 -    filecont2 = ''
  15.589 -
  15.590 -    for line in filecont:
  15.591 -        if line == ' ' or line == '':
  15.592 -            continue
  15.593 -
  15.594 -        if waiting_for_end_string:
  15.595 -            if re.search('}',line):
  15.596 -                waiting_for_end_string = 0
  15.597 -                continue
  15.598 -
  15.599 -        if abbrdef_rex.search(line):
  15.600 -            abbr = abbrdef_rex.sub('\g<1>', line)
  15.601 -
  15.602 -            if abbr_list.count(abbr) == 0:
  15.603 -                val = abbrdef_rex.sub('\g<2>', line)
  15.604 -                abbr_list.append(abbr)
  15.605 -                value_list.append(string.strip(val))
  15.606 -                abbr_rex.append( re.compile( front + abbr_list[total_abbr_count] + back, re.I ) )
  15.607 -                total_abbr_count = total_abbr_count + 1
  15.608 -            waiting_for_end_string = 1
  15.609 -            continue
  15.610 -
  15.611 -        if comment_rex.search(line):
  15.612 -            waiting_for_end_string = 1
  15.613 -            continue
  15.614 -
  15.615 -        if preamble_rex.search(line):
  15.616 -            waiting_for_end_string = 1
  15.617 -            continue
  15.618 -
  15.619 -
  15.620 -        # replace subsequent abbreviations with the value
  15.621 -        abbr_count = 0
  15.622 -
  15.623 -        for x in abbr_list:
  15.624 -
  15.625 -            if abbr_rex[abbr_count].search(line):
  15.626 -                if verify_out_of_braces(line,abbr_list[abbr_count]) == 1:
  15.627 -                    line = abbr_rex[abbr_count].sub( value_list[abbr_count] + '\g<1>', line)
  15.628 -                # Check for # concatenations
  15.629 -                if concatsplit_rex.search(line):
  15.630 -                    line = concat_line(line)
  15.631 -            abbr_count = abbr_count + 1
  15.632 -
  15.633 -
  15.634 -        filecont2 = filecont2 + line + '\n'
  15.635 -        i = i+1
  15.636 -
  15.637 -
  15.638 -    # Do one final pass over file
  15.639 -
  15.640 -    # make sure that didn't end up with {" or }" after the substitution
  15.641 -    filecont2 = filecont2.replace('{"','{{')
  15.642 -    filecont2 = filecont2.replace('"}','}}')
  15.643 -
  15.644 -    afterquotevalue_rex = re.compile('"\s*,\s*')
  15.645 -    afterbrace_rex = re.compile('"\s*}')
  15.646 -    afterbracevalue_rex = re.compile('(=\s*{[^=]*)},\s*')
  15.647 -
  15.648 -    # add new lines to data that changed because of abbreviation substitutions
  15.649 -    filecont2 = afterquotevalue_rex.sub('",\n', filecont2)
  15.650 -    filecont2 = afterbrace_rex.sub('"\n}', filecont2)
  15.651 -    filecont2 = afterbracevalue_rex.sub('\g<1>},\n', filecont2)
  15.652 -
  15.653 -    return filecont2
  15.654 -
  15.655 -#
  15.656 -# convert @type( ... ) to @type{ ... }
  15.657 -#
  15.658 -def no_outer_parens(filecont):
  15.659 -
  15.660 -    # do checking for open parens
  15.661 -    # will convert to braces
  15.662 -    paren_split = re.split('([(){}])',filecont)
  15.663 -
  15.664 -    open_paren_count = 0
  15.665 -    open_type = 0
  15.666 -    look_next = 0
  15.667 -
  15.668 -    # rebuild filecont
  15.669 -    filecont = ''
  15.670 -
  15.671 -    at_rex = re.compile('@\w*')
  15.672 -
  15.673 -    for phrase in paren_split:
  15.674 -        if look_next == 1:
  15.675 -            if phrase == '(':
  15.676 -                phrase = '{'
  15.677 -                open_paren_count = open_paren_count + 1
  15.678 -            else:
  15.679 -                open_type = 0
  15.680 -            look_next = 0
  15.681 -
  15.682 -        if phrase == '(':
  15.683 -            open_paren_count = open_paren_count + 1
  15.684 -
  15.685 -        elif phrase == ')':
  15.686 -            open_paren_count = open_paren_count - 1
  15.687 -            if open_type == 1 and open_paren_count == 0:
  15.688 -                phrase = '}'
  15.689 -                open_type = 0
  15.690 -
  15.691 -        elif at_rex.search( phrase ):
  15.692 -            open_type = 1
  15.693 -            look_next = 1
  15.694 -
  15.695 -        filecont = filecont + phrase
  15.696 -
  15.697 -    return filecont
  15.698 -
  15.699 -
  15.700 -#
  15.701 -# make all whitespace into just one space
  15.702 -# format the bibtex file into a usable form.
  15.703 -#
  15.704 -def bibtexwasher(filecont_source):
  15.705 -
  15.706 -    space_rex = re.compile('\s+')
  15.707 -    comment_rex = re.compile('\s*%')
  15.708 -
  15.709 -    filecont = []
  15.710 -
  15.711 -    # remove trailing and excessive whitespace
  15.712 -    # ignore comments
  15.713 -    for line in filecont_source:
  15.714 -        line = string.strip(line)
  15.715 -        line = space_rex.sub(' ', line)
  15.716 -        # ignore comments
  15.717 -        if not comment_rex.match(line) and line != '':
  15.718 -            filecont.append(' '+ line)
  15.719 -
  15.720 -    filecont = string.join(filecont, '')
  15.721 -
  15.722 -    # the file is in one long string
  15.723 -
  15.724 -    filecont = no_outer_parens(filecont)
  15.725 -
  15.726 -    #
  15.727 -    # split lines according to preferred syntax scheme
  15.728 -    #
  15.729 -    filecont = re.sub('(=\s*{[^=]*)},', '\g<1>},\n', filecont)
  15.730 -
  15.731 -    # add new lines after commas that are after values
  15.732 -    filecont = re.sub('"\s*,', '",\n', filecont)
  15.733 -    filecont = re.sub('=\s*([\w\d]+)\s*,', '= \g<1>,\n', filecont)
  15.734 -    filecont = re.sub('(@\w*)\s*({(\s*)[^,\s]*)\s*,',
  15.735 -                          '\n\n\g<1>\g<2>,\n', filecont)
  15.736 -
  15.737 -    # add new lines after }
  15.738 -    filecont = re.sub('"\s*}','"\n}\n', filecont)
  15.739 -    filecont = re.sub('}\s*,','},\n', filecont)
  15.740 -
  15.741 -
  15.742 -    filecont = re.sub('@(\w*)', '\n@\g<1>', filecont)
  15.743 -
  15.744 -    # character encoding, reserved latex characters
  15.745 -    filecont = re.sub('{\\\&}', '&', filecont)
  15.746 -    filecont = re.sub('\\\&', '&', filecont)
  15.747 -
  15.748 -    # do checking for open braces to get format correct
  15.749 -    open_brace_count = 0
  15.750 -    brace_split = re.split('([{}])',filecont)
  15.751 -
  15.752 -    # rebuild filecont
  15.753 -    filecont = ''
  15.754 -
  15.755 -    for phrase in brace_split:
  15.756 -        if phrase == '{':
  15.757 -            open_brace_count = open_brace_count + 1
  15.758 -        elif phrase == '}':
  15.759 -            open_brace_count = open_brace_count - 1
  15.760 -            if open_brace_count == 0:
  15.761 -                filecont = filecont + '\n'
  15.762 -
  15.763 -        filecont = filecont + phrase
  15.764 -
  15.765 -    filecont2 = bibtex_replace_abbreviations(filecont)
  15.766 -
  15.767 -    # gather
  15.768 -    filecont = filecont2.splitlines()
  15.769 -    i=0
  15.770 -    j=0         # count the number of blank lines
  15.771 -    for line in filecont:
  15.772 -        # ignore blank lines
  15.773 -        if line == '' or line == ' ':
  15.774 -            j = j+1
  15.775 -            continue
  15.776 -        filecont[i] = line + '\n'
  15.777 -        i = i+1
  15.778 -
  15.779 -    # get rid of the extra stuff at the end of the array
  15.780 -    # (The extra stuff are duplicates that are in the array because
  15.781 -    # blank lines were removed.)
  15.782 -    length = len( filecont)
  15.783 -    filecont[length-j:length] = []
  15.784 -
  15.785 -    return filecont
  15.786 -
  15.787 -
  15.788 -def filehandler(filepath):
  15.789 -    try:
  15.790 -        fd = open(filepath, 'r')
  15.791 -        filecont_source = fd.readlines()
  15.792 -        fd.close()
  15.793 -    except:
  15.794 -        print 'Could not open file:', filepath
  15.795 -    washeddata = bibtexwasher(filecont_source)
  15.796 -    outdata = bibtexdecoder(washeddata)
  15.797 -    print '/**'
  15.798 -    print '\page references References'
  15.799 -    print
  15.800 -    for line in outdata:
  15.801 -        print line
  15.802 -    print '*/'
  15.803 -
  15.804 -
  15.805 -# main program
  15.806 -
  15.807 -def main():
  15.808 -    import sys
  15.809 -    if sys.argv[1:]:
  15.810 -        filepath = sys.argv[1]
  15.811 -    else:
  15.812 -        print "No input file"
  15.813 -        sys.exit()
  15.814 -    filehandler(filepath)
  15.815 -
  15.816 -if __name__ == "__main__": main()
  15.817 -
  15.818 -
  15.819 -# end python script