diff --git a/femtolisp/builtins.c b/femtolisp/builtins.c index c7c544d..fdd14e9 100644 --- a/femtolisp/builtins.c +++ b/femtolisp/builtins.c @@ -39,8 +39,8 @@ value_t fl_print(value_t *args, u_int32_t nargs) { unsigned i; for (i=0; i < nargs; i++) - print(stdout, args[i], 0); - fputc('\n', stdout); + print(ios_stdout, args[i], 0); + ios_putc('\n', ios_stdout); return nargs ? args[nargs-1] : NIL; } @@ -48,7 +48,7 @@ value_t fl_princ(value_t *args, u_int32_t nargs) { unsigned i; for (i=0; i < nargs; i++) - print(stdout, args[i], 1); + print(ios_stdout, args[i], 1); return nargs ? args[nargs-1] : NIL; } @@ -56,7 +56,7 @@ value_t fl_read(value_t *args, u_int32_t nargs) { (void)args; argcount("read", nargs, 0); - return read_sexpr(stdin); + return read_sexpr(ios_stdin); } value_t fl_load(value_t *args, u_int32_t nargs) diff --git a/femtolisp/cvalues.c b/femtolisp/cvalues.c index 1e0b1d4..f2b2b12 100644 --- a/femtolisp/cvalues.c +++ b/femtolisp/cvalues.c @@ -32,7 +32,7 @@ value_t autoreleasesym, typeofsym, sizeofsym; static void cvalue_init(value_t type, value_t *vs, u_int32_t nv, void *dest); -void cvalue_print(FILE *f, value_t v, int princ); +void cvalue_print(ios_t *f, value_t v, int princ); // exported guest functions value_t cvalue_new(value_t *args, u_int32_t nargs); value_t cvalue_sizeof(value_t *args, u_int32_t nargs); diff --git a/femtolisp/flisp.c b/femtolisp/flisp.c index b2de19a..8f3309e 100644 --- a/femtolisp/flisp.c +++ b/femtolisp/flisp.c @@ -84,7 +84,7 @@ value_t defunsym, defmacrosym, forsym, labelsym, printprettysym; static value_t eval_sexpr(value_t e, uint32_t penv, int tail); static value_t *alloc_words(int n); static value_t relocate(value_t v); -static void do_print(FILE *f, value_t v, int princ); +static void do_print(ios_t *f, value_t v, int princ); typedef struct _readstate_t { ptrhash_t backrefs; @@ -1389,62 +1389,64 @@ static void print_toplevel_exception() { if (iscons(lasterror) && car_(lasterror) == TypeError && llength(lasterror) == 4) { - fprintf(stderr, "type-error: "); - print(stderr, car_(cdr_(lasterror)), 1); - fprintf(stderr, ": expected "); - print(stderr, car_(cdr_(cdr_(lasterror))), 1); - fprintf(stderr, ", got "); - print(stderr, car_(cdr_(cdr_(cdr_(lasterror)))), 0); + ios_printf(ios_stderr, "type-error: "); + print(ios_stderr, car_(cdr_(lasterror)), 1); + ios_printf(ios_stderr, ": expected "); + print(ios_stderr, car_(cdr_(cdr_(lasterror))), 1); + ios_printf(ios_stderr, ", got "); + print(ios_stderr, car_(cdr_(cdr_(cdr_(lasterror)))), 0); } else if (iscons(lasterror) && car_(lasterror) == UnboundError && iscons(cdr_(lasterror))) { - fprintf(stderr, "unbound-error: eval: variable %s has no value", - (symbol_name(car_(cdr_(lasterror))))); + ios_printf(ios_stderr, "unbound-error: eval: variable %s has no value", + (symbol_name(car_(cdr_(lasterror))))); } else if (iscons(lasterror) && car_(lasterror) == Error) { value_t v = cdr_(lasterror); - fprintf(stderr, "error: "); + ios_printf(ios_stderr, "error: "); while (iscons(v)) { - print(stderr, car_(v), 1); + print(ios_stderr, car_(v), 1); v = cdr_(v); } } else { if (lasterror != NIL) { if (!lerrorbuf[0]) - fprintf(stderr, "*** Unhandled exception: "); - print(stderr, lasterror, 0); + ios_printf(ios_stderr, "*** Unhandled exception: "); + print(ios_stderr, lasterror, 0); if (lerrorbuf[0]) - fprintf(stderr, ": "); + ios_printf(ios_stderr, ": "); } } if (lerrorbuf[0]) - fprintf(stderr, "%s", lerrorbuf); + ios_printf(ios_stderr, "%s", lerrorbuf); } value_t load_file(char *fname) { value_t volatile e, v=NIL; - FILE * volatile f = fopen(fname, "r"); + ios_t fi; + ios_t * volatile f; + f = &fi; f = ios_file(f, fname, 0, 0); if (f == NULL) lerror(IOError, "file \"%s\" not found", fname); FL_TRY { while (1) { e = read_sexpr(f); - //print(stdout,e,0); printf("\n"); - if (feof(f)) break; + //print(ios_stdout,e,0); ios_puts("\n", ios_stdout); + if (ios_eof(f)) break; v = toplevel_eval(e); } } FL_CATCH { - fclose(f); + ios_close(f); size_t msglen = strlen(lerrorbuf); snprintf(&lerrorbuf[msglen], sizeof(lerrorbuf)-msglen, "\nin file \"%s\"", fname); lerrorbuf[sizeof(lerrorbuf)-1] = '\0'; raise(lasterror); } - fclose(f); + ios_close(f); return v; } @@ -1477,7 +1479,7 @@ int main(int argc, char *argv[]) lerrorbuf[0] = '\0'; lasterror = NIL; - fprintf(stderr, "\n\n"); + ios_puts("\n\n", ios_stderr); goto repl; } load_file("system.lsp"); @@ -1488,13 +1490,13 @@ int main(int argc, char *argv[]) printf(";-------------------|----------------------------------------------------------\n\n"); repl: while (1) { - printf("> "); - v = read_sexpr(stdin); - if (feof(stdin)) break; - print(stdout, v=toplevel_eval(v), 0); + ios_puts("> ", ios_stdout); ios_flush(ios_stdout); + v = read_sexpr(ios_stdin); + if (ios_eof(ios_stdin)) break; + print(ios_stdout, v=toplevel_eval(v), 0); set(symbol("that"), v); - printf("\n\n"); + ios_puts("\n\n", ios_stdout); } - printf("\n"); + ios_puts("\n", ios_stdout); return 0; } diff --git a/femtolisp/flisp.h b/femtolisp/flisp.h index 17605aa..4ebe40a 100644 --- a/femtolisp/flisp.h +++ b/femtolisp/flisp.h @@ -105,8 +105,8 @@ enum { extern value_t NIL, T; /* read, eval, print main entry points */ -value_t read_sexpr(FILE *f); -void print(FILE *f, value_t v, int princ); +value_t read_sexpr(ios_t *f); +void print(ios_t *f, value_t v, int princ); value_t toplevel_eval(value_t expr); value_t apply(value_t f, value_t l); value_t load_file(char *fname); diff --git a/femtolisp/print.c b/femtolisp/print.c index e1b7952..9ea009a 100644 --- a/femtolisp/print.c +++ b/femtolisp/print.c @@ -3,27 +3,27 @@ static u_int32_t printlabel; static int print_pretty; static int HPOS, VPOS; -static void outc(char c, FILE *f) +static void outc(char c, ios_t *f) { - fputc(c, f); + ios_putc(c, f); HPOS++; } -static void outs(char *s, FILE *f) +static void outs(char *s, ios_t *f) { - fputs(s, f); + ios_puts(s, f); HPOS += u8_strwidth(s); } -static void outindent(int n, FILE *f) +static void outindent(int n, ios_t *f) { - fputc('\n', f); + ios_putc('\n', f); VPOS++; HPOS = n; while (n >= 8) { - fputc('\t', f); + ios_putc('\t', f); n -= 8; } while (n) { - fputc(' ', f); + ios_putc(' ', f); n--; } } @@ -65,7 +65,7 @@ static void print_traverse(value_t v) } } -static void print_symbol_name(FILE *f, char *name) +static void print_symbol_name(ios_t *f, char *name) { int i, escape=0, charescape=0; @@ -202,7 +202,7 @@ static int blockindent(value_t v) return (allsmallp(v) > 9); } -static void print_pair(FILE *f, value_t v, int princ) +static void print_pair(ios_t *f, value_t v, int princ) { value_t cd; char *op = NULL; @@ -286,16 +286,16 @@ static void print_pair(FILE *f, value_t v, int princ) } } -void cvalue_print(FILE *f, value_t v, int princ); +void cvalue_print(ios_t *f, value_t v, int princ); -static void do_print(FILE *f, value_t v, int princ) +static void do_print(ios_t *f, value_t v, int princ) { value_t label; char *name; switch (tag(v)) { case TAG_NUM : - case TAG_NUM1: HPOS+=fprintf(f, "%ld", numval(v)); break; + case TAG_NUM1: HPOS+=ios_printf(f, "%ld", numval(v)); break; case TAG_SYM: name = symbol_name(v); if (princ) @@ -323,10 +323,10 @@ static void do_print(FILE *f, value_t v, int princ) if ((label=(value_t)ptrhash_get(&printconses, (void*)v)) != (value_t)PH_NOTFOUND) { if (!ismarked(v)) { - HPOS+=fprintf(f, "#%ld#", numval(label)); + HPOS+=ios_printf(f, "#%ld#", numval(label)); return; } - HPOS+=fprintf(f, "#%ld=", numval(label)); + HPOS+=ios_printf(f, "#%ld=", numval(label)); } if (isvector(v)) { outc('[', f); @@ -362,7 +362,7 @@ static void do_print(FILE *f, value_t v, int princ) } } -void print_string(FILE *f, char *str, size_t sz) +void print_string(ios_t *f, char *str, size_t sz) { char buf[512]; size_t i = 0; @@ -381,7 +381,7 @@ static numerictype_t sym_to_numtype(value_t type); // for example #int32(0) can be printed as just 0. this is used // printing in a context where a type is already implied, e.g. inside // an array. -static void cvalue_printdata(FILE *f, void *data, size_t len, value_t type, +static void cvalue_printdata(ios_t *f, void *data, size_t len, value_t type, int princ, int weak) { int64_t tmp=0; @@ -392,11 +392,11 @@ static void cvalue_printdata(FILE *f, void *data, size_t len, value_t type, if (princ) outc(ch, f); else if (weak) - HPOS+=fprintf(f, "%hhu", ch); + HPOS+=ios_printf(f, "%hhu", ch); else if (isprint(ch)) - HPOS+=fprintf(f, "#\\%c", ch); + HPOS+=ios_printf(f, "#\\%c", ch); else - HPOS+=fprintf(f, "#char(%hhu)", ch); + HPOS+=ios_printf(f, "#char(%hhu)", ch); } /* else if (type == ucharsym) { @@ -405,8 +405,8 @@ static void cvalue_printdata(FILE *f, void *data, size_t len, value_t type, outc(ch, f); else { if (!weak) - fprintf(f, "#uchar("); - fprintf(f, "%hhu", ch); + ios_printf(f, "#uchar("); + ios_printf(f, "%hhu", ch); if (!weak) outs(")", f); } @@ -416,7 +416,7 @@ static void cvalue_printdata(FILE *f, void *data, size_t len, value_t type, uint32_t wc = *(uint32_t*)data; char seq[8]; if (weak) - HPOS+=fprintf(f, "%d", (int)wc); + HPOS+=ios_printf(f, "%d", (int)wc); else if (princ || (iswprint(wc) && wc>0x7f)) { // reader only reads #\c syntax as wchar if the code is >0x7f size_t nb = u8_toutf8(seq, sizeof(seq), &wc, 1); @@ -426,7 +426,7 @@ static void cvalue_printdata(FILE *f, void *data, size_t len, value_t type, outs(seq, f); } else { - HPOS+=fprintf(f, "#%s(%d)", symbol_name(type), (int)wc); + HPOS+=ios_printf(f, "#%s(%d)", symbol_name(type), (int)wc); } } else if (type == int64sym @@ -437,14 +437,14 @@ static void cvalue_printdata(FILE *f, void *data, size_t len, value_t type, int64_t i64 = *(int64_t*)data; if (fits_fixnum(i64) || princ) { if (weak || princ) - HPOS+=fprintf(f, "%lld", i64); + HPOS+=ios_printf(f, "%lld", i64); else - HPOS+=fprintf(f, "#%s(%lld)", symbol_name(type), i64); + HPOS+=ios_printf(f, "#%s(%lld)", symbol_name(type), i64); } else - HPOS+=fprintf(f, "#%s(0x%08x%08x)", symbol_name(type), - (uint32_t)(i64>>32), - (uint32_t)(i64)); + HPOS+=ios_printf(f, "#%s(0x%08x%08x)", symbol_name(type), + (uint32_t)(i64>>32), + (uint32_t)(i64)); } else if (type == uint64sym #ifdef BITS64 @@ -454,14 +454,14 @@ static void cvalue_printdata(FILE *f, void *data, size_t len, value_t type, uint64_t ui64 = *(uint64_t*)data; if (fits_fixnum(ui64) || princ) { if (weak || princ) - HPOS+=fprintf(f, "%llu", ui64); + HPOS+=ios_printf(f, "%llu", ui64); else - HPOS+=fprintf(f, "#%s(%llu)", symbol_name(type), ui64); + HPOS+=ios_printf(f, "#%s(%llu)", symbol_name(type), ui64); } else - HPOS+=fprintf(f, "#%s(0x%08x%08x)", symbol_name(type), - (uint32_t)(ui64>>32), - (uint32_t)(ui64)); + HPOS+=ios_printf(f, "#%s(0x%08x%08x)", symbol_name(type), + (uint32_t)(ui64>>32), + (uint32_t)(ui64)); } else if (type == lispvaluesym) { // TODO @@ -479,9 +479,9 @@ static void cvalue_printdata(FILE *f, void *data, size_t len, value_t type, } else { if (!DFINITE(d)) - HPOS+=fprintf(f, "#%s(\"%s\")", symbol_name(type), buf); + HPOS+=ios_printf(f, "#%s(\"%s\")", symbol_name(type), buf); else - HPOS+=fprintf(f, "#%s(%s)", symbol_name(type), buf); + HPOS+=ios_printf(f, "#%s(%s)", symbol_name(type), buf); } } else if (issymbol(type)) { @@ -490,13 +490,13 @@ static void cvalue_printdata(FILE *f, void *data, size_t len, value_t type, tmp = conv_to_int64(data, sym_to_numtype(type)); if (fits_fixnum(tmp) || princ) { if (weak || princ) - HPOS+=fprintf(f, "%lld", tmp); + HPOS+=ios_printf(f, "%lld", tmp); else - HPOS+=fprintf(f, "#%s(%lld)", symbol_name(type), tmp); + HPOS+=ios_printf(f, "#%s(%lld)", symbol_name(type), tmp); } else - HPOS+=fprintf(f, "#%s(0x%08x)", symbol_name(type), - (uint32_t)(tmp&0xffffffff)); + HPOS+=ios_printf(f, "#%s(0x%08x)", symbol_name(type), + (uint32_t)(tmp&0xffffffff)); } else if (iscons(type)) { if (car_(type) == arraysym) { @@ -514,7 +514,7 @@ static void cvalue_printdata(FILE *f, void *data, size_t len, value_t type, } if (eltype == charsym) { if (princ) { - fwrite(data, 1, len, f); + ios_write(f, data, len); } else { print_string(f, (char*)data, len); @@ -562,21 +562,21 @@ static void cvalue_printdata(FILE *f, void *data, size_t len, value_t type, } } -void cvalue_print(FILE *f, value_t v, int princ) +void cvalue_print(ios_t *f, value_t v, int princ) { cvalue_t *cv = (cvalue_t*)ptr(v); void *data = cv_data(cv); if (cv->flags.islispfunction) { - HPOS+=fprintf(f, "#", - (unsigned long)*(guestfunc_t*)data); + HPOS+=ios_printf(f, "#", + (unsigned long)*(guestfunc_t*)data); return; } cvalue_printdata(f, data, cv_len(cv), cv_type(cv), princ, 0); } -void print(FILE *f, value_t v, int princ) +void print(ios_t *f, value_t v, int princ) { print_pretty = (symbol_value(printprettysym) != NIL); ptrhash_reset(&printconses, 32); diff --git a/femtolisp/read.c b/femtolisp/read.c index 461cb31..2b8a3be 100644 --- a/femtolisp/read.c +++ b/femtolisp/read.c @@ -55,21 +55,21 @@ static u_int32_t toktype = TOK_NONE; static value_t tokval; static char buf[256]; -static char nextchar(FILE *f) +static char nextchar(ios_t *f) { int ch; char c; do { - ch = fgetc(f); - if (ch == EOF) + ch = ios_getc(f); + if (ch == IOS_EOF) return 0; c = (char)ch; if (c == ';') { // single-line comment do { - ch = fgetc(f); - if (ch == EOF) + ch = ios_getc(f); + if (ch == IOS_EOF) return 0; } while ((char)ch != '\n'); c = (char)ch; @@ -91,14 +91,14 @@ static void accumchar(char c, int *pi) } // return: 1 if escaped (forced to be symbol) -static int read_token(FILE *f, char c, int digits) +static int read_token(ios_t *f, char c, int digits) { int i=0, ch, escaped=0, issym=0, first=1; while (1) { if (!first) { - ch = fgetc(f); - if (ch == EOF) + ch = ios_getc(f); + if (ch == IOS_EOF) goto terminate; c = (char)ch; } @@ -109,8 +109,8 @@ static int read_token(FILE *f, char c, int digits) } else if (c == '\\') { issym = 1; - ch = fgetc(f); - if (ch == EOF) + ch = ios_getc(f); + if (ch == IOS_EOF) goto terminate; accumchar((char)ch, &i); } @@ -121,13 +121,13 @@ static int read_token(FILE *f, char c, int digits) accumchar(c, &i); } } - ungetc(c, f); + ios_ungetc(c, f); terminate: buf[i++] = '\0'; return issym; } -static u_int32_t peek(FILE *f) +static u_int32_t peek(ios_t *f) { char c, *end; fixnum_t x; @@ -136,7 +136,7 @@ static u_int32_t peek(FILE *f) if (toktype != TOK_NONE) return toktype; c = nextchar(f); - if (feof(f)) return TOK_NONE; + if (ios_eof(f)) return TOK_NONE; if (c == '(') { toktype = TOK_OPEN; } @@ -159,8 +159,8 @@ static u_int32_t peek(FILE *f) toktype = TOK_DOUBLEQUOTE; } else if (c == '#') { - ch = fgetc(f); - if (ch == EOF) + ch = ios_getc(f); + if (ch == IOS_EOF) lerror(ParseError, "read: invalid read macro"); if ((char)ch == '.') { toktype = TOK_SHARPDOT; @@ -169,8 +169,8 @@ static u_int32_t peek(FILE *f) toktype = TOK_SHARPQUOTE; } else if ((char)ch == '\\') { - u_int32_t cval = u8_fgetc(f); - if (cval == UEOF) + uint32_t cval; + if (ios_getutf8(f, &cval) == IOS_EOF) lerror(ParseError, "read: end of input in character constant"); toktype = TOK_NUM; tokval = fixnum(cval); @@ -189,7 +189,7 @@ static u_int32_t peek(FILE *f) } else if (isdigit((char)ch)) { read_token(f, (char)ch, 1); - c = (char)fgetc(f); + c = (char)ios_getc(f); if (c == '#') toktype = TOK_BACKREF; else if (c == '=') @@ -205,19 +205,19 @@ static u_int32_t peek(FILE *f) else if ((char)ch == '!') { // #! single line comment for shbang script support do { - ch = fgetc(f); - } while (ch != EOF && (char)ch != '\n'); + ch = ios_getc(f); + } while (ch != IOS_EOF && (char)ch != '\n'); return peek(f); } else if ((char)ch == '|') { // multiline comment while (1) { - ch = fgetc(f); + ch = ios_getc(f); hashpipe_got: - if (ch == EOF) + if (ch == IOS_EOF) lerror(ParseError, "read: eof within comment"); if ((char)ch == '|') { - ch = fgetc(f); + ch = ios_getc(f); if ((char)ch == '#') break; goto hashpipe_got; @@ -228,9 +228,9 @@ static u_int32_t peek(FILE *f) } else if ((char)ch == ':') { // gensym - ch = fgetc(f); + ch = ios_getc(f); if ((char)ch == 'g') - ch = fgetc(f); + ch = ios_getc(f); read_token(f, (char)ch, 0); errno = 0; x = strtol(buf, &end, 10); @@ -256,15 +256,15 @@ static u_int32_t peek(FILE *f) } else if (c == ',') { toktype = TOK_COMMA; - ch = fgetc(f); - if (ch == EOF) + ch = ios_getc(f); + if (ch == IOS_EOF) return toktype; if ((char)ch == '@') toktype = TOK_COMMAAT; else if ((char)ch == '.') toktype = TOK_COMMADOT; else - ungetc((char)ch, f); + ios_ungetc((char)ch, f); } else { if (!read_token(f, c, 0)) { @@ -286,9 +286,9 @@ static u_int32_t peek(FILE *f) return toktype; } -static value_t do_read_sexpr(FILE *f, value_t label); +static value_t do_read_sexpr(ios_t *f, value_t label); -static value_t read_vector(FILE *f, value_t label, u_int32_t closer) +static value_t read_vector(ios_t *f, value_t label, u_int32_t closer) { value_t v=alloc_vector(4, 1), elt; u_int32_t i=0; @@ -296,7 +296,7 @@ static value_t read_vector(FILE *f, value_t label, u_int32_t closer) if (label != UNBOUND) ptrhash_put(&readstate->backrefs, (void*)label, (void*)v); while (peek(f) != closer) { - if (feof(f)) + if (ios_eof(f)) lerror(ParseError, "read: unexpected end of input"); if (i >= vector_size(v)) Stack[SP-1] = vector_grow(v); @@ -310,7 +310,7 @@ static value_t read_vector(FILE *f, value_t label, u_int32_t closer) return POP(); } -static value_t read_string(FILE *f) +static value_t read_string(ios_t *f) { char *buf, *temp; char eseq[10]; @@ -330,16 +330,16 @@ static value_t read_string(FILE *f) } buf = temp; } - c = fgetc(f); - if (c == EOF) { + c = ios_getc(f); + if (c == IOS_EOF) { free(buf); lerror(ParseError, "read: unexpected end of input in string"); } if (c == '"') break; else if (c == '\\') { - c = fgetc(f); - if (c == EOF) { + c = ios_getc(f); + if (c == IOS_EOF) { free(buf); lerror(ParseError, "read: end of input in escape sequence"); } @@ -347,9 +347,9 @@ static value_t read_string(FILE *f) if (octal_digit(c)) { do { eseq[j++] = c; - c = fgetc(f); - } while (octal_digit(c) && j<3 && (c!=EOF)); - if (c!=EOF) ungetc(c, f); + c = ios_getc(f); + } while (octal_digit(c) && j<3 && (c!=IOS_EOF)); + if (c!=IOS_EOF) ios_ungetc(c, f); eseq[j] = '\0'; wc = strtol(eseq, NULL, 8); i += u8_wc_toutf8(&buf[i], wc); @@ -358,12 +358,12 @@ static value_t read_string(FILE *f) (c=='u' && (ndig=4)) || (c=='U' && (ndig=8))) { wc = c; - c = fgetc(f); - while (hex_digit(c) && jsize - s->bpos; + if (s->state == bst_wr) + return space; + if (space >= n || s->bm == bm_mem || s->fd == -1) + return space; + if (s->maxsize < s->bpos+n) { + if (_buf_realloc(s, s->maxsize + n)==NULL) + return space; + } + size_t got; + int result = _os_read(s->fd, s->buf+s->size, s->maxsize - s->size, &got); + if (result) + return space; + s->size += got; + return s->size - s->bpos; +} + size_t ios_write(ios_t *s, char *data, size_t n) { if (n == 0) return 0; @@ -421,10 +440,13 @@ int ios_eof(ios_t *s) return 1; if (s->_eof) return 1; + return 0; + /* if (_fd_available(s->fd)) return 0; s->_eof = 1; return 1; + */ } static void _discard_partial_buffer(ios_t *s) @@ -646,36 +668,22 @@ ios_t *ios_fd(ios_t *s, long fd, int isfile) return s; } -ios_t *ios_stdin() -{ - static ios_t *_ios_stdin = NULL; - if (_ios_stdin == NULL) { - _ios_stdin = malloc(sizeof(ios_t)); - ios_fd(_ios_stdin, STDIN_FILENO, 0); - } - return _ios_stdin; -} +ios_t *ios_stdin = NULL; +ios_t *ios_stdout = NULL; +ios_t *ios_stderr = NULL; -ios_t *ios_stdout() +void ios_init_stdstreams() { - static ios_t *_ios_stdout = NULL; - if (_ios_stdout == NULL) { - _ios_stdout = malloc(sizeof(ios_t)); - ios_fd(_ios_stdout, STDOUT_FILENO, 0); - _ios_stdout->bm = bm_line; - } - return _ios_stdout; -} + ios_stdin = malloc(sizeof(ios_t)); + ios_fd(ios_stdin, STDIN_FILENO, 0); -ios_t *ios_stderr() -{ - static ios_t *_ios_stderr = NULL; - if (_ios_stderr == NULL) { - _ios_stderr = malloc(sizeof(ios_t)); - ios_fd(_ios_stderr, STDERR_FILENO, 0); - _ios_stderr->bm = bm_none; - } - return _ios_stderr; + ios_stdout = malloc(sizeof(ios_t)); + ios_fd(ios_stdout, STDOUT_FILENO, 0); + ios_stdout->bm = bm_line; + + ios_stderr = malloc(sizeof(ios_t)); + ios_fd(ios_stderr, STDERR_FILENO, 0); + ios_stderr->bm = bm_none; } /* higher level interface */ @@ -689,10 +697,11 @@ int ios_putc(int c, ios_t *s) int ios_getc(ios_t *s) { + if (s->bpos < s->size) + return s->buf[s->bpos++]; if (s->_eof) return IOS_EOF; char ch; - size_t n = ios_read(s, &ch, 1); - if (n < 1) + if (ios_read(s, &ch, 1) < 1) return IOS_EOF; return (int)ch; } @@ -716,20 +725,53 @@ int ios_ungetc(int c, ios_t *s) return c; } +int ios_getutf8(ios_t *s, uint32_t *pwc) +{ + int c; + size_t sz; + char c0; + char buf[8]; + + c = ios_getc(s); + if (c == IOS_EOF) + return IOS_EOF; + c0 = (char)c; + sz = u8_seqlen(&c0)-1; + if (sz == 0) { + *pwc = (uint32_t)c0; + return 1; + } + if (ios_ungetc(c, s) == IOS_EOF) + return IOS_EOF; + if (ios_readprep(s, sz) < sz) + // NOTE: this can return EOF even if some bytes are available + return IOS_EOF; + size_t i = s->bpos; + *pwc = u8_nextchar(s->buf, &i); + ios_read(s, buf, sz+1); + return 1; +} + int ios_printf(ios_t *s, char *format, ...) { - char *str; + char buf[512]; + char *str=&buf[0]; va_list args; + int c; va_start(args, format); + // TODO: avoid copy - int c = vasprintf(&str, format, args); + c = vsnprintf(buf, sizeof(buf), format, args); + if ((size_t)c >= sizeof(buf)) + c = vasprintf(&str, format, args); + va_end(args); - if (c == -1) return c; + if (c < 0) return c; ios_write(s, str, c); - free(str); + if (str != &buf[0]) free(str); return c; } diff --git a/llt/ios.h b/llt/ios.h index 9feb13f..2076e55 100644 --- a/llt/ios.h +++ b/llt/ios.h @@ -9,7 +9,7 @@ typedef enum { bm_none, bm_line, bm_block, bm_mem } bufmode_t; typedef enum { bst_none, bst_rd, bst_wr } bufstate_t; #define IOS_INLSIZE 54 -#define IOS_BUFSIZE 4095 +#define IOS_BUFSIZE 8191 typedef struct { bufmode_t bm; @@ -79,8 +79,8 @@ int ios_bufmode(ios_t *s, bufmode_t mode); void ios_bswap(ios_t *s, int bswap); int ios_copy(ios_t *to, ios_t *from, size_t nbytes); int ios_copyall(ios_t *to, ios_t *from); -// ensure at least n bytes are buffered if possible. returns actual #. -//size_t ios_ensure(ios_t *from, size_t n); +// ensure at least n bytes are buffered if possible. returns # available. +size_t ios_readprep(ios_t *from, size_t n); //void ios_lock(ios_t *s); //int ios_trylock(ios_t *s); //int ios_unlock(ios_t *s); @@ -91,9 +91,10 @@ ios_t *ios_mem(ios_t *s, size_t initsize); ios_t *ios_str(ios_t *s, char *str); ios_t *ios_fd(ios_t *s, long fd, int isfile); // todo: ios_socket -ios_t *ios_stdin(); -ios_t *ios_stdout(); -ios_t *ios_stderr(); +extern ios_t *ios_stdin; +extern ios_t *ios_stdout; +extern ios_t *ios_stderr; +void ios_init_stdstreams(); /* high-level functions - output */ int ios_putnum(ios_t *s, char *data, uint32_t type); diff --git a/llt/utf8.c b/llt/utf8.c index 78c1d99..c9fc8d3 100644 --- a/llt/utf8.c +++ b/llt/utf8.c @@ -80,7 +80,7 @@ size_t u8_codingsize(u_int32_t *wcstr, size_t n) sz = dest size in # of wide characters returns # characters converted - if sz = srcsz+1 (i.e. 4*srcsz+4 bytes), there will always be enough space. + if sz == srcsz+1 (i.e. 4*srcsz+4 bytes), there will always be enough space. */ size_t u8_toucs(u_int32_t *dest, size_t sz, const char *src, size_t srcsz) { @@ -565,23 +565,25 @@ int u8_is_locale_utf8(const char *locale) size_t u8_vprintf(const char *fmt, va_list ap) { - size_t cnt, sz=0, nc; + size_t cnt, sz=0, nc, needfree=0; char *buf; u_int32_t *wcs; sz = 512; buf = (char*)alloca(sz); - try_print: cnt = vsnprintf(buf, sz, fmt, ap); + if ((ssize_t)cnt < 0) + return 0; if (cnt >= sz) { - buf = (char*)alloca(cnt - sz + 1); - sz = cnt + 1; - goto try_print; + buf = (char*)malloc(cnt + 1); + needfree = 1; + vsnprintf(buf, cnt+1, fmt, ap); } wcs = (u_int32_t*)alloca((cnt+1) * sizeof(u_int32_t)); nc = u8_toucs(wcs, cnt+1, buf, cnt); wcs[nc] = 0; printf("%ls", (wchar_t*)wcs); + if (needfree) free(buf); return nc; } @@ -702,27 +704,3 @@ int u8_reverse(char *dest, char * src, size_t len) } return 0; } - -u_int32_t u8_fgetc(FILE *f) -{ - int amt=0, sz, c; - u_int32_t ch=0; - char c0; - - c = fgetc(f); - if (c == EOF) - return UEOF; - ch = (u_int32_t)c; - c0 = (char)ch; - amt = sz = u8_seqlen(&c0); - while (--amt) { - ch <<= 6; - c = fgetc(f); - if (c == EOF) - return UEOF; - ch += (u_int32_t)c; - } - ch -= offsetsFromUTF8[sz-1]; - - return ch; -} diff --git a/llt/utf8.h b/llt/utf8.h index 656483c..1a5db95 100644 --- a/llt/utf8.h +++ b/llt/utf8.h @@ -121,8 +121,4 @@ int u8_isvalid(const char *str, int length); be allocated to at least len+1 bytes. returns 1 for error, 0 otherwise */ int u8_reverse(char *dest, char *src, size_t len); -#include // temporary, until u8_fgetc is gone -/* read a UTF-8 sequence from a stream and return a wide character or UEOF */ -u_int32_t u8_fgetc(FILE *f); - #endif