1(**************************************************************************) 2(* bibtex2html - A BibTeX to HTML translator *) 3(* Copyright (C) 1997-2014 Jean-Christophe Filliâtre and Claude Marché *) 4(* *) 5(* This software is free software; you can redistribute it and/or *) 6(* modify it under the terms of the GNU General Public *) 7(* License version 2, as published by the Free Software Foundation. *) 8(* *) 9(* This software is distributed in the hope that it will be useful, *) 10(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) 11(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *) 12(* *) 13(* See the GNU General Public License version 2 for more details *) 14(* (enclosed in the file GPL). *) 15(**************************************************************************) 16 17(*s Filtering and saturating BibTeX files. *) 18 19open Printf 20open Bibtex 21 22let debug = false 23 24(*s [filter bib f] returns the list of keys of [bib] whose fields 25 satisfy the filter criterion [f] *) 26 27let filter biblio criterion = 28 Bibtex.fold 29 (fun entry keys -> 30 match entry with 31 Entry(entry_type,key,fields) 32 when criterion entry_type key fields -> 33 KeySet.add key keys 34 | _ -> keys) 35 biblio 36 KeySet.empty 37 38 39(*s [needed_keys biblio field value keys] returns the set of keys 40 [keys] augmented with the needed keys for [value] *) 41 42let rec needed_keys_for_field biblio field value keys abbrevs = 43 if field = "crossref" 44 then 45 match value with 46 [String(s)] -> 47 if not (KeySet.mem s keys) then 48 begin 49 try 50 let e = find_entry s biblio 51 in 52 if debug then begin 53 eprintf "We need additional crossref %s\n" s 54 end; 55 needed_keys_for_entry biblio (KeySet.add s keys) abbrevs e 56 with Not_found -> 57 if not !Options.quiet then 58 eprintf "Warning: cross-reference \"%s\" not found.\n" s; 59 if !Options.warn_error then exit 2; 60 (keys,abbrevs) 61 end 62 else (keys,abbrevs) 63 | _ -> 64 if not !Options.quiet then 65 eprintf "Warning: cross-references must be constant strings\n"; 66 if !Options.warn_error then exit 2; 67 (keys,abbrevs) 68 else 69 List.fold_right 70 (fun a (keys,abbrevs) -> 71 match a with 72 Id(id) -> 73 let id = String.lowercase_ascii id in 74 if not (KeySet.mem id abbrevs) 75 then 76 try 77 let e = find_abbrev id biblio in 78 if debug then begin 79 eprintf "We need additional abbrev %s\n" id 80 end; 81 needed_keys_for_entry biblio keys (KeySet.add id abbrevs) e 82 with Not_found -> 83 if abbrev_is_implicit id then (keys,abbrevs) 84 else 85 begin 86 if not !Options.quiet then 87 eprintf "Warning: string \"%s\" not found.\n" id; 88 if !Options.warn_error then exit 2; 89 (keys,abbrevs) 90 end 91 else (keys,abbrevs) 92 | _ -> (keys,abbrevs)) 93 value 94 (keys,abbrevs) 95 96and needed_keys_for_entry biblio keys abbrevs = function 97 Entry(entry_type,key,fields) -> 98 List.fold_right 99 (fun (field,value) (keys,abbrevs) -> 100 (*i eprintf "Field : %s\n" field; i*) 101 needed_keys_for_field biblio field value keys abbrevs) 102 fields 103 (keys,abbrevs) 104 | Abbrev(field,value) -> 105 needed_keys_for_field biblio field value keys abbrevs 106 | _ -> (keys,abbrevs) 107 108 109(*s [saturate bib l] returns the smallest part of the bibliography 110 [bib] containing all the keys in l together with all the necessary 111 abbreviation strings and cross-references *) 112 113let saturate biblio s = 114 let (keys,abbrevs) = 115 Bibtex.fold 116 (fun entry (keys,abbrevs) -> 117 match entry with 118 | Entry(_,key,_) as e when KeySet.mem key s -> 119 needed_keys_for_entry biblio keys abbrevs e 120 | _ -> (keys,abbrevs)) 121 biblio 122 (s,KeySet.empty) 123 in 124 KeySet.union keys abbrevs 125