2 # the next line restarts using wish \
6 tk_dialog .err Error
$msg {} 0 Damn
10 set res
[lindex
$desc 0]
12 set res
[lindex
$desc 1]
13 if {$res=="TYPEREF"} {
14 set res
[lindex
[lindex
$desc 4] 1]
23 set tp
[string trimright
"$pdu $tp"]
26 proc newenc
{tp r toggle
} {
30 set cur
[lindex
[array get asnenc
$idx] 1]
31 set pr [lsearch
-exact $cur $r]
35 set cur
[lreplace
$cur $pr $pr]
46 set i
[.selector.l nearest
$y]
48 set tpval
[.selector.l get
$i]
49 if {$tag(selector
)=="CHOICE"} {
50 newenc
[lindex
$tpval 0] [lindex
$tpval 1] 0
52 newenc
[lindex
$tpval 0] [lindex
$tpval 1] 1
58 set i
[.composer.l nearest
$y]
59 set tpval
[.composer.l get
$i]
60 set tp
[lindex
$tpval 0]
61 set val
[lindex
$tpval 1]
63 set td
[$table type -followref $typetoask]
68 .selector.l delete
0 end
69 .selector.l insert end
"$tp is a CHOICE of:"
70 foreach
{subtypedesc req
} [lindex
$td 4] {
71 set r
[ref
$subtypedesc]
72 .selector.l insert end
[list
$tp $r]
75 wm deiconify .selector
80 .selector.l delete
0 end
81 .selector.l insert end
"In SEQUENCE $tp, the following are OPTIONAL:"
82 foreach
{subtypedesc req
} [lindex
$td 4] {
84 set r
[ref
$subtypedesc]
85 .selector.l insert end
[list
$tp $r]
89 wm deiconify .selector
93 if {$t=="SEQUENCE OF"} {
94 set text
"Size of SEQUENCE OF $tp:"
96 set text
"New value of $tp:"
99 .insertor.l configure
-text $text
100 .insertor.e delete
0 end
101 .insertor.e insert
0 $val
102 wm withdraw .selector
103 wm deiconify .insertor
111 newenc
$tag(insertor
) [.insertor.e get
] 0
114 proc fillcomposer
{} {
117 if [winfo exists .composer.l
] {
118 set fraction
[lindex
[.composer.l yview
] 0]
119 .composer.l delete
0 end
122 pack .composer
-fill both
-expand 1
123 listbox .composer.l
-yscrollcommand ".composer.v set"
124 scrollbar .composer.v
-orient vertical
-command ".composer.l yview"
125 pack .composer.v
-fill y
-side right
126 pack .composer.l
-expand yes -fill both
127 bind .composer.l
<ButtonPress
-1> {comppress
%y
}
129 listbox .selector.l
-yscrollcommand ".selector.v set"
130 scrollbar .selector.v
-orient vertical
-command ".selector.l yview"
131 pack .selector.v
-fill y
-side right
132 pack .selector.l
-expand yes -fill both
133 bind .selector.l
<ButtonPress
-1> {selpress
%y
}
134 wm protocol .selector WM_DELETE_WINDOW
{wm withdraw .selector
}
135 wm title .selector
"Snacc ASN.1 data item selection"
139 pack .insertor.l
-fill x
-expand yes -side top
140 pack .insertor.e
-fill x
-expand yes -side bottom
141 bind .insertor.e
<KeyPress
-Return> {inspress
}
142 wm protocol .insertor WM_DELETE_WINDOW
{wm withdraw .insertor
}
143 wm title .insertor
"Snacc ASN.1 data item modification"
145 wm withdraw .selector
146 wm withdraw .insertor
147 set null
[open
"/dev/null" w
]
148 $table encode
$null $pdu "encodevalcompose $null"
150 .composer.l yview moveto
$fraction
155 proc decodetype
{tp val
} {
158 set l
[expr [llength
$tp]-1]
159 set final
[lindex
$tp $l]
160 set addto
[lrange
$tp 0 [expr $l-1]]
162 set td
[$table type -followref $addto]
163 if {[lindex
$td 1]=="SEQUENCE"} {
164 if [catch
{set asnenc
($addto)}] {
165 set asnenc
($addto) ""
167 foreach
{elem req
} [lindex
$td 4] {
168 if {[lindex
$elem 0]==$final} {
170 lappend asnenc
($addto) $final
176 set asnenc
($addto) $final
181 proc decodeval
{chan tp val
} {
185 set typ
[$table type -followref $tp]
186 if {[lindex
$typ 1]=="BIT STRING"} {
187 set namespecs
[lindex
$typ 3]
189 foreach bit
[split $val ""] {
190 set idx
[lsearch
$namespecs "$bitno *"]
191 if {$idx>=0 && $bit} {
192 lappend val
"[lindex {! {}} $bit][lindex [lindex $namespecs $idx] 1]($bitno)"
196 } elseif
{[lindex
$typ 1]=="ENUMERATED"} {
197 set namespecs
[lindex
$typ 3]
198 set idx
[lsearch
$namespecs "$val *"]
200 lappend val
"[lindex [lindex $namespecs $idx] 1]"
206 proc encodevalcompose
{chan tp
} {
209 if [catch
{set val
$asnenc($tp)}] {
212 .composer.l insert end
[list
$tp $val]
216 proc encodeval
{chan tp val
} {
219 set val
[subst
-nobackslashes $val]
220 set typ
[$table type -followref $tp]
221 if {[lindex
$typ 1]=="OCTET STRING"} {
222 set fromto
[lindex
$typ 2]
223 set from
[lindex
$fromto 0]
224 set to
[lindex
$fromto 1]
228 regsub
-all {[^
\\]} $val {} slashes
229 set len
[expr [string length
$val] - [string length
$slashes] * 3]
230 if {$from!={} && $from>$len} {
231 set val
[format
"%$prefix[expr $from]s" $val]
232 } elseif
{$to!={} && $to<$len} {
233 err
[list encodeval
: value
$val for $tp >$to]
235 set last
[string last
\\ $val]
236 if {$last==-1 || $last<[string length
$val]-4} {
237 set val
[string range
$val 0 [expr [string length
$val] - 2]]
239 set val
[string range
$val 0 [expr $last - 1]]
241 regsub
-all {[^
\\]} $val {} slashes
242 set len
[expr [string length
$val] - [string length
$slashes] * 3]
245 } elseif
{[lindex
$typ 1]=="BIT STRING"} {
246 set namespecs
[lindex
$typ 3]
247 if {[regexp
{^
[01]+$
} [lindex
$val 0]]} {
248 set val
[split [lindex
$val 0] ""]
252 foreach name
$names {
253 if {[regsub
{([a
-zA-Z_][a
-zA-Z0-9_]*)?\
(([0-9]+)\
)} $name {\
2} bitno
]!=1} {
254 set idx
[lsearch
-regexp $namespecs "^\[0-9\]+ $name$"]
256 err
"Bit $name of $tp not in $namespecs"
259 set bitno
[lindex
[lindex
$namespecs $idx] 0]
261 while {[llength
$val]<=$bitno} {
264 set val
[lreplace
$val $bitno $bitno 1]
267 proc namespeccmp
{a b
} {return [expr [lindex
$a 0] - [lindex
$b 0]]}
268 set sorted
[lsort
-command namespeccmp
-decreasing $namespecs]
269 set bitno
[lindex
[lindex
$sorted 0] 0]
270 while {[llength
$val]<=$bitno} {
273 set val
[join $val ""]
274 } elseif
{[lindex
$typ 1]=="ENUMERATED"} {
275 set namespecs
[lindex
$typ 3]
276 if {![regexp
{^
[0-9]*$
} [lindex
$val 0]]} {
277 set idx
[lsearch
-regexp $namespecs "^\[0-9\]+ $val$"]
279 err
"Named value $val of $tp not in $namespecs"
281 set val
[lindex
[lindex
$namespecs $idx] 0]
288 proc encodeasnenc
{chan tp
} {
291 if [catch
{set val
$asnenc($tp)}] {
294 return [encodeval
$chan $tp $val]
297 wm title .
"Snacc ASN.1 message editor"
298 wm geometry .
400x300
299 frame .mbar
-relief raised
300 pack .mbar
-side top
-fill x
302 menubutton .mbar.
file -text Message
-menu .mbar.
file.menu
303 pack .mbar.
file -side left
306 .mbar.
file.menu add
command -label "Open ..." -command {openfile
}
307 .mbar.
file.menu add
command -label "Save As ..." -command {savefile
}
308 .mbar.
file.menu add
command -label "Quit" -command {quit
}
309 wm protocol . WM_DELETE_WINDOW
{quit
}
313 global table pdu asnenc
315 set chan
[open
$fn r
]
316 fconfigure
$chan -translation binary
317 set bytes
[$table decode
$chan $pdu "decodeval $chan" decodetype
]
323 readfile
[tk_getOpenFile
-defaultextension .ber
-filetypes {{{ASN
.1 data
} {.ber .bin .out .tt
}} {{All files
} {.
*}}}]
327 set fn
[tk_getSaveFile
-defaultextension .ber
-filetypes {{{ASN
.1 data
} {.ber .bin .out .tt
}} {{All files
} {.
*}}}]
330 set chan
[open
$fn w
]
331 $table encode
$chan $pdu "encodeasnenc $chan"
340 set asnfile
[lindex
$argv 0]
342 puts stderr
"Usage: $argv0 <table-file> ?<ber-file>?"
344 puts stderr
"This program is a simple editor for ASN.1 messages"
345 puts stderr
"encoded using the Basic Encoding Rules (BER). It requires"
346 puts stderr
"the grammar specification, in binary format as generated"
347 puts stderr
"by \"snacc -T\", as the initial argument on the command line."
349 puts stderr
"The purpose of this program is to demonstrate the usage of"
350 puts stderr
"the new Tcl/Tk command \"asn\". Have a look at the Tcl/Tk"
351 puts stderr
"script \"$argv0\"!"
355 set table
[asn
$asnfile]
357 foreach
type [$table types
] {
358 if {[lindex
[$table type $type] 0]=="$type pdu"} {
364 readfile
[lindex
$argv 1]