From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,8183b99d3c85c57b X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 2003-11-04 16:13:14 PST Path: archiver1.google.com!news2.google.com!news.maxwell.syr.edu!skynet.be!skynet.be!skynet.be!skynet.be!louie!tlk!not-for-mail Sender: lbrenta@lbrenta Newsgroups: comp.lang.ada Subject: Re: Handling Exceptions? References: From: Ludovic Brenta Date: 05 Nov 2003 01:13:13 +0100 Message-ID: User-Agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.2 MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Organization: -= Belgacom Usenet Service =- NNTP-Posting-Host: 217.136.27.120 X-Trace: 1067991193 reader1.news.skynet.be 29035 217.136.27.120:38674 X-Complaints-To: usenet-abuse@skynet.be Xref: archiver1.google.com comp.lang.ada:2061 Date: 2003-11-05T01:13:13+01:00 List-Id: Freejack writes: > I've recently switched back to using Adasockets for my programming needs. > > I never bothered to catch exceptions before, since none of my apps were > really that important. So, to get a little practice I slung together the > following program(in about 5 minutes.) using Adasockets. > > The problem is that the compiler will let me use the exceptions declared > in the first declaritive part but not the second declaritive part. > > Any pointers would be appreciated. The exception handler is the portion of your code comprised between the "exception" keyword and the next "end;" or "end loop;" statement. Thus, after a casual reading of your code, here are my comments: > with Sockets; > with Sockets.Naming; > with Ada.Text_IO; > with Ada.Numerics.Discrete_Random; > procedure newconn is > -- Or "Learning to use exceptions the right way." -- > package TIO renames Ada.Text_IO; > package SockNames renames Sockets.Naming; > NameQuery : String := "www.yahoo.com"; -- Line Filler -- > HostIP : SockNames.Address; > HostImage : String(1..14); > LocalHost : String := "127.0.0.1"; > LocalIP : String := ""; > begin > -- This code left over from an cut+paste operation -- > -- And it still works. -- > HostIP := SockNames.Address_Of(NameQuery); > HostImage := SockNames.Image(HostIP); > TIO.Put_Line(HostImage); > ----------------------------------------------------- > declare > Site: Sockets.Socket_FD; > use Sockets; > begin > > Socket(Site, AF_INET, SOCK_STREAM); > Connect(Site, LocalHost, 9); -- Discard service -- > exception > when Connection_Refused => > TIO.Put_Line("Connection Refused."); > when others => > TIO.Put_Line("Something else went wrong"); > Sockets.Shutdown(Site, Both); > end; Here ends your first exception handler. So far, so good. Note however that you only call Sockets.Shutdown when handling "others", contrary to what your indentation seems to suggest. > declare > Echo : Sockets.Socket_FD; > EchoString : String(1..10); > EchoResponse : String(1..10); -- Could get less. Wont get more than 10 -- > use Sockets; > > -- This may look a little fruity, but I just wanna see if it'll work. -- > package RandChar is new Ada.Numerics.Discrete_Random(Character); > use RandChar; > G : Generator; > > begin > Socket(Echo, AF_INET, SOCK_STREAM); > Connect(Echo, LocalIP, 7); > exception > when Connection_Refused => > TIO.Put_Line("Connection Refused"); > exit; > when others => > Sockets.Shutdown(Echo, Both); > TIO.Put_Line("There was a problem connecting to Echo"); > exit; All of the code after this point is dead code because of the "exit" statement above, but, although your indentation seems to imply otherwise, the exception handler for "others" really continues here. > -- Loop a bunch of times and send a bunch of shit to Echo. -- > -- And get a bunch of shit back. -- > > EchoString := "1234567890"; > Reset(G); > > for X in 1..EchoString'Length loop > -- First we send the String. -- > Put(Echo, EchoString); > exception > when Connection_Closed => > TIO.Put_Line("Connection Closed Prematurely"); > TIO.Put_Line("Terminating Application."); > Shutdown(Echo, Both); > exit; -- This should break us out of the loop? -- > -- Then we get it back. -- Again, the "exit" statement does not end this exception handler. You need "end" or "end loop". We are still within the dead code. > EchoResponse := Get_Line(Echo, 10); > exception > when Connection_Closed => > TIO.Put_Line("Peer Closed Connection before sending whole line"); > TIO.Put_Line("Got characters" & EchoResponse &"."); > TIO.Put_Line("Terminating Application."); > Shutdown(Echo, Both); > exit; > > -- Now we modify our string a bit(or a byte, pun intended) -- > EchoString(X) := Random(G); > end loop; > Shutdown(Echo, Both); > end; Now this really ends your second exception handler. > end newconn; The RM and the Rationale recommend that you indent the "exception" keyword at the same level as the "begin" keyword, like this: declare -- declarations begin -- statements exception when others => -- statements end; This better reflects the grammatical structure for exception handlers. If you need to execute several statements with different handlers, you need several "begin" blocks. You did this properly for the first exception handler, not for the ones that follow. HTH -- Ludovic Brenta.