defaria@hpcupt3.cup.hp.com (Andy DeFaria) (05/22/91)
I have been having three problems lately in TP: 1) How do you perform I/O redirection using Exec? I remember this being discussed and had thought that my home-brewed shell did this properly then found out it doesn't and the posting has since timed out. I thought that I needed to Exec Command.Com and specify the ">" or "|" options in the Options parameter but this not working. 2) How do you get the name of an open text file from AFile : Text variable? 3) The FileSize function doesn't work on Text files. How can I easily and efficiently get the FileSize (in bytes) of a Text file? Thanks
defaria@hpcupt3.cup.hp.com (Andy DeFaria) (05/22/91)
>/ hpcupt3:comp.lang.pascal / defaria@hpcupt3.cup.hp.com (Andy DeFaria) / 10:44 am May 21, 1991 / >I have been having three problems lately in TP: > > 1) How do you perform I/O redirection using Exec? I remember this > being discussed and had thought that my home-brewed shell did > this properly then found out it doesn't and the posting has > since timed out. I thought that I needed to Exec Command.Com > and specify the ">" or "|" options in the Options parameter but > this not working. > > 2) How do you get the name of an open text file from AFile : Text > variable? > > 3) The FileSize function doesn't work on Text files. How can I > easily and efficiently get the FileSize (in bytes) of a Text > file? I have solved #2 and #3. The solution for #2 is to cast the Text file to a TextRec and extract the Name field. Unfortunately this Name field is an ASCIIZ string (smells like a C string). So: FileName := ASCIIZToString (TextRec (TextFile).Name); Where ASCIIZToString is a function that converts the ASCIIZ string to a TP String. The solution to #3 is a little bit uglier but works. Basically, I take the Text file, get its name (see above), assign it to a File of Byte and call FileSize on that file (Oh and don't forget to Close the file). I would like to come up with a better method for this. I don't like opening and closing files if I can avoid it. Perhaps a FindFirst would give me the information but I'm not sure if FindFirst would incur more overhead than an Open/Filesize/Close. Does anybody know? Oh, and I'm still waiting for an answer to #1.
ts@uwasa.fi (Timo Salmi) (05/23/91)
In article <45670017@hpcupt3.cup.hp.com> defaria@hpcupt3.cup.hp.com (Andy DeFaria) writes: >I have been having three problems lately in TP: > 3) The FileSize function doesn't work on Text files. How can I > easily and efficiently get the FileSize (in bytes) of a Text > file? Among other units /ts/tspa23##.arc (##=40,50,55,60) at garbo.uwasa.fi (and SIMTEL20) archives contains: TSUNTE: (uses Dos) ALLSIZFN Allocated true size of a file in bytes BORDER Change border color (CGA, VGA) CAPS Turn CapsLock on, or off CAPSONFN Get CapsLock status CLB Clear the keyboard buffer CLUSIZFN Cluster size on a device (cluster is the allocation unit) CMDLNFN Returns the entire command line CURSOFF Turn off cursor (keeps other cursor attributes) CURSON Turn cursor back on as it was CURSOR Change cursor size DATEOKFN Is a date a valid, existing date FEXISTFN File existence status, handles ReadOnly files correctly FSIZE2FN File size in bytes, alternative method FSIZEFN File size in bytes as in directory (never on open file) LASTDMFN The number of days in a given month and year MONOFN Is it a monochrome NUMLOCK Turn NumLock on, or off NUMLONFN Get NumLock status SCRLOCK Turn ScrollLock on, or off SCRLONFN Get ScrollLock status WEEKNRFN Returns the week number for a given date WKDAYFN Returns modern weekday ZELLERFN Zeller's congruence (for comparing dates etc) ................................................................... Prof. Timo Salmi Moderating at garbo.uwasa.fi anonymous ftp archives 128.214.12.37 School of Business Studies, University of Vaasa, SF-65101, Finland Internet: ts@chyde.uwasa.fi Funet: gado::salmi Bitnet: salmi@finfun
phys169@csc.canterbury.ac.nz (05/23/91)
In article <45670017@hpcupt3.cup.hp.com>, defaria@hpcupt3.cup.hp.com (Andy DeFaria) writes: > I have been having three problems lately in TP: > > 1) How do you perform I/O redirection using Exec? I remember this > being discussed and had thought that my home-brewed shell did > this properly then found out it doesn't and the posting has > since timed out. I thought that I needed to Exec Command.Com > and specify the ">" or "|" options in the Options parameter but > this not working. > The basic answer is to the the handle duplication DOS calls; copy the current handle, open a file for redirection, and force a copy of its handle to be put on handle 1 (for output) or 0 (for stdin), etc. When you've finished, force the old one back again and close the temporary copy. An example of all this is at the end of the posting. > 2) How do you get the name of an open text file from AFile : Text > variable? > Note that this gets what name was given by the last assign, so you can't get the name from a handle in general this way (e.g. you can't use it to see the name of where the stdout is going). {make sure you have a "uses DOS" at the start} st:=TextRec(AFile).Name; {uses the pre-defined type TextRec} st:=copy(st,1,pred(pos(#0,st))); {truncate (it is ASCIZ)} writeln('The file AFile is assigned to: ',st); > 3) The FileSize function doesn't work on Text files. How can I > easily and efficiently get the FileSize (in bytes) of a Text > file? > The following inline assembler will do that, except for devices. function TextSize(var TF ) : longint; inline( $5F/ {pop di} $07/ {pop es} $B8/$4202/ {mov ax,4202} $33/$C9/ {xor cx,cx} $8B/$D1/ {mov dx,cx} $26/$8B/$1D/{mov bx,es:[di]} $CD/$21/ {int 21} $50/ {push ax} $52/ {push dx} $B8/$4200/ {mov ax,4200} $33/$C9/ {xor cx,cx} $8B/$D1/ {mov dx,cx} $26/$8B/$1D/{mov bx,es:[di]} $CD/$21/ {int 21} $5A/ {pop dx} $58); {pop ax} Hope this helps, Mark Aitchison, Physics, University of Canterbury, New Zealand, Up Under. --snip-- program TryRedirection; {$M 9000,0,0} uses DOS; const StandardInputHandle = 0; StandardOutputHandle= 1; StandardErrorHandle = 2; StandardPrinterHandle=4; StandardAuxHandle = 3; var RedirectionFile : text; OldHandle : word; reg : registers; function Truncate(st : string) : string; begin Truncate:=copy(st,1,pred(pos(#0,st))); end; function Redirect(HandleToRedirect,NewFileHandle : word) : word; begin with reg do begin AH:=$45; BX:=HandleToRedirect; MsDos(reg); {Duplicate a file handle} Redirect:=AX; {Return the temporary copy of the original handle} AH:=$46; CX:=HandleToRedirect; BX:=NewFileHandle; if BX<>CX then MsDos(reg); {MSDOS might hang if BX=CX!} end; end; procedure UnRedirect(HandleToRedirect,OldFileHandle : word); begin with reg do begin AH:=$46; {force duplicate handle} CX:=HandleToRedirect; BX:=OldFileHandle; if BX<>CX then MsDos(reg); {MSDOS might hang if BX=CX!} AH:=$3E; {close a handle} BX:=OldFileHandle; MsDos(reg); end; end; begin writeln('This goes to the standard output file (screen)'); writeToStandardFile(StandardOutputHandle,' So does this...'^M^J); assign(RedirectionFile,'Test.out'); rewrite(RedirectionFile); writeln('Output will be redirected to: ',truncate(TextRec(RedirectionFile).name)); writeln(RedirectionFile,'This is the file to get the redirected output...'); OldHandle:=Redirect(StandardOutputHandle,TextRec(RedirectionFile).handle); close(RedirectionFile); exec('c:\COMMAND.COM','/C dir try*.*'); UnRedirect(StandardOutputHandle,OldHandle); end.
CDCKAB%EMUVM1.BITNET@cunyvm.cuny.edu ( Karl Brendel) (05/24/91)
In article 45670018@hpcupt3.cup.hp.com, defaria@hpcupt3.cup.hp.com (Andy DeFaria) wrote: [... scattered deletions throughout ...] >2) How do you get the name of an open text file from AFile : Text > variable? > >3) The FileSize function doesn't work on Text files. How can I > easily and efficiently get the FileSize (in bytes) of a Text > file? >I have solved #2 and #3. The solution for #2 is to cast the Text >file to a TextRec and extract the Name field. Unfortunately this >The solution to #3 is a little bit uglier but works. Basically, I >take the Text file, get its name (see above), assign it to a File >of Byte and call FileSize on that file (Oh and don't forget to >Close the file). I would like to come up with a better method >for this. I don't like opening and closing files if I can avoid Unfortunately, that "solution" to #3 overlooks the text currently in the file's buffer (within the TextRec). This doesn't matter if you aren't currently writing the file. _My_ solution to this problem is to use routines from TurboPower Software. ;) However, for your use I offer this: Again casting the text file as a TextRec, extract the Handle and BufPos values. With a registers variable, call MSdos with ah := $42, al := 1, bx := Handle, and cx and dx := 0. The current position of the DOS file pointer will return in dx and ax. Save it as fpos := longint(dx) shl 16 + ax. If you are writing the file, the true size, including buffered output, should be fpos + BufPos. If you are reading the file, you need to do a DOS seek to EOF. Don't forget to save fpos, because you'll need it to restore the file pointer. Call MSdos again with ah := $42, al := 2, bx := Handle, cx and dx := 0. The current DOS file size will return in dx and ax as before. That should be the true size. Now call MSdos with ah := $42, al := 0, bx := Handle, cx := fpos shr 16, dx := fpos and $FFFF. This will return the file pointer to the original position. Here's code for making the actual DOS calls. Note that this code knows nothing about text files and doesn't set TPas' InOutRes, so you have to pay attention to the function returns to detect a file io error. =========================== cut here ============================ const {base of DOS file seek} baseSOF = 0; {seek from start of file} baseCurPos = 1; {seek from current file pointer} baseEOF = 2; {seek from end of file} function DosFilePos(handle : word; var fpos : longint) : integer; { Call DOS to determine the absolute position of the file pointer IN BYTES from the beginning of the file. Remember that DOS knows nothing of file contents that may be buffered with Turbo Pascal: this file pointer is the one DOS keeps, and may differ from Turbo Pascal's buffered file pointer within a text file. Return the error code. If no error, return the absolute position of the file pointer IN BYTES in fpos. } var regs : Registers; begin {DosFilePos} with regs do begin ah := $42; al := baseCurPos; bx := handle; cx := 0; dx := 0; MSdos(regs); if (flags and FCarry) = FCarry then {error} DosFilePos := ax else begin DosFilePos := 0; fpos := longint(dx) shl 16 + ax; end; {no error} end; {with regs} end; {DosFilePos} function DosFileSeek(handle : word; base : word; var fpos : longint) : integer; { Call DOS to do a seek of the offset fpos IN BYTES from the specified base (see constants above). Return the error code. If no error, return the new absolute position of the file pointer IN BYTES in fpos. } var regs : registers; begin {DosFileSeek} with regs do begin ah := $42; al := base; bx := handle; cx := fpos shr 16; dx := fpos and $FFFF; MSdos(regs); if (flags and FCarry) = FCarry then {error} DosFileSeek := ax else begin DosFileSeek := 0; fpos := longint(dx) shl 16 + ax; end; {no error} end; {with regs} end; {DosFileSeek} function DosFileSize(handle : word; var fsize : longint) : integer; { Call DOS to get the size of the file. Return the error code. If no error code, return the file size IN BYTES in fsize. This calls DosFilePos and DosFileSeek and is subject to the same caveats re text files and buffers. } var pos : longint; res : integer; begin {DosFileSize} pos := 0; res := DosFilePos(handle,pos); {get current offset} fsize := 0; if res = 0 then res := DosFileSeek(handle,baseEOF,fsize); {seek to EOF} DosFileSize := res; res := DosFileSeek(handle,baseSOF,pos); {restore original offset} end; {DosFileSize} =========================== cut here ============================ (BTW--this code is relatively new and I would urge any users to consider it Not Adequately Tested. It is in the public domain.) Cheers-- --Karl +====================================================================+ | Karl Brendel Centers for Disease Control | | Internet: CDCKAB@EMUVM1.BITNET Epidemiology Program Office | | Bitnet: CDCKAB@EMUVM1 Atlanta GA 30093 USA | | Home of Epi Info 5.0 | +====================================================================+