io.c revision f765521f
15dfecf96Smrg/*
25dfecf96Smrg * Copyright (c) 2002 by The XFree86 Project, Inc.
35dfecf96Smrg *
45dfecf96Smrg * Permission is hereby granted, free of charge, to any person obtaining a
55dfecf96Smrg * copy of this software and associated documentation files (the "Software"),
65dfecf96Smrg * to deal in the Software without restriction, including without limitation
75dfecf96Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
85dfecf96Smrg * and/or sell copies of the Software, and to permit persons to whom the
95dfecf96Smrg * Software is furnished to do so, subject to the following conditions:
105dfecf96Smrg *
115dfecf96Smrg * The above copyright notice and this permission notice shall be included in
125dfecf96Smrg * all copies or substantial portions of the Software.
135dfecf96Smrg *
145dfecf96Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
155dfecf96Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
165dfecf96Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
175dfecf96Smrg * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
185dfecf96Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
195dfecf96Smrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
205dfecf96Smrg * SOFTWARE.
215dfecf96Smrg *
225dfecf96Smrg * Except as contained in this notice, the name of the XFree86 Project shall
235dfecf96Smrg * not be used in advertising or otherwise to promote the sale, use or other
245dfecf96Smrg * dealings in this Software without prior written authorization from the
255dfecf96Smrg * XFree86 Project.
265dfecf96Smrg *
275dfecf96Smrg * Author: Paulo César Pereira de Andrade
285dfecf96Smrg */
295dfecf96Smrg
305dfecf96Smrg/* $XFree86: xc/programs/xedit/lisp/io.c,v 1.16tsi Exp $ */
315dfecf96Smrg
325dfecf96Smrg#include "lisp/io.h"
335dfecf96Smrg#include <errno.h>
345dfecf96Smrg#include <fcntl.h>
355dfecf96Smrg#include <stdarg.h>
365dfecf96Smrg#include <sys/types.h>
375dfecf96Smrg#include <sys/stat.h>
385dfecf96Smrg
395dfecf96Smrg/* Match the FILE_XXX flags */
405dfecf96Smrg#define READ_BIT	0x01
415dfecf96Smrg#define WRITE_BIT	0x02
425dfecf96Smrg#define APPEND_BIT	0x04
435dfecf96Smrg#define BUFFERED_BIT	0x08
445dfecf96Smrg#define UNBUFFERED_BIT	0x10
455dfecf96Smrg#define BINARY_BIT	0x20
465dfecf96Smrg
475dfecf96Smrg
485dfecf96Smrg/*
495dfecf96Smrg * Initialization
505dfecf96Smrg */
515dfecf96Smrgextern int pagesize;
525dfecf96Smrg
535dfecf96Smrg/*
545dfecf96Smrg * Implementation
555dfecf96Smrg */
565dfecf96Smrgint
575dfecf96SmrgLispGet(void)
585dfecf96Smrg{
595dfecf96Smrg    int ch = EOF;
605dfecf96Smrg    LispUngetInfo *unget = lisp__data.unget[lisp__data.iunget];
615dfecf96Smrg
625dfecf96Smrg    if (unget->offset)
635dfecf96Smrg	ch = ((unsigned char*)unget->buffer)[--unget->offset];
645dfecf96Smrg    else if (SINPUT->data.stream.readable) {
655dfecf96Smrg	LispFile *file = NULL;
665dfecf96Smrg
675dfecf96Smrg	switch (SINPUT->data.stream.type) {
685dfecf96Smrg	    case LispStreamStandard:
695dfecf96Smrg	    case LispStreamFile:
705dfecf96Smrg		file = FSTREAMP(SINPUT);
715dfecf96Smrg		break;
725dfecf96Smrg	    case LispStreamPipe:
735dfecf96Smrg		file = IPSTREAMP(SINPUT);
745dfecf96Smrg		break;
755dfecf96Smrg	    case LispStreamString:
765dfecf96Smrg		ch = LispSgetc(SSTREAMP(SINPUT));
775dfecf96Smrg		break;
785dfecf96Smrg	    default:
795dfecf96Smrg		ch = EOF;
805dfecf96Smrg		break;
815dfecf96Smrg	}
825dfecf96Smrg	if (file != NULL) {
835dfecf96Smrg	    if (file->nonblock) {
845dfecf96Smrg		if (fcntl(file->descriptor, F_SETFL, 0) < 0)
855dfecf96Smrg		    LispDestroy("fcntl: %s", strerror(errno));
865dfecf96Smrg		file->nonblock = 0;
875dfecf96Smrg	    }
885dfecf96Smrg	    ch = LispFgetc(file);
895dfecf96Smrg	}
905dfecf96Smrg    }
915dfecf96Smrg    else
925dfecf96Smrg	LispDestroy("cannot read from *STANDARD-INPUT*");
935dfecf96Smrg
945dfecf96Smrg    if (ch == EOF)
955dfecf96Smrg	lisp__data.eof = 1;
965dfecf96Smrg
975dfecf96Smrg    return (ch);
985dfecf96Smrg}
995dfecf96Smrg
1005dfecf96Smrgint
1015dfecf96SmrgLispUnget(int ch)
1025dfecf96Smrg{
1035dfecf96Smrg    LispUngetInfo *unget = lisp__data.unget[lisp__data.iunget];
1045dfecf96Smrg
105c05e22d7Smrg    if ((ch & 0xff) == ch) {
106c05e22d7Smrg	if (unget->offset == sizeof(unget->buffer)) {
107c05e22d7Smrg	    LispWarning("character %c lost at LispUnget()", unget->buffer[0]);
108c05e22d7Smrg	    memmove(unget->buffer, unget->buffer + 1, unget->offset - 1);
109c05e22d7Smrg	    unget->buffer[unget->offset - 1] = ch;
110c05e22d7Smrg	}
111c05e22d7Smrg	else
112c05e22d7Smrg	    unget->buffer[unget->offset++] = ch;
1135dfecf96Smrg    }
1145dfecf96Smrg
1155dfecf96Smrg    return (ch);
1165dfecf96Smrg}
1175dfecf96Smrg
1185dfecf96Smrgvoid
1195dfecf96SmrgLispPushInput(LispObj *stream)
1205dfecf96Smrg{
1215dfecf96Smrg    if (!STREAMP(stream) || !stream->data.stream.readable)
1225dfecf96Smrg	LispDestroy("bad stream at PUSH-INPUT");
1235dfecf96Smrg    lisp__data.input_list = CONS(stream, lisp__data.input_list);
1245dfecf96Smrg    SINPUT = stream;
1255dfecf96Smrg    if (lisp__data.iunget + 1 == lisp__data.nunget) {
1265dfecf96Smrg	LispUngetInfo **info =
1275dfecf96Smrg	    realloc(lisp__data.unget,
1285dfecf96Smrg		    sizeof(LispUngetInfo) * (lisp__data.nunget + 1));
1295dfecf96Smrg
1305dfecf96Smrg	if (!info ||
1315dfecf96Smrg	    (info[lisp__data.nunget] =
1325dfecf96Smrg	     calloc(1, sizeof(LispUngetInfo))) == NULL)
1335dfecf96Smrg	    LispDestroy("out of memory");
1345dfecf96Smrg	lisp__data.unget = info;
1355dfecf96Smrg	++lisp__data.nunget;
1365dfecf96Smrg    }
1375dfecf96Smrg    ++lisp__data.iunget;
1385dfecf96Smrg    memset(lisp__data.unget[lisp__data.iunget], '\0', sizeof(LispUngetInfo));
1395dfecf96Smrg    lisp__data.eof = 0;
1405dfecf96Smrg}
1415dfecf96Smrg
1425dfecf96Smrgvoid
1435dfecf96SmrgLispPopInput(LispObj *stream)
1445dfecf96Smrg{
1455dfecf96Smrg    if (!CONSP(lisp__data.input_list) || stream != CAR(lisp__data.input_list))
1465dfecf96Smrg	LispDestroy("bad stream at POP-INPUT");
1475dfecf96Smrg    lisp__data.input_list = CDR(lisp__data.input_list);
1485dfecf96Smrg    SINPUT = CONSP(lisp__data.input_list) ?
1495dfecf96Smrg    CAR(lisp__data.input_list) : lisp__data.input_list;
1505dfecf96Smrg    --lisp__data.iunget;
1515dfecf96Smrg    lisp__data.eof = 0;
1525dfecf96Smrg}
1535dfecf96Smrg
1545dfecf96Smrg/*
1555dfecf96Smrg * Low level functions
1565dfecf96Smrg */
1575dfecf96Smrgstatic int
158f765521fSmrgcalculate_line(const void *data, int size)
1595dfecf96Smrg{
1605dfecf96Smrg    int line = 0;
161f765521fSmrg    const char *str, *ptr;
1625dfecf96Smrg
163f765521fSmrg    for (str = (const char *)data, ptr = (const char *)data + size;
164f765521fSmrg         str < ptr; str++)
1655dfecf96Smrg	if (*ptr == '\n')
1665dfecf96Smrg	    ++line;
1675dfecf96Smrg
1685dfecf96Smrg    return (line);
1695dfecf96Smrg}
1705dfecf96Smrg
1715dfecf96Smrgstatic int
172f765521fSmrgcalculate_column(const void *data, int size, int column)
1735dfecf96Smrg{
174f765521fSmrg    const char *str, *ptr;
1755dfecf96Smrg
1765dfecf96Smrg    /* search for newline in data */
177f765521fSmrg    for (str = (const char *)data, ptr = (const char *)data + size - 1;
178f765521fSmrg         ptr >= str; ptr--)
1795dfecf96Smrg	if (*ptr == '\n')
1805dfecf96Smrg	    break;
1815dfecf96Smrg
1825dfecf96Smrg    /* newline found */
1835dfecf96Smrg    if (ptr >= str)
1845dfecf96Smrg	return (size - (ptr - str) - 1);
1855dfecf96Smrg
1865dfecf96Smrg    /* newline not found */
1875dfecf96Smrg    return (column + size);
1885dfecf96Smrg}
1895dfecf96Smrg
1905dfecf96SmrgLispFile *
1915dfecf96SmrgLispFdopen(int descriptor, int mode)
1925dfecf96Smrg{
1935dfecf96Smrg    LispFile *file = calloc(1, sizeof(LispFile));
1945dfecf96Smrg
1955dfecf96Smrg    if (file) {
1965dfecf96Smrg	struct stat st;
1975dfecf96Smrg
1985dfecf96Smrg	file->descriptor = descriptor;
1995dfecf96Smrg	file->readable = (mode & READ_BIT) != 0;
2005dfecf96Smrg	file->writable = (mode & WRITE_BIT) != 0;
2015dfecf96Smrg
2025dfecf96Smrg	if (fstat(descriptor, &st) == 0)
2035dfecf96Smrg	    file->regular = S_ISREG(st.st_mode);
2045dfecf96Smrg	else
2055dfecf96Smrg	    file->regular = 0;
2065dfecf96Smrg
2075dfecf96Smrg	file->buffered = (mode & BUFFERED_BIT) != 0;
2085dfecf96Smrg	if ((mode & UNBUFFERED_BIT) == 0)
2095dfecf96Smrg	    file->buffered = file->regular;
2105dfecf96Smrg
2115dfecf96Smrg	if (file->buffered) {
2125dfecf96Smrg	    file->buffer = malloc(pagesize);
2135dfecf96Smrg	    if (file->buffer == NULL)
2145dfecf96Smrg		file->buffered = 0;
2155dfecf96Smrg	}
2165dfecf96Smrg	file->line = 1;
2175dfecf96Smrg	file->binary = (mode & BINARY_BIT) != 0;
2185dfecf96Smrg	file->io_write = write;
2195dfecf96Smrg    }
2205dfecf96Smrg
2215dfecf96Smrg    return (file);
2225dfecf96Smrg}
2235dfecf96Smrg
2245dfecf96SmrgLispFile *
225f765521fSmrgLispFopen(const char *path, int mode)
2265dfecf96Smrg{
2275dfecf96Smrg    LispFile *file;
2285dfecf96Smrg    int descriptor;
2295dfecf96Smrg    int flags = O_NOCTTY;
2305dfecf96Smrg
2315dfecf96Smrg    /* check read/write attributes */
2325dfecf96Smrg    if ((mode & (READ_BIT | WRITE_BIT)) == (READ_BIT | WRITE_BIT))
2335dfecf96Smrg	flags |= O_RDWR;
2345dfecf96Smrg    else if (mode & READ_BIT)
2355dfecf96Smrg	flags |= O_RDONLY;
2365dfecf96Smrg    else if (mode & WRITE_BIT)
2375dfecf96Smrg	flags |= O_WRONLY;
2385dfecf96Smrg
2395dfecf96Smrg    /* create if does not exist */
2405dfecf96Smrg    if (mode & WRITE_BIT) {
2415dfecf96Smrg	flags |= O_CREAT;
2425dfecf96Smrg
2435dfecf96Smrg	/* append if exists? */
2445dfecf96Smrg	if (mode & APPEND_BIT)
2455dfecf96Smrg	    flags |= O_APPEND;
2465dfecf96Smrg	else
2475dfecf96Smrg	    flags |= O_TRUNC;
2485dfecf96Smrg    }
2495dfecf96Smrg
2505dfecf96Smrg    /* open file */
2515dfecf96Smrg    descriptor = open(path, flags, 0666);
2525dfecf96Smrg    if (descriptor < 0)
2535dfecf96Smrg	return (NULL);
2545dfecf96Smrg
2555dfecf96Smrg    /* initialize LispFile structure */
2565dfecf96Smrg    file = LispFdopen(descriptor, mode);
2575dfecf96Smrg    if (file == NULL)
2585dfecf96Smrg	close(descriptor);
2595dfecf96Smrg
2605dfecf96Smrg    return (file);
2615dfecf96Smrg}
2625dfecf96Smrg
2635dfecf96Smrgvoid
2645dfecf96SmrgLispFclose(LispFile *file)
2655dfecf96Smrg{
2665dfecf96Smrg    /* flush any pending output */
2675dfecf96Smrg    LispFflush(file);
2685dfecf96Smrg    /* cleanup */
2695dfecf96Smrg    close(file->descriptor);
2705dfecf96Smrg    if (file->buffer)
2715dfecf96Smrg	free(file->buffer);
2725dfecf96Smrg    free(file);
2735dfecf96Smrg}
2745dfecf96Smrg
2755dfecf96Smrgio_write_fn
2765dfecf96SmrgLispSetFileWrite(LispFile *file, io_write_fn new_write)
2775dfecf96Smrg{
2785dfecf96Smrg    io_write_fn old_write = file->io_write;
2795dfecf96Smrg
2805dfecf96Smrg    file->io_write = new_write;
2815dfecf96Smrg
2825dfecf96Smrg    return (old_write);
2835dfecf96Smrg}
2845dfecf96Smrg
2855dfecf96Smrgint
2865dfecf96SmrgLispFflush(LispFile *file)
2875dfecf96Smrg{
2885dfecf96Smrg    if (file->writable && file->length) {
2895dfecf96Smrg	int length = (*file->io_write)(file->descriptor,
2905dfecf96Smrg				       file->buffer, file->length);
2915dfecf96Smrg
2925dfecf96Smrg	if (length > 0) {
2935dfecf96Smrg	    if (file->length > length)
2945dfecf96Smrg		memmove(file->buffer, file->buffer + length,
2955dfecf96Smrg			file->length - length);
2965dfecf96Smrg	    file->length -= length;
2975dfecf96Smrg	}
2985dfecf96Smrg	return (length);
2995dfecf96Smrg    }
3005dfecf96Smrg
3015dfecf96Smrg    return (0);
3025dfecf96Smrg}
3035dfecf96Smrg
3045dfecf96Smrgint
3055dfecf96SmrgLispFungetc(LispFile *file, int ch)
3065dfecf96Smrg{
3075dfecf96Smrg    if (file->readable) {
3085dfecf96Smrg	file->available = 1;
3095dfecf96Smrg	file->unget = ch;
3105dfecf96Smrg	/* this should never happen */
3115dfecf96Smrg	if (ch == '\n' && !file->binary)
3125dfecf96Smrg	    --file->line;
3135dfecf96Smrg    }
3145dfecf96Smrg
3155dfecf96Smrg    return (ch);
3165dfecf96Smrg}
3175dfecf96Smrg
3185dfecf96Smrgint
3195dfecf96SmrgLispFgetc(LispFile *file)
3205dfecf96Smrg{
3215dfecf96Smrg    int ch;
3225dfecf96Smrg
3235dfecf96Smrg    if (file->readable) {
3245dfecf96Smrg	unsigned char c;
3255dfecf96Smrg
3265dfecf96Smrg	if (file->available) {
3275dfecf96Smrg	    ch = file->unget;
3285dfecf96Smrg	    file->available = 0;
3295dfecf96Smrg	}
3305dfecf96Smrg	else if (file->buffered) {
3315dfecf96Smrg	    if (file->writable) {
3325dfecf96Smrg		LispFflush(file);
3335dfecf96Smrg		if (read(file->descriptor, &c, 1) == 1)
3345dfecf96Smrg		    ch = c;
3355dfecf96Smrg		else
3365dfecf96Smrg		    ch = EOF;
3375dfecf96Smrg	    }
3385dfecf96Smrg	    else {
3395dfecf96Smrg		if (file->offset < file->length)
3405dfecf96Smrg		    ch = ((unsigned char*)file->buffer)[file->offset++];
3415dfecf96Smrg		else {
3425dfecf96Smrg		    int length = read(file->descriptor,
3435dfecf96Smrg				      file->buffer, pagesize);
3445dfecf96Smrg
3455dfecf96Smrg		    if (length >= 0)
3465dfecf96Smrg			file->length = length;
3475dfecf96Smrg		    else
3485dfecf96Smrg			file->length = 0;
3495dfecf96Smrg		    file->offset = 0;
3505dfecf96Smrg		    if (file->length)
3515dfecf96Smrg			ch = ((unsigned char*)file->buffer)[file->offset++];
3525dfecf96Smrg		    else
3535dfecf96Smrg			ch = EOF;
3545dfecf96Smrg		}
3555dfecf96Smrg	    }
3565dfecf96Smrg	}
3575dfecf96Smrg	else if (read(file->descriptor, &c, 1) == 1)
3585dfecf96Smrg	    ch = c;
3595dfecf96Smrg	else
3605dfecf96Smrg	    ch = EOF;
3615dfecf96Smrg    }
3625dfecf96Smrg    else
3635dfecf96Smrg	ch = EOF;
3645dfecf96Smrg
3655dfecf96Smrg    if (ch == '\n' && !file->binary)
3665dfecf96Smrg	++file->line;
3675dfecf96Smrg
3685dfecf96Smrg    return (ch);
3695dfecf96Smrg}
3705dfecf96Smrg
3715dfecf96Smrgint
3725dfecf96SmrgLispFputc(LispFile *file, int ch)
3735dfecf96Smrg{
3745dfecf96Smrg    if (file->writable) {
3755dfecf96Smrg	unsigned char c = ch;
3765dfecf96Smrg
3775dfecf96Smrg	if (file->buffered) {
3785dfecf96Smrg	    if (file->length + 1 >= pagesize)
3795dfecf96Smrg		LispFflush(file);
3805dfecf96Smrg	    file->buffer[file->length++] = c;
3815dfecf96Smrg	}
3825dfecf96Smrg	else if ((*file->io_write)(file->descriptor, &c, 1) != 1)
3835dfecf96Smrg	    ch = EOF;
3845dfecf96Smrg
3855dfecf96Smrg	if (!file->binary) {
3865dfecf96Smrg	    /* update column number */
3875dfecf96Smrg	    if (ch == '\n')
3885dfecf96Smrg		file->column = 0;
3895dfecf96Smrg	    else
3905dfecf96Smrg		++file->column;
3915dfecf96Smrg	}
3925dfecf96Smrg    }
3935dfecf96Smrg
3945dfecf96Smrg    return (ch);
3955dfecf96Smrg}
3965dfecf96Smrg
3975dfecf96Smrgint
3985dfecf96SmrgLispSgetc(LispString *string)
3995dfecf96Smrg{
4005dfecf96Smrg    int ch;
4015dfecf96Smrg
4025dfecf96Smrg    if (string->input >= string->length)
4035dfecf96Smrg	return (EOF);			/* EOF reading from string */
4045dfecf96Smrg
4055dfecf96Smrg    ch = ((unsigned char*)string->string)[string->input++];
4065dfecf96Smrg    if (ch == '\n' && !string->binary)
4075dfecf96Smrg	++string->line;
4085dfecf96Smrg
4095dfecf96Smrg    return (ch);
4105dfecf96Smrg}
4115dfecf96Smrg
4125dfecf96Smrgint
4135dfecf96SmrgLispSputc(LispString *string, int ch)
4145dfecf96Smrg{
4155dfecf96Smrg    if (string->output + 1 >= string->space) {
4165dfecf96Smrg	if (string->fixed)
4175dfecf96Smrg	    return (EOF);
4185dfecf96Smrg	else {
4195dfecf96Smrg	    char *tmp = realloc(string->string, string->space + pagesize);
4205dfecf96Smrg
4215dfecf96Smrg	    if (tmp == NULL)
4225dfecf96Smrg		return (EOF);
4235dfecf96Smrg	    string->string = tmp;
4245dfecf96Smrg	    string->space += pagesize;
4255dfecf96Smrg	}
4265dfecf96Smrg    }
4275dfecf96Smrg
4285dfecf96Smrg    string->string[string->output++] = ch;
4295dfecf96Smrg    if (string->length < string->output)
4305dfecf96Smrg	string->length = string->output;
4315dfecf96Smrg
4325dfecf96Smrg    /* update column number */
4335dfecf96Smrg    if (!string->binary) {
4345dfecf96Smrg	if (ch == '\n')
4355dfecf96Smrg	    string->column = 0;
4365dfecf96Smrg	else
4375dfecf96Smrg	    ++string->column;
4385dfecf96Smrg    }
4395dfecf96Smrg
4405dfecf96Smrg    return (ch);
4415dfecf96Smrg}
4425dfecf96Smrg
4435dfecf96Smrgchar *
4445dfecf96SmrgLispFgets(LispFile *file, char *string, int size)
4455dfecf96Smrg{
4465dfecf96Smrg    int ch, offset = 0;
4475dfecf96Smrg
4485dfecf96Smrg    if (size < 1)
4495dfecf96Smrg	return (string);
4505dfecf96Smrg
4515dfecf96Smrg    for (;;) {
4525dfecf96Smrg	if (offset + 1 >= size)
4535dfecf96Smrg	    break;
4545dfecf96Smrg	if ((ch = LispFgetc(file)) == EOF)
4555dfecf96Smrg	    break;
4565dfecf96Smrg	string[offset++] = ch;
4575dfecf96Smrg	/* line number is calculated in LispFgetc */
4585dfecf96Smrg	if (ch == '\n')
4595dfecf96Smrg	    break;
4605dfecf96Smrg    }
4615dfecf96Smrg    string[offset] = '\0';
4625dfecf96Smrg
4635dfecf96Smrg    return (offset ? string : NULL);
4645dfecf96Smrg}
4655dfecf96Smrg
4665dfecf96Smrgint
467f765521fSmrgLispFputs(LispFile *file, const char *buffer)
4685dfecf96Smrg{
4695dfecf96Smrg    return (LispFwrite(file, buffer, strlen(buffer)));
4705dfecf96Smrg}
4715dfecf96Smrg
4725dfecf96Smrgint
473f765521fSmrgLispSputs(LispString *string, const char *buffer)
4745dfecf96Smrg{
4755dfecf96Smrg    return (LispSwrite(string, buffer, strlen(buffer)));
4765dfecf96Smrg}
4775dfecf96Smrg
4785dfecf96Smrgint
4795dfecf96SmrgLispFread(LispFile *file, void *data, int size)
4805dfecf96Smrg{
4815dfecf96Smrg    int bytes, length;
4825dfecf96Smrg    char *buffer;
4835dfecf96Smrg
4845dfecf96Smrg    if (!file->readable)
4855dfecf96Smrg	return (EOF);
4865dfecf96Smrg
4875dfecf96Smrg    if (size <= 0)
4885dfecf96Smrg	return (size);
4895dfecf96Smrg
4905dfecf96Smrg    length = 0;
4915dfecf96Smrg    buffer = (char*)data;
4925dfecf96Smrg
4935dfecf96Smrg    /* check if there is an unget character */
4945dfecf96Smrg    if (file->available) {
4955dfecf96Smrg	*buffer++ = file->unget;
4965dfecf96Smrg	file->available = 0;
4975dfecf96Smrg	if (--size == 0) {
4985dfecf96Smrg	    if (file->unget == '\n' && !file->binary)
4995dfecf96Smrg		++file->line;
5005dfecf96Smrg
5015dfecf96Smrg	    return (1);
5025dfecf96Smrg	}
5035dfecf96Smrg
5045dfecf96Smrg	length = 1;
5055dfecf96Smrg    }
5065dfecf96Smrg
5075dfecf96Smrg    if (file->buffered) {
5085dfecf96Smrg	void *base_data = (char*)data - length;
5095dfecf96Smrg
5105dfecf96Smrg	if (file->writable) {
5115dfecf96Smrg	    LispFflush(file);
5125dfecf96Smrg	    bytes = read(file->descriptor, buffer, size);
5135dfecf96Smrg	    if (bytes < 0)
5145dfecf96Smrg		bytes = 0;
5155dfecf96Smrg	    if (!file->binary)
5165dfecf96Smrg		file->line += calculate_line(base_data, length + bytes);
5175dfecf96Smrg
5185dfecf96Smrg	    return (length + bytes);
5195dfecf96Smrg	}
5205dfecf96Smrg
5215dfecf96Smrg	/* read anything that is in the buffer */
5225dfecf96Smrg	if (file->offset < file->length) {
5235dfecf96Smrg	    bytes = file->length - file->offset;
5245dfecf96Smrg	    if (bytes > size)
5255dfecf96Smrg		bytes = size;
5265dfecf96Smrg	    memcpy(buffer, file->buffer + file->offset, bytes);
5275dfecf96Smrg	    buffer += bytes;
5285dfecf96Smrg	    file->offset += bytes;
5295dfecf96Smrg	    size -= bytes;
5305dfecf96Smrg	}
5315dfecf96Smrg
5325dfecf96Smrg	/* if there is still something to read */
5335dfecf96Smrg	if (size) {
5345dfecf96Smrg	    bytes = read(file->descriptor, buffer, size);
5355dfecf96Smrg	    if (bytes < 0)
5365dfecf96Smrg		bytes = 0;
5375dfecf96Smrg
5385dfecf96Smrg	    length += bytes;
5395dfecf96Smrg	}
5405dfecf96Smrg
5415dfecf96Smrg	if (!file->binary)
5425dfecf96Smrg	    file->line += calculate_line(base_data, length);
5435dfecf96Smrg
5445dfecf96Smrg	return (length);
5455dfecf96Smrg    }
5465dfecf96Smrg
5475dfecf96Smrg    bytes = read(file->descriptor, buffer, size);
5485dfecf96Smrg    if (bytes < 0)
5495dfecf96Smrg	bytes = 0;
5505dfecf96Smrg    if (!file->binary)
5515dfecf96Smrg	file->line += calculate_line(buffer - length, length + bytes);
5525dfecf96Smrg
5535dfecf96Smrg    return (length + bytes);
5545dfecf96Smrg}
5555dfecf96Smrg
5565dfecf96Smrgint
557f765521fSmrgLispFwrite(LispFile *file, const void *data, int size)
5585dfecf96Smrg{
5595dfecf96Smrg    if (!file->writable || size < 0)
5605dfecf96Smrg	return (EOF);
5615dfecf96Smrg
5625dfecf96Smrg    if (!file->binary)
5635dfecf96Smrg	file->column = calculate_column(data, size, file->column);
5645dfecf96Smrg
5655dfecf96Smrg    if (file->buffered) {
5665dfecf96Smrg	int length, bytes;
567f765521fSmrg	const char *buffer = (const char *)data;
5685dfecf96Smrg
5695dfecf96Smrg	length = 0;
5705dfecf96Smrg	if (size + file->length > pagesize) {
5715dfecf96Smrg	    /* fill remaining space in buffer and flush */
5725dfecf96Smrg	    bytes = pagesize - file->length;
5735dfecf96Smrg	    memcpy(file->buffer + file->length, buffer, bytes);
5745dfecf96Smrg	    file->length += bytes;
5755dfecf96Smrg	    LispFflush(file);
5765dfecf96Smrg
5775dfecf96Smrg	    /* check if all data was written */
5785dfecf96Smrg	    if (file->length)
5795dfecf96Smrg		return (pagesize - file->length);
5805dfecf96Smrg
5815dfecf96Smrg	    length = bytes;
5825dfecf96Smrg	    buffer += bytes;
5835dfecf96Smrg	    size -= bytes;
5845dfecf96Smrg	}
5855dfecf96Smrg
5865dfecf96Smrg	while (size > pagesize) {
5875dfecf96Smrg	    /* write multiple of pagesize */
5885dfecf96Smrg	    bytes = (*file->io_write)(file->descriptor, buffer,
5895dfecf96Smrg				      size - (size % pagesize));
5905dfecf96Smrg	    if (bytes <= 0)
5915dfecf96Smrg		return (length);
5925dfecf96Smrg
5935dfecf96Smrg	    length += bytes;
5945dfecf96Smrg	    buffer += bytes;
5955dfecf96Smrg	    size -= bytes;
5965dfecf96Smrg	}
5975dfecf96Smrg
5985dfecf96Smrg	if (size) {
5995dfecf96Smrg	    /* keep remaining data in buffer */
6005dfecf96Smrg	    switch (size) {
6015dfecf96Smrg		case 8:
6025dfecf96Smrg		    file->buffer[file->length++] = *buffer++;
6035dfecf96Smrg		case 7:
6045dfecf96Smrg		    file->buffer[file->length++] = *buffer++;
6055dfecf96Smrg		case 6:
6065dfecf96Smrg		    file->buffer[file->length++] = *buffer++;
6075dfecf96Smrg		case 5:
6085dfecf96Smrg		    file->buffer[file->length++] = *buffer++;
6095dfecf96Smrg		case 4:
6105dfecf96Smrg		    file->buffer[file->length++] = *buffer++;
6115dfecf96Smrg		case 3:
6125dfecf96Smrg		    file->buffer[file->length++] = *buffer++;
6135dfecf96Smrg		case 2:
6145dfecf96Smrg		    file->buffer[file->length++] = *buffer++;
6155dfecf96Smrg		case 1:
6165dfecf96Smrg		    file->buffer[file->length++] = *buffer++;
6175dfecf96Smrg		    break;
6185dfecf96Smrg		default:
6195dfecf96Smrg		    memcpy(file->buffer + file->length, buffer, size);
6205dfecf96Smrg		    file->length += size;
6215dfecf96Smrg		    break;
6225dfecf96Smrg	    }
6235dfecf96Smrg	    length += size;
6245dfecf96Smrg	}
6255dfecf96Smrg
6265dfecf96Smrg	return (length);
6275dfecf96Smrg    }
6285dfecf96Smrg
6295dfecf96Smrg    return ((*file->io_write)(file->descriptor, data, size));
6305dfecf96Smrg}
6315dfecf96Smrg
6325dfecf96Smrgint
633f765521fSmrgLispSwrite(LispString *string, const void *data, int size)
6345dfecf96Smrg{
635f14f4646Smrg    int bytes;
636f14f4646Smrg
6375dfecf96Smrg    if (size < 0)
6385dfecf96Smrg	return (EOF);
6395dfecf96Smrg
6405dfecf96Smrg    if (string->output + size >= string->space) {
6415dfecf96Smrg	if (string->fixed) {
6425dfecf96Smrg	    /* leave space for a ending nul character */
643f14f4646Smrg	    bytes = string->space - string->output - 1;
644f14f4646Smrg
645f14f4646Smrg	    if (bytes < size)
646f14f4646Smrg		size = bytes;
6475dfecf96Smrg
6485dfecf96Smrg	    if (size <= 0)
6495dfecf96Smrg		return (-1);
6505dfecf96Smrg	}
6515dfecf96Smrg	else {
652f14f4646Smrg	    char *tmp;
653f14f4646Smrg
654f14f4646Smrg	    bytes = string->space + size;
655f14f4646Smrg	    bytes += pagesize - (bytes % pagesize);
656f14f4646Smrg	    tmp = realloc(string->string, bytes);
6575dfecf96Smrg
6585dfecf96Smrg	    if (tmp == NULL)
6595dfecf96Smrg		return (-1);
6605dfecf96Smrg
6615dfecf96Smrg	    string->string = tmp;
662f14f4646Smrg	    string->space = bytes;
6635dfecf96Smrg	}
6645dfecf96Smrg    }
6655dfecf96Smrg    memcpy(string->string + string->output, data, size);
6665dfecf96Smrg    string->output += size;
6675dfecf96Smrg    if (string->length < string->output)
6685dfecf96Smrg	string->length = string->output;
6695dfecf96Smrg
6705dfecf96Smrg    if (!string->binary)
6715dfecf96Smrg	string->column = calculate_column(data, size, string->column);
6725dfecf96Smrg
6735dfecf96Smrg    return (size);
6745dfecf96Smrg}
6755dfecf96Smrg
676f765521fSmrgconst char *
6775dfecf96SmrgLispGetSstring(LispString *string, int *length)
6785dfecf96Smrg{
6795dfecf96Smrg    if (string->string == NULL || string->length <= 0) {
6805dfecf96Smrg	*length = 0;
6815dfecf96Smrg
6825dfecf96Smrg	return ("");
6835dfecf96Smrg    }
6845dfecf96Smrg    *length = string->length;
6855dfecf96Smrg    if (string->string[string->length -1] != '\0') {
6865dfecf96Smrg	if (string->length < string->space)
6875dfecf96Smrg	    string->string[string->length] = '\0';
6885dfecf96Smrg	else if (string->fixed && string->space)
6895dfecf96Smrg	    string->string[string->space - 1] = '\0';
6905dfecf96Smrg	else {
6915dfecf96Smrg	    char *tmp = realloc(string->string, string->space + pagesize);
6925dfecf96Smrg
6935dfecf96Smrg	    if (tmp == NULL)
6945dfecf96Smrg		string->string[string->space - 1] = '\0';
6955dfecf96Smrg	    else {
6965dfecf96Smrg		string->string = tmp;
6975dfecf96Smrg		string->space += pagesize;
6985dfecf96Smrg		string->string[string->length] = '\0';
6995dfecf96Smrg	    }
7005dfecf96Smrg	}
7015dfecf96Smrg    }
7025dfecf96Smrg
7035dfecf96Smrg    return (string->string);
7045dfecf96Smrg}
7055dfecf96Smrg
7065dfecf96Smrgint
707f765521fSmrgLispRename(const char *from, const char *to)
7085dfecf96Smrg{
7095dfecf96Smrg    return (rename(from, to));
7105dfecf96Smrg}
7115dfecf96Smrg
7125dfecf96Smrgint
713f765521fSmrgLispUnlink(const char *name)
7145dfecf96Smrg{
7155dfecf96Smrg    return (unlink(name));
7165dfecf96Smrg}
717