refactored escape sequence handling a bit, added error for invalid hex
discarding rest of input line after a parse error made compare() do less work for unordered comparison added peekc and purge to ios
This commit is contained in:
parent
120522c212
commit
c89111f7cb
|
@ -30,10 +30,8 @@ static void eq_union(ptrhash_t *table, value_t a, value_t b,
|
||||||
ptrhash_put(table, (void*)b, (void*)ca);
|
ptrhash_put(table, (void*)b, (void*)ca);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ordered comparison
|
|
||||||
|
|
||||||
// a is a fixnum, b is a cvalue
|
// a is a fixnum, b is a cvalue
|
||||||
static value_t compare_num_cvalue(value_t a, value_t b)
|
static value_t compare_num_cvalue(value_t a, value_t b, int eq)
|
||||||
{
|
{
|
||||||
cvalue_t *bcv = (cvalue_t*)ptr(b);
|
cvalue_t *bcv = (cvalue_t*)ptr(b);
|
||||||
numerictype_t bt;
|
numerictype_t bt;
|
||||||
|
@ -42,6 +40,7 @@ static value_t compare_num_cvalue(value_t a, value_t b)
|
||||||
void *bptr = cv_data(bcv);
|
void *bptr = cv_data(bcv);
|
||||||
if (cmp_eq(&ia, T_FIXNUM, bptr, bt))
|
if (cmp_eq(&ia, T_FIXNUM, bptr, bt))
|
||||||
return fixnum(0);
|
return fixnum(0);
|
||||||
|
if (eq) return fixnum(1);
|
||||||
if (cmp_lt(&ia, T_FIXNUM, bptr, bt))
|
if (cmp_lt(&ia, T_FIXNUM, bptr, bt))
|
||||||
return fixnum(-1);
|
return fixnum(-1);
|
||||||
}
|
}
|
||||||
|
@ -51,17 +50,19 @@ static value_t compare_num_cvalue(value_t a, value_t b)
|
||||||
return fixnum(1);
|
return fixnum(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static value_t bounded_compare(value_t a, value_t b, int bound);
|
static value_t bounded_compare(value_t a, value_t b, int bound, int eq);
|
||||||
static value_t cyc_compare(value_t a, value_t b, ptrhash_t *table);
|
static value_t cyc_compare(value_t a, value_t b, ptrhash_t *table, int eq);
|
||||||
|
|
||||||
static value_t bounded_vector_compare(value_t a, value_t b, int bound)
|
static value_t bounded_vector_compare(value_t a, value_t b, int bound, int eq)
|
||||||
{
|
{
|
||||||
size_t la = vector_size(a);
|
size_t la = vector_size(a);
|
||||||
size_t lb = vector_size(b);
|
size_t lb = vector_size(b);
|
||||||
size_t m, i;
|
size_t m, i;
|
||||||
|
if (eq && (la!=lb)) return fixnum(1);
|
||||||
m = la < lb ? la : lb;
|
m = la < lb ? la : lb;
|
||||||
for (i = 0; i < m; i++) {
|
for (i = 0; i < m; i++) {
|
||||||
value_t d = bounded_compare(vector_elt(a,i), vector_elt(b,i), bound-1);
|
value_t d = bounded_compare(vector_elt(a,i), vector_elt(b,i),
|
||||||
|
bound-1, eq);
|
||||||
if (d==NIL || numval(d)!=0) return d;
|
if (d==NIL || numval(d)!=0) return d;
|
||||||
}
|
}
|
||||||
if (la < lb) return fixnum(-1);
|
if (la < lb) return fixnum(-1);
|
||||||
|
@ -71,7 +72,7 @@ static value_t bounded_vector_compare(value_t a, value_t b, int bound)
|
||||||
|
|
||||||
// strange comparisons are resolved arbitrarily but consistently.
|
// strange comparisons are resolved arbitrarily but consistently.
|
||||||
// ordering: number < builtin < cvalue < vector < symbol < cons
|
// ordering: number < builtin < cvalue < vector < symbol < cons
|
||||||
static value_t bounded_compare(value_t a, value_t b, int bound)
|
static value_t bounded_compare(value_t a, value_t b, int bound, int eq)
|
||||||
{
|
{
|
||||||
value_t d;
|
value_t d;
|
||||||
|
|
||||||
|
@ -88,16 +89,17 @@ static value_t bounded_compare(value_t a, value_t b, int bound)
|
||||||
return (numval(a) < numval(b)) ? fixnum(-1) : fixnum(1);
|
return (numval(a) < numval(b)) ? fixnum(-1) : fixnum(1);
|
||||||
}
|
}
|
||||||
if (iscvalue(b)) {
|
if (iscvalue(b)) {
|
||||||
return compare_num_cvalue(a, b);
|
return compare_num_cvalue(a, b, eq);
|
||||||
}
|
}
|
||||||
return fixnum(-1);
|
return fixnum(-1);
|
||||||
case TAG_SYM:
|
case TAG_SYM:
|
||||||
|
if (eq) return fixnum(1);
|
||||||
if (tagb < TAG_SYM) return fixnum(1);
|
if (tagb < TAG_SYM) return fixnum(1);
|
||||||
if (tagb > TAG_SYM) return fixnum(-1);
|
if (tagb > TAG_SYM) return fixnum(-1);
|
||||||
return fixnum(strcmp(symbol_name(a), symbol_name(b)));
|
return fixnum(strcmp(symbol_name(a), symbol_name(b)));
|
||||||
case TAG_VECTOR:
|
case TAG_VECTOR:
|
||||||
if (isvector(b))
|
if (isvector(b))
|
||||||
return bounded_vector_compare(a, b, bound);
|
return bounded_vector_compare(a, b, bound, eq);
|
||||||
break;
|
break;
|
||||||
case TAG_CVALUE:
|
case TAG_CVALUE:
|
||||||
if (iscvalue(b)) {
|
if (iscvalue(b)) {
|
||||||
|
@ -109,6 +111,7 @@ static value_t bounded_compare(value_t a, value_t b, int bound)
|
||||||
void *bptr = cv_data(bcv);
|
void *bptr = cv_data(bcv);
|
||||||
if (cmp_eq(aptr, at, bptr, bt))
|
if (cmp_eq(aptr, at, bptr, bt))
|
||||||
return fixnum(0);
|
return fixnum(0);
|
||||||
|
if (eq) return fixnum(1);
|
||||||
if (cmp_lt(aptr, at, bptr, bt))
|
if (cmp_lt(aptr, at, bptr, bt))
|
||||||
return fixnum(-1);
|
return fixnum(-1);
|
||||||
return fixnum(1);
|
return fixnum(1);
|
||||||
|
@ -116,7 +119,7 @@ static value_t bounded_compare(value_t a, value_t b, int bound)
|
||||||
return cvalue_compare(a, b);
|
return cvalue_compare(a, b);
|
||||||
}
|
}
|
||||||
else if (isfixnum(b)) {
|
else if (isfixnum(b)) {
|
||||||
return fixnum(-numval(compare_num_cvalue(b, a)));
|
return fixnum(-numval(compare_num_cvalue(b, a, eq)));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TAG_BUILTIN:
|
case TAG_BUILTIN:
|
||||||
|
@ -126,7 +129,7 @@ static value_t bounded_compare(value_t a, value_t b, int bound)
|
||||||
break;
|
break;
|
||||||
case TAG_CONS:
|
case TAG_CONS:
|
||||||
if (tagb < TAG_CONS) return fixnum(1);
|
if (tagb < TAG_CONS) return fixnum(1);
|
||||||
d = bounded_compare(car_(a), car_(b), bound-1);
|
d = bounded_compare(car_(a), car_(b), bound-1, eq);
|
||||||
if (d==NIL || numval(d) != 0) return d;
|
if (d==NIL || numval(d) != 0) return d;
|
||||||
a = cdr_(a); b = cdr_(b);
|
a = cdr_(a); b = cdr_(b);
|
||||||
bound--;
|
bound--;
|
||||||
|
@ -135,7 +138,8 @@ static value_t bounded_compare(value_t a, value_t b, int bound)
|
||||||
return (taga < tagb) ? fixnum(-1) : fixnum(1);
|
return (taga < tagb) ? fixnum(-1) : fixnum(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static value_t cyc_vector_compare(value_t a, value_t b, ptrhash_t *table)
|
static value_t cyc_vector_compare(value_t a, value_t b, ptrhash_t *table,
|
||||||
|
int eq)
|
||||||
{
|
{
|
||||||
size_t la = vector_size(a);
|
size_t la = vector_size(a);
|
||||||
size_t lb = vector_size(b);
|
size_t lb = vector_size(b);
|
||||||
|
@ -143,12 +147,13 @@ static value_t cyc_vector_compare(value_t a, value_t b, ptrhash_t *table)
|
||||||
value_t d, xa, xb, ca, cb;
|
value_t d, xa, xb, ca, cb;
|
||||||
|
|
||||||
// first try to prove them different with no recursion
|
// first try to prove them different with no recursion
|
||||||
|
if (eq && (la!=lb)) return fixnum(1);
|
||||||
m = la < lb ? la : lb;
|
m = la < lb ? la : lb;
|
||||||
for (i = 0; i < m; i++) {
|
for (i = 0; i < m; i++) {
|
||||||
xa = vector_elt(a,i);
|
xa = vector_elt(a,i);
|
||||||
xb = vector_elt(b,i);
|
xb = vector_elt(b,i);
|
||||||
if (leafp(xa) || leafp(xb)) {
|
if (leafp(xa) || leafp(xb)) {
|
||||||
d = bounded_compare(xa, xb, 1);
|
d = bounded_compare(xa, xb, 1, eq);
|
||||||
if (numval(d)!=0) return d;
|
if (numval(d)!=0) return d;
|
||||||
}
|
}
|
||||||
else if (cmptag(xa) < cmptag(xb)) {
|
else if (cmptag(xa) < cmptag(xb)) {
|
||||||
|
@ -170,7 +175,7 @@ static value_t cyc_vector_compare(value_t a, value_t b, ptrhash_t *table)
|
||||||
xa = vector_elt(a,i);
|
xa = vector_elt(a,i);
|
||||||
xb = vector_elt(b,i);
|
xb = vector_elt(b,i);
|
||||||
if (!leafp(xa) && !leafp(xb)) {
|
if (!leafp(xa) && !leafp(xb)) {
|
||||||
d = cyc_compare(xa, xb, table);
|
d = cyc_compare(xa, xb, table, eq);
|
||||||
if (numval(d)!=0)
|
if (numval(d)!=0)
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
@ -181,7 +186,7 @@ static value_t cyc_vector_compare(value_t a, value_t b, ptrhash_t *table)
|
||||||
return fixnum(0);
|
return fixnum(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static value_t cyc_compare(value_t a, value_t b, ptrhash_t *table)
|
static value_t cyc_compare(value_t a, value_t b, ptrhash_t *table, int eq)
|
||||||
{
|
{
|
||||||
if (a==b)
|
if (a==b)
|
||||||
return fixnum(0);
|
return fixnum(0);
|
||||||
|
@ -193,7 +198,7 @@ static value_t cyc_compare(value_t a, value_t b, ptrhash_t *table)
|
||||||
int tagab = cmptag(ab); int tagdb = cmptag(db);
|
int tagab = cmptag(ab); int tagdb = cmptag(db);
|
||||||
value_t d, ca, cb;
|
value_t d, ca, cb;
|
||||||
if (leafp(aa) || leafp(ab)) {
|
if (leafp(aa) || leafp(ab)) {
|
||||||
d = bounded_compare(aa, ab, 1);
|
d = bounded_compare(aa, ab, 1, eq);
|
||||||
if (numval(d)!=0) return d;
|
if (numval(d)!=0) return d;
|
||||||
}
|
}
|
||||||
else if (tagaa < tagab)
|
else if (tagaa < tagab)
|
||||||
|
@ -201,7 +206,7 @@ static value_t cyc_compare(value_t a, value_t b, ptrhash_t *table)
|
||||||
else if (tagaa > tagab)
|
else if (tagaa > tagab)
|
||||||
return fixnum(1);
|
return fixnum(1);
|
||||||
if (leafp(da) || leafp(db)) {
|
if (leafp(da) || leafp(db)) {
|
||||||
d = bounded_compare(da, db, 1);
|
d = bounded_compare(da, db, 1, eq);
|
||||||
if (numval(d)!=0) return d;
|
if (numval(d)!=0) return d;
|
||||||
}
|
}
|
||||||
else if (tagda < tagdb)
|
else if (tagda < tagdb)
|
||||||
|
@ -215,18 +220,18 @@ static value_t cyc_compare(value_t a, value_t b, ptrhash_t *table)
|
||||||
return fixnum(0);
|
return fixnum(0);
|
||||||
|
|
||||||
eq_union(table, a, b, ca, cb);
|
eq_union(table, a, b, ca, cb);
|
||||||
d = cyc_compare(aa, ab, table);
|
d = cyc_compare(aa, ab, table, eq);
|
||||||
if (numval(d)!=0) return d;
|
if (numval(d)!=0) return d;
|
||||||
return cyc_compare(da, db, table);
|
return cyc_compare(da, db, table, eq);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return fixnum(1);
|
return fixnum(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (isvector(a) && isvector(b)) {
|
else if (isvector(a) && isvector(b)) {
|
||||||
return cyc_vector_compare(a, b, table);
|
return cyc_vector_compare(a, b, table, eq);
|
||||||
}
|
}
|
||||||
return bounded_compare(a, b, 1);
|
return bounded_compare(a, b, 1, eq);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ptrhash_t equal_eq_hashtable;
|
static ptrhash_t equal_eq_hashtable;
|
||||||
|
@ -235,21 +240,27 @@ void comparehash_init()
|
||||||
ptrhash_new(&equal_eq_hashtable, 512);
|
ptrhash_new(&equal_eq_hashtable, 512);
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t compare(value_t a, value_t b)
|
// 'eq' means unordered comparison is sufficient
|
||||||
|
static value_t compare_(value_t a, value_t b, int eq)
|
||||||
{
|
{
|
||||||
value_t guess = bounded_compare(a, b, 2048);
|
value_t guess = bounded_compare(a, b, 2048, eq);
|
||||||
if (guess == NIL) {
|
if (guess == NIL) {
|
||||||
guess = cyc_compare(a, b, &equal_eq_hashtable);
|
guess = cyc_compare(a, b, &equal_eq_hashtable, eq);
|
||||||
ptrhash_reset(&equal_eq_hashtable, 512);
|
ptrhash_reset(&equal_eq_hashtable, 512);
|
||||||
}
|
}
|
||||||
return guess;
|
return guess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
value_t compare(value_t a, value_t b)
|
||||||
|
{
|
||||||
|
return compare_(a, b, 0);
|
||||||
|
}
|
||||||
|
|
||||||
value_t equal(value_t a, value_t b)
|
value_t equal(value_t a, value_t b)
|
||||||
{
|
{
|
||||||
if (eq_comparable(a, b))
|
if (eq_comparable(a, b))
|
||||||
return (a == b) ? T : NIL;
|
return (a == b) ? T : NIL;
|
||||||
return (numval(compare(a,b))==0 ? T : NIL);
|
return (numval(compare_(a,b,1))==0 ? T : NIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1509,7 +1509,13 @@ int main(int argc, char *argv[])
|
||||||
repl:
|
repl:
|
||||||
while (1) {
|
while (1) {
|
||||||
ios_puts("> ", ios_stdout); ios_flush(ios_stdout);
|
ios_puts("> ", ios_stdout); ios_flush(ios_stdout);
|
||||||
|
FL_TRY {
|
||||||
v = read_sexpr(ios_stdin);
|
v = read_sexpr(ios_stdin);
|
||||||
|
}
|
||||||
|
FL_CATCH {
|
||||||
|
ios_purge(ios_stdin);
|
||||||
|
raise(lasterror);
|
||||||
|
}
|
||||||
if (ios_eof(ios_stdin)) break;
|
if (ios_eof(ios_stdin)) break;
|
||||||
print(ios_stdout, v=toplevel_eval(v), 0);
|
print(ios_stdout, v=toplevel_eval(v), 0);
|
||||||
set(symbol("that"), v);
|
set(symbol("that"), v);
|
||||||
|
|
|
@ -357,7 +357,6 @@ static value_t read_string(ios_t *f)
|
||||||
else if ((c=='x' && (ndig=2)) ||
|
else if ((c=='x' && (ndig=2)) ||
|
||||||
(c=='u' && (ndig=4)) ||
|
(c=='u' && (ndig=4)) ||
|
||||||
(c=='U' && (ndig=8))) {
|
(c=='U' && (ndig=8))) {
|
||||||
wc = c;
|
|
||||||
c = ios_getc(f);
|
c = ios_getc(f);
|
||||||
while (hex_digit(c) && j<ndig && (c!=IOS_EOF)) {
|
while (hex_digit(c) && j<ndig && (c!=IOS_EOF)) {
|
||||||
eseq[j++] = c;
|
eseq[j++] = c;
|
||||||
|
@ -366,24 +365,15 @@ static value_t read_string(ios_t *f)
|
||||||
if (c!=IOS_EOF) ios_ungetc(c, f);
|
if (c!=IOS_EOF) ios_ungetc(c, f);
|
||||||
eseq[j] = '\0';
|
eseq[j] = '\0';
|
||||||
if (j) wc = strtol(eseq, NULL, 16);
|
if (j) wc = strtol(eseq, NULL, 16);
|
||||||
|
else {
|
||||||
|
free(buf);
|
||||||
|
lerror(ParseError, "read: invalid escape sequence");
|
||||||
|
}
|
||||||
i += u8_wc_toutf8(&buf[i], wc);
|
i += u8_wc_toutf8(&buf[i], wc);
|
||||||
}
|
}
|
||||||
else if (c == 'n')
|
else {
|
||||||
buf[i++] = '\n';
|
buf[i++] = read_escape_control_char((char)c);
|
||||||
else if (c == 't')
|
}
|
||||||
buf[i++] = '\t';
|
|
||||||
else if (c == 'r')
|
|
||||||
buf[i++] = '\r';
|
|
||||||
else if (c == 'b')
|
|
||||||
buf[i++] = '\b';
|
|
||||||
else if (c == 'f')
|
|
||||||
buf[i++] = '\f';
|
|
||||||
else if (c == 'v')
|
|
||||||
buf[i++] = '\v';
|
|
||||||
else if (c == 'a')
|
|
||||||
buf[i++] = '\a';
|
|
||||||
else
|
|
||||||
buf[i++] = c;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
buf[i++] = c;
|
buf[i++] = c;
|
||||||
|
|
|
@ -47,11 +47,10 @@
|
||||||
(defun nconc lsts
|
(defun nconc lsts
|
||||||
(cond ((null lsts) ())
|
(cond ((null lsts) ())
|
||||||
((null (cdr lsts)) (car lsts))
|
((null (cdr lsts)) (car lsts))
|
||||||
(T ((lambda (l d) (if (null l) d
|
((null (car lsts)) (apply nconc (cdr lsts)))
|
||||||
(prog1 l
|
(T (prog1 (car lsts)
|
||||||
(while (consp (cdr l)) (setq l (cdr l)))
|
(rplacd (last (car lsts))
|
||||||
(rplacd l d))))
|
(apply nconc (cdr lsts)))))))
|
||||||
(car lsts) (apply nconc (cdr lsts))))))
|
|
||||||
|
|
||||||
(defun append lsts
|
(defun append lsts
|
||||||
(cond ((null lsts) ())
|
(cond ((null lsts) ())
|
||||||
|
@ -211,10 +210,21 @@
|
||||||
|
|
||||||
(defun transpose (M) (apply mapcar (cons list M)))
|
(defun transpose (M) (apply mapcar (cons list M)))
|
||||||
|
|
||||||
(defun filter (pred lst)
|
(defun filter (pred lst) (filter- pred lst nil))
|
||||||
(cond ((null lst) ())
|
(defun filter- (pred lst accum)
|
||||||
((pred (car lst)) (cons (car lst) (filter pred (cdr lst))))
|
(cond ((null lst) accum)
|
||||||
(T (filter pred (cdr lst)))))
|
((pred (car lst))
|
||||||
|
(filter- pred (cdr lst) (cons (car lst) accum)))
|
||||||
|
(T
|
||||||
|
(filter- pred (cdr lst) accum))))
|
||||||
|
|
||||||
|
(defun separate (pred lst) (separate- pred lst nil nil))
|
||||||
|
(defun separate- (pred lst yes no)
|
||||||
|
(cond ((null lst) (cons yes no))
|
||||||
|
((pred (car lst))
|
||||||
|
(separate- pred (cdr lst) (cons (car lst) yes) no))
|
||||||
|
(T
|
||||||
|
(separate- pred (cdr lst) yes (cons (car lst) no)))))
|
||||||
|
|
||||||
(define (foldr f zero lst)
|
(define (foldr f zero lst)
|
||||||
(if (null lst) zero
|
(if (null lst) zero
|
||||||
|
|
|
@ -79,22 +79,30 @@ value_t fl_hashtablep(value_t *args, u_int32_t nargs)
|
||||||
return NIL;
|
return NIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// (put table key value)
|
||||||
value_t fl_hash_put(value_t *args, u_int32_t nargs)
|
value_t fl_hash_put(value_t *args, u_int32_t nargs)
|
||||||
{
|
{
|
||||||
|
argcount("put", nargs, 3);
|
||||||
return NIL;
|
return NIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// (get table key)
|
||||||
value_t fl_hash_get(value_t *args, u_int32_t nargs)
|
value_t fl_hash_get(value_t *args, u_int32_t nargs)
|
||||||
{
|
{
|
||||||
|
argcount("get", nargs, 2);
|
||||||
return NIL;
|
return NIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// (has table key)
|
||||||
value_t fl_hash_has(value_t *args, u_int32_t nargs)
|
value_t fl_hash_has(value_t *args, u_int32_t nargs)
|
||||||
{
|
{
|
||||||
|
argcount("has", nargs, 2);
|
||||||
return NIL;
|
return NIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// (del table key)
|
||||||
value_t fl_hash_delete(value_t *args, u_int32_t nargs)
|
value_t fl_hash_delete(value_t *args, u_int32_t nargs)
|
||||||
{
|
{
|
||||||
|
argcount("del", nargs, 2);
|
||||||
return NIL;
|
return NIL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,10 +43,11 @@
|
||||||
|
|
||||||
(defun sort (l)
|
(defun sort (l)
|
||||||
(if (or (null l) (null (cdr l))) l
|
(if (or (null l) (null (cdr l))) l
|
||||||
(let ((piv (car l)))
|
(let* ((piv (car l))
|
||||||
(nconc (sort (filter (lambda (x) (<= x piv)) (cdr l)))
|
(halves (separate (lambda (x) (< x piv)) (cdr l))))
|
||||||
|
(nconc (sort (car halves))
|
||||||
(list piv)
|
(list piv)
|
||||||
(sort (filter (lambda (x) (> x piv)) (cdr l)))))))
|
(sort (cdr halves))))))
|
||||||
|
|
||||||
(defmacro dotimes (var . body)
|
(defmacro dotimes (var . body)
|
||||||
(let ((v (car var))
|
(let ((v (car var))
|
||||||
|
|
|
@ -928,3 +928,35 @@ consolidated todo list as of 8/30:
|
||||||
- remaining cvalues functions
|
- remaining cvalues functions
|
||||||
- special efficient reader for #array
|
- special efficient reader for #array
|
||||||
- finish ios
|
- finish ios
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
cvalues redesign
|
||||||
|
|
||||||
|
goals:
|
||||||
|
. allow custom types with vtables
|
||||||
|
. use less space, share types more
|
||||||
|
. simplify access to important metadata like length
|
||||||
|
. unify vectors and arrays
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
fltype_t *type;
|
||||||
|
void *data;
|
||||||
|
size_t len; // length of *data in bytes
|
||||||
|
|
||||||
|
value_t parent; // optional
|
||||||
|
char data[1]; // variable size
|
||||||
|
} cvalue_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
fltype_t *type;
|
||||||
|
void *data;
|
||||||
|
} cprim_t;
|
||||||
|
|
||||||
|
typedef struct _fltype_t {
|
||||||
|
value_t type;
|
||||||
|
int numtype;
|
||||||
|
size_t sz;
|
||||||
|
cvtable_t *vtable;
|
||||||
|
struct _fltype_t *eltype; // for arrays
|
||||||
|
} fltype_t;
|
||||||
|
|
17
llt/ios.c
17
llt/ios.c
|
@ -715,6 +715,16 @@ int ios_getc(ios_t *s)
|
||||||
return (int)ch;
|
return (int)ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ios_peekc(ios_t *s)
|
||||||
|
{
|
||||||
|
if (s->bpos < s->size)
|
||||||
|
return s->buf[s->bpos];
|
||||||
|
if (s->_eof) return IOS_EOF;
|
||||||
|
size_t n = ios_readprep(s, 1);
|
||||||
|
if (n == 0) return IOS_EOF;
|
||||||
|
return s->buf[s->bpos];
|
||||||
|
}
|
||||||
|
|
||||||
int ios_ungetc(int c, ios_t *s)
|
int ios_ungetc(int c, ios_t *s)
|
||||||
{
|
{
|
||||||
if (s->state == bst_wr)
|
if (s->state == bst_wr)
|
||||||
|
@ -761,6 +771,13 @@ int ios_getutf8(ios_t *s, uint32_t *pwc)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ios_purge(ios_t *s)
|
||||||
|
{
|
||||||
|
if (s->state == bst_rd) {
|
||||||
|
s->bpos = s->size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int ios_printf(ios_t *s, char *format, ...)
|
int ios_printf(ios_t *s, char *format, ...)
|
||||||
{
|
{
|
||||||
char *str=NULL;
|
char *str=NULL;
|
||||||
|
|
|
@ -112,6 +112,9 @@ int ios_getstringn(ios_t *dest, ios_t *src, size_t nchars);
|
||||||
int ios_readline(ios_t *dest, ios_t *s, char delim);
|
int ios_readline(ios_t *dest, ios_t *s, char delim);
|
||||||
int ios_getline(ios_t *s, char **pbuf, size_t *psz);
|
int ios_getline(ios_t *s, char **pbuf, size_t *psz);
|
||||||
|
|
||||||
|
// discard data buffered for reading
|
||||||
|
void ios_purge(ios_t *s);
|
||||||
|
|
||||||
// seek by utf8 sequence increments
|
// seek by utf8 sequence increments
|
||||||
int ios_nextutf8(ios_t *s);
|
int ios_nextutf8(ios_t *s);
|
||||||
int ios_prevutf8(ios_t *s);
|
int ios_prevutf8(ios_t *s);
|
||||||
|
@ -121,6 +124,7 @@ int ios_prevutf8(ios_t *s);
|
||||||
int ios_putc(int c, ios_t *s);
|
int ios_putc(int c, ios_t *s);
|
||||||
//wint_t ios_putwc(ios_t *s, wchar_t wc);
|
//wint_t ios_putwc(ios_t *s, wchar_t wc);
|
||||||
int ios_getc(ios_t *s);
|
int ios_getc(ios_t *s);
|
||||||
|
int ios_peekc(ios_t *s);
|
||||||
//wint_t ios_getwc(ios_t *s);
|
//wint_t ios_getwc(ios_t *s);
|
||||||
int ios_ungetc(int c, ios_t *s);
|
int ios_ungetc(int c, ios_t *s);
|
||||||
//wint_t ios_ungetwc(ios_t *s, wint_t wc);
|
//wint_t ios_ungetwc(ios_t *s, wint_t wc);
|
||||||
|
|
|
@ -70,7 +70,7 @@ static void **ptrhash_lookup_bp(ptrhash_t *h, void *key)
|
||||||
orig = index;
|
orig = index;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (tab[index] == PH_NOTFOUND) {
|
if (tab[index+1] == PH_NOTFOUND) {
|
||||||
tab[index] = key;
|
tab[index] = key;
|
||||||
return &tab[index+1];
|
return &tab[index+1];
|
||||||
}
|
}
|
||||||
|
|
80
llt/utf8.c
80
llt/utf8.c
|
@ -313,56 +313,56 @@ int hex_digit(char c)
|
||||||
(c >= 'a' && c <= 'f'));
|
(c >= 'a' && c <= 'f'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* assumes that src points to the character after a backslash
|
char read_escape_control_char(char c)
|
||||||
returns number of input characters processed */
|
|
||||||
int u8_read_escape_sequence(const char *str, u_int32_t *dest)
|
|
||||||
{
|
{
|
||||||
u_int32_t ch;
|
if (c == 'n')
|
||||||
char digs[9]="\0\0\0\0\0\0\0\0\0";
|
return '\n';
|
||||||
int dno=0, i=1;
|
else if (c == 't')
|
||||||
|
return '\t';
|
||||||
|
else if (c == 'r')
|
||||||
|
return '\r';
|
||||||
|
else if (c == 'b')
|
||||||
|
return '\b';
|
||||||
|
else if (c == 'f')
|
||||||
|
return '\f';
|
||||||
|
else if (c == 'v')
|
||||||
|
return '\v';
|
||||||
|
else if (c == 'a')
|
||||||
|
return '\a';
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
ch = (u_int32_t)str[0]; /* take literal character */
|
/* assumes that src points to the character after a backslash
|
||||||
if (str[0] == 'n')
|
returns number of input characters processed, 0 if error */
|
||||||
ch = L'\n';
|
size_t u8_read_escape_sequence(const char *str, size_t ssz, u_int32_t *dest)
|
||||||
else if (str[0] == 't')
|
{
|
||||||
ch = L'\t';
|
assert(ssz > 0);
|
||||||
else if (str[0] == 'r')
|
u_int32_t ch;
|
||||||
ch = L'\r';
|
char digs[10];
|
||||||
else if (str[0] == 'b')
|
int dno=0, ndig;
|
||||||
ch = L'\b';
|
size_t i=1;
|
||||||
else if (str[0] == 'f')
|
char c0 = str[0];
|
||||||
ch = L'\f';
|
|
||||||
else if (str[0] == 'v')
|
if (octal_digit(c0)) {
|
||||||
ch = L'\v';
|
|
||||||
else if (str[0] == 'a')
|
|
||||||
ch = L'\a';
|
|
||||||
else if (octal_digit(str[0])) {
|
|
||||||
i = 0;
|
i = 0;
|
||||||
do {
|
do {
|
||||||
digs[dno++] = str[i++];
|
digs[dno++] = str[i++];
|
||||||
} while (octal_digit(str[i]) && dno < 3);
|
} while (i<ssz && octal_digit(str[i]) && dno<3);
|
||||||
|
digs[dno] = '\0';
|
||||||
ch = strtol(digs, NULL, 8);
|
ch = strtol(digs, NULL, 8);
|
||||||
}
|
}
|
||||||
else if (str[0] == 'x') {
|
else if ((c0=='x' && (ndig=2)) ||
|
||||||
while (hex_digit(str[i]) && dno < 2) {
|
(c0=='u' && (ndig=4)) ||
|
||||||
|
(c0=='U' && (ndig=8))) {
|
||||||
|
while (i<ssz && hex_digit(str[i]) && dno<ndig) {
|
||||||
digs[dno++] = str[i++];
|
digs[dno++] = str[i++];
|
||||||
}
|
}
|
||||||
if (dno > 0)
|
if (dno == 0) return 0;
|
||||||
|
digs[dno] = '\0';
|
||||||
ch = strtol(digs, NULL, 16);
|
ch = strtol(digs, NULL, 16);
|
||||||
}
|
}
|
||||||
else if (str[0] == 'u') {
|
else {
|
||||||
while (hex_digit(str[i]) && dno < 4) {
|
ch = (u_int32_t)read_escape_control_char(c0);
|
||||||
digs[dno++] = str[i++];
|
|
||||||
}
|
|
||||||
if (dno > 0)
|
|
||||||
ch = strtol(digs, NULL, 16);
|
|
||||||
}
|
|
||||||
else if (str[0] == 'U') {
|
|
||||||
while (hex_digit(str[i]) && dno < 8) {
|
|
||||||
digs[dno++] = str[i++];
|
|
||||||
}
|
|
||||||
if (dno > 0)
|
|
||||||
ch = strtol(digs, NULL, 16);
|
|
||||||
}
|
}
|
||||||
*dest = ch;
|
*dest = ch;
|
||||||
|
|
||||||
|
@ -381,7 +381,7 @@ size_t u8_unescape(char *buf, size_t sz, const char *src)
|
||||||
while (*src && c < sz) {
|
while (*src && c < sz) {
|
||||||
if (*src == '\\') {
|
if (*src == '\\') {
|
||||||
src++;
|
src++;
|
||||||
amt = u8_read_escape_sequence(src, &ch);
|
amt = u8_read_escape_sequence(src, 1000, &ch);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ch = (u_int32_t)*src;
|
ch = (u_int32_t)*src;
|
||||||
|
|
|
@ -55,10 +55,12 @@ size_t u8_charlen(u_int32_t ch);
|
||||||
/* computes the # of bytes needed to encode a WC string as UTF-8 */
|
/* computes the # of bytes needed to encode a WC string as UTF-8 */
|
||||||
size_t u8_codingsize(u_int32_t *wcstr, size_t n);
|
size_t u8_codingsize(u_int32_t *wcstr, size_t n);
|
||||||
|
|
||||||
|
char read_escape_control_char(char c);
|
||||||
|
|
||||||
/* assuming src points to the character after a backslash, read an
|
/* assuming src points to the character after a backslash, read an
|
||||||
escape sequence, storing the result in dest and returning the number of
|
escape sequence, storing the result in dest and returning the number of
|
||||||
input characters processed */
|
input characters processed */
|
||||||
int u8_read_escape_sequence(const char *src, u_int32_t *dest);
|
size_t u8_read_escape_sequence(const char *src, size_t ssz, u_int32_t *dest);
|
||||||
|
|
||||||
/* given a wide character, convert it to an ASCII escape sequence stored in
|
/* given a wide character, convert it to an ASCII escape sequence stored in
|
||||||
buf, where buf is "sz" bytes. returns the number of characters output.
|
buf, where buf is "sz" bytes. returns the number of characters output.
|
||||||
|
|
Loading…
Reference in New Issue