TheHobbit has asked for the wisdom of the Perl Monks concerning the following question:

Greetings fellows monks,
Today (as seen from here) I posted a question readline error behavior. Answers same to point me to return undef and set $!. This in turn raises another question. Here it is.

Looking at perlvar it appears that $! can be set, so setting the underlying C variable errno. Nevertheless, this only takes into account the numeric side of $!.

If one affects to $! a number not defined in errno.h, the stringification of $! gives Unknown error n, where n is the numerical value of $!.

Is it possible to modify the stringification of $! (obviously without touching at the perl intrpreter code) to include user-defined messages?

Obviouly I'd like to have these custom messages localized accordigly to the locale setted by the user.

Am I daydreaming in hoping there is a way to achieve this?

Thanks for helping


Leo TheHobbit

Replies are listed 'Best First'.
Re: Setting $! to custom values
by Abigail-II (Bishop) on Nov 03, 2003 at 22:36 UTC
    Is it possible to modify the stringification of $! (obviously without touching at the perl intrpreter code) to include user-defined messages?

    Not in pure Perl. It's probably possible in XS.

    Obviouly I'd like to have these custom messages localized accordigly to the locale setted by the user.
    Do you have to use $! for that? You can freely assign to $@.

    Abigail

Re: Setting $! to custom values
by belg4mit (Prior) on Nov 04, 2003 at 00:16 UTC
    What's wrong with die?
    do {} or die $ERR{DO}; #Where %ERR is locale specific
    See block eval.

    --
    I'm not belgian but I play one on TV.

Re: Setting $! to custom values
by diotalevi (Canon) on Nov 03, 2003 at 22:59 UTC
    $! is intended as a system error indicator - as in the system that is external to perl. If things fail inside perl then $! isn't where you should be noting that. Set $@ instead - that's meant to be used within perl.
      No, please no. $@ is for eval errors. Not user-level errors. When you mix those up, you make it much harder to program for evals.

      Please, don't be like the IO::* Modules. Wrong.

      -- Randal L. Schwartz, Perl hacker
      Be sure to read my standard disclaimer if this is a reply.


      Update: Note the docs on this:
      $@ The Perl syntax error message from the last eval() operato +r. If $@ is the null string, the last eval() parsed and executed correctly (although the operations you invoked may have fa +iled in the normal fashion). (Mnemonic: Where was the syntax er +ror "at"?) Warning messages are not collected in this variable. You c +an, however, set up a routine to process warnings by setting $SIG{__WARN__} as described below. Also see "Error Indicators".
      Nowhere does it say that it's for user errors. And if you set $@ in the middle of your code, you lose the eval error!

        I'm not sure I see your point. How exactly do you define a "user-level" error?

        What is the significant difference between the two subs in the following code?

        sub foo { eval { my $m = shift; die $m; }; return; } sub bar { my $m = shift; $@ = $m . ' at ' . __FILE__ . ' line ' . __LINE__ . "\n"; return } foo("foo message"); print "foo $@"; bar("bar message"); print "bar $@";
        It seems to me that whenever you use die() to throw exceptions expecting (or requiring) your users to use eval() to catch those exceptions you are, essentially, just setting $@ for them.

        I don't see how it could hurt anything to set it explicitly as long as you document that your code uses it to return an error. That's not to say I'm a fan of this approach (I'm not), but I am suspicious of your claim that it would "make it much harder to program for evals."

        And if you set $@ in the middle of your code, you lose the eval error!

        But, if you want to rely on $@, you had better inspect it immediately after your eval() anyway. That is, unless you trust everyone else's code to always localize $@ and be free from compile time errors in their eval BLOCKs.

        -sauoq
        "My two cents aren't worth a dime.";
        
        Of course $@ is for user errors! That's the entire point behind putting useful messages or objects into die. Just because I didn't use die() to set $@ (and trigger the exception handler, if any) doesn't mean I'm not intending for $@ to be a place to look for my error.
Re: Setting $! to custom values
by welchavw (Pilgrim) on Nov 04, 2003 at 17:04 UTC

    Leo,

    Please bear with me for a second as I think out loud. You are trying to overload IO::File and are overloading getline. The inconvenience is that getline's error reporting method relies on $! and you apparently can't "fit" your errors into the set specified by the errnos (and the set cannot be expanded without XS, and probably shouldn't be expanded anyway). In other words, IO::File has proven impractical for your class to inherit from because of a too restrictive error reporting mechanism.

    In my opinion, this means that you should not be inheriting from IO::File. Your class must report errors in a way not contemplated by the designers of IO::File. In my opinion, your class and IO::File can not be associated by an ISA relationship, due to this mismatch. In my opinion (and I am no expert on IO::File, so I truly apologize if I misconstrue), one of the apparent implications of the error reporting design of IO::File is that classes that need to report errors beyond "OS errors" cannot really inherit from the class. I would backtrack, redesign your inheritance tree, perhaps document this experience and chalk it up to learning "the hard way" a limitation of IO::File.

    ,welchavw