0
                         0
                         2
                     
                 
                    | 1 | 
		%%%%% Defining LEMON %%%%%  | 
|
| 2 | 
		 | 
|
| 3 | 
		@misc{lemon,
	 | 
|
| 4 | 
		  key =          {LEMON},
	 | 
|
| 5 | 
		  title =        {{LEMON} -- {L}ibrary for {E}fficient {M}odeling and
	 | 
|
| 6 | 
		                  {O}ptimization in {N}etworks},
	 | 
|
| 7 | 
		  howpublished = {\url{http://lemon.cs.elte.hu/}},
	 | 
|
| 8 | 
		year = 2009  | 
|
| 9 | 
		}  | 
|
| 10 | 
		 | 
|
| 11 | 
		@misc{egres,
	 | 
|
| 12 | 
		  key =          {EGRES},
	 | 
|
| 13 | 
		  title =        {{EGRES} -- {E}gerv{\'a}ry {R}esearch {G}roup on
	 | 
|
| 14 | 
		                  {C}ombinatorial {O}ptimization},
	 | 
|
| 15 | 
		  howpublished = {\url{http://www.cs.elte.hu/egres/}},
	 | 
|
| 16 | 
		year = 2009  | 
|
| 17 | 
		}  | 
|
| 18 | 
		 | 
|
| 19 | 
		@misc{coinor,
	 | 
|
| 20 | 
		  key =          {COIN-OR},
	 | 
|
| 21 | 
		  title =        {{COIN-OR} -- {C}omputational {I}nfrastructure for
	 | 
|
| 22 | 
		                  {O}perations {R}esearch},
	 | 
|
| 23 | 
		  howpublished = {\url{http://www.coin-or.org/}},
	 | 
|
| 24 | 
		year = 2009  | 
|
| 25 | 
		}  | 
|
| 26 | 
		 | 
|
| 27 | 
		 | 
|
| 28 | 
		%%%%% Other libraries %%%%%%  | 
|
| 29 | 
		 | 
|
| 30 | 
		@misc{boost,
	 | 
|
| 31 | 
		  key =          {Boost},
	 | 
|
| 32 | 
		  title =        {{B}oost {C++} {L}ibraries},
	 | 
|
| 33 | 
		  howpublished = {\url{http://www.boost.org/}},
	 | 
|
| 34 | 
		year = 2009  | 
|
| 35 | 
		}  | 
|
| 36 | 
		 | 
|
| 37 | 
		@book{bglbook,
	 | 
|
| 38 | 
		  author =       {Jeremy G. Siek and Lee-Quan Lee and Andrew
	 | 
|
| 39 | 
		Lumsdaine},  | 
|
| 40 | 
		  title =        {The Boost Graph Library: User Guide and Reference
	 | 
|
| 41 | 
		Manual},  | 
|
| 42 | 
		  publisher =    {Addison-Wesley},
	 | 
|
| 43 | 
		year = 2002  | 
|
| 44 | 
		}  | 
|
| 45 | 
		 | 
|
| 46 | 
		@misc{leda,
	 | 
|
| 47 | 
		  key =          {LEDA},
	 | 
|
| 48 | 
		  title =        {{LEDA} -- {L}ibrary of {E}fficient {D}ata {T}ypes and
	 | 
|
| 49 | 
		                  {A}lgorithms},
	 | 
|
| 50 | 
		  howpublished = {\url{http://www.algorithmic-solutions.com/}},
	 | 
|
| 51 | 
		year = 2009  | 
|
| 52 | 
		}  | 
|
| 53 | 
		 | 
|
| 54 | 
		@book{ledabook,
	 | 
|
| 55 | 
		  author =       {Kurt Mehlhorn and Stefan N{\"a}her},
	 | 
|
| 56 | 
		  title =        {{LEDA}: {A} platform for combinatorial and geometric
	 | 
|
| 57 | 
		computing},  | 
|
| 58 | 
		  isbn =         {0-521-56329-1},
	 | 
|
| 59 | 
		  publisher =    {Cambridge University Press},
	 | 
|
| 60 | 
		  address =      {New York, NY, USA},
	 | 
|
| 61 | 
		year = 1999  | 
|
| 62 | 
		}  | 
|
| 63 | 
		 | 
|
| 64 | 
		 | 
|
| 65 | 
		%%%%% Tools that LEMON depends on %%%%%  | 
|
| 66 | 
		 | 
|
| 67 | 
		@misc{cmake,
	 | 
|
| 68 | 
		  key =          {CMake},
	 | 
|
| 69 | 
		  title =        {{CMake} -- {C}ross {P}latform {M}ake},
	 | 
|
| 70 | 
		  howpublished = {\url{http://www.cmake.org/}},
	 | 
|
| 71 | 
		year = 2009  | 
|
| 72 | 
		}  | 
|
| 73 | 
		 | 
|
| 74 | 
		@misc{doxygen,
	 | 
|
| 75 | 
		  key =          {Doxygen},
	 | 
|
| 76 | 
		  title =        {{Doxygen} -- {S}ource code documentation generator
	 | 
|
| 77 | 
		tool},  | 
|
| 78 | 
		  howpublished = {\url{http://www.doxygen.org/}},
	 | 
|
| 79 | 
		year = 2009  | 
|
| 80 | 
		}  | 
|
| 81 | 
		 | 
|
| 82 | 
		 | 
|
| 83 | 
		%%%%% LP/MIP libraries %%%%%  | 
|
| 84 | 
		 | 
|
| 85 | 
		@misc{glpk,
	 | 
|
| 86 | 
		  key =          {GLPK},
	 | 
|
| 87 | 
		  title =        {{GLPK} -- {GNU} {L}inear {P}rogramming {K}it},
	 | 
|
| 88 | 
		  howpublished = {\url{http://www.gnu.org/software/glpk/}},
	 | 
|
| 89 | 
		year = 2009  | 
|
| 90 | 
		}  | 
|
| 91 | 
		 | 
|
| 92 | 
		@misc{clp,
	 | 
|
| 93 | 
		  key =          {Clp},
	 | 
|
| 94 | 
		  title =        {{Clp} -- {Coin-Or} {L}inear {P}rogramming},
	 | 
|
| 95 | 
		  howpublished = {\url{http://projects.coin-or.org/Clp/}},
	 | 
|
| 96 | 
		year = 2009  | 
|
| 97 | 
		}  | 
|
| 98 | 
		 | 
|
| 99 | 
		@misc{cbc,
	 | 
|
| 100 | 
		  key =          {Cbc},
	 | 
|
| 101 | 
		  title =        {{Cbc} -- {Coin-Or} {B}ranch and {C}ut},
	 | 
|
| 102 | 
		  howpublished = {\url{http://projects.coin-or.org/Cbc/}},
	 | 
|
| 103 | 
		year = 2009  | 
|
| 104 | 
		}  | 
|
| 105 | 
		 | 
|
| 106 | 
		@misc{cplex,
	 | 
|
| 107 | 
		  key =          {CPLEX},
	 | 
|
| 108 | 
		  title =        {{ILOG} {CPLEX}},
	 | 
|
| 109 | 
		  howpublished = {\url{http://www.ilog.com/}},
	 | 
|
| 110 | 
		year = 2009  | 
|
| 111 | 
		}  | 
|
| 112 | 
		 | 
|
| 113 | 
		@misc{soplex,
	 | 
|
| 114 | 
		  key =          {SoPlex},
	 | 
|
| 115 | 
		  title =        {{SoPlex} -- {T}he {S}equential {O}bject-{O}riented
	 | 
|
| 116 | 
		                  {S}implex},
	 | 
|
| 117 | 
		  howpublished = {\url{http://soplex.zib.de/}},
	 | 
|
| 118 | 
		year = 2009  | 
|
| 119 | 
		}  | 
|
| 120 | 
		 | 
|
| 121 | 
		 | 
|
| 122 | 
		%%%%% General books %%%%%  | 
|
| 123 | 
		 | 
|
| 124 | 
		@book{amo93networkflows,
	 | 
|
| 125 | 
		  author =       {Ravindra K. Ahuja and Thomas L. Magnanti and James
	 | 
|
| 126 | 
		B. Orlin},  | 
|
| 127 | 
		  title =        {Network Flows: Theory, Algorithms, and Applications},
	 | 
|
| 128 | 
		  publisher =    {Prentice-Hall, Inc.},
	 | 
|
| 129 | 
		year = 1993,  | 
|
| 130 | 
		month = feb,  | 
|
| 131 | 
		  isbn =         {978-0136175490}
	 | 
|
| 132 | 
		}  | 
|
| 133 | 
		 | 
|
| 134 | 
		@book{schrijver03combinatorial,
	 | 
|
| 135 | 
		  author =       {Alexander Schrijver},
	 | 
|
| 136 | 
		  title =        {Combinatorial Optimization: Polyhedra and Efficiency},
	 | 
|
| 137 | 
		  publisher =    {Springer-Verlag},
	 | 
|
| 138 | 
		year = 2003,  | 
|
| 139 | 
		  isbn =         {978-3540443896}
	 | 
|
| 140 | 
		}  | 
|
| 141 | 
		 | 
|
| 142 | 
		@book{clrs01algorithms,
	 | 
|
| 143 | 
		  author =       {Thomas H. Cormen and Charles E. Leiserson and Ronald
	 | 
|
| 144 | 
		L. Rivest and Clifford Stein},  | 
|
| 145 | 
		  title =        {Introduction to Algorithms},
	 | 
|
| 146 | 
		  publisher =    {The MIT Press},
	 | 
|
| 147 | 
		year = 2001,  | 
|
| 148 | 
		  edition =      {2nd}
	 | 
|
| 149 | 
		}  | 
|
| 150 | 
		 | 
|
| 151 | 
		@book{stroustrup00cpp,
	 | 
|
| 152 | 
		  author =       {Bjarne Stroustrup},
	 | 
|
| 153 | 
		  title =        {The C++ Programming Language},
	 | 
|
| 154 | 
		  edition =      {3rd},
	 | 
|
| 155 | 
		  publisher =    {Addison-Wesley Professional},
	 | 
|
| 156 | 
		isbn = 0201700735,  | 
|
| 157 | 
		  month =        {February},
	 | 
|
| 158 | 
		year = 2000  | 
|
| 159 | 
		}  | 
|
| 160 | 
		 | 
|
| 161 | 
		 | 
|
| 162 | 
		%%%%% Maximum flow algorithms %%%%%  | 
|
| 163 | 
		 | 
|
| 164 | 
		@inproceedings{goldberg86newapproach,
	 | 
|
| 165 | 
		  author =       {Andrew V. Goldberg and Robert E. Tarjan},
	 | 
|
| 166 | 
		  title =        {A new approach to the maximum flow problem},
	 | 
|
| 167 | 
		  booktitle =    {STOC '86: Proceedings of the Eighteenth Annual ACM
	 | 
|
| 168 | 
		Symposium on Theory of Computing},  | 
|
| 169 | 
		year = 1986,  | 
|
| 170 | 
		  publisher =    {ACM Press},
	 | 
|
| 171 | 
		  address =      {New York, NY},
	 | 
|
| 172 | 
		  pages =        {136-146}
	 | 
|
| 173 | 
		}  | 
|
| 174 | 
		 | 
|
| 175 | 
		@article{dinic70algorithm,
	 | 
|
| 176 | 
		  author =       {E. A. Dinic},
	 | 
|
| 177 | 
		  title =        {Algorithm for solution of a problem of maximum flow
	 | 
|
| 178 | 
		in a network with power estimation},  | 
|
| 179 | 
		  journal =      {Soviet Math. Doklady},
	 | 
|
| 180 | 
		year = 1970,  | 
|
| 181 | 
		volume = 11,  | 
|
| 182 | 
		  pages =        {1277-1280}
	 | 
|
| 183 | 
		}  | 
|
| 184 | 
		 | 
|
| 185 | 
		@article{goldberg08partial,
	 | 
|
| 186 | 
		  author =       {Andrew V. Goldberg},
	 | 
|
| 187 | 
		  title =        {The Partial Augment-Relabel Algorithm for the
	 | 
|
| 188 | 
		Maximum Flow Problem},  | 
|
| 189 | 
		  journal =      {16th Annual European Symposium on Algorithms},
	 | 
|
| 190 | 
		year = 2008,  | 
|
| 191 | 
		  pages =        {466-477}
	 | 
|
| 192 | 
		}  | 
|
| 193 | 
		 | 
|
| 194 | 
		@article{sleator83dynamic,
	 | 
|
| 195 | 
		  author =       {Daniel D. Sleator and Robert E. Tarjan},
	 | 
|
| 196 | 
		  title =        {A data structure for dynamic trees},
	 | 
|
| 197 | 
		  journal =      {Journal of Computer and System Sciences},
	 | 
|
| 198 | 
		year = 1983,  | 
|
| 199 | 
		volume = 26,  | 
|
| 200 | 
		number = 3,  | 
|
| 201 | 
		  pages =        {362-391}
	 | 
|
| 202 | 
		}  | 
|
| 203 | 
		 | 
|
| 204 | 
		 | 
|
| 205 | 
		%%%%% Minimum mean cycle algorithms %%%%%  | 
|
| 206 | 
		 | 
|
| 207 | 
		@article{karp78characterization,
	 | 
|
| 208 | 
		  author =       {Richard M. Karp},
	 | 
|
| 209 | 
		  title =        {A characterization of the minimum cycle mean in a
	 | 
|
| 210 | 
		digraph},  | 
|
| 211 | 
		  journal =      {Discrete Math.},
	 | 
|
| 212 | 
		year = 1978,  | 
|
| 213 | 
		volume = 23,  | 
|
| 214 | 
		  pages =        {309-311}
	 | 
|
| 215 | 
		}  | 
|
| 216 | 
		 | 
|
| 217 | 
		@article{dasdan98minmeancycle,
	 | 
|
| 218 | 
		  author =       {Ali Dasdan and Rajesh K. Gupta},
	 | 
|
| 219 | 
		  title =        {Faster Maximum and Minimum Mean Cycle Alogrithms for
	 | 
|
| 220 | 
		System Performance Analysis},  | 
|
| 221 | 
		  journal =      {IEEE Transactions on Computer-Aided Design of
	 | 
|
| 222 | 
		Integrated Circuits and Systems},  | 
|
| 223 | 
		year = 1998,  | 
|
| 224 | 
		volume = 17,  | 
|
| 225 | 
		number = 10,  | 
|
| 226 | 
		  pages =        {889-899}
	 | 
|
| 227 | 
		}  | 
|
| 228 | 
		 | 
|
| 229 | 
		 | 
|
| 230 | 
		%%%%% Minimum cost flow algorithms %%%%%  | 
|
| 231 | 
		 | 
|
| 232 | 
		@article{klein67primal,
	 | 
|
| 233 | 
		  author =       {Morton Klein},
	 | 
|
| 234 | 
		  title =        {A primal method for minimal cost flows with
	 | 
|
| 235 | 
		applications to the assignment and transportation  | 
|
| 236 | 
		problems},  | 
|
| 237 | 
		  journal =      {Management Science},
	 | 
|
| 238 | 
		year = 1967,  | 
|
| 239 | 
		volume = 14,  | 
|
| 240 | 
		  pages =        {205-220}
	 | 
|
| 241 | 
		}  | 
|
| 242 | 
		 | 
|
| 243 | 
		@inproceedings{goldberg88cyclecanceling,
	 | 
|
| 244 | 
		  author =       {Andrew V. Goldberg and Robert E. Tarjan},
	 | 
|
| 245 | 
		  title =        {Finding minimum-cost circulations by canceling
	 | 
|
| 246 | 
		negative cycles},  | 
|
| 247 | 
		  booktitle =    {STOC '88: Proceedings of the Twentieth Annual ACM
	 | 
|
| 248 | 
		Symposium on Theory of Computing},  | 
|
| 249 | 
		year = 1988,  | 
|
| 250 | 
		  publisher =    {ACM Press},
	 | 
|
| 251 | 
		  address =      {New York, NY},
	 | 
|
| 252 | 
		  pages =        {388-397}
	 | 
|
| 253 | 
		}  | 
|
| 254 | 
		 | 
|
| 255 | 
		@article{edmondskarp72theoretical,
	 | 
|
| 256 | 
		  author =       {Jack Edmonds and Richard M. Karp},
	 | 
|
| 257 | 
		  title =        {Theoretical improvements in algorithmic efficiency
	 | 
|
| 258 | 
		for network flow problems},  | 
|
| 259 | 
		  journal =      {Journal of the ACM},
	 | 
|
| 260 | 
		year = 1972,  | 
|
| 261 | 
		volume = 19,  | 
|
| 262 | 
		number = 2,  | 
|
| 263 | 
		  pages =        {248-264}
	 | 
|
| 264 | 
		}  | 
|
| 265 | 
		 | 
|
| 266 | 
		@inproceedings{goldberg87approximation,
	 | 
|
| 267 | 
		  author =       {Andrew V. Goldberg and Robert E. Tarjan},
	 | 
|
| 268 | 
		  title =        {Solving minimum-cost flow problems by successive
	 | 
|
| 269 | 
		approximation},  | 
|
| 270 | 
		  booktitle =    {STOC '87: Proceedings of the Nineteenth Annual ACM
	 | 
|
| 271 | 
		Symposium on Theory of Computing},  | 
|
| 272 | 
		year = 1987,  | 
|
| 273 | 
		  publisher =    {ACM Press},
	 | 
|
| 274 | 
		  address =      {New York, NY},
	 | 
|
| 275 | 
		  pages =        {7-18}
	 | 
|
| 276 | 
		}  | 
|
| 277 | 
		 | 
|
| 278 | 
		@article{goldberg90finding,
	 | 
|
| 279 | 
		  author =       {Andrew V. Goldberg and Robert E. Tarjan},
	 | 
|
| 280 | 
		  title =        {Finding Minimum-Cost Circulations by Successive
	 | 
|
| 281 | 
		Approximation},  | 
|
| 282 | 
		  journal =      {Mathematics of Operations Research},
	 | 
|
| 283 | 
		year = 1990,  | 
|
| 284 | 
		volume = 15,  | 
|
| 285 | 
		number = 3,  | 
|
| 286 | 
		  pages =        {430-466}
	 | 
|
| 287 | 
		}  | 
|
| 288 | 
		 | 
|
| 289 | 
		@article{goldberg97efficient,
	 | 
|
| 290 | 
		  author =       {Andrew V. Goldberg},
	 | 
|
| 291 | 
		  title =        {An Efficient Implementation of a Scaling
	 | 
|
| 292 | 
		Minimum-Cost Flow Algorithm},  | 
|
| 293 | 
		  journal =      {Journal of Algorithms},
	 | 
|
| 294 | 
		year = 1997,  | 
|
| 295 | 
		volume = 22,  | 
|
| 296 | 
		number = 1,  | 
|
| 297 | 
		  pages =        {1-29}
	 | 
|
| 298 | 
		}  | 
|
| 299 | 
		 | 
|
| 300 | 
		@article{bunnagel98efficient,
	 | 
|
| 301 | 
		  author =       {Ursula B{\"u}nnagel and Bernhard Korte and Jens
	 | 
|
| 302 | 
		Vygen},  | 
|
| 303 | 
		  title =        {Efficient implementation of the {G}oldberg-{T}arjan
	 | 
|
| 304 | 
		minimum-cost flow algorithm},  | 
|
| 305 | 
		  journal =      {Optimization Methods and Software},
	 | 
|
| 306 | 
		year = 1998,  | 
|
| 307 | 
		volume = 10,  | 
|
| 308 | 
		  pages =        {157-174}
	 | 
|
| 309 | 
		}  | 
|
| 310 | 
		 | 
|
| 311 | 
		@mastersthesis{kellyoneill91netsimplex,
	 | 
|
| 312 | 
		  author =       {Damian J. Kelly and Garrett M. O'Neill},
	 | 
|
| 313 | 
		  title =        {The Minimum Cost Flow Problem and The Network
	 | 
|
| 314 | 
		Simplex Method},  | 
|
| 315 | 
		  school =       {University College},
	 | 
|
| 316 | 
		  address =      {Dublin, Ireland},
	 | 
|
| 317 | 
		year = 1991,  | 
|
| 318 | 
		month = sep,  | 
|
| 319 | 
		}  | 
|
| 320 | 
		 | 
|
| 321 | 
		@techreport{lobel96networksimplex,
	 | 
|
| 322 | 
		  author =       {Andreas L{\"o}bel},
	 | 
|
| 323 | 
		  title =        {Solving large-scale real-world minimum-cost flow
	 | 
|
| 324 | 
		problems by a network simplex method},  | 
|
| 325 | 
		  institution =  {Konrad-Zuse-Zentrum fur Informationstechnik Berlin
	 | 
|
| 326 | 
		                  ({ZIB})},
	 | 
|
| 327 | 
		  address =      {Berlin, Germany},
	 | 
|
| 328 | 
		year = 1996,  | 
|
| 329 | 
		  number =       {SC 96-7}
	 | 
|
| 330 | 
		}  | 
|
| 331 | 
		 | 
|
| 332 | 
		@article{frangioni06computational,
	 | 
|
| 333 | 
		  author =       {Antonio Frangioni and Antonio Manca},
	 | 
|
| 334 | 
		  title =        {A Computational Study of Cost Reoptimization for
	 | 
|
| 335 | 
		Min-Cost Flow Problems},  | 
|
| 336 | 
		  journal =      {INFORMS Journal On Computing},
	 | 
|
| 337 | 
		year = 2006,  | 
|
| 338 | 
		volume = 18,  | 
|
| 339 | 
		number = 1,  | 
|
| 340 | 
		  pages =        {61-70}
	 | 
|
| 341 | 
		}  | 
| 1 | 
		#!/usr/bin/env /usr/local/Python/bin/python2.1  | 
|
| 2 | 
		"""  | 
|
| 3 | 
		BibTeX to Doxygen converter  | 
|
| 4 | 
		Usage: python bib2dox.py bibfile.bib > bibfile.dox  | 
|
| 5 | 
		 | 
|
| 6 | 
		This code is the modification of the BibTeX to XML converter  | 
|
| 7 | 
		by Vidar Bronken Gundersen et al. See the original copyright notices below.  | 
|
| 8 | 
		 | 
|
| 9 | 
		**********************************************************************  | 
|
| 10 | 
		 | 
|
| 11 | 
		Decoder for bibliographic data, BibTeX  | 
|
| 12 | 
		Usage: python bibtex2xml.py bibfile.bib > bibfile.xml  | 
|
| 13 | 
		 | 
|
| 14 | 
		v.8  | 
|
| 15 | 
		(c)2002-06-23 Vidar Bronken Gundersen  | 
|
| 16 | 
		http://bibtexml.sf.net/  | 
|
| 17 | 
		Reuse approved as long as this notification is kept.  | 
|
| 18 | 
		Licence: GPL.  | 
|
| 19 | 
		 | 
|
| 20 | 
		Contributions/thanks to:  | 
|
| 21 | 
		Egon Willighagen, http://sf.net/projects/jreferences/  | 
|
| 22 | 
		Richard Mahoney (for providing a test case)  | 
|
| 23 | 
		 | 
|
| 24 | 
		Editted by Sara Sprenkle to be more robust and handle more bibtex features.  | 
|
| 25 | 
		(c) 2003-01-15  | 
|
| 26 | 
		 | 
|
| 27 | 
		1. Changed bibtex: tags to bibxml: tags.  | 
|
| 28 | 
		2. Use xmlns:bibxml="http://bibtexml.sf.net/"  | 
|
| 29 | 
		  3.  Allow spaces between @type and first {
	 | 
|
| 30 | 
		4. "author" fields with multiple authors split by " and "  | 
|
| 31 | 
		are put in separate xml "bibxml:author" tags.  | 
|
| 32 | 
		5. Option for Titles: words are capitalized  | 
|
| 33 | 
		only if first letter in title or capitalized inside braces  | 
|
| 34 | 
		6. Removes braces from within field values  | 
|
| 35 | 
		  7.  Ignores comments in bibtex file (including @comment{ or % )
	 | 
|
| 36 | 
		8. Replaces some special latex tags, e.g., replaces ~ with ' '  | 
|
| 37 | 
		9. Handles bibtex @string abbreviations  | 
|
| 38 | 
		--> includes bibtex's default abbreviations for months  | 
|
| 39 | 
		--> does concatenation of abbr # " more " and " more " # abbr  | 
|
| 40 | 
		  10. Handles @type( ... ) or @type{ ... }
	 | 
|
| 41 | 
		11. The keywords field is split on , or ; and put into separate xml  | 
|
| 42 | 
		"bibxml:keywords" tags  | 
|
| 43 | 
		12. Ignores @preamble  | 
|
| 44 | 
		 | 
|
| 45 | 
		Known Limitations  | 
|
| 46 | 
		1. Does not transform Latex encoding like math mode and special  | 
|
| 47 | 
		latex symbols.  | 
|
| 48 | 
		2. Does not parse author fields into first and last names.  | 
|
| 49 | 
		E.g., It does not do anything special to an author whose name is  | 
|
| 50 | 
		in the form LAST_NAME, FIRST_NAME  | 
|
| 51 | 
		In "author" tag, will show up as  | 
|
| 52 | 
		<bibxml:author>LAST_NAME, FIRST_NAME</bibxml:author>  | 
|
| 53 | 
		3. Does not handle "crossref" fields other than to print  | 
|
| 54 | 
		<bibxml:crossref>...</bibxml:crossref>  | 
|
| 55 | 
		4. Does not inform user of the input's format errors. You just won't  | 
|
| 56 | 
		be able to transform the file later with XSL  | 
|
| 57 | 
		 | 
|
| 58 | 
		You will have to manually edit the XML output if you need to handle  | 
|
| 59 | 
		these (and unknown) limitations.  | 
|
| 60 | 
		 | 
|
| 61 | 
		"""  | 
|
| 62 | 
		 | 
|
| 63 | 
		import string, re  | 
|
| 64 | 
		 | 
|
| 65 | 
		# set of valid name characters  | 
|
| 66 | 
		valid_name_chars = '[\w\-:]'  | 
|
| 67 | 
		 | 
|
| 68 | 
		#  | 
|
| 69 | 
		# define global regular expression variables  | 
|
| 70 | 
		#  | 
|
| 71 | 
		author_rex = re.compile('\s+and\s+')
	 | 
|
| 72 | 
		rembraces_rex = re.compile('[{}]')
	 | 
|
| 73 | 
		capitalize_rex = re.compile('({\w*})')
	 | 
|
| 74 | 
		 | 
|
| 75 | 
		# used by bibtexkeywords(data)  | 
|
| 76 | 
		keywords_rex = re.compile('[,;]')
	 | 
|
| 77 | 
		 | 
|
| 78 | 
		# used by concat_line(line)  | 
|
| 79 | 
		concatsplit_rex = re.compile('\s*#\s*')
	 | 
|
| 80 | 
		 | 
|
| 81 | 
		# split on {, }, or " in verify_out_of_braces
	 | 
|
| 82 | 
		delimiter_rex = re.compile('([{}"])',re.I)
	 | 
|
| 83 | 
		 | 
|
| 84 | 
		field_rex = re.compile('\s*(\w*)\s*=\s*(.*)')
	 | 
|
| 85 | 
		data_rex = re.compile('\s*(\w*)\s*=\s*([^,]*),?')
	 | 
|
| 86 | 
		 | 
|
| 87 | 
		url_rex = re.compile('\\\url\{([^}]*)\}')
	 | 
|
| 88 | 
		 | 
|
| 89 | 
		 | 
|
| 90 | 
		#  | 
|
| 91 | 
		# return the string parameter without braces  | 
|
| 92 | 
		#  | 
|
| 93 | 
		def transformurls(str):  | 
|
| 94 | 
		return url_rex.sub(r'<a href="\1">\1</a>', str)  | 
|
| 95 | 
		 | 
|
| 96 | 
		#  | 
|
| 97 | 
		# return the string parameter without braces  | 
|
| 98 | 
		#  | 
|
| 99 | 
		def removebraces(str):  | 
|
| 100 | 
		    return rembraces_rex.sub('', str)
	 | 
|
| 101 | 
		 | 
|
| 102 | 
		#  | 
|
| 103 | 
		# latex-specific replacements  | 
|
| 104 | 
		# (do this after braces were removed)  | 
|
| 105 | 
		#  | 
|
| 106 | 
		def latexreplacements(line):  | 
|
| 107 | 
		line = string.replace(line, '~', ' ')  | 
|
| 108 | 
		line = string.replace(line, '\\\'a', 'á')  | 
|
| 109 | 
		line = string.replace(line, '\\"a', 'ä')  | 
|
| 110 | 
		line = string.replace(line, '\\\'e', 'é')  | 
|
| 111 | 
		line = string.replace(line, '\\"e', 'ë')  | 
|
| 112 | 
		line = string.replace(line, '\\\'i', 'í')  | 
|
| 113 | 
		line = string.replace(line, '\\"i', 'ï')  | 
|
| 114 | 
		line = string.replace(line, '\\\'o', 'ó')  | 
|
| 115 | 
		line = string.replace(line, '\\"o', 'ö')  | 
|
| 116 | 
		line = string.replace(line, '\\\'u', 'ú')  | 
|
| 117 | 
		line = string.replace(line, '\\"u', 'ü')  | 
|
| 118 | 
		line = string.replace(line, '\\H o', 'õ')  | 
|
| 119 | 
		line = string.replace(line, '\\H u', 'ü') # ũ does not exist  | 
|
| 120 | 
		line = string.replace(line, '\\\'A', 'Á')  | 
|
| 121 | 
		line = string.replace(line, '\\"A', 'Ä')  | 
|
| 122 | 
		line = string.replace(line, '\\\'E', 'É')  | 
|
| 123 | 
		line = string.replace(line, '\\"E', 'Ë')  | 
|
| 124 | 
		line = string.replace(line, '\\\'I', 'Í')  | 
|
| 125 | 
		line = string.replace(line, '\\"I', 'Ï')  | 
|
| 126 | 
		line = string.replace(line, '\\\'O', 'Ó')  | 
|
| 127 | 
		line = string.replace(line, '\\"O', 'Ö')  | 
|
| 128 | 
		line = string.replace(line, '\\\'U', 'Ú')  | 
|
| 129 | 
		line = string.replace(line, '\\"U', 'Ü')  | 
|
| 130 | 
		line = string.replace(line, '\\H O', 'Õ')  | 
|
| 131 | 
		line = string.replace(line, '\\H U', 'Ü') # Ũ does not exist  | 
|
| 132 | 
		 | 
|
| 133 | 
		return line  | 
|
| 134 | 
		 | 
|
| 135 | 
		#  | 
|
| 136 | 
		# copy characters form a string decoding html expressions (&xyz;)  | 
|
| 137 | 
		#  | 
|
| 138 | 
		def copychars(str, ifrom, count):  | 
|
| 139 | 
		result = ''  | 
|
| 140 | 
		i = ifrom  | 
|
| 141 | 
		c = 0  | 
|
| 142 | 
		html_spec = False  | 
|
| 143 | 
		while (i < len(str)) and (c < count):  | 
|
| 144 | 
		if str[i] == '&':  | 
|
| 145 | 
		html_spec = True;  | 
|
| 146 | 
		if i+1 < len(str):  | 
|
| 147 | 
		result += str[i+1]  | 
|
| 148 | 
		c += 1  | 
|
| 149 | 
		i += 2  | 
|
| 150 | 
		else:  | 
|
| 151 | 
		if not html_spec:  | 
|
| 152 | 
		if ((str[i] >= 'A') and (str[i] <= 'Z')) or \  | 
|
| 153 | 
		((str[i] >= 'a') and (str[i] <= 'z')):  | 
|
| 154 | 
		result += str[i]  | 
|
| 155 | 
		c += 1  | 
|
| 156 | 
		elif str[i] == ';':  | 
|
| 157 | 
		html_spec = False;  | 
|
| 158 | 
		i += 1  | 
|
| 159 | 
		 | 
|
| 160 | 
		return result  | 
|
| 161 | 
		 | 
|
| 162 | 
		 | 
|
| 163 | 
		#  | 
|
| 164 | 
		# Handle a list of authors (separated by 'and').  | 
|
| 165 | 
		# It gives back an array of the follwing values:  | 
|
| 166 | 
		# - num: the number of authors,  | 
|
| 167 | 
		# - list: the list of the author names,  | 
|
| 168 | 
		# - text: the bibtex text (separated by commas and/or 'and')  | 
|
| 169 | 
		# - abbrev: abbreviation that can be used for indicate the  | 
|
| 170 | 
		# bibliography entries  | 
|
| 171 | 
		#  | 
|
| 172 | 
		def bibtexauthor(data):  | 
|
| 173 | 
		    result = {}
	 | 
|
| 174 | 
		bibtex = ''  | 
|
| 175 | 
		result['list'] = author_rex.split(data)  | 
|
| 176 | 
		result['num'] = len(result['list'])  | 
|
| 177 | 
		for i, author in enumerate(result['list']):  | 
|
| 178 | 
		# general transformations  | 
|
| 179 | 
		author = latexreplacements(removebraces(author.strip()))  | 
|
| 180 | 
		# transform "Xyz, A. B." to "A. B. Xyz"  | 
|
| 181 | 
		        pos = author.find(',')
	 | 
|
| 182 | 
		if pos != -1:  | 
|
| 183 | 
		author = author[pos+1:].strip() + ' ' + author[:pos].strip()  | 
|
| 184 | 
		result['list'][i] = author  | 
|
| 185 | 
		bibtex += author + '#'  | 
|
| 186 | 
		bibtex = bibtex[:-1]  | 
|
| 187 | 
		if result['num'] > 1:  | 
|
| 188 | 
		        ix = bibtex.rfind('#')
	 | 
|
| 189 | 
		if result['num'] == 2:  | 
|
| 190 | 
		bibtex = bibtex[:ix] + ' and ' + bibtex[ix+1:]  | 
|
| 191 | 
		else:  | 
|
| 192 | 
		bibtex = bibtex[:ix] + ', and ' + bibtex[ix+1:]  | 
|
| 193 | 
		    bibtex = bibtex.replace('#', ', ')
	 | 
|
| 194 | 
		result['text'] = bibtex  | 
|
| 195 | 
		 | 
|
| 196 | 
		result['abbrev'] = ''  | 
|
| 197 | 
		for author in result['list']:  | 
|
| 198 | 
		        pos = author.rfind(' ') + 1
	 | 
|
| 199 | 
		count = 1  | 
|
| 200 | 
		if result['num'] == 1:  | 
|
| 201 | 
		count = 3  | 
|
| 202 | 
		result['abbrev'] += copychars(author, pos, count)  | 
|
| 203 | 
		 | 
|
| 204 | 
		return result  | 
|
| 205 | 
		 | 
|
| 206 | 
		 | 
|
| 207 | 
		#  | 
|
| 208 | 
		# data = title string  | 
|
| 209 | 
		# @return the capitalized title (first letter is capitalized), rest are capitalized  | 
|
| 210 | 
		# only if capitalized inside braces  | 
|
| 211 | 
		#  | 
|
| 212 | 
		def capitalizetitle(data):  | 
|
| 213 | 
		title_list = capitalize_rex.split(data)  | 
|
| 214 | 
		title = ''  | 
|
| 215 | 
		count = 0  | 
|
| 216 | 
		for phrase in title_list:  | 
|
| 217 | 
		check = string.lstrip(phrase)  | 
|
| 218 | 
		 | 
|
| 219 | 
		# keep phrase's capitalization the same  | 
|
| 220 | 
		         if check.find('{') == 0:
	 | 
|
| 221 | 
		title += removebraces(phrase)  | 
|
| 222 | 
		else:  | 
|
| 223 | 
		# first word --> capitalize first letter (after spaces)  | 
|
| 224 | 
		if count == 0:  | 
|
| 225 | 
		title += check.capitalize()  | 
|
| 226 | 
		else:  | 
|
| 227 | 
		title += phrase.lower()  | 
|
| 228 | 
		count = count + 1  | 
|
| 229 | 
		 | 
|
| 230 | 
		return title  | 
|
| 231 | 
		 | 
|
| 232 | 
		 | 
|
| 233 | 
		#  | 
|
| 234 | 
		# @return the bibtex for the title  | 
|
| 235 | 
		# @param data --> title string  | 
|
| 236 | 
		# braces are removed from title  | 
|
| 237 | 
		#  | 
|
| 238 | 
		def bibtextitle(data, entrytype):  | 
|
| 239 | 
		    if entrytype in ('book', 'inbook'):
	 | 
|
| 240 | 
		title = removebraces(data.strip())  | 
|
| 241 | 
		else:  | 
|
| 242 | 
		title = removebraces(capitalizetitle(data.strip()))  | 
|
| 243 | 
		bibtex = title  | 
|
| 244 | 
		return bibtex  | 
|
| 245 | 
		 | 
|
| 246 | 
		 | 
|
| 247 | 
		#  | 
|
| 248 | 
		# function to compare entry lists  | 
|
| 249 | 
		#  | 
|
| 250 | 
		def entry_cmp(x, y):  | 
|
| 251 | 
		return cmp(x[0], y[0])  | 
|
| 252 | 
		 | 
|
| 253 | 
		 | 
|
| 254 | 
		#  | 
|
| 255 | 
		# print the XML for the transformed "filecont_source"  | 
|
| 256 | 
		#  | 
|
| 257 | 
		def bibtexdecoder(filecont_source):  | 
|
| 258 | 
		filecont = []  | 
|
| 259 | 
		file = []  | 
|
| 260 | 
		 | 
|
| 261 | 
		    # want @<alphanumeric chars><spaces>{<spaces><any chars>,
	 | 
|
| 262 | 
		    pubtype_rex = re.compile('@(\w*)\s*{\s*(.*),')
	 | 
|
| 263 | 
		    endtype_rex = re.compile('}\s*$')
	 | 
|
| 264 | 
		    endtag_rex = re.compile('^\s*}\s*$')
	 | 
|
| 265 | 
		 | 
|
| 266 | 
		    bracefield_rex = re.compile('\s*(\w*)\s*=\s*(.*)')
	 | 
|
| 267 | 
		    bracedata_rex = re.compile('\s*(\w*)\s*=\s*{(.*)},?')
	 | 
|
| 268 | 
		 | 
|
| 269 | 
		    quotefield_rex = re.compile('\s*(\w*)\s*=\s*(.*)')
	 | 
|
| 270 | 
		    quotedata_rex = re.compile('\s*(\w*)\s*=\s*"(.*)",?')
	 | 
|
| 271 | 
		 | 
|
| 272 | 
		for line in filecont_source:  | 
|
| 273 | 
		line = line[:-1]  | 
|
| 274 | 
		 | 
|
| 275 | 
		# encode character entities  | 
|
| 276 | 
		line = string.replace(line, '&', '&')  | 
|
| 277 | 
		line = string.replace(line, '<', '<')  | 
|
| 278 | 
		line = string.replace(line, '>', '>')  | 
|
| 279 | 
		 | 
|
| 280 | 
		# start entry: publication type (store for later use)  | 
|
| 281 | 
		if pubtype_rex.match(line):  | 
|
| 282 | 
		        # want @<alphanumeric chars><spaces>{<spaces><any chars>,
	 | 
|
| 283 | 
		            entrycont = {}
	 | 
|
| 284 | 
		entry = []  | 
|
| 285 | 
		            entrytype = pubtype_rex.sub('\g<1>',line)
	 | 
|
| 286 | 
		entrytype = string.lower(entrytype)  | 
|
| 287 | 
		            # entryid   = pubtype_rex.sub('\g<2>', line)
	 | 
|
| 288 | 
		 | 
|
| 289 | 
		# end entry if just a }  | 
|
| 290 | 
		elif endtype_rex.match(line):  | 
|
| 291 | 
		# generate doxygen code for the entry  | 
|
| 292 | 
		 | 
|
| 293 | 
		# enty type related formattings  | 
|
| 294 | 
		            if entrytype in ('book', 'inbook'):
	 | 
|
| 295 | 
		entrycont['title'] = '<em>' + entrycont['title'] + '</em>'  | 
|
| 296 | 
		                if not entrycont.has_key('author'):
	 | 
|
| 297 | 
		entrycont['author'] = entrycont['editor']  | 
|
| 298 | 
		entrycont['author']['text'] += ', editors'  | 
|
| 299 | 
		elif entrytype == 'article':  | 
|
| 300 | 
		entrycont['journal'] = '<em>' + entrycont['journal'] + '</em>'  | 
|
| 301 | 
		            elif entrytype in ('inproceedings', 'incollection', 'conference'):
	 | 
|
| 302 | 
		entrycont['booktitle'] = '<em>' + entrycont['booktitle'] + '</em>'  | 
|
| 303 | 
		elif entrytype == 'techreport':  | 
|
| 304 | 
		                if not entrycont.has_key('type'):
	 | 
|
| 305 | 
		entrycont['type'] = 'Technical report'  | 
|
| 306 | 
		elif entrytype == 'mastersthesis':  | 
|
| 307 | 
		entrycont['type'] = 'Master\'s thesis'  | 
|
| 308 | 
		elif entrytype == 'phdthesis':  | 
|
| 309 | 
		entrycont['type'] = 'PhD thesis'  | 
|
| 310 | 
		 | 
|
| 311 | 
		for eline in entrycont:  | 
|
| 312 | 
		if eline != '':  | 
|
| 313 | 
		eline = latexreplacements(eline)  | 
|
| 314 | 
		 | 
|
| 315 | 
		            if entrycont.has_key('pages') and (entrycont['pages'] != ''):
	 | 
|
| 316 | 
		entrycont['pages'] = string.replace(entrycont['pages'], '--', '-')  | 
|
| 317 | 
		 | 
|
| 318 | 
		            if entrycont.has_key('author') and (entrycont['author'] != ''):
	 | 
|
| 319 | 
		entry.append(entrycont['author']['text'] + '.')  | 
|
| 320 | 
		            if entrycont.has_key('title') and (entrycont['title'] != ''):
	 | 
|
| 321 | 
		entry.append(entrycont['title'] + '.')  | 
|
| 322 | 
		            if entrycont.has_key('journal') and (entrycont['journal'] != ''):
	 | 
|
| 323 | 
		entry.append(entrycont['journal'] + ',')  | 
|
| 324 | 
		            if entrycont.has_key('booktitle') and (entrycont['booktitle'] != ''):
	 | 
|
| 325 | 
		                entry.append('In ' + entrycont['booktitle'] + ',')
	 | 
|
| 326 | 
		            if entrycont.has_key('type') and (entrycont['type'] != ''):
	 | 
|
| 327 | 
		eline = entrycont['type']  | 
|
| 328 | 
		                if entrycont.has_key('number') and (entrycont['number'] != ''):
	 | 
|
| 329 | 
		eline += ' ' + entrycont['number']  | 
|
| 330 | 
		eline += ','  | 
|
| 331 | 
		entry.append(eline)  | 
|
| 332 | 
		            if entrycont.has_key('institution') and (entrycont['institution'] != ''):
	 | 
|
| 333 | 
		entry.append(entrycont['institution'] + ',')  | 
|
| 334 | 
		            if entrycont.has_key('publisher') and (entrycont['publisher'] != ''):
	 | 
|
| 335 | 
		entry.append(entrycont['publisher'] + ',')  | 
|
| 336 | 
		            if entrycont.has_key('school') and (entrycont['school'] != ''):
	 | 
|
| 337 | 
		entry.append(entrycont['school'] + ',')  | 
|
| 338 | 
		            if entrycont.has_key('address') and (entrycont['address'] != ''):
	 | 
|
| 339 | 
		entry.append(entrycont['address'] + ',')  | 
|
| 340 | 
		            if entrycont.has_key('edition') and (entrycont['edition'] != ''):
	 | 
|
| 341 | 
		entry.append(entrycont['edition'] + ' edition,')  | 
|
| 342 | 
		            if entrycont.has_key('howpublished') and (entrycont['howpublished'] != ''):
	 | 
|
| 343 | 
		entry.append(entrycont['howpublished'] + ',')  | 
|
| 344 | 
		            if entrycont.has_key('volume') and (entrycont['volume'] != ''):
	 | 
|
| 345 | 
		eline = entrycont['volume'];  | 
|
| 346 | 
		                if entrycont.has_key('number') and (entrycont['number'] != ''):
	 | 
|
| 347 | 
		                    eline += '(' + entrycont['number'] + ')'
	 | 
|
| 348 | 
		                if entrycont.has_key('pages') and (entrycont['pages'] != ''):
	 | 
|
| 349 | 
		eline += ':' + entrycont['pages']  | 
|
| 350 | 
		eline += ','  | 
|
| 351 | 
		entry.append(eline)  | 
|
| 352 | 
		else:  | 
|
| 353 | 
		                if entrycont.has_key('pages') and (entrycont['pages'] != ''):
	 | 
|
| 354 | 
		                    entry.append('pages ' + entrycont['pages'] + ',')
	 | 
|
| 355 | 
		            if entrycont.has_key('year') and (entrycont['year'] != ''):
	 | 
|
| 356 | 
		                if entrycont.has_key('month') and (entrycont['month'] != ''):
	 | 
|
| 357 | 
		entry.append(entrycont['month'] + ' ' + entrycont['year'] + '.')  | 
|
| 358 | 
		else:  | 
|
| 359 | 
		entry.append(entrycont['year'] + '.')  | 
|
| 360 | 
		            if entrycont.has_key('note') and (entrycont['note'] != ''):
	 | 
|
| 361 | 
		entry.append(entrycont['note'] + '.')  | 
|
| 362 | 
		 | 
|
| 363 | 
		# generate keys for sorting and for the output  | 
|
| 364 | 
		sortkey = ''  | 
|
| 365 | 
		bibkey = ''  | 
|
| 366 | 
		            if entrycont.has_key('author'):
	 | 
|
| 367 | 
		for author in entrycont['author']['list']:  | 
|
| 368 | 
		                    sortkey += copychars(author, author.rfind(' ')+1, len(author))
	 | 
|
| 369 | 
		bibkey = entrycont['author']['abbrev']  | 
|
| 370 | 
		else:  | 
|
| 371 | 
		bibkey = 'x'  | 
|
| 372 | 
		            if entrycont.has_key('year'):
	 | 
|
| 373 | 
		sortkey += entrycont['year']  | 
|
| 374 | 
		bibkey += entrycont['year'][-2:]  | 
|
| 375 | 
		            if entrycont.has_key('title'):
	 | 
|
| 376 | 
		sortkey += entrycont['title']  | 
|
| 377 | 
		            if entrycont.has_key('key'):
	 | 
|
| 378 | 
		sortkey = entrycont['key'] + sortkey  | 
|
| 379 | 
		bibkey = entrycont['key']  | 
|
| 380 | 
		entry.insert(0, sortkey)  | 
|
| 381 | 
		entry.insert(1, bibkey)  | 
|
| 382 | 
		 | 
|
| 383 | 
		# add the entry to the file contents  | 
|
| 384 | 
		filecont.append(entry)  | 
|
| 385 | 
		 | 
|
| 386 | 
		else:  | 
|
| 387 | 
		# field, publication info  | 
|
| 388 | 
		field = ''  | 
|
| 389 | 
		data = ''  | 
|
| 390 | 
		 | 
|
| 391 | 
		            # field = {data} entries
	 | 
|
| 392 | 
		if bracedata_rex.match(line):  | 
|
| 393 | 
		                field = bracefield_rex.sub('\g<1>', line)
	 | 
|
| 394 | 
		field = string.lower(field)  | 
|
| 395 | 
		                data =  bracedata_rex.sub('\g<2>', line)
	 | 
|
| 396 | 
		 | 
|
| 397 | 
		# field = "data" entries  | 
|
| 398 | 
		elif quotedata_rex.match(line):  | 
|
| 399 | 
		                field = quotefield_rex.sub('\g<1>', line)
	 | 
|
| 400 | 
		field = string.lower(field)  | 
|
| 401 | 
		                data =  quotedata_rex.sub('\g<2>', line)
	 | 
|
| 402 | 
		 | 
|
| 403 | 
		# field = data entries  | 
|
| 404 | 
		elif data_rex.match(line):  | 
|
| 405 | 
		                field = field_rex.sub('\g<1>', line)
	 | 
|
| 406 | 
		field = string.lower(field)  | 
|
| 407 | 
		                data =  data_rex.sub('\g<2>', line)
	 | 
|
| 408 | 
		 | 
|
| 409 | 
		            if field in ('author', 'editor'):
	 | 
|
| 410 | 
		entrycont[field] = bibtexauthor(data)  | 
|
| 411 | 
		line = ''  | 
|
| 412 | 
		elif field == 'title':  | 
|
| 413 | 
		line = bibtextitle(data, entrytype)  | 
|
| 414 | 
		elif field != '':  | 
|
| 415 | 
		line = removebraces(transformurls(data.strip()))  | 
|
| 416 | 
		 | 
|
| 417 | 
		if line != '':  | 
|
| 418 | 
		line = latexreplacements(line)  | 
|
| 419 | 
		entrycont[field] = line  | 
|
| 420 | 
		 | 
|
| 421 | 
		 | 
|
| 422 | 
		# sort entries  | 
|
| 423 | 
		filecont.sort(entry_cmp)  | 
|
| 424 | 
		 | 
|
| 425 | 
		# count the bibtex keys  | 
|
| 426 | 
		    keytable = {}
	 | 
|
| 427 | 
		    counttable = {}
	 | 
|
| 428 | 
		for entry in filecont:  | 
|
| 429 | 
		bibkey = entry[1]  | 
|
| 430 | 
		if not keytable.has_key(bibkey):  | 
|
| 431 | 
		keytable[bibkey] = 1  | 
|
| 432 | 
		else:  | 
|
| 433 | 
		keytable[bibkey] += 1  | 
|
| 434 | 
		 | 
|
| 435 | 
		for bibkey in keytable.keys():  | 
|
| 436 | 
		counttable[bibkey] = 0  | 
|
| 437 | 
		 | 
|
| 438 | 
		# generate output  | 
|
| 439 | 
		for entry in filecont:  | 
|
| 440 | 
		# generate output key form the bibtex key  | 
|
| 441 | 
		bibkey = entry[1]  | 
|
| 442 | 
		if keytable[bibkey] == 1:  | 
|
| 443 | 
		outkey = bibkey  | 
|
| 444 | 
		else:  | 
|
| 445 | 
		outkey = bibkey + chr(97 + counttable[bibkey])  | 
|
| 446 | 
		counttable[bibkey] += 1  | 
|
| 447 | 
		 | 
|
| 448 | 
		# append the entry code to the output  | 
|
| 449 | 
		        file.append('<tr valign="top">\n' + \
	 | 
|
| 450 | 
		'<td>[' + outkey + ']</td>')  | 
|
| 451 | 
		        file.append('<td>')
	 | 
|
| 452 | 
		        file.append('\\anchor ' + outkey)
	 | 
|
| 453 | 
		for line in entry[2:]:  | 
|
| 454 | 
		file.append(line)  | 
|
| 455 | 
		        file.append('</td>\n</tr>')
	 | 
|
| 456 | 
		        file.append('')
	 | 
|
| 457 | 
		 | 
|
| 458 | 
		return file  | 
|
| 459 | 
		 | 
|
| 460 | 
		 | 
|
| 461 | 
		#  | 
|
| 462 | 
		# return 1 iff abbr is in line but not inside braces or quotes  | 
|
| 463 | 
		# assumes that abbr appears only once on the line (out of braces and quotes)  | 
|
| 464 | 
		#  | 
|
| 465 | 
		def verify_out_of_braces(line, abbr):  | 
|
| 466 | 
		 | 
|
| 467 | 
		phrase_split = delimiter_rex.split(line)  | 
|
| 468 | 
		 | 
|
| 469 | 
		abbr_rex = re.compile( '\\b' + abbr + '\\b', re.I)  | 
|
| 470 | 
		 | 
|
| 471 | 
		open_brace = 0  | 
|
| 472 | 
		open_quote = 0  | 
|
| 473 | 
		 | 
|
| 474 | 
		for phrase in phrase_split:  | 
|
| 475 | 
		        if phrase == "{":
	 | 
|
| 476 | 
		open_brace = open_brace + 1  | 
|
| 477 | 
		elif phrase == "}":  | 
|
| 478 | 
		open_brace = open_brace - 1  | 
|
| 479 | 
		elif phrase == '"':  | 
|
| 480 | 
		if open_quote == 1:  | 
|
| 481 | 
		open_quote = 0  | 
|
| 482 | 
		else:  | 
|
| 483 | 
		open_quote = 1  | 
|
| 484 | 
		elif abbr_rex.search(phrase):  | 
|
| 485 | 
		if open_brace == 0 and open_quote == 0:  | 
|
| 486 | 
		return 1  | 
|
| 487 | 
		 | 
|
| 488 | 
		return 0  | 
|
| 489 | 
		 | 
|
| 490 | 
		 | 
|
| 491 | 
		#  | 
|
| 492 | 
		# a line in the form phrase1 # phrase2 # ... # phrasen  | 
|
| 493 | 
		# is returned as phrase1 phrase2 ... phrasen  | 
|
| 494 | 
		# with the correct punctuation  | 
|
| 495 | 
		# Bug: Doesn't always work with multiple abbreviations plugged in  | 
|
| 496 | 
		#  | 
|
| 497 | 
		def concat_line(line):  | 
|
| 498 | 
		# only look at part after equals  | 
|
| 499 | 
		    field = field_rex.sub('\g<1>',line)
	 | 
|
| 500 | 
		    rest = field_rex.sub('\g<2>',line)
	 | 
|
| 501 | 
		 | 
|
| 502 | 
		concat_line = field + ' ='  | 
|
| 503 | 
		 | 
|
| 504 | 
		pound_split = concatsplit_rex.split(rest)  | 
|
| 505 | 
		 | 
|
| 506 | 
		phrase_count = 0  | 
|
| 507 | 
		length = len(pound_split)  | 
|
| 508 | 
		 | 
|
| 509 | 
		for phrase in pound_split:  | 
|
| 510 | 
		phrase = phrase.strip()  | 
|
| 511 | 
		if phrase_count != 0:  | 
|
| 512 | 
		            if phrase.startswith('"') or phrase.startswith('{'):
	 | 
|
| 513 | 
		phrase = phrase[1:]  | 
|
| 514 | 
		        elif phrase.startswith('"'):
	 | 
|
| 515 | 
		            phrase = phrase.replace('"','{',1)
	 | 
|
| 516 | 
		 | 
|
| 517 | 
		if phrase_count != length-1:  | 
|
| 518 | 
		            if phrase.endswith('"') or phrase.endswith('}'):
	 | 
|
| 519 | 
		phrase = phrase[:-1]  | 
|
| 520 | 
		else:  | 
|
| 521 | 
		            if phrase.endswith('"'):
	 | 
|
| 522 | 
		phrase = phrase[:-1]  | 
|
| 523 | 
		phrase = phrase + "}"  | 
|
| 524 | 
		            elif phrase.endswith('",'):
	 | 
|
| 525 | 
		phrase = phrase[:-2]  | 
|
| 526 | 
		phrase = phrase + "},"  | 
|
| 527 | 
		 | 
|
| 528 | 
		# if phrase did have \#, add the \# back  | 
|
| 529 | 
		        if phrase.endswith('\\'):
	 | 
|
| 530 | 
		phrase = phrase + "#"  | 
|
| 531 | 
		concat_line = concat_line + ' ' + phrase  | 
|
| 532 | 
		 | 
|
| 533 | 
		phrase_count = phrase_count + 1  | 
|
| 534 | 
		 | 
|
| 535 | 
		return concat_line  | 
|
| 536 | 
		 | 
|
| 537 | 
		 | 
|
| 538 | 
		#  | 
|
| 539 | 
		# substitute abbreviations into filecont  | 
|
| 540 | 
		# @param filecont_source - string of data from file  | 
|
| 541 | 
		#  | 
|
| 542 | 
		def bibtex_replace_abbreviations(filecont_source):  | 
|
| 543 | 
		filecont = filecont_source.splitlines()  | 
|
| 544 | 
		 | 
|
| 545 | 
		# These are defined in bibtex, so we'll define them too  | 
|
| 546 | 
		abbr_list = ['jan','feb','mar','apr','may','jun',  | 
|
| 547 | 
		'jul','aug','sep','oct','nov','dec']  | 
|
| 548 | 
		value_list = ['January','February','March','April',  | 
|
| 549 | 
		'May','June','July','August','September',  | 
|
| 550 | 
		'October','November','December']  | 
|
| 551 | 
		 | 
|
| 552 | 
		abbr_rex = []  | 
|
| 553 | 
		total_abbr_count = 0  | 
|
| 554 | 
		 | 
|
| 555 | 
		front = '\\b'  | 
|
| 556 | 
		back = '(,?)\\b'  | 
|
| 557 | 
		 | 
|
| 558 | 
		for x in abbr_list:  | 
|
| 559 | 
		abbr_rex.append( re.compile( front + abbr_list[total_abbr_count] + back, re.I ) )  | 
|
| 560 | 
		total_abbr_count = total_abbr_count + 1  | 
|
| 561 | 
		 | 
|
| 562 | 
		 | 
|
| 563 | 
		    abbrdef_rex = re.compile('\s*@string\s*{\s*('+ valid_name_chars +'*)\s*=(.*)',
	 | 
|
| 564 | 
		re.I)  | 
|
| 565 | 
		 | 
|
| 566 | 
		    comment_rex = re.compile('@comment\s*{',re.I)
	 | 
|
| 567 | 
		    preamble_rex = re.compile('@preamble\s*{',re.I)
	 | 
|
| 568 | 
		 | 
|
| 569 | 
		waiting_for_end_string = 0  | 
|
| 570 | 
		i = 0  | 
|
| 571 | 
		filecont2 = ''  | 
|
| 572 | 
		 | 
|
| 573 | 
		for line in filecont:  | 
|
| 574 | 
		if line == ' ' or line == '':  | 
|
| 575 | 
		continue  | 
|
| 576 | 
		 | 
|
| 577 | 
		if waiting_for_end_string:  | 
|
| 578 | 
		            if re.search('}',line):
	 | 
|
| 579 | 
		waiting_for_end_string = 0  | 
|
| 580 | 
		continue  | 
|
| 581 | 
		 | 
|
| 582 | 
		if abbrdef_rex.search(line):  | 
|
| 583 | 
		            abbr = abbrdef_rex.sub('\g<1>', line)
	 | 
|
| 584 | 
		 | 
|
| 585 | 
		if abbr_list.count(abbr) == 0:  | 
|
| 586 | 
		                val = abbrdef_rex.sub('\g<2>', line)
	 | 
|
| 587 | 
		abbr_list.append(abbr)  | 
|
| 588 | 
		value_list.append(string.strip(val))  | 
|
| 589 | 
		abbr_rex.append( re.compile( front + abbr_list[total_abbr_count] + back, re.I ) )  | 
|
| 590 | 
		total_abbr_count = total_abbr_count + 1  | 
|
| 591 | 
		waiting_for_end_string = 1  | 
|
| 592 | 
		continue  | 
|
| 593 | 
		 | 
|
| 594 | 
		if comment_rex.search(line):  | 
|
| 595 | 
		waiting_for_end_string = 1  | 
|
| 596 | 
		continue  | 
|
| 597 | 
		 | 
|
| 598 | 
		if preamble_rex.search(line):  | 
|
| 599 | 
		waiting_for_end_string = 1  | 
|
| 600 | 
		continue  | 
|
| 601 | 
		 | 
|
| 602 | 
		 | 
|
| 603 | 
		# replace subsequent abbreviations with the value  | 
|
| 604 | 
		abbr_count = 0  | 
|
| 605 | 
		 | 
|
| 606 | 
		for x in abbr_list:  | 
|
| 607 | 
		 | 
|
| 608 | 
		if abbr_rex[abbr_count].search(line):  | 
|
| 609 | 
		if verify_out_of_braces(line,abbr_list[abbr_count]) == 1:  | 
|
| 610 | 
		line = abbr_rex[abbr_count].sub( value_list[abbr_count] + '\g<1>', line)  | 
|
| 611 | 
		# Check for # concatenations  | 
|
| 612 | 
		if concatsplit_rex.search(line):  | 
|
| 613 | 
		line = concat_line(line)  | 
|
| 614 | 
		abbr_count = abbr_count + 1  | 
|
| 615 | 
		 | 
|
| 616 | 
		 | 
|
| 617 | 
		filecont2 = filecont2 + line + '\n'  | 
|
| 618 | 
		i = i+1  | 
|
| 619 | 
		 | 
|
| 620 | 
		 | 
|
| 621 | 
		# Do one final pass over file  | 
|
| 622 | 
		 | 
|
| 623 | 
		    # make sure that didn't end up with {" or }" after the substitution
	 | 
|
| 624 | 
		    filecont2 = filecont2.replace('{"','{{')
	 | 
|
| 625 | 
		    filecont2 = filecont2.replace('"}','}}')
	 | 
|
| 626 | 
		 | 
|
| 627 | 
		    afterquotevalue_rex = re.compile('"\s*,\s*')
	 | 
|
| 628 | 
		    afterbrace_rex = re.compile('"\s*}')
	 | 
|
| 629 | 
		    afterbracevalue_rex = re.compile('(=\s*{[^=]*)},\s*')
	 | 
|
| 630 | 
		 | 
|
| 631 | 
		# add new lines to data that changed because of abbreviation substitutions  | 
|
| 632 | 
		    filecont2 = afterquotevalue_rex.sub('",\n', filecont2)
	 | 
|
| 633 | 
		    filecont2 = afterbrace_rex.sub('"\n}', filecont2)
	 | 
|
| 634 | 
		    filecont2 = afterbracevalue_rex.sub('\g<1>},\n', filecont2)
	 | 
|
| 635 | 
		 | 
|
| 636 | 
		return filecont2  | 
|
| 637 | 
		 | 
|
| 638 | 
		#  | 
|
| 639 | 
		# convert @type( ... ) to @type{ ... }
	 | 
|
| 640 | 
		#  | 
|
| 641 | 
		def no_outer_parens(filecont):  | 
|
| 642 | 
		 | 
|
| 643 | 
		# do checking for open parens  | 
|
| 644 | 
		# will convert to braces  | 
|
| 645 | 
		    paren_split = re.split('([(){}])',filecont)
	 | 
|
| 646 | 
		 | 
|
| 647 | 
		open_paren_count = 0  | 
|
| 648 | 
		open_type = 0  | 
|
| 649 | 
		look_next = 0  | 
|
| 650 | 
		 | 
|
| 651 | 
		# rebuild filecont  | 
|
| 652 | 
		filecont = ''  | 
|
| 653 | 
		 | 
|
| 654 | 
		    at_rex = re.compile('@\w*')
	 | 
|
| 655 | 
		 | 
|
| 656 | 
		for phrase in paren_split:  | 
|
| 657 | 
		if look_next == 1:  | 
|
| 658 | 
		            if phrase == '(':
	 | 
|
| 659 | 
		                phrase = '{'
	 | 
|
| 660 | 
		open_paren_count = open_paren_count + 1  | 
|
| 661 | 
		else:  | 
|
| 662 | 
		open_type = 0  | 
|
| 663 | 
		look_next = 0  | 
|
| 664 | 
		 | 
|
| 665 | 
		        if phrase == '(':
	 | 
|
| 666 | 
		open_paren_count = open_paren_count + 1  | 
|
| 667 | 
		 | 
|
| 668 | 
		elif phrase == ')':  | 
|
| 669 | 
		open_paren_count = open_paren_count - 1  | 
|
| 670 | 
		if open_type == 1 and open_paren_count == 0:  | 
|
| 671 | 
		phrase = '}'  | 
|
| 672 | 
		open_type = 0  | 
|
| 673 | 
		 | 
|
| 674 | 
		elif at_rex.search( phrase ):  | 
|
| 675 | 
		open_type = 1  | 
|
| 676 | 
		look_next = 1  | 
|
| 677 | 
		 | 
|
| 678 | 
		filecont = filecont + phrase  | 
|
| 679 | 
		 | 
|
| 680 | 
		return filecont  | 
|
| 681 | 
		 | 
|
| 682 | 
		 | 
|
| 683 | 
		#  | 
|
| 684 | 
		# make all whitespace into just one space  | 
|
| 685 | 
		# format the bibtex file into a usable form.  | 
|
| 686 | 
		#  | 
|
| 687 | 
		def bibtexwasher(filecont_source):  | 
|
| 688 | 
		 | 
|
| 689 | 
		    space_rex = re.compile('\s+')
	 | 
|
| 690 | 
		    comment_rex = re.compile('\s*%')
	 | 
|
| 691 | 
		 | 
|
| 692 | 
		filecont = []  | 
|
| 693 | 
		 | 
|
| 694 | 
		# remove trailing and excessive whitespace  | 
|
| 695 | 
		# ignore comments  | 
|
| 696 | 
		for line in filecont_source:  | 
|
| 697 | 
		line = string.strip(line)  | 
|
| 698 | 
		        line = space_rex.sub(' ', line)
	 | 
|
| 699 | 
		# ignore comments  | 
|
| 700 | 
		if not comment_rex.match(line) and line != '':  | 
|
| 701 | 
		            filecont.append(' '+ line)
	 | 
|
| 702 | 
		 | 
|
| 703 | 
		filecont = string.join(filecont, '')  | 
|
| 704 | 
		 | 
|
| 705 | 
		# the file is in one long string  | 
|
| 706 | 
		 | 
|
| 707 | 
		filecont = no_outer_parens(filecont)  | 
|
| 708 | 
		 | 
|
| 709 | 
		#  | 
|
| 710 | 
		# split lines according to preferred syntax scheme  | 
|
| 711 | 
		#  | 
|
| 712 | 
		    filecont = re.sub('(=\s*{[^=]*)},', '\g<1>},\n', filecont)
	 | 
|
| 713 | 
		 | 
|
| 714 | 
		# add new lines after commas that are after values  | 
|
| 715 | 
		    filecont = re.sub('"\s*,', '",\n', filecont)
	 | 
|
| 716 | 
		    filecont = re.sub('=\s*([\w\d]+)\s*,', '= \g<1>,\n', filecont)
	 | 
|
| 717 | 
		    filecont = re.sub('(@\w*)\s*({(\s*)[^,\s]*)\s*,',
	 | 
|
| 718 | 
		'\n\n\g<1>\g<2>,\n', filecont)  | 
|
| 719 | 
		 | 
|
| 720 | 
		# add new lines after }  | 
|
| 721 | 
		    filecont = re.sub('"\s*}','"\n}\n', filecont)
	 | 
|
| 722 | 
		    filecont = re.sub('}\s*,','},\n', filecont)
	 | 
|
| 723 | 
		 | 
|
| 724 | 
		 | 
|
| 725 | 
		    filecont = re.sub('@(\w*)', '\n@\g<1>', filecont)
	 | 
|
| 726 | 
		 | 
|
| 727 | 
		# character encoding, reserved latex characters  | 
|
| 728 | 
		    filecont = re.sub('{\\\&}', '&', filecont)
	 | 
|
| 729 | 
		    filecont = re.sub('\\\&', '&', filecont)
	 | 
|
| 730 | 
		 | 
|
| 731 | 
		# do checking for open braces to get format correct  | 
|
| 732 | 
		open_brace_count = 0  | 
|
| 733 | 
		    brace_split = re.split('([{}])',filecont)
	 | 
|
| 734 | 
		 | 
|
| 735 | 
		# rebuild filecont  | 
|
| 736 | 
		filecont = ''  | 
|
| 737 | 
		 | 
|
| 738 | 
		for phrase in brace_split:  | 
|
| 739 | 
		        if phrase == '{':
	 | 
|
| 740 | 
		open_brace_count = open_brace_count + 1  | 
|
| 741 | 
		elif phrase == '}':  | 
|
| 742 | 
		open_brace_count = open_brace_count - 1  | 
|
| 743 | 
		if open_brace_count == 0:  | 
|
| 744 | 
		filecont = filecont + '\n'  | 
|
| 745 | 
		 | 
|
| 746 | 
		filecont = filecont + phrase  | 
|
| 747 | 
		 | 
|
| 748 | 
		filecont2 = bibtex_replace_abbreviations(filecont)  | 
|
| 749 | 
		 | 
|
| 750 | 
		# gather  | 
|
| 751 | 
		filecont = filecont2.splitlines()  | 
|
| 752 | 
		i=0  | 
|
| 753 | 
		j=0 # count the number of blank lines  | 
|
| 754 | 
		for line in filecont:  | 
|
| 755 | 
		# ignore blank lines  | 
|
| 756 | 
		if line == '' or line == ' ':  | 
|
| 757 | 
		j = j+1  | 
|
| 758 | 
		continue  | 
|
| 759 | 
		filecont[i] = line + '\n'  | 
|
| 760 | 
		i = i+1  | 
|
| 761 | 
		 | 
|
| 762 | 
		# get rid of the extra stuff at the end of the array  | 
|
| 763 | 
		# (The extra stuff are duplicates that are in the array because  | 
|
| 764 | 
		# blank lines were removed.)  | 
|
| 765 | 
		length = len( filecont)  | 
|
| 766 | 
		filecont[length-j:length] = []  | 
|
| 767 | 
		 | 
|
| 768 | 
		return filecont  | 
|
| 769 | 
		 | 
|
| 770 | 
		 | 
|
| 771 | 
		def filehandler(filepath):  | 
|
| 772 | 
		try:  | 
|
| 773 | 
		fd = open(filepath, 'r')  | 
|
| 774 | 
		filecont_source = fd.readlines()  | 
|
| 775 | 
		fd.close()  | 
|
| 776 | 
		except:  | 
|
| 777 | 
		print 'Could not open file:', filepath  | 
|
| 778 | 
		washeddata = bibtexwasher(filecont_source)  | 
|
| 779 | 
		outdata = bibtexdecoder(washeddata)  | 
|
| 780 | 
		print '/**'  | 
|
| 781 | 
		print '\page references References'  | 
|
| 782 | 
		 | 
|
| 783 | 
		print '<table border="0" cellspacing="5px" width="100%">'  | 
|
| 784 | 
		 | 
|
| 785 | 
		for line in outdata:  | 
|
| 786 | 
		print line  | 
|
| 787 | 
		print '</table>'  | 
|
| 788 | 
		 | 
|
| 789 | 
		print '*/'  | 
|
| 790 | 
		 | 
|
| 791 | 
		 | 
|
| 792 | 
		# main program  | 
|
| 793 | 
		 | 
|
| 794 | 
		def main():  | 
|
| 795 | 
		import sys  | 
|
| 796 | 
		if sys.argv[1:]:  | 
|
| 797 | 
		filepath = sys.argv[1]  | 
|
| 798 | 
		else:  | 
|
| 799 | 
		print "No input file"  | 
|
| 800 | 
		sys.exit()  | 
|
| 801 | 
		filehandler(filepath)  | 
|
| 802 | 
		 | 
|
| 803 | 
		if __name__ == "__main__": main()  | 
|
| 804 | 
		 | 
|
| 805 | 
		 | 
|
| 806 | 
		# end python script  | 
0 comments (0 inline)