Path: utzoo!utgpu!jarvis.csri.toronto.edu!rutgers!cs.utexas.edu!usc!csun!csuna!abcscnuk From: abcscnuk@csuna.csun.edu (Naoto Kimura) Newsgroups: comp.lang.pascal Subject: Re: Turbo and Standard Pascal Message-ID: <2075@csuna.csun.edu> Date: 9 Jul 89 20:08:25 GMT References: <20172@adm.BRL.MIL> <4822@freja.diku.dk> <4249@eos.UUCP> Reply-To: abcscnuk@csuna.csun.edu (Naoto Kimura) Organization: CSU Northridge Lines: 230 In article <4249@eos.UUCP> woody@aurora.UUCP (Wayne Wood) writes: >In article <4822@freja.diku.dk> dat0@rimfaxe.diku.dk (Dat-0 undervisningsassistent) writes: >>texbell!utafll!john@cs.utexas.edu (John Baima) writes: >> >>>Turbo Pascal does (as of version 5.0) allow Procedures as parameters. >>>They have implemented a Procedure type which I believe goes beyond >>>"stansard" pascal. With the @ operator in version 4.0, it was easy to >>>pass procedures as parameters anyway. >> >>Right, you can do it, but you still can't do it the standard way. ("Oh there >>he goes again"). Can anyone tell me, why it wasn't implemented in such a >>way as to let standard programs compile without any trouble. >>It can't be that hard to do. >> > >i've been using Turbo since version 3.0 [still not very long] and i have always >been able to pass procedures and functions as parameters to other >procedures/functions. and i learned to do it in UCSD PASCAL, it worked the >same for me in both languages. > >refer to OH! PASCAL [author name escapes me] for more information. > >-- woody >%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% >%% ...tongue tied and twisted, just an earthbound misfit, I... %% >%% -- David Gilmour, Pink Floyd %% >%% woody@aurora.arc.nasa.gov %% my opinions,like my mind,are my own %% >%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% The question was not whether you can or cannot, it was that you can't do it in the standard method. BTW, for those who might be making the mistake that several people had made a couple of years back (when this same discussion came about in this newsgroup the last time), what is meant by procedural and functional parameters, it does not mean passing the value returned by a function to a procedure or function. In other words, It's not something like: y := sin(deg2rad(x)); which is passing the value returned by deg2rad() to sin(). An assembly language equivalent of the above would go something like this: mov ax,[word x+4] push ax mov ax,[word x+2] push ax mov ax,[word x] push ax call deg2rad ; evaluate deg2rad(x) push dx push bx push ax call sin ; send return value off to sin(x) mov [word y],dx ; store value into 'y' mov [word y+2],bx mov [word y+4],ax Passing a procedure or function to another procedure or function means basically at the low level, the address of the procedure or function being passed is passed to the called procedure or function. The called procedure then uses the address to perform an indirect call to the passed procedure or function: PROC comparison ARG Key1:DWORD,Key2:DWORD ... ... ret ENDP PROC sort ARG list:DWORD,compare:DWORD LOCAL Temp1:DWORD,Temp2:DWORD ... ; see if we need to swap records mov ax,[Temp1] push ax mov ax,[Temp2] push ax call far [compare] jnc NoSwap ; swap records ... NoSwap: ... ... ret ENDP PROC caller ... push ds mov ax,List push ax push cs mov ax,ptr comparison push ax call sort ... ret ENDP To get back to the discussion, Turbo pascal will not compile the following (the standard method of passing procedural and functional parameters): program bleah(output); procedure ugh( argh : integer ); begin writeln('ugh: passed parameter = ',argh) end; procedure plbbt( yuck : integer ); begin writeln('plbbt: passed parameter = ',yuck) end; procedure oof( procedure foo ( bar : integer ); ick : integer ); begin writeln('oof: calling passed procedure'); foo(ick) end; begin oof(ugh,3); oof(plbbt,5) end. To do the above in Turbo pascal, you have to resort to using inline machine code (some of the code may be incorrect -- I haven't used version 3.0 for a while...). You can continue to do the same sort of thing in versions 4.0 and 5.0, except that with those versions you have to worry about far references. Unfortunately, there was no checking to see if the function or procedure that was passed had the correct number and types of parameters. program bleah(output); {for each kind of procedure or function you want to pass as a parameter, you'll need to build a similar procedure or function} procedure indirect ( parm : integer; proc : integer ); { ^^^^^^^^^^^^^^^ parameters to be passed should come before the address of procedure to be called, this makes calling the procedure easier } begin inline( {I don't have it available with me right now, but it went something like the following (in assembly)} {mov sp,bp ; get rid of local variables} {pop bp ; restore bp} {pop ax ; grab return address} {pop bx ; grab address to routine} {push ax ; put return address back on stack} {jmp near [bx] ; jump to routine -- let it handle stack cleanup} ) end; procedure ugh( argh : integer ); begin writeln('ugh: passed parameter = ',argh) end; procedure plbbt( yuck : integer ); begin writeln('plbbt: passed parameter = ',yuck) end; procedure illegal; begin writeln('this should screw up the stack !') end; procedure oof( foo : integer; ick : integer ); begin writeln('oof: calling passed procedure'); indirect(ick,foo) end; begin oof(addr(ugh),3); oof(addr(plbbt),5); (* The following should cause some problems with the stack *) (* since calling the 'indirect' procedure will cause an *) (* integer parameter to be passed on the stack, which is *) (* expected to be cleaned up by the procedure it jumps to. *) (* But 'illegal' will not, so it ends up leaving an extra *) (* word on the stack. This would cause procedure 'oof' to *) (* use that value as the return address when it performs a *) (* 'ret' instruction *) oof(addr(illegal),0) end. Version 5.0 introduced the ability to pass procedures and functions as parameters without having to resort to inline code, though in a non-standard way. program bleah(output); type procparm = procedure ( iarg : integer ); procedure ugh( argh : integer ); begin writeln('ugh: passed parameter = ',argh) end; procedure plbbt( yuck : integer ); begin writeln('plbbt: passed parameter = ',yuck) end; procedure oof( foo : procparm; ick : integer ); begin writeln('oof: calling passed procedure'); foo(ick) end; begin oof(ugh,3); oof(plbbt,5) end. //-n-\\ Naoto Kimura _____---=======---_____ (abcscnuk@csuna.csun.edu) ====____\ /.. ..\ /____==== // ---\__O__/--- \\ Enterprise... Surrender or we'll \_\ /_/ send back your *&^$% tribbles !!