mirror of
https://github.com/wrog/lambdamoo
synced 2026-08-13 00:26:05 -04:00
Phase two is to insert the #defines and implement the utf8 versions of the various API calls.
321 lines
7.3 KiB
C
321 lines
7.3 KiB
C
/******************************************************************************
|
|
Copyright (c) 1992, 1995, 1996 Xerox Corporation. All rights reserved.
|
|
Portions of this code were written by Stephen White, aka ghond.
|
|
Use and copying of this software and preparation of derivative works based
|
|
upon this software are permitted. Any distribution of this software or
|
|
derivative works must comply with all applicable United States export
|
|
control laws. This software is made available AS IS, and Xerox Corporation
|
|
makes no warranty about the software, its performance or its conformity to
|
|
any specification. Any person obtaining a copy of this software is requested
|
|
to send their name and post office or electronic mail address to:
|
|
Pavel Curtis
|
|
Xerox PARC
|
|
3333 Coyote Hill Rd.
|
|
Palo Alto, CA 94304
|
|
Pavel@Xerox.Com
|
|
*****************************************************************************/
|
|
|
|
#include "streams.h"
|
|
|
|
#include "config.h"
|
|
#include "options.h"
|
|
|
|
#include "my-math.h"
|
|
#include "my-stdarg.h"
|
|
#include "my-string.h"
|
|
#include "my-stdio.h"
|
|
|
|
#include "exceptions.h"
|
|
#include "log.h"
|
|
#include "storage.h"
|
|
#include "structures.h"
|
|
#include "utf.h"
|
|
|
|
/*
|
|
* v must be a variable.
|
|
* set v to 1<<k: k smallest such that v < (1<<k)
|
|
* (Does not branch.)
|
|
* (Assumes v>>32 is optimzed out for 32-bit v?)
|
|
*/
|
|
#define NEXT_2_POWER(v) \
|
|
(v=(v|(v>>1)),v=(v|(v>>2)),v=(v|(v>>4)), \
|
|
v=(v|(v>>8)),v=(v|(v>>16)),v=1+(v|(v>>32)))
|
|
|
|
Stream *
|
|
new_stream(size_t size)
|
|
{
|
|
Stream *s = mymalloc(sizeof(Stream), M_STREAM);
|
|
|
|
/* We probably get an entire cache line
|
|
* whether we want it or not, so force size >= 32.
|
|
* ((XXX separate M_STREAMSTR with 64b alignment?))
|
|
*/
|
|
size |= 0x1f;
|
|
NEXT_2_POWER(size);
|
|
|
|
s->buffer = mymalloc(size, M_STREAM);
|
|
s->buflen = size;
|
|
s->current = 0;
|
|
|
|
return s;
|
|
}
|
|
|
|
Exception stream_too_big;
|
|
size_t stream_alloc_maximum = 0;
|
|
|
|
static int allow_stream_exceptions = 0;
|
|
|
|
void
|
|
enable_stream_exceptions(void)
|
|
{
|
|
++allow_stream_exceptions;
|
|
}
|
|
|
|
void
|
|
disable_stream_exceptions(void)
|
|
{
|
|
--allow_stream_exceptions;
|
|
}
|
|
|
|
static int
|
|
grew(Stream * s, size_t need)
|
|
{
|
|
if (s->current + need < s->buflen)
|
|
return 0;
|
|
|
|
size_t newlen = s->current + need;
|
|
NEXT_2_POWER(newlen);
|
|
if (allow_stream_exceptions > 0) {
|
|
if (newlen > stream_alloc_maximum) {
|
|
if (s->current + need < stream_alloc_maximum)
|
|
newlen = stream_alloc_maximum;
|
|
else
|
|
RAISE(stream_too_big, 0);
|
|
}
|
|
}
|
|
char *newbuf = mymalloc(newlen, M_STREAM);
|
|
|
|
memcpy(newbuf, s->buffer, s->current);
|
|
myfree(s->buffer, M_STREAM);
|
|
s->buffer = newbuf;
|
|
s->buflen = newlen;
|
|
return 1;
|
|
}
|
|
|
|
void
|
|
stream_add_char(Stream * s, char c)
|
|
{
|
|
(void)grew(s, 1);
|
|
s->buffer[s->current++] = c;
|
|
}
|
|
|
|
void
|
|
stream_delete_char(Stream * s)
|
|
{
|
|
if (s->current > 0)
|
|
s->current--;
|
|
}
|
|
|
|
#if UNICODE_STRINGS
|
|
|
|
int
|
|
stream_add_utf(Stream * s, uint32_t c)
|
|
{
|
|
(void)grew(s, 4);
|
|
|
|
char *b = s->buffer + s->current;
|
|
int result = put_utf(&b, c);
|
|
s->current = b - s->buffer;
|
|
|
|
return result;
|
|
}
|
|
|
|
void
|
|
stream_delete_utf(Stream * s)
|
|
{
|
|
if (s->current > 0)
|
|
do
|
|
--s->current;
|
|
while (is_utf8_cont_byte(s->buffer[s->current]));
|
|
}
|
|
|
|
#endif /* UNICODE_STRINGS */
|
|
|
|
#if FLOATING_TYPE == FT_QUAD
|
|
|
|
void
|
|
stream_float_printf(Stream *s, const char *fmt, size_t prec, FlNum d)
|
|
{
|
|
ssize_t len;
|
|
do {
|
|
len = quadmath_snprintf(s->buffer + s->current,
|
|
s->buflen - s->current, fmt, prec, d);
|
|
if (len < 0)
|
|
panic("quadmath_snprintf returned negative");
|
|
}
|
|
while (grew(s, len));
|
|
s->current += len;
|
|
}
|
|
|
|
#endif /* FLOATING_TYPE == FT_QUAD */
|
|
|
|
void
|
|
stream_unparse_float(Stream *s, FlNum n, int for_tostr)
|
|
{
|
|
size_t here = s->current;
|
|
int prec = FLOAT_DIGITS;
|
|
for (;;) {
|
|
stream_float_printf(s, "%.*"PRIgR, prec, n);
|
|
if (for_tostr
|
|
|| (n == strtoflnum(s->buffer + here, NULL))
|
|
|| (prec - FLOAT_DIGITS >= 4))
|
|
break;
|
|
s->current = here;
|
|
++prec;
|
|
}
|
|
if (!strpbrk(s->buffer + here, ".e"))
|
|
stream_add_string(s, ".0"); /* make it look floating */
|
|
}
|
|
|
|
void
|
|
stream_add_bytes(Stream * s, const char *bytes, size_t len)
|
|
{
|
|
(void)grew(s, len);
|
|
memcpy(s->buffer + s->current, bytes, len);
|
|
s->current += len;
|
|
}
|
|
|
|
void
|
|
stream_printf(Stream * s, const char *fmt,...)
|
|
{
|
|
va_list args, pargs;
|
|
ssize_t len;
|
|
|
|
va_start(args, fmt);
|
|
|
|
va_copy(pargs, args);
|
|
len = vsnprintf(s->buffer + s->current, s->buflen - s->current,
|
|
fmt, pargs);
|
|
if (len < 0)
|
|
panic("vsnprintf returned negative");
|
|
|
|
va_end(pargs);
|
|
|
|
if (grew(s, len))
|
|
len = vsnprintf(s->buffer + s->current, s->buflen - s->current,
|
|
fmt, args);
|
|
va_end(args);
|
|
s->current += len;
|
|
}
|
|
|
|
void
|
|
free_stream(Stream * s)
|
|
{
|
|
myfree(s->buffer, M_STREAM);
|
|
myfree(s, M_STREAM);
|
|
}
|
|
|
|
char *
|
|
reset_stream(Stream * s)
|
|
{
|
|
s->buffer[s->current] = '\0';
|
|
s->current = 0;
|
|
return s->buffer;
|
|
}
|
|
|
|
char *
|
|
stream_contents(Stream * s)
|
|
{
|
|
s->buffer[s->current] = '\0';
|
|
return s->buffer;
|
|
}
|
|
|
|
size_t
|
|
stream_length(Stream * s)
|
|
{
|
|
return s->current;
|
|
}
|
|
|
|
const char *
|
|
str_dup_then_free_stream(Stream *s)
|
|
{
|
|
const char *r = str_dup(stream_contents(s));
|
|
free_stream(s);
|
|
return r;
|
|
}
|
|
|
|
int32_t
|
|
stream_last_byte(Stream *s)
|
|
{
|
|
return s->current ? s->buffer[s->current - 1] : -1;
|
|
}
|
|
|
|
/*
|
|
* Return a fixed length buffer (in *BUF and *LEN)
|
|
* growing stream as necessary so that *LEN >= NEED
|
|
* and so that even if all *LEN bytes are used there
|
|
* is space for a final \0.
|
|
*/
|
|
void
|
|
stream_beginfill(Stream *s, size_t need, char **buf, size_t *len)
|
|
{
|
|
(void)grew(s, need);
|
|
*buf = s->buffer + s->current;
|
|
*len = s->buflen - s->current - 1;
|
|
}
|
|
|
|
/*
|
|
* Advance stream pointer so that exactly UNUSED bytes remain,
|
|
* or equivalently, update stream to account for
|
|
* *LEN - UNUSED bytes having been written
|
|
* starting at *BUF; UNUSED must be <= *LEN).
|
|
*
|
|
* Not calling this leaves stream in the state as if
|
|
* nothing had been written to it since the _beginfill call
|
|
*/
|
|
void
|
|
stream_endfill(Stream *s, size_t unused)
|
|
{
|
|
if (unused >= s->buflen - s->current)
|
|
panic("stream_endfill: unused count too large");
|
|
s->current = s->buflen - 1 - unused;
|
|
}
|
|
|
|
|
|
/*
|
|
* $Log$
|
|
* Revision 2.5 1996/03/19 07:14:02 pavel
|
|
* Fixed default printing of floating-point numbers. Release 1.8.0p2.
|
|
*
|
|
* Revision 2.4 1996/03/11 23:33:04 pavel
|
|
* Added support for hexadecimal to stream_printf(). Release 1.8.0p1.
|
|
*
|
|
* Revision 2.3 1996/03/10 01:04:38 pavel
|
|
* Increased the precision of printed floating-point numbers by two digits.
|
|
* Release 1.8.0.
|
|
*
|
|
* Revision 2.2 1996/02/08 06:50:39 pavel
|
|
* Added support for %g conversion in stream_printf(). Renamed err/logf() to
|
|
* errlog/oklog(). Updated copyright notice for 1996. Release 1.8.0beta1.
|
|
*
|
|
* Revision 2.1 1996/01/11 07:43:01 pavel
|
|
* Added support for `%o' to stream_printf(). Release 1.8.0alpha5.
|
|
*
|
|
* Revision 2.0 1995/11/30 04:31:43 pavel
|
|
* New baseline version, corresponding to release 1.8.0alpha1.
|
|
*
|
|
* Revision 1.5 1992/10/23 23:03:47 pavel
|
|
* Added copyright notice.
|
|
*
|
|
* Revision 1.4 1992/10/21 03:02:35 pavel
|
|
* Converted to use new automatic configuration system.
|
|
*
|
|
* Revision 1.3 1992/08/10 16:52:24 pjames
|
|
* Updated #includes.
|
|
*
|
|
* Revision 1.2 1992/07/21 00:06:51 pavel
|
|
* Added rcsid_<filename-root> declaration to hold the RCS ident. string.
|
|
*
|
|
* Revision 1.1 1992/07/20 23:23:12 pavel
|
|
* Initial RCS-controlled version.
|
|
*/
|