io.c revision 5dfecf96
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 * Prototypes
495dfecf96Smrg */
505dfecf96Smrgstatic int calculate_line(void*, int);
515dfecf96Smrgstatic int calculate_column(void*, int, int);
525dfecf96Smrg
535dfecf96Smrg/*
545dfecf96Smrg * Initialization
555dfecf96Smrg */
565dfecf96Smrgextern int pagesize;
575dfecf96Smrg
585dfecf96Smrg/*
595dfecf96Smrg * Implementation
605dfecf96Smrg */
615dfecf96Smrgint
625dfecf96SmrgLispGet(void)
635dfecf96Smrg{
645dfecf96Smrg    int ch = EOF;
655dfecf96Smrg    LispUngetInfo *unget = lisp__data.unget[lisp__data.iunget];
665dfecf96Smrg
675dfecf96Smrg    if (unget->offset)
685dfecf96Smrg	ch = ((unsigned char*)unget->buffer)[--unget->offset];
695dfecf96Smrg    else if (SINPUT->data.stream.readable) {
705dfecf96Smrg	LispFile *file = NULL;
715dfecf96Smrg
725dfecf96Smrg	switch (SINPUT->data.stream.type) {
735dfecf96Smrg	    case LispStreamStandard:
745dfecf96Smrg	    case LispStreamFile:
755dfecf96Smrg		file = FSTREAMP(SINPUT);
765dfecf96Smrg		break;
775dfecf96Smrg	    case LispStreamPipe:
785dfecf96Smrg		file = IPSTREAMP(SINPUT);
795dfecf96Smrg		break;
805dfecf96Smrg	    case LispStreamString:
815dfecf96Smrg		ch = LispSgetc(SSTREAMP(SINPUT));
825dfecf96Smrg		break;
835dfecf96Smrg	    default:
845dfecf96Smrg		ch = EOF;
855dfecf96Smrg		break;
865dfecf96Smrg	}
875dfecf96Smrg	if (file != NULL) {
885dfecf96Smrg	    if (file->nonblock) {
895dfecf96Smrg		if (fcntl(file->descriptor, F_SETFL, 0) < 0)
905dfecf96Smrg		    LispDestroy("fcntl: %s", strerror(errno));
915dfecf96Smrg		file->nonblock = 0;
925dfecf96Smrg	    }
935dfecf96Smrg	    ch = LispFgetc(file);
945dfecf96Smrg	}
955dfecf96Smrg    }
965dfecf96Smrg    else
975dfecf96Smrg	LispDestroy("cannot read from *STANDARD-INPUT*");
985dfecf96Smrg
995dfecf96Smrg    if (ch == EOF)
1005dfecf96Smrg	lisp__data.eof = 1;
1015dfecf96Smrg
1025dfecf96Smrg    return (ch);
1035dfecf96Smrg}
1045dfecf96Smrg
1055dfecf96Smrgint
1065dfecf96SmrgLispUnget(int ch)
1075dfecf96Smrg{
1085dfecf96Smrg    LispUngetInfo *unget = lisp__data.unget[lisp__data.iunget];
1095dfecf96Smrg
1105dfecf96Smrg    if (unget->offset == sizeof(unget->buffer)) {
1115dfecf96Smrg	LispWarning("character %c lost at LispUnget()", unget->buffer[0]);
1125dfecf96Smrg	memmove(unget->buffer, unget->buffer + 1, unget->offset - 1);
1135dfecf96Smrg	unget->buffer[unget->offset - 1] = ch;
1145dfecf96Smrg    }
1155dfecf96Smrg    else
1165dfecf96Smrg	unget->buffer[unget->offset++] = ch;
1175dfecf96Smrg
1185dfecf96Smrg    return (ch);
1195dfecf96Smrg}
1205dfecf96Smrg
1215dfecf96Smrgvoid
1225dfecf96SmrgLispPushInput(LispObj *stream)
1235dfecf96Smrg{
1245dfecf96Smrg    if (!STREAMP(stream) || !stream->data.stream.readable)
1255dfecf96Smrg	LispDestroy("bad stream at PUSH-INPUT");
1265dfecf96Smrg    lisp__data.input_list = CONS(stream, lisp__data.input_list);
1275dfecf96Smrg    SINPUT = stream;
1285dfecf96Smrg    if (lisp__data.iunget + 1 == lisp__data.nunget) {
1295dfecf96Smrg	LispUngetInfo **info =
1305dfecf96Smrg	    realloc(lisp__data.unget,
1315dfecf96Smrg		    sizeof(LispUngetInfo) * (lisp__data.nunget + 1));
1325dfecf96Smrg
1335dfecf96Smrg	if (!info ||
1345dfecf96Smrg	    (info[lisp__data.nunget] =
1355dfecf96Smrg	     calloc(1, sizeof(LispUngetInfo))) == NULL)
1365dfecf96Smrg	    LispDestroy("out of memory");
1375dfecf96Smrg	lisp__data.unget = info;
1385dfecf96Smrg	++lisp__data.nunget;
1395dfecf96Smrg    }
1405dfecf96Smrg    ++lisp__data.iunget;
1415dfecf96Smrg    memset(lisp__data.unget[lisp__data.iunget], '\0', sizeof(LispUngetInfo));
1425dfecf96Smrg    lisp__data.eof = 0;
1435dfecf96Smrg}
1445dfecf96Smrg
1455dfecf96Smrgvoid
1465dfecf96SmrgLispPopInput(LispObj *stream)
1475dfecf96Smrg{
1485dfecf96Smrg    if (!CONSP(lisp__data.input_list) || stream != CAR(lisp__data.input_list))
1495dfecf96Smrg	LispDestroy("bad stream at POP-INPUT");
1505dfecf96Smrg    lisp__data.input_list = CDR(lisp__data.input_list);
1515dfecf96Smrg    SINPUT = CONSP(lisp__data.input_list) ?
1525dfecf96Smrg    CAR(lisp__data.input_list) : lisp__data.input_list;
1535dfecf96Smrg    --lisp__data.iunget;
1545dfecf96Smrg    lisp__data.eof = 0;
1555dfecf96Smrg}
1565dfecf96Smrg
1575dfecf96Smrg/*
1585dfecf96Smrg * Low level functions
1595dfecf96Smrg */
1605dfecf96Smrgstatic int
1615dfecf96Smrgcalculate_line(void *data, int size)
1625dfecf96Smrg{
1635dfecf96Smrg    int line = 0;
1645dfecf96Smrg    char *str, *ptr;
1655dfecf96Smrg
1665dfecf96Smrg    for (str = (char*)data, ptr = (char*)data + size; str < ptr; str++)
1675dfecf96Smrg	if (*ptr == '\n')
1685dfecf96Smrg	    ++line;
1695dfecf96Smrg
1705dfecf96Smrg    return (line);
1715dfecf96Smrg}
1725dfecf96Smrg
1735dfecf96Smrgstatic int
1745dfecf96Smrgcalculate_column(void *data, int size, int column)
1755dfecf96Smrg{
1765dfecf96Smrg    char *str, *ptr;
1775dfecf96Smrg
1785dfecf96Smrg    /* search for newline in data */
1795dfecf96Smrg    for (str = (char*)data, ptr = (char*)data + size - 1; ptr >= str; ptr--)
1805dfecf96Smrg	if (*ptr == '\n')
1815dfecf96Smrg	    break;
1825dfecf96Smrg
1835dfecf96Smrg    /* newline found */
1845dfecf96Smrg    if (ptr >= str)
1855dfecf96Smrg	return (size - (ptr - str) - 1);
1865dfecf96Smrg
1875dfecf96Smrg    /* newline not found */
1885dfecf96Smrg    return (column + size);
1895dfecf96Smrg}
1905dfecf96Smrg
1915dfecf96SmrgLispFile *
1925dfecf96SmrgLispFdopen(int descriptor, int mode)
1935dfecf96Smrg{
1945dfecf96Smrg    LispFile *file = calloc(1, sizeof(LispFile));
1955dfecf96Smrg
1965dfecf96Smrg    if (file) {
1975dfecf96Smrg	struct stat st;
1985dfecf96Smrg
1995dfecf96Smrg	file->descriptor = descriptor;
2005dfecf96Smrg	file->readable = (mode & READ_BIT) != 0;
2015dfecf96Smrg	file->writable = (mode & WRITE_BIT) != 0;
2025dfecf96Smrg
2035dfecf96Smrg	if (fstat(descriptor, &st) == 0)
2045dfecf96Smrg	    file->regular = S_ISREG(st.st_mode);
2055dfecf96Smrg	else
2065dfecf96Smrg	    file->regular = 0;
2075dfecf96Smrg
2085dfecf96Smrg	file->buffered = (mode & BUFFERED_BIT) != 0;
2095dfecf96Smrg	if ((mode & UNBUFFERED_BIT) == 0)
2105dfecf96Smrg	    file->buffered = file->regular;
2115dfecf96Smrg
2125dfecf96Smrg	if (file->buffered) {
2135dfecf96Smrg	    file->buffer = malloc(pagesize);
2145dfecf96Smrg	    if (file->buffer == NULL)
2155dfecf96Smrg		file->buffered = 0;
2165dfecf96Smrg	}
2175dfecf96Smrg	file->line = 1;
2185dfecf96Smrg	file->binary = (mode & BINARY_BIT) != 0;
2195dfecf96Smrg	file->io_write = write;
2205dfecf96Smrg    }
2215dfecf96Smrg
2225dfecf96Smrg    return (file);
2235dfecf96Smrg}
2245dfecf96Smrg
2255dfecf96SmrgLispFile *
2265dfecf96SmrgLispFopen(char *path, int mode)
2275dfecf96Smrg{
2285dfecf96Smrg    LispFile *file;
2295dfecf96Smrg    int descriptor;
2305dfecf96Smrg    int flags = O_NOCTTY;
2315dfecf96Smrg
2325dfecf96Smrg    /* check read/write attributes */
2335dfecf96Smrg    if ((mode & (READ_BIT | WRITE_BIT)) == (READ_BIT | WRITE_BIT))
2345dfecf96Smrg	flags |= O_RDWR;
2355dfecf96Smrg    else if (mode & READ_BIT)
2365dfecf96Smrg	flags |= O_RDONLY;
2375dfecf96Smrg    else if (mode & WRITE_BIT)
2385dfecf96Smrg	flags |= O_WRONLY;
2395dfecf96Smrg
2405dfecf96Smrg    /* create if does not exist */
2415dfecf96Smrg    if (mode & WRITE_BIT) {
2425dfecf96Smrg	flags |= O_CREAT;
2435dfecf96Smrg
2445dfecf96Smrg	/* append if exists? */
2455dfecf96Smrg	if (mode & APPEND_BIT)
2465dfecf96Smrg	    flags |= O_APPEND;
2475dfecf96Smrg	else
2485dfecf96Smrg	    flags |= O_TRUNC;
2495dfecf96Smrg    }
2505dfecf96Smrg
2515dfecf96Smrg    /* open file */
2525dfecf96Smrg    descriptor = open(path, flags, 0666);
2535dfecf96Smrg    if (descriptor < 0)
2545dfecf96Smrg	return (NULL);
2555dfecf96Smrg
2565dfecf96Smrg    /* initialize LispFile structure */
2575dfecf96Smrg    file = LispFdopen(descriptor, mode);
2585dfecf96Smrg    if (file == NULL)
2595dfecf96Smrg	close(descriptor);
2605dfecf96Smrg
2615dfecf96Smrg    return (file);
2625dfecf96Smrg}
2635dfecf96Smrg
2645dfecf96Smrgvoid
2655dfecf96SmrgLispFclose(LispFile *file)
2665dfecf96Smrg{
2675dfecf96Smrg    /* flush any pending output */
2685dfecf96Smrg    LispFflush(file);
2695dfecf96Smrg    /* cleanup */
2705dfecf96Smrg    close(file->descriptor);
2715dfecf96Smrg    if (file->buffer)
2725dfecf96Smrg	free(file->buffer);
2735dfecf96Smrg    free(file);
2745dfecf96Smrg}
2755dfecf96Smrg
2765dfecf96Smrgio_write_fn
2775dfecf96SmrgLispSetFileWrite(LispFile *file, io_write_fn new_write)
2785dfecf96Smrg{
2795dfecf96Smrg    io_write_fn old_write = file->io_write;
2805dfecf96Smrg
2815dfecf96Smrg    file->io_write = new_write;
2825dfecf96Smrg
2835dfecf96Smrg    return (old_write);
2845dfecf96Smrg}
2855dfecf96Smrg
2865dfecf96Smrgint
2875dfecf96SmrgLispFflush(LispFile *file)
2885dfecf96Smrg{
2895dfecf96Smrg    if (file->writable && file->length) {
2905dfecf96Smrg	int length = (*file->io_write)(file->descriptor,
2915dfecf96Smrg				       file->buffer, file->length);
2925dfecf96Smrg
2935dfecf96Smrg	if (length > 0) {
2945dfecf96Smrg	    if (file->length > length)
2955dfecf96Smrg		memmove(file->buffer, file->buffer + length,
2965dfecf96Smrg			file->length - length);
2975dfecf96Smrg	    file->length -= length;
2985dfecf96Smrg	}
2995dfecf96Smrg	return (length);
3005dfecf96Smrg    }
3015dfecf96Smrg
3025dfecf96Smrg    return (0);
3035dfecf96Smrg}
3045dfecf96Smrg
3055dfecf96Smrgint
3065dfecf96SmrgLispFungetc(LispFile *file, int ch)
3075dfecf96Smrg{
3085dfecf96Smrg    if (file->readable) {
3095dfecf96Smrg	file->available = 1;
3105dfecf96Smrg	file->unget = ch;
3115dfecf96Smrg	/* this should never happen */
3125dfecf96Smrg	if (ch == '\n' && !file->binary)
3135dfecf96Smrg	    --file->line;
3145dfecf96Smrg    }
3155dfecf96Smrg
3165dfecf96Smrg    return (ch);
3175dfecf96Smrg}
3185dfecf96Smrg
3195dfecf96Smrgint
3205dfecf96SmrgLispFgetc(LispFile *file)
3215dfecf96Smrg{
3225dfecf96Smrg    int ch;
3235dfecf96Smrg
3245dfecf96Smrg    if (file->readable) {
3255dfecf96Smrg	unsigned char c;
3265dfecf96Smrg
3275dfecf96Smrg	if (file->available) {
3285dfecf96Smrg	    ch = file->unget;
3295dfecf96Smrg	    file->available = 0;
3305dfecf96Smrg	}
3315dfecf96Smrg	else if (file->buffered) {
3325dfecf96Smrg	    if (file->writable) {
3335dfecf96Smrg		LispFflush(file);
3345dfecf96Smrg		if (read(file->descriptor, &c, 1) == 1)
3355dfecf96Smrg		    ch = c;
3365dfecf96Smrg		else
3375dfecf96Smrg		    ch = EOF;
3385dfecf96Smrg	    }
3395dfecf96Smrg	    else {
3405dfecf96Smrg		if (file->offset < file->length)
3415dfecf96Smrg		    ch = ((unsigned char*)file->buffer)[file->offset++];
3425dfecf96Smrg		else {
3435dfecf96Smrg		    int length = read(file->descriptor,
3445dfecf96Smrg				      file->buffer, pagesize);
3455dfecf96Smrg
3465dfecf96Smrg		    if (length >= 0)
3475dfecf96Smrg			file->length = length;
3485dfecf96Smrg		    else
3495dfecf96Smrg			file->length = 0;
3505dfecf96Smrg		    file->offset = 0;
3515dfecf96Smrg		    if (file->length)
3525dfecf96Smrg			ch = ((unsigned char*)file->buffer)[file->offset++];
3535dfecf96Smrg		    else
3545dfecf96Smrg			ch = EOF;
3555dfecf96Smrg		}
3565dfecf96Smrg	    }
3575dfecf96Smrg	}
3585dfecf96Smrg	else if (read(file->descriptor, &c, 1) == 1)
3595dfecf96Smrg	    ch = c;
3605dfecf96Smrg	else
3615dfecf96Smrg	    ch = EOF;
3625dfecf96Smrg    }
3635dfecf96Smrg    else
3645dfecf96Smrg	ch = EOF;
3655dfecf96Smrg
3665dfecf96Smrg    if (ch == '\n' && !file->binary)
3675dfecf96Smrg	++file->line;
3685dfecf96Smrg
3695dfecf96Smrg    return (ch);
3705dfecf96Smrg}
3715dfecf96Smrg
3725dfecf96Smrgint
3735dfecf96SmrgLispFputc(LispFile *file, int ch)
3745dfecf96Smrg{
3755dfecf96Smrg    if (file->writable) {
3765dfecf96Smrg	unsigned char c = ch;
3775dfecf96Smrg
3785dfecf96Smrg	if (file->buffered) {
3795dfecf96Smrg	    if (file->length + 1 >= pagesize)
3805dfecf96Smrg		LispFflush(file);
3815dfecf96Smrg	    file->buffer[file->length++] = c;
3825dfecf96Smrg	}
3835dfecf96Smrg	else if ((*file->io_write)(file->descriptor, &c, 1) != 1)
3845dfecf96Smrg	    ch = EOF;
3855dfecf96Smrg
3865dfecf96Smrg	if (!file->binary) {
3875dfecf96Smrg	    /* update column number */
3885dfecf96Smrg	    if (ch == '\n')
3895dfecf96Smrg		file->column = 0;
3905dfecf96Smrg	    else
3915dfecf96Smrg		++file->column;
3925dfecf96Smrg	}
3935dfecf96Smrg    }
3945dfecf96Smrg
3955dfecf96Smrg    return (ch);
3965dfecf96Smrg}
3975dfecf96Smrg
3985dfecf96Smrgint
3995dfecf96SmrgLispSgetc(LispString *string)
4005dfecf96Smrg{
4015dfecf96Smrg    int ch;
4025dfecf96Smrg
4035dfecf96Smrg    if (string->input >= string->length)
4045dfecf96Smrg	return (EOF);			/* EOF reading from string */
4055dfecf96Smrg
4065dfecf96Smrg    ch = ((unsigned char*)string->string)[string->input++];
4075dfecf96Smrg    if (ch == '\n' && !string->binary)
4085dfecf96Smrg	++string->line;
4095dfecf96Smrg
4105dfecf96Smrg    return (ch);
4115dfecf96Smrg}
4125dfecf96Smrg
4135dfecf96Smrgint
4145dfecf96SmrgLispSputc(LispString *string, int ch)
4155dfecf96Smrg{
4165dfecf96Smrg    if (string->output + 1 >= string->space) {
4175dfecf96Smrg	if (string->fixed)
4185dfecf96Smrg	    return (EOF);
4195dfecf96Smrg	else {
4205dfecf96Smrg	    char *tmp = realloc(string->string, string->space + pagesize);
4215dfecf96Smrg
4225dfecf96Smrg	    if (tmp == NULL)
4235dfecf96Smrg		return (EOF);
4245dfecf96Smrg	    string->string = tmp;
4255dfecf96Smrg	    string->space += pagesize;
4265dfecf96Smrg	}
4275dfecf96Smrg    }
4285dfecf96Smrg
4295dfecf96Smrg    string->string[string->output++] = ch;
4305dfecf96Smrg    if (string->length < string->output)
4315dfecf96Smrg	string->length = string->output;
4325dfecf96Smrg
4335dfecf96Smrg    /* update column number */
4345dfecf96Smrg    if (!string->binary) {
4355dfecf96Smrg	if (ch == '\n')
4365dfecf96Smrg	    string->column = 0;
4375dfecf96Smrg	else
4385dfecf96Smrg	    ++string->column;
4395dfecf96Smrg    }
4405dfecf96Smrg
4415dfecf96Smrg    return (ch);
4425dfecf96Smrg}
4435dfecf96Smrg
4445dfecf96Smrgchar *
4455dfecf96SmrgLispFgets(LispFile *file, char *string, int size)
4465dfecf96Smrg{
4475dfecf96Smrg    int ch, offset = 0;
4485dfecf96Smrg
4495dfecf96Smrg    if (size < 1)
4505dfecf96Smrg	return (string);
4515dfecf96Smrg
4525dfecf96Smrg    for (;;) {
4535dfecf96Smrg	if (offset + 1 >= size)
4545dfecf96Smrg	    break;
4555dfecf96Smrg	if ((ch = LispFgetc(file)) == EOF)
4565dfecf96Smrg	    break;
4575dfecf96Smrg	string[offset++] = ch;
4585dfecf96Smrg	/* line number is calculated in LispFgetc */
4595dfecf96Smrg	if (ch == '\n')
4605dfecf96Smrg	    break;
4615dfecf96Smrg    }
4625dfecf96Smrg    string[offset] = '\0';
4635dfecf96Smrg
4645dfecf96Smrg    return (offset ? string : NULL);
4655dfecf96Smrg}
4665dfecf96Smrg
4675dfecf96Smrgint
4685dfecf96SmrgLispFputs(LispFile *file, char *buffer)
4695dfecf96Smrg{
4705dfecf96Smrg    return (LispFwrite(file, buffer, strlen(buffer)));
4715dfecf96Smrg}
4725dfecf96Smrg
4735dfecf96Smrgint
4745dfecf96SmrgLispSputs(LispString *string, char *buffer)
4755dfecf96Smrg{
4765dfecf96Smrg    return (LispSwrite(string, buffer, strlen(buffer)));
4775dfecf96Smrg}
4785dfecf96Smrg
4795dfecf96Smrgint
4805dfecf96SmrgLispFread(LispFile *file, void *data, int size)
4815dfecf96Smrg{
4825dfecf96Smrg    int bytes, length;
4835dfecf96Smrg    char *buffer;
4845dfecf96Smrg
4855dfecf96Smrg    if (!file->readable)
4865dfecf96Smrg	return (EOF);
4875dfecf96Smrg
4885dfecf96Smrg    if (size <= 0)
4895dfecf96Smrg	return (size);
4905dfecf96Smrg
4915dfecf96Smrg    length = 0;
4925dfecf96Smrg    buffer = (char*)data;
4935dfecf96Smrg
4945dfecf96Smrg    /* check if there is an unget character */
4955dfecf96Smrg    if (file->available) {
4965dfecf96Smrg	*buffer++ = file->unget;
4975dfecf96Smrg	file->available = 0;
4985dfecf96Smrg	if (--size == 0) {
4995dfecf96Smrg	    if (file->unget == '\n' && !file->binary)
5005dfecf96Smrg		++file->line;
5015dfecf96Smrg
5025dfecf96Smrg	    return (1);
5035dfecf96Smrg	}
5045dfecf96Smrg
5055dfecf96Smrg	length = 1;
5065dfecf96Smrg    }
5075dfecf96Smrg
5085dfecf96Smrg    if (file->buffered) {
5095dfecf96Smrg	void *base_data = (char*)data - length;
5105dfecf96Smrg
5115dfecf96Smrg	if (file->writable) {
5125dfecf96Smrg	    LispFflush(file);
5135dfecf96Smrg	    bytes = read(file->descriptor, buffer, size);
5145dfecf96Smrg	    if (bytes < 0)
5155dfecf96Smrg		bytes = 0;
5165dfecf96Smrg	    if (!file->binary)
5175dfecf96Smrg		file->line += calculate_line(base_data, length + bytes);
5185dfecf96Smrg
5195dfecf96Smrg	    return (length + bytes);
5205dfecf96Smrg	}
5215dfecf96Smrg
5225dfecf96Smrg	/* read anything that is in the buffer */
5235dfecf96Smrg	if (file->offset < file->length) {
5245dfecf96Smrg	    bytes = file->length - file->offset;
5255dfecf96Smrg	    if (bytes > size)
5265dfecf96Smrg		bytes = size;
5275dfecf96Smrg	    memcpy(buffer, file->buffer + file->offset, bytes);
5285dfecf96Smrg	    buffer += bytes;
5295dfecf96Smrg	    file->offset += bytes;
5305dfecf96Smrg	    size -= bytes;
5315dfecf96Smrg	}
5325dfecf96Smrg
5335dfecf96Smrg	/* if there is still something to read */
5345dfecf96Smrg	if (size) {
5355dfecf96Smrg	    bytes = read(file->descriptor, buffer, size);
5365dfecf96Smrg	    if (bytes < 0)
5375dfecf96Smrg		bytes = 0;
5385dfecf96Smrg
5395dfecf96Smrg	    length += bytes;
5405dfecf96Smrg	}
5415dfecf96Smrg
5425dfecf96Smrg	if (!file->binary)
5435dfecf96Smrg	    file->line += calculate_line(base_data, length);
5445dfecf96Smrg
5455dfecf96Smrg	return (length);
5465dfecf96Smrg    }
5475dfecf96Smrg
5485dfecf96Smrg    bytes = read(file->descriptor, buffer, size);
5495dfecf96Smrg    if (bytes < 0)
5505dfecf96Smrg	bytes = 0;
5515dfecf96Smrg    if (!file->binary)
5525dfecf96Smrg	file->line += calculate_line(buffer - length, length + bytes);
5535dfecf96Smrg
5545dfecf96Smrg    return (length + bytes);
5555dfecf96Smrg}
5565dfecf96Smrg
5575dfecf96Smrgint
5585dfecf96SmrgLispFwrite(LispFile *file, void *data, int size)
5595dfecf96Smrg{
5605dfecf96Smrg    if (!file->writable || size < 0)
5615dfecf96Smrg	return (EOF);
5625dfecf96Smrg
5635dfecf96Smrg    if (!file->binary)
5645dfecf96Smrg	file->column = calculate_column(data, size, file->column);
5655dfecf96Smrg
5665dfecf96Smrg    if (file->buffered) {
5675dfecf96Smrg	int length, bytes;
5685dfecf96Smrg	char *buffer = (char*)data;
5695dfecf96Smrg
5705dfecf96Smrg	length = 0;
5715dfecf96Smrg	if (size + file->length > pagesize) {
5725dfecf96Smrg	    /* fill remaining space in buffer and flush */
5735dfecf96Smrg	    bytes = pagesize - file->length;
5745dfecf96Smrg	    memcpy(file->buffer + file->length, buffer, bytes);
5755dfecf96Smrg	    file->length += bytes;
5765dfecf96Smrg	    LispFflush(file);
5775dfecf96Smrg
5785dfecf96Smrg	    /* check if all data was written */
5795dfecf96Smrg	    if (file->length)
5805dfecf96Smrg		return (pagesize - file->length);
5815dfecf96Smrg
5825dfecf96Smrg	    length = bytes;
5835dfecf96Smrg	    buffer += bytes;
5845dfecf96Smrg	    size -= bytes;
5855dfecf96Smrg	}
5865dfecf96Smrg
5875dfecf96Smrg	while (size > pagesize) {
5885dfecf96Smrg	    /* write multiple of pagesize */
5895dfecf96Smrg	    bytes = (*file->io_write)(file->descriptor, buffer,
5905dfecf96Smrg				      size - (size % pagesize));
5915dfecf96Smrg	    if (bytes <= 0)
5925dfecf96Smrg		return (length);
5935dfecf96Smrg
5945dfecf96Smrg	    length += bytes;
5955dfecf96Smrg	    buffer += bytes;
5965dfecf96Smrg	    size -= bytes;
5975dfecf96Smrg	}
5985dfecf96Smrg
5995dfecf96Smrg	if (size) {
6005dfecf96Smrg	    /* keep remaining data in buffer */
6015dfecf96Smrg	    switch (size) {
6025dfecf96Smrg		case 8:
6035dfecf96Smrg		    file->buffer[file->length++] = *buffer++;
6045dfecf96Smrg		case 7:
6055dfecf96Smrg		    file->buffer[file->length++] = *buffer++;
6065dfecf96Smrg		case 6:
6075dfecf96Smrg		    file->buffer[file->length++] = *buffer++;
6085dfecf96Smrg		case 5:
6095dfecf96Smrg		    file->buffer[file->length++] = *buffer++;
6105dfecf96Smrg		case 4:
6115dfecf96Smrg		    file->buffer[file->length++] = *buffer++;
6125dfecf96Smrg		case 3:
6135dfecf96Smrg		    file->buffer[file->length++] = *buffer++;
6145dfecf96Smrg		case 2:
6155dfecf96Smrg		    file->buffer[file->length++] = *buffer++;
6165dfecf96Smrg		case 1:
6175dfecf96Smrg		    file->buffer[file->length++] = *buffer++;
6185dfecf96Smrg		    break;
6195dfecf96Smrg		default:
6205dfecf96Smrg		    memcpy(file->buffer + file->length, buffer, size);
6215dfecf96Smrg		    file->length += size;
6225dfecf96Smrg		    break;
6235dfecf96Smrg	    }
6245dfecf96Smrg	    length += size;
6255dfecf96Smrg	}
6265dfecf96Smrg
6275dfecf96Smrg	return (length);
6285dfecf96Smrg    }
6295dfecf96Smrg
6305dfecf96Smrg    return ((*file->io_write)(file->descriptor, data, size));
6315dfecf96Smrg}
6325dfecf96Smrg
6335dfecf96Smrgint
6345dfecf96SmrgLispSwrite(LispString *string, void *data, int size)
6355dfecf96Smrg{
6365dfecf96Smrg    if (size < 0)
6375dfecf96Smrg	return (EOF);
6385dfecf96Smrg
6395dfecf96Smrg    if (string->output + size >= string->space) {
6405dfecf96Smrg	if (string->fixed) {
6415dfecf96Smrg	    /* leave space for a ending nul character */
6425dfecf96Smrg	    size = string->space - string->output - 1;
6435dfecf96Smrg
6445dfecf96Smrg	    if (size <= 0)
6455dfecf96Smrg		return (-1);
6465dfecf96Smrg	}
6475dfecf96Smrg	else {
6485dfecf96Smrg	    char *tmp = realloc(string->string, string->space +
6495dfecf96Smrg				(size / pagesize) * pagesize + pagesize);
6505dfecf96Smrg
6515dfecf96Smrg	    if (tmp == NULL)
6525dfecf96Smrg		return (-1);
6535dfecf96Smrg
6545dfecf96Smrg	    string->string = tmp;
6555dfecf96Smrg	    string->space += pagesize;
6565dfecf96Smrg	}
6575dfecf96Smrg    }
6585dfecf96Smrg    memcpy(string->string + string->output, data, size);
6595dfecf96Smrg    string->output += size;
6605dfecf96Smrg    if (string->length < string->output)
6615dfecf96Smrg	string->length = string->output;
6625dfecf96Smrg
6635dfecf96Smrg    if (!string->binary)
6645dfecf96Smrg	string->column = calculate_column(data, size, string->column);
6655dfecf96Smrg
6665dfecf96Smrg    return (size);
6675dfecf96Smrg}
6685dfecf96Smrg
6695dfecf96Smrgchar *
6705dfecf96SmrgLispGetSstring(LispString *string, int *length)
6715dfecf96Smrg{
6725dfecf96Smrg    if (string->string == NULL || string->length <= 0) {
6735dfecf96Smrg	*length = 0;
6745dfecf96Smrg
6755dfecf96Smrg	return ("");
6765dfecf96Smrg    }
6775dfecf96Smrg    *length = string->length;
6785dfecf96Smrg    if (string->string[string->length -1] != '\0') {
6795dfecf96Smrg	if (string->length < string->space)
6805dfecf96Smrg	    string->string[string->length] = '\0';
6815dfecf96Smrg	else if (string->fixed && string->space)
6825dfecf96Smrg	    string->string[string->space - 1] = '\0';
6835dfecf96Smrg	else {
6845dfecf96Smrg	    char *tmp = realloc(string->string, string->space + pagesize);
6855dfecf96Smrg
6865dfecf96Smrg	    if (tmp == NULL)
6875dfecf96Smrg		string->string[string->space - 1] = '\0';
6885dfecf96Smrg	    else {
6895dfecf96Smrg		string->string = tmp;
6905dfecf96Smrg		string->space += pagesize;
6915dfecf96Smrg		string->string[string->length] = '\0';
6925dfecf96Smrg	    }
6935dfecf96Smrg	}
6945dfecf96Smrg    }
6955dfecf96Smrg
6965dfecf96Smrg    return (string->string);
6975dfecf96Smrg}
6985dfecf96Smrg
6995dfecf96Smrgint
7005dfecf96SmrgLispRename(char *from, char *to)
7015dfecf96Smrg{
7025dfecf96Smrg    return (rename(from, to));
7035dfecf96Smrg}
7045dfecf96Smrg
7055dfecf96Smrgint
7065dfecf96SmrgLispUnlink(char *name)
7075dfecf96Smrg{
7085dfecf96Smrg    return (unlink(name));
7095dfecf96Smrg}
710