Tcl Library Source Code

Hex Artifact Content
Login

Artifact c15cf53523ed4eaf65da0c41300ad37ef1ba675c:


0000: 23 23 23 23 23 0a 23 0a 23 20 22 42 69 62 54 65  #####.#.# "BibTe
0010: 58 20 70 61 72 73 65 72 22 0a 23 20 68 74 74 70  X parser".# http
0020: 3a 2f 2f 77 69 6b 69 2e 74 63 6c 2e 74 6b 2f 31  ://wiki.tcl.tk/1
0030: 33 37 31 39 0a 23 0a 23 20 54 63 6c 20 63 6f 64  3719.#.# Tcl cod
0040: 65 20 68 61 72 76 65 73 74 65 64 20 6f 6e 3a 20  e harvested on: 
0050: 20 20 37 20 4d 61 72 20 32 30 30 35 2c 20 32 33    7 Mar 2005, 23
0060: 3a 35 35 20 47 4d 54 0a 23 20 57 69 6b 69 20 70  :55 GMT.# Wiki p
0070: 61 67 65 20 6c 61 73 74 20 75 70 64 61 74 65 64  age last updated
0080: 3a 20 3f 3f 3f 0a 23 0a 23 23 23 23 23 0a 0a 23  : ???.#.#####..#
0090: 20 62 69 62 74 65 78 2e 74 63 6c 20 2d 2d 0a 23   bibtex.tcl --.#
00a0: 0a 23 20 20 20 20 20 20 41 20 62 61 73 69 63 20  .#      A basic 
00b0: 70 61 72 73 65 72 20 66 6f 72 20 42 69 62 54 65  parser for BibTe
00c0: 58 20 62 69 62 6c 69 6f 67 72 61 70 68 79 20 64  X bibliography d
00d0: 61 74 61 62 61 73 65 73 2e 0a 23 0a 23 20 43 6f  atabases..#.# Co
00e0: 70 79 72 69 67 68 74 20 28 63 29 20 32 30 30 35  pyright (c) 2005
00f0: 20 4e 65 69 6c 20 4d 61 64 64 65 6e 2e 0a 23 20   Neil Madden..# 
0100: 43 6f 70 79 72 69 67 68 74 20 28 63 29 20 32 30  Copyright (c) 20
0110: 30 35 20 41 6e 64 72 65 61 73 20 4b 75 70 72 69  05 Andreas Kupri
0120: 65 73 2e 0a 23 20 4c 69 63 65 6e 73 65 3a 20 54  es..# License: T
0130: 63 6c 2f 42 53 44 20 73 74 79 6c 65 2e 0a 0a 23  cl/BSD style...#
0140: 23 23 20 4e 4f 54 45 53 0a 23 23 23 0a 23 23 23  ## NOTES.###.###
0150: 20 4e 65 65 64 20 63 6f 6d 6d 61 6e 64 73 20 74   Need commands t
0160: 6f 20 69 6e 74 72 6f 73 70 65 63 74 20 70 61 72  o introspect par
0170: 73 65 72 20 73 74 61 74 65 2e 20 45 73 70 65 63  ser state. Espec
0180: 69 61 6c 6c 79 20 74 68 65 20 73 74 72 69 6e 67  ially the string
0190: 0a 23 23 23 20 6d 61 70 20 28 66 6f 72 20 74 65  .### map (for te
01a0: 73 74 69 6e 67 20 6f 66 20 27 61 64 64 53 74 72  sting of 'addStr
01b0: 69 6e 67 73 27 2c 20 73 68 6f 75 6c 64 20 62 65  ings', should be
01c0: 20 75 73 65 66 75 6c 20 69 6e 20 67 65 6e 65 72   useful in gener
01d0: 61 6c 20 61 73 0a 23 23 23 20 77 65 6c 6c 29 2e  al as.### well).
01e0: 0a 0a 23 20 23 23 23 20 23 23 23 20 23 23 23 20  ..# ### ### ### 
01f0: 23 23 23 23 23 23 23 23 23 20 23 23 23 23 23 23  ######### ######
0200: 23 23 23 20 23 23 23 23 23 23 23 23 23 0a 23 23  ### #########.##
0210: 20 52 65 71 75 69 73 69 74 65 73 0a 0a 70 61 63   Requisites..pac
0220: 6b 61 67 65 20 72 65 71 75 69 72 65 20 54 63 6c  kage require Tcl
0230: 20 38 2e 34 0a 70 61 63 6b 61 67 65 20 72 65 71   8.4.package req
0240: 75 69 72 65 20 63 6d 64 6c 69 6e 65 0a 0a 23 20  uire cmdline..# 
0250: 23 23 23 20 23 23 23 20 23 23 23 20 23 23 23 23  ### ### ### ####
0260: 23 23 23 23 23 20 23 23 23 23 23 23 23 23 23 20  ##### ######### 
0270: 23 23 23 23 23 23 23 23 23 0a 23 23 20 49 6d 70  #########.## Imp
0280: 6c 65 6d 65 6e 74 61 74 69 6f 6e 3a 20 50 75 62  lementation: Pub
0290: 6c 69 63 20 41 50 49 0a 0a 6e 61 6d 65 73 70 61  lic API..namespa
02a0: 63 65 20 65 76 61 6c 20 3a 3a 62 69 62 74 65 78  ce eval ::bibtex
02b0: 20 7b 7d 0a 0a 23 20 62 69 62 74 65 78 3a 3a 70   {}..# bibtex::p
02c0: 61 72 73 65 20 2d 2d 0a 23 0a 23 09 50 61 72 73  arse --.#.#.Pars
02d0: 65 20 61 20 62 69 62 74 65 78 20 66 69 6c 65 2e  e a bibtex file.
02e0: 0a 23 0a 23 20 70 61 72 73 65 20 3f 6f 70 74 69  .#.# parse ?opti
02f0: 6f 6e 73 3f 20 3f 62 69 62 74 65 78 3f 0a 0a 70  ons? ?bibtex?..p
0300: 72 6f 63 20 3a 3a 62 69 62 74 65 78 3a 3a 70 61  roc ::bibtex::pa
0310: 72 73 65 20 7b 61 72 67 73 7d 20 7b 0a 20 20 20  rse {args} {.   
0320: 20 76 61 72 69 61 62 6c 65 20 64 61 74 61 0a 20   variable data. 
0330: 20 20 20 76 61 72 69 61 62 6c 65 20 69 64 0a 0a     variable id..
0340: 20 20 20 20 23 20 41 72 67 75 6d 65 6e 74 20 70      # Argument p
0350: 72 6f 63 65 73 73 69 6e 67 0a 20 20 20 20 69 66  rocessing.    if
0360: 20 7b 5b 6c 6c 65 6e 67 74 68 20 24 61 72 67 73   {[llength $args
0370: 5d 20 3c 20 31 7d 20 7b 0a 09 73 65 74 20 65 72  ] < 1} {..set er
0380: 72 20 22 5b 6c 69 6e 64 65 78 20 5b 69 6e 66 6f  r "[lindex [info
0390: 20 6c 65 76 65 6c 20 30 5d 20 30 5d 20 3f 6f 70   level 0] 0] ?op
03a0: 74 69 6f 6e 73 3f 20 3f 62 69 62 74 65 78 3f 22  tions? ?bibtex?"
03b0: 0a 09 72 65 74 75 72 6e 20 2d 63 6f 64 65 20 65  ..return -code e
03c0: 72 72 6f 72 20 22 77 72 6f 6e 67 20 23 20 61 72  rror "wrong # ar
03d0: 67 73 3a 20 73 68 6f 75 6c 64 20 62 65 20 5c 22  gs: should be \"
03e0: 24 65 72 72 5c 22 22 0a 20 20 20 20 7d 0a 0a 20  $err\"".    }.. 
03f0: 20 20 20 61 72 72 61 79 20 73 65 74 20 73 74 61     array set sta
0400: 74 65 20 7b 7d 0a 20 20 20 20 47 65 74 4f 70 74  te {}.    GetOpt
0410: 69 6f 6e 73 20 24 61 72 67 73 20 73 74 61 74 65  ions $args state
0420: 0a 0a 20 20 20 20 23 20 49 6e 69 74 69 61 6c 69  ..    # Initiali
0430: 7a 65 20 74 68 65 20 70 61 72 73 65 72 20 73 74  ze the parser st
0440: 61 74 65 20 66 72 6f 6d 20 74 68 65 20 6f 70 74  ate from the opt
0450: 69 6f 6e 73 2c 20 66 69 6c 6c 20 69 6e 20 64 65  ions, fill in de
0460: 66 61 75 6c 74 0a 20 20 20 20 23 20 76 61 6c 75  fault.    # valu
0470: 65 73 2c 20 61 6e 64 20 68 61 6e 64 6c 65 20 74  es, and handle t
0480: 68 65 20 69 6e 70 75 74 20 61 63 63 6f 72 64 69  he input accordi
0490: 6e 67 20 74 68 65 20 73 70 65 63 69 66 69 65 64  ng the specified
04a0: 20 6d 6f 64 65 2e 0a 0a 20 20 20 20 73 65 74 20   mode...    set 
04b0: 74 6f 6b 65 6e 20 62 69 62 74 65 78 5b 69 6e 63  token bibtex[inc
04c0: 72 20 69 64 5d 0a 20 20 20 20 66 6f 72 65 61 63  r id].    foreac
04d0: 68 20 7b 6b 20 76 7d 20 5b 61 72 72 61 79 20 67  h {k v} [array g
04e0: 65 74 20 73 74 61 74 65 5d 20 7b 0a 09 73 65 74  et state] {..set
04f0: 20 64 61 74 61 28 24 74 6f 6b 65 6e 2c 24 6b 29   data($token,$k)
0500: 20 24 76 0a 20 20 20 20 7d 0a 0a 20 20 20 20 69   $v.    }..    i
0510: 66 20 7b 24 73 74 61 74 65 28 73 74 72 65 61 6d  f {$state(stream
0520: 29 7d 20 7b 0a 09 23 20 54 65 78 74 20 6e 6f 74  )} {..# Text not
0530: 20 69 6e 20 6d 65 6d 6f 72 79 0a 09 69 66 20 7b   in memory..if {
0540: 21 24 73 74 61 74 65 28 62 67 29 7d 20 7b 0a 09  !$state(bg)} {..
0550: 20 20 20 20 23 20 54 65 78 74 20 66 72 6f 6d 20      # Text from 
0560: 61 20 63 68 61 6e 6e 65 6c 2c 20 6e 6f 20 61 73  a channel, no as
0570: 79 6e 63 20 70 72 6f 63 65 73 73 69 6e 67 2e 20  ync processing. 
0580: 57 65 20 72 65 61 64 20 65 76 65 72 79 74 68 69  We read everythi
0590: 6e 67 0a 09 20 20 20 20 23 20 69 6e 74 6f 20 6d  ng..    # into m
05a0: 65 6d 6f 72 79 20 61 6e 64 20 74 68 65 20 68 61  emory and the ha
05b0: 6e 64 6c 65 20 69 74 20 61 73 20 62 65 66 6f 72  ndle it as befor
05c0: 65 2e 0a 0a 09 20 20 20 20 73 65 74 20 62 6c 6f  e....    set blo
05d0: 63 6b 6d 6f 64 65 20 5b 66 63 6f 6e 66 69 67 75  ckmode [fconfigu
05e0: 72 65 20 24 73 74 61 74 65 28 2d 63 68 61 6e 6e  re $state(-chann
05f0: 65 6c 29 20 2d 62 6c 6f 63 6b 69 6e 67 5d 0a 09  el) -blocking]..
0600: 20 20 20 20 66 63 6f 6e 66 69 67 75 72 65 20 24      fconfigure $
0610: 73 74 61 74 65 28 2d 63 68 61 6e 6e 65 6c 29 20  state(-channel) 
0620: 2d 62 6c 6f 63 6b 69 6e 67 20 31 0a 09 20 20 20  -blocking 1..   
0630: 20 73 65 74 20 64 61 74 61 28 24 74 6f 6b 65 6e   set data($token
0640: 2c 62 75 66 66 65 72 29 20 5b 72 65 61 64 20 24  ,buffer) [read $
0650: 73 74 61 74 65 28 2d 63 68 61 6e 6e 65 6c 29 5d  state(-channel)]
0660: 0a 09 20 20 20 20 66 63 6f 6e 66 69 67 75 72 65  ..    fconfigure
0670: 20 24 73 74 61 74 65 28 2d 63 68 61 6e 6e 65 6c   $state(-channel
0680: 29 20 2d 62 6c 6f 63 6b 69 6e 67 20 24 62 6c 6f  ) -blocking $blo
0690: 63 6b 6d 6f 64 65 0a 0a 09 20 20 20 20 23 20 54  ckmode...    # T
06a0: 65 6c 6c 20 75 70 63 6f 6d 69 6e 67 20 70 72 6f  ell upcoming pro
06b0: 63 65 73 73 69 6e 67 20 74 68 61 74 20 74 68 65  cessing that the
06c0: 20 74 65 78 74 20 69 73 20 69 6e 20 6d 65 6d 6f   text is in memo
06d0: 72 79 2e 0a 09 20 20 20 20 73 65 74 20 73 74 61  ry...    set sta
06e0: 74 65 28 73 74 72 65 61 6d 29 20 30 0a 09 7d 20  te(stream) 0..} 
06f0: 65 6c 73 65 20 7b 0a 09 20 20 20 20 23 20 54 65  else {..    # Te
0700: 78 74 20 66 72 6f 6d 20 61 20 63 68 61 6e 6e 65  xt from a channe
0710: 6c 2c 20 61 6e 64 20 70 72 6f 63 65 73 73 69 6e  l, and processin
0720: 67 20 69 73 20 61 73 79 6e 63 2e 20 43 72 65 61  g is async. Crea
0730: 74 65 20 61 6e 0a 09 20 20 20 20 23 20 65 76 65  te an..    # eve
0740: 6e 74 20 68 61 6e 64 6c 65 72 20 66 6f 72 20 74  nt handler for t
0750: 68 65 20 69 6e 63 6f 6d 69 6e 67 20 64 61 74 61  he incoming data
0760: 2e 0a 0a 09 20 20 20 20 73 65 74 20 64 61 74 61  ....    set data
0770: 28 24 74 6f 6b 65 6e 2c 64 6f 6e 65 29 20 30 0a  ($token,done) 0.
0780: 09 20 20 20 20 66 69 6c 65 65 76 65 6e 74 20 24  .    fileevent $
0790: 73 74 61 74 65 28 2d 63 68 61 6e 6e 65 6c 29 20  state(-channel) 
07a0: 72 65 61 64 61 62 6c 65 20 5c 0a 09 09 20 20 20  readable \...   
07b0: 20 5b 6c 69 73 74 20 3a 3a 62 69 62 74 65 78 3a   [list ::bibtex:
07c0: 3a 52 65 61 64 43 68 61 6e 20 24 74 6f 6b 65 6e  :ReadChan $token
07d0: 5d 0a 0a 09 20 20 20 20 23 20 49 6e 69 74 69 61  ]...    # Initia
07e0: 6c 69 7a 65 20 74 68 65 20 70 61 72 73 65 72 20  lize the parser 
07f0: 69 6e 74 65 72 6e 61 6c 20 72 65 73 75 6c 74 20  internal result 
0800: 62 75 66 66 65 72 20 69 66 20 77 65 20 75 73 65  buffer if we use
0810: 20 70 6c 61 69 6e 0a 09 20 20 20 20 23 20 2d 63   plain..    # -c
0820: 6f 6d 6d 61 6e 64 2c 20 61 6e 64 20 6e 6f 74 20  ommand, and not 
0830: 74 68 65 20 53 41 58 20 61 70 69 2e 0a 09 20 20  the SAX api...  
0840: 20 20 69 66 20 7b 21 24 73 74 61 74 65 28 73 61    if {!$state(sa
0850: 78 29 7d 20 7b 0a 09 09 73 65 74 20 64 61 74 61  x)} {...set data
0860: 28 24 74 6f 6b 65 6e 2c 72 65 73 75 6c 74 29 20  ($token,result) 
0870: 7b 7d 0a 09 20 20 20 20 7d 0a 09 7d 0a 20 20 20  {}..    }..}.   
0880: 20 7d 0a 0a 20 20 20 20 23 20 49 6e 69 74 69 61   }..    # Initia
0890: 6c 69 7a 65 20 74 68 65 20 73 74 72 69 6e 67 20  lize the string 
08a0: 6d 61 70 70 69 6e 67 73 20 28 6e 6f 6e 65 20 6b  mappings (none k
08b0: 6e 6f 77 6e 29 2c 20 61 6e 64 20 74 68 65 20 72  nown), and the r
08c0: 65 73 75 6c 74 0a 20 20 20 20 23 20 61 63 63 75  esult.    # accu
08d0: 6d 75 6c 61 74 6f 72 2e 0a 20 20 20 20 73 65 74  mulator..    set
08e0: 20 64 61 74 61 28 24 74 6f 6b 65 6e 2c 73 74 72   data($token,str
08f0: 69 6e 67 73 29 20 7b 7d 0a 20 20 20 20 73 65 74  ings) {}.    set
0900: 20 64 61 74 61 28 24 74 6f 6b 65 6e 2c 72 65 73   data($token,res
0910: 75 6c 74 29 20 20 7b 7d 0a 0a 20 20 20 20 69 66  ult)  {}..    if
0920: 20 7b 21 24 73 74 61 74 65 28 73 74 72 65 61 6d   {!$state(stream
0930: 29 7d 20 7b 0a 09 50 61 72 73 65 52 65 63 6f 72  )} {..ParseRecor
0940: 64 73 20 24 74 6f 6b 65 6e 20 31 0a 09 69 66 20  ds $token 1..if 
0950: 7b 24 73 74 61 74 65 28 73 61 78 29 7d 20 7b 0a  {$state(sax)} {.
0960: 09 20 20 20 20 73 65 74 20 72 65 73 75 6c 74 20  .    set result 
0970: 24 74 6f 6b 65 6e 0a 09 7d 20 65 6c 73 65 20 7b  $token..} else {
0980: 0a 09 20 20 20 20 73 65 74 20 72 65 73 75 6c 74  ..    set result
0990: 20 24 64 61 74 61 28 24 74 6f 6b 65 6e 2c 72 65   $data($token,re
09a0: 73 75 6c 74 29 0a 09 20 20 20 20 64 65 73 74 72  sult)..    destr
09b0: 6f 79 20 24 74 6f 6b 65 6e 0a 09 7d 0a 09 72 65  oy $token..}..re
09c0: 74 75 72 6e 20 24 72 65 73 75 6c 74 0a 20 20 20  turn $result.   
09d0: 20 7d 0a 0a 20 20 20 20 23 20 41 73 73 65 72 74   }..    # Assert
09e0: 3a 20 50 72 6f 63 65 73 73 69 6e 67 20 69 73 20  : Processing is 
09f0: 69 6e 20 62 61 63 6b 67 72 6f 75 6e 64 2e 0a 20  in background.. 
0a00: 20 20 20 72 65 74 75 72 6e 20 24 74 6f 6b 65 6e     return $token
0a10: 0a 7d 0a 0a 23 20 43 6c 65 61 6e 75 70 20 61 20  .}..# Cleanup a 
0a20: 70 61 72 73 65 72 2c 20 63 61 6e 63 65 6c 6c 69  parser, cancelli
0a30: 6e 67 20 61 6e 79 20 63 61 6c 6c 62 61 63 6b 73  ng any callbacks
0a40: 20 65 74 63 2e 0a 0a 70 72 6f 63 20 3a 3a 62 69   etc...proc ::bi
0a50: 62 74 65 78 3a 3a 64 65 73 74 72 6f 79 20 7b 74  btex::destroy {t
0a60: 6f 6b 65 6e 7d 20 7b 0a 20 20 20 20 76 61 72 69  oken} {.    vari
0a70: 61 62 6c 65 20 64 61 74 61 0a 0a 20 20 20 20 69  able data..    i
0a80: 66 20 7b 21 5b 69 6e 66 6f 20 65 78 69 73 74 73  f {![info exists
0a90: 20 64 61 74 61 28 24 74 6f 6b 65 6e 2c 73 74 72   data($token,str
0aa0: 65 61 6d 29 5d 7d 20 7b 0a 09 72 65 74 75 72 6e  eam)]} {..return
0ab0: 20 2d 63 6f 64 65 20 65 72 72 6f 72 20 22 49 6c   -code error "Il
0ac0: 6c 65 67 61 6c 20 62 69 62 74 65 78 20 70 61 72  legal bibtex par
0ad0: 73 65 72 20 5c 22 24 74 6f 6b 65 6e 5c 22 22 0a  ser \"$token\"".
0ae0: 20 20 20 20 7d 0a 20 20 20 20 69 66 20 7b 24 64      }.    if {$d
0af0: 61 74 61 28 24 74 6f 6b 65 6e 2c 73 74 72 65 61  ata($token,strea
0b00: 6d 29 7d 20 7b 0a 09 66 69 6c 65 65 76 65 6e 74  m)} {..fileevent
0b10: 20 24 64 61 74 61 28 24 74 6f 6b 65 6e 2c 2d 63   $data($token,-c
0b20: 68 61 6e 6e 65 6c 29 20 72 65 61 64 61 62 6c 65  hannel) readable
0b30: 20 7b 7d 0a 20 20 20 20 7d 0a 0a 20 20 20 20 61   {}.    }..    a
0b40: 72 72 61 79 20 75 6e 73 65 74 20 64 61 74 61 20  rray unset data 
0b50: 24 74 6f 6b 65 6e 2c 2a 0a 20 20 20 20 72 65 74  $token,*.    ret
0b60: 75 72 6e 0a 7d 0a 0a 0a 70 72 6f 63 20 3a 3a 62  urn.}...proc ::b
0b70: 69 62 74 65 78 3a 3a 77 61 69 74 20 7b 74 6f 6b  ibtex::wait {tok
0b80: 65 6e 7d 20 7b 0a 20 20 20 20 76 61 72 69 61 62  en} {.    variab
0b90: 6c 65 20 64 61 74 61 0a 0a 20 20 20 20 69 66 20  le data..    if 
0ba0: 7b 21 5b 69 6e 66 6f 20 65 78 69 73 74 73 20 64  {![info exists d
0bb0: 61 74 61 28 24 74 6f 6b 65 6e 2c 73 74 72 65 61  ata($token,strea
0bc0: 6d 29 5d 7d 20 7b 0a 09 72 65 74 75 72 6e 20 2d  m)]} {..return -
0bd0: 63 6f 64 65 20 65 72 72 6f 72 20 22 49 6c 6c 65  code error "Ille
0be0: 67 61 6c 20 62 69 62 74 65 78 20 70 61 72 73 65  gal bibtex parse
0bf0: 72 20 5c 22 24 74 6f 6b 65 6e 5c 22 22 0a 20 20  r \"$token\"".  
0c00: 20 20 7d 0a 20 20 20 20 76 77 61 69 74 20 3a 3a    }.    vwait ::
0c10: 62 69 62 74 65 78 3a 3a 64 61 74 61 28 24 74 6f  bibtex::data($to
0c20: 6b 65 6e 2c 64 6f 6e 65 29 0a 20 20 20 20 72 65  ken,done).    re
0c30: 74 75 72 6e 0a 7d 0a 0a 23 20 62 69 62 74 65 78  turn.}..# bibtex
0c40: 3a 3a 61 64 64 53 74 72 69 6e 67 73 20 2d 2d 0a  ::addStrings --.
0c50: 23 0a 23 09 41 64 64 20 73 74 72 69 6e 67 73 20  #.#.Add strings 
0c60: 74 6f 20 74 68 65 20 6d 61 70 20 66 6f 72 20 61  to the map for a
0c70: 20 70 61 72 74 69 63 75 6c 61 72 20 70 61 72 73   particular pars
0c80: 65 72 2e 20 41 6c 6c 20 73 74 72 69 6e 67 73 20  er. All strings 
0c90: 61 72 65 0a 23 09 65 78 70 61 6e 64 65 64 20 61  are.#.expanded a
0ca0: 74 20 70 61 72 73 65 20 74 69 6d 65 2e 0a 0a 70  t parse time...p
0cb0: 72 6f 63 20 3a 3a 62 69 62 74 65 78 3a 3a 61 64  roc ::bibtex::ad
0cc0: 64 53 74 72 69 6e 67 73 20 7b 74 6f 6b 65 6e 20  dStrings {token 
0cd0: 73 74 72 69 6e 67 73 7d 20 7b 0a 20 20 20 20 76  strings} {.    v
0ce0: 61 72 69 61 62 6c 65 20 64 61 74 61 0a 20 20 20  ariable data.   
0cf0: 20 65 76 61 6c 20 5b 6c 69 6e 73 65 72 74 20 24   eval [linsert $
0d00: 73 74 72 69 6e 67 73 20 30 20 6c 61 70 70 65 6e  strings 0 lappen
0d10: 64 20 64 61 74 61 28 24 74 6f 6b 65 6e 2c 73 74  d data($token,st
0d20: 72 69 6e 67 73 29 5d 0a 20 20 20 20 72 65 74 75  rings)].    retu
0d30: 72 6e 0a 7d 0a 0a 23 20 23 23 23 20 23 23 23 20  rn.}..# ### ### 
0d40: 23 23 23 20 23 23 23 23 23 23 23 23 23 20 23 23  ### ######### ##
0d50: 23 23 23 23 23 23 23 20 23 23 23 23 23 23 23 23  ####### ########
0d60: 23 0a 23 23 20 49 6d 70 6c 65 6d 65 6e 74 61 74  #.## Implementat
0d70: 69 6f 6e 3a 20 50 72 69 76 61 74 65 20 75 74 69  ion: Private uti
0d80: 6c 69 74 79 20 72 6f 75 74 69 6e 65 73 0a 0a 70  lity routines..p
0d90: 72 6f 63 20 3a 3a 62 69 62 74 65 78 3a 3a 41 64  roc ::bibtex::Ad
0da0: 64 52 65 63 6f 72 64 20 7b 74 6f 6b 65 6e 20 74  dRecord {token t
0db0: 79 70 65 20 6b 65 79 20 72 65 63 64 61 74 61 7d  ype key recdata}
0dc0: 20 7b 0a 20 20 20 20 76 61 72 69 61 62 6c 65 20   {.    variable 
0dd0: 64 61 74 61 0a 20 20 20 20 6c 61 70 70 65 6e 64  data.    lappend
0de0: 20 20 64 61 74 61 28 24 74 6f 6b 65 6e 2c 72 65    data($token,re
0df0: 73 75 6c 74 29 20 5b 6c 69 73 74 20 24 74 79 70  sult) [list $typ
0e00: 65 20 24 6b 65 79 20 24 72 65 63 64 61 74 61 5d  e $key $recdata]
0e10: 0a 20 20 20 20 72 65 74 75 72 6e 0a 7d 0a 0a 70  .    return.}..p
0e20: 72 6f 63 20 3a 3a 62 69 62 74 65 78 3a 3a 47 65  roc ::bibtex::Ge
0e30: 74 4f 70 74 69 6f 6e 73 20 7b 61 72 67 76 20 73  tOptions {argv s
0e40: 74 61 74 65 76 61 72 7d 20 7b 0a 20 20 20 20 75  tatevar} {.    u
0e50: 70 76 61 72 20 31 20 24 73 74 61 74 65 76 61 72  pvar 1 $statevar
0e60: 20 73 74 61 74 65 0a 0a 20 20 20 20 23 20 42 61   state..    # Ba
0e70: 73 69 63 20 70 72 6f 63 65 73 73 69 6e 67 20 6f  sic processing o
0e80: 66 20 74 68 65 20 61 72 67 75 6d 65 6e 74 20 6c  f the argument l
0e90: 69 73 74 0a 20 20 20 20 23 20 61 6e 64 20 74 68  ist.    # and th
0ea0: 65 20 6f 70 74 69 6f 6e 73 20 66 6f 75 6e 64 20  e options found 
0eb0: 74 68 65 72 65 69 6e 2e 0a 0a 20 20 20 20 73 65  therein...    se
0ec0: 74 20 6f 70 74 73 20 5b 6c 72 61 6e 67 65 20 5b  t opts [lrange [
0ed0: 3a 3a 63 6d 64 6c 69 6e 65 3a 3a 47 65 74 4f 70  ::cmdline::GetOp
0ee0: 74 69 6f 6e 44 65 66 61 75 6c 74 73 20 7b 0a 09  tionDefaults {..
0ef0: 7b 63 6f 6d 6d 61 6e 64 2e 61 72 67 20 20 20 20  {command.arg    
0f00: 20 20 20 20 20 20 20 20 20 20 7b 7d 7d 0a 09 7b            {}}..{
0f10: 63 68 61 6e 6e 65 6c 2e 61 72 67 20 20 20 20 20  channel.arg     
0f20: 20 20 20 20 20 20 20 20 20 7b 7d 7d 0a 09 7b 72           {}}..{r
0f30: 65 63 6f 72 64 63 6f 6d 6d 61 6e 64 2e 61 72 67  ecordcommand.arg
0f40: 20 20 20 20 20 20 20 20 7b 7d 7d 0a 09 7b 70 72          {}}..{pr
0f50: 65 61 6d 62 6c 65 63 6f 6d 6d 61 6e 64 2e 61 72  eamblecommand.ar
0f60: 67 20 20 20 20 20 20 7b 7d 7d 0a 09 7b 73 74 72  g      {}}..{str
0f70: 69 6e 67 63 6f 6d 6d 61 6e 64 2e 61 72 67 20 20  ingcommand.arg  
0f80: 20 20 20 20 20 20 7b 7d 7d 0a 09 7b 63 6f 6d 6d        {}}..{comm
0f90: 65 6e 74 63 6f 6d 6d 61 6e 64 2e 61 72 67 20 20  entcommand.arg  
0fa0: 20 20 20 20 20 7b 7d 7d 0a 09 7b 70 72 6f 67 72       {}}..{progr
0fb0: 65 73 73 63 6f 6d 6d 61 6e 64 2e 61 72 67 20 20  esscommand.arg  
0fc0: 20 20 20 20 7b 7d 7d 0a 09 7b 63 61 73 65 73 65      {}}..{casese
0fd0: 6e 73 69 74 69 76 65 73 74 72 69 6e 67 73 2e 61  nsitivestrings.a
0fe0: 72 67 20 7b 7d 7d 0a 20 20 20 20 7d 20 72 65 73  rg {}}.    } res
0ff0: 75 6c 74 5d 20 32 20 65 6e 64 5d 20 3b 23 20 52  ult] 2 end] ;# R
1000: 65 6d 6f 76 65 20 3f 20 61 6e 64 20 68 65 6c 70  emove ? and help
1010: 2e 0a 0a 20 20 20 20 73 65 74 20 61 72 67 63 20  ...    set argc 
1020: 5b 6c 6c 65 6e 67 74 68 20 24 61 72 67 76 5d 0a  [llength $argv].
1030: 20 20 20 20 77 68 69 6c 65 20 7b 5b 73 65 74 20      while {[set 
1040: 65 72 72 20 5b 3a 3a 63 6d 64 6c 69 6e 65 3a 3a  err [::cmdline::
1050: 67 65 74 6f 70 74 20 61 72 67 76 20 24 6f 70 74  getopt argv $opt
1060: 73 20 6f 70 74 20 61 72 67 5d 5d 7d 20 7b 0a 09  s opt arg]]} {..
1070: 69 66 20 7b 24 65 72 72 20 3c 20 30 7d 20 7b 0a  if {$err < 0} {.
1080: 09 20 20 20 20 73 65 74 20 6f 6c 69 73 74 20 22  .    set olist "
1090: 22 0a 09 20 20 20 20 66 6f 72 65 61 63 68 20 6f  "..    foreach o
10a0: 20 5b 6c 73 6f 72 74 20 24 6f 70 74 73 5d 20 7b   [lsort $opts] {
10b0: 0a 09 09 69 66 20 7b 5b 73 74 72 69 6e 67 20 6d  ...if {[string m
10c0: 61 74 63 68 20 2a 2e 61 72 67 20 24 6f 5d 7d 20  atch *.arg $o]} 
10d0: 7b 0a 09 09 20 20 20 20 73 65 74 20 6f 20 5b 73  {...    set o [s
10e0: 74 72 69 6e 67 20 72 61 6e 67 65 20 24 6f 20 30  tring range $o 0
10f0: 20 65 6e 64 2d 34 5d 0a 09 09 7d 0a 09 09 6c 61   end-4]...}...la
1100: 70 70 65 6e 64 20 6f 6c 69 73 74 20 2d 24 6f 0a  ppend olist -$o.
1110: 09 20 20 20 20 7d 0a 09 20 20 20 20 72 65 74 75  .    }..    retu
1120: 72 6e 20 2d 63 6f 64 65 20 65 72 72 6f 72 20 22  rn -code error "
1130: 62 61 64 20 6f 70 74 69 6f 6e 20 5c 22 24 6f 70  bad option \"$op
1140: 74 5c 22 2c 5c 0a 09 09 20 20 20 20 73 68 6f 75  t\",\...    shou
1150: 6c 64 20 62 65 20 6f 6e 65 20 6f 66 5c 0a 09 09  ld be one of\...
1160: 20 20 20 20 5b 6c 69 6e 73 65 72 74 20 5b 6a 6f      [linsert [jo
1170: 69 6e 20 24 6f 6c 69 73 74 20 22 2c 20 22 5d 20  in $olist ", "] 
1180: 65 6e 64 2d 31 20 6f 72 5d 22 0a 09 7d 0a 09 73  end-1 or]"..}..s
1190: 65 74 20 73 74 61 74 65 28 2d 24 6f 70 74 29 20  et state(-$opt) 
11a0: 24 61 72 67 0a 20 20 20 20 7d 0a 0a 20 20 20 20  $arg.    }..    
11b0: 23 20 43 68 65 63 6b 20 74 68 65 20 69 6e 66 6f  # Check the info
11c0: 72 6d 61 74 69 6f 6e 20 67 61 69 6e 65 64 20 73  rmation gained s
11d0: 6f 20 66 61 72 0a 20 20 20 20 23 20 66 6f 72 20  o far.    # for 
11e0: 69 6e 63 6f 6e 73 69 73 74 65 6e 63 69 65 73 20  inconsistencies 
11f0: 61 6e 64 2f 6f 72 20 6d 69 73 73 69 6e 67 0a 20  and/or missing. 
1200: 20 20 20 23 20 70 69 65 63 65 73 2e 0a 0a 20 20     # pieces...  
1210: 20 20 73 65 74 20 73 61 78 20 5b 65 78 70 72 20    set sax [expr 
1220: 7b 0a 09 5b 69 6e 66 6f 20 65 78 69 73 74 73 20  {..[info exists 
1230: 73 74 61 74 65 28 2d 72 65 63 6f 72 64 63 6f 6d  state(-recordcom
1240: 6d 61 6e 64 29 5d 20 20 20 7c 7c 0a 09 5b 69 6e  mand)]   ||..[in
1250: 66 6f 20 65 78 69 73 74 73 20 73 74 61 74 65 28  fo exists state(
1260: 2d 70 72 65 61 6d 62 6c 65 63 6f 6d 6d 61 6e 64  -preamblecommand
1270: 29 5d 20 7c 7c 0a 09 5b 69 6e 66 6f 20 65 78 69  )] ||..[info exi
1280: 73 74 73 20 73 74 61 74 65 28 2d 73 74 72 69 6e  sts state(-strin
1290: 67 63 6f 6d 6d 61 6e 64 29 5d 20 20 20 7c 7c 0a  gcommand)]   ||.
12a0: 09 5b 69 6e 66 6f 20 65 78 69 73 74 73 20 73 74  .[info exists st
12b0: 61 74 65 28 2d 63 6f 6d 6d 65 6e 74 63 6f 6d 6d  ate(-commentcomm
12c0: 61 6e 64 29 5d 20 20 7c 7c 0a 09 5b 69 6e 66 6f  and)]  ||..[info
12d0: 20 65 78 69 73 74 73 20 73 74 61 74 65 28 2d 70   exists state(-p
12e0: 72 6f 67 72 65 73 73 63 6f 6d 6d 61 6e 64 29 5d  rogresscommand)]
12f0: 0a 20 20 20 20 7d 5d 20 3b 20 23 20 7b 7d 0a 0a  .    }] ; # {}..
1300: 20 20 20 20 73 65 74 20 62 67 20 5b 69 6e 66 6f      set bg [info
1310: 20 65 78 69 73 74 73 20 73 74 61 74 65 28 2d 63   exists state(-c
1320: 6f 6d 6d 61 6e 64 29 5d 0a 0a 20 20 20 20 69 66  ommand)]..    if
1330: 20 7b 24 73 61 78 20 26 26 20 24 62 67 7d 20 7b   {$sax && $bg} {
1340: 0a 09 23 20 53 61 78 20 63 61 6c 6c 62 61 63 6b  ..# Sax callback
1350: 73 20 61 6e 64 20 63 68 61 6e 6e 65 6c 20 63 6f  s and channel co
1360: 6d 70 6c 65 74 69 6f 6e 20 63 61 6c 6c 62 61 63  mpletion callbac
1370: 6b 20 65 78 63 6c 75 64 65 20 65 61 63 68 0a 09  k exclude each..
1380: 23 20 6f 74 68 65 72 2e 0a 09 72 65 74 75 72 6e  # other...return
1390: 20 2d 63 6f 64 65 20 65 72 72 6f 72 20 22 54 68   -code error "Th
13a0: 65 20 6f 70 74 69 6f 6e 73 20 2d 63 6f 6d 6d 61  e options -comma
13b0: 6e 64 20 61 6e 64 20 2d 54 59 50 45 63 6f 6d 6d  nd and -TYPEcomm
13c0: 61 6e 64 20 65 78 63 6c 75 64 65 20 65 61 63 68  and exclude each
13d0: 20 6f 74 68 65 72 22 0a 20 20 20 20 7d 0a 0a 20   other".    }.. 
13e0: 20 20 20 73 65 74 20 73 74 72 65 61 6d 20 5b 69     set stream [i
13f0: 6e 66 6f 20 65 78 69 73 74 73 20 73 74 61 74 65  nfo exists state
1400: 28 2d 63 68 61 6e 6e 65 6c 29 5d 0a 0a 20 20 20  (-channel)]..   
1410: 20 69 66 20 7b 24 73 74 72 65 61 6d 7d 20 7b 0a   if {$stream} {.
1420: 09 23 20 43 68 61 6e 6e 65 6c 20 69 73 20 70 72  .# Channel is pr
1430: 65 73 65 6e 74 2c 20 61 20 74 65 78 74 20 69 73  esent, a text is
1440: 20 6e 6f 74 20 61 6c 6c 6f 77 65 64 2e 0a 09 69   not allowed...i
1450: 66 20 7b 5b 6c 6c 65 6e 67 74 68 20 24 61 72 67  f {[llength $arg
1460: 76 5d 7d 20 7b 0a 09 20 20 20 20 72 65 74 75 72  v]} {..    retur
1470: 6e 20 2d 63 6f 64 65 20 65 72 72 6f 72 20 22 4f  n -code error "O
1480: 70 74 69 6f 6e 20 2d 63 68 61 6e 6e 65 6c 20 61  ption -channel a
1490: 6e 64 20 74 65 78 74 20 65 78 63 6c 75 64 65 20  nd text exclude 
14a0: 65 61 63 68 20 6f 74 68 65 72 22 0a 09 7d 0a 0a  each other"..}..
14b0: 09 23 20 54 68 65 20 63 68 61 6e 6e 65 6c 20 68  .# The channel h
14c0: 61 73 20 74 6f 20 65 78 69 73 74 20 61 73 20 77  as to exist as w
14d0: 65 6c 6c 2e 0a 09 69 66 20 7b 5b 6c 73 65 61 72  ell...if {[lsear
14e0: 63 68 20 2d 65 78 61 63 74 20 5b 66 69 6c 65 20  ch -exact [file 
14f0: 63 68 61 6e 6e 65 6c 73 5d 20 24 73 74 61 74 65  channels] $state
1500: 28 2d 63 68 61 6e 6e 65 6c 29 5d 20 3c 20 30 7d  (-channel)] < 0}
1510: 20 7b 0a 09 20 20 20 20 72 65 74 75 72 6e 20 2d   {..    return -
1520: 63 6f 64 65 20 65 72 72 6f 72 20 22 49 6c 6c 65  code error "Ille
1530: 67 61 6c 20 63 68 61 6e 6e 65 6c 20 68 61 6e 64  gal channel hand
1540: 6c 65 20 5c 22 24 73 74 61 74 65 28 2d 63 68 61  le \"$state(-cha
1550: 6e 6e 65 6c 29 5c 22 22 0a 09 7d 0a 20 20 20 20  nnel)\""..}.    
1560: 7d 20 65 6c 73 65 20 7b 0a 09 23 20 43 68 61 6e  } else {..# Chan
1570: 6e 65 6c 20 69 73 20 6e 6f 74 20 70 72 65 73 65  nel is not prese
1580: 6e 74 2c 20 77 65 20 68 61 76 65 20 74 6f 20 68  nt, we have to h
1590: 61 76 65 20 61 20 74 65 78 74 2c 20 61 6e 64 20  ave a text, and 
15a0: 6f 6e 6c 79 0a 09 23 20 65 78 61 63 74 6c 79 20  only..# exactly 
15b0: 6f 6e 65 2e 20 41 6e 64 20 61 20 67 65 6e 65 72  one. And a gener
15c0: 61 6c 20 2d 63 6f 6d 6d 61 6e 64 20 63 61 6c 6c  al -command call
15d0: 62 61 63 6b 20 69 73 20 6e 6f 74 20 61 6c 6c 6f  back is not allo
15e0: 77 65 64 2e 0a 0a 09 69 66 20 7b 21 5b 6c 6c 65  wed....if {![lle
15f0: 6e 67 74 68 20 24 61 72 67 76 5d 7d 20 7b 0a 09  ngth $argv]} {..
1600: 20 20 20 20 72 65 74 75 72 6e 20 2d 63 6f 64 65      return -code
1610: 20 65 72 72 6f 72 20 22 4e 65 69 74 68 65 72 20   error "Neither 
1620: 2d 63 68 61 6e 6e 65 6c 20 6e 6f 72 20 74 65 78  -channel nor tex
1630: 74 20 73 70 65 63 69 66 69 65 64 22 0a 09 7d 20  t specified"..} 
1640: 65 6c 73 65 69 66 20 7b 5b 6c 6c 65 6e 67 74 68  elseif {[llength
1650: 20 24 61 72 67 76 5d 20 3e 20 31 7d 20 7b 0a 09   $argv] > 1} {..
1660: 20 20 20 20 72 65 74 75 72 6e 20 2d 63 6f 64 65      return -code
1670: 20 65 72 72 6f 72 20 22 77 72 6f 6e 67 20 23 20   error "wrong # 
1680: 61 72 67 73 3a 20 5b 6c 69 6e 64 65 78 20 5b 69  args: [lindex [i
1690: 6e 66 6f 20 6c 65 76 65 6c 20 31 5d 20 30 5d 20  nfo level 1] 0] 
16a0: 3f 6f 70 74 69 6f 6e 73 3f 20 3f 62 69 62 74 65  ?options? ?bibte
16b0: 78 3f 22 0a 09 7d 0a 0a 09 23 20 43 68 61 6e 6e  x?"..}...# Chann
16c0: 65 6c 20 63 6f 6d 70 6c 65 74 69 6f 6e 20 63 61  el completion ca
16d0: 6c 6c 62 61 63 6b 20 69 73 20 6e 6f 74 20 61 6c  llback is not al
16e0: 6c 6f 77 65 64 20 69 66 20 77 65 20 61 72 65 20  lowed if we are 
16f0: 6e 6f 74 0a 09 23 20 72 65 61 64 69 6e 67 20 66  not..# reading f
1700: 72 6f 6d 20 61 20 63 68 61 6e 6e 65 6c 2e 0a 0a  rom a channel...
1710: 09 69 66 20 7b 24 62 67 7d 20 7b 0a 09 20 20 20  .if {$bg} {..   
1720: 20 72 65 74 75 72 6e 20 2d 63 6f 64 65 20 65 72   return -code er
1730: 72 6f 72 20 22 4f 70 74 69 6f 6e 20 2d 63 6f 6d  ror "Option -com
1740: 6d 61 6e 64 20 61 6e 64 20 74 65 78 74 20 65 78  mand and text ex
1750: 63 6c 75 64 65 20 65 61 63 68 20 6f 74 68 65 72  clude each other
1760: 22 0a 09 7d 0a 0a 09 73 65 74 20 73 74 61 74 65  "..}...set state
1770: 28 62 75 66 66 65 72 29 20 5b 6c 69 6e 64 65 78  (buffer) [lindex
1780: 20 24 61 72 67 76 20 30 5d 0a 20 20 20 20 7d 0a   $argv 0].    }.
1790: 0a 20 20 20 20 73 65 74 20 73 74 61 74 65 28 73  .    set state(s
17a0: 74 72 65 61 6d 29 20 24 73 74 72 65 61 6d 0a 20  tream) $stream. 
17b0: 20 20 20 73 65 74 20 73 74 61 74 65 28 73 61 78     set state(sax
17c0: 29 20 20 20 20 24 73 61 78 0a 20 20 20 20 73 65  )    $sax.    se
17d0: 74 20 73 74 61 74 65 28 62 67 29 20 20 20 20 20  t state(bg)     
17e0: 5b 65 78 70 72 20 7b 24 73 61 78 20 7c 7c 20 24  [expr {$sax || $
17f0: 62 67 7d 5d 0a 0a 20 20 20 20 69 66 20 7b 21 5b  bg}]..    if {![
1800: 69 6e 66 6f 20 65 78 69 73 74 73 20 73 74 61 74  info exists stat
1810: 65 28 2d 73 74 72 69 6e 67 63 6f 6d 6d 61 6e 64  e(-stringcommand
1820: 29 5d 7d 20 7b 0a 09 73 65 74 20 73 74 61 74 65  )]} {..set state
1830: 28 2d 73 74 72 69 6e 67 63 6f 6d 6d 61 6e 64 29  (-stringcommand)
1840: 20 5b 6c 69 73 74 20 3a 3a 62 69 62 74 65 78 3a   [list ::bibtex:
1850: 3a 61 64 64 53 74 72 69 6e 67 73 5d 0a 20 20 20  :addStrings].   
1860: 20 7d 0a 20 20 20 20 69 66 20 7b 21 5b 69 6e 66   }.    if {![inf
1870: 6f 20 65 78 69 73 74 73 20 73 74 61 74 65 28 2d  o exists state(-
1880: 72 65 63 6f 72 64 63 6f 6d 6d 61 6e 64 29 5d 20  recordcommand)] 
1890: 26 26 20 28 21 24 73 61 78 29 7d 20 7b 0a 09 73  && (!$sax)} {..s
18a0: 65 74 20 73 74 61 74 65 28 2d 72 65 63 6f 72 64  et state(-record
18b0: 63 6f 6d 6d 61 6e 64 29 20 5b 6c 69 73 74 20 3a  command) [list :
18c0: 3a 62 69 62 74 65 78 3a 3a 41 64 64 52 65 63 6f  :bibtex::AddReco
18d0: 72 64 5d 0a 20 20 20 20 7d 0a 20 20 20 20 69 66  rd].    }.    if
18e0: 20 7b 5b 69 6e 66 6f 20 65 78 69 73 74 73 20 73   {[info exists s
18f0: 74 61 74 65 28 2d 63 61 73 65 73 65 6e 73 69 74  tate(-casesensit
1900: 69 76 65 73 74 72 69 6e 67 73 29 5d 20 26 26 0a  ivestrings)] &&.
1910: 09 24 73 74 61 74 65 28 2d 63 61 73 65 73 65 6e  .$state(-casesen
1920: 73 69 74 69 76 65 73 74 72 69 6e 67 73 29 0a 20  sitivestrings). 
1930: 20 20 20 7d 20 7b 0a 09 73 65 74 20 73 74 61 74     } {..set stat
1940: 65 28 63 61 73 65 73 65 6e 73 69 74 69 76 65 73  e(casesensitives
1950: 74 72 69 6e 67 73 29 20 31 0a 20 20 20 20 7d 20  trings) 1.    } 
1960: 65 6c 73 65 20 7b 0a 09 73 65 74 20 73 74 61 74  else {..set stat
1970: 65 28 63 61 73 65 73 65 6e 73 69 74 69 76 65 73  e(casesensitives
1980: 74 72 69 6e 67 73 29 20 30 0a 20 20 20 20 7d 0a  trings) 0.    }.
1990: 20 20 20 20 72 65 74 75 72 6e 0a 7d 0a 0a 70 72      return.}..pr
19a0: 6f 63 20 3a 3a 62 69 62 74 65 78 3a 3a 43 61 6c  oc ::bibtex::Cal
19b0: 6c 62 61 63 6b 20 7b 74 6f 6b 65 6e 20 74 79 70  lback {token typ
19c0: 65 20 61 72 67 73 7d 20 7b 0a 20 20 20 20 76 61  e args} {.    va
19d0: 72 69 61 62 6c 65 20 64 61 74 61 0a 0a 20 20 20  riable data..   
19e0: 20 23 70 75 74 73 20 73 74 64 6f 75 74 20 22 43   #puts stdout "C
19f0: 61 6c 6c 62 61 63 6b 20 28 24 74 6f 6b 65 6e 20  allback ($token 
1a00: 24 74 79 70 65 20 28 24 61 72 67 73 29 29 22 0a  $type ($args))".
1a10: 0a 20 20 20 20 69 66 20 7b 5b 69 6e 66 6f 20 65  .    if {[info e
1a20: 78 69 73 74 73 20 64 61 74 61 28 24 74 6f 6b 65  xists data($toke
1a30: 6e 2c 2d 24 7b 74 79 70 65 7d 63 6f 6d 6d 61 6e  n,-${type}comman
1a40: 64 29 5d 7d 20 7b 0a 09 65 76 61 6c 20 24 64 61  d)]} {..eval $da
1a50: 74 61 28 24 74 6f 6b 65 6e 2c 2d 24 7b 74 79 70  ta($token,-${typ
1a60: 65 7d 63 6f 6d 6d 61 6e 64 29 20 5b 6c 69 6e 73  e}command) [lins
1a70: 65 72 74 20 24 61 72 67 73 20 30 20 24 74 6f 6b  ert $args 0 $tok
1a80: 65 6e 5d 0a 20 20 20 20 7d 0a 20 20 20 20 72 65  en].    }.    re
1a90: 74 75 72 6e 0a 7d 0a 0a 70 72 6f 63 20 3a 3a 62  turn.}..proc ::b
1aa0: 69 62 74 65 78 3a 3a 52 65 61 64 43 68 61 6e 20  ibtex::ReadChan 
1ab0: 7b 74 6f 6b 65 6e 7d 20 7b 0a 20 20 20 20 76 61  {token} {.    va
1ac0: 72 69 61 62 6c 65 20 64 61 74 61 0a 0a 20 20 20  riable data..   
1ad0: 20 23 20 52 65 61 64 20 74 68 65 20 77 61 69 74   # Read the wait
1ae0: 69 6e 67 20 63 68 61 72 61 63 74 65 72 73 20 69  ing characters i
1af0: 6e 74 6f 20 6f 75 72 20 62 75 66 66 65 72 20 61  nto our buffer a
1b00: 6e 64 20 70 72 6f 63 65 73 73 0a 20 20 20 20 23  nd process.    #
1b10: 20 74 68 65 6d 2e 20 54 68 65 20 72 65 63 6f 72   them. The recor
1b20: 64 73 20 61 72 65 20 73 61 76 65 64 20 65 69 74  ds are saved eit
1b30: 68 65 72 20 74 68 72 6f 75 67 68 20 61 20 75 73  her through a us
1b40: 65 72 20 73 75 70 70 6c 69 65 64 0a 20 20 20 20  er supplied.    
1b50: 23 20 72 65 63 6f 72 64 20 63 61 6c 6c 62 61 63  # record callbac
1b60: 6b 2c 20 6f 72 20 74 68 65 20 73 74 61 6e 64 61  k, or the standa
1b70: 72 64 20 63 61 6c 6c 62 61 63 6b 20 66 6f 72 20  rd callback for 
1b80: 6f 75 72 20 6e 6f 6e 2d 73 61 78 0a 20 20 20 20  our non-sax.    
1b90: 23 20 70 72 6f 63 65 73 73 69 6e 67 2e 0a 0a 20  # processing... 
1ba0: 20 20 20 73 65 74 20 20 20 20 63 68 61 6e 20 24     set    chan $
1bb0: 64 61 74 61 28 24 74 6f 6b 65 6e 2c 2d 63 68 61  data($token,-cha
1bc0: 6e 6e 65 6c 29 0a 20 20 20 20 61 70 70 65 6e 64  nnel).    append
1bd0: 20 64 61 74 61 28 24 74 6f 6b 65 6e 2c 62 75 66   data($token,buf
1be0: 66 65 72 29 20 5b 72 65 61 64 20 24 63 68 61 6e  fer) [read $chan
1bf0: 5d 0a 0a 20 20 20 20 69 66 20 7b 5b 65 6f 66 20  ]..    if {[eof 
1c00: 24 63 68 61 6e 5d 7d 20 7b 0a 09 23 20 46 69 6e  $chan]} {..# Fin
1c10: 61 6c 20 70 72 6f 63 65 73 73 69 6e 67 2e 20 49  al processing. I
1c20: 6e 20 6e 6f 6e 2d 53 41 58 20 6d 6f 64 65 20 77  n non-SAX mode w
1c30: 65 20 68 61 76 65 20 74 6f 20 64 65 6c 69 76 65  e have to delive
1c40: 72 20 74 68 65 0a 09 23 20 63 6f 6d 70 6c 65 74  r the..# complet
1c50: 65 64 20 72 65 73 75 6c 74 20 62 65 66 6f 72 65  ed result before
1c60: 20 64 65 73 74 72 6f 79 69 6e 67 20 74 68 65 20   destroying the 
1c70: 70 61 72 73 65 72 2e 0a 0a 09 50 61 72 73 65 52  parser....ParseR
1c80: 65 63 6f 72 64 73 20 24 74 6f 6b 65 6e 20 31 0a  ecords $token 1.
1c90: 09 73 65 74 20 64 61 74 61 28 24 74 6f 6b 65 6e  .set data($token
1ca0: 2c 64 6f 6e 65 29 20 31 0a 09 69 66 20 7b 21 24  ,done) 1..if {!$
1cb0: 64 61 74 61 28 24 74 6f 6b 65 6e 2c 73 61 78 29  data($token,sax)
1cc0: 7d 20 7b 0a 09 20 20 20 20 43 61 6c 6c 62 61 63  } {..    Callbac
1cd0: 6b 20 24 74 6f 6b 65 6e 20 7b 7d 20 24 64 61 74  k $token {} $dat
1ce0: 61 28 24 74 6f 6b 65 6e 2c 72 65 73 75 6c 74 29  a($token,result)
1cf0: 0a 09 7d 0a 09 72 65 74 75 72 6e 0a 20 20 20 20  ..}..return.    
1d00: 7d 0a 0a 20 20 20 20 23 20 50 72 6f 63 65 73 73  }..    # Process
1d10: 69 6e 67 20 6f 66 20 70 61 72 74 69 61 6c 20 64  ing of partial d
1d20: 61 74 61 2e 0a 0a 20 20 20 20 50 61 72 73 65 52  ata...    ParseR
1d30: 65 63 6f 72 64 73 20 24 74 6f 6b 65 6e 20 30 0a  ecords $token 0.
1d40: 20 20 20 20 72 65 74 75 72 6e 0a 7d 0a 0a 70 72      return.}..pr
1d50: 6f 63 20 3a 3a 62 69 62 74 65 78 3a 3a 54 69 64  oc ::bibtex::Tid
1d60: 79 20 7b 73 74 72 7d 20 7b 0a 20 20 20 20 72 65  y {str} {.    re
1d70: 74 75 72 6e 20 5b 73 74 72 69 6e 67 20 74 6f 6c  turn [string tol
1d80: 6f 77 65 72 20 5b 73 74 72 69 6e 67 20 74 72 69  ower [string tri
1d90: 6d 20 24 73 74 72 5d 5d 0a 7d 0a 0a 70 72 6f 63  m $str]].}..proc
1da0: 20 3a 3a 62 69 62 74 65 78 3a 3a 50 61 72 73 65   ::bibtex::Parse
1db0: 52 65 63 6f 72 64 73 20 7b 74 6f 6b 65 6e 20 65  Records {token e
1dc0: 6f 66 7d 20 7b 0a 20 20 20 20 23 20 41 20 72 6f  of} {.    # A ro
1dd0: 75 67 68 20 42 69 62 54 65 58 20 67 72 61 6d 6d  ugh BibTeX gramm
1de0: 61 72 20 28 63 61 73 65 2d 69 6e 73 65 6e 73 69  ar (case-insensi
1df0: 74 69 76 65 29 3a 0a 20 20 20 20 23 0a 20 20 20  tive):.    #.   
1e00: 20 23 20 44 61 74 61 62 61 73 65 20 20 20 20 20   # Database     
1e10: 20 3a 3a 3d 20 28 4a 75 6e 6b 20 27 40 27 20 45   ::= (Junk '@' E
1e20: 6e 74 72 79 29 2a 0a 20 20 20 20 23 20 4a 75 6e  ntry)*.    # Jun
1e30: 6b 20 20 20 20 20 20 20 20 20 20 3a 3a 3d 20 2e  k          ::= .
1e40: 2a 3f 0a 20 20 20 20 23 20 45 6e 74 72 79 20 20  *?.    # Entry  
1e50: 20 20 20 20 20 20 20 3a 3a 3d 20 52 65 63 6f 72         ::= Recor
1e60: 64 0a 20 20 20 20 23 20 20 20 20 20 20 20 20 20  d.    #         
1e70: 20 20 20 20 20 20 7c 20 20 20 43 6f 6d 6d 65 6e        |   Commen
1e80: 74 0a 20 20 20 20 23 20 20 20 20 20 20 20 20 20  t.    #         
1e90: 20 20 20 20 20 20 7c 20 20 20 53 74 72 69 6e 67        |   String
1ea0: 0a 20 20 20 20 23 20 20 20 20 20 20 20 20 20 20  .    #          
1eb0: 20 20 20 20 20 7c 20 20 20 50 72 65 61 6d 62 6c       |   Preambl
1ec0: 65 0a 20 20 20 20 23 20 43 6f 6d 6d 65 6e 74 20  e.    # Comment 
1ed0: 20 20 20 20 20 20 3a 3a 3d 20 22 63 6f 6d 6d 65        ::= "comme
1ee0: 6e 74 22 20 5b 5e 5c 6e 5d 2a 20 5c 6e 20 20 20  nt" [^\n]* \n   
1ef0: 20 20 20 20 20 20 2d 2d 20 69 67 6e 6f 72 65 64        -- ignored
1f00: 0a 20 20 20 20 23 20 53 74 72 69 6e 67 20 20 20  .    # String   
1f10: 20 20 20 20 20 3a 3a 3d 20 22 73 74 72 69 6e 67       ::= "string
1f20: 22 20 27 7b 27 20 46 69 65 6c 64 2a 20 27 7d 27  " '{' Field* '}'
1f30: 0a 20 20 20 20 23 20 50 72 65 61 6d 62 6c 65 20  .    # Preamble 
1f40: 20 20 20 20 20 3a 3a 3d 20 22 70 72 65 61 6d 62       ::= "preamb
1f50: 6c 65 22 20 27 7b 27 20 2e 2a 20 27 7d 27 20 20  le" '{' .* '}'  
1f60: 20 20 20 20 20 2d 2d 20 28 62 61 6c 61 6e 63 65       -- (balance
1f70: 64 29 0a 20 20 20 20 23 20 52 65 63 6f 72 64 20  d).    # Record 
1f80: 20 20 20 20 20 20 20 3a 3a 3d 20 54 79 70 65 20         ::= Type 
1f90: 27 7b 27 20 4b 65 79 20 27 2c 27 20 46 69 65 6c  '{' Key ',' Fiel
1fa0: 64 2a 20 27 7d 27 0a 20 20 20 20 23 20 20 20 20  d* '}'.    #    
1fb0: 20 20 20 20 20 20 20 20 20 20 20 7c 20 20 20 54             |   T
1fc0: 79 70 65 20 27 28 27 20 4b 65 79 20 27 2c 27 20  ype '(' Key ',' 
1fd0: 46 69 65 6c 64 2a 20 27 29 27 20 2d 2d 20 6e 6f  Field* ')' -- no
1fe0: 74 20 68 61 6e 64 6c 65 64 0a 20 20 20 20 23 20  t handled.    # 
1ff0: 54 79 70 65 20 20 20 20 20 20 20 20 20 20 3a 3a  Type          ::
2000: 3d 20 4e 61 6d 65 0a 20 20 20 20 23 20 4b 65 79  = Name.    # Key
2010: 20 20 20 20 20 20 20 20 20 20 20 3a 3a 3d 20 4e             ::= N
2020: 61 6d 65 0a 20 20 20 20 23 20 46 69 65 6c 64 20  ame.    # Field 
2030: 20 20 20 20 20 20 20 20 3a 3a 3d 20 4e 61 6d 65          ::= Name
2040: 20 27 3d 27 20 56 61 6c 75 65 0a 20 20 20 20 23   '=' Value.    #
2050: 20 4e 61 6d 65 20 20 20 20 20 20 20 20 20 20 3a   Name          :
2060: 3a 3d 20 5b 5e 5c 73 5c 22 23 25 27 28 29 7b 7d  := [^\s\"#%'(){}
2070: 5d 2a 0a 20 20 20 20 23 20 56 61 6c 75 65 20 20  ]*.    # Value  
2080: 20 20 20 20 20 20 20 3a 3a 3d 20 5b 30 2d 39 5d         ::= [0-9]
2090: 2b 0a 20 20 20 20 23 20 20 20 20 20 20 20 20 20  +.    #         
20a0: 20 20 20 20 20 20 7c 20 20 20 27 22 27 20 28 5b        |   '"' ([
20b0: 5e 27 22 27 5d 7c 5c 5c 27 22 27 29 2a 20 27 22  ^'"']|\\'"')* '"
20c0: 27 0a 20 20 20 20 23 20 20 20 20 20 20 20 20 20  '.    #         
20d0: 20 20 20 20 20 20 7c 20 20 20 27 7b 27 20 2e 2a        |   '{' .*
20e0: 20 27 7d 27 20 20 20 20 20 20 20 20 20 20 20 20   '}'            
20f0: 20 20 20 20 20 20 2d 2d 20 28 62 61 6c 61 6e 63        -- (balanc
2100: 65 64 29 0a 0a 20 20 20 20 23 20 22 20 2d 20 46  ed)..    # " - F
2110: 69 78 75 70 20 65 6d 61 63 73 20 68 69 6c 69 74  ixup emacs hilit
2120: 20 63 6f 6e 66 75 73 69 6f 6e 20 66 72 6f 6d 20   confusion from 
2130: 74 68 65 20 67 72 61 6d 6d 61 72 20 61 62 6f 76  the grammar abov
2140: 65 2e 0a 20 20 20 20 76 61 72 69 61 62 6c 65 20  e..    variable 
2150: 64 61 74 61 0a 20 20 20 20 73 65 74 20 62 69 62  data.    set bib
2160: 74 65 78 20 24 64 61 74 61 28 24 74 6f 6b 65 6e  tex $data($token
2170: 2c 62 75 66 66 65 72 29 0a 0a 20 20 20 20 23 20  ,buffer)..    # 
2180: 53 70 6c 69 74 20 61 74 20 65 61 63 68 20 40 20  Split at each @ 
2190: 63 68 61 72 61 63 74 65 72 20 77 68 69 63 68 20  character which 
21a0: 69 73 20 61 74 20 74 68 65 20 62 65 67 69 6e 6e  is at the beginn
21b0: 69 6e 67 20 6f 66 20 61 20 6c 69 6e 65 2c 0a 20  ing of a line,. 
21c0: 20 20 20 23 20 6d 6f 64 75 6c 6f 20 77 68 69 74     # modulo whit
21d0: 65 73 70 61 63 65 2e 20 54 68 69 73 20 69 73 20  espace. This is 
21e0: 61 20 68 65 75 72 69 73 74 69 63 20 74 6f 20 64  a heuristic to d
21f0: 69 73 74 69 6e 67 75 69 73 68 20 74 68 65 20 40  istinguish the @
2200: 27 73 0a 20 20 20 20 23 20 73 74 61 72 74 69 6e  's.    # startin
2210: 67 20 61 20 6e 65 77 20 72 65 63 6f 72 64 20 66  g a new record f
2220: 72 6f 6d 20 74 68 65 20 40 27 73 20 6f 63 63 75  rom the @'s occu
2230: 72 69 6e 67 20 69 6e 73 69 64 65 20 61 20 72 65  ring inside a re
2240: 63 6f 72 64 2c 20 61 73 0a 20 20 20 20 23 20 70  cord, as.    # p
2250: 61 72 74 20 6f 66 20 65 6d 61 69 6c 20 61 64 64  art of email add
2260: 72 65 73 73 65 73 2e 20 45 6d 70 74 79 20 70 69  resses. Empty pi
2270: 63 65 73 20 61 74 20 62 65 67 69 6e 6e 69 6e 67  ces at beginning
2280: 20 6f 72 20 65 6e 64 20 61 72 65 0a 20 20 20 20   or end are.    
2290: 23 20 73 74 72 69 70 70 65 64 20 62 65 66 6f 72  # stripped befor
22a0: 65 20 74 68 65 20 73 70 6c 69 74 2e 0a 0a 20 20  e the split...  
22b0: 20 20 72 65 67 73 75 62 20 2d 6c 69 6e 65 20 2d    regsub -line -
22c0: 61 6c 6c 20 7b 5e 5b 5c 6e 5c 72 5c 66 5c 74 20  all {^[\n\r\f\t 
22d0: 5d 2a 40 7d 20 24 62 69 62 74 65 78 20 5c 30 30  ]*@} $bibtex \00
22e0: 30 20 62 69 62 74 65 78 0a 20 20 20 20 73 65 74  0 bibtex.    set
22f0: 20 64 62 20 5b 73 70 6c 69 74 20 5b 73 74 72 69   db [split [stri
2300: 6e 67 20 74 72 69 6d 20 24 62 69 62 74 65 78 20  ng trim $bibtex 
2310: 5c 30 30 30 5d 20 5c 30 30 30 5d 0a 0a 20 20 20  \000] \000]..   
2320: 20 69 66 20 7b 24 65 6f 66 7d 20 7b 0a 09 73 65   if {$eof} {..se
2330: 74 20 74 6f 74 61 6c 20 5b 6c 6c 65 6e 67 74 68  t total [llength
2340: 20 24 64 62 5d 0a 09 73 65 74 20 73 74 65 70 20   $db]..set step 
2350: 20 5b 65 78 70 72 20 7b 64 6f 75 62 6c 65 28 24   [expr {double($
2360: 74 6f 74 61 6c 29 20 2f 20 31 30 30 2e 30 7d 5d  total) / 100.0}]
2370: 0a 09 73 65 74 20 69 73 74 65 70 20 5b 65 78 70  ..set istep [exp
2380: 72 20 7b 24 73 74 65 70 20 3e 20 31 20 3f 20 69  r {$step > 1 ? i
2390: 6e 74 28 24 73 74 65 70 29 20 3a 20 31 7d 5d 0a  nt($step) : 1}].
23a0: 09 73 65 74 20 63 6f 75 6e 74 20 30 0a 20 20 20  .set count 0.   
23b0: 20 7d 20 65 6c 73 65 20 7b 0a 09 69 66 20 7b 5b   } else {..if {[
23c0: 6c 6c 65 6e 67 74 68 20 24 64 62 5d 20 3c 20 32  llength $db] < 2
23d0: 7d 20 7b 0a 09 20 20 20 20 23 20 4e 6f 74 68 69  } {..    # Nothi
23e0: 6e 67 20 74 6f 20 70 72 6f 63 65 73 73 2c 20 6f  ng to process, o
23f0: 72 20 64 61 74 61 20 77 68 69 63 68 20 61 79 20  r data which ay 
2400: 62 65 20 69 6e 63 6f 6d 70 6c 65 74 65 2e 0a 09  be incomplete...
2410: 20 20 20 20 72 65 74 75 72 6e 0a 09 7d 0a 0a 09      return..}...
2420: 73 65 74 20 64 61 74 61 28 24 74 6f 6b 65 6e 2c  set data($token,
2430: 62 75 66 66 65 72 29 20 5b 6c 69 6e 64 65 78 20  buffer) [lindex 
2440: 24 64 62 20 65 6e 64 5d 0a 09 73 65 74 20 64 62  $db end]..set db
2450: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2460: 20 20 5b 6c 72 61 6e 67 65 20 24 64 62 20 30 20    [lrange $db 0 
2470: 65 6e 64 2d 31 5d 0a 0a 09 23 20 46 61 6b 65 20  end-1]...# Fake 
2480: 70 72 6f 67 72 65 73 73 20 6d 65 74 65 72 2e 0a  progress meter..
2490: 09 73 65 74 20 63 6f 75 6e 74 20 2d 31 0a 20 20  .set count -1.  
24a0: 20 20 7d 0a 0a 20 20 20 20 66 6f 72 65 61 63 68    }..    foreach
24b0: 20 62 6c 6f 63 6b 20 24 64 62 20 7b 0a 09 69 66   block $db {..if
24c0: 20 7b 24 63 6f 75 6e 74 20 3c 20 30 7d 20 7b 0a   {$count < 0} {.
24d0: 09 20 20 20 20 43 61 6c 6c 62 61 63 6b 20 24 74  .    Callback $t
24e0: 6f 6b 65 6e 20 70 72 6f 67 72 65 73 73 20 2d 31  oken progress -1
24f0: 0a 09 7d 20 65 6c 73 65 69 66 20 7b 28 5b 69 6e  ..} elseif {([in
2500: 63 72 20 63 6f 75 6e 74 5d 20 25 20 24 69 73 74  cr count] % $ist
2510: 65 70 29 20 3d 3d 20 30 7d 20 7b 0a 09 20 20 20  ep) == 0} {..   
2520: 20 43 61 6c 6c 62 61 63 6b 20 24 74 6f 6b 65 6e   Callback $token
2530: 20 70 72 6f 67 72 65 73 73 20 5b 65 78 70 72 20   progress [expr 
2540: 7b 69 6e 74 28 24 63 6f 75 6e 74 20 2f 20 24 73  {int($count / $s
2550: 74 65 70 29 7d 5d 0a 09 7d 0a 09 69 66 20 7b 5b  tep)}]..}..if {[
2560: 72 65 67 65 78 70 20 2d 6e 6f 63 61 73 65 20 7b  regexp -nocase {
2570: 5c 73 2a 63 6f 6d 6d 65 6e 74 28 5b 5e 5c 6e 5d  \s*comment([^\n]
2580: 29 2a 5c 6e 28 2e 2a 29 7d 20 24 62 6c 6f 63 6b  )*\n(.*)} $block
2590: 20 5c 0a 09 09 2d 3e 20 63 6d 6e 74 20 72 65 73   \...-> cmnt res
25a0: 74 5d 7d 20 7b 0a 09 20 20 20 20 23 20 41 72 65  t]} {..    # Are
25b0: 20 40 63 6f 6d 6d 65 6e 74 73 20 62 6c 6f 63 6b   @comments block
25c0: 73 2c 20 6f 72 20 6a 75 73 74 20 31 20 6c 69 6e  s, or just 1 lin
25d0: 65 3f 0a 09 20 20 20 20 23 20 44 6f 65 73 20 61  e?..    # Does a
25e0: 6e 79 6f 6e 65 20 63 61 72 65 3f 0a 09 20 20 20  nyone care?..   
25f0: 20 43 61 6c 6c 62 61 63 6b 20 24 74 6f 6b 65 6e   Callback $token
2600: 20 63 6f 6d 6d 65 6e 74 20 24 63 6d 6e 74 0a 0a   comment $cmnt..
2610: 09 7d 20 65 6c 73 65 69 66 20 7b 5b 72 65 67 65  .} elseif {[rege
2620: 78 70 20 2d 6e 6f 63 61 73 65 20 7b 5e 5c 73 2a  xp -nocase {^\s*
2630: 73 74 72 69 6e 67 5b 5e 5c 7b 5d 2a 5c 7b 28 2e  string[^\{]*\{(.
2640: 2a 29 5c 7d 5b 5e 5c 7d 5d 2a 7d 20 5c 0a 09 09  *)\}[^\}]*} \...
2650: 24 62 6c 6f 63 6b 20 2d 3e 20 72 65 73 74 5d 7d  $block -> rest]}
2660: 20 7b 0a 09 20 20 20 20 23 20 73 74 72 69 6e 67   {..    # string
2670: 20 6d 61 63 72 6f 20 64 65 66 73 0a 09 20 20 20   macro defs..   
2680: 20 69 66 20 7b 24 64 61 74 61 28 24 74 6f 6b 65   if {$data($toke
2690: 6e 2c 63 61 73 65 73 65 6e 73 69 74 69 76 65 73  n,casesensitives
26a0: 74 72 69 6e 67 73 29 7d 20 7b 0a 09 09 43 61 6c  trings)} {...Cal
26b0: 6c 62 61 63 6b 20 24 74 6f 6b 65 6e 20 73 74 72  lback $token str
26c0: 69 6e 67 20 5b 50 61 72 73 65 53 74 72 69 6e 67  ing [ParseString
26d0: 20 24 72 65 73 74 5d 0a 09 20 20 20 20 7d 20 65   $rest]..    } e
26e0: 6c 73 65 20 7b 0a 09 09 43 61 6c 6c 62 61 63 6b  lse {...Callback
26f0: 20 24 74 6f 6b 65 6e 20 73 74 72 69 6e 67 20 5b   $token string [
2700: 50 61 72 73 65 42 6c 6f 63 6b 20 24 72 65 73 74  ParseBlock $rest
2710: 5d 0a 09 20 20 20 20 7d 0a 09 7d 20 65 6c 73 65  ]..    }..} else
2720: 69 66 20 7b 5b 72 65 67 65 78 70 20 2d 6e 6f 63  if {[regexp -noc
2730: 61 73 65 20 7b 5c 73 2a 70 72 65 61 6d 62 6c 65  ase {\s*preamble
2740: 5b 5e 5c 7b 5d 2a 5c 7b 28 2e 2a 29 5c 7d 5b 5e  [^\{]*\{(.*)\}[^
2750: 5c 7d 5d 2a 7d 20 5c 0a 09 09 24 62 6c 6f 63 6b  \}]*} \...$block
2760: 20 2d 3e 20 72 65 73 74 5d 7d 20 7b 0a 09 20 20   -> rest]} {..  
2770: 20 20 43 61 6c 6c 62 61 63 6b 20 24 74 6f 6b 65    Callback $toke
2780: 6e 20 70 72 65 61 6d 62 6c 65 20 24 72 65 73 74  n preamble $rest
2790: 0a 0a 09 7d 20 65 6c 73 65 69 66 20 7b 5b 72 65  ...} elseif {[re
27a0: 67 65 78 70 20 7b 28 5b 5e 5c 7b 5d 2b 29 5c 7b  gexp {([^\{]+)\{
27b0: 28 5b 5e 2c 5d 2a 29 2c 28 2e 2a 29 5c 7d 5b 5e  ([^,]*),(.*)\}[^
27c0: 5c 7d 5d 2a 7d 20 5c 0a 09 09 24 62 6c 6f 63 6b  \}]*} \...$block
27d0: 20 2d 3e 20 74 79 70 65 20 6b 65 79 20 72 65 73   -> type key res
27e0: 74 5d 7d 20 7b 0a 09 20 20 20 20 23 20 44 6f 20  t]} {..    # Do 
27f0: 61 6e 79 20 40 73 74 72 69 6e 67 20 6d 61 70 70  any @string mapp
2800: 69 6e 67 73 0a 09 20 20 20 20 69 66 20 7b 24 64  ings..    if {$d
2810: 61 74 61 28 24 74 6f 6b 65 6e 2c 63 61 73 65 73  ata($token,cases
2820: 65 6e 73 69 74 69 76 65 73 74 72 69 6e 67 73 29  ensitivestrings)
2830: 7d 20 7b 0a 09 09 23 20 70 75 74 73 20 24 64 61  } {...# puts $da
2840: 74 61 28 24 74 6f 6b 65 6e 2c 73 74 72 69 6e 67  ta($token,string
2850: 73 29 0a 09 09 73 65 74 20 72 65 73 74 20 5b 73  s)...set rest [s
2860: 74 72 69 6e 67 20 6d 61 70 20 24 64 61 74 61 28  tring map $data(
2870: 24 74 6f 6b 65 6e 2c 73 74 72 69 6e 67 73 29 20  $token,strings) 
2880: 24 72 65 73 74 5d 0a 09 20 20 20 20 7d 20 65 6c  $rest]..    } el
2890: 73 65 20 7b 0a 09 09 73 65 74 20 72 65 73 74 20  se {...set rest 
28a0: 5b 73 74 72 69 6e 67 20 6d 61 70 20 2d 6e 6f 63  [string map -noc
28b0: 61 73 65 20 24 64 61 74 61 28 24 74 6f 6b 65 6e  ase $data($token
28c0: 2c 73 74 72 69 6e 67 73 29 20 24 72 65 73 74 5d  ,strings) $rest]
28d0: 0a 09 20 20 20 20 7d 0a 09 20 20 20 20 43 61 6c  ..    }..    Cal
28e0: 6c 62 61 63 6b 20 24 74 6f 6b 65 6e 20 72 65 63  lback $token rec
28f0: 6f 72 64 20 5b 54 69 64 79 20 24 74 79 70 65 5d  ord [Tidy $type]
2900: 20 5b 73 74 72 69 6e 67 20 74 72 69 6d 20 24 6b   [string trim $k
2910: 65 79 5d 20 5c 0a 09 09 20 20 20 20 5b 50 61 72  ey] \...    [Par
2920: 73 65 42 6c 6f 63 6b 20 24 72 65 73 74 5d 0a 09  seBlock $rest]..
2930: 7d 20 65 6c 73 65 20 7b 0a 09 20 20 20 20 23 23  } else {..    ##
2940: 20 46 55 54 55 52 45 3a 20 55 73 65 20 61 20 6c   FUTURE: Use a l
2950: 6f 67 67 65 72 2e 0a 09 20 20 20 20 70 75 74 73  ogger...    puts
2960: 20 73 74 64 65 72 72 20 22 53 6b 69 70 70 69 6e   stderr "Skippin
2970: 67 3a 20 24 62 6c 6f 63 6b 22 0a 09 7d 0a 20 20  g: $block"..}.  
2980: 20 20 7d 0a 7d 0a 0a 70 72 6f 63 20 3a 3a 62 69    }.}..proc ::bi
2990: 62 74 65 78 3a 3a 50 61 72 73 65 53 74 72 69 6e  btex::ParseStrin
29a0: 67 20 7b 62 6c 6f 63 6b 7d 20 7b 0a 20 20 20 20  g {block} {.    
29b0: 72 65 67 65 78 70 20 7b 28 5c 53 2b 29 5b 5e 3d  regexp {(\S+)[^=
29c0: 5d 2a 3d 28 2e 2a 29 7d 20 24 62 6c 6f 63 6b 20  ]*=(.*)} $block 
29d0: 2d 3e 20 6b 65 79 20 72 65 73 74 0a 20 20 20 20  -> key rest.    
29e0: 72 65 74 75 72 6e 20 5b 6c 69 73 74 20 24 6b 65  return [list $ke
29f0: 79 20 24 72 65 73 74 5d 0a 7d 0a 0a 70 72 6f 63  y $rest].}..proc
2a00: 20 3a 3a 62 69 62 74 65 78 3a 3a 50 61 72 73 65   ::bibtex::Parse
2a10: 42 6c 6f 63 6b 20 7b 62 6c 6f 63 6b 7d 20 7b 0a  Block {block} {.
2a20: 20 20 20 20 73 65 74 20 72 65 74 20 20 20 5b 6c      set ret   [l
2a30: 69 73 74 5d 0a 20 20 20 20 73 65 74 20 69 6e 64  ist].    set ind
2a40: 65 78 20 30 0a 20 20 20 20 77 68 69 6c 65 20 7b  ex 0.    while {
2a50: 0a 09 5b 72 65 67 65 78 70 20 2d 73 74 61 72 74  ..[regexp -start
2a60: 20 24 69 6e 64 65 78 20 2d 69 6e 64 69 63 65 73   $index -indices
2a70: 20 2d 2d 20 5c 0a 09 09 7b 28 5c 53 2b 29 5b 5e   -- \...{(\S+)[^
2a80: 3d 5d 2a 3d 28 2e 2a 29 7d 20 24 62 6c 6f 63 6b  =]*=(.*)} $block
2a90: 20 2d 3e 20 6b 65 79 20 72 65 73 74 5d 0a 20 20   -> key rest].  
2aa0: 20 20 7d 20 7b 0a 09 66 6f 72 65 61 63 68 20 7b    } {..foreach {
2ab0: 6b 73 20 6b 65 7d 20 24 6b 65 79 20 62 72 65 61  ks ke} $key brea
2ac0: 6b 0a 09 73 65 74 20 6b 20 5b 54 69 64 79 20 5b  k..set k [Tidy [
2ad0: 73 74 72 69 6e 67 20 72 61 6e 67 65 20 24 62 6c  string range $bl
2ae0: 6f 63 6b 20 24 6b 73 20 24 6b 65 5d 5d 0a 09 66  ock $ks $ke]]..f
2af0: 6f 72 65 61 63 68 20 7b 72 73 20 72 65 7d 20 24  oreach {rs re} $
2b00: 72 65 73 74 20 62 72 65 61 6b 0a 09 66 6f 72 65  rest break..fore
2b10: 61 63 68 20 7b 76 20 69 6e 64 65 78 7d 20 5c 0a  ach {v index} \.
2b20: 09 09 5b 50 61 72 73 65 42 69 62 53 74 72 69 6e  ..[ParseBibStrin
2b30: 67 20 24 72 73 20 5b 73 74 72 69 6e 67 20 72 61  g $rs [string ra
2b40: 6e 67 65 20 24 62 6c 6f 63 6b 20 24 72 73 20 24  nge $block $rs $
2b50: 72 65 5d 5d 20 5c 0a 09 09 62 72 65 61 6b 0a 09  re]] \...break..
2b60: 6c 61 70 70 65 6e 64 20 72 65 74 20 24 6b 20 24  lappend ret $k $
2b70: 76 0a 20 20 20 20 7d 0a 20 20 20 20 72 65 74 75  v.    }.    retu
2b80: 72 6e 20 24 72 65 74 0a 7d 0a 0a 70 72 6f 63 20  rn $ret.}..proc 
2b90: 3a 3a 62 69 62 74 65 78 3a 3a 50 61 72 73 65 42  ::bibtex::ParseB
2ba0: 69 62 53 74 72 69 6e 67 20 7b 69 6e 64 65 78 20  ibString {index 
2bb0: 73 74 72 7d 20 7b 0a 20 20 20 20 73 65 74 20 63  str} {.    set c
2bc0: 6f 75 6e 74 20 30 0a 20 20 20 20 73 65 74 20 72  ount 0.    set r
2bd0: 65 74 73 74 72 20 22 22 0a 20 20 20 20 73 65 74  etstr "".    set
2be0: 20 65 73 63 61 70 65 20 30 0a 20 20 20 20 73 65   escape 0.    se
2bf0: 74 20 73 74 72 69 6e 67 20 30 0a 20 20 20 20 66  t string 0.    f
2c00: 6f 72 65 61 63 68 20 63 68 61 72 20 5b 73 70 6c  oreach char [spl
2c10: 69 74 20 24 73 74 72 20 22 22 5d 20 7b 0a 09 69  it $str ""] {..i
2c20: 6e 63 72 20 69 6e 64 65 78 0a 09 69 66 20 7b 24  ncr index..if {$
2c30: 65 73 63 61 70 65 7d 20 7b 0a 09 20 20 20 20 73  escape} {..    s
2c40: 65 74 20 65 73 63 61 70 65 20 30 0a 09 7d 20 65  et escape 0..} e
2c50: 6c 73 65 20 7b 0a 09 20 20 20 20 69 66 20 7b 24  lse {..    if {$
2c60: 63 68 61 72 20 65 71 20 22 5c 7b 22 7d 20 7b 0a  char eq "\{"} {.
2c70: 09 09 69 6e 63 72 20 63 6f 75 6e 74 0a 09 09 63  ..incr count...c
2c80: 6f 6e 74 69 6e 75 65 0a 09 20 20 20 20 7d 20 65  ontinue..    } e
2c90: 6c 73 65 69 66 20 7b 24 63 68 61 72 20 65 71 20  lseif {$char eq 
2ca0: 22 5c 7d 22 7d 20 7b 0a 09 09 69 6e 63 72 20 63  "\}"} {...incr c
2cb0: 6f 75 6e 74 20 2d 31 0a 09 09 69 66 20 7b 24 63  ount -1...if {$c
2cc0: 6f 75 6e 74 20 3c 20 30 7d 20 7b 69 6e 63 72 20  ount < 0} {incr 
2cd0: 69 6e 64 65 78 20 2d 31 3b 20 62 72 65 61 6b 7d  index -1; break}
2ce0: 0a 09 09 63 6f 6e 74 69 6e 75 65 0a 09 20 20 20  ...continue..   
2cf0: 20 7d 20 65 6c 73 65 69 66 20 7b 24 63 68 61 72   } elseif {$char
2d00: 20 65 71 20 22 2c 22 7d 20 7b 0a 09 09 69 66 20   eq ","} {...if 
2d10: 7b 24 63 6f 75 6e 74 20 3d 3d 20 30 7d 20 62 72  {$count == 0} br
2d20: 65 61 6b 0a 09 20 20 20 20 7d 20 65 6c 73 65 69  eak..    } elsei
2d30: 66 20 7b 24 63 68 61 72 20 65 71 20 22 5c 5c 22  f {$char eq "\\"
2d40: 7d 20 7b 0a 09 09 73 65 74 20 65 73 63 61 70 65  } {...set escape
2d50: 20 31 0a 09 09 63 6f 6e 74 69 6e 75 65 0a 09 20   1...continue.. 
2d60: 20 20 20 7d 20 65 6c 73 65 69 66 20 7b 24 63 68     } elseif {$ch
2d70: 61 72 20 65 71 20 22 5c 22 22 7d 20 7b 0a 09 09  ar eq "\""} {...
2d80: 23 20 4d 61 6e 61 67 69 6e 67 20 74 68 65 20 63  # Managing the c
2d90: 6f 75 6e 74 20 65 6e 73 75 72 65 73 20 74 68 61  ount ensures tha
2da0: 74 20 63 6f 6d 6d 61 20 69 6e 73 69 64 65 20 6f  t comma inside o
2db0: 66 20 61 0a 09 09 23 20 73 74 72 69 6e 67 20 69  f a...# string i
2dc0: 73 20 6e 6f 74 20 63 6f 6e 73 69 64 65 72 65 64  s not considered
2dd0: 20 61 73 20 74 68 65 20 65 6e 64 20 6f 66 20 74   as the end of t
2de0: 68 65 20 66 69 65 6c 64 2e 0a 09 09 69 66 20 7b  he field....if {
2df0: 21 24 73 74 72 69 6e 67 7d 20 7b 0a 09 09 20 20  !$string} {...  
2e00: 20 20 69 6e 63 72 20 63 6f 75 6e 74 0a 09 09 20    incr count... 
2e10: 20 20 20 73 65 74 20 73 74 72 69 6e 67 20 31 0a     set string 1.
2e20: 09 09 7d 20 65 6c 73 65 20 7b 0a 09 09 20 20 20  ..} else {...   
2e30: 20 69 6e 63 72 20 63 6f 75 6e 74 20 2d 31 0a 09   incr count -1..
2e40: 09 20 20 20 20 73 65 74 20 73 74 72 69 6e 67 20  .    set string 
2e50: 30 0a 09 09 7d 0a 09 09 63 6f 6e 74 69 6e 75 65  0...}...continue
2e60: 0a 09 20 20 20 20 7d 0a 09 20 20 20 20 23 20 65  ..    }..    # e
2e70: 6c 73 65 3a 20 4e 6f 74 68 69 6e 67 0a 09 7d 0a  lse: Nothing..}.
2e80: 09 61 70 70 65 6e 64 20 72 65 74 73 74 72 20 24  .append retstr $
2e90: 63 68 61 72 0a 20 20 20 20 7d 0a 20 20 20 20 72  char.    }.    r
2ea0: 65 67 73 75 62 20 2d 61 6c 6c 20 7b 5c 73 2b 7d  egsub -all {\s+}
2eb0: 20 24 72 65 74 73 74 72 20 7b 20 7d 20 72 65 74   $retstr { } ret
2ec0: 73 74 72 0a 20 20 20 20 72 65 74 75 72 6e 20 5b  str.    return [
2ed0: 6c 69 73 74 20 5b 73 74 72 69 6e 67 20 74 72 69  list [string tri
2ee0: 6d 20 24 72 65 74 73 74 72 5d 20 24 69 6e 64 65  m $retstr] $inde
2ef0: 78 5d 0a 7d 0a 0a 0a 23 20 23 23 23 20 23 23 23  x].}...# ### ###
2f00: 20 23 23 23 20 23 23 23 23 23 23 23 23 23 20 23   ### ######### #
2f10: 23 23 23 23 23 23 23 23 20 23 23 23 23 23 23 23  ######## #######
2f20: 23 23 0a 23 23 20 49 6e 74 65 72 6e 61 6c 2e 20  ##.## Internal. 
2f30: 50 61 63 6b 61 67 65 20 63 6f 6e 66 69 67 75 72  Package configur
2f40: 61 74 69 6f 6e 20 61 6e 64 20 73 74 61 74 65 2e  ation and state.
2f50: 0a 0a 6e 61 6d 65 73 70 61 63 65 20 65 76 61 6c  ..namespace eval
2f60: 20 62 69 62 74 65 78 20 7b 0a 20 20 20 20 23 20   bibtex {.    # 
2f70: 43 6f 75 6e 74 65 72 20 66 6f 72 20 74 68 65 20  Counter for the 
2f80: 67 65 6e 65 72 61 74 69 6f 6e 20 6f 66 20 70 61  generation of pa
2f90: 72 73 65 72 20 74 6f 6b 65 6e 73 2e 0a 20 20 20  rser tokens..   
2fa0: 20 76 61 72 69 61 62 6c 65 20 69 64 20 30 0a 0a   variable id 0..
2fb0: 20 20 20 20 23 20 53 74 61 74 65 20 6f 66 20 61      # State of a
2fc0: 6c 6c 20 70 61 72 73 65 72 73 2e 20 4b 65 79 73  ll parsers. Keys
2fd0: 20 66 6f 72 20 65 61 63 68 20 70 61 72 73 65 72   for each parser
2fe0: 20 61 72 65 20 70 72 65 66 69 78 65 64 20 77 69   are prefixed wi
2ff0: 74 68 20 74 68 65 0a 20 20 20 20 23 20 70 61 72  th the.    # par
3000: 73 65 72 20 74 6f 6b 65 6e 2e 0a 20 20 20 20 76  ser token..    v
3010: 61 72 69 61 62 6c 65 20 20 64 61 74 61 0a 20 20  ariable  data.  
3020: 20 20 61 72 72 61 79 20 73 65 74 20 64 61 74 61    array set data
3030: 20 7b 7d 0a 0a 20 20 20 20 23 20 4b 65 79 73 20   {}..    # Keys 
3040: 61 6e 64 20 74 68 65 69 72 20 6d 65 61 6e 69 6e  and their meanin
3050: 67 20 28 6c 69 73 74 65 64 20 77 69 74 68 6f 75  g (listed withou
3060: 74 20 74 6f 6b 65 6e 20 70 72 65 66 69 78 29 0a  t token prefix).
3070: 20 20 20 20 23 23 0a 20 20 20 20 23 20 62 75 66      ##.    # buf
3080: 66 65 72 0a 20 20 20 20 23 20 65 6f 66 0a 20 20  fer.    # eof.  
3090: 20 20 23 20 63 68 61 6e 6e 65 6c 20 20 20 20 3c    # channel    <
30a0: 2d 5c 2f 2d 20 44 69 66 66 65 72 65 6e 63 65 20  -\/- Difference 
30b0: 3f 0a 20 20 20 20 23 20 73 74 72 69 6e 67 73 20  ?.    # strings 
30c0: 20 20 20 20 20 7c 0a 20 20 20 20 23 20 2d 61 73       |.    # -as
30d0: 79 6e 63 20 20 20 20 20 20 20 7c 0a 20 20 20 20  ync       |.    
30e0: 23 20 2d 62 6c 6f 63 6b 73 69 7a 65 20 20 20 7c  # -blocksize   |
30f0: 0a 20 20 20 20 23 20 2d 63 68 61 6e 6e 65 6c 20  .    # -channel 
3100: 20 20 3c 2d 2f 0a 20 20 20 20 23 20 2d 72 65 63    <-/.    # -rec
3110: 6f 72 64 63 6f 6d 6d 61 6e 64 20 20 20 2d 2d 20  ordcommand   -- 
3120: 63 61 6c 6c 62 61 63 6b 20 66 6f 72 20 65 61 63  callback for eac
3130: 68 20 72 65 63 6f 72 64 0a 20 20 20 20 23 20 2d  h record.    # -
3140: 70 72 65 61 6d 62 6c 65 63 6f 6d 6d 61 6e 64 20  preamblecommand 
3150: 2d 2d 20 63 61 6c 6c 62 61 63 6b 20 66 6f 72 20  -- callback for 
3160: 40 70 72 65 61 6d 62 6c 65 20 62 6c 6f 63 6b 73  @preamble blocks
3170: 0a 20 20 20 20 23 20 2d 73 74 72 69 6e 67 63 6f  .    # -stringco
3180: 6d 6d 61 6e 64 20 20 20 2d 2d 20 63 61 6c 6c 62  mmand   -- callb
3190: 61 63 6b 20 66 6f 72 20 40 73 74 72 69 6e 67 20  ack for @string 
31a0: 6d 61 63 72 6f 73 0a 20 20 20 20 23 20 2d 63 6f  macros.    # -co
31b0: 6d 6d 65 6e 74 63 6f 6d 6d 61 6e 64 20 20 2d 2d  mmentcommand  --
31c0: 20 63 61 6c 6c 62 61 63 6b 20 66 6f 72 20 40 63   callback for @c
31d0: 6f 6d 6d 65 6e 74 20 62 6c 6f 63 6b 73 0a 20 20  omment blocks.  
31e0: 20 20 23 20 2d 70 72 6f 67 72 65 73 73 63 6f 6d    # -progresscom
31f0: 6d 61 6e 64 20 2d 2d 20 63 61 6c 6c 62 61 63 6b  mand -- callback
3200: 20 74 6f 20 69 6e 64 69 63 61 74 65 20 70 72 6f   to indicate pro
3210: 67 72 65 73 73 20 6f 66 20 70 61 72 73 65 0a 20  gress of parse. 
3220: 20 20 20 23 23 0a 7d 0a 0a 23 20 23 23 23 20 23     ##.}..# ### #
3230: 23 23 20 23 23 23 20 23 23 23 23 23 23 23 23 23  ## ### #########
3240: 20 23 23 23 23 23 23 23 23 23 20 23 23 23 23 23   ######### #####
3250: 23 23 23 23 0a 23 23 20 52 65 61 64 79 20 74 6f  ####.## Ready to
3260: 20 67 6f 0a 70 61 63 6b 61 67 65 20 70 72 6f 76   go.package prov
3270: 69 64 65 20 62 69 62 74 65 78 20 30 2e 36 0a 23  ide bibtex 0.6.#
3280: 20 45 4f 46 0a                                    EOF.