[Nickle] nickle: Branch 'master' - 3 commits

Keith Packard keithp at keithp.com
Tue Oct 2 01:54:03 PDT 2007


 builtin-toplevel.c |    1 
 ctype.5c           |   20 ++++++++-----
 file.c             |   79 +++++++++++++++++++++++++++++------------------------
 value.h            |    1 
 4 files changed, 57 insertions(+), 44 deletions(-)

New commits:
commit 2278b93b7e760f1153847a0b3c36d07684f72e0c
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Tue Oct 2 01:53:02 2007 -0700

    Manage file buffer chains with explicit malloc/free.
    
    Buffer chains must have life equal to the file they belong to; an
    unreferenced file may still have buffered data, so the buffers cannot be
    reclaimed. The nickle GC does not have a separate pass that checks to see
    which objects can be freed, rather it assumes that such objects are
    self-contained.
    
    Hence, anything hanging off of an object which can refuse to
    be reclaimed must not have been allocated from the nickle GC system. Yes,
    this is a significant limitation to this allocator.
    
    Someday I'll figure out a good general fix for this problem, right now we'll
    stop segfaults when applications drop file references without closing them.

diff --git a/file.c b/file.c
index 77356b1..933b544 100644
--- a/file.c
+++ b/file.c
@@ -472,6 +472,30 @@ ProcessInterrupt ()
     }
 }
 
+static FileChainPtr
+FileChainAlloc (FileChainPtr next, int size)
+{
+    FileChainPtr	ret;
+
+    ret = malloc (sizeof (FileChain) + size);
+    ret->next = next;
+    ret->size = size;
+    ret->used = 0;
+    ret->ptr = 0;
+    return ret;
+}
+
+static void
+FileChainFree (FileChainPtr ic)
+{
+    while (ic)
+    {
+	FileChainPtr next = ic->next;
+	free (ic);
+	ic = next;
+    }
+}
+
 int
 FileInit (void)
 {
@@ -521,8 +545,6 @@ FileMark (void *object)
 
     FileFlush ((Value) file, False);
     MemReference (file->next);
-    MemReference (file->input);
-    MemReference (file->output);
 }
 
 void
@@ -538,10 +560,14 @@ FileFree (void *object)
 {
     File    *file = object;
 
-    if (file->fd == -1)
-	return 1;
-    if (FileClose ((Value) file) != FileBlocked)
+    if (file->fd == -1 || FileClose ((Value) file) != FileBlocked)
+    {
+	FileChainFree (file->input);
+	file->input = NULL;
+	FileChainFree (file->output);
+	file->output = NULL;
 	return 1;
+    }
     return 0;
 }
 
@@ -613,30 +639,6 @@ FileResetFd (int fd)
 #endif
 }
 
-static void
-FileChainMark (void *object)
-{
-    FileChainPtr	chain = object;
-
-    MemReference (chain->next);
-}
-
-DataType    FileChainType = { FileChainMark, 0, "FileChainType" };
-
-static FileChainPtr
-NewFileChain (FileChainPtr next, int size)
-{
-    ENTER ();
-    FileChainPtr	ret;
-
-    ret = MemAllocate (&FileChainType, sizeof (FileChain) + size);
-    ret->next = next;
-    ret->size = size;
-    ret->used = 0;
-    ret->ptr = 0;
-    RETURN (ret);
-}
-
 Value
 FileCreate (int fd, int flags)
 {
@@ -893,7 +895,7 @@ FileStringRead (char *string, int len)
 
     file = NewFile (-1);
     file->file.flags |= FileString|FileReadable;
-    file->file.input = NewFileChain (0, len);
+    file->file.input = FileChainAlloc (0, len);
     memcpy (FileBuffer (file->file.input), string, len);
     file->file.input->used = len;
     RETURN (file);
@@ -1009,7 +1011,7 @@ FileInput (Value file)
 	    EXIT ();
 	    return FileEOF;
 	}
-	file->file.input = NewFileChain (0, FileBufferSize);
+	file->file.input = FileChainAlloc (NULL, FileBufferSize);
     }
     ic = file->file.input;
     for (;;)
@@ -1022,7 +1024,12 @@ FileInput (Value file)
 	else
 	{
 	    if (ic->next)
-		ic = ic->next;
+	    {
+		file->file.input = ic->next;
+		ic->next = NULL;
+		FileChainFree (ic);
+		ic = file->file.input;
+	    }
 	    else if (file->file.flags & FileString)
 	    {
 		file->file.flags |= FileEnd;
@@ -1084,7 +1091,7 @@ FileUnput (Value file, unsigned char c)
     ic = file->file.input;
     if (!ic || ic->ptr == 0)
     {
-	ic = file->file.input = NewFileChain (file->file.input, FileBufferSize);
+	ic = file->file.input = FileChainAlloc (file->file.input, FileBufferSize);
 	ic->ptr = ic->used = ic->size;
     }
     FileBuffer(ic)[--ic->ptr] = c;
@@ -1175,6 +1182,8 @@ FileFlush (Value file, Bool block)
 		    ic->used = ic->ptr = 0;
 		    break;
 		}
+		else
+		    FileChainFree (ic);
 		*prev = 0;
 	    }
 	}
