Tcl Library Source Code

Check-in [8cd20a672a]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Ticket [071dbedcc8]. bibtex. string-handling fix, plus new option -casesensitivestrings. Code, docs, pcs updated. No testcases available for the bug, nor the new feature.
Timelines: family | ancestors | descendants | both | bibtex-071dbedcc8
Files: files | file ages | folders
SHA1: 8cd20a672ae41eeb4d0e2293565d40e9c034a04f
User & Date: andreask 2015-04-15 00:22:43
Context
2015-04-21
18:52
Merged branch [bibtex-071dbedcc8], ticket [071dbedcc8] into release. Updated docs. Updated README. check-in: cd1a3ac12d user: andreask tags: tcllib-1-17-rc
2015-04-15
00:22
Ticket [071dbedcc8]. bibtex. string-handling fix, plus new option -casesensitivestrings. Code, docs, pcs updated. No testcases available for the bug, nor the new feature. Closed-Leaf check-in: 8cd20a672a user: andreask tags: bibtex-071dbedcc8
2015-04-14
23:05
Ticket [9014664163] - control - Drop superfluous "version" variable. check-in: 71ed84053f user: andreask tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to modules/bibtex/bibtex.man.

1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[comment {-*- tcl -*- doctools manpage}]

[manpage_begin bibtex n 0.5]
[keywords bibliography]
[keywords bibtex]
[keywords parsing]
[keywords {text processing}]
[copyright {2005 for documentation, Andreas Kupries <[email protected]>}]
[moddesc   {bibtex}]
[titledesc {Parse bibtex files}]
[category  {Text processing}]
[require Tcl 8.4]
[require bibtex [opt 0.5]]
[description]
[para]

This package provides commands for the parsing of bibliographies in
BibTeX format.

[list_begin definitions]

>
|









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[comment {-*- tcl -*- doctools manpage}]
[vset VERSION 0.6]
[manpage_begin bibtex n [vset VERSION]]
[keywords bibliography]
[keywords bibtex]
[keywords parsing]
[keywords {text processing}]
[copyright {2005 for documentation, Andreas Kupries <[email protected]>}]
[moddesc   {bibtex}]
[titledesc {Parse bibtex files}]
[category  {Text processing}]
[require Tcl 8.4]
[require bibtex [opt [vset VERSION]]]
[description]
[para]

This package provides commands for the parsing of bibliographies in
BibTeX format.

[list_begin definitions]
72
73
74
75
76
77
78

79
80
81
82
83
84
85

[call [cmd ::bibtex::parse] \
	[opt "[option -recordcommand]   [arg recordcmd]"] \
	[opt "[option -preamblecommand] [arg preamblecmd]"] \
	[opt "[option -stringcommand]   [arg stringcmd]"] \
	[opt "[option -commentcommand]  [arg commentcmd]"] \
	[opt "[option -progresscommand] [arg progresscmd]"] \

	"([arg text] | [option -channel] [arg chan])"]

This is the most low-level form for the parser. The returned result
will be a handle for the parser. During processing it will invoke the
invoke the specified callback commands for each type of data found in
the bibliography.








>







73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

[call [cmd ::bibtex::parse] \
	[opt "[option -recordcommand]   [arg recordcmd]"] \
	[opt "[option -preamblecommand] [arg preamblecmd]"] \
	[opt "[option -stringcommand]   [arg stringcmd]"] \
	[opt "[option -commentcommand]  [arg commentcmd]"] \
	[opt "[option -progresscommand] [arg progresscmd]"] \
	[opt "[option -casesensitivestrings] [arg bool]"] \
	"([arg text] | [option -channel] [arg chan])"]

This is the most low-level form for the parser. The returned result
will be a handle for the parser. During processing it will invoke the
invoke the specified callback commands for each type of data found in
the bibliography.

95
96
97
98
99
100
101






