Commits

Anonymous committed ad14361

Initial revision.

Comments (0)

Files changed (1)

+(* compile with: ocamlopt -o footnotes str.cmxa footnotes.ml *)
+
+let sep_line = "@footnote:";;		(* the seperator line *)
+
+let ref_regexp = Str.regexp "\\[\\([0-9]+\\)\\]";;
+
+let ref_of_int n = "[" ^ string_of_int n ^ "]";;
+
+let output_endline c s = output_string c s; output_char c '\n';;
+
+exception End_of_body;;
+
+(* footnotes: read from channel c and print with renumbered footnotes *)
+let footnotes inc outc =
+  let refs = Hashtbl.create 1000000 in
+  let sub_ref l ref =
+    let old_n = int_of_string (Str.matched_group 1 l) in
+    ref_of_int
+      (try Hashtbl.find refs old_n
+      with Not_found ->
+	let n = Hashtbl.length refs + 1 in
+	Hashtbl.add refs old_n n;
+	n)
+  in
+  try
+    while true do
+      let l = input_line inc in
+      if l = sep_line then raise End_of_body;
+      output_endline outc (Str.global_substitute ref_regexp (sub_ref l) l)
+    done
+  with
+    End_of_file ->
+      failwith "Missing footnotes part"
+  | End_of_body ->
+      output_endline outc sep_line;
+      let foots = Array.make (Hashtbl.length refs) None in
+      let add_foot l =
+	if Str.string_match ref_regexp l 0 then
+	  let old_n = int_of_string (Str.matched_group 1 l) in
+	  try
+	    let n = Hashtbl.find refs old_n in
+	    foots.(n-1) <- Some (Str.string_after l (Str.match_end ()))
+	  with
+	    Not_found -> prerr_endline ("unreferenced footnote: " ^ l)
+	else prerr_endline ("malformed footnote: " ^ l)
+      in
+      try
+	while true do
+	  let l = input_line inc in
+	  add_foot l
+	done
+      with End_of_file ->
+	let print_foot idx elt =
+	  output_string outc (ref_of_int (idx + 1));
+	  match elt with
+	    None   -> output_endline outc " ### missing footnote ###"
+	  | Some l -> output_endline outc l in
+	Array.iteri print_foot foots;;
+
+let main () =
+  if Array.length Sys.argv > 1 then
+    let do_file f =
+      let c = open_in f in
+      (try footnotes c stdout with e -> close_in c; raise e);
+      close_in c
+    in
+    Array.iter do_file (Array.sub Sys.argv 1 (Array.length Sys.argv - 1))
+  else footnotes stdin stdout;;
+
+main ();;