[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