102
103
104
105
106
107
108
The callbacks, i.e. [arg *cmd], are all command prefixes and will be
invoked with additional arguments appended to them. The meaning of the
arguments depends on the callback and is explained below. The first
argument will however always be the handle of the parser invoking the
callback.

[list_begin definitions]







[def "[cmd recordcmd] [arg token] [arg type] [arg key] [arg recorddict]"]

This callback is invoked whenever the parser detects a bibliography
record in the input. Its arguments are the record type, the
bibliography key for the record, and a dictionary containing the keys
and values describing the record. Any string macros known to the







>
>
>
>
>
>







97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
The callbacks, i.e. [arg *cmd], are all command prefixes and will be
invoked with additional arguments appended to them. The meaning of the
arguments depends on the callback and is explained below. The first
argument will however always be the handle of the parser invoking the
callback.

[list_begin definitions]

[def "[option -casesensitivestrings]"]

This option takes a boolean value. When set string macro processing
becomes case-sensitive. The default is case-insensitive string macro
processing.

[def "[cmd recordcmd] [arg token] [arg type] [arg key] [arg recorddict]"]

This callback is invoked whenever the parser detects a bibliography
record in the input. Its arguments are the record type, the
bibliography key for the record, and a dictionary containing the keys
and values describing the record. Any string macros known to the

Changes to modules/bibtex/bibtex.pcx.

1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
# -*- tcl -*- bibtex.pcx
# Syntax of the commands provided by package bibtex.
#
# For use by TclDevKit's static syntax checker (v4.1+).
# See http://www.activestate.com/solutions/tcl/
# See http://aspn.activestate.com/ASPN/docs/Tcl_Dev_Kit/4.0/Checker.html#pcx_api
# for the specification of the format of the code in this file.
#

package require pcx
pcx::register bibtex
pcx::tcldep   0.5 needs tcl 8.5


namespace eval ::bibtex {}

pcx::message parseSaxCmdErr {Options -*command and -command exclude each other} err

pcx::check 0.5 std ::bibtex::addStrings \
    {checkSimpleArgs 2 2 {












>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# -*- tcl -*- bibtex.pcx
# Syntax of the commands provided by package bibtex.
#
# For use by TclDevKit's static syntax checker (v4.1+).
# See http://www.activestate.com/solutions/tcl/
# See http://aspn.activestate.com/ASPN/docs/Tcl_Dev_Kit/4.0/Checker.html#pcx_api
# for the specification of the format of the code in this file.
#

package require pcx
pcx::register bibtex
pcx::tcldep   0.5 needs tcl 8.5
pcx::tcldep   0.6 needs tcl 8.5

namespace eval ::bibtex {}

pcx::message parseSaxCmdErr {Options -*command and -command exclude each other} err

pcx::check 0.5 std ::bibtex::addStrings \
    {checkSimpleArgs 2 2 {
48
49
50
51
52
53
54


























55
56
57
58
	    }}}
	}}
    }}
pcx::check 0.5 std ::bibtex::wait \
    {checkSimpleArgs 1 1 {
	checkWord
    }}



























# Initialization via pcx::init.
# Use a ::bibtex::init procedure for non-standard initialization.
pcx::complete







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
	    }}}
	}}
    }}
pcx::check 0.5 std ::bibtex::wait \
    {checkSimpleArgs 1 1 {
	checkWord
    }}

