From keithp at keithp.com Fri Jan 4 00:39:34 2008 From: keithp at keithp.com (Keith Packard) Date: Fri, 4 Jan 2008 00:39:34 -0800 (PST) Subject: [Nickle] nickle: Branch 'master' - 4 commits Message-ID: <20080104083934.E4426130021@keithp.com> float.c | 8 +++++++ hash.c | 8 +++---- test/Makefile.am | 5 +++- test/hashtest.5c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ test/round.5c | 52 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 128 insertions(+), 5 deletions(-) New commits: commit 0dde80f6dfed86346709a603499da6cbb2230e91 Author: Keith Packard Date: Fri Jan 4 00:38:41 2008 -0800 Floating floor and ceil functions broken for values with no integer part. The ceiling of any positive fraction < 1 is 1, the floor of any negative fraction > -1 is -1. These cases were missing from the existing functions. diff --git a/float.c b/float.c index 9b7281b..12e49d6 100644 --- a/float.c +++ b/float.c @@ -531,7 +531,11 @@ FloatFloor (Value av, int expandOk) if (a->exp->sign == Positive) RETURN (FloatInteger (av)); if (NaturalLess (NewNatural (a->prec), a->exp->mag)) + { + if (a->mant->sign == Negative) + RETURN (NewInt (-1)); RETURN (Zero); + } d = NaturalToInt (a->exp->mag); mant = FpartRsl (a->mant, d); if (d && a->mant->sign == Negative) @@ -555,7 +559,11 @@ FloatCeil (Value av, int expandOk) if (a->exp->sign == Positive) RETURN (FloatInteger (av)); if (NaturalLess (NewNatural (a->prec), a->exp->mag)) + { + if (a->mant->sign == Positive && !NaturalZero (a->mant->mag)) + RETURN (One); RETURN (Zero); + } d = NaturalToInt (a->exp->mag); mant = FpartRsl (a->mant, d); if (d && a->mant->sign == Positive) commit b4a4b66be2ce66de162818cd94ae17d840b00c05 Author: Keith Packard Date: Fri Jan 4 00:36:58 2008 -0800 Add test case for floor and ceil functions. Floating point floor and ceiling functions are broken, this demonstrates the bug. diff --git a/test/Makefile.am b/test/Makefile.am index bf7aaa0..a40c63c 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -5,7 +5,9 @@ check_SCRIPTS=gcdtest.5c \ rattest.5c \ reftest.5c \ modtest.5c \ - hashtest.5c + hashtest.5c \ + round.5c + TESTS_ENVIRONMENT=NICKLESTART=$(top_srcdir)/builtin.5c NICKLEPATH=$(top_srcdir) ../nickle TESTS=$(check_SCRIPTS) diff --git a/test/round.5c b/test/round.5c new file mode 100644 index 0000000..132fdac --- /dev/null +++ b/test/round.5c @@ -0,0 +1,52 @@ +exception bad_round (int num, int den, int round); + +autoimport PRNG; + +void floor_check (int num, int den, int floor) +{ + if (num // den != floor) + raise bad_round (num, den, floor); +} + +void ceil_check (int num, int den, int ceil) +{ + int compare; + + compare = num // den; + if (num % den != 0) + compare++; + if (compare != ceil) + raise bad_round (num, den, ceil); +} + +void function round_random (int numbits, int denbits) +{ + int num = randbits (numbits); + int den = randbits (numbits); + + if (den == 0) + return; + + floor_check (num, den, floor (num / den)); + ceil_check (num, den, ceil (num / den)); + + floor_check (num, den, floor (imprecise (num / den))); + ceil_check (num, den, ceil (imprecise (num / den))); + + floor_check (-num, den, floor (-num / den)); + ceil_check (-num, den, ceil (-num / den)); + + floor_check (-num, den, floor (-imprecise (num / den))); + ceil_check (-num, den, ceil (-imprecise (num / den))); +} + +void function round_test (int amin, int amax, int bmin, int bmax) +{ + int a, b; + + for (a = amin; a <= amax; a += randint(30)) + for (b = bmin; b <= bmax; b += randint(30)) + round_random (a, b); +} + +round_test (2, 512, 2, 512) commit 0d645e8090c135b451949a844fdd53f8ebfc1575 Author: Keith Packard Date: Mon Dec 31 14:23:56 2007 -0800 Copy hash keys on insertion. Mutable hash keys must be copied when placed into the table as any changes to the original key value must not change the hash mapping. diff --git a/hash.c b/hash.c index 6e61d5d..8a8dd3d 100644 --- a/hash.c +++ b/hash.c @@ -359,7 +359,7 @@ HashGet (Value hv, Value key) } ht->count++; HashEltHash(he) = hash; - HashEltKey(he) = key; + HashEltKey(he) = Copy (key); HashEltValue(he) = Copy(ht->def); } value = HashEltValue (he); @@ -388,8 +388,8 @@ HashSet (Value hv, Value key, Value value) if (!HashEltValid (he)) ht->count++; HashEltHash (he) = hash; - HashEltKey (he) = key; - HashEltValue (he) = value; + HashEltKey (he) = Copy (key); + HashEltValue (he) = Copy (value); } void @@ -418,7 +418,7 @@ HashRef (Value hv, Value key) { ht->count++; HashEltHash (he) = hash; - HashEltKey (he) = key; + HashEltKey (he) = Copy (key); if (ht->def) HashEltValue (he) = Copy(ht->def); } commit 2727d3ade55570c172a6fd6d22a92287503c917a Author: Keith Packard Date: Mon Dec 31 14:23:01 2007 -0800 Add tests for hash tables, including mutable key copying. Test hash tables. Has test that checks correct behaviour with mutable keys where the key is copied when placed into the table. diff --git a/test/Makefile.am b/test/Makefile.am index 38fbb11..bf7aaa0 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -4,7 +4,8 @@ check_SCRIPTS=gcdtest.5c \ orderofoptest.5c \ rattest.5c \ reftest.5c \ - modtest.5c + modtest.5c \ + hashtest.5c TESTS_ENVIRONMENT=NICKLESTART=$(top_srcdir)/builtin.5c NICKLEPATH=$(top_srcdir) ../nickle TESTS=$(check_SCRIPTS) diff --git a/test/hashtest.5c b/test/hashtest.5c new file mode 100644 index 0000000..f93ab05 --- /dev/null +++ b/test/hashtest.5c @@ -0,0 +1,60 @@ +exception bad_result (string reason, poly[poly] h, poly key, poly value); + +poly[*][2] values = { + { "hello", "world" }, + { 1, "one" }, + { (int[*]) { 1, 2, 3, 4 }, (struct { int x, y; }) { x = 1, y = 2 } }, +}; + +void hash_tests () +{ + poly[poly] h; + + /* + * Test basic insert/find + */ + for (int i = 0; i < dim(values); i++) + h[values[i][0]] = values[i][1]; + for (int i = 0; i < dim(values); i++) + if (h[values[i][0]] != values[i][1]) + raise bad_result ("wrong value returned", h, values[i][0], values[i][1]); + /* + * check list of keys + */ + poly[*] keys = hash_keys (h); + if (dim (keys) != dim (values)) + raise bad_result ("wrong number of keys", h, dim(keys), dim (values)); + for (int i = 0; i < dim (values); i++) { + int j; + for (j = 0; j < dim (keys); j++) + if (keys[j] == values[i][0]) + break; + if (j == dim (keys)) + raise bad_result ("missing key", h, values[i][0], ???); + } + /* + * test delete + */ + for (int i = 0; i < dim (values); i++) + hash_del (h, values[i][0]); + if (dim (hash_keys(h)) != 0) + raise bad_result ("couldn't delete all keys", h, ???, ???); + + /* + * test mutable keys + */ + + int[*] a = { 1, 2, 3 }; + int[*] b = a; + h[a] = "hello"; + if (h[b] != "hello") + raise bad_result ("couldn't find mutable key", h, a, "hello"); + a[0] = 12; + if (hash_test (h, a)) + raise bad_result ("hash contains mutated key", h, a, h[a]); + if (h[b] != "hello") + raise bad_result ("couldn't find unmutated key", h, b, h[b]); + +} + +hash_tests (); From keithp at keithp.com Fri Jan 4 00:48:04 2008 From: keithp at keithp.com (Keith Packard) Date: Fri, 4 Jan 2008 00:48:04 -0800 (PST) Subject: [Nickle] nickle: Changes to 'refs/tags/2.64' Message-ID: <20080104084804.12464130021@keithp.com> Tag '2.64' created by Keith Packard at 2008-01-04 08:43 -0800 Version 2.64 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) iD8DBQBHffHAQp8BWwlsTdMRAovmAKCuS0AS1UbyZqakxs5WmOLZC/29PwCeKtou esHTiAYWtNMVO5wV3Mxucxw= =LZBT -----END PGP SIGNATURE----- Changes since 2.63-4: --- 0 files changed --- From keithp at keithp.com Sat Jan 5 12:16:59 2008 From: keithp at keithp.com (Keith Packard) Date: Sat, 05 Jan 2008 12:16:59 -0800 Subject: [Nickle] Struct/union subclassing syntax Message-ID: <1199564219.13522.11.camel@koto.keithp.com> With fairly complete subtype/supertype support, nickle provides limited-polymorphism for user types. However, it doesn't make constructing subtypes easy. In fact, subtypes can only be constructed by explicitly replicating the structure members from the supertype: typedef struct { int i; } super_t; typedef struct { int i; real f; } sub_t; While this works just fine, it's rather clumsy, and is prone to errors when the super type changes. It seems like it would be nice to tie the two types together syntactically, perhaps like: typedef struct super_t { real f; } sub_t; or typedef struct extend super_t { real f; } sub_t; the 'extend' keyword is already used for namespaces, with slightly different semantics, there it adds names to an existing namespace, while this time, it will inherit the members from the existing structure. Of course, you could inherit from more than one struct quite easily: typedef struct extend super_t, another_super_t { real f; } sub_t; Does this seem reasonable? -- keith.packard at intel.com -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: This is a digitally signed message part Url : /pipermail/nickle/attachments/20080105/be4fda6e/attachment.pgp From keithp at keithp.com Sat Jan 5 23:01:10 2008 From: keithp at keithp.com (Keith Packard) Date: Sat, 05 Jan 2008 23:01:10 -0800 Subject: [Nickle] Better struct subtype syntax Message-ID: <1199602870.13522.18.camel@koto.keithp.com> Bart and I chatted on the phone this evening about struct subtyping and decided that all syntaxes involving the 'extend' keyword were too confusing, and that what we really wanted to talk about was joining two struct types together to create a composite type. Well, we use the '+' keyword for lots of other joining operations, so why not for types? typedef struct { int i; } super_t; typedef super_t + struct { real f; } sub_t; This extends to joining more than two types together quite naturally, with familiar behavior. -- keith.packard at intel.com -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: This is a digitally signed message part Url : /pipermail/nickle/attachments/20080105/1196f979/attachment.pgp From keithp at keithp.com Sun Jan 6 16:27:13 2008 From: keithp at keithp.com (Keith Packard) Date: Sun, 6 Jan 2008 16:27:13 -0800 (PST) Subject: [Nickle] nickle: Branch 'master' - 6 commits Message-ID: <20080107002713.9194CE8029@keithp.com> compile.c | 18 +++++++++++--- configure.in | 2 - debian/changelog | 7 +++++ file.c | 8 +++++- gram.y | 11 ++++++++ lex.l | 15 +++++++++++ pretty.c | 26 +++++++++++++++----- type.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ value.h | 2 + 9 files changed, 147 insertions(+), 11 deletions(-) New commits: commit 8e8c6197f0b7448fd27fa1bae5daf2bb839ce1df Author: Keith Packard Date: Sun Jan 6 16:26:07 2008 -0800 Exit with status 1 if last action was parse failure. Nickle normally exits with the status of the last thread; if the last action of the user was a parse failure (causing no thread to execute), exit with failure (status 1). diff --git a/gram.y b/gram.y index 1437f08..4f358f7 100644 --- a/gram.y +++ b/gram.y @@ -218,6 +218,7 @@ reset : CurrentNamespace = TopNamespace; funcDepth = 0; notCommand = 0; + lastThreadError = True; } ; commit edc47ba279d74bbc18de3531dd8aabdbbdd60f70 Author: Keith Packard Date: Sun Jan 6 16:18:49 2008 -0800 Function declarations would segfault the pretty printer. void g () { void f (int i); } print g would segfault as 'f' was a function declaration without a code body. Fixed by adding pretty printing code to handle this case. diff --git a/pretty.c b/pretty.c index a067028..9e33ced 100644 --- a/pretty.c +++ b/pretty.c @@ -605,6 +605,9 @@ _PrettyCatch (Value f, Expr *e, int level, Bool nest, ProfileData *pd) FilePuts (f, "\n"); } +static void +PrintArgs (Value f, ArgType *args); + void PrettyStatement (Value f, Expr *e, int level, int blevel, Bool nest, ProfileData *pd) { @@ -739,12 +742,23 @@ PrettyStatement (Value f, Expr *e, int level, int blevel, Bool nest, ProfileData { DeclListPtr decl = e->decl.decl; ExprPtr init = decl->init; - CodePtr code = init->code.code; - - PrettyCode (f, code, decl->name, - e->decl.class, - e->decl.publish, - level, nest); + if (init) + { + CodePtr code = init->code.code; + + PrettyCode (f, code, decl->name, + e->decl.class, + e->decl.publish, + level, nest); + } + else + { + Type *t = e->decl.type; + FilePrintf (f, "%p%k%T %A ", e->decl.publish, + e->decl.class, t->func.ret, decl->name); + PrintArgs (f, t->func.args); + FilePuts (f, ";"); + } } FilePuts (f, "\n"); break; commit 691a76447cea42cb3c5bdc3ccb1aae228081fe3b Author: Keith Packard Date: Sun Jan 6 15:51:07 2008 -0800 Check for duplicate function param and struct/union members While duplicate function parameters and struct/union members may have well defined semantics, they're a bad idea, so we make them an error. diff --git a/compile.c b/compile.c index c21bc8d..d7ce654 100644 --- a/compile.c +++ b/compile.c @@ -4117,10 +4117,10 @@ static ObjPtr CompileType (ObjPtr obj, ExprPtr decls, TypePtr type, ExprPtr stat, CodePtr code) { ENTER(); - ArgType *at; + ArgType *at, *aat; StructType *st; TypeElt *et; - int i; + int i, j; switch (type->base.tag) { case type_prim: @@ -4132,8 +4132,14 @@ CompileType (ObjPtr obj, ExprPtr decls, TypePtr type, ExprPtr stat, CodePtr code break; case type_func: obj = CompileType (obj, decls, type->func.ret, stat, code); - for (at = type->func.args; at; at = at->next) + for (at = type->func.args; at; at = at->next) { + if (at->name) + for (aat = at->next; aat; aat = aat->next) + if (aat->name == at->name) + CompileError (obj, stat, "Duplicate function parameter '%A'", + at->name); obj = CompileType (obj, decls, at->type, stat, code); + } break; case type_array: obj = CompileArrayType (obj, decls, type, stat, code); @@ -4147,7 +4153,13 @@ CompileType (ObjPtr obj, ExprPtr decls, TypePtr type, ExprPtr stat, CodePtr code case type_union: st = type->structs.structs; for (i = 0; i < st->nelements; i++) + { + for (j = 0; j < i; j++) + if (StructTypeAtoms(st)[j] == StructTypeAtoms(st)[i]) + CompileError (obj, stat, "Duplicate structure member %A", + StructTypeAtoms(st)[i]); obj = CompileType (obj, decls, BoxTypesElements(st->types)[i], stat, code); + } break; case type_types: for (et = type->types.elt; et; et = et->next) commit cf60fcd340021ed1e29fdc208fe4634924c124e1 Author: Keith Packard Date: Sun Jan 6 15:50:39 2008 -0800 Reduce warnings when compiling flex output diff --git a/lex.l b/lex.l index d0b0aac..36c0efa 100644 --- a/lex.l +++ b/lex.l @@ -17,6 +17,21 @@ #include #endif +/* + * Silence gcc by providing prototypes for these functions + */ +int yyget_lineno (void); +FILE *yyget_in (void); +FILE *yyget_out (void); +int yyget_leng (void); +char *yyget_text (void); +void yyset_lineno (int); +void yyset_in (FILE *); +void yyset_out (FILE *); +int yyget_debug (void); +void yyset_debug (int); +int yylex_destroy (void); + typedef struct _lexInput { DataType data; struct _lexInput *next; commit 4ae8bb3a888432b3101e16fbbd63e04c9229fb9b Author: Keith Packard Date: Sun Jan 6 15:20:10 2008 -0800 Add new '+' type operator; creates subtypes for struct/union types. Merges two struct, union or enum types together to form a unified type containing each of the elements of the two original structures. diff --git a/file.c b/file.c index 933b544..0628cfa 100644 --- a/file.c +++ b/file.c @@ -1659,7 +1659,13 @@ FilePutType (Value f, Type *t, Bool minimal) break; case type_struct: case type_union: - if (t->structs.enumeration) + if (t->structs.left && t->structs.right) + { + FilePutType (f, t->structs.left, False); + FilePuts (f, " + "); + FilePutType (f, t->structs.right, False); + } + else if (t->structs.enumeration) { FilePuts (f, "enum { "); st = t->structs.structs; diff --git a/gram.y b/gram.y index 0f2970a..1437f08 100644 --- a/gram.y +++ b/gram.y @@ -941,6 +941,16 @@ type : subtype subscripts %prec CALL { $$ = NewTypeRef (NewTypeRef ($2, False), False); } | LAND type %prec POINTER { $$ = NewTypeRef ($2, False); } + | type PLUS type + { + if (ParseCanonType ($1, False) != CanonTypeDefined) + YYERROR; + if (ParseCanonType ($3, False) != CanonTypeDefined) + YYERROR; + $$ = NewTypePlus ($1, $3); + if (!$$) + YYERROR; + } ; subtype : basetype | STRUCT OC struct_members CC diff --git a/type.c b/type.c index fa2b59c..33c77fc 100644 --- a/type.c +++ b/type.c @@ -89,6 +89,8 @@ TypeStructMark (void *object) TypeStruct *ts = object; MemReference (ts->structs); + MemReference (ts->left); + MemReference (ts->right); } static void @@ -215,6 +217,8 @@ NewTypeStruct (StructType *structs) t->base.tag = type_struct; t->structs.structs = structs; t->structs.enumeration = False; + t->structs.left = NULL; + t->structs.right = NULL; RETURN (t); } @@ -228,9 +232,74 @@ NewTypeUnion (StructType *structs, Bool enumeration) t->base.tag = type_union; t->structs.structs = structs; t->structs.enumeration = enumeration; + t->structs.left = NULL; + t->structs.right = NULL; RETURN (t); } +static Type * +TypePlusPart (Type *type) +{ + type = TypeCanon (type); + switch (type->base.tag) { + case type_struct: + case type_union: + break; + default: + ParseError ("Type '%T' not struct or union", type); + return NULL; + } + return type; +} + +static int +AddPlusType (StructType *new, StructType *old, int pos) +{ + int i; + + for (i = 0; i < old->nelements; i++) { + AddBoxType (&new->types, BoxTypesElements (old->types)[i]); + StructTypeAtoms (new)[pos] = StructTypeAtoms (old)[i]; + pos++; + } + return pos; +} + +Type * +NewTypePlus (Type *left, Type *right) +{ + ENTER (); + Type *t, *l, *r;; + StructType *st; + int i; + + l = TypePlusPart (left); + r = TypePlusPart (right); + if (!l || !r) + RETURN (NULL); + if (l->base.tag != r->base.tag) { + ParseError ("'%T' and '%T' are not the same type", left, right); + RETURN (NULL); + } + + st = NewStructType (l->structs.structs->nelements + r->structs.structs->nelements); + i = AddPlusType (st, l->structs.structs, 0); + if (i < 0) + RETURN (NULL); + i = AddPlusType (st, r->structs.structs, i); + if (i < 0) + RETURN (NULL); + + t = ALLOCATE (&TypeStructType, sizeof (TypeStruct)); + t->base.tag = l->base.tag; + t->structs.structs = st; + t->structs.enumeration = l->structs.enumeration && r->structs.enumeration; + t->structs.left = left; + t->structs.right = right; + RETURN (t); +} + + Type * NewTypeTypes (TypeElt *elt) { diff --git a/value.h b/value.h index af33302..fbebfe8 100644 --- a/value.h +++ b/value.h @@ -440,6 +440,7 @@ typedef struct _typeStruct { TypeBase base; StructTypePtr structs; Bool enumeration; + TypePtr left, right; } TypeStruct; typedef struct _typeElt { @@ -483,6 +484,7 @@ extern Type *typePrim[rep_void + 1]; Type *NewTypeName (ExprPtr expr, SymbolPtr name); Type *NewTypeRef (Type *ref, Bool pointer); +Type *NewTypePlus (Type *left, Type *right); Type *NewTypePointer (Type *ref); Type *NewTypeFunc (Type *ret, ArgType *args); Type *NewTypeArray (Type *type, ExprPtr dimensions, Bool resizable); commit 7761936b1b7318d29d4cc948308f9742f5c3f433 Author: Keith Packard Date: Fri Jan 4 00:41:57 2008 -0800 Bump to version 2.64 diff --git a/configure.in b/configure.in index 7eaa968..b920c70 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ dnl for licensing information. AC_PREREQ(2.59) AC_INIT([nickle], - 2.63, + 2.64, [http://nickle.org], nickle) diff --git a/debian/changelog b/debian/changelog index 68c4aeb..eb35ca5 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +nickle (2.64-1) unstable; urgency=low + * Fix float floor/ceil with small values + * Copy hash key/value on insert + * Bump to version 2.64 + + -- Keith Packard Fri, 04 Jan 2008 00:41:15 -0800 + nickle (2.63-1) unstable; urgency=low * Avoid using extra libraries unless necessary * Fix -Wl,-E testing by using AC_LINK_IFELSE From keithp at keithp.com Sun Jan 6 16:45:24 2008 From: keithp at keithp.com (Keith Packard) Date: Sun, 6 Jan 2008 16:45:24 -0800 (PST) Subject: [Nickle] nickle: Branch 'master' Message-ID: <20080107004524.6E3508110@keithp.com> configure.in | 2 +- debian/changelog | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) New commits: commit 4a8813f98e03663108757ade2da6d6f372598060 Author: Keith Packard Date: Sun Jan 6 16:41:03 2008 -0800 Bump version to 2.65 diff --git a/configure.in b/configure.in index b920c70..8bfc146 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ dnl for licensing information. AC_PREREQ(2.59) AC_INIT([nickle], - 2.64, + 2.65, [http://nickle.org], nickle) diff --git a/debian/changelog b/debian/changelog index eb35ca5..9c6763a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +nickle (2.65-1) unstable; urgency=low + * Add new '+' type operator for subtyping struct/union + * Eliminate segfault when pretty printing func declarations + * Check for duplicate func param/struct member names + + -- Keith Packard Sun, 06 Jan 2008 16:38:51 -0800 + nickle (2.64-1) unstable; urgency=low * Fix float floor/ceil with small values * Copy hash key/value on insert From keithp at keithp.com Sun Jan 6 16:45:28 2008 From: keithp at keithp.com (Keith Packard) Date: Sun, 6 Jan 2008 16:45:28 -0800 (PST) Subject: [Nickle] nickle: Changes to 'refs/tags/2.65' Message-ID: <20080107004528.1B36A8110@keithp.com> Tag '2.65' created by Keith Packard at 2008-01-07 00:41 -0800 Version 2.65 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) iD8DBQBHgXUoQp8BWwlsTdMRAvOOAJ48f1ZeSP8zR1k9HkRYgIGq6/LagwCbBoeG fAcGQPjiRCJTCvULTLB12Pg= =k53M -----END PGP SIGNATURE----- Changes since 2.64-5: --- 0 files changed --- From keithp at keithp.com Mon Jan 28 22:09:01 2008 From: keithp at keithp.com (Keith Packard) Date: Mon, 28 Jan 2008 22:09:01 -0800 (PST) Subject: [Nickle] nickle: Branch 'master' - 5 commits Message-ID: <20080129060901.70C2E8117@keithp.com> TODO | 4 ++-- command.5c | 51 +++++++++++++++++++++++++++++++-------------------- configure.in | 2 +- debian/changelog | 6 ++++++ float.c | 3 +++ scope.c | 2 +- 6 files changed, 44 insertions(+), 24 deletions(-) New commits: commit b739d5a6f5816100b56b5278f4a99ab4ee937222 Author: Keith Packard Date: Tue Jan 29 17:08:53 2008 +1100 Silent underflow on conversion to machine double diff --git a/configure.in b/configure.in index 8bfc146..87853cf 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ dnl for licensing information. AC_PREREQ(2.59) AC_INIT([nickle], - 2.65, + 2.66, [http://nickle.org], nickle) diff --git a/debian/changelog b/debian/changelog index 9c6763a..90392c0 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +nickle (2.66-1) unstable; urgency=low + * Support autoload/autoimport of nested namespaces. + * Allow 'print' to find unpublished names + + -- Keith Packard Sun, 13 Jan 2008 17:39:49 -0800 + nickle (2.65-1) unstable; urgency=low * Add new '+' type operator for subtyping struct/union * Eliminate segfault when pretty printing func declarations diff --git a/float.c b/float.c index 12e49d6..2b65ab8 100644 --- a/float.c +++ b/float.c @@ -1172,6 +1172,9 @@ DoublePart (Value av, char *error) e = MAX_NICKLE_INT; if (e > 1023) { + if (av->floats.exp->sign == Negative) + return 0.0; + RaiseStandardException (exception_invalid_argument, error, 2, NewInt (0), av); return 0.0; commit 9f26613cfa6ce6dd58edf671390d3379fbaf1a34 Author: Keith Packard Date: Fri Jan 25 19:44:19 2008 -0800 Fix autoimport for nested namespaces diff --git a/command.5c b/command.5c index 3e69c5a..574c458 100644 --- a/command.5c +++ b/command.5c @@ -150,25 +150,32 @@ extend namespace Command { return r + ".5c"; } - void import_if_needed(string name) + void import_if_needed(string[*] name) { if (do_import) { - string imp = File::sprintf("import %s;\n", name); + file f = File::string_write (); + File::fprintf (f, "import "); + for (int i = 0; i < dim (name); i++) { + if (i != 0) + File::fprintf (f, "::"); + File::fprintf (f, "%s", name[i]); + } + File::fprintf (f, ";\n"); + string imp = File::string_string (f); lex_string(imp); } } for (int i = 0; i < dim(args); i++) { string[*] name = args[i]; - if (valid_name (name)) { - for (int i = 0; i < dim(name); i++) - import_if_needed(name[i]); + import_if_needed(name); + + if (valid_name (name)) continue; - } + for (int j = dim(name) - 1; j >= 0; j--) { - import_if_needed(name[j]); string[*] subname = (string[j+1]) { [k] = name[k] }; if (!valid_name (subname)) { commit d9959cfa510ebc56ed6d66cd529c85529b780886 Author: Keith Packard Date: Sun Jan 13 17:34:02 2008 -0800 Notice that some TODO items were done a long time ago diff --git a/TODO b/TODO index c4fe10f..8f265c1 100644 --- a/TODO +++ b/TODO @@ -3,12 +3,10 @@ TO DO + Allow poll() as a substitute for select(). + Allow nick to be built without all the async IO and gettimeofday() and the like. -+ Build a small test suite. + Build regression tests for everything on the DONE list. + Finish the manual. + Fix output formatting length problems. + Tagless GC. -+ Null-safe strings. TO THINK ABOUT @@ -37,6 +35,8 @@ NOT TO DO DONE ++ Build a small test suite. ++ Null-safe strings. + Move std math functions out of math, or import math. + Implement library autoload mechanism. + Write fixed position (scale=n) math library in nickle ala bc/dc. commit a8439dbfd270b47bc62b0e6d9a8bf37471ba470d Author: Keith Packard Date: Tue Jan 8 23:27:53 2008 -0800 Support autoload/autoimport of nested namespaces. While nested namespaces could be loaded, the filenames would reference only the last element making it hard to actually use them. This change glues the namespace elements together with '-' when building filenames. diff --git a/command.5c b/command.5c index c4f69c1..3e69c5a 100644 --- a/command.5c +++ b/command.5c @@ -126,22 +126,26 @@ extend namespace Command { if (do_import) autotype = "autoimport"; - string make_filename(string m) + string make_filename(string[*] m) { string r = ""; - bool last_lower = false; - for (int i = 0; i < String::length(m); i++) - { - int c = m[i]; - bool cur_lower = Ctype::islower(c); - if (Ctype::isupper(c)) + for (int j = 0; j < dim (m); j++) { + if (j > 0) + r = r + "-"; + bool last_lower = false; + for (int i = 0; i < String::length(m[j]); i++) { - c = Ctype::tolower(c); - if (last_lower) - r = r + "-"; + int c = m[j][i]; + bool cur_lower = Ctype::islower(c); + if (Ctype::isupper(c)) + { + c = Ctype::tolower(c); + if (last_lower) + r = r + "-"; + } + r = r + String::new(c); + last_lower = cur_lower; } - r = r + String::new(c); - last_lower = cur_lower; } return r + ".5c"; } @@ -168,7 +172,7 @@ extend namespace Command { string[*] subname = (string[j+1]) { [k] = name[k] }; if (!valid_name (subname)) { - string f = make_filename(name[j]); + string f = make_filename(subname); if (!lex_library (f)) { File::fprintf (stderr, commit e324f392b2bf13f99a2e39dfde7b7f4913be7dfb Author: Keith Packard Date: Tue Jan 8 13:14:16 2008 -0800 Search for unpublished names with NamespaceLocate diff --git a/scope.c b/scope.c index 7a44fc6..97bc192 100644 --- a/scope.c +++ b/scope.c @@ -257,7 +257,7 @@ NamespaceLocate (Value names, } namelist = NamespaceFindNamelist (namespace, AtomId (StringChars (&string->string)), - search, False); + search, True); search = False; if (!namelist) { From cworth at cworth.org Thu Jan 31 14:25:19 2008 From: cworth at cworth.org (Carl Worth) Date: Fri, 1 Feb 2008 09:25:19 +1100 Subject: [PATCH] Socket::create: Add support for Unix domain sockets Message-ID: --- builtin-sockets.c | 127 +++++++++++++++++++++++++++++++++++----------------- 1 files changed, 85 insertions(+), 42 deletions(-) diff --git a/builtin-sockets.c b/builtin-sockets.c index 32cec13..47b6ab1 100644 --- a/builtin-sockets.c +++ b/builtin-sockets.c @@ -16,6 +16,8 @@ #include #include #include +#include +#include #include #include #include @@ -32,7 +34,7 @@ NamespacePtr SocketNamespace; Type *typeSockaddr; -Value do_Socket_create (Value type); +Value do_Socket_create (Value family, Value type); Value do_Socket_connect (Value s, Value host, Value port); Value do_Socket_bind (Value s, Value host, Value port); Value do_Socket_listen (Value s, Value backlog); @@ -55,12 +57,6 @@ import_Socket_namespace() }; static const struct fbuiltin_1 funcs_1[] = { - { do_Socket_create, "create", "f", "i", "\n" - " file create (int type)\n" - "\n" - " Create a socket where 'type' is one of:\n" - " SOCK_STREAM: a stream socket.\n" - " SOCK_DGRAM: a datagram socket.\n" }, { do_Socket_accept, "accept", "f", "f", "\n" " file accept (file listen)\n" "\n" @@ -73,6 +69,16 @@ import_Socket_namespace() }; static const struct fbuiltin_2 funcs_2[] = { + { do_Socket_create, "create", "f", "ii", "\n" + " file create (int type)\n" + "\n" + " Create a socket where 'family' is one of:\n" + " AF_UNIX: Local communication.\n" + " AF_INET: IPv4 Internet protocols.\n" + " AF_INET6: IPv6 Internet protocols.\n" + " and where 'type' is one of:\n" + " SOCK_STREAM: a stream socket.\n" + " SOCK_DGRAM: a datagram socket.\n" }, { do_Socket_listen, "listen", "v", "fi", "\n" " void listen (file socket, int length)\n" "\n" @@ -100,6 +106,11 @@ import_Socket_namespace() }; static const struct ibuiltin ivars[] = { + { AF_UNIX, "AF_UNIX", &SocketNamespace }, + { AF_INET, "AF_INET", &SocketNamespace }, +#ifdef AF_INET6 + { AF_INET6, "AF_INET6", &SocketNamespace }, +#endif { SOCK_STREAM, "SOCK_STREAM", &SocketNamespace }, { SOCK_DGRAM, "SOCK_DGRAM", &SocketNamespace }, { SHUT_RD, "SHUT_RD", &SocketNamespace }, @@ -143,21 +154,32 @@ import_Socket_namespace() /* File::file do_Socket_create ({SOCK_STREAM,SOCK_DGRAM} type); */ Value -do_Socket_create (Value type) +do_Socket_create (Value family, Value type) { ENTER (); - int itype, s; + int ifamily, itype, s; + ifamily = IntPart (family, "Illegal address family"); itype = IntPart (type, "Illegal socket type"); if (aborting) RETURN (Void); - s = socket (PF_INET, itype, 0); + s = socket (ifamily, itype, 0); if (s == -1) RETURN (Void); RETURN (FileCreate (s, FileReadable|FileWritable)); } -static Bool address_lookup (Value hostname, Value portname, - struct sockaddr_in *addr) +typedef union { + struct sockaddr_in in; + struct sockaddr_un un; + struct sockaddr addr; + struct { + struct sockaddr_un un; + char path[PATH_MAX]; + } align; +} sockaddr_all_t; + +static Bool address_lookup (int s, Value hostname, Value portname, + sockaddr_all_t *addr, socklen_t *len) { struct hostent *host; struct servent *port; @@ -176,32 +198,51 @@ static Bool address_lookup (Value hostname, Value portname, if (*hostchars == '\0' || *portchars == '\0') return False; /* FIXME: more here? */ - addr->sin_family = AF_INET; - - /* host lookup */ - host = gethostbyname (hostchars); - if (host == 0) - { - herror ("address_lookup"); - return False; /* FIXME: more here? */ - } - memcpy (&addr->sin_addr.s_addr, host->h_addr_list[0], sizeof addr->sin_addr.s_addr); + /* Read the address family back from the kernel. */ + *len = sizeof (*addr); + if (getsockname (s, &addr->addr, len) < 0) + return False; - /* port lookup */ - portnum = strtol (portchars, &endptr, /* base */ 10); - if (*endptr != '\0') /* non-numeric port specification */ - { - /* FIXME: this should not always be "tcp"! */ - port = getservbyname (portchars, "tcp"); - if (port == 0) - return False; /* FIXME: more here? */ - addr->sin_port = port->s_port; - } - else - { - if (portnum <= 0 || portnum >= (1 << 16)) + switch (addr->addr.sa_family) { + case AF_UNIX: + if (strlen (portchars) > PATH_MAX) + return False; + *len = SUN_LEN (&addr->un); + strcpy (addr->un.sun_path, portchars); + break; + case AF_INET: + /* host lookup */ + host = gethostbyname (hostchars); + if (host == 0) + { + herror ("address_lookup"); return False; /* FIXME: more here? */ - addr->sin_port = htons (portnum); + } + memcpy (&addr->in.sin_addr.s_addr, host->h_addr_list[0], sizeof addr->in.sin_addr.s_addr); + + /* port lookup */ + portnum = strtol (portchars, &endptr, /* base */ 10); + + if (*endptr != '\0') /* non-numeric port specification */ + { + /* FIXME: this should not always be "tcp"! */ + port = getservbyname (portchars, "tcp"); + if (port == 0) + return False; /* FIXME: more here? */ + addr->in.sin_port = port->s_port; + } + else + { + if (portnum <= 0 || portnum >= (1 << 16)) + return False; /* FIXME: more here? */ + addr->in.sin_port = htons (portnum); + } + break; +#if AF_INET6 + case AF_INET6: +#endif + default: + return False; } return True; @@ -212,9 +253,10 @@ Value do_Socket_connect (Value s, Value host, Value port) { ENTER (); - struct sockaddr_in addr; + sockaddr_all_t addr; + socklen_t len; - if (!address_lookup (host, port, &addr)) + if (!address_lookup (s->file.fd, host, port, &addr, &len)) RETURN (Void); if (!running->thread.partial) @@ -230,7 +272,7 @@ do_Socket_connect (Value s, Value host, Value port) (char *) &one, sizeof (int)); } #endif - n = connect (s->file.fd, (struct sockaddr *) &addr, sizeof addr); + n = connect (s->file.fd, &addr.addr, len); flags &= ~O_NONBLOCK; fcntl (s->file.fd, F_SETFL, flags); err = errno; @@ -266,9 +308,10 @@ Value do_Socket_bind (Value s, Value host, Value port) { ENTER (); - struct sockaddr_in addr; + sockaddr_all_t addr; + socklen_t len; - if (!address_lookup (host, port, &addr)) + if (!address_lookup (s->file.fd, host, port, &addr, &len)) RETURN (Void); #ifdef SO_REUSEADDR @@ -277,7 +320,7 @@ do_Socket_bind (Value s, Value host, Value port) setsockopt (s->file.fd, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof (int)); } #endif - if (bind (s->file.fd, (struct sockaddr *) &addr, sizeof addr) == -1) + if (bind (s->file.fd, &addr.addr, len) == -1) { RaiseStandardException (exception_io_error, FileGetErrorMessage (errno), -- 1.5.3.2