chiark / gitweb /
Cache datagram format parsing; profiled.
authorian <ian>
Sat, 2 Mar 2002 17:42:40 +0000 (17:42 +0000)
committerian <ian>
Sat, 2 Mar 2002 17:42:40 +0000 (17:42 +0000)
make-probes.tcl

index 6a033ff5aff84ff77a36367bb8f3593520a62c66..52a580e29dc5e6c05caef8aa123f15668370daa6 100755 (executable)
@@ -1,6 +1,10 @@
 #!/usr/bin/tclsh8.2
 
 
+       package require profiler
+       ::profiler::init
+
+
 set debug_level 1
 
 proc debug {level str} {
@@ -57,7 +61,6 @@ namespace eval Random-Bytes {
            error "openssl bf-ofb exited unexpectedly"
        }
        set y [packet-fromstring $x]
-       if {[string length $y] != $n*2} { error "binary format failed $n $y" }
        return $y
     }
 }
@@ -258,151 +261,175 @@ proc get/string {s v minlen maxlen first rest} {
 }
 
 
-proc assemble {outvarname format} {
-    # format should look like those RFC diagrams.
-    # +-+-+ stuff and good formatting is mandatory.
-    # Tabs are forbidden.
-    #
-    # Field names are converted to lowercase; internal spaces
-    # are replaced with _.  They are then assumed to be
-    # variable names in the caller's scope.  The packet is
-    # assembled from those values (which must all be set)
-    # and stored in $varname in the caller's scope.
-    #
-    # Variables ?_whatever will be *set* with the location of the
-    # field in the string (in internal format); the corresponding
-    # `whatever' (with the ?_ stripped) will be read when assembling.
-    #
-    # Field name `0' means set the field to zero.
-
-    upvar 1 $outvarname out
-    set out {}
-    set lno 0
-    debug 7 "ASSEMBLY $outvarname\n$format"
-    foreach l [split $format "\n"] {
-       incr lno
-       if {[regexp -nocase {^ *\| +\| *$} $l]} {
-           if {![info exists wordbits]} {
-               error "vspace not in data @$lno\n?$l?"
-           }
-           incr words
-       } elseif {[regexp -nocase {^ *[|? a-z0-9]+$} $l]} {
-           if {[info exists words]} {
-               error "data without delimline @$lno\n?$l?"
+namespace eval Assembler {
+    namespace export assemble assembly-overwrite
+
+    proc assemble {outvarname format} {
+       # format should look like those RFC diagrams.
+       # +-+-+ stuff and good formatting is mandatory.
+       # Tabs are forbidden.
+       #
+       # Field names are converted to lowercase; internal spaces
+       # are replaced with _.  They are then assumed to be
+       # variable names in the caller's scope.  The packet is
+       # assembled from those values (which must all be set)
+       # and stored in $varname in the caller's scope.
+       #
+       # Variables ?_whatever will be *set* with the location of the
+       # field in the string (in internal format); the corresponding
+       # `whatever' (with the ?_ stripped) will be read when assembling.
+       #
+       # Field name `0' means set the field to zero.
+
+       variable cache
+       upvar 1 $outvarname out
+       if {[catch { set parsed $cache($format) }]} {
+           set parsed [parse $format]
+           set cache($format) $parsed
+       }
+
+       manyset $parsed outbytes lout
+       set out [string repeat 00 $outbytes]
+       foreach {location varname locvarname} $lout {
+           if {"$varname" == "0"} {
+               set value 0
+           } else {
+               set value [uplevel 1 [list set $varname]]
            }
-           set words 1
-           set cue $l
-       } elseif {[regexp {^ *[-+]+ *$} $l]} {
-           set wordbits 0
-           set newlineform {}
-           while {[regexp {^([-= ]+)\+(.*)$} $l dummy before after]} {
-               set atpos([string length $before]) $wordbits
-               incr wordbits
-               set l "$before=$after"
-               append newlineform "@[string length $before]:$wordbits "
+           if {[string length $locvarname]} {
+               upvar 1 $locvarname lv
+               set lv $location
            }
-           incr wordbits -1
-           append newlineform $wordbits
-           if {[info exists lineform]} {
-               if {"$newlineform" != "$lineform"} {
- error "format change @$lno\n?$l?\n$wordformat != $oldwordformat"
+           assembly-overwrite out $location $value
+       }
+    }
+
+    proc parse {format} {
+       set lno 0
+       set outbytes 0
+       debug 7 "ASSEMBLY $format"
+       foreach l [split $format "\n"] {
+           incr lno
+           if {[regexp -nocase {^ *\| +\| *$} $l]} {
+               if {![info exists wordbits]} {
+                   error "vspace not in data @$lno\n?$l?"
                }
-               if {![info exists words] || $words<0} {
-                   error "consecutive delimlines @$lno\n?$l?"
+               incr words
+           } elseif {[regexp -nocase {^ *[|? a-z0-9]+$} $l]} {
+               if {[info exists words]} {
+                   error "data without delimline @$lno\n?$l?"
                }
-               append out [string repeat 00 [expr {$words*$wordbits/8}]]
-               set l $cue
-               while {[regexp -nocase \
-                       {^([ =]*)\|( *[? a-z0-9]*[a-z0-9] *)\|(.*)$} \
-                       $l dummy before midpart after]} {
-                   debug 7 "RWORKG ?$l?"
-                   set varname [string tolower [string trim $midpart]]
-                   set varname [string map {{ } _} $varname]
-                   set p1 [string length $before]
-                   set p2 [expr {
-                       [string length $before] +
-                       [string length $midpart] + 1
-                   }]
-                   if {![info exists atpos($p1)] ||
-                       ![info exists atpos($p2)]} {
- error "vdelims not found @$lno $varname $p1 $p2 -- $lineform ?$cue?"
+               set words 1
+               set cue $l
+           } elseif {[regexp {^ *[-+]+ *$} $l]} {
+               set wordbits 0
+               set newlineform {}
+               while {[regexp {^([-= ]+)\+(.*)$} $l dummy before after]} {
+                   set atpos([string length $before]) $wordbits
+                   incr wordbits
+                   set l "$before=$after"
+                   append newlineform "@[string length $before]:$wordbits "
+               }
+               incr wordbits -1
+               append newlineform $wordbits
+               if {[info exists lineform]} {
+                   if {"$newlineform" != "$lineform"} {
+ error "format change @$lno\n?$l?\n$wordformat != $oldwordformat"
+                   }
+                   if {![info exists words] || $words<0} {
+                       error "consecutive delimlines @$lno\n?$l?"
                    }
-                   set bit1 [expr {
-                       [string length $out]*4
-                       - $words*$wordbits
-                       + $atpos($p1)
-                   }]
-                   set bitlen [expr {
-                       $atpos($p2) - $atpos($p1) + ($words-1)*$wordbits
-                   }]
-                   set location [list $bit1 $bitlen $outvarname-$varname]
-                   if {[regexp {^\?_(.*)} $varname dummy realvarname]} {
-                       debug 7 "LOCATING $varname $location"
-                       upvar 1 $varname locvarname
-                       set locvarname $location
-                        set varname $realvarname
+                   incr outbytes [expr {$words*$wordbits/8}]
+                   set l $cue
+                   while {[regexp -nocase \
+                           {^([ =]*)\|( *[? a-z0-9]*[a-z0-9] *)\|(.*)$} \
+                           $l dummy before midpart after]} {
+                       debug 7 "RWORKG ?$l?"
+                       set varname [string tolower [string trim $midpart]]
+                       set varname [string map {{ } _} $varname]
+                       set p1 [string length $before]
+                       set p2 [expr {
+                           [string length $before] +
+                           [string length $midpart] + 1
+                       }]
+                       if {![info exists atpos($p1)] ||
+                           ![info exists atpos($p2)]} {
+ error "vdelims not found @$lno $varname $p1 $p2 -- $lineform ?$cue?"
+                       }
+                       set bit1 [expr {
+                           $outbytes*8
+                           - $words*$wordbits
+                           + $atpos($p1)
+                       }]
+                       set bitlen [expr {
+                           $atpos($p2) - $atpos($p1) + ($words-1)*$wordbits
+                       }]
+                       set location [list $bit1 $bitlen $varname]
+                       if {[regexp {^\?_(.*)} $varname dummy realvarname]} {
+                           debug 7 "LOCATING $varname $location"
+                           set locvarname $varname
+                           set varname $realvarname
+                       } else {
+                           set locvarname {}
+                       }
+                       lappend lout $location $varname $locvarname
+                       set l "$before="
+                       append l [string repeat = [string length $midpart]]
+                       append l |$after
                    }
-                   if {"$varname" == "0"} {
-                       set value 0
-                   } else {
-                       set value [uplevel 1 [list set $varname]]
+                   debug 7 "REMAIN ?$l?"
+               } else {
+                   if {$wordbits % 8 || $wordbits >32} {
+                       error "bad wordbits $wordbits @$lno ?$l? $newlineform"
                    }
-                   assembly-overwrite out $location $value
-                   set l "$before="
-                   append l [string repeat = [string length $midpart]]
-                   append l |$after
+                   set lineform $newlineform
                }
-               debug 7 "REMAIN ?$l?"
+               catch { unset words }
+           } elseif {[regexp {^ *$} $l]} {
            } else {
-               if {$wordbits % 8 || $wordbits >32} {
-                   error "bad wordbits $wordbits @$lno ?$l? $newlineform"
-               }
-               set lineform $newlineform
+               error "huh? @$lno ?$l?"
            }
-           catch { unset words }
-       } elseif {[regexp {^ *$} $l]} {
-       } else {
-           error "huh? @$lno ?$l?"
        }
+       debug 7 "ASSEMBLY\n$outbytes\n$lout\n"
+       return [list $outbytes $lout]
     }
-    debug 7 "ASSEMBLY\n$out\n"
-    return $out
-}
 
-proc assembly-overwrite {outvarname location value} {
-    upvar 1 $outvarname out
-    manyset $location bit1 bitlen diag
-    debug 8 "ASSEMBLY $diag == $value == 0x[format %x $value] (@$bit1+$bitlen)"
-    if {$bitlen < 32 && $value >= (1<<$bitlen)} {
-       error "$diag $value >= 2**$bitlen"
-    }
-    if {!($bit1 % 8) && !($bitlen % 8)} {
-       set char0no [expr {$bit1/4}]
-       set charlen [expr {$bitlen/4}]
-       set chareno [expr {$char0no + $charlen -1}]
-       set repl [format %0${charlen}x $value]
-       set out [string replace $out $char0no $chareno $repl]
-    } else {
-       while {$bitlen > 0} {
-           set byteno [expr {$bit1 / 8}]
-           set char0no [expr {$byteno*2}]
-           set char1no [expr {$char0no+1}]
-           set bytebit [expr {128>>($bit1 % 8)}]
-           set byte 0x[string range $out $char0no $char1no]
-           debug 7 "< $bit1+$bitlen $byteno $char0no $bytebit $byte $out"
-           set byte [expr {
-               ($value & (1<<($bitlen-1)))
-               ? ($byte | $bytebit)
-               : ($byte & ~$bytebit)
-           }]
-           set out [string replace $out $char0no $char1no [format %02x $byte]]
+    proc assembly-overwrite {outvarname location value} {
+       upvar 1 $outvarname out
+       manyset $location bit1 bitlen diag
+ debug 8 "ASSEMBLY $diag == $value == 0x[format %x $value] (@$bit1+$bitlen)"
+       if {$bitlen < 32 && $value >= (1<<$bitlen)} {
+           error "$diag $value >= 2**$bitlen"
+       }
+       if {!($bit1 % 8) && !($bitlen % 8)} {
+           set char0no [expr {$bit1/4}]
+           set charlen [expr {$bitlen/4}]
+           set chareno [expr {$char0no + $charlen -1}]
+           set repl [format %0${charlen}x $value]
+           set out [string replace $out $char0no $chareno $repl]
+       } else {
+           while {$bitlen > 0} {
+               set byteno [expr {$bit1 / 8}]
+               set char0no [expr {$byteno*2}]
+               set char1no [expr {$char0no+1}]
+               set bytebit [expr {128>>($bit1 % 8)}]
+               set byte 0x[string range $out $char0no $char1no]
+               debug 7 "< $bit1+$bitlen $byteno $char0no $bytebit $byte $out"
+               set byte [expr {
+                   ($value & (1<<($bitlen-1)))
+                   ? ($byte | $bytebit)
+                   : ($byte & ~$bytebit)
+               }]
+               set out [string replace $out $char0no $char1no \
+                       [format %02x $byte]]
  debug 8 "> $bit1+$bitlen $byteno $char0no $bytebit 0x[format %02x $byte] $out"
-           incr bitlen -1
-           incr bit1
+               incr bitlen -1
+               incr bit1
+           }
        }
     }
 }
-
+namespace import Assembler::*
 
 proc gen_1_ip {mtu} {
     # RFC791
@@ -757,3 +784,17 @@ if {![llength $argv]} {
 } else {
     foreach count $argv { emit $count }
 }
+
+
+puts [::profiler::dump]
+
+puts ---------------------IWJ
+
+puts [::profiler::print]
+
+puts ---------------------IWJ
+
+foreach i [::profiler::sortFunctions totalRuntime] {
+    manyset $i f v
+    puts [::profiler::print $f]
+}