-1

All, Need a suggestion for the following. Before i commit the new tcl procs in cvs, i want to check if the new procs which is being committed has duplicate name of pre-existing tcl procs. If there is duplicate in the name, we can abort the commit.

Thanks in advance.

user245011
  • 65
  • 1
  • 9
  • I find your description a little confusing. Could you show us some code that demonstrates what you're trying to do? The code doesn't have to work yet; the answerers will tell you how to fix it… – Donal Fellows May 23 '14 at 17:44
  • Sorry about that. Let me try to explain again. 1- I want to write a python/bash script and call it as part of pre-commit(commitinfo). 2- I dont know how to pass the cvs diff to the pre-commit script, so that i can find the new proc being added from diff and scan through the repository to find the duplicate proc name. – user245011 May 23 '14 at 17:52
  • 1
    is it important to detect duplicates across files, or only duplicates within a single file? – Bryan Oakley May 23 '14 at 17:52
  • Yes i need to detect to the duplicate across files residing in multiple directories. – user245011 May 23 '14 at 18:02

2 Answers2

0

You can do that with a dict to check for duplicates:

dict exists $hash procName
dict append hash procName value

So

if ![dict exists $hash procName] {dict append hash procName value}
beautifulcoder
  • 10,832
  • 3
  • 19
  • 29
  • Thanks for your response. Let me clarify my question little bit. I want to call python/bash script in cvs commitinfo, which will find out the proc in cvs diff and check for duplicate proc names and warn accordingly. – user245011 May 23 '14 at 17:45
  • OK, your description mentions Tcl. Python has a similar data structure for this. – beautifulcoder May 23 '14 at 18:46
  • My cvs repository is tcl and i am trying to avoid duplicate procs in tcl. I want to detect the duplicate when the user is trying to commit the tcl code. I am trying to find out, how do we pass the diff to the commitinfo script(which can be python/bash) – user245011 May 23 '14 at 20:56
  • and why not Tcl? Tcl is the best language to parse Tcl. – Johannes Kuhn May 24 '14 at 10:40
  • I am open to any language. I love tcl which has been feeding me for a while :) – user245011 May 24 '14 at 16:49
0

Well, instead of using bash or python, I suggest using Tcl itself to do that. I assume that you have Tcl 8.5 or higher.

The basic idea is to use an interpreter which ignores most commands except proc definitions.

set ip [interp create]
interp hide $ip source
interp eval $ip {
    rename ::tcl::info::frame tcl:info:frame
}
interp hide $ip tcl:info:frame
interp eval $ip {
    namespace delete ::
}
proc NOP args {}
interp alias $ip unknown {} NOP

Now we need to handle some commands in a special way:

proc qualify-cmd {name} {
    return $name
}

proc proc-alias {name arg body} {
    define-cmd [qualify-cmd $name]
}
interp alias $ip proc {} proc-alias

proc define-cmd {name} {
   global procs
   set frameinfo [interp invokehidden $::ip tcl:info:frame 1]
   if {[dict get $frameinfo type] eq "source"} {
      set file [dict get $frameinfo file]
      set line [dict get $frameinfo line]
   } else {
      set file "<unknown>"
      set line 0
   }
   if {[dict exists $procs $name]} {
       set ofile [dict get $procs $name file]
       set oline [dict get $procs $name line]
       return -code error "proc redefiniton of $name in $file line $line (original $ofile line $oline)"
   } else {
       dict set procs $name file $file
       dict set procs $name line $line
   }
}
# Load the old definitions
set procs {}

# Now we have to source changed file in the slave interp

proc checkfile {file} {
    global procs
    dict for {name val} $procs {
        if {[dict get $val file] eq $file} {
            dict unset procs $name
        }
    }
    interp invokehidden $ip source foobar.tcl
}

The rest is the hardest work, but I'm not sure if it is needed for you:

  • namespaces. You have to handle the namespace command and modify qualify-cmd.
  • branches. Someone could define a command inside if or while etc.
  • variables. This solution is not bulletproof. If someone uses variables outside of an proc, this will fail. You could try and catch the error, set the variable and try again. (And that's why I want unknownvar)
Johannes Kuhn
  • 14,778
  • 4
  • 49
  • 73