plat/msdos86: add isatty( ), _setmode( ), read( ), write( )
This commit is contained in:
parent
2dfddf3fa8
commit
0d2b55cd29
|
@ -73,6 +73,8 @@ name led
|
|||
{FLOATS?} \
|
||||
(.e:{TAIL}={PLATFORMDIR}/libem.a \
|
||||
{PLATFORMDIR}/libsys.a \
|
||||
{PLATFORMDIR}/libc.a \
|
||||
{PLATFORMDIR}/libem.a \
|
||||
{PLATFORMDIR}/libend.a)
|
||||
linker
|
||||
end
|
||||
|
|
12
plat/msdos86/include/ack/plat.h
Normal file
12
plat/msdos86/include/ack/plat.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
/* $Source$
|
||||
* $State$
|
||||
* $Revision$
|
||||
*/
|
||||
|
||||
#ifndef _ACK_PLAT_H
|
||||
#define _ACK_PLAT_H
|
||||
|
||||
#define ACKCONF_WANT_O_TEXT_O_BINARY 1
|
||||
#define ACKCONF_WANT_EMULATED_TIME 0
|
||||
|
||||
#endif
|
24
plat/msdos86/include/build.lua
Normal file
24
plat/msdos86/include/build.lua
Normal file
|
@ -0,0 +1,24 @@
|
|||
include("plat/build.lua")
|
||||
|
||||
headermap = {}
|
||||
packagemap = {}
|
||||
|
||||
local function addheader(h)
|
||||
headermap[h] = "./"..h
|
||||
packagemap["$(PLATIND)/msdos86/include/"..h] = "./"..h
|
||||
end
|
||||
|
||||
addheader("ack/plat.h")
|
||||
addheader("sys/types.h")
|
||||
|
||||
acklibrary {
|
||||
name = "headers",
|
||||
hdrs = headermap
|
||||
}
|
||||
|
||||
installable {
|
||||
name = "pkg",
|
||||
map = packagemap
|
||||
}
|
||||
|
||||
|
9
plat/msdos86/include/sys/types.h
Normal file
9
plat/msdos86/include/sys/types.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#ifndef _SYS_TYPES_H
|
||||
#define _SYS_TYPES_H
|
||||
|
||||
typedef int pid_t;
|
||||
typedef int mode_t;
|
||||
typedef long time_t;
|
||||
typedef long suseconds_t;
|
||||
|
||||
#endif
|
19
plat/msdos86/libsys/_hol0.s
Normal file
19
plat/msdos86/libsys/_hol0.s
Normal file
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
! $Source$
|
||||
! $State$
|
||||
! $Revision$
|
||||
|
||||
! Declare segments (the order is important).
|
||||
|
||||
.sect .text
|
||||
.sect .rom
|
||||
.sect .data
|
||||
.sect .bss
|
||||
|
||||
.sect .bss
|
||||
|
||||
! This data block is used to store information about the current line number
|
||||
! and file.
|
||||
|
||||
.define hol0
|
||||
.comm hol0, 8
|
59
plat/msdos86/libsys/brk.c
Normal file
59
plat/msdos86/libsys/brk.c
Normal file
|
@ -0,0 +1,59 @@
|
|||
/* $Source$
|
||||
* $State$
|
||||
* $Revision$
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include "libsys.h"
|
||||
|
||||
#define STACK_BUFFER 128 /* number of bytes to leave for stack */
|
||||
|
||||
extern char _end[1];
|
||||
static char* current = _end;
|
||||
|
||||
int brk(void* newend)
|
||||
{
|
||||
/* This variable is used to figure out the current stack pointer,
|
||||
* by taking its address. */
|
||||
char dummy;
|
||||
char* p = newend;
|
||||
|
||||
if ((p > (&dummy - STACK_BUFFER)) ||
|
||||
(p < _end))
|
||||
{
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
current = p;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* sbrk(int increment)
|
||||
{
|
||||
char* old;
|
||||
char* new;
|
||||
|
||||
if (increment == 0)
|
||||
return current;
|
||||
|
||||
old = current;
|
||||
|
||||
new = old + increment;
|
||||
|
||||
if ((increment > 0) && (new <= old))
|
||||
goto out_of_memory;
|
||||
else if ((increment < 0) && (new >= old))
|
||||
goto out_of_memory;
|
||||
|
||||
if (brk(new) < 0)
|
||||
goto out_of_memory;
|
||||
|
||||
return old;
|
||||
|
||||
out_of_memory:
|
||||
errno = ENOMEM;
|
||||
return OUT_OF_MEMORY;
|
||||
}
|
15
plat/msdos86/libsys/build.lua
Normal file
15
plat/msdos86/libsys/build.lua
Normal file
|
@ -0,0 +1,15 @@
|
|||
acklibrary {
|
||||
name = "lib",
|
||||
srcs = {
|
||||
"./*.c",
|
||||
"./*.s",
|
||||
},
|
||||
deps = {
|
||||
"lang/cem/libcc.ansi/headers+headers",
|
||||
"plat/msdos86/include+headers",
|
||||
},
|
||||
vars = {
|
||||
plat = "msdos86"
|
||||
}
|
||||
}
|
||||
|
14
plat/msdos86/libsys/creat.c
Normal file
14
plat/msdos86/libsys/creat.c
Normal file
|
@ -0,0 +1,14 @@
|
|||
/* $Source$
|
||||
* $State$
|
||||
* $Revision$
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include "libsys.h"
|
||||
|
||||
int creat(const char* path, int mode)
|
||||
{
|
||||
return open(path, O_CREAT|O_WRONLY|O_TRUNC, mode);
|
||||
}
|
37
plat/msdos86/libsys/isatty.s
Normal file
37
plat/msdos86/libsys/isatty.s
Normal file
|
@ -0,0 +1,37 @@
|
|||
#
|
||||
! $Source$
|
||||
! $State$
|
||||
! $Revision$
|
||||
|
||||
! Declare segments (the order is important).
|
||||
|
||||
.sect .text
|
||||
.sect .rom
|
||||
.sect .data
|
||||
.sect .bss
|
||||
|
||||
.sect .text
|
||||
|
||||
! Say whether a given file descriptor number refers to a terminal.
|
||||
|
||||
.define _isatty
|
||||
_isatty:
|
||||
mov bx, sp
|
||||
mov bx, 2(bx)
|
||||
mov ax, 0x4400
|
||||
int 0x21
|
||||
jc error
|
||||
testb dl, dl
|
||||
jz not_tty
|
||||
mov ax, 1
|
||||
ret
|
||||
not_tty:
|
||||
mov (_errno), 25 ! ENOTTY
|
||||
not_tty_2:
|
||||
xor ax, ax
|
||||
ret
|
||||
error:
|
||||
push ax
|
||||
call __sys_seterrno
|
||||
pop cx
|
||||
jmp not_tty_2
|
53
plat/msdos86/libsys/libsys.h
Normal file
53
plat/msdos86/libsys/libsys.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
/* $Source$
|
||||
* $State$
|
||||
* $Revision$
|
||||
*/
|
||||
|
||||
#ifndef LIBSYS_H
|
||||
#define LIBSYS_H
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define OUT_OF_MEMORY ((void *)-1) /* sbrk returns this on failure */
|
||||
|
||||
/*
|
||||
* Data structure for remembering whether each file descriptor is open in
|
||||
* text mode (O_TEXT) or binary mode (O_BINARY).
|
||||
*
|
||||
* Currently this is just a simple linked list, where each linked list node
|
||||
* records the modes for 16 file descriptors, in bit vector form (0: text,
|
||||
* 1: binary). In addition, each node also remembers, for each of its file
|
||||
* descriptors, whether an end-of-file (^Z) character was encountered when
|
||||
* reading from it in text mode.
|
||||
*
|
||||
* List nodes are allocated using sbrk() and never freed.
|
||||
*
|
||||
* This scheme should be fast and light enough, as the number of open file
|
||||
* descriptors is expected to be small.
|
||||
*
|
||||
* FIXME: the code for updating this structure is not exactly thread-safe.
|
||||
*/
|
||||
typedef uint16_t _fdvec_t;
|
||||
|
||||
struct _fdmodes {
|
||||
struct _fdmodes *next;
|
||||
int begfd;
|
||||
_fdvec_t modevec, eofvec;
|
||||
};
|
||||
|
||||
extern struct _fdmodes _sys_fdmodes;
|
||||
|
||||
#define _FDVECMASK (sizeof(_fdvec_t) * CHAR_BIT - 1)
|
||||
|
||||
extern int _sys_getmode(int);
|
||||
extern int _sys_setmode(int, int);
|
||||
extern int _sys_iseof(int);
|
||||
extern int _sys_seteof(int, int);
|
||||
extern ssize_t _sys_rawread(int, char *, size_t);
|
||||
extern ssize_t _sys_rawwrite(int, const char *, size_t);
|
||||
extern int _sys_isopen(int);
|
||||
extern int _sys_isreadyr(int);
|
||||
|
||||
#endif
|
77
plat/msdos86/libsys/read.c
Normal file
77
plat/msdos86/libsys/read.c
Normal file
|
@ -0,0 +1,77 @@
|
|||
/* $Source$
|
||||
* $State$
|
||||
* $Revision$
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include "libsys.h"
|
||||
|
||||
ssize_t read(int fd, void* buffer, size_t count)
|
||||
{
|
||||
char *p, *q;
|
||||
ssize_t r, tot;
|
||||
size_t left;
|
||||
int eof = 0;
|
||||
|
||||
if (!count || _sys_getmode(fd) == O_BINARY)
|
||||
return _sys_rawread(fd, buffer, count);
|
||||
|
||||
if (_sys_iseof(fd))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If the file descriptor is an O_TEXT fd, read from it, and then
|
||||
* remove CRs from the input. After removing CRs, if the buffer is
|
||||
* not filled and the fd still has bytes left to read, then keep
|
||||
* reading, and keep removing CRs.
|
||||
*
|
||||
* Also handle end-of-file indicators (^Z). If we see one, move the
|
||||
* file pointer to just before the ^Z. Also set an internal flag
|
||||
* for the fd so that we do not try to read any further (until e.g.
|
||||
* a seek happens).
|
||||
*/
|
||||
p = buffer;
|
||||
tot = 0;
|
||||
|
||||
do
|
||||
{
|
||||
r = _sys_rawread(fd, p, count - (p - (char *)buffer));
|
||||
if (r <= 0)
|
||||
return tot;
|
||||
|
||||
q = memchr(p, 0x1a, (size_t)r);
|
||||
if (q)
|
||||
{
|
||||
_sys_rawlseek(fd, (off_t)(q - p) - r, SEEK_CUR);
|
||||
r = q - p;
|
||||
eof = 1;
|
||||
_sys_seteof(fd, 1);
|
||||
}
|
||||
|
||||
q = memchr(p, '\r', (size_t)r);
|
||||
if (!q)
|
||||
return tot + r;
|
||||
|
||||
tot += q - p;
|
||||
left = r - (q + 1 - p);
|
||||
p = q;
|
||||
++q;
|
||||
|
||||
while (left)
|
||||
{
|
||||
char c = *q++;
|
||||
if (c != '\r')
|
||||
{
|
||||
*p++ = c;
|
||||
++tot;
|
||||
}
|
||||
--left;
|
||||
}
|
||||
} while (tot < count && !eof && _sys_isreadyr(fd));
|
||||
|
||||
return tot;
|
||||
}
|
23
plat/msdos86/libsys/setmode.c
Normal file
23
plat/msdos86/libsys/setmode.c
Normal file
|
@ -0,0 +1,23 @@
|
|||
/* $Source$
|
||||
* $State$
|
||||
* $Revision$
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include "libsys.h"
|
||||
|
||||
int _setmode(int fd, int mode)
|
||||
{
|
||||
if (mode != O_TEXT && mode != O_BINARY)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (!_sys_isopen(fd))
|
||||
{
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
return _sys_setmode(fd, mode);
|
||||
}
|
13
plat/msdos86/libsys/sys_fdmodes.c
Normal file
13
plat/msdos86/libsys/sys_fdmodes.c
Normal file
|
@ -0,0 +1,13 @@
|
|||
/* $Source$
|
||||
* $State$
|
||||
* $Revision$
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "libsys.h"
|
||||
|
||||
/*
|
||||
* By default, consider all file descriptors, including those for stdin (0),
|
||||
* stdout (1), and stderr (2), as being open in text mode.
|
||||
*/
|
||||
struct _fdmodes _sys_fdmodes = { NULL, 0, 0 };
|
27
plat/msdos86/libsys/sys_getmode.c
Normal file
27
plat/msdos86/libsys/sys_getmode.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
/* $Source$
|
||||
* $State$
|
||||
* $Revision$
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include "libsys.h"
|
||||
|
||||
/*
|
||||
* Say whether a particular fd is currently open in text or binary mode.
|
||||
* Assume that the fd is valid. Return O_TEXT or O_BINARY.
|
||||
*/
|
||||
int _sys_getmode(int fd)
|
||||
{
|
||||
int reqbegfd = fd & ~_FDVECMASK;
|
||||
struct _fdmodes *p = &_sys_fdmodes;
|
||||
_fdvec_t mask;
|
||||
|
||||
while (p->begfd != reqbegfd)
|
||||
{
|
||||
p = p->next;
|
||||
if (!p)
|
||||
return O_TEXT;
|
||||
}
|
||||
mask = (_fdvec_t)1 << (fd & _FDVECMASK);
|
||||
return (p->modevec & mask) ? O_BINARY : O_TEXT;
|
||||
}
|
|
@ -6,8 +6,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define OUT_OF_MEMORY (void*)(-1) /* sbrk returns this on failure */
|
||||
#include "libsys.h"
|
||||
|
||||
struct for_main {
|
||||
int argc;
|
||||
|
|
27
plat/msdos86/libsys/sys_iseof.c
Normal file
27
plat/msdos86/libsys/sys_iseof.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
/* $Source$
|
||||
* $State$
|
||||
* $Revision$
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include "libsys.h"
|
||||
|
||||
/*
|
||||
* Say whether a particular fd is currently open in text mode and has just
|
||||
* hit an MS-DOS end-of-file character (^Z).
|
||||
*/
|
||||
int _sys_iseof(int fd)
|
||||
{
|
||||
int reqbegfd = fd & ~_FDVECMASK;
|
||||
struct _fdmodes *p = &_sys_fdmodes;
|
||||
_fdvec_t mask;
|
||||
|
||||
while (p->begfd != reqbegfd)
|
||||
{
|
||||
p = p->next;
|
||||
if (!p)
|
||||
return 0;
|
||||
}
|
||||
mask = (_fdvec_t)1 << (fd & _FDVECMASK);
|
||||
return p->eofvec & mask;
|
||||
}
|
26
plat/msdos86/libsys/sys_isopen.s
Normal file
26
plat/msdos86/libsys/sys_isopen.s
Normal file
|
@ -0,0 +1,26 @@
|
|||
#
|
||||
! $Source$
|
||||
! $State$
|
||||
! $Revision$
|
||||
|
||||
! Declare segments (the order is important).
|
||||
|
||||
.sect .text
|
||||
.sect .rom
|
||||
.sect .data
|
||||
.sect .bss
|
||||
|
||||
.sect .text
|
||||
|
||||
! Say whether a given file descriptor number refers to a valid open file
|
||||
! descriptor.
|
||||
|
||||
.define __sys_isopen
|
||||
__sys_isopen:
|
||||
mov bx, sp
|
||||
mov bx, 2(bx)
|
||||
mov ax, 0x4400
|
||||
int 0x21
|
||||
sbb ax, ax
|
||||
inc ax
|
||||
ret
|
28
plat/msdos86/libsys/sys_isreadyr.s
Normal file
28
plat/msdos86/libsys/sys_isreadyr.s
Normal file
|
@ -0,0 +1,28 @@
|
|||
#
|
||||
! $Source$
|
||||
! $State$
|
||||
! $Revision$
|
||||
|
||||
! Declare segments (the order is important).
|
||||
|
||||
.sect .text
|
||||
.sect .rom
|
||||
.sect .data
|
||||
.sect .bss
|
||||
|
||||
.sect .text
|
||||
|
||||
! Say whether a file descriptor is ready for input, i.e. reading from the
|
||||
! fd will immediately return something.
|
||||
|
||||
.define __sys_isreadyr
|
||||
__sys_isreadyr:
|
||||
mov bx, sp
|
||||
mov ax, 0x4406
|
||||
mov bx, 2(bx)
|
||||
int 0x21
|
||||
jnc ok
|
||||
movb al, 0
|
||||
ok:
|
||||
cbw
|
||||
ret
|
33
plat/msdos86/libsys/sys_rawrw.s
Normal file
33
plat/msdos86/libsys/sys_rawrw.s
Normal file
|
@ -0,0 +1,33 @@
|
|||
#
|
||||
! $Source$
|
||||
! $State$
|
||||
! $Revision$
|
||||
|
||||
! Declare segments (the order is important).
|
||||
|
||||
.sect .text
|
||||
.sect .rom
|
||||
.sect .data
|
||||
.sect .bss
|
||||
|
||||
.sect .text
|
||||
|
||||
! Read/write bytes to/to a file descriptor. These routines do not do any
|
||||
! translation between CRLF and LF line endings.
|
||||
!
|
||||
! Note that, for MS-DOS, a raw "write" request of zero bytes will truncate
|
||||
! (or extend) the file to the current file position.
|
||||
|
||||
.define __sys_rawread
|
||||
__sys_rawread:
|
||||
movb ah, 0x3f
|
||||
.data1 0x3d ! eat up the next instruction
|
||||
.define __sys_rawwrite
|
||||
__sys_rawwrite:
|
||||
movb ah, 0x40
|
||||
mov bx, sp
|
||||
mov dx, 4(bx)
|
||||
mov cx, 6(bx)
|
||||
mov bx, 2(bx)
|
||||
int 0x21
|
||||
jmp .sys_axret
|
42
plat/msdos86/libsys/sys_seteof.c
Normal file
42
plat/msdos86/libsys/sys_seteof.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
/* $Source$
|
||||
* $State$
|
||||
* $Revision$
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include "libsys.h"
|
||||
|
||||
/*
|
||||
* Set or reset the "end-of-file encountered" indicator for a particular fd.
|
||||
* Assume that the fd is valid, and is being read from in text mode.
|
||||
*/
|
||||
int _sys_seteof(int fd, int eof)
|
||||
{
|
||||
int reqbegfd = fd & ~_FDVECMASK;
|
||||
struct _fdmodes *p = &_sys_fdmodes;
|
||||
_fdvec_t mask;
|
||||
|
||||
while (p->begfd != reqbegfd)
|
||||
{
|
||||
p = p->next;
|
||||
if (!p)
|
||||
{
|
||||
if (!eof)
|
||||
return 0;
|
||||
if ((p = sbrk(sizeof(struct _fdmodes)))
|
||||
== OUT_OF_MEMORY)
|
||||
return -1;
|
||||
p->next = _sys_fdmodes.next;
|
||||
p->begfd = reqbegfd;
|
||||
p->modevec = p->eofvec = 0;
|
||||
_sys_fdmodes.next = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mask = (_fdvec_t)1 << (fd & _FDVECMASK);
|
||||
if (eof)
|
||||
p->eofvec |= mask;
|
||||
else
|
||||
p->eofvec &= ~mask;
|
||||
return 0;
|
||||
}
|
55
plat/msdos86/libsys/sys_setmode.c
Normal file
55
plat/msdos86/libsys/sys_setmode.c
Normal file
|
@ -0,0 +1,55 @@
|
|||
/* $Source$
|
||||
* $State$
|
||||
* $Revision$
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include "libsys.h"
|
||||
|
||||
/*
|
||||
* Set text/binary mode for a particular fd. Assume that the fd is valid,
|
||||
* and that the mode is either O_TEXT or O_BINARY.
|
||||
*
|
||||
* Return the previous mode (either O_TEXT or O_BINARY) on success, -1 (with
|
||||
* errno set) on error.
|
||||
*/
|
||||
int _sys_setmode(int fd, int mode)
|
||||
{
|
||||
int reqbegfd = fd & ~_FDVECMASK;
|
||||
struct _fdmodes *p = &_sys_fdmodes;
|
||||
_fdvec_t mask;
|
||||
|
||||
while (p->begfd != reqbegfd)
|
||||
{
|
||||
p = p->next;
|
||||
if (!p)
|
||||
{
|
||||
if (mode == O_TEXT)
|
||||
return O_TEXT;
|
||||
if ((p = sbrk(sizeof(struct _fdmodes)))
|
||||
== OUT_OF_MEMORY)
|
||||
return -1;
|
||||
p->next = _sys_fdmodes.next;
|
||||
p->begfd = reqbegfd;
|
||||
p->modevec = p->eofvec = 0;
|
||||
_sys_fdmodes.next = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mask = (_fdvec_t)1 << (fd & _FDVECMASK);
|
||||
if (mode == O_BINARY)
|
||||
{
|
||||
if (p->modevec & mask)
|
||||
return O_BINARY;
|
||||
p->modevec |= mask;
|
||||
p->eofvec &= ~mask;
|
||||
return O_TEXT;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(p->modevec & mask))
|
||||
return O_TEXT;
|
||||
p->modevec &= ~mask;
|
||||
return O_BINARY;
|
||||
}
|
||||
}
|
61
plat/msdos86/libsys/write.c
Normal file
61
plat/msdos86/libsys/write.c
Normal file
|
@ -0,0 +1,61 @@
|
|||
/* $Source$
|
||||
* $State$
|
||||
* $Revision$
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include "libsys.h"
|
||||
|
||||
ssize_t write(int fd, void* buffer, size_t count)
|
||||
{
|
||||
static const char crlf[2] = "\r\n";
|
||||
int i;
|
||||
char *p, *q;
|
||||
size_t left, n;
|
||||
ssize_t r, tot;
|
||||
|
||||
if (!count)
|
||||
return 0;
|
||||
|
||||
if (_sys_getmode(fd) == O_BINARY)
|
||||
return _sys_rawwrite(fd, buffer, count);
|
||||
|
||||
/* If the file descriptor is an O_TEXT fd, translate LFs to CRLFs. */
|
||||
p = buffer;
|
||||
left = count;
|
||||
tot = 0;
|
||||
while (left)
|
||||
{
|
||||
q = memchr(p, '\n', left);
|
||||
if (!q)
|
||||
return _sys_rawwrite(fd, p, left);
|
||||
|
||||
n = q - p;
|
||||
if (n)
|
||||
{
|
||||
r = _sys_rawwrite(fd, p, n);
|
||||
if (r <= 0)
|
||||
return tot ? tot : r;
|
||||
tot += r;
|
||||
p += r;
|
||||
left -= r;
|
||||
if (r != n)
|
||||
break;
|
||||
}
|
||||
|
||||
r = _sys_rawwrite(fd, crlf, sizeof crlf);
|
||||
if (r != 2)
|
||||
{
|
||||
if (r > 0)
|
||||
r = 0;
|
||||
return tot ? tot : r;
|
||||
}
|
||||
++tot;
|
||||
++p;
|
||||
--left;
|
||||
}
|
||||
return tot;
|
||||
}
|
Loading…
Reference in a new issue