sgxCP | : | Code Profiling |
sgxCT | : | Code Tracing |
sgxDbg | : | Debug procedures |
sgxRSM | : | Resource Standard Metrics |
sgxTVC | : | Test Variable Consistency |
sgxCP © is a package profiling procedures to check runtime behaviour.
sgxCT © is a package tracing selected procedures and giving basic counters and dependencies of applications.
sgxDbg © is a package containing useful procedures to debug.
sgxRSM © is a package creating basic source metrics to check code quality.
sgxTVC © is a package checking declaration and usage of variables to validate code.
These packages have been written as development supporting tools to a large scale network management extension system called SoftGuard ®.
All packages are running on Linux, Unix (FreeBSD, SunOS, HP-UX ...), Microsoft Windows (NT 4/95/98/ME/2000/...).
sgxTools (© 1998 - 2001) are based on Tcl/Tk 8.#. sgxRSM and sgxTVC should support Tcl 7.x, too; best to use with TkCon 1.# or 2.#.
To unpack sgxTools-#.#.tgz distribution file on Microsoft Windows systems use e.g. WinZip.)
This software is copyrighted by S. Finzel (finzel@osn.de) and other parties. The following terms apply to all files associated with the software unless explicitly disclaimed in individual files.
The authors hereby grant permission to use, copy, modify, distribute, and license this software and its documentation for any purpose, provided that existing copyright notices are retained in all copies and that this notice is included verbatim in any distributions. No written agreement, license, or royalty fee is required for any of the authorized uses. Modifications to this software may be copyrighted by their authors and need not follow the licensing terms described here, provided that the new terms are clearly indicated on the first page of each file where they apply.
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
GOVERNMENT USE: If you are acquiring this software on behalf of the U.S. government, the Government shall have only "Restricted Rights" in the software and related documentation as defined in the Federal Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are acquiring the software on behalf of the Department of Defense, the software shall be classified as "Commercial Computer Software" and the Government shall have only "Restricted Rights" as defined in Clause 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the authors grant the U.S. Government and others acting in its behalf permission to use and distribute the software in accordance with the terms specified in this license.
Simply download and unpack the distribution file sgxTools-2.1.tgz (size is about 30 kB) to any directory XXX after installing and checking Tcl/Tk. This distribution file is supporting all previously mentioned operating systems.
Have a look at test/test_YYY.tcl how to start a package sgxYYY without the need of changing your code.
Have a look at the examples at end of each package lib/YYY.tcl or test/test_yyy.tcl how to statically integrate a package YYY to your code.
sgxCP has been derived from ::profiler (tcllib). Only minor changes have been made to make it usable for older Tcl versions (>= 8.0) and print out never used procedures. The time is now measured in machine dependant [clock clicks / 1000] not in milliseconds as used by ::profiler.
sgxCP can be run against your code without changing any line. Of
cause, you'll be able to integerate it in your code too.
tclsh8.2
% lappend auto_path .
% package require sgxCP 1.0
% ::sgxCP::init
% source [file join . test test_ct.dat]
% puts stderr [::sgxCP::print]
Profiling information for ::BANG
-------------------------
Total calls: 1
Caller distribution:
1 ::ping
Compile time: 12951
Total runtime: 12951
Average runtime: 12951
Runtime StDev: 0
Runtime cov(%): 0
Total descendant time: 0
Average descendant time: 0
Descendants:
none
Profiling information for ::ping
-------------------------
Total calls: 4
Caller distribution:
1 ::pingpong
3 ::pong
Compile time: 13772
Total runtime: 58592
Average runtime: 14648
Runtime StDev: 960
Runtime cov(%): 6.6
Total descendant time: 56580
Average descendant time: 14145
Descendants:
1 ::BANG
3 ::pong
Profiling information for ::pingpong
-------------------------
Total calls: 1
Caller distribution:
1 test/test_ct.dat
Compile time: 16499
Total runtime: 16499
Average runtime: 16499
Runtime StDev: 0
Runtime cov(%): 0
Total descendant time: 15998
Average descendant time: 15998
Descendants:
1 ::ping
Profiling information for ::pong
-------------------------
Total calls: 3
Caller distribution:
3 ::ping
Compile time: 14166
Total runtime: 43629
Average runtime: 14543
Runtime StDev: 367
Runtime cov(%): 2.5
Total descendant time: 42594
Average descendant time: 14198
Descendants:
3 ::ping
Never used: 1 proc(s)
::pongping
This package has been derived of the internal handling of ::profiler (tcllib).
Please be aware sgxCT is procedure based. It'll not handle internal commands at all. Although it is very useful to check an applications call structure at runtime.
sgxCT can be run against your code without changing any line. Of cause, you'll be able to integerate it in your code too.
The following example will run sgxCT against the test file and show the
results of the procedure based trace and the summary.
It'll initialize tracing, source and trace a file. Every procedure created after
first call of ::sgxCT::Init can be traced. Every procedure matching the given
regular expression of the last call of ::sgxCT::Init will be traced. You are
able to print short trace summaries using ::sgxCT::Summary for all procedures
matching the given regular expression. Use ::sgxCT::Reset to reset all data for
all procedures matching the given regular expression.
tclsh8.2
% lappend auto_path .
% package require sgxCT 1.0
% ::sgxCT::Init {p.*g} stderr
% source [file join . test test_ct.dat]
% ::sgxCT::Summary {p.*g}
% ::sgxCT::Reset {p.*g}
proc BANG {args} {
puts stdout "\n\tBANG\t${args}\n"
return BANG
}
proc ping {i} {
if {${i} <= 3} {
pong ${i}
} else {
BANG ${i}
}
}
proc pong {o} {
ping [expr {${o} + 1}]
return ${o}
}
proc pingpong {{io 1}} {
ping ${io}
}
proc pongping {{oi 1}} {
pong ${oi}
}
pingpong
# Call Trace regexp: 'p.*g'
mode level proc args/return
call 1 ::pingpong
call 2 ::ping 1
call 3 ::pong 1
call 4 ::ping 2
call 5 ::pong 2
call 6 ::ping 3
call 7 ::pong 3
call 8 ::ping 4
BANG 4
return 8 ::ping BANG
return 7 ::pong 3
return 6 ::ping 3
return 5 ::pong 2
return 4 ::ping 2
return 3 ::pong 1
return 2 ::ping 1
return 1 ::pingpong 1
# Call Trace Summary regexp: 'p.*g'
# called:
4 ::ping
1 ::pingpong
3 ::pong
# caller:
4 ::ping
1 ::pingpong
3 ::pong
# callings:
1 ::ping ::BANG
3 ::ping ::pong
1 ::pingpong ::ping
3 ::pong ::ping
1 ./test/test_ct.dat ::pingpong
# unused:
0 ::pongping
As the procedure ::BANG is not matching the given regular expression for
::sgxCT::Init and ::sgxCT::Summary it is neither traced
nor listed as called or as unused. But the calling from ::ping to ::BANG
has to be listed as ::ping" is matching.
You are able to change the summary by de-/activating it's parts setting array ::sgxCT::sgxCT(list_ZZZ) to 0/1.
list_ZZZ | Description |
---|---|
list_called | 0/1=do not/ list all called procedures matching regular expression |
list_caller | 0/1=do not/ list all caller procedures matching regular expression |
list_callings | 0/1=do not/ list all calling pairs of procedures matching regular expression |
list_calls | 0/1=do not/ list all unused procedures matching regular expression |
Set ::sgxCT::sgxCT(enabled) to 0/1 to temporarly stop/restart code tracing.
sgxTVC can be run against your code without changing any line. Of cause, you'll be able to integerate it in your code too.
Both sgxRSM and sgxTVC require clean code.
First check your code using procheck
and second beautify your code with
frink
prior using sgxRSM and sgxTVC.
The following example will run sgxTVC against the test file and show the
results of the check.
tclsh8.2
% lappend auto_path .
% package require sgxTVC 1.0
% ::sgxTVC::_Files_ [file join test test_tvc.dat]
# ==============================================================================
# test_tvc.dat --
#
# test_tvc.dat: file to test variable(s) consistency
#
# Copyright (c) 2000 by T&E Soft, Stefan G. R. Finzel <finzel@osn.de>.
# All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: sgxTools.html,v 1.7 2002/08/12 18:57:37 fis Exp $
# ==============================================================================
# ------------------------------------------------------------------------------
# test_tvc --
# test some common consistency issues
# Arguments:
# unused_00 an unused variable
# proc an unused variable and bad style variable name
# args another unused variable, but warning is disabled by comment
# Results:
# None.
# ------------------------------------------------------------------------------
# Document proc parameters and variables outside of proc to avoid mistakes
# variables xxx_01, ... xxx_99 will be complained
# variables var_a, ... var_z will not be complained
# variables err_A, ... err_Z should be complained, but won't
# variable var is a dummy
# some constructs avoid warnings using TclPro (-Wall)
# examples marked by *) considered as bad style programming
# ------------------------------------------------------------------------------
proc test_tvc {{unused_00 {}} {proc {}} args} {
# --------------------------------------------------------------------------
# test some common code snippets using non existing variables
# --------------------------------------------------------------------------
# In most cases it is more convenient to write "set [set var] ..." or
# "set ${var} ..." instead of "set [subst ${var}] ..." but procheck will
# complain "set ${var} ...".
# "set [set var] ..." will be accepted by procheck, frink and sgxTVC.
# So, we use "set [subst ${var}] ..." for the tests.
# --------------------------------------------------------------------------
# Usage of undefined variable(s)
# --------------------------------------------------------------------------
# ${undef_01} : Comments are also checked, to maintain unused code too;
# This may cause problems using some command names within comments!
variable [subst ${undef_02}]
unset [subst ${undef_03}]
upvar #1 ${undef_04} var
global [subst ${undef_05}] var
set [subst ${undef_06}] {}
set var [list ${undef_07}]
append [subst ${undef_08}] {}
lappend [subst ${undef_09}] {}
if {${undef_10}} {
break
}
foreach [list var ${undef_11}] [list var ${undef_12}] {
break
}
for {set var 0} {${undef_13}} {incr undef_14} {
break
}
# ..........................................................................
# Use of a variables name after unsetting
# ..........................................................................
unset undef_15
set var ${undef_15}
set undef_15 {}
# ..........................................................................
# existence of variable
# ..........................................................................
set var [array names undef_16]
info exists undef_17
# ..........................................................................
# a var used to define itself in the same command
# ..........................................................................
set undef_18 ${undef_18}
# --------------------------------------------------------------------------
# bad style name(s) of variable(s)
# --------------------------------------------------------------------------
# ..........................................................................
# *) I don't like to use identical names for commands and variables either.
# They will also complained as unused.
# ..........................................................................
# It depends on the loaded packages whether a variables name is complained or not.
# e.g.: as "text" is a Tk built-in command it'll be complained running the
# sgxTVC package in Tcl/Tk but NOT in a raw Tcl interpreter.
# ..........................................................................
append append {}
lappend lappend {}
set set {}
incr incr
# --------------------------------------------------------------------------
# never used variable(s)
# --------------------------------------------------------------------------
# ..........................................................................
# *) I don't like to use 'undefined' variables at all and decided to
# write a prior definition like 'set var {}' every time
# ..........................................................................
append unused_01 {}
lappend unused_02 {}
# ..........................................................................
# The following snippets are correct tcl;
# ..........................................................................
global unused_03 var
variable unused_04
# ..........................................................................
# It'll be good style to initialize this vars before using it:
# ..........................................................................
regexp -nocase -- {xyz} ${var} unused_05
regsub -- {xyz} ${var} {123} unused_06
scan ${var} {%s} unused_07
# --------------------------------------------------------------------------
# Some examples of tests that will fail, altough they shouldn't:
# --------------------------------------------------------------------------
# ..........................................................................
# array elements are not handled at all
# ..........................................................................
set err_A(B) {}
unset err_A(C)
# ..........................................................................
# *) a loop that's never executed, but the created var is used later on
# ..........................................................................
foreach var {} {
set err_D ${var}
}
set var ${err_D}
# --------------------------------------------------------------------------
# Use comments to avoid warnings:
# --------------------------------------------------------------------------
# ..........................................................................
# to avoid warnings from (very) special code use comments before a variables
# first usage or after a variables last modification, like
#
# FRINK: set var_a / var_b / var_c by foreach
#
# Beware any comment including the variables name will be accepted!
# ..........................................................................
foreach [string tolower {var_A var_B var_C}] {1 2 3} {
expr {${var_a} + ${var_b} + ${var_c}}
}
# ..........................................................................
# FRINK: set var_D by for
# ..........................................................................
for {set var_D 0} {${var_D} < 10} {incr var_D} {break}
# ..........................................................................
# something like a pointer
# ..........................................................................
set var var_a
set var_a {}
# ..........................................................................
# FRINK: ${var_a} will never be used: this comment will avoid the warning
# ..........................................................................
set var [subst $${var}]
# ..........................................................................
# another trick to avoid warnings is to enclosure command names in brackets
# ..........................................................................
set var [list {global} {set} {upvar} {variable}]
# ..........................................................................
# FRINK: ${args} was not used so far, don't complain
# ..........................................................................
return {}
}
test_tvc error undef_01 variable undefined
test_tvc error undef_02 variable undefined
test_tvc error undef_03 variable undefined
test_tvc error undef_04 variable undefined
test_tvc error undef_05 variable undefined
test_tvc error undef_06 variable undefined
test_tvc error undef_07 variable undefined
test_tvc error undef_08 variable undefined
test_tvc error undef_09 variable undefined
test_tvc error undef_10 variable undefined
test_tvc error undef_11 variable undefined
test_tvc error undef_12 variable undefined
test_tvc error undef_13 variable undefined
test_tvc error undef_18 variable undefined
test_tvc error undef_14 variable undefined used by incr
test_tvc error undef_15 variable undefined used by unset
test_tvc error undef_16 variable undefined used by array
test_tvc error undef_17 variable undefined used by info
test_tvc warning append bad style variable
test_tvc warning lappend bad style variable
test_tvc warning incr bad style variable
test_tvc error unused_01 variable undefined used by append
test_tvc error unused_02 variable undefined used by lappend
test_tvc error unused_00 argument unused
test_tvc error proc argument unused
test_tvc warning proc bad style argument
test_tvc error append variable unused
test_tvc warning append bad style variable
test_tvc error lappend variable unused
test_tvc warning lappend bad style variable
test_tvc warning set bad style variable
test_tvc error incr variable unused
test_tvc warning incr bad style variable
test_tvc error unused_01 variable unused
test_tvc error unused_02 variable unused
test_tvc error unused_03 variable unused
test_tvc error unused_04 variable unused
test_tvc error unused_05 variable unused
test_tvc error unused_06 variable unused
test_tvc error unused_07 variable unused
As there are three different routines to check, the order of the messages does not fit the order of the lines of code.
sgxRSM was inspired by Resource Standard Metrics © for C, C++ and Java by M Squared Technologies. I really advice their RSM tool and web page.
sgxRSM can be run against your code without changing any line. Of cause, you'll be able to integerate it in your code too.
The example will run sgxRSM against the same test file and show
the results of the check.
tclsh8.2
% lappend auto_path .
% package require sgxRSM 1.0
% ::sgxRSM::_Files_ [file join test test_tvc.dat]
# ------------------------------------------------
Proc : test_tvc
FPM : 3 FRPM : 1 FC : 22
LOC : 142 eLOC : 57 SCUM : 149.1%
Calls: 62
3 append
1 array
3 break
1 expr
1 for
3 foreach
3 global
1 if
2 incr
1 info
3 lappend
4 list
1 regexp
1 regsub
1 return
1 scan
16 set
1 string
7 subst
3 unset
2 upvar
3 variable
# ------------------------------------------------
# ================================================
RSM Summary
total values
CCM : 1
FPM : 3 FRPM : 1 FC : 22
LOC : 142 eLOC : 57
mean values
FPM : 3.0 FRPM : 1.0 FC : 22.0
LOC : 142.0 eLOC : 57.0 SCUM : 149.1%
Calls: 62
3 append
1 array
3 break
1 expr
1 for
3 foreach
3 global
1 if
2 incr
1 info
3 lappend
4 list
1 regexp
1 regsub
1 return
1 scan
16 set
1 string
7 subst
3 unset
2 upvar
3 variable
# ================================================
Now what's the meaning of the abbreviations?
Abb. | Meaning | Description |
---|---|---|
Calls | number of all calls | number of all calls |
CCM | command count metrics | number of checked procs |
FPM | function parameter metric | number of proc arguments |
FRPM | function return point metric | number of returns and exits |
FC | function calls | number of unique proc calls |
LOC | lines of code | total lines including blank lines and comment lines |
eLOC | effective lines of code | code lines excluding blank lines or comment lines |
SCUM | source code understandability metrics | ((comment lines + blank lines) / eLOC ) * 100 |
sgxRSM is checking only procedures but no flat code or namespace declarations. To check against rules define your private limits or change some other settings in the file test/sgxRSM.tcl.
sgxTVC : The interpretation of comments will be changed in future, to use same pragmas as used by frink written by Lindsay Marshall.