If your program does not use tasks, you can define an exception that signifies an "emergency exit"; perhaps in some package:
package Emergency is
Emergency_Exit : exception;
end Emergency;
In your main procedure, catch this exception:
procedure Your_Main_Procedure is
begin
... whatever the main procedure does
exception
when Emergency.Emergency_Exit =>
null;
end Your_Main_Procedure;
So that whenever you raise the exception somewhere in your program:
raise Emergency_Exit;
it will transfer control to the null
statement, which will then reach the end of the main procedure and exit the program.
Doing it this way means you can add cleanup code to other procedures:
procedure Something_Else is
...
begin
Direct_IO_Instance.Open (Some_File, Direct_IO_Instance.Out_File, "filename");
begin
... do your work
exception
when Emergency.Emergency_Exit =>
-- cleanup
Finish_Writing (Some_File);
Direct_IO_Instance.Close (Some_File);
-- now reraise, which will eventually reach the end of the program
raise;
end;
end Something_Else;
So when Emergency_Exit
is raised, it will eventually transfer control to the end of the main procedure, but it might stop off in other exception handlers along the way to do any needed cleanup.
I don't think this works if there are other tasks running, because the main procedure will wait for those other tasks to complete before the program exits. In that case, in Ada 83, you'll need to coordinate the exit with the other tasks; perhaps you can define a global Boolean that those tasks check periodically to get them to exit, or perhaps you can structure the program in a way so that the Emergency_Exit
exception handler knows what tasks to abort, or can call a task entry to get those tasks to terminate. The best solution would depend on the actual program structure.