gnuerr

Usually, when an error is to be signalled, error command is to do the job. However, what it prints to standard error when used in scripts doesn't conform to Unix conventions, which require an error message to be preceded by the program name and a colon, e. g.:

 foo: unrecognized option `--bar'

 bar: file: No such file or directory

Here is suggested a simple gnuerr command to print error messages, similar to the GNU C Library error function. Of course, it's only useful in applications which aren't interactive (or which support non-interactive mode at least.) That is, in CLI applications.

Variable
program-short-name

This variable holds the tail element of the program path, argv0, i. e.:

 file tail $::argv0

It's put before the error message itself by the following procedures.

Procedure
gnuerr ?-exit returnCode? formatString ?arg arg ...?

Prints an error message to stderr. The message consists of the program name, followed by a colon, a space, and the result of applying format to the formatString and the remaining arguments. If the message to be printed contains embedded newlines, each line of the message will be prepended by the program name on output.

If the returnCode is given and non-zero, the procedure pass it to exit after the message is printed.

TODO List:

  • parse errorCode (if requested) and print POSIX error message after the message printed;
  • something like error_at_line could be useful as well.
 ### gnuerr.tcl  -*- Tcl -*-
 ## The following code is in public domain.

 ### Code:

 namespace eval ::gnuerr {
     variable program-short-name \
         [ expr { [ info exists  ::argv0 ]
                  ? [ file tail $::argv0 ]
                  : "" } ]
     namespace export gnuerr
 }

 proc ::gnuerr::prefix-lines { prefix text } {
     set result ""
     ## .
     append result \
        $prefix [ string map [ list "\n" "\n${prefix}" ] $text ]
 }

 proc ::gnuerr::msg { formatString args } {
     variable program-short-name
     set s [ uplevel \#0 [ list ::format $formatString ] $args ]
     puts stderr [ prefix-lines "${program-short-name}: " $s ]
 }

 proc ::gnuerr::gnuerr { args } {
     if { [ llength $args ] < 1 } {
         error [ format "wrong # args: should be \"gnuerr %s\"" \
                     "?-exit returnCode? formatString ?arg arg ...?" ]
     } elseif { ! [ string equal "-exit" [ lindex $args 0 ] ] } {
         set exit 0
     } elseif { [ llength $args ] < 2 } {
         error "expected argument after \"-exit\""
     } elseif { [ set exit [ lindex $args 1 ]
                  catch { incr exit 0 } ] } {
         error "expected integer but got \"$exit\""
     } else {
         set args [ lrange $args 2 end ]
     }
     eval msg $args
     ## .
     if { $exit } {
         exit $exit
     }
 }

 package provide gnuerr 0.1

 ### gnuerr.tcl ends here

Category Package