www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/1996/04/12/22:35:27

Date: Fri, 12 Apr 1996 22:33:27 -0400
From: dj (DJ Delorie)
Message-Id: <199604130233.WAA04438@delorie.com>
To: djgpp-workers
Subject: new write.c

Here is a rewritten write() function, that in theory should optimize
buffer use and transfer size when writing in text mode, and won't need
to call malloc() at all.  Comments?

Unfortunately, this breaks the file system extensions, so I was
thinking of moving those to the posix layer (i.e. \n is never
converted to \r\n), which might be better anyway - stuff talking to
devices or tcp/ip probably doesn't want the conversion by default.

DJ


/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
#include <libc/stubs.h>
#include <unistd.h>
#include <fcntl.h>
#include <go32.h>
#include <dpmi.h>
#include <io.h>
#include <errno.h>
#include <libc/farptrgs.h>

#include <libc/dosio.h>

#define tblen _go32_info_block.size_of_transfer_buffer

ssize_t
write(int handle, const void* buffer, size_t count)
{
  const char *buf = (const char *)buffer;
  int bytes_in_tb = 0;
  int offset_into_buf = 0;
  __dpmi_regs r;

  if (count == 0)
    return 0; /* POSIX.1 requires this */

  if(__file_handle_modes[handle] & O_BINARY)
    return _write(handle, buf, count);

  while (offset_into_buf < count)
  {
    _farsetsel(_dos_ds);
    while (bytes_in_tb < tblen && offset_into_buf < count)
    {
      if (buf[offset_into_buf] == '\n')
      {
	if (bytes_in_tb == tblen - 1)
	  break; /* can't fit two more */
	_farnspokeb(__tb + bytes_in_tb, '\r');
	bytes_in_tb++;
      }
      _farnspokeb(__tb + bytes_in_tb, buf[offset_into_buf]);
      bytes_in_tb++;
      offset_into_buf++;
    }

    /* we now have a transfer buf stuffed with data; write it out */
    r.x.ax = 0x4000;
    r.x.bx = handle;
    r.x.cx = bytes_in_tb;
    r.x.dx = __tb & 15;
    r.x.ds = __tb / 16;
    __dpmi_int(0x21, &r);
    if (r.x.flags & 1)
    {
      errno = __doserr_to_errno(r.x.ax);
      return -1;
    }

    if (r.x.ax < bytes_in_tb) /* disk full? */
      return count - offset_into_buf;

    bytes_in_tb = 0;
  }

  return count;	/* Don't return count with CR's (TC) */
}

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019