/* FILES.C */ /*+-------------------------------------------------------------------------+ | | | add_extension_to_file | | | +-------------------------------------------------------------------------+*/ string_ptr add_extension_to_file(string_ptr fn, string_ptr ext) BeginDeclarations EndDeclarations BeginCode If index_string(fn,0,colon_string) IsNot 1 Then /* AUX:, CON:, or PRN: */ return(fn); EndIf; If index_string(fn,0,dot_string) Is 0xFFFF Then concat_string(fn,ext); EndIf; return(fn); EndCode /*+-------------------------------------------------------------------------+ | | | add_files_to_list | | | +-------------------------------------------------------------------------+*/ void add_files_to_list(file_info_list *file_list, string_ptr fn) BeginDeclarations bit_16 already_in_list; byte_ptr matched_file; bit_16 compare_len; file_info_ptr file_entry; #define File_entry (*file_entry) #define File_list (*file_list) bit_16 rc; EndDeclarations BeginCode matched_file = String(current_filename); rc = start_file_search(fn, 0); If rc IsNotZero Then linker_error(4,"No matching files for file specification:\n" "\t\"%Fs\"\n", String(fn)); EndIf; While rc IsZero BeginWhile compare_len = Length(current_filename) + 1; already_in_list = 0; TraverseList(File_list, file_entry) BeginTraverse already_in_list = far_compare(matched_file, BytePtr(File_entry.filename),compare_len) IsZero; ExitIf(already_in_list); EndTraverse; If Not already_in_list Then file_entry = (file_info_ptr) allocate_memory(Addr(static_pool), Bit_32(sizeof(file_info_type)) + Bit_32(compare_len) - 1L); File_entry.attribute = (*DTA).attribute; File_entry.time_stamp = (*DTA).time_stamp; File_entry.date_stamp = (*DTA).date_stamp; File_entry.file_size = (*DTA).file_size; File_entry.pass_count = File_entry.module_count = 0; far_move(File_entry.filename, matched_file, compare_len); Insert file_entry AtEnd InList File_list EndInsert; EndIf; rc = continue_file_search(); EndWhile; return; EndCode #undef File_entry #undef File_list /*+-------------------------------------------------------------------------+ | | | change_extension | | | +-------------------------------------------------------------------------+*/ string_ptr change_extension(string_ptr fn, string_ptr ext) BeginDeclarations EndDeclarations BeginCode trunc_string(fn, reverse_index_string(fn,0xFFFF,dot_string)); concat_string(fn, ext); return(fn); EndCode /*+-------------------------------------------------------------------------+ | | | continue_file_search | | | | O/S dependent | | | +-------------------------------------------------------------------------+*/ bit_16 continue_file_search() BeginDeclarations bit_16 rc; EndDeclarations BeginCode /*+-------------------------------------------------------------------------+ | | | Set up a new DTA | | | +-------------------------------------------------------------------------+*/ old_DTA = get_DTA_address(); set_DTA_address(DTA); inregs.h.ah = 0x4F; /* Continue file search */ rc = (bit_16) intdos(Addr(inregs), Addr(outregs)); set_DTA_address(old_DTA); If rc IsNotZero Then copy_string(current_filename, null_string); Else far_to_lower((*DTA).filename, 12); copy_string(current_filename, current_path); concat_string(current_filename, string((*DTA).filename)); EndIf; return(rc); EndCode /*+-------------------------------------------------------------------------+ | | | default_directory | | | | O/S dependent | | | +-------------------------------------------------------------------------+*/ string_ptr default_directory(string_ptr drive, string_ptr directory) BeginDeclarations EndDeclarations BeginCode inregs.h.ah = 0x47; /* Get current directory*/ inregs.h.dl = *String(drive) - 'a' + 1; inregs.x.si = Offset(String(directory)) + 1; segregs.ds = Segment(String(directory)); intdosx(Addr(inregs), Addr(outregs), Addr(segregs)); *String(directory) = '\\'; Length(directory) = far_index(String(directory), 0); far_to_lower(String(directory), Length(directory)); If LastCharIn(directory) IsNot '\\' Then concat_string(directory,backslash_string); EndIf; return(directory); EndCode /*+-------------------------------------------------------------------------+ | | | default_drive | | | | O/S dependent | | | +-------------------------------------------------------------------------+*/ string_ptr default_drive() BeginDeclarations string_ptr drive; EndDeclarations BeginCode drive = make_constant_string(Addr(static_pool), (byte *) " :"); inregs.h.ah = 0x19; /* Report current drive */ intdosx(Addr(inregs), Addr(outregs), Addr(segregs)); /* DOS_int21("Failed to get current drive.\n");*/ *String(drive) = (char) (outregs.h.al + 'a'); return(drive); EndCode /*+-------------------------------------------------------------------------+ | | | file_close_for_read | | | | O/S dependent | | | +-------------------------------------------------------------------------+*/ void file_close_for_read() BeginDeclarations #define File infile EndDeclarations BeginCode If File.file_handle Exceeds 4 Then /* Only issue close if not one of the standard handles. */ inregs.h.ah = 0x3E; /* Close for read */ inregs.x.bx = File.file_handle; DOS_int21("Trouble closing \"%Fs\".\n", (*File.file_info).filename); EndIf; return; EndCode #undef File /*+-------------------------------------------------------------------------+ | | | file_close_for_write | | | | O/S dependent | | | +-------------------------------------------------------------------------+*/ void file_close_for_write() BeginDeclarations #define File outfile EndDeclarations BeginCode If File.bytes_in_buffer Exceeds 0 Then inregs.h.ah = 0x40; /* Write */ inregs.x.bx = File.file_handle; inregs.x.cx = File.bytes_in_buffer; inregs.x.dx = Offset(File.buffer); segregs.ds = Segment(File.buffer); DOS_int21("Trouble writing file \"%Fs\" at byte %lu.\n", (*File.file_info).filename, File.next_buffer_position); EndIf; If File.file_handle Exceeds 4 Then /* Only issue close if not one of the standard handles. */ inregs.h.ah = 0x3E; /* Close for read */ inregs.x.bx = File.file_handle; DOS_int21("Trouble closing \"%Fs\".\n", (*File.file_info).filename); EndIf; return; EndCode #undef File /*+-------------------------------------------------------------------------+ | | | file_exists | | | | O/S dependent | | | +-------------------------------------------------------------------------+*/ bit_16 file_exists(string_ptr fn, bit_16 attr) BeginDeclarations bit_16 rc; EndDeclarations BeginCode old_DTA = get_DTA_address(); set_DTA_address(DTA); inregs.h.ah = 0x4E; /* Start file search */ segregs.ds = Segment(String(fn)); inregs.x.dx = Offset(String(fn)); inregs.x.cx = attr; rc = (bit_16) intdosx(Addr(inregs), Addr(outregs), Addr(segregs)); set_DTA_address(old_DTA); return(rc IsZero); EndCode /*+-------------------------------------------------------------------------+ | | | file_delete | | | | O/S dependent | | | +-------------------------------------------------------------------------+*/ void file_delete(file_info_ptr file_info) BeginDeclarations #define File_info (*file_info) EndDeclarations BeginCode inregs.h.ah = 0x41; /* Delete file */ inregs.x.dx = Offset(File_info.filename); segregs.ds = Segment(File_info.filename); DOS_int21("Trouble deleting file \"%Fs\".\n", File_info.filename); return; EndCode #undef File_info /*+-------------------------------------------------------------------------+ | | | file_IO_limit | | | +-------------------------------------------------------------------------+*/ void file_IO_limit(bit_16 limit) BeginDeclarations #define File infile EndDeclarations BeginCode If (limit IsZero) OrIf (limit Exceeds File.buffer_size) Then File.IO_limit = File.buffer_size; Else File.IO_limit = limit; EndIf; return; EndCode #undef File /*+-------------------------------------------------------------------------+ | | | file_open_for_read | | | | O/S dependent | | | +-------------------------------------------------------------------------+*/ void file_open_for_read(file_info_ptr file_info) BeginDeclarations #define File infile #define File_info (*file_info) EndDeclarations BeginCode /*+-------------------------------------------------------------------------+ | | | Initialize the data structure | | | +-------------------------------------------------------------------------+*/ File.current_byte = File.buffer; File.IO_limit = File.buffer_size; File.start_of_buffer_position = File.next_buffer_position = 0L; File.bytes_in_buffer = File.bytes_left_in_buffer = File.byte_position = 0; File.file_info = file_info; /*+-------------------------------------------------------------------------+ | | | Open the file and save the handle | | | +-------------------------------------------------------------------------+*/ If compare_string(string(File_info.filename), device_AUX) IsZero Then File.file_handle = 3; return; EndIf; If compare_string(string(File_info.filename), device_CON) IsZero Then File.file_handle = 0; return; EndIf; If compare_string(string(File_info.filename), device_PRN) IsZero Then File.file_handle = 4; return; EndIf; inregs.h.ah = 0x3D; /* Open for read */ inregs.h.al = 0x00; /* Access code */ inregs.x.dx = Offset(File_info.filename); segregs.ds = Segment(File_info.filename); DOS_int21("Trouble opening \"%Fs\" for input.\n", File_info.filename); File.file_handle = outregs.x.ax; return; EndCode #undef File #undef File_info /*+-------------------------------------------------------------------------+ | | | file_open_for_write | | | | O/S dependent | | | +-------------------------------------------------------------------------+*/ void file_open_for_write(file_info_ptr file_info) BeginDeclarations #define File outfile #define File_info (*file_info) EndDeclarations BeginCode /*+-------------------------------------------------------------------------+ | | | Initialize the data structure | | | +-------------------------------------------------------------------------+*/ File.current_byte = File.buffer; File.bytes_left_in_buffer = File.IO_limit = File.buffer_size; File.start_of_buffer_position = File.next_buffer_position = 0L; File.bytes_in_buffer = File.byte_position = 0; File.file_info = file_info; /*+-------------------------------------------------------------------------+ | | | Open the file and save the handle | | | +-------------------------------------------------------------------------+*/ If compare_string(string(File_info.filename), device_AUX) IsZero Then File.file_handle = 3; return; EndIf; If compare_string(string(File_info.filename), device_CON) IsZero Then File.file_handle = 1; return; EndIf; If compare_string(string(File_info.filename), device_PRN) IsZero Then File.file_handle = 4; return; EndIf; inregs.h.ah = 0x3C; /* Open for write */ inregs.x.cx = 0x00; /* File attribute */ inregs.x.dx = Offset(File_info.filename); segregs.ds = Segment(File_info.filename); DOS_int21("Trouble opening \"%Fs\" for output.\n", File_info.filename); File.file_handle = outregs.x.ax; return; EndCode #undef File #undef File_info /*+-------------------------------------------------------------------------+ | | | file_position | | | | O/S dependent | | | +-------------------------------------------------------------------------+*/ void file_position(bit_32 position) BeginDeclarations #define File infile EndDeclarations BeginCode If (position NotLessThan File.start_of_buffer_position) AndIf (position LessThan File.next_buffer_position) Then File.byte_position = Bit_16(position-File.start_of_buffer_position); File.current_byte = Addr(File.buffer[File.byte_position]); File.bytes_left_in_buffer = File.bytes_in_buffer - File.byte_position; Else inregs.h.ah = 0x42; /* Move file pointer */ inregs.h.al = 0x00; /* Relative to start of file */ inregs.x.bx = File.file_handle; inregs.x.cx = High(position); inregs.x.dx = Low(position); DOS_int21("Trouble positioning file \"%Fs\" to byte %lu.\n", (*File.file_info).filename, position); File.start_of_buffer_position = File.next_buffer_position = position; File.byte_position = File.bytes_in_buffer = File.bytes_left_in_buffer = 0; File.current_byte = File.buffer; EndIf; return; EndCode #undef File /*+-------------------------------------------------------------------------+ | | | file_read | | | | O/S dependent | | | +-------------------------------------------------------------------------+*/ void file_read(byte_ptr into, bit_16 length) BeginDeclarations #define File infile EndDeclarations BeginCode While length Exceeds 0 BeginWhile If length Exceeds File.bytes_left_in_buffer Then If File.bytes_left_in_buffer Exceeds 0 Then far_move(into, File.current_byte, File.bytes_left_in_buffer); length -= File.bytes_left_in_buffer; into += File.bytes_left_in_buffer; EndIf; inregs.h.ah = 0x3F; /* Read */ inregs.x.bx = File.file_handle; inregs.x.cx = File.IO_limit; inregs.x.dx = Offset(File.buffer); segregs.ds = Segment(File.buffer); DOS_int21("Trouble reading file \"%Fs\" at byte %lu.\n", (*File.file_info).filename, File.next_buffer_position); File.bytes_in_buffer = File.bytes_left_in_buffer = outregs.x.ax; File.current_byte = File.buffer; File.byte_position = 0; File.start_of_buffer_position = File.next_buffer_position; File.next_buffer_position = File.start_of_buffer_position + File.bytes_in_buffer; Else far_move(into, File.current_byte, length); into += length; File.current_byte += length; File.bytes_left_in_buffer -= length; File.byte_position += length; length = 0; EndIf; EndWhile; return; EndCode #undef File /*+-------------------------------------------------------------------------+ | | | file_write | | | | O/S dependent | | | +-------------------------------------------------------------------------+*/ void file_write(byte_ptr from, bit_32 length) BeginDeclarations #define File outfile EndDeclarations BeginCode While length Exceeds 0L BeginWhile If length Exceeds Bit_32(File.bytes_left_in_buffer) Then far_move(File.current_byte, from, File.bytes_left_in_buffer); length -= Bit_32(File.bytes_left_in_buffer); from += File.bytes_left_in_buffer; File.bytes_in_buffer += File.bytes_left_in_buffer; inregs.h.ah = 0x40; /* Write */ inregs.x.bx = File.file_handle; inregs.x.cx = File.bytes_in_buffer; inregs.x.dx = Offset(File.buffer); segregs.ds = Segment(File.buffer); DOS_int21("Trouble writing file \"%Fs\" at byte %lu.\n", (*File.file_info).filename, File.next_buffer_position); File.current_byte = File.buffer; File.bytes_left_in_buffer = File.buffer_size; File.bytes_in_buffer = File.byte_position = 0; File.start_of_buffer_position = File.next_buffer_position; File.next_buffer_position = File.start_of_buffer_position + File.bytes_left_in_buffer; Else far_move(File.current_byte, from, Bit_16(length)); from += Bit_16(length); File.current_byte += Bit_16(length); File.bytes_left_in_buffer -= Bit_16(length); File.byte_position += Bit_16(length); File.bytes_in_buffer += Bit_16(length); length = 0; EndIf; EndWhile; return; EndCode #undef File /*+-------------------------------------------------------------------------+ | | | get_DTA_address | | | | O/S dependent | | | +-------------------------------------------------------------------------+*/ DTA_ptr get_DTA_address() BeginDeclarations DTA_ptr DTA_address; EndDeclarations BeginCode inregs.h.ah = 0x2F; /* Get DTA address */ intdosx(Addr(inregs), Addr(outregs), Addr(segregs)); DTA_address = (DTA_ptr) MakeFarPtr(segregs.es, outregs.x.bx); return(DTA_address); EndCode /*+-------------------------------------------------------------------------+ | | | process_filename | | | +-------------------------------------------------------------------------+*/ string_ptr process_filename(string_ptr fn) BeginDeclarations bit_16 left; bit_16 right; EndDeclarations BeginCode lowercase_string(fn); /*+-------------------------------------------------------------------------+ | | | Check for AUX:, CON: & PRN: | | | +-------------------------------------------------------------------------+*/ If compare_string(substr(fn,0,4), device_AUX) IsZero Then copy_string(fn, device_AUX); return(fn); EndIf; If compare_string(substr(fn,0,4), device_CON) IsZero Then copy_string(fn, device_CON); return(fn); EndIf; If compare_string(substr(fn,0,4), device_PRN) IsZero Then copy_string(fn, device_PRN); return(fn); EndIf; /*+-------------------------------------------------------------------------+ | | | Add drive designator if missing. | | | +-------------------------------------------------------------------------+*/ If compare_string(substr(fn,1,1), colon_string) IsNotZero Then paste_string(fn, 0, default_drive_string); EndIf; /*+-------------------------------------------------------------------------+ | | | Substitute current directory if not based from root. | | | +-------------------------------------------------------------------------+*/ If compare_string(substr(fn,2,1), backslash_string) IsNotZero Then default_directory(fn, default_directory_string); paste_string(fn, 2, default_directory_string); EndIf; /*+-------------------------------------------------------------------------+ | | | Scan out all \. and \.. from filename. | | | +-------------------------------------------------------------------------+*/ left = index_string(fn, -1, backslash_string); right = index_string(fn, left+1, backslash_string); While right IsNot 0xffff BeginWhile If compare_string(substr(fn,left,4), backslash_dot_dot_string) IsZero Then cut_string(fn, left, 3); right = left; left = reverse_index_string(fn, right-1, backslash_string); If left Is 0xffff Then return(null_string); EndIf; cut_string(fn, left, right-left); right = index_string(fn, left+1, backslash_string); ContinueLoop; Else If compare_string(substr(fn,left,3), backslash_dot_string) IsZero Then cut_string(fn, left, 2); right = index_string(fn, left+1, backslash_string); ContinueLoop; EndIf; EndIf; left = right; right = index_string(fn, left+1, backslash_string); EndWhile; return(fn); EndCode /*+-------------------------------------------------------------------------+ | | | set_DTA_address | | | | O/S dependent | | | +-------------------------------------------------------------------------+*/ void set_DTA_address(DTA_ptr DTA_address) BeginDeclarations EndDeclarations BeginCode inregs.h.ah = 0x1A; /* Set DTA address */ segregs.ds = Segment(DTA_address); inregs.x.dx = Offset(DTA_address); intdosx(Addr(inregs), Addr(outregs), Addr(segregs)); return; EndCode /*+-------------------------------------------------------------------------+ | | | start_file_search | | | | O/S dependent | | | +-------------------------------------------------------------------------+*/ bit_16 start_file_search(string_ptr fn, bit_16 attr) BeginDeclarations bit_16 rc; EndDeclarations BeginCode /*+-------------------------------------------------------------------------+ | | | Set up a new DTA | | | +-------------------------------------------------------------------------+*/ old_DTA = get_DTA_address(); set_DTA_address(DTA); /*+-------------------------------------------------------------------------+ | | | Remember the current file path | | | +-------------------------------------------------------------------------+*/ copy_string(current_path, fn); trunc_string(current_path, reverse_index_string(current_path, 0xFFFF, backslash_string)+1); inregs.h.ah = 0x4E; /* Start file search */ segregs.ds = Segment(String(fn)); inregs.x.dx = Offset(String(fn)); inregs.x.cx = attr; rc = (bit_16) intdosx(Addr(inregs), Addr(outregs), Addr(segregs)); set_DTA_address(old_DTA); If rc IsNotZero Then copy_string(current_filename, null_string); Else far_to_lower((*DTA).filename, 12); copy_string(current_filename, current_path); concat_string(current_filename, string((*DTA).filename)); EndIf; return(rc); EndCode