home *** CD-ROM | disk | FTP | other *** search
- { FUNCTION v1dir came when I wanted to allow wild cards in the file
- designation for a Turbo Pascal lister. Since Version 2.0 of Turbo does not
- allow path names in its file designation, I decided to use DOS functions 11
- and 12, so that the procedure would work with DOS 1.x as well as later
- versions. As long as I was getting the directory for file names, I decided to
- also give the rest of the directory information, and to translate the date and
- time to standard integers.
- v1dir uses a MARK(dir_mark) instruction. As a result, page 13 of the
- addendum to the Turbo manual says that the calling program must not use the
- DISPOSE procedure. On the other hand, you probably should RELEASE the space
- after you are done with the returned directory.
-
- Lew Paper
- E-1212 First National Bank Building
- St. Paul, MN 55101
- 3/17/85 }
-
- TYPE
-
- dirpoint = ^dirtype;
-
- dirtype = RECORD
- full_name : STRING[14];
- name : STRING[8];
- ext : STRING[3];
- attribute : BYTE;
- hours : BYTE;
- minutes : BYTE;
- seconds : BYTE;
- year : INTEGER;
- month : BYTE;
- day : BYTE;
- size : REAL;
- {To avoid Turbo 2.0's small integer}
- next : dirpoint;
- END; {RECORD dirtype}
-
- intpoint = ^INTEGER;
-
- FUNCTION v1dir(in_name:str255; VAR out_dir:dirpoint; VAR dir_mark:intpoint;
- VAR bad_spec: BOOLEAN): INTEGER;
-
- {v1dir : Number of files which match in_name
- in_name : Input file name. Can contain a drive letter and wild card
- characters. Can not contain a DOS 2.0 path
- out_dir : Pointer to a chain of dirtype records for files found. NIL
- if none found.
- dir_mark : Pointer MARKed. Use RELEASE to return the chain of dirtype
- records. NIL if none found.
- bad_spec : TRUE if an illegal drive letter or a bad file specification.
-
- Requires :
- Function match_char. In file MATCHCH.PAS.
- Type str255 = STRING[255];
- }
-
- LABEL 1;
-
- TYPE
- regtype = RECORD
- ax,bx,cx,dx,bp,si,di,ds,es,flags : integer;
- END; {RECORD regtype}
-
- two_byte = RECORD
- low : BYTE;
- high : BYTE;
- END; {RECORD two_byte}
-
- file_size_rec = RECORD
- low_order: two_byte;
- high_order: two_byte;
- END; {RECORD file_size_rec}
-
- DTA_dir_type = RECORD
- drive_number : BYTE;
- filename : ARRAY [0..7] OF CHAR;
- filename_extension: ARRAY[8..10] OF CHAR;
- file_attribute : BYTE;
- reserved : ARRAY[12..21] OF BYTE;
- time : INTEGER;
- date : INTEGER;
- starting_cluster : INTEGER;
- file_size : file_size_rec;
- END; {RECORD DTA_dir_type}
-
- VAR
- n_matches,
- parse_lo_ax,
- search_lo_ax,
- i, j: INTEGER;
- wild_file: STRING[15];
- reg: regtype;
- FCB: ARRAY[0..36] of BYTE;
- dir_read: DTA_dir_type;
- first_find: dirpoint;
- first_mark: intpoint;
-
- PROCEDURE error_message(message: str255);
-
- BEGIN {PROCEDURE error_message}
- WRITELN;
- WRITELN('Error in call to FUNCTION v1dir. ', in_name,
- ' has invalid ', message);
- bad_spec := TRUE;
- END; {PROCEDURE error_message}
-
- PROCEDURE convert_dir;
-
- FUNCTION float_byte(in_byte: BYTE): REAL;
-
- TYPE
- real_half_type = ARRAY[0..$F] OF REAL;
-
- CONST
- real_half_byte: real_half_type = (0.0, 1.0, 2.0, 3.0, 4.0, 5.0,
- 6.0, 7.0, 8.0, 9.0, 10.0, 11.0,
- 12.0, 13.0, 14.0, 15.0);
-
- BEGIN {FUNCTION float_byte}
- float_byte := 16.0 * real_half_byte[in_byte SHR 4] +
- real_half_byte[in_byte AND $F];
- END; {FUNCTION float_byte}
-
- BEGIN {PROCEDURE convert_dir}
-
- {Create full_name}
- IF FCB[0] > 0
- THEN first_find^.full_name := CHR(ORD('A') -1 + FCB[0]) + ':'
- ELSE first_find^.full_name := '';
- i := 0;
- WHILE (i <= 7) AND (dir_read.filename[i] <> ' ') DO
- BEGIN
- first_find^.full_name := first_find^.full_name +
- dir_read.filename[i];
- i := i + 1;
- END; {WHILE (i <= 7) AND (dir_read.filename[i] <> ' ')}
- first_find^.full_name := first_find^.full_name + '.';
- i := 8;
- WHILE (i <= 10) AND (dir_read.filename_extension[i] <> ' ') DO
- BEGIN
- first_find^.full_name := first_find^.full_name +
- dir_read.filename_extension[i];
- i := i + 1;
- END; {WHILE (i <= 10) AND (dir_read.filename_extension[i] <> ' ')}
-
- MOVE(dir_read.filename[0], first_find^.name[1], 8);
- first_find^.name[0] := CHR(8);
- MOVE(dir_read.filename_extension[8], first_find^.ext[1], 3);
- first_find^.ext[0] := CHR(3);
- first_find^.attribute := dir_read.file_attribute;
-
- {Get time of creation}
- first_find^.hours := dir_read.time SHR 11;
- first_find^.minutes := (dir_read.time SHR 5) AND $3F;
- first_find^.seconds := (dir_read.time AND $1F) SHL 1;
-
- {Get date of creation}
- first_find^.year := (dir_read.date SHR 9) + 1980;
- first_find^.month := (dir_read.date SHR 5) AND $F;
- first_find^.day := dir_read.date AND $1F;
-
- first_find^.size := 256.0 *
- (256.0 * float_byte(dir_read.file_size.high_order.low) +
- float_byte(dir_read.file_size.low_order.high)) +
- float_byte(dir_read.file_size.low_order.low);
-
- first_find^.next := NIL;
-
- END; {PROCEDURE convert_dir}
-
- BEGIN {FUNCTION v1dir}
- out_dir := NIL;
- dir_mark := NIL;
- n_matches := 0;
-
- {Strip in_file of leading spaces, copy it to wild_file with space
- separator}
- i := match_char(in_name, 1, 32, next_unmatch);
- IF i = 0 THEN
- BEGIN
- WRITELN;
- WRITELN('Error in call to FUNCTION v1dir. No file name');
- bad_spec := TRUE;
- GOTO 1;
- END; {i = 0}
- j := LENGTH(in_name) - i + 1;
- IF j > 14 THEN j := 14; {Trim off superfluous characters}
- wild_file := COPY(in_name, i, j) + ' ';
-
- {Parse file name}
- WITH reg DO
- BEGIN
- AX := $2900;
- DS := SEG(wild_file[1]);
- SI := OFS(wild_file[1]);
- ES := SEG(FCB);
- DI := OFS(FCB);
- MSDOS(reg);
- parse_lo_ax := LO(AX);
- IF parse_lo_ax = $FF THEN
- BEGIN
- error_message('drive specifier.');
- GOTO 1;
- END; {IF LO(AX) = $FF}
-
- (* {Debug parse}
- WRITELN;
- WRITELN('FCB[0] = ', FCB[0]);
- FOR i := 1 TO 11 DO
- BEGIN
- WRITE('FCB[', i, '] ');
- IF (FCB[i] >= 33) AND (FCB[i] < 127)
- THEN
- WRITELN(CHR(FCB[I]))
- ELSE
- WRITELN('DECIMAL ', FCB[i]);
- END; {FOR i := 1 TO 11}
- WRITELN;
- WRITELN('parse_lo_ax = ', parse_lo_ax); *)
-
- IF FCB[1] = 32 THEN
- BEGIN
- error_message('file name.');
- GOTO 1;
- END; {FCB[1] = 32}
- bad_spec := FALSE;
-
- {Set DTA}
- AX := $1A00;
- DS := SEG(dir_read);
- DX := OFS(dir_read);
- MSDOS(reg);
-
- {Get first directory entry}
- AX := $1100;
- DS := SEG(FCB);
- DX := OFS(FCB);
- MSDOS(reg);
- search_lo_ax := LO(AX);
-
- IF search_lo_ax = 0 THEN
- BEGIN
- MARK(first_mark);
- NEW(first_find);
- convert_dir;
- n_matches := n_matches + 1;
- out_dir := first_find;
- dir_mark := first_mark;
-
- {Get later directory entries}
- WHILE search_lo_ax = 0 DO
- BEGIN
- AX := $1200;
- DS := SEG(FCB);
- DX := OFS(FCB);
- MSDOS(reg);
- search_lo_ax := LO(AX);
- IF search_lo_ax = 0 THEN
- BEGIN
- NEW(first_find^.next);
- first_find := first_find^.next;
- convert_dir;
- n_matches := n_matches + 1;
- END; {IF search_lo_ax = 0}
- END; {WHILE search_lo_ax = 0}
-
- END; {IF search_lo_ax = 0}
-
- END; {WITH reg}
-
- 1: v1dir := n_matches;
- END; {FUNCTION v1dir}
-