%{ #!/usr/bin/tclsh # Counts characters, words, and lines, with support for multiple # filenames. # This is based upon example 'ch2-03.l' from "lex & yacc" by John # R. Levine, Tony Mason, and Doug Brown (by O'Reilly & Associates, ISBN # 1-56592-000-7). For more information on using lex and yacc, see # http://www.oreilly.com/catalog/lex/. set charCount 0 set wordCount 0 set lineCount 0 %} %option noheaders word [^ \t\n]+ eol \n %% {word} { incr ::wordCount; incr ::charCount $yyleng } {eol} { incr ::charCount; incr ::lineCount } . { incr ::charCount } %% # lexer calls yywrap to handle EOF conditions (e.g., to # connect to a new file, as we do in this case.) proc yywrap {} { set file "" if {$::currentFile != 0 && $::nFiles > 1 && $::currentFile < $::nFiles} { # print out statstics for previous file puts [format "%8u %8u %8u %s" $::lineCount $::wordCount $::charCount \ [lindex $::fileList [expr {$::currentFile - 1}]]] incr ::totalCC $::charCount incr ::totalWC $::wordCount incr ::totalLC $::lineCount set ::charCount 0 set ::wordCount 0 set ::lineCount 0 close $::yyin } while {$::currentFile < $::nFiles} { if {[catch {open [lindex $::fileList $::currentFile] r} file]} { puts stderr "could not open [lindex $::fileList $::currentFile]" incr ::currentFile } else { set ::yyin $file incr ::currentFile break } } if {$file != ""} { return 0 ;# 0 means there's more input } else { return 1 } } set fileList "" set currentFile 0 set nFiles 0 set totalCC 0 set totalWC 0 set totalLC 0 set fileList $argv set nFiles [llength $argv] if {[llength $argv] == 1} { # handle single file case differenly since we don't need to print a # summary line set currentFile 1 if {[catch {open [lindex $argv 0] r} file]} { puts stderr "could not open file [lindex $argv 0]" exit 1 } set yyin $file } if {[llength $argv] > 1} { yywrap } yylex # handle zero or one file differently from multiple files if {[llength $argv] > 1} { puts [format "%8u %8u %8u %s" $lineCount $wordCount $charCount \ [lindex $argv [expr {$currentFile - 1}]]] incr totalCC $charCount incr totalWC $wordCount incr totalLC $lineCount puts [format "%8u %8u %8u total" $totalLC $totalWC $totalCC] } else { puts [format "%8u %8u %8u" $lineCount $wordCount $charCount] } return 0