milne@ICS.UCI.EDU (Alastair Milne) (12/15/89)
Our project is moving a number of its CAI programs from UCSD Pascal (under the p-System, of course) to Turbo Pascal 5.0. Though it has gone much more smoothly overall than one might have expected, a few hard problems keep coming up. A couple have already been addressed by some people on this group, so I have some hope for this one: UCSD Pascal defines the call "EXIT(procedure-name);", where procedure-name must be one of the procedures currently running -- that is, it must have a stack-frame currently allocated somewhere up the call stack. EXIT exits the local procedure and every calling procedure until it reaches and exits "procedure-name". Each procedure exited first has its "termination code" executed, which usually is either empty or makes sure any local files are properly closed. This means that, in exceptional situations, major chunks of code can be exited at the option of local routines, without actually halting the whole program. Turbo Pascal gives only, as far as I know, EXIT (which exits the immediate block, but nothing further) and HALT (which kills the whole program). Does anybody know of a way in Turbo Pascal to obtain the effect of UCSD Pascal's EXIT? Alastair Milne, Programming Manager, Educational Techology Center
al@crucible.UUCP (Al Evans) (12/15/89)
In article <8912141752.aa23459@ICS.UCI.EDU> milne@ICS.UCI.EDU (Alastair Milne) writes: [description of need for multi-level "EXIT" deleted....] > Turbo Pascal gives only, as far as I know, EXIT (which exits the immediate > block, but nothing further) and HALT (which kills the whole program). > Does anybody know of a way in Turbo Pascal to obtain the effect of UCSD > Pascal's EXIT? I wish there were. Actually, in UCSD, I think you can even exit procedures that HAVEN'T been called -- this gives interesting results. I do things as shown below, in about 60K lines of Pascal that exists under both Turbo and UCSD (don't ask:-). PROCEDURE BigBlock VAR exitFlag: BOOLEAN; PROCEDURE SubProcA; BEGIN ... {Condition requiring exit from main block found} exitFlag:= TRUE; EXIT; ... END; PROCEDURE SubProcB; BEGIN ... SubProcA; IF exitFlag THEN EXIT; ... END; BEGIN {BigBlock} exitFlag:= FALSE; ... SubProcB; IF exitFlag THEN EXIT; ... END; It ain't pretty, but it's the only way I've found to accomplish a multilevel exit under Turbo Pascal. --Al Evans-- -- Al Evans "You'd grep to know what ...uunet!execu!sequoia!crucible!al you really sed." --Referent Blob
d88-eli@nada.kth.se (Erik Liljencrantz) (12/17/89)
In article <122@crucible.UUCP> al@crucible.UUCP (Al Evans) writes: >In article <8912141752.aa23459@ICS.UCI.EDU> milne@ICS.UCI.EDU (Alastair Milne) writes: >[description of need for multi-level "EXIT" deleted....] >> Turbo Pascal gives only, as far as I know, EXIT (which exits the immediate >> block, but nothing further) and HALT (which kills the whole program). >> Does anybody know of a way in Turbo Pascal to obtain the effect of UCSD >> Pascal's EXIT? >I wish there were. Actually, in UCSD, I think you can even exit procedures >that HAVEN'T been called -- this gives interesting results. I do things >as shown below, in about 60K lines of Pascal that exists under both Turbo and >UCSD (don't ask:-). >[code with boolean exitflag deleted] >It ain't pretty, but it's the only way I've found to accomplish a multilevel >exit under Turbo Pascal. >... >Al Evans "You'd grep to know what >...uunet!execu!sequoia!crucible!al you really sed." > --Referent Blob In C there are a standard method of exiting from several levels of calls. setjmp and longjmp works together to accomplish this. A call to setjmp saves the state of the stack (i.e. SP) and some registers (only BP needed for Turbo) and a returnaddress just after setjmp. A call to longjmp from a deeper level restores the stack and BP and jumps to the setjmp location. This would be possible to accomplish in Turbo Pascal too (just a little assembler). A small example of how it could work: Declarations: FUNCTION SetJmp (Buffer:Save_SP_BP_CS_IP_Record):INTEGER; { Return 0 when explicitly called, or ReturnValue from LongJmp if LongJmp is used. } PROCEDURE LongJmp(Buffer:Save_SP_BP_CS_IP_Record; ReturnValue:INTEGER); { Buffer must have been initialized by a previous call to SetJmp. ReturnValue is the result for SetJmp. It shouldn't be 0 (reserved for explicit call to SetJmp). } Usage: PROGRAM JustATest; USES The_Imaginary_SetJmp_And_LongJmp_Unit; VAR ReturnToMainLoop:Save_SP_BP_CS_IP_Record; PROCEDURE NoReturn; BEGIN LongJmp(ReturnToMainLoop,1); { Transfer control to the mainloop! (Two level exit) } END; PROCEDURE DoSomething; BEGIN NoReturn; WriteLn('It never happens'); END; BEGIN IF SetJmp(ReturnToMainLoop)<>0 THEN BEGIN { SetJmp returns 0 on initialization or something else if LongJmp was called. } WriteLn('A call to LongJmp returned control here!'); END; REPEAT { Never ending main loop } CASE UpCase(ReadKey) OF 'D':DoSomething; 'Q':Halt; END; UNTIL FALSE; END. Well, I hope you get the idea... This isn't a multilevel exit, but it's a method to jump back in the call-chain at least. In C it can be used to exit callingchains when an error is encountered. I hope I will be able to find some time to write the procedures. If you are interested, just email! Comments? Email them too! -- Erik Liljencrantz | "No silly quotes!!" d88-eli@nada.kth.se | Embraquel D. Tuta
d88-eli@nada.kth.se (Erik Liljencrantz) (12/18/89)
I mentioned SetJmp and LongJmp in a previous posting. Now they exist! They can be used like this to accomplish multilevel exit: VAR ErrorOccured:Jmp_Buf; PROCEDURE WantToExit; BEGIN ... LongJmp(ErrorOccured,1); { Instead of Exit } ... END; PROCEDURE Demo; BEGIN IF SetJmp(ErrorOccured)<>0 THEN BEGIN ... { LongJmp(ErrorOccured,1) will arrive here } Exit; { Exit out of this function too } END; ... WantToExit; ... END; Below is a uuencoded version of jmpunit.zoo. Contents: jmpunit.pas Pascal unit source jmpunit.asm Assembly source for SetJmp and LongJmp jmpunit.obj Assembled jmpunit.asm testjmp.pas Demonstration program (very short) Send your comments (and new nice ideas) to me... --- Erik Liljencrantz | "No silly quotes!!" d88-eli@nada.kth.se | Embraquel D. Tuta begin 644 jmpunit.zoo M6D]/(#(N,#`@07)C:&EV92X:``#<I\3]*@```-;___\"``$````````!W*?$ M_0(!N`0``'$```"1$S>-+*4&"```1P0```$```````````!J;7!U;FET+F%S M;0!T"@!_84D`````````````0"DC*```J22APJ0(B(,'E;2!4\5-&CH-%$3< M`>**G(=TRK@!(28/B"(7UX!@DH:-&HUCY(1Q0T</B!@W0!`I,Z9,&S%EY+S, M@2-'Q(D@II2AHQ`.B)5D1KYQ<Z8HB#MOY*R9<Y0J'31ETN@<`F+,FSHL<\() M(X?.'!<_%5!DDF1($2=3BN@`4;3APZ-NDCX\077.5SDUO9(I`R(-5:QRRG0$ M069IF(Q)Z;P!<94PG#IBV*09P_A-FS!IW*!5BS#+5Q"?/9I)7(:-QSISRK#H M^@:.1Z2,#=.Y**9.1LI808"]&X8JFZ5GJ@(G["9,&\)OS``]6!E$U#1G0H=A M<]0WFJ@@4(!,(Y*D290J6>I)49AJZ#%LZ@Q.&D;,&SME1D=D\F1($"93(`0" M$$"D19$1:;1&!E71+0>"&@M]T9L9("3FE1QD1/3%%%`(B%`1453AX4$H7/&$ M%$2```454H``0PH:"M'AB""*.&*))Z:X8HLRP*C`%T,$2&.((X9G(HHJL@@" M#3Y^D<2,'M98)(Y([@B"#3Y&-,031!CD85Q'-/$6%2`(D045!D%1A1!L#1%1 MD0@%,<4458AY4)`Z;-FE@494X<00`CWAQ$%"$;50>%8$T:(0=9AA1DXZ3!$& M?E/0\5@94M`4%1DIZ)"$$V@>4804.Z15J%,(02%%?R`8H6A$:K+9EH"G+O0F MG"`T\80510J!!0L<W@IG04)Z2$02P$ZAPQ:^KD!#%\(6J2NO(P;Q*X>XCKC# M$4,%!46TU1*18K6_XI"MMD-L-T8=;%SJ+0AF@#?&=FSD!*Z'TQ99A+);'-N% M"QM"P8*UVDJ*7V%T%+9145\P*IT"V>9+([_^`BPC"S+>*Z#$'EJ;[++-R@`M MQ+AR+."^RU8,Y!0#8Z$Q0B;'>2V_OHX<\:[Z4IS$OTX*;.W+!V%Q8I$>$WPN M0CL8`=88=*2Q5&)SL)LP#$"#($419(Y(0T2U&O6A$T1\*Y%:JO97!!%57*T4 M4T6AX/"C<D0Z:1F57IKIA610E&G4;-#A*:A%B"I%"J6.S01RJ*JX*E>N2@'K MFFT*>#C;MI(,9\P'^0JLV#=3V_',(&/A;!=P;MLMU%)7/331OQI]-`@[-!'& M&H1%G1C"?('@QE)ZY/1&U4HXH461!`8AQU=Y5?TI5^2^[N$.221\1W$@]'Y\ M"%8/58<<&\6@\!P9A4'&:,4?#Q89<Q%;Y+$?,RNZ#:07:7K"<+P16D8Z208" M^.Y:N&G5F"N3P%#6KYU9#$I(VYMD;I<QRTD+9R,:PJ\(J+(@%:P,9W@.2R@S M&0D"$(+&FJ#.>/8D;3W!4;%)F/Z(X#('CBB`'&(!!0T8,&TI,"J$"98+/:2F M*2`A@EAPGH!V``78H&%_&-0@1'8HH![^,(1"1%H1YW#$Z)@AA56[6M:BB*L= M9(H.V]N(_N8PMZ3@Z4G[0=RA#O*6L*5%3UXZ&=BF$)$V1D0#`0'<I\3]`@': M!0``_P0``)$34H_`7N(```#;`````0```````````&IM<'5N:70N;V)J`'0* M`'](T0````````````!`*2,H```!-0"P0$D3*%6<)*'B(LB4)C(0@0!`D4H= M.6+>@`@R9TZ9-F+8E)$#`H25D7/2O'$#(H8+&#$0(9H``$BZ&XTB32AX,.'" MA@\G(1I0,QT32P(HHK%D``"!(4^(%"F"Z0``%$<`"`@0P!VD@0`"&)A2A(I! M*!0!)(+D@&*``TR>.#ERU@3%#H@(U!05(!*H)6$I+N)F@]@?`HN(%4``P$2B M`H[;"+"QZ(@`QT4(4#Z`V<`,8,KT#J9\A,`"8'4"`"G\QX")19)?-R'PNHKK M126B2%F&25%2`'0"`MRGQ/T"`7`(```A!@``D1-;AW/\`0,``$\"```!```` M````````:FUP=6YI="YP87,`=`H`?[&9`````````````$`I(R@``*LX24*E M@0(0()2T@5/%31HZ.PP:W`/BBIR'=,JX`2$F#X@B%]>`8)*&C1J-8^2$<4-' M#X@8-T`0*3.F3!LQ9>2\S($C!X@^$A50G%*&CD(X(%:2&?G&S9FC(.Z\D;-F M3E*K=-"42:-S"(@Q;^JPS`DGC!PZ<US\G`B"BAR/5(I,H:*D"1074(),`6%F M:E(09&PVG4-')9TT34&@*.QQ3AJG;,H0+@,'SN,S41^B`9&U#.`R8NJ<.9,S MA5J@"M@R23*DB),I170D7-CP85(W2Q^>L#HGK)R:8`.#2&-5JQS0'LDT#9-Q M*9TWG+6"@%-'#)LT8P"_:1/FL0N#"!%F"0N"NT<SQ\NP\5AG3AD67]_`\:@4 M,/'":4)GC.Y9K.TP5K'1%&8`\@>"&V&TX=D;9H`77F<@3)7&&8^%P492=63E M%PH@I2$222:AI!)+>J0PG%6/C<%&'8$M%888;]A1QFE!)>%$7%(8$41K05&1 M!11%.'C4%T+4848/4A0QQ!-2$.$@0E-`P8(04@XQ!0M)0*'#%4P2$=%!'SGA M95!&"#0$%4D\X02414&%@A5!2`%"D6:8D9,.0]*9@@XVQG5$$5)\"8443[1& M1!5),N7442C0::<<>"Y$I)$[@""%9'6P00>?-Q;QIQ0I?&E0$G8Q4403KE$1 M!)IJDFDFJVN"0)11"RD&IYR.WIFGD7OVZ2F@E1:!!8Y.!,&$H(0:BF@1BCZU M4*-&/AHI').:4>FE<V2ZJ:^?AOK1L(`6>^Q$)#`Q&T,.T8&:0:X1\9T"&@0$ MW*?$_0(!?PH``+<(``"1$T2/+;ME`@``R`$```$```````````!T97-T:FUP M+G!A<P!T"@!_:\T`````````````0"DC*```H4AY<D1*D"8@J)290T=)&S@[ M&BB0N`>$E3)R\H"8TR8,&S8@X,AY<T9.F#8@Z+Q)N9!.2C1A7-)!4P:$0SA5 MW*1Q>>>-G#5S0(1Q0P8$F3)MWKAA:)).&8D@-J9YR*9FG3EASM1\8P;$E#(- M'PHE"H*)TC,W78#H(Y%B0IHA1Y8\">).FH]QT[AQ*<*L&[1B[X0).L9C53(A M1-2EZ0:$G#INU+*=J*`B$:0K[<[<^*:.G#$UCXJI<T:K'!U0O8(%(49.F3!K MX+S1ZQ+%$#IRV+0P@B.%4#-.Y;RL61BO2M5AX8!`,;/F%3D[RS!IS#`FTC)[ M4[A(/47OF:H,RRA'8>2&[YDC2:,9'I>DR3:2VRJH,J7(E-0W<^Z,2-E*$"FI M"5&'&69@I,--7PAH!G\2"?3$$$40484418!`Q!M3O-$&6&AXQY\011R1A!.I M^048'"@H6*`<+,0`0PK\%>$$$0PJ`**()"H051)&('=3B@.NF`(//L"0$!(R M@G#CB*E%]5QTTZ%P@HDWU348",4=%L(),$8%0D5?N=3::['-MM=RM^6V6V\@ MT.1:""&LU20(1>"Q7VHRTIC:A1EN.).'$N6YG0(:!`3<I\3]`@`````````` K``````````````````````````````````````````````````````#\@P`` ` end -- Erik Liljencrantz | "No silly quotes!!" d88-eli@nada.kth.se | Embraquel D. Tuta
scl@sasha.acc.Virginia.EDU (Steve Losen) (12/18/89)
In article <8912141752.aa23459@ICS.UCI.EDU> milne@ICS.UCI.EDU (Alastair Milne) writes [description of need for multi-level "EXIT" deleted....] > Turbo Pascal gives only, as far as I know, EXIT (which exits the immediate > block, but nothing further) and HALT (which kills the whole program). > Does anybody know of a way in Turbo Pascal to obtain the effect of UCSD Doesn't turbo allow non-local gotos, which are in the current ISO standard and have been a Pascal feature since the beginning? You can declare a label in an outer block and jump to it from an inner block. This terminates the activation of the inner block and all intervening activations back to the most recent activation of the outer block. Execution of the outer block resumes at the goto target label. This may not be as flexible as the UCSD exit. You can only non-locally goto a block that encloses the current block. Furthermore, the target statement must be at the outermost nesting level of the block (eg, you cannot jump into a "for", "while", "if", etc. statement.). For years folks have used this for emergency error termination. You declare a label in the main program and place it near the final "end.". Any block that hasn't redeclared the label can jump back to the main program for a clean exit. You could also use this technique in a deeply nested menu driven application to jump back to the code that displays top of the main menu. Steve Losen scl@virginia.edu University of Virginia Academic Computing Center
tris@alzabo.uucp (Tris Orendorff) (12/19/89)
milne@ICS.UCI.EDU (Alastair Milne) writes: > Turbo Pascal gives only, as far as I know, EXIT (which exits the immediate > block, but nothing further) and HALT (which kills the whole program). > Does anybody know of a way in Turbo Pascal to obtain the effect of UCSD > Pascal's EXIT? This Month's issue of PC Magazine (V8, Number 22) has an implementation of setjmp() and longjmp () for Turbo Pascal on page 298. This should do the trick. -- Sincerely Yours Tris Orendorff tris@alzabo.uucp -----------------------------------------------------------------------
schrader@loligo (David F. Schrader) (12/19/89)
In article <1989Dec18.132328.6049@murdoch.acc.Virginia.EDU> scl@sasha.acc.Virginia.EDU (Steve Losen) writes: > >In article <8912141752.aa23459@ICS.UCI.EDU> milne@ICS.UCI.EDU (Alastair >Milne) writes > > [description of need for multi-level "EXIT" deleted....] > >> Turbo Pascal gives only, as far as I know, EXIT (which exits the immediate >> block, but nothing further) and HALT (which kills the whole program). >> Does anybody know of a way in Turbo Pascal to obtain the effect of UCSD > > [followup note deleted...] I am not sure that I have followed the entire thread of this sequence but I believe that what you want to do is possible (at TP5.0/TP5.5 levels at least). I do not know whether this is supported before TP5.n . Check TP5.0 (and by extension TP5.5) Reference Guide Chapter 15, page 229, regarding _Exit Procedures_. TP5.0 supports an _ExitProc_ pointer which points to a procedure (w/o parameters) which is to be executed upon exit from a program (and program "unit"). By saving, replacing, and later restoring, the pointer it is possible to "chain" these _Exit Procedure_s. The _Exit Procedure_ must be compiled in _Far_ call model ({$F+}/{$F-}). The brief example that provide is: PROGRAM Testexit; VAR ExitSave : pointer; {$F+} PROCEDURE MyExit; BEGIN ExitProc := ExitSave; : END; {MyExit} {$F-) BEGIN {Main/Testexit} ExitSave := ExitProc; ExitProc := @MyExit; : END. {Main/Testexit} Note that the manuals is much more expansive in their coverage. Please read this(these) page(s) before committing yourself to this particular method as I cannot guarentee this is the solution you are seeking (particularly since I am coming in in the middle of the thread...). Hope that this helps. David F. Schrader Disclaimer : FSUCC - "No comment." ; ME - "I reserve the right to qualify what I said if necessary."