@@ -1214,7 +1223,7 @@ FileOutput (Value file, char c)
     }
     ic = file->file.output;
     if (!ic)
-	ic = file->file.output = NewFileChain (0, FileBufferSize);
+	ic = file->file.output = FileChainAlloc (0, FileBufferSize);
     if (ic->used == ic->size)
     {
 	if (FileFlush (file, False) == FileError)
@@ -1224,7 +1233,7 @@ FileOutput (Value file, char c)
 	}
 	ic = file->file.output;
 	if (ic->used == ic->size)
-	    ic = file->file.output = NewFileChain (file->file.output, FileBufferSize);
+	    ic = file->file.output = FileChainAlloc (file->file.output, FileBufferSize);
     }
     ic = file->file.output;
     FileBuffer(ic)[ic->used++] = c;
diff --git a/value.h b/value.h
index c941011..e94428f 100644
--- a/value.h
+++ b/value.h
@@ -625,7 +625,6 @@ typedef struct _array {
 #define ArrayValueSet(a,i,v) (BoxValueSet(ArrayValueBox(a,i),ArrayValueElt(a,i), v))
 
 typedef struct _io_chain {
-    DataType		*data;
     struct _io_chain	*next;
     int			size;
     int			used;
commit 8e3690cea5da54d83e6fd6d26c073c1c4d8ae403
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Tue Oct 2 01:16:05 2007 -0700

    Extend Ctype namespace to latin-1.
    
    This should be extended to all of unicode, but that's a huge amount of data.

diff --git a/ctype.5c b/ctype.5c
index 88dd1df..a595452 100644
--- a/ctype.5c
+++ b/ctype.5c
@@ -16,8 +16,8 @@ namespace Ctype {
 	return ch >= 0 && ch <= 127;
     }
     
-    /* The characteristic vector of sets of ASCII chars. */
-    public typedef bool[128] charset;
+    /* The characteristic vector of sets of Latin-1 chars. */
+    public typedef bool[256] charset;
 
     public charset make_charset(bool(int) cfun) 
 	/*
@@ -25,7 +25,7 @@ namespace Ctype {
 	 */
     {
 	charset result;
-	for (int i = 0; i < 128; i++)
+	for (int i = 0; i < dim(result); i++)
 	    result[i] = cfun(i);
 	return result;
     }
@@ -35,7 +35,7 @@ namespace Ctype {
 	 * Test whether a particular char is in a charset. 
 	 */
     {
-	return isascii(ch) && v[ch];
+	return ch >= 0 && ch < dim(v) && v[ch];
     }
 
 
@@ -51,7 +51,8 @@ namespace Ctype {
 	 */
     {
 	static bool cfun(int ch) {
-	    return ch >= 'A' && ch <= 'Z';
+	    return (ch >= 'A' && ch <= 'Z' ||
+		    ch >= 'À' && ch <= 'Þ');
 	}
 	static charset v = make_charset(cfun);
 	return member(v, ch);
@@ -63,7 +64,8 @@ namespace Ctype {
 	 */
     {
 	static bool cfun(int ch) {
-	    return ch >= 'a' && ch <= 'z';
+	    return (ch >= 'a' && ch <= 'z' ||
+		    ch >= 'à' && ch <= 'þ');
 	}
 	static charset v = make_charset(cfun);
 	return member(v, ch);
@@ -107,7 +109,8 @@ namespace Ctype {
 	 */	
     {
 	static bool cfun(int ch) {
-	    return ch > ' ' && ch < 127;
+	    return (ch > ' ' && ch < 127 ||
+		    ch >= 'À' && ch <= 'þ');
 	}
 	static charset v = make_charset(cfun);
 	return member(v, ch);
@@ -119,7 +122,8 @@ namespace Ctype {
 	 */	
     {
 	static bool cfun(int ch) {
-	    return ch >= ' ' && ch < 127;
+	    return (ch >= ' ' && ch < 127 ||
+		    ch >= 'À' && ch <= 'þ');
 	}
 	static charset v = make_charset(cfun);
 	return member(v, ch);
commit 52c9ae4e5c476f6b202b49de3840c7ffdd0e02d8
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Tue Oct 2 01:15:16 2007 -0700

    Flush file output on exit call.
    
    Use of the built-in exit function should flush all file I/O, just as if the
    program terminated by returning to the top level at EOF.

diff --git a/builtin-toplevel.c b/builtin-toplevel.c
index 36f854c..6ef745b 100644
--- a/builtin-toplevel.c
+++ b/builtin-toplevel.c
@@ -422,6 +422,7 @@ do_exit (Value av)
     if (aborting)
 	RETURN (Void);
     IoFini ();
+    FileFini ();
     exit (code);
     RETURN (Void);
 }


More information about the Nickle mailing list