pcx::check 0.6 std ::bibtex::parse \
    {checkSimpleArgs 1 -1 {
	{checkConstrained {
	    checkSwitches exact {
		{-casesensitivestrings checkBoolean}
		{-recordcommand        {checkSetConstraint sax {checkProcCall 4}}}
		{-preamblecommand      {checkSetConstraint sax {checkProcCall 2}}}
		{-stringcommand        {checkSetConstraint sax {checkProcCall 2}}}
		{-commentcommand       {checkSetConstraint sax {checkProcCall 2}}}
		{-progresscommand      {checkSetConstraint sax {checkProcCall 2}}}
		{-command              {checkSetConstraint cmd {checkProcCall 2}}}
		{-channel              {checkSetConstraint chan checkChannelID}}
	    } {checkConstraint {
		{{chan sax cmd} {warn bibtex::parseSaxCmdErr {} checkAtEnd}}
		{{sax cmd}      {warn bibtex::parseSaxCmdErr {} {
		    checkSimpleArgs 1 1 {
			checkWord
		    }
		}}}
		{chan checkAtEnd}
	    } {checkSimpleArgs 1 1 {
		checkWord
	    }}}
	}}
    }}

# Initialization via pcx::init.
# Use a ::bibtex::init procedure for non-standard initialization.
pcx::complete

Changes to modules/bibtex/bibtex.tcl.

159
160
161
162
163
164
165
166
167
168
169
170
171
172

