home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #26 / NN_1992_26.iso / spool / comp / sys / acorn / tech / 584 < prev    next >
Encoding:
Text File  |  1992-11-11  |  6.4 KB  |  137 lines

  1. Newsgroups: comp.sys.acorn.tech
  2. Path: sparky!uunet!charon.amdahl.com!pacbell.com!ames!agate!doc.ic.ac.uk!mrccrc!warwick!pavo.csi.cam.ac.uk!jubilex!crj10
  3. From: crj10@phx.cam.ac.uk (Clive Jones)
  4. Subject: Re: Exception handling in C.
  5. In-Reply-To: bwc@waikato.ac.nz (Ug!)'s message of 9 Nov 92 13:50:23 +1300
  6. Message-ID: <1992Nov11.223824.9107@infodev.cam.ac.uk>
  7. Telephone-Messages: +44 223 33 4900
  8. Sender: news@infodev.cam.ac.uk (USENET news)
  9. Address: Christ's College, Cambridge CB2 3BU, ENGLAND.
  10. Nntp-Posting-Host: bourn.cl.cam.ac.uk
  11. Organization: 6am Digital Playground
  12. X-Furry-Character: Gerald_Duck
  13. References: <1992Nov9.135023.12048@waikato.ac.nz>
  14. Date: Wed, 11 Nov 1992 22:38:24 GMT
  15. Lines: 120
  16.  
  17. In article <1992Nov9.135023.12048@waikato.ac.nz>, bwc@waikato.ac.nz (Ug!) writes:
  18. > I'd like to discuss a few things about what I am implementing at the moment,
  19. > first among them being the issue of exception handling in C.
  20.  
  21. I will have exception handling available Real Soon Now in Desktop C. I intend
  22. to release it into the public domain, as part of a package of extra 'primitives'
  23. to alter the flow of control in C programs (or, I suppose, Pascal, or other
  24. APCS languages).
  25.  
  26. The complete package will contain:
  27.   Coroutines
  28.   Vectors
  29.   Exceptions
  30.   (and possibly) Timer-activated pre-emptive triggering of functions.
  31. The combination of coroutines and pre-emptive function calls obviously combine
  32. to provide pre-emptive multitasking WITHIN a C program.
  33.  
  34. > Exception handling is always a messy business, and C doesn't cope
  35. > particularly well with it, although in fact I've yet to meet a language
  36. > which does.
  37.  
  38. C has *no* explicit mechanism for passing exceptions around in your programs -
  39. it only provides the signal and errno interfaces to the standard library and
  40. operating system. A cynic might say that even those are only there to aid
  41. portability, and not for the tidier programming style they engender. (-8
  42.  
  43. Exceptions are handled well, IMO, by Modula-3, PL/1 and BBC Basic 4. Admittedly,
  44. the LOCAL/RESTORE ERROR pair of commands are primitive, but they do the
  45. business. Look at the other two languages as well if you want some ideas for
  46. nice exception systems.
  47.  
  48. [...] 
  49. > *  exceptions should be interceptable.  For instance, if I call a routine
  50. >    to open a file, and the routine raises an exception if that file doesn't
  51. >    exist, then an error message may not always be appropriate for that
  52. >    situation.  I should be able to intercept that exception, and in this
  53. >    case, decide not to raise an error.
  54.  
  55. In other words, you should be able to locally handle exceptions, as well as
  56. having the global handlers. This is, to my mind, the vital difference between
  57. a proper exceptions mechanism and a simple signal system.
  58.  
  59. > *  exceptions should not alter the normal flow of code.  If you allow
  60. >    an exception to land you somewhere else in the program, then you end
  61. >    up with a mess that makes spaghetti look friendly.  Instead, exceptions
  62. >    should be coped with in a manner resembling interrupt handlers.
  63.  
  64. The two halves of that seem to contradict. I agree with the first half, which
  65. basically means that an exception shouldn't let you go somewhere you couldn't
  66. go with a longjmp(), for example. However, this seems to contradict the idea of
  67. it behaving like an interrupt - i.e. calling some function when an exception
  68. occurs, thus breaking the normal flow of control.
  69.  
  70. > Those were my base ideas for handling exceptions.  What I came up with was
  71. > essentially each module registering a handler with an 'error' module.  The
  72. > most recent registered handler is passed the exception first.  If it doesn't
  73. > handle the exception, then the next most recent handler is called, and so on.
  74.  
  75. Fair enough, for some uses...
  76.  
  77. > How do other people cope with exceptions?  Is there something I'm missing?
  78. > I've noticed that my way of doing adds the additional ability to cope well
  79. > with internationalisation, which is an added bonus.
  80.  
  81. The structure I decided upon was as follows:
  82.  
  83.   1) Each module can produce some anomalous circumstances. Classify these, and
  84.      you ought to have "exception classes". Try and arrange it so that each of
  85.      these exceptions can be expressed by a pointer to a struct, or similar.
  86.  
  87.   2) For each of these, provide an extern function pointer to a handler. By
  88.      default, have this pointing at something which just generates a textual
  89.      error message, and passes it to an error handler function (which is just
  90.      another extern function pointer, but one which is always fed a char *).
  91.      The default function on this 'hook' should print the message to stderr and
  92.      exit.
  93.  
  94.   3) NOW - each module is standalone, and doesn't rely on any given exception
  95.      mechanism. This means that in simple programs, you can forgo ANY exception
  96.      system and save space. It also means that someone else can come along with
  97.      their own pet exception handling system and bolt it on instead. However,
  98.      then also supply...
  99.  
  100.   4) An exceptions mechanism. Provide a standard function exception_raise(),
  101.      for example, which can be set as the handler function for all the
  102.      anomalous situations in any appropriate modules. Also provide an
  103.      exception_handle() function, akin to setjmp(), which returns NULL when
  104.      called directly, but a pointer to an exception if one is returned via
  105.      it. Bind this up in some 'syntactic sugar' such as:
  106.        #define try { if (exception_handle())
  107.        #define except else { switch (exception_type())
  108.        #define endtry exception_passon(); } exception_unhandle(); }
  109.      ...so that you can catch exceptions in a tidy structure of the form:
  110.        try
  111.         {
  112.          f = openfile("Spong", "r");
  113.         }
  114.        except
  115.         {
  116.          case ex_FILENOTFOUND:
  117.            ...
  118.         }
  119.        endtry
  120.  
  121.      (Try substituting the macros above to see roughly how that would work!)
  122.  
  123.      Your exception_raise() function should then backtrace the stack until it
  124.      finds an exception handler, and then call it. If it hits the end of the
  125.      program, it should call some default function. You can use longjmp if
  126.      you're not brave enough to write some assembler to do this.
  127.  
  128.   5) For added spice, you could actually attach a vector to each of the
  129.      anomalous condition handlers instead, and put the exception mechanism as
  130.      one of the claimants of the vector. You could then do cunning things like
  131.      report the exception to a different coroutine if the generating
  132.      coroutine didn't handle it, etc. - you get the idea.
  133.  
  134. Hope this is of *some* interest,         
  135.  
  136. --Clive.
  137.