# HG changeset patch # User Alpar Juttner # Date 1363624879 -3600 # Node ID 1c978b5bcc657cc3c0623b96d72f94cd60ae40a1 # Parent eb2f9d453070f2251c5c194610f0722d1670df31 Use doxygen's own bibtex support (#456) diff -r eb2f9d453070 -r 1c978b5bcc65 doc/CMakeLists.txt --- a/doc/CMakeLists.txt Sat Mar 16 14:11:32 2013 +0100 +++ b/doc/CMakeLists.txt Mon Mar 18 17:41:19 2013 +0100 @@ -51,7 +51,6 @@ COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r8 -sOutputFile=gen-images/nodeshape_3.png ${CMAKE_CURRENT_SOURCE_DIR}/images/nodeshape_3.eps COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r8 -sOutputFile=gen-images/nodeshape_4.png ${CMAKE_CURRENT_SOURCE_DIR}/images/nodeshape_4.eps COMMAND ${CMAKE_COMMAND} -E remove_directory html - COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/scripts/bib2dox.py ${CMAKE_CURRENT_SOURCE_DIR}/references.bib >references.dox COMMAND ${DOXYGEN_EXECUTABLE} Doxyfile WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) diff -r eb2f9d453070 -r 1c978b5bcc65 doc/Doxyfile.in --- a/doc/Doxyfile.in Sat Mar 16 14:11:32 2013 +0100 +++ b/doc/Doxyfile.in Mon Mar 18 17:41:19 2013 +0100 @@ -77,6 +77,7 @@ SHOW_NAMESPACES = YES FILE_VERSION_FILTER = LAYOUT_FILE = "@abs_top_srcdir@/doc/DoxygenLayout.xml" +CITE_BIB_FILES = "@abs_top_srcdir@/doc/references.bib" #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- diff -r eb2f9d453070 -r 1c978b5bcc65 doc/groups.dox --- a/doc/groups.dox Sat Mar 16 14:11:32 2013 +0100 +++ b/doc/groups.dox Mon Mar 18 17:41:19 2013 +0100 @@ -317,7 +317,7 @@ This group contains the common graph search algorithms, namely \e breadth-first \e search (BFS) and \e depth-first \e search (DFS) -\ref clrs01algorithms. +\cite clrs01algorithms. */ /** @@ -326,7 +326,7 @@ \brief Algorithms for finding shortest paths. This group contains the algorithms for finding shortest paths in digraphs -\ref clrs01algorithms. +\cite clrs01algorithms. - \ref Dijkstra algorithm for finding shortest paths from a source node when all arc lengths are non-negative. @@ -348,7 +348,7 @@ \brief Algorithms for finding minimum cost spanning trees and arborescences. This group contains the algorithms for finding minimum cost spanning -trees and arborescences \ref clrs01algorithms. +trees and arborescences \cite clrs01algorithms. */ /** @@ -357,7 +357,7 @@ \brief Algorithms for finding maximum flows. This group contains the algorithms for finding maximum flows and -feasible circulations \ref clrs01algorithms, \ref amo93networkflows. +feasible circulations \cite clrs01algorithms, \cite amo93networkflows. The \e maximum \e flow \e problem is to find a flow of maximum value between a single source and a single target. Formally, there is a \f$G=(V,A)\f$ @@ -373,13 +373,13 @@ LEMON contains several algorithms for solving maximum flow problems: - \ref EdmondsKarp Edmonds-Karp algorithm - \ref edmondskarp72theoretical. + \cite edmondskarp72theoretical. - \ref Preflow Goldberg-Tarjan's preflow push-relabel algorithm - \ref goldberg88newapproach. + \cite goldberg88newapproach. - \ref DinitzSleatorTarjan Dinitz's blocking flow algorithm with dynamic trees - \ref dinic70algorithm, \ref sleator83dynamic. + \cite dinic70algorithm, \cite sleator83dynamic. - \ref GoldbergTarjan !Preflow push-relabel algorithm with dynamic trees - \ref goldberg88newapproach, \ref sleator83dynamic. + \cite goldberg88newapproach, \cite sleator83dynamic. In most cases the \ref Preflow algorithm provides the fastest method for computing a maximum flow. All implementations @@ -399,20 +399,20 @@ \brief Algorithms for finding minimum cost flows and circulations. This group contains the algorithms for finding minimum cost flows and -circulations \ref amo93networkflows. For more information about this +circulations \cite amo93networkflows. For more information about this problem and its dual solution, see: \ref min_cost_flow "Minimum Cost Flow Problem". LEMON contains several algorithms for this problem. - \ref NetworkSimplex Primal Network Simplex algorithm with various - pivot strategies \ref dantzig63linearprog, \ref kellyoneill91netsimplex. + pivot strategies \cite dantzig63linearprog, \cite kellyoneill91netsimplex. - \ref CostScaling Cost Scaling algorithm based on push/augment and - relabel operations \ref goldberg90approximation, \ref goldberg97efficient, - \ref bunnagel98efficient. + relabel operations \cite goldberg90approximation, \cite goldberg97efficient, + \cite bunnagel98efficient. - \ref CapacityScaling Capacity Scaling algorithm based on the successive - shortest path method \ref edmondskarp72theoretical. + shortest path method \cite edmondskarp72theoretical. - \ref CycleCanceling Cycle-Canceling algorithms, two of which are - strongly polynomial \ref klein67primal, \ref goldberg89cyclecanceling. + strongly polynomial \cite klein67primal, \cite goldberg89cyclecanceling. In general, \ref NetworkSimplex and \ref CostScaling are the most efficient implementations. @@ -430,7 +430,7 @@ data are required to be integer). For more details about these implementations and for a comprehensive -experimental study, see the paper \ref KiralyKovacs12MCF. +experimental study, see the paper \cite KiralyKovacs12MCF. It also compares these codes to other publicly available minimum cost flow solvers. */ @@ -471,7 +471,7 @@ \brief Algorithms for finding minimum mean cycles. This group contains the algorithms for finding minimum mean cycles -\ref amo93networkflows, \ref karp78characterization. +\cite amo93networkflows, \cite karp78characterization. The \e minimum \e mean \e cycle \e problem is to find a directed cycle of minimum mean length (cost) in a digraph. @@ -487,11 +487,11 @@ function. LEMON contains three algorithms for solving the minimum mean cycle problem: -- \ref KarpMmc Karp's original algorithm \ref karp78characterization. +- \ref KarpMmc Karp's original algorithm \cite karp78characterization. - \ref HartmannOrlinMmc Hartmann-Orlin's algorithm, which is an improved - version of Karp's algorithm \ref hartmann93finding. + version of Karp's algorithm \cite hartmann93finding. - \ref HowardMmc Howard's policy iteration algorithm - \ref dasdan98minmeancycle, \ref dasdan04experimental. + \cite dasdan98minmeancycle, \cite dasdan04experimental. In practice, the \ref HowardMmc "Howard" algorithm turned out to be by far the most efficient one, though the best known theoretical bound on its running @@ -647,8 +647,8 @@ Various LP solvers could be used in the same manner with this high-level interface. -The currently supported solvers are \ref glpk, \ref clp, \ref cbc, -\ref cplex, \ref soplex. +The currently supported solvers are \cite glpk, \cite clp, \cite cbc, +\cite cplex, \cite soplex. */ /** diff -r eb2f9d453070 -r 1c978b5bcc65 doc/mainpage.dox.in --- a/doc/mainpage.dox.in Sat Mar 16 14:11:32 2013 +0100 +++ b/doc/mainpage.dox.in Mon Mar 18 17:41:19 2013 +0100 @@ -25,7 +25,7 @@ and Optimization in Networks. It is a C++ template library providing efficient implementations of common data structures and algorithms with focus on combinatorial optimization -tasks connected mainly with graphs and networks \ref DezsoJuttnerKovacs11Lemon. +tasks connected mainly with graphs and networks \cite DezsoJuttnerKovacs11Lemon. LEMON is an open source @@ -37,12 +37,12 @@ The project is maintained by the Egerváry Research Group on -Combinatorial Optimization \ref egres +Combinatorial Optimization \cite egres at the Operations Research Department of the Eötvös Loránd University, Budapest, Hungary. LEMON is also a member of the COIN-OR -initiative \ref coinor. +initiative \cite coinor. \section howtoread How to Read the Documentation diff -r eb2f9d453070 -r 1c978b5bcc65 doc/min_cost_flow.dox --- a/doc/min_cost_flow.dox Sat Mar 16 14:11:32 2013 +0100 +++ b/doc/min_cost_flow.dox Mon Mar 18 17:41:19 2013 +0100 @@ -26,7 +26,7 @@ The \e minimum \e cost \e flow \e problem is to find a feasible flow of minimum total cost from a set of supply nodes to a set of demand nodes in a network with capacity constraints (lower and upper bounds) -and arc costs \ref amo93networkflows. +and arc costs \cite amo93networkflows. Formally, let \f$G=(V,A)\f$ be a digraph, \f$lower: A\rightarrow\mathbf{R}\f$, \f$upper: A\rightarrow\mathbf{R}\cup\{+\infty\}\f$ denote the lower and diff -r eb2f9d453070 -r 1c978b5bcc65 lemon/capacity_scaling.h --- a/lemon/capacity_scaling.h Sat Mar 16 14:11:32 2013 +0100 +++ b/lemon/capacity_scaling.h Mon Mar 18 17:41:19 2013 +0100 @@ -66,8 +66,8 @@ /// /// \ref CapacityScaling implements the capacity scaling version /// of the successive shortest path algorithm for finding a - /// \ref min_cost_flow "minimum cost flow" \ref amo93networkflows, - /// \ref edmondskarp72theoretical. It is an efficient dual + /// \ref min_cost_flow "minimum cost flow" \cite amo93networkflows, + /// \cite edmondskarp72theoretical. It is an efficient dual /// solution method, which runs in polynomial time /// \f$O(e\log U (n+e)\log n)\f$, where U denotes the maximum /// of node supply and arc capacity values. diff -r eb2f9d453070 -r 1c978b5bcc65 lemon/cost_scaling.h --- a/lemon/cost_scaling.h Sat Mar 16 14:11:32 2013 +0100 +++ b/lemon/cost_scaling.h Mon Mar 18 17:41:19 2013 +0100 @@ -91,8 +91,8 @@ /// /// \ref CostScaling implements a cost scaling algorithm that performs /// push/augment and relabel operations for finding a \ref min_cost_flow - /// "minimum cost flow" \ref amo93networkflows, \ref goldberg90approximation, - /// \ref goldberg97efficient, \ref bunnagel98efficient. + /// "minimum cost flow" \cite amo93networkflows, \cite goldberg90approximation, + /// \cite goldberg97efficient, \cite bunnagel98efficient. /// It is a highly efficient primal-dual solution method, which /// can be viewed as the generalization of the \ref Preflow /// "preflow push-relabel" algorithm for the maximum flow problem. diff -r eb2f9d453070 -r 1c978b5bcc65 lemon/cycle_canceling.h --- a/lemon/cycle_canceling.h Sat Mar 16 14:11:32 2013 +0100 +++ b/lemon/cycle_canceling.h Mon Mar 18 17:41:19 2013 +0100 @@ -47,8 +47,8 @@ /// /// \ref CycleCanceling implements three different cycle-canceling /// algorithms for finding a \ref min_cost_flow "minimum cost flow" - /// \ref amo93networkflows, \ref klein67primal, - /// \ref goldberg89cyclecanceling. + /// \cite amo93networkflows, \cite klein67primal, + /// \cite goldberg89cyclecanceling. /// The most efficent one is the \ref CANCEL_AND_TIGHTEN /// "Cancel-and-Tighten" algorithm, thus it is the default method. /// It runs in strongly polynomial time O(n2e2log(n)), @@ -131,13 +131,13 @@ SIMPLE_CYCLE_CANCELING, /// The "Minimum Mean Cycle-Canceling" algorithm, which is a /// well-known strongly polynomial method - /// \ref goldberg89cyclecanceling. It improves along a + /// \cite goldberg89cyclecanceling. It improves along a /// \ref min_mean_cycle "minimum mean cycle" in each iteration. /// Its running time complexity is O(n2e3log(n)). MINIMUM_MEAN_CYCLE_CANCELING, /// The "Cancel-and-Tighten" algorithm, which can be viewed as an /// improved version of the previous method - /// \ref goldberg89cyclecanceling. + /// \cite goldberg89cyclecanceling. /// It is faster both in theory and in practice, its running time /// complexity is O(n2e2log(n)). CANCEL_AND_TIGHTEN diff -r eb2f9d453070 -r 1c978b5bcc65 lemon/grosso_locatelli_pullan_mc.h --- a/lemon/grosso_locatelli_pullan_mc.h Sat Mar 16 14:11:32 2013 +0100 +++ b/lemon/grosso_locatelli_pullan_mc.h Mon Mar 18 17:41:19 2013 +0100 @@ -40,7 +40,7 @@ /// /// \ref GrossoLocatelliPullanMc implements the iterated local search /// algorithm of Grosso, Locatelli, and Pullan for solving the \e maximum - /// \e clique \e problem \ref grosso08maxclique. + /// \e clique \e problem \cite grosso08maxclique. /// It is to find the largest complete subgraph (\e clique) in an /// undirected graph, i.e., the largest set of nodes where each /// pair of nodes is connected. diff -r eb2f9d453070 -r 1c978b5bcc65 lemon/hartmann_orlin_mmc.h --- a/lemon/hartmann_orlin_mmc.h Sat Mar 16 14:11:32 2013 +0100 +++ b/lemon/hartmann_orlin_mmc.h Mon Mar 18 17:41:19 2013 +0100 @@ -98,7 +98,7 @@ /// /// This class implements the Hartmann-Orlin algorithm for finding /// a directed cycle of minimum mean cost in a digraph - /// \ref hartmann93finding, \ref dasdan98minmeancycle. + /// \cite hartmann93finding, \cite dasdan98minmeancycle. /// This method is based on \ref KarpMmc "Karp"'s original algorithm, but /// applies an early termination scheme. It makes the algorithm /// significantly faster for some problem instances, but slower for others. diff -r eb2f9d453070 -r 1c978b5bcc65 lemon/howard_mmc.h --- a/lemon/howard_mmc.h Sat Mar 16 14:11:32 2013 +0100 +++ b/lemon/howard_mmc.h Mon Mar 18 17:41:19 2013 +0100 @@ -98,7 +98,7 @@ /// /// This class implements Howard's policy iteration algorithm for finding /// a directed cycle of minimum mean cost in a digraph - /// \ref dasdan98minmeancycle, \ref dasdan04experimental. + /// \cite dasdan98minmeancycle, \cite dasdan04experimental. /// This class provides the most efficient algorithm for the /// minimum mean cycle problem, though the best known theoretical /// bound on its running time is exponential. diff -r eb2f9d453070 -r 1c978b5bcc65 lemon/karp_mmc.h --- a/lemon/karp_mmc.h Sat Mar 16 14:11:32 2013 +0100 +++ b/lemon/karp_mmc.h Mon Mar 18 17:41:19 2013 +0100 @@ -98,7 +98,7 @@ /// /// This class implements Karp's algorithm for finding a directed /// cycle of minimum mean cost in a digraph - /// \ref karp78characterization, \ref dasdan98minmeancycle. + /// \cite karp78characterization, \cite dasdan98minmeancycle. /// It runs in time O(ne) and uses space O(n2+e). /// /// \tparam GR The type of the digraph the algorithm runs on. diff -r eb2f9d453070 -r 1c978b5bcc65 lemon/network_simplex.h --- a/lemon/network_simplex.h Sat Mar 16 14:11:32 2013 +0100 +++ b/lemon/network_simplex.h Mon Mar 18 17:41:19 2013 +0100 @@ -41,8 +41,8 @@ /// /// \ref NetworkSimplex implements the primal Network Simplex algorithm /// for finding a \ref min_cost_flow "minimum cost flow" - /// \ref amo93networkflows, \ref dantzig63linearprog, - /// \ref kellyoneill91netsimplex. + /// \cite amo93networkflows, \cite dantzig63linearprog, + /// \cite kellyoneill91netsimplex. /// This algorithm is a highly efficient specialized version of the /// linear programming simplex method directly for the minimum cost /// flow problem. diff -r eb2f9d453070 -r 1c978b5bcc65 lemon/preflow.h --- a/lemon/preflow.h Sat Mar 16 14:11:32 2013 +0100 +++ b/lemon/preflow.h Mon Mar 18 17:41:19 2013 +0100 @@ -102,8 +102,8 @@ /// /// This class provides an implementation of Goldberg-Tarjan's \e preflow /// \e push-relabel algorithm producing a \ref max_flow - /// "flow of maximum value" in a digraph \ref clrs01algorithms, - /// \ref amo93networkflows, \ref goldberg88newapproach. + /// "flow of maximum value" in a digraph \cite clrs01algorithms, + /// \cite amo93networkflows, \cite goldberg88newapproach. /// The preflow algorithms are the fastest known maximum /// flow algorithms. The current implementation uses a mixture of the /// \e "highest label" and the \e "bound decrease" heuristics. diff -r eb2f9d453070 -r 1c978b5bcc65 scripts/bib2dox.py --- a/scripts/bib2dox.py Sat Mar 16 14:11:32 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,816 +0,0 @@ -#! /usr/bin/env python -""" - BibTeX to Doxygen converter - Usage: python bib2dox.py bibfile.bib > bibfile.dox - - This file is a part of LEMON, a generic C++ optimization library. - - ********************************************************************** - - This code is the modification of the BibTeX to XML converter - by Vidar Bronken Gundersen et al. - See the original copyright notices below. - - ********************************************************************** - - Decoder for bibliographic data, BibTeX - Usage: python bibtex2xml.py bibfile.bib > bibfile.xml - - v.8 - (c)2002-06-23 Vidar Bronken Gundersen - http://bibtexml.sf.net/ - Reuse approved as long as this notification is kept. - Licence: GPL. - - Contributions/thanks to: - Egon Willighagen, http://sf.net/projects/jreferences/ - Richard Mahoney (for providing a test case) - - Editted by Sara Sprenkle to be more robust and handle more bibtex features. - (c) 2003-01-15 - - 1. Changed bibtex: tags to bibxml: tags. - 2. Use xmlns:bibxml="http://bibtexml.sf.net/" - 3. Allow spaces between @type and first { - 4. "author" fields with multiple authors split by " and " - are put in separate xml "bibxml:author" tags. - 5. Option for Titles: words are capitalized - only if first letter in title or capitalized inside braces - 6. Removes braces from within field values - 7. Ignores comments in bibtex file (including @comment{ or % ) - 8. Replaces some special latex tags, e.g., replaces ~ with ' ' - 9. Handles bibtex @string abbreviations - --> includes bibtex's default abbreviations for months - --> does concatenation of abbr # " more " and " more " # abbr - 10. Handles @type( ... ) or @type{ ... } - 11. The keywords field is split on , or ; and put into separate xml - "bibxml:keywords" tags - 12. Ignores @preamble - - Known Limitations - 1. Does not transform Latex encoding like math mode and special - latex symbols. - 2. Does not parse author fields into first and last names. - E.g., It does not do anything special to an author whose name is - in the form LAST_NAME, FIRST_NAME - In "author" tag, will show up as - LAST_NAME, FIRST_NAME - 3. Does not handle "crossref" fields other than to print - ... - 4. Does not inform user of the input's format errors. You just won't - be able to transform the file later with XSL - - You will have to manually edit the XML output if you need to handle - these (and unknown) limitations. - -""" - -import string, re - -# set of valid name characters -valid_name_chars = '[\w\-:]' - -# -# define global regular expression variables -# -author_rex = re.compile('\s+and\s+') -rembraces_rex = re.compile('[{}]') -capitalize_rex = re.compile('({[^}]*})') - -# used by bibtexkeywords(data) -keywords_rex = re.compile('[,;]') - -# used by concat_line(line) -concatsplit_rex = re.compile('\s*#\s*') - -# split on {, }, or " in verify_out_of_braces -delimiter_rex = re.compile('([{}"])',re.I) - -field_rex = re.compile('\s*(\w*)\s*=\s*(.*)') -data_rex = re.compile('\s*(\w*)\s*=\s*([^,]*),?') - -url_rex = re.compile('\\\url\{([^}]*)\}') - -# -# styles for html formatting -# -divstyle = 'margin-top: -4ex; margin-left: 10em;' - -# -# return the string parameter without braces -# -def transformurls(str): - return url_rex.sub(r'\1', str) - -# -# return the string parameter without braces -# -def removebraces(str): - return rembraces_rex.sub('', str) - -# -# latex-specific replacements -# (do this after braces were removed) -# -def latexreplacements(line): - line = string.replace(line, '~', ' ') - line = string.replace(line, '\\\'a', 'á') - line = string.replace(line, '\\"a', 'ä') - line = string.replace(line, '\\\'e', 'é') - line = string.replace(line, '\\"e', 'ë') - line = string.replace(line, '\\\'i', 'í') - line = string.replace(line, '\\"i', 'ï') - line = string.replace(line, '\\\'o', 'ó') - line = string.replace(line, '\\"o', 'ö') - line = string.replace(line, '\\\'u', 'ú') - line = string.replace(line, '\\"u', 'ü') - line = string.replace(line, '\\H o', 'õ') - line = string.replace(line, '\\H u', 'ü') # ũ does not exist - line = string.replace(line, '\\\'A', 'Á') - line = string.replace(line, '\\"A', 'Ä') - line = string.replace(line, '\\\'E', 'É') - line = string.replace(line, '\\"E', 'Ë') - line = string.replace(line, '\\\'I', 'Í') - line = string.replace(line, '\\"I', 'Ï') - line = string.replace(line, '\\\'O', 'Ó') - line = string.replace(line, '\\"O', 'Ö') - line = string.replace(line, '\\\'U', 'Ú') - line = string.replace(line, '\\"U', 'Ü') - line = string.replace(line, '\\H O', 'Õ') - line = string.replace(line, '\\H U', 'Ü') # Ũ does not exist - - return line - -# -# copy characters form a string decoding html expressions (&xyz;) -# -def copychars(str, ifrom, count): - result = '' - i = ifrom - c = 0 - html_spec = False - while (i < len(str)) and (c < count): - if str[i] == '&': - html_spec = True; - if i+1 < len(str): - result += str[i+1] - c += 1 - i += 2 - else: - if not html_spec: - if ((str[i] >= 'A') and (str[i] <= 'Z')) or \ - ((str[i] >= 'a') and (str[i] <= 'z')): - result += str[i] - c += 1 - elif str[i] == ';': - html_spec = False; - i += 1 - - return result - - -# -# Handle a list of authors (separated by 'and'). -# It gives back an array of the follwing values: -# - num: the number of authors, -# - list: the list of the author names, -# - text: the bibtex text (separated by commas and/or 'and') -# - abbrev: abbreviation that can be used for indicate the -# bibliography entries -# -def bibtexauthor(data): - result = {} - bibtex = '' - result['list'] = author_rex.split(data) - result['num'] = len(result['list']) - for i, author in enumerate(result['list']): - # general transformations - author = latexreplacements(removebraces(author.strip())) - # transform "Xyz, A. B." to "A. B. Xyz" - pos = author.find(',') - if pos != -1: - author = author[pos+1:].strip() + ' ' + author[:pos].strip() - result['list'][i] = author - bibtex += author + '#' - bibtex = bibtex[:-1] - if result['num'] > 1: - ix = bibtex.rfind('#') - if result['num'] == 2: - bibtex = bibtex[:ix] + ' and ' + bibtex[ix+1:] - else: - bibtex = bibtex[:ix] + ', and ' + bibtex[ix+1:] - bibtex = bibtex.replace('#', ', ') - result['text'] = bibtex - - result['abbrev'] = '' - for author in result['list']: - pos = author.rfind(' ') + 1 - count = 1 - if result['num'] == 1: - count = 3 - result['abbrev'] += copychars(author, pos, count) - - return result - - -# -# data = title string -# @return the capitalized title (first letter is capitalized), rest are capitalized -# only if capitalized inside braces -# -def capitalizetitle(data): - title_list = capitalize_rex.split(data) - title = '' - count = 0 - for phrase in title_list: - check = string.lstrip(phrase) - - # keep phrase's capitalization the same - if check.find('{') == 0: - title += removebraces(phrase) - else: - # first word --> capitalize first letter (after spaces) - if count == 0: - title += check.capitalize() - else: - title += phrase.lower() - count = count + 1 - - return title - - -# -# @return the bibtex for the title -# @param data --> title string -# braces are removed from title -# -def bibtextitle(data, entrytype): - if entrytype in ('book', 'inbook'): - title = removebraces(data.strip()) - else: - title = removebraces(capitalizetitle(data.strip())) - bibtex = title - return bibtex - - -# -# function to compare entry lists -# -def entry_cmp(x, y): - return cmp(x[0], y[0]) - - -# -# print the XML for the transformed "filecont_source" -# -def bibtexdecoder(filecont_source): - filecont = [] - file = [] - - # want @{, - pubtype_rex = re.compile('@(\w*)\s*{\s*(.*),') - endtype_rex = re.compile('}\s*$') - endtag_rex = re.compile('^\s*}\s*$') - - bracefield_rex = re.compile('\s*(\w*)\s*=\s*(.*)') - bracedata_rex = re.compile('\s*(\w*)\s*=\s*{(.*)},?') - - quotefield_rex = re.compile('\s*(\w*)\s*=\s*(.*)') - quotedata_rex = re.compile('\s*(\w*)\s*=\s*"(.*)",?') - - for line in filecont_source: - line = line[:-1] - - # encode character entities - line = string.replace(line, '&', '&') - line = string.replace(line, '<', '<') - line = string.replace(line, '>', '>') - - # start entry: publication type (store for later use) - if pubtype_rex.match(line): - # want @{, - entrycont = {} - entry = [] - entrytype = pubtype_rex.sub('\g<1>',line) - entrytype = string.lower(entrytype) - entryid = pubtype_rex.sub('\g<2>', line) - - # end entry if just a } - elif endtype_rex.match(line): - # generate doxygen code for the entry - - # enty type related formattings - if entrytype in ('book', 'inbook'): - entrycont['title'] = '' + entrycont['title'] + '' - if not entrycont.has_key('author'): - entrycont['author'] = entrycont['editor'] - entrycont['author']['text'] += ', editors' - elif entrytype == 'article': - entrycont['journal'] = '' + entrycont['journal'] + '' - elif entrytype in ('inproceedings', 'incollection', 'conference'): - entrycont['booktitle'] = '' + entrycont['booktitle'] + '' - elif entrytype == 'techreport': - if not entrycont.has_key('type'): - entrycont['type'] = 'Technical report' - elif entrytype == 'mastersthesis': - entrycont['type'] = 'Master\'s thesis' - elif entrytype == 'phdthesis': - entrycont['type'] = 'PhD thesis' - - for eline in entrycont: - if eline != '': - eline = latexreplacements(eline) - - if entrycont.has_key('pages') and (entrycont['pages'] != ''): - entrycont['pages'] = string.replace(entrycont['pages'], '--', '-') - - if entrycont.has_key('author') and (entrycont['author'] != ''): - entry.append(entrycont['author']['text'] + '.') - if entrycont.has_key('title') and (entrycont['title'] != ''): - entry.append(entrycont['title'] + '.') - if entrycont.has_key('journal') and (entrycont['journal'] != ''): - entry.append(entrycont['journal'] + ',') - if entrycont.has_key('booktitle') and (entrycont['booktitle'] != ''): - entry.append('In ' + entrycont['booktitle'] + ',') - if entrycont.has_key('type') and (entrycont['type'] != ''): - eline = entrycont['type'] - if entrycont.has_key('number') and (entrycont['number'] != ''): - eline += ' ' + entrycont['number'] - eline += ',' - entry.append(eline) - if entrycont.has_key('institution') and (entrycont['institution'] != ''): - entry.append(entrycont['institution'] + ',') - if entrycont.has_key('publisher') and (entrycont['publisher'] != ''): - entry.append(entrycont['publisher'] + ',') - if entrycont.has_key('school') and (entrycont['school'] != ''): - entry.append(entrycont['school'] + ',') - if entrycont.has_key('address') and (entrycont['address'] != ''): - entry.append(entrycont['address'] + ',') - if entrycont.has_key('edition') and (entrycont['edition'] != ''): - entry.append(entrycont['edition'] + ' edition,') - if entrycont.has_key('howpublished') and (entrycont['howpublished'] != ''): - entry.append(entrycont['howpublished'] + ',') - if entrycont.has_key('volume') and (entrycont['volume'] != ''): - eline = entrycont['volume']; - if entrycont.has_key('number') and (entrycont['number'] != ''): - eline += '(' + entrycont['number'] + ')' - if entrycont.has_key('pages') and (entrycont['pages'] != ''): - eline += ':' + entrycont['pages'] - eline += ',' - entry.append(eline) - else: - if entrycont.has_key('pages') and (entrycont['pages'] != ''): - entry.append('pages ' + entrycont['pages'] + ',') - if entrycont.has_key('year') and (entrycont['year'] != ''): - if entrycont.has_key('month') and (entrycont['month'] != ''): - entry.append(entrycont['month'] + ' ' + entrycont['year'] + '.') - else: - entry.append(entrycont['year'] + '.') - if entrycont.has_key('note') and (entrycont['note'] != ''): - entry.append(entrycont['note'] + '.') - if entrycont.has_key('url') and (entrycont['url'] != ''): - entry.append(entrycont['url'] + '.') - - # generate keys for sorting and for the output - sortkey = '' - bibkey = '' - if entrycont.has_key('author'): - for author in entrycont['author']['list']: - sortkey += copychars(author, author.rfind(' ')+1, len(author)) - bibkey = entrycont['author']['abbrev'] - else: - bibkey = 'x' - if entrycont.has_key('year'): - sortkey += entrycont['year'] - bibkey += entrycont['year'][-2:] - if entrycont.has_key('title'): - sortkey += entrycont['title'] - if entrycont.has_key('key'): - sortkey = entrycont['key'] + sortkey - bibkey = entrycont['key'] - entry.insert(0, sortkey) - entry.insert(1, bibkey) - entry.insert(2, entryid) - - # add the entry to the file contents - filecont.append(entry) - - else: - # field, publication info - field = '' - data = '' - - # field = {data} entries - if bracedata_rex.match(line): - field = bracefield_rex.sub('\g<1>', line) - field = string.lower(field) - data = bracedata_rex.sub('\g<2>', line) - - # field = "data" entries - elif quotedata_rex.match(line): - field = quotefield_rex.sub('\g<1>', line) - field = string.lower(field) - data = quotedata_rex.sub('\g<2>', line) - - # field = data entries - elif data_rex.match(line): - field = field_rex.sub('\g<1>', line) - field = string.lower(field) - data = data_rex.sub('\g<2>', line) - - if field == 'url': - data = '\\url{' + data.strip() + '}' - - if field in ('author', 'editor'): - entrycont[field] = bibtexauthor(data) - line = '' - elif field == 'title': - line = bibtextitle(data, entrytype) - elif field != '': - line = removebraces(transformurls(data.strip())) - - if line != '': - line = latexreplacements(line) - entrycont[field] = line - - - # sort entries - filecont.sort(entry_cmp) - - # count the bibtex keys - keytable = {} - counttable = {} - for entry in filecont: - bibkey = entry[1] - if not keytable.has_key(bibkey): - keytable[bibkey] = 1 - else: - keytable[bibkey] += 1 - - for bibkey in keytable.keys(): - counttable[bibkey] = 0 - - # generate output - for entry in filecont: - # generate output key form the bibtex key - bibkey = entry[1] - entryid = entry[2] - if keytable[bibkey] == 1: - outkey = bibkey - else: - outkey = bibkey + chr(97 + counttable[bibkey]) - counttable[bibkey] += 1 - - # append the entry code to the output - file.append('\\section ' + entryid + ' [' + outkey + ']') - file.append('
') - for line in entry[3:]: - file.append(line) - file.append('
') - file.append('') - - return file - - -# -# return 1 iff abbr is in line but not inside braces or quotes -# assumes that abbr appears only once on the line (out of braces and quotes) -# -def verify_out_of_braces(line, abbr): - - phrase_split = delimiter_rex.split(line) - - abbr_rex = re.compile( '\\b' + abbr + '\\b', re.I) - - open_brace = 0 - open_quote = 0 - - for phrase in phrase_split: - if phrase == "{": - open_brace = open_brace + 1 - elif phrase == "}": - open_brace = open_brace - 1 - elif phrase == '"': - if open_quote == 1: - open_quote = 0 - else: - open_quote = 1 - elif abbr_rex.search(phrase): - if open_brace == 0 and open_quote == 0: - return 1 - - return 0 - - -# -# a line in the form phrase1 # phrase2 # ... # phrasen -# is returned as phrase1 phrase2 ... phrasen -# with the correct punctuation -# Bug: Doesn't always work with multiple abbreviations plugged in -# -def concat_line(line): - # only look at part after equals - field = field_rex.sub('\g<1>',line) - rest = field_rex.sub('\g<2>',line) - - concat_line = field + ' =' - - pound_split = concatsplit_rex.split(rest) - - phrase_count = 0 - length = len(pound_split) - - for phrase in pound_split: - phrase = phrase.strip() - if phrase_count != 0: - if phrase.startswith('"') or phrase.startswith('{'): - phrase = phrase[1:] - elif phrase.startswith('"'): - phrase = phrase.replace('"','{',1) - - if phrase_count != length-1: - if phrase.endswith('"') or phrase.endswith('}'): - phrase = phrase[:-1] - else: - if phrase.endswith('"'): - phrase = phrase[:-1] - phrase = phrase + "}" - elif phrase.endswith('",'): - phrase = phrase[:-2] - phrase = phrase + "}," - - # if phrase did have \#, add the \# back - if phrase.endswith('\\'): - phrase = phrase + "#" - concat_line = concat_line + ' ' + phrase - - phrase_count = phrase_count + 1 - - return concat_line - - -# -# substitute abbreviations into filecont -# @param filecont_source - string of data from file -# -def bibtex_replace_abbreviations(filecont_source): - filecont = filecont_source.splitlines() - - # These are defined in bibtex, so we'll define them too - abbr_list = ['jan','feb','mar','apr','may','jun', - 'jul','aug','sep','oct','nov','dec'] - value_list = ['January','February','March','April', - 'May','June','July','August','September', - 'October','November','December'] - - abbr_rex = [] - total_abbr_count = 0 - - front = '\\b' - back = '(,?)\\b' - - for x in abbr_list: - abbr_rex.append( re.compile( front + abbr_list[total_abbr_count] + back, re.I ) ) - total_abbr_count = total_abbr_count + 1 - - - abbrdef_rex = re.compile('\s*@string\s*{\s*('+ valid_name_chars +'*)\s*=(.*)', - re.I) - - comment_rex = re.compile('@comment\s*{',re.I) - preamble_rex = re.compile('@preamble\s*{',re.I) - - waiting_for_end_string = 0 - i = 0 - filecont2 = '' - - for line in filecont: - if line == ' ' or line == '': - continue - - if waiting_for_end_string: - if re.search('}',line): - waiting_for_end_string = 0 - continue - - if abbrdef_rex.search(line): - abbr = abbrdef_rex.sub('\g<1>', line) - - if abbr_list.count(abbr) == 0: - val = abbrdef_rex.sub('\g<2>', line) - abbr_list.append(abbr) - value_list.append(string.strip(val)) - abbr_rex.append( re.compile( front + abbr_list[total_abbr_count] + back, re.I ) ) - total_abbr_count = total_abbr_count + 1 - waiting_for_end_string = 1 - continue - - if comment_rex.search(line): - waiting_for_end_string = 1 - continue - - if preamble_rex.search(line): - waiting_for_end_string = 1 - continue - - - # replace subsequent abbreviations with the value - abbr_count = 0 - - for x in abbr_list: - - if abbr_rex[abbr_count].search(line): - if verify_out_of_braces(line,abbr_list[abbr_count]) == 1: - line = abbr_rex[abbr_count].sub( value_list[abbr_count] + '\g<1>', line) - # Check for # concatenations - if concatsplit_rex.search(line): - line = concat_line(line) - abbr_count = abbr_count + 1 - - - filecont2 = filecont2 + line + '\n' - i = i+1 - - - # Do one final pass over file - - # make sure that didn't end up with {" or }" after the substitution - filecont2 = filecont2.replace('{"','{{') - filecont2 = filecont2.replace('"}','}}') - - afterquotevalue_rex = re.compile('"\s*,\s*') - afterbrace_rex = re.compile('"\s*}') - afterbracevalue_rex = re.compile('(=\s*{[^=]*)},\s*') - - # add new lines to data that changed because of abbreviation substitutions - filecont2 = afterquotevalue_rex.sub('",\n', filecont2) - filecont2 = afterbrace_rex.sub('"\n}', filecont2) - filecont2 = afterbracevalue_rex.sub('\g<1>},\n', filecont2) - - return filecont2 - -# -# convert @type( ... ) to @type{ ... } -# -def no_outer_parens(filecont): - - # do checking for open parens - # will convert to braces - paren_split = re.split('([(){}])',filecont) - - open_paren_count = 0 - open_type = 0 - look_next = 0 - - # rebuild filecont - filecont = '' - - at_rex = re.compile('@\w*') - - for phrase in paren_split: - if look_next == 1: - if phrase == '(': - phrase = '{' - open_paren_count = open_paren_count + 1 - else: - open_type = 0 - look_next = 0 - - if phrase == '(': - open_paren_count = open_paren_count + 1 - - elif phrase == ')': - open_paren_count = open_paren_count - 1 - if open_type == 1 and open_paren_count == 0: - phrase = '}' - open_type = 0 - - elif at_rex.search( phrase ): - open_type = 1 - look_next = 1 - - filecont = filecont + phrase - - return filecont - - -# -# make all whitespace into just one space -# format the bibtex file into a usable form. -# -def bibtexwasher(filecont_source): - - space_rex = re.compile('\s+') - comment_rex = re.compile('\s*%') - - filecont = [] - - # remove trailing and excessive whitespace - # ignore comments - for line in filecont_source: - line = string.strip(line) - line = space_rex.sub(' ', line) - # ignore comments - if not comment_rex.match(line) and line != '': - filecont.append(' '+ line) - - filecont = string.join(filecont, '') - - # the file is in one long string - - filecont = no_outer_parens(filecont) - - # - # split lines according to preferred syntax scheme - # - filecont = re.sub('(=\s*{[^=]*)},', '\g<1>},\n', filecont) - - # add new lines after commas that are after values - filecont = re.sub('"\s*,', '",\n', filecont) - filecont = re.sub('=\s*([\w\d]+)\s*,', '= \g<1>,\n', filecont) - filecont = re.sub('(@\w*)\s*({(\s*)[^,\s]*)\s*,', - '\n\n\g<1>\g<2>,\n', filecont) - - # add new lines after } - filecont = re.sub('"\s*}','"\n}\n', filecont) - filecont = re.sub('}\s*,','},\n', filecont) - - - filecont = re.sub('@(\w*)', '\n@\g<1>', filecont) - - # character encoding, reserved latex characters - filecont = re.sub('{\\\&}', '&', filecont) - filecont = re.sub('\\\&', '&', filecont) - - # do checking for open braces to get format correct - open_brace_count = 0 - brace_split = re.split('([{}])',filecont) - - # rebuild filecont - filecont = '' - - for phrase in brace_split: - if phrase == '{': - open_brace_count = open_brace_count + 1 - elif phrase == '}': - open_brace_count = open_brace_count - 1 - if open_brace_count == 0: - filecont = filecont + '\n' - - filecont = filecont + phrase - - filecont2 = bibtex_replace_abbreviations(filecont) - - # gather - filecont = filecont2.splitlines() - i=0 - j=0 # count the number of blank lines - for line in filecont: - # ignore blank lines - if line == '' or line == ' ': - j = j+1 - continue - filecont[i] = line + '\n' - i = i+1 - - # get rid of the extra stuff at the end of the array - # (The extra stuff are duplicates that are in the array because - # blank lines were removed.) - length = len( filecont) - filecont[length-j:length] = [] - - return filecont - - -def filehandler(filepath): - try: - fd = open(filepath, 'r') - filecont_source = fd.readlines() - fd.close() - except: - print 'Could not open file:', filepath - washeddata = bibtexwasher(filecont_source) - outdata = bibtexdecoder(washeddata) - print '/**' - print '\page references References' - print - for line in outdata: - print line - print '*/' - - -# main program - -def main(): - import sys - if sys.argv[1:]: - filepath = sys.argv[1] - else: - print "No input file" - sys.exit() - filehandler(filepath) - -if __name__ == "__main__": main() - - -# end python script