173
174
175
176
177
178
179
proc ::bibtex::GetOptions {argv statevar} {
    upvar 1 $statevar state

    # Basic processing of the argument list
    # and the options found therein.

    set opts [lrange [::cmdline::GetOptionDefaults {
	{command.arg         {}}
	{channel.arg         {}}
	{recordcommand.arg   {}}
	{preamblecommand.arg {}}
	{stringcommand.arg   {}}
	{commentcommand.arg  {}}
	{progresscommand.arg {}}

    } result] 2 end] ;# Remove ? and help.

    set argc [llength $argv]
    while {[set err [::cmdline::getopt argv $opts opt arg]]} {
	if {$err < 0} {
	    set olist ""
	    foreach o [lsort $opts] {







|
|
|
|
|
|
|
>







159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
proc ::bibtex::GetOptions {argv statevar} {
    upvar 1 $statevar state

    # Basic processing of the argument list
    # and the options found therein.

    set opts [lrange [::cmdline::GetOptionDefaults {
	{command.arg              {}}
	{channel.arg              {}}
	{recordcommand.arg        {}}
	{preamblecommand.arg      {}}
	{stringcommand.arg        {}}
	{commentcommand.arg       {}}
	{progresscommand.arg      {}}
	{casesensitivestrings.arg {}}
    } result] 2 end] ;# Remove ? and help.

    set argc [llength $argv]
    while {[set err [::cmdline::getopt argv $opts opt arg]]} {
	if {$err < 0} {
	    set olist ""
	    foreach o [lsort $opts] {
246
247
248
249
250
251
252







253
254
255
256
257
258
259
    set state(bg)     [expr {$sax || $bg}]

    if {![info exists state(-stringcommand)]} {
	set state(-stringcommand) [list ::bibtex::addStrings]
    }
    if {![info exists state(-recordcommand)] && (!$sax)} {
	set state(-recordcommand) [list ::bibtex::AddRecord]







    }
    return
}

proc ::bibtex::Callback {token type args} {
    variable data








>
>
>
>
>
>
>







247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
    set state(bg)     [expr {$sax || $bg}]

    if {![info exists state(-stringcommand)]} {
	set state(-stringcommand) [list ::bibtex::addStrings]
    }
    if {![info exists state(-recordcommand)] && (!$sax)} {
	set state(-recordcommand) [list ::bibtex::AddRecord]
    }
    if {[info exists state(-casesensitivestrings)] &&
	$state(-casesensitivestrings)
    } {
	set state(casesensitivestrings) 1
    } else {
	set state(casesensitivestrings) 0
    }
    return
}

proc ::bibtex::Callback {token type args} {
    variable data

359
360
361
362
363
364
365
366
367
368



369
370
371
372
373
374
375
376
377




378

379
380
381
382
383
384
385
386





387
388
389
390
391
392
393
	}
	if {[regexp -nocase {\s*comment([^\n])*\n(.*)} $block \
		-> cmnt rest]} {
	    # Are @comments blocks, or just 1 line?
	    # Does anyone care?
	    Callback $token comment $cmnt

	} elseif {[regexp -nocase {\s*string[^\{]*\{(.*)\}[^\}]*} \
		$block -> rest]} {
	    # string macro defs



	    Callback $token string [ParseBlock $rest]

	} elseif {[regexp -nocase {\s*preamble[^\{]*\{(.*)\}[^\}]*} \
		$block -> rest]} {
	    Callback $token preamble $rest

	} elseif {[regexp {([^\{]+)\{([^,]*),(.*)\}[^\}]*} \
		$block -> type key rest]} {
	    # Do any @string mappings (these are case insensitive)




	    set rest [string map -nocase $data($token,strings) $rest]

	    Callback $token record [Tidy $type] [string trim $key] \
		    [ParseBlock $rest]
	} else {
	    ## FUTURE: Use a logger.
	    puts stderr "Skipping: $block"
	}
    }
}






proc ::bibtex::ParseBlock {block} {
    set ret   [list]
    set index 0
    while {
	[regexp -start $index -indices -- \
		{(\S+)[^=]*=(.*)} $block -> key rest]







|


>
>
>
|
|






|
>
>
>
>
|
>








>
>
>
>
>







367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
	}
	if {[regexp -nocase {\s*comment([^\n])*\n(.*)} $block \
		-> cmnt rest]} {
	    # Are @comments blocks, or just 1 line?
	    # Does anyone care?
	    Callback $token comment $cmnt

	} elseif {[regexp -nocase {^\s*string[^\{]*\{(.*)\}[^\}]*} \
		$block -> rest]} {
	    # string macro defs
	    if {$data($token,casesensitivestrings)} {
		Callback $token string [ParseString $rest]
	    } else {
		Callback $token string [ParseBlock $rest]
	    }
	} elseif {[regexp -nocase {\s*preamble[^\{]*\{(.*)\}[^\}]*} \
		$block -> rest]} {
	    Callback $token preamble $rest

	} elseif {[regexp {([^\{]+)\{([^,]*),(.*)\}[^\}]*} \
		$block -> type key rest]} {
	    # Do any @string mappings
	    if {$data($token,casesensitivestrings)} {
		# puts $data($token,strings)
		set rest [string map $data($token,strings) $rest]
	    } else {
		set rest [string map -nocase $data($token,strings) $rest]
	    }
	    Callback $token record [Tidy $type] [string trim $key] \
		    [ParseBlock $rest]
	} else {
	    ## FUTURE: Use a logger.
	    puts stderr "Skipping: $block"
	}
    }
}

proc ::bibtex::ParseString {block} {
    regexp {(\S+)[^=]*=(.*)} $block -> key rest
    return [list $key $rest]
}

proc ::bibtex::ParseBlock {block} {
    set ret   [list]
    set index 0
    while {
	[regexp -start $index -indices -- \
		{(\S+)[^=]*=(.*)} $block -> key rest]
473
474
475
476
477
478
479
480
481
    # -commentcommand  -- callback for @comment blocks
    # -progresscommand -- callback to indicate progress of parse
    ##
}

# ### ### ### ######### ######### #########
## Ready to go
package provide bibtex 0.5
# EOF







|

494
495
496
497
498
499
500
501
502
    # -commentcommand  -- callback for @comment blocks
    # -progresscommand -- callback to indicate progress of parse
    ##
}

# ### ### ### ######### ######### #########
## Ready to go
package provide bibtex 0.6
# EOF

Changes to modules/bibtex/pkgIndex.tcl.

1
2
if {![package vsatisfies [package provide Tcl] 8.4]} {return}
package ifneeded bibtex 0.5 [list source [file join $dir bibtex.tcl]]

|
1
2
if {![package vsatisfies [package provide Tcl] 8.4]} {return}
package ifneeded bibtex 0.6 [list source [file join $dir bibtex.tcl]]