Path: utzoo!mnetor!uunet!portal!atari!apratt From: apratt@atari.UUCP (Allan Pratt) Newsgroups: comp.sys.atari.st Subject: Re: C and autostarting GEM programs Message-ID: <1018@atari.UUCP> Date: 17 Mar 88 19:15:47 GMT References: <176@bdt.UUCP> Organization: Atari Corp., Sunnyvale CA Lines: 83 From article <176@bdt.UUCP>, by david@bdt.UUCP (David Beckemeyer): > In article <1008@atari.UUCP> apratt@atari.UUCP (Allan Pratt) writes: >>It *is* just a simple longjmp! (Except that it gets executed in Super >>mode -- but the handler can just consist of a longjmp.) If you have a... > > If the Pterm handler consists of just a longjmp, doesn't that mean that the > supervisor stack is permanently shrinking, and that the program thereafter > runs in supervisor mode, even if it was started in user mode? Wouldn't > that mean that a lot (maybe not so many) ^C's would use up all the supervisor > stack? You misunderstand me. By "Pterm handler" I meant the thing YOU might install to catch bombs, Pterm's, and ^C's yourself. *Of course* Pterm is more complicated than that in Gemdos: it has to free your memory, close your files, and so on. If you want to execute some procedure (like removing your vblank routine) when you get ^C, bombs, or Pterm, you should install the address of that procedure as the terminate vector. When Pterm gets hit (for any of these reasons), your handler will get called (via jsr, in super mode), and when it returns, the Pterm continues and terminates the process. This is what Sid does when it says "Bye!" -- that's the terminate handler talking. If you are a shell and you want to return to your command prompt when the user hits ^C, you have to be a little more clever: you make the terminate vector point to a routine which does a go-to-user-mode-and-longjmp operation. The target of the longjmp is responsible for recovering from the problem. Simply put, it could look like this: #include #include jmp_buf err_buf; long old_terminate_value; main_loop() { char cmdbuf[258]; int terminate_handler(); old_terminate_value = Setexc(0x102,terminate_handler); if (setjmp(err_buf)) { /* this code is target of longjmp */ Cconws("*Break*\r\n"); } /* normal flow and longjmp both end up here */ cmdbuf[0] = 255; while (1) { Cconws(prompt_string); Cconrs(cmdbuf); cmdbuf[cmdbuf[1]+2] = 0; /* null-terminate the string */ do_cmdline(&cmdbuf[2]); } } terminate_handler() { longjmp(err_buf,-1); } exit_command() { Setexc(0x102,old_terminate_value); Pterm(0); } The above fragments assume that setjmp saves the SR of the caller and restores it for the longjmp... This is a nontrivial thing to do because you can't just use RTE from user mode. The exit_command fragment is here to show that you have to UN-install the vector before you Pterm, because otherwise it'll just get hit again. Does this make anything more clear? ============================================ Opinions expressed above do not necessarily -- Allan Pratt, Atari Corp. reflect those of Atari Corp. or anyone else. ...ames!atari!apratt