1. RE: [Windows] Associate file extensions with a program
- Posted by Chris Bensler <bensler at nt.net> Oct 13, 2004
- 445 views
Matt Lewis wrote: > > > posted by: Matt Lewis <matthewwalkerlewis at yahoo.com> > > Pete Lomax wrote: > > > > Juergen Luethje wrote: > > > > > I can see that implementation #1 is not a good idea, but what about > > > implementation #2? > > > > If there is an error in proc1, such as FileDoesNotExist, then it would > > not help matters to replace this with ErrorWritingToFile in proc2. > > > > In fact, wouldn't most error conditions tend to daisy-chain? > > Yes. It's important to allow for errors to propagate back up through > the call chain. I've done this a couple of different ways in EuSQL and > in matheval. In EuSQL, all functions return a sequence on success, and > an integer on failure. After pretty much every call from a library > routine to another, I check this condition, and simply return the error > code. There is also an extended error message that can be set, and that > an application can request. > > In matheval, I defined a separate type, called INVALID. Each matheval > type is smart enough to only operate on other types that it understands, > so the INVALID type is simply passed back. Part of the INVALID type is > an error message. > > Matt Lewis What you want is error trapping and exception handling. I've written a library to deal with this.. It's not perfect, because we can't bail out of the call stack, but otherwise, it's a good solution for error trapping. Note also, that error trapping puts the sanity tests into the routines that are actually making the errors. That is how it should be. Error trapping also keeps the routine's result unambiguous. here is a psuedo-example... ------------------------------------ allow_error_trapping(OFF) allow_pending_errors(OFF) constant ERR_FOPEN = define_error(NULL) function fopen(sequence name, sequence flags) integer fn if fn = -1 then throw_error(ERR_FOPEN,"Failed to open "&name&" with the flags: \'"*flags&"\'\n") end if return fn end function -- now I can do stuff like this.. integer fn1,fn2,fn3,fn4,fn5 fn1 = fopen("foo1.txt","rb") fn2 = fopen("foo2.txt","rb") fn3 = fopen("foo3.txt","rb") fn4 = fopen("foo4.txt","rb") fn5 = fopen("foo5.txt","rb") trap_error(ERR_FOPEN) ---------------------------------------- In that specific example, trap_error() is not even needed at all. If allow_error_trapping() is OFF, allow_pending_errors() has no affect. With allow_error_trapping(OFF), each error is thrown and called immmediately. throw_error() acts like a regular error msg routine. For example, if foo1.txt fails.. the error occurs immediately within fopen() With allow_error_trapping(ON), and allow_pending_errors(OFF), each error is thrown, but is not called unless an error is already pending. For example, if foo1.txt fails, and foo3.txt fails, the error will be thrown for foo1.txt when the error for foo3.txt is discovered. With allow_error_trapping(ON) and allow_pending_errors(ON), each error is thrown, and only called via trap_error() For example, if foo1.txt fails, and foo3.txt fails. Eu will still process each fopen statement. When it reaches, and calls trap_error(ERR_FOPEN), it checks for any pending errors, matching that ERR_FOPEN, and calls the first occurance. (An error would be instantiated for foo1.txt) The library does much more than I have described. Such as the ability to define custom error handlers for each error code, the ability to catch, drop, fetch and intercept exceptions, and some other lower level error routines. I'll share it with anyone interested. I'm not going to post it, because the code is written for my own libraries, and isn't compatible with the official rds libraries. There also isn't any documentation. If there is anyone interested, I can port it back for them, and whip up some docs. Chris Bensler Code is Alchemy
2. RE: [Windows] Associate file extensions with a program
- Posted by Matt Lewis <matthewwalkerlewis at yahoo.com> Oct 13, 2004
- 462 views
Chris Bensler wrote: > > What you want is error trapping and exception handling. > > I've written a library to deal with this.. > It's not perfect, because we can't bail out of the call stack, but > otherwise, it's a good solution for error trapping. > Note also, that error trapping puts the sanity tests into the routines > that are actually making the errors. That is how it should be. > Error trapping also keeps the routine's result unambiguous. > > here is a psuedo-example... > ------------------------------------ > allow_error_trapping(OFF) > allow_pending_errors(OFF) > > constant ERR_FOPEN = define_error(NULL) > function fopen(sequence name, sequence flags) > integer fn > if fn = -1 then > throw_error(ERR_FOPEN,"Failed to open "&name&" with the flags: > \'"*flags&"\'\n") > end if > return fn > end function > > -- now I can do stuff like this.. > integer fn1,fn2,fn3,fn4,fn5 > fn1 = fopen("foo1.txt","rb") > fn2 = fopen("foo2.txt","rb") > fn3 = fopen("foo3.txt","rb") > fn4 = fopen("foo4.txt","rb") > fn5 = fopen("foo5.txt","rb") > trap_error(ERR_FOPEN) > ---------------------------------------- > In that specific example, trap_error() is not even needed at all. > > If allow_error_trapping() is OFF, allow_pending_errors() has no affect. > > With allow_error_trapping(OFF), each error is thrown and called > immmediately. throw_error() acts like a regular error msg routine. > For example, if foo1.txt fails.. the error occurs immediately within > fopen() > > With allow_error_trapping(ON), and allow_pending_errors(OFF), each error > is thrown, but is not called unless an error is already pending. > For example, if foo1.txt fails, and foo3.txt fails, the error will be > thrown for foo1.txt when the error for foo3.txt is discovered. > > With allow_error_trapping(ON) and allow_pending_errors(ON), each error > is thrown, and only called via trap_error() > For example, if foo1.txt fails, and foo3.txt fails. > Eu will still process each fopen statement. When it reaches, and calls > trap_error(ERR_FOPEN), it checks for any pending errors, matching that > ERR_FOPEN, and calls the first occurance. (An error would be > instantiated for foo1.txt) This seems very similar with the error handling I use in EuSQL (except that it has to bail out of the call stack). There's even an 'automatic' way, using a user defined type (EUSQLRESULT), to get errors reported to the user, and this can cause the app to shut down or not (user-defined). I tend to use it for debugging and testing mostly, since it shuts down and allows me to see where things went wrong. I assume there must be a way to get at the error information in your library. How do you recover from an error (i.e., what would you do if foo1.txt didn't open, but you needed it to continue)? Matt Lewis
3. RE: [Windows] Associate file extensions with a program
- Posted by Chris Bensler <bensler at nt.net> Oct 13, 2004
- 456 views
Matt Lewis wrote: > > > posted by: Matt Lewis <matthewwalkerlewis at yahoo.com> > > Chris Bensler wrote: > > > > What you want is error trapping and exception handling. > > > > I've written a library to deal with this.. > > It's not perfect, because we can't bail out of the call stack, but > > otherwise, it's a good solution for error trapping. > > Note also, that error trapping puts the sanity tests into the routines > > that are actually making the errors. That is how it should be. > > Error trapping also keeps the routine's result unambiguous. > > > > here is a psuedo-example... > > > > constant ERR_FOPEN = define_error(NULL) > > function fopen(sequence name, sequence flags) > > integer fn > > if fn = -1 then > > throw_error(ERR_FOPEN,"Failed to open "&name&" with the flags: > > \'"*flags&"\'\n") > > end if > > return fn > > end function > > > > -- now I can do stuff like this.. > > integer fn1,fn2,fn3,fn4,fn5 > > fn1 = fopen("foo1.txt","rb") > > fn2 = fopen("foo2.txt","rb") > > fn3 = fopen("foo3.txt","rb") > > fn4 = fopen("foo4.txt","rb") > > fn5 = fopen("foo5.txt","rb") > > trap_error(ERR_FOPEN) > > > > If allow_error_trapping() is OFF, allow_pending_errors() has no affect. > > > > With allow_error_trapping(OFF), each error is thrown and called > > immmediately. throw_error() acts like a regular error msg routine. > > For example, if foo1.txt fails.. the error occurs immediately within > > fopen() > > > > With allow_error_trapping(ON), and allow_pending_errors(OFF), each error > > is thrown, but is not called unless an error is already pending. > > For example, if foo1.txt fails, and foo3.txt fails, the error will be > > thrown for foo1.txt when the error for foo3.txt is discovered. > > > > With allow_error_trapping(ON) and allow_pending_errors(ON), each error > > is thrown, and only called via trap_error() > > For example, if foo1.txt fails, and foo3.txt fails. > > Eu will still process each fopen statement. When it reaches, and calls > > trap_error(ERR_FOPEN), it checks for any pending errors, matching that > > ERR_FOPEN, and calls the first occurance. (An error would be > > instantiated for foo1.txt) > > This seems very similar with the error handling I use in EuSQL (except > that it has to bail out of the call stack). There's even an 'automatic' > > way, using a user defined type (EUSQLRESULT), to get errors reported to > the user, and this can cause the app to shut down or not (user-defined). > > I tend to use it for debugging and testing mostly, since it shuts down > and allows me to see where things went wrong. > > I assume there must be a way to get at the error information in your > library. How do you recover from an error (i.e., what would you do if > foo1.txt didn't open, but you needed it to continue)? > > Matt Lewis My library is based on top of a lower level error library. The error library includes routines such as fatal_error() and error(). error() is a user definable error routine. By default it calls fatal_error(). Very much like you are describing Matt. If I wanted to make sure that foo1.txt was successful before opening foo2.. I could set allow_error_trapping(ON) -- throw errors, but don't call them. This allows the exception to fall through the stack, to the next statement. After opening foo1.txt, I can call trap_error(ERR_FOPEN). That would check the exception stack, and call the error handler immediately. If I just want to check if there is a pending error, without actually calling the error handler, I can use catch_error(ERR_FOPEN) if catch_error(ERR_FOPEN) then if some_special_condition then -- ignore this error errval = fetch_error(ERR_FOPEN) -- get the error data if drop_error(ERR_FOPEN) then end if else -- call the error handler trap_error(ERR_FOPEN) end if end if If there is an error that I wish to simply ignore. I can just use drop_error(). fn1 = fopen("foo1.txt","rb") if drop_error(ERR_FOPEN) then -- an error was encountered end if Chris Bensler Code is Alchemy