[comp.sys.ibm.pc] Shelling to dos, and running C from Pascal

jtb901@leah.Albany.Edu (James Brooking) (04/27/88)

I am currently writing a screen editor for a class project and would
appreciate anyone's input as to a way to shell to DOS (3.2) from
Turbo Pascal III.  (I know, I know, "Get version 4!", but I haven't
the time to wait at the moment.)

Also, does anyone know a quick and easy way to run a program written
in Turbo C 1.5 from a Turbo Pascal 3 program?  I'd like to use
EXTERNALs, rather than the EXECUTE procedure.  I'm using C for some
graphics intensive stuff.  The course is primarily Pascal oriented,
if anyone's wondering why I just don't do the whole thing in C.

-- 
 / /\    JT Brooking @ The University at Albany
/_/ _\   Computing services center

madd@bu-cs.BU.EDU (Jim Frost) (04/28/88)

In article <717@leah.Albany.Edu> jtb901@leah.Albany.Edu (James Brooking) writes:
|I am currently writing a screen editor for a class project and would
|appreciate anyone's input as to a way to shell to DOS (3.2) from
|Turbo Pascal III.  (I know, I know, "Get version 4!", but I haven't
|the time to wait at the moment.)
|
|Also, does anyone know a quick and easy way to run a program written
|in Turbo C 1.5 from a Turbo Pascal 3 program?  I'd like to use
|EXTERNALs, rather than the EXECUTE procedure.  I'm using C for some
|graphics intensive stuff.  The course is primarily Pascal oriented,
|if anyone's wondering why I just don't do the whole thing in C.

Well, here's a routine that I use to execute things in Turbo Pascal.
To shell out, execute whatever's in COMSPEC.  I have a getenv() as
well, so ask if you need it.

HOW TO USE:

"name" should contain the full path name (optional drive and path if
it's the current one) with extension (.EXE or .COM) of the executable.
"parameters" should be the parameters passed to the program you're
executing.

The return value is most likely going to be one of:
	0 : ok
	2 : file not found
	3 : invalid path
	8 : not enough memory
	10 : bad environment
	11 : bad program format (possibly damaged file)

I usually execute in a case statement that handles each of these.

CAVEATS:

This function does not properly build the FCB's.  While it is very
seldom a problem, it does pop up with the use of system utilities such
as FORMAT.  The easiest way to overcome this is to run "COMMAND.COM /C
(whatever)", which is what the Tech. Ref. Manual suggests.  I have a
more complex function used in psh (a csh-like shell) that handles
this, but it really relies on other things so I can't just cut it out.
If you want to see psh, it's on simtel in (I think)
<MSDOS-UTILS>PSH.PAS;1.

Happy hacking,

jim frost
madd@bu-it.bu.edu

-- cut here --
type e_string = string[255];

function exec(name,parameters : e_string) : integer;
type parmblock = record
                   envseg,
                   parmofs,
                   parmseg,
                   FCB1ofs,
                   FCB1seg,
                   FCB2ofs,
                   FCB2seg : integer;
                 end;
     FCB = array[0..$24] of byte;
     register = record
                  ax,bx,cx,dx,bp,si,di,ds,es,flags : integer
                end;

var pb : parmblock;
    r  : register;
begin
  if length(name)=255
    then name[255]:= chr(0)
    else name:= name+chr(0);
  pb.envseg:= 0;                  { pass child the parent's environment }
  pb.parmseg:= seg(parameters);   { get pointer to parameter string     }
  pb.parmofs:= ofs(parameters);
  pb.FCB1seg:= cseg;              { get pointer to FCB                  }
  pb.FCB1ofs:= $005C;
  pb.FCB2seg:= cseg;              { get pointer to second FCB           }
  pb.FCB2ofs:= $006C;
  r.ax:= $4B00;                   { function 0 is load and execute      }
  r.ds:= seg(name[1]);            { get pointer to ASCIIZ pathname      }
  r.dx:= ofs(name[1]);
  r.es:= seg(pb);                 { get pointer to parameter block      }
  r.bx:= ofs(pb);
  msdos(r);                       { call the function                   }
  if (r.flags and 1)=1            { check for error (carry set)         }
    then exec:= r.ax
    else exec:= 0
end;