home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / pgmutil / val_link.zip / FILES.C < prev    next >
Text File  |  1989-02-18  |  32KB  |  714 lines

  1. /*                                 FILES.C                                 */
  2.  
  3. /*+-------------------------------------------------------------------------+
  4.   |                                                                         |
  5.   |                         add_extension_to_file                           |
  6.   |                                                                         |
  7.   +-------------------------------------------------------------------------+*/
  8. string_ptr add_extension_to_file(string_ptr fn, string_ptr ext)
  9. BeginDeclarations
  10. EndDeclarations
  11. BeginCode
  12.  If index_string(fn,0,colon_string) IsNot 1
  13.   Then  /* AUX:, CON:, or PRN: */
  14.    return(fn);
  15.   EndIf;
  16.  If index_string(fn,0,dot_string) Is 0xFFFF
  17.   Then
  18.    concat_string(fn,ext);
  19.   EndIf;
  20. return(fn);
  21. EndCode
  22.  
  23. /*+-------------------------------------------------------------------------+
  24.   |                                                                         |
  25.   |                         add_files_to_list                               |
  26.   |                                                                         |
  27.   +-------------------------------------------------------------------------+*/
  28. void add_files_to_list(file_info_list *file_list, string_ptr fn)
  29. BeginDeclarations
  30. bit_16                                 already_in_list;
  31. byte_ptr                               matched_file;
  32. bit_16                                 compare_len;
  33. file_info_ptr                          file_entry;
  34. #define File_entry                     (*file_entry)
  35. #define File_list                      (*file_list)
  36. bit_16                                 rc;
  37. EndDeclarations
  38. BeginCode
  39.  matched_file = String(current_filename);
  40.  rc = start_file_search(fn, 0);
  41.  If rc IsNotZero
  42.   Then
  43.    linker_error(4,"No matching files for file specification:\n"
  44.                   "\t\"%Fs\"\n",
  45.                   String(fn));
  46.   EndIf;
  47.  While rc IsZero
  48.   BeginWhile
  49.    compare_len = Length(current_filename) + 1;
  50.    already_in_list = 0;
  51.    TraverseList(File_list, file_entry)
  52.     BeginTraverse
  53.      already_in_list = far_compare(matched_file,
  54.                                    BytePtr(File_entry.filename),compare_len)
  55.                        IsZero;
  56.      ExitIf(already_in_list);
  57.     EndTraverse;
  58.    If Not already_in_list
  59.     Then
  60.      file_entry = (file_info_ptr)
  61.                    allocate_memory(Addr(static_pool),
  62.                                    Bit_32(sizeof(file_info_type)) +
  63.                                    Bit_32(compare_len) - 1L);
  64.      File_entry.attribute       = (*DTA).attribute;
  65.      File_entry.time_stamp      = (*DTA).time_stamp;
  66.      File_entry.date_stamp      = (*DTA).date_stamp;
  67.      File_entry.file_size       = (*DTA).file_size;
  68.      File_entry.pass_count      =
  69.      File_entry.module_count    = 0;
  70.      far_move(File_entry.filename, matched_file, compare_len);
  71.      Insert file_entry AtEnd InList File_list EndInsert;
  72.     EndIf;
  73.    rc = continue_file_search();
  74.   EndWhile;
  75.  return;
  76. EndCode
  77. #undef File_entry
  78. #undef File_list
  79.  
  80. /*+-------------------------------------------------------------------------+
  81.   |                                                                         |
  82.   |                              change_extension                           |
  83.   |                                                                         |
  84.   +-------------------------------------------------------------------------+*/
  85. string_ptr change_extension(string_ptr  fn, string_ptr ext)
  86. BeginDeclarations
  87. EndDeclarations
  88. BeginCode
  89.  trunc_string(fn, reverse_index_string(fn,0xFFFF,dot_string));
  90.  concat_string(fn, ext);
  91.  return(fn);
  92. EndCode
  93.  
  94. /*+-------------------------------------------------------------------------+
  95.   |                                                                         |
  96.   |                       continue_file_search                              |
  97.   |                                                                         |
  98.   |                         O/S dependent                                   |
  99.   |                                                                         |
  100.   +-------------------------------------------------------------------------+*/
  101. bit_16 continue_file_search()
  102. BeginDeclarations
  103. bit_16                                 rc;
  104. EndDeclarations
  105. BeginCode
  106. /*+-------------------------------------------------------------------------+
  107.   |                                                                         |
  108.   |                         Set up a new DTA                                |
  109.   |                                                                         |
  110.   +-------------------------------------------------------------------------+*/
  111.  
  112.  old_DTA = get_DTA_address();
  113.  set_DTA_address(DTA);
  114.  
  115.  inregs.h.ah = 0x4F;                   /* Continue file search */
  116.  rc = (bit_16) intdos(Addr(inregs), Addr(outregs));
  117.  set_DTA_address(old_DTA);
  118.  If rc IsNotZero
  119.   Then
  120.    copy_string(current_filename, null_string);
  121.   Else
  122.    far_to_lower((*DTA).filename, 12);
  123.    copy_string(current_filename, current_path);
  124.    concat_string(current_filename, string((*DTA).filename));
  125.   EndIf;
  126.  return(rc);
  127. EndCode
  128.  
  129. /*+-------------------------------------------------------------------------+
  130.   |                                                                         |
  131.   |                       default_directory                                 |
  132.   |                                                                         |
  133.   |                         O/S dependent                                   |
  134.   |                                                                         |
  135.   +-------------------------------------------------------------------------+*/
  136. string_ptr default_directory(string_ptr drive, string_ptr directory)
  137. BeginDeclarations
  138. EndDeclarations
  139. BeginCode
  140.  inregs.h.ah = 0x47;                   /* Get current directory*/
  141.  inregs.h.dl = *String(drive) - 'a' + 1;
  142.  inregs.x.si = Offset(String(directory)) + 1;
  143.  segregs.ds  = Segment(String(directory));
  144.  intdosx(Addr(inregs), Addr(outregs), Addr(segregs));
  145.  *String(directory) = '\\';
  146.  Length(directory) = far_index(String(directory), 0);
  147.  far_to_lower(String(directory), Length(directory));
  148.  If LastCharIn(directory) IsNot '\\'
  149.   Then
  150.    concat_string(directory,backslash_string);
  151.   EndIf;
  152.  return(directory);
  153. EndCode
  154.  
  155. /*+-------------------------------------------------------------------------+
  156.   |                                                                         |
  157.   |                         default_drive                                   |
  158.   |                                                                         |
  159.   |                         O/S dependent                                   |
  160.   |                                                                         |
  161.   +-------------------------------------------------------------------------+*/
  162. string_ptr default_drive()
  163. BeginDeclarations
  164. string_ptr                             drive;
  165. EndDeclarations
  166. BeginCode
  167.  drive = make_constant_string(Addr(static_pool), (byte *) " :");
  168.  inregs.h.ah = 0x19;                   /* Report current drive */
  169.  intdosx(Addr(inregs), Addr(outregs), Addr(segregs));
  170. /* DOS_int21("Failed to get current drive.\n");*/
  171.  *String(drive) = (char) (outregs.h.al + 'a');
  172.  return(drive);
  173. EndCode
  174.  
  175. /*+-------------------------------------------------------------------------+
  176.   |                                                                         |
  177.   |                          file_close_for_read                            |
  178.   |                                                                         |
  179.   |                           O/S dependent                                 |
  180.   |                                                                         |
  181.   +-------------------------------------------------------------------------+*/
  182. void file_close_for_read()
  183. BeginDeclarations
  184. #define File                           infile
  185. EndDeclarations
  186. BeginCode
  187.  If File.file_handle Exceeds 4
  188.   Then  /* Only issue close if not one of the standard handles. */
  189.    inregs.h.ah = 0x3E;                   /* Close for read */
  190.    inregs.x.bx = File.file_handle;
  191.    DOS_int21("Trouble closing \"%Fs\".\n",
  192.              (*File.file_info).filename);
  193.   EndIf;
  194.  return;
  195. EndCode
  196. #undef File
  197.  
  198. /*+-------------------------------------------------------------------------+
  199.   |                                                                         |
  200.   |                         file_close_for_write                            |
  201.   |                                                                         |
  202.   |                           O/S dependent                                 |
  203.   |                                                                         |
  204.   +-------------------------------------------------------------------------+*/
  205. void file_close_for_write()
  206. BeginDeclarations
  207. #define File                           outfile
  208. EndDeclarations
  209. BeginCode
  210.  If File.bytes_in_buffer Exceeds 0
  211.   Then
  212.    inregs.h.ah = 0x40;               /* Write */
  213.    inregs.x.bx = File.file_handle;
  214.    inregs.x.cx = File.bytes_in_buffer;
  215.    inregs.x.dx = Offset(File.buffer);
  216.    segregs.ds  = Segment(File.buffer);
  217.    DOS_int21("Trouble writing file \"%Fs\" at byte %lu.\n",
  218.              (*File.file_info).filename, File.next_buffer_position);
  219.   EndIf;
  220.  If File.file_handle Exceeds 4
  221.   Then  /* Only issue close if not one of the standard handles. */
  222.    inregs.h.ah = 0x3E;                   /* Close for read */
  223.    inregs.x.bx = File.file_handle;
  224.    DOS_int21("Trouble closing \"%Fs\".\n",
  225.              (*File.file_info).filename);
  226.   EndIf;
  227.  return;
  228. EndCode
  229. #undef File
  230.  
  231. /*+-------------------------------------------------------------------------+
  232.   |                                                                         |
  233.   |                          file_exists                                    |
  234.   |                                                                         |
  235.   |                         O/S dependent                                   |
  236.   |                                                                         |
  237.   +-------------------------------------------------------------------------+*/
  238. bit_16 file_exists(string_ptr fn, bit_16 attr)
  239. BeginDeclarations
  240. bit_16                                 rc;
  241. EndDeclarations
  242. BeginCode
  243.  old_DTA = get_DTA_address();
  244.  set_DTA_address(DTA);
  245.  inregs.h.ah = 0x4E;                   /* Start file search */
  246.  segregs.ds  = Segment(String(fn));
  247.  inregs.x.dx = Offset(String(fn));
  248.  inregs.x.cx = attr;
  249.  rc = (bit_16) intdosx(Addr(inregs), Addr(outregs), Addr(segregs));
  250.  set_DTA_address(old_DTA);
  251.  return(rc IsZero);
  252. EndCode
  253.  
  254. /*+-------------------------------------------------------------------------+
  255.   |                                                                         |
  256.   |                              file_delete                                |
  257.   |                                                                         |
  258.   |                             O/S dependent                               |
  259.   |                                                                         |
  260.   +-------------------------------------------------------------------------+*/
  261. void file_delete(file_info_ptr file_info)
  262. BeginDeclarations
  263. #define File_info                      (*file_info)
  264. EndDeclarations
  265. BeginCode
  266.  inregs.h.ah = 0x41;                   /* Delete file */
  267.  inregs.x.dx = Offset(File_info.filename);
  268.  segregs.ds  = Segment(File_info.filename);
  269.  DOS_int21("Trouble deleting file \"%Fs\".\n",
  270.            File_info.filename);
  271.  return;
  272. EndCode
  273. #undef File_info
  274.  
  275. /*+-------------------------------------------------------------------------+
  276.   |                                                                         |
  277.   |                            file_IO_limit                                |
  278.   |                                                                         |
  279.   +-------------------------------------------------------------------------+*/
  280. void file_IO_limit(bit_16 limit)
  281. BeginDeclarations
  282. #define File                           infile
  283. EndDeclarations
  284. BeginCode
  285.  If (limit IsZero) OrIf (limit Exceeds File.buffer_size)
  286.   Then
  287.    File.IO_limit = File.buffer_size;
  288.   Else
  289.    File.IO_limit = limit;
  290.   EndIf;
  291.  return;
  292. EndCode
  293. #undef File
  294.  
  295. /*+-------------------------------------------------------------------------+
  296.   |                                                                         |
  297.   |                         file_open_for_read                              |
  298.   |                                                                         |
  299.   |                           O/S dependent                                 |
  300.   |                                                                         |
  301.   +-------------------------------------------------------------------------+*/
  302. void file_open_for_read(file_info_ptr file_info)
  303. BeginDeclarations
  304. #define File                           infile
  305. #define File_info                      (*file_info)
  306. EndDeclarations
  307. BeginCode
  308. /*+-------------------------------------------------------------------------+
  309.   |                                                                         |
  310.   |                    Initialize the data structure                        |
  311.   |                                                                         |
  312.   +-------------------------------------------------------------------------+*/
  313.  File.current_byte               = File.buffer;
  314.  File.IO_limit                   = File.buffer_size;
  315.  File.start_of_buffer_position   =
  316.  File.next_buffer_position       = 0L;
  317.  File.bytes_in_buffer            =
  318.  File.bytes_left_in_buffer       =
  319.  File.byte_position              = 0;
  320.  File.file_info                  = file_info;
  321. /*+-------------------------------------------------------------------------+
  322.   |                                                                         |
  323.   |                    Open the file and save the handle                    |
  324.   |                                                                         |
  325.   +-------------------------------------------------------------------------+*/
  326.  If compare_string(string(File_info.filename), device_AUX) IsZero
  327.   Then
  328.    File.file_handle = 3;
  329.    return;
  330.   EndIf;
  331.  If compare_string(string(File_info.filename), device_CON) IsZero
  332.   Then
  333.    File.file_handle = 0;
  334.    return;
  335.   EndIf;
  336.  If compare_string(string(File_info.filename), device_PRN) IsZero
  337.   Then
  338.    File.file_handle = 4;
  339.    return;
  340.   EndIf;
  341.  inregs.h.ah = 0x3D;                   /* Open for read */
  342.  inregs.h.al = 0x00;                   /* Access code */
  343.  inregs.x.dx = Offset(File_info.filename);
  344.  segregs.ds  = Segment(File_info.filename);
  345.  DOS_int21("Trouble opening \"%Fs\" for input.\n",
  346.            File_info.filename);
  347.  File.file_handle = outregs.x.ax;
  348.  return;
  349. EndCode
  350. #undef File
  351. #undef File_info
  352.  
  353. /*+-------------------------------------------------------------------------+
  354.   |                                                                         |
  355.   |                         file_open_for_write                             |
  356.   |                                                                         |
  357.   |                           O/S dependent                                 |
  358.   |                                                                         |
  359.   +-------------------------------------------------------------------------+*/
  360. void file_open_for_write(file_info_ptr file_info)
  361. BeginDeclarations
  362. #define File                           outfile
  363. #define File_info                      (*file_info)
  364. EndDeclarations
  365. BeginCode
  366. /*+-------------------------------------------------------------------------+
  367.   |                                                                         |
  368.   |                    Initialize the data structure                        |
  369.   |                                                                         |
  370.   +-------------------------------------------------------------------------+*/
  371.  File.current_byte               = File.buffer;
  372.  File.bytes_left_in_buffer       =
  373.  File.IO_limit                   = File.buffer_size;
  374.  File.start_of_buffer_position   =
  375.  File.next_buffer_position       = 0L;
  376.  File.bytes_in_buffer            =
  377.  File.byte_position              = 0;
  378.  File.file_info                  = file_info;
  379. /*+-------------------------------------------------------------------------+
  380.   |                                                                         |
  381.   |                    Open the file and save the handle                    |
  382.   |                                                                         |
  383.   +-------------------------------------------------------------------------+*/
  384.  If compare_string(string(File_info.filename), device_AUX) IsZero
  385.   Then
  386.    File.file_handle = 3;
  387.    return;
  388.   EndIf;
  389.  If compare_string(string(File_info.filename), device_CON) IsZero
  390.   Then
  391.    File.file_handle = 1;
  392.    return;
  393.   EndIf;
  394.  If compare_string(string(File_info.filename), device_PRN) IsZero
  395.   Then
  396.    File.file_handle = 4;
  397.    return;
  398.   EndIf;
  399.  inregs.h.ah = 0x3C;                   /* Open for write */
  400.  inregs.x.cx = 0x00;                   /* File attribute */
  401.  inregs.x.dx = Offset(File_info.filename);
  402.  segregs.ds  = Segment(File_info.filename);
  403.  DOS_int21("Trouble opening \"%Fs\" for output.\n",
  404.            File_info.filename);
  405.  File.file_handle = outregs.x.ax;
  406.  return;
  407. EndCode
  408. #undef File
  409. #undef File_info
  410.  
  411. /*+-------------------------------------------------------------------------+
  412.   |                                                                         |
  413.   |                           file_position                                 |
  414.   |                                                                         |
  415.   |                           O/S dependent                                 |
  416.   |                                                                         |
  417.   +-------------------------------------------------------------------------+*/
  418. void file_position(bit_32 position)
  419. BeginDeclarations
  420. #define File                           infile
  421. EndDeclarations
  422. BeginCode
  423.  If (position NotLessThan File.start_of_buffer_position) AndIf
  424.     (position LessThan    File.next_buffer_position)
  425.   Then
  426.    File.byte_position        = Bit_16(position-File.start_of_buffer_position);
  427.    File.current_byte         = Addr(File.buffer[File.byte_position]);
  428.    File.bytes_left_in_buffer = File.bytes_in_buffer - File.byte_position;
  429.   Else
  430.    inregs.h.ah = 0x42;                   /* Move file pointer */
  431.    inregs.h.al = 0x00;                   /* Relative to start of file */
  432.    inregs.x.bx = File.file_handle;
  433.    inregs.x.cx = High(position);
  434.    inregs.x.dx = Low(position);
  435.    DOS_int21("Trouble positioning file \"%Fs\" to byte %lu.\n",
  436.              (*File.file_info).filename, position);
  437.    File.start_of_buffer_position   =
  438.    File.next_buffer_position       = position;
  439.    File.byte_position              =
  440.    File.bytes_in_buffer            =
  441.    File.bytes_left_in_buffer       = 0;
  442.    File.current_byte               = File.buffer;
  443.   EndIf;
  444.  return;
  445. EndCode
  446. #undef File
  447.  
  448. /*+-------------------------------------------------------------------------+
  449.   |                                                                         |
  450.   |                               file_read                                 |
  451.   |                                                                         |
  452.   |                             O/S dependent                               |
  453.   |                                                                         |
  454.   +-------------------------------------------------------------------------+*/
  455. void file_read(byte_ptr into, bit_16 length)
  456. BeginDeclarations
  457. #define File                           infile
  458. EndDeclarations
  459. BeginCode
  460.  While length Exceeds 0
  461.   BeginWhile
  462.    If length Exceeds File.bytes_left_in_buffer
  463.     Then
  464.      If File.bytes_left_in_buffer Exceeds 0
  465.       Then
  466.        far_move(into, File.current_byte, File.bytes_left_in_buffer);
  467.        length -= File.bytes_left_in_buffer;
  468.        into   += File.bytes_left_in_buffer;
  469.       EndIf;
  470.      inregs.h.ah = 0x3F;               /* Read */
  471.      inregs.x.bx = File.file_handle;
  472.      inregs.x.cx = File.IO_limit;
  473.      inregs.x.dx = Offset(File.buffer);
  474.      segregs.ds  = Segment(File.buffer);
  475.      DOS_int21("Trouble reading file \"%Fs\" at byte %lu.\n",
  476.                (*File.file_info).filename, File.next_buffer_position);
  477.      File.bytes_in_buffer            =
  478.      File.bytes_left_in_buffer       = outregs.x.ax;
  479.      File.current_byte               = File.buffer;
  480.      File.byte_position              = 0;
  481.      File.start_of_buffer_position   = File.next_buffer_position;
  482.      File.next_buffer_position       = File.start_of_buffer_position +
  483.                                        File.bytes_in_buffer;
  484.     Else
  485.      far_move(into, File.current_byte, length);
  486.      into                      += length;
  487.      File.current_byte         += length;
  488.      File.bytes_left_in_buffer -= length;
  489.      File.byte_position        += length;
  490.      length                     = 0;
  491.     EndIf;
  492.   EndWhile;
  493.  return;
  494. EndCode
  495. #undef File
  496.  
  497. /*+-------------------------------------------------------------------------+
  498.   |                                                                         |
  499.   |                              file_write                                 |
  500.   |                                                                         |
  501.   |                             O/S dependent                               |
  502.   |                                                                         |
  503.   +-------------------------------------------------------------------------+*/
  504. void file_write(byte_ptr from, bit_32 length)
  505. BeginDeclarations
  506. #define File                           outfile
  507. EndDeclarations
  508. BeginCode
  509.  While length Exceeds 0L
  510.   BeginWhile
  511.    If length Exceeds Bit_32(File.bytes_left_in_buffer)
  512.     Then
  513.      far_move(File.current_byte, from, File.bytes_left_in_buffer);
  514.      length               -= Bit_32(File.bytes_left_in_buffer);
  515.      from                 += File.bytes_left_in_buffer;
  516.      File.bytes_in_buffer += File.bytes_left_in_buffer;
  517.      inregs.h.ah = 0x40;               /* Write */
  518.      inregs.x.bx = File.file_handle;
  519.      inregs.x.cx = File.bytes_in_buffer;
  520.      inregs.x.dx = Offset(File.buffer);
  521.      segregs.ds  = Segment(File.buffer);
  522.      DOS_int21("Trouble writing file \"%Fs\" at byte %lu.\n",
  523.                (*File.file_info).filename, File.next_buffer_position);
  524.      File.current_byte               = File.buffer;
  525.      File.bytes_left_in_buffer       = File.buffer_size;
  526.      File.bytes_in_buffer            =
  527.      File.byte_position              = 0;
  528.      File.start_of_buffer_position   = File.next_buffer_position;
  529.      File.next_buffer_position       = File.start_of_buffer_position +
  530.                                        File.bytes_left_in_buffer;
  531.     Else
  532.      far_move(File.current_byte, from, Bit_16(length));
  533.      from                      += Bit_16(length);
  534.      File.current_byte         += Bit_16(length);
  535.      File.bytes_left_in_buffer -= Bit_16(length);
  536.      File.byte_position        += Bit_16(length);
  537.      File.bytes_in_buffer      += Bit_16(length);
  538.      length                     = 0;
  539.     EndIf;
  540.   EndWhile;
  541.  return;
  542. EndCode
  543. #undef File
  544.  
  545. /*+-------------------------------------------------------------------------+
  546.   |                                                                         |
  547.   |                        get_DTA_address                                  |
  548.   |                                                                         |
  549.   |                         O/S dependent                                   |
  550.   |                                                                         |
  551.   +-------------------------------------------------------------------------+*/
  552. DTA_ptr get_DTA_address()
  553. BeginDeclarations
  554. DTA_ptr                                DTA_address;
  555. EndDeclarations
  556. BeginCode
  557.  inregs.h.ah = 0x2F;                   /* Get DTA address */
  558.  intdosx(Addr(inregs), Addr(outregs), Addr(segregs));
  559.  DTA_address = (DTA_ptr) MakeFarPtr(segregs.es, outregs.x.bx);
  560.  return(DTA_address);
  561. EndCode
  562.  
  563. /*+-------------------------------------------------------------------------+
  564.   |                                                                         |
  565.   |                       process_filename                                  |
  566.   |                                                                         |
  567.   +-------------------------------------------------------------------------+*/
  568. string_ptr process_filename(string_ptr fn)
  569. BeginDeclarations
  570. bit_16                                 left;
  571. bit_16                                 right;
  572. EndDeclarations
  573. BeginCode
  574.  lowercase_string(fn);
  575. /*+-------------------------------------------------------------------------+
  576.   |                                                                         |
  577.   |                       Check for AUX:, CON: & PRN:                       |
  578.   |                                                                         |
  579.   +-------------------------------------------------------------------------+*/
  580.  If compare_string(substr(fn,0,4), device_AUX) IsZero
  581.   Then
  582.    copy_string(fn, device_AUX);
  583.    return(fn);
  584.   EndIf;
  585.  If compare_string(substr(fn,0,4), device_CON) IsZero
  586.   Then
  587.    copy_string(fn, device_CON);
  588.    return(fn);
  589.   EndIf;
  590.  If compare_string(substr(fn,0,4), device_PRN) IsZero
  591.   Then
  592.    copy_string(fn, device_PRN);
  593.    return(fn);               
  594.   EndIf;
  595. /*+-------------------------------------------------------------------------+
  596.   |                                                                         |
  597.   |                      Add drive designator if missing.                   |
  598.   |                                                                         |
  599.   +-------------------------------------------------------------------------+*/
  600.  If compare_string(substr(fn,1,1), colon_string) IsNotZero
  601.   Then
  602.    paste_string(fn, 0, default_drive_string);
  603.   EndIf;
  604. /*+-------------------------------------------------------------------------+
  605.   |                                                                         |
  606.   |          Substitute current directory if not based from root.           |
  607.   |                                                                         |
  608.   +-------------------------------------------------------------------------+*/
  609.  If compare_string(substr(fn,2,1), backslash_string) IsNotZero
  610.   Then
  611.    default_directory(fn, default_directory_string);
  612.    paste_string(fn, 2, default_directory_string);
  613.   EndIf;
  614. /*+-------------------------------------------------------------------------+
  615.   |                                                                         |
  616.   |            Scan out all \. and \.. from filename.                       |
  617.   |                                                                         |
  618.   +-------------------------------------------------------------------------+*/
  619.  left  = index_string(fn, -1, backslash_string);
  620.  right = index_string(fn, left+1, backslash_string);
  621.  While right IsNot 0xffff
  622.   BeginWhile
  623.    If compare_string(substr(fn,left,4), backslash_dot_dot_string) IsZero
  624.     Then
  625.      cut_string(fn, left, 3);
  626.      right = left;
  627.      left  = reverse_index_string(fn, right-1, backslash_string);
  628.      If left Is 0xffff
  629.       Then
  630.        return(null_string);
  631.       EndIf;
  632.      cut_string(fn, left, right-left);
  633.      right = index_string(fn, left+1, backslash_string);
  634.      ContinueLoop;
  635.     Else
  636.      If compare_string(substr(fn,left,3), backslash_dot_string) IsZero
  637.       Then
  638.        cut_string(fn, left, 2);
  639.        right = index_string(fn, left+1, backslash_string);
  640.        ContinueLoop;
  641.       EndIf;
  642.     EndIf;
  643.    left  = right;
  644.    right = index_string(fn, left+1, backslash_string);
  645.   EndWhile;
  646.  return(fn);
  647. EndCode
  648.  
  649. /*+-------------------------------------------------------------------------+
  650.   |                                                                         |
  651.   |                        set_DTA_address                                  |
  652.   |                                                                         |
  653.   |                         O/S dependent                                   |
  654.   |                                                                         |
  655.   +-------------------------------------------------------------------------+*/
  656. void set_DTA_address(DTA_ptr DTA_address)
  657. BeginDeclarations
  658. EndDeclarations
  659. BeginCode
  660.  inregs.h.ah = 0x1A;                   /* Set DTA address */
  661.  segregs.ds  = Segment(DTA_address);
  662.  inregs.x.dx = Offset(DTA_address);
  663.  intdosx(Addr(inregs), Addr(outregs), Addr(segregs));
  664.  return;
  665. EndCode
  666.  
  667. /*+-------------------------------------------------------------------------+
  668.   |                                                                         |
  669.   |                       start_file_search                                 |
  670.   |                                                                         |
  671.   |                         O/S dependent                                   |
  672.   |                                                                         |
  673.   +-------------------------------------------------------------------------+*/
  674. bit_16 start_file_search(string_ptr fn, bit_16 attr)
  675. BeginDeclarations
  676. bit_16                                 rc;
  677. EndDeclarations
  678. BeginCode
  679. /*+-------------------------------------------------------------------------+
  680.   |                                                                         |
  681.   |                         Set up a new DTA                                |
  682.   |                                                                         |
  683.   +-------------------------------------------------------------------------+*/
  684.  
  685.  old_DTA = get_DTA_address();
  686.  set_DTA_address(DTA);
  687.  
  688. /*+-------------------------------------------------------------------------+
  689.   |                                                                         |
  690.   |                  Remember the current file path                         |
  691.   |                                                                         |
  692.   +-------------------------------------------------------------------------+*/
  693.  
  694.  copy_string(current_path, fn);
  695.  trunc_string(current_path,
  696.               reverse_index_string(current_path, 0xFFFF, backslash_string)+1);
  697.  inregs.h.ah = 0x4E;                   /* Start file search */
  698.  segregs.ds  = Segment(String(fn));
  699.  inregs.x.dx = Offset(String(fn));
  700.  inregs.x.cx = attr;
  701.  rc = (bit_16) intdosx(Addr(inregs), Addr(outregs), Addr(segregs));
  702.  set_DTA_address(old_DTA);
  703.  If rc IsNotZero
  704.   Then
  705.    copy_string(current_filename, null_string);
  706.   Else
  707.    far_to_lower((*DTA).filename, 12);
  708.    copy_string(current_filename, current_path);
  709.    concat_string(current_filename, string((*DTA).filename));
  710.   EndIf;
  711.  return(rc);
  712. EndCode
  713.  
  714.