[Commit] nickle ChangeLog, 1.39, 1.40 builtin-command.c, 1.11, 1.12 builtin-environ.c, 1.4, 1.5 builtin-file.c, 1.15, 1.16 builtin-sockets.c, 1.13, 1.14 builtin-string.c, 1.9, 1.10 configure.in, 1.32, 1.33 edit.c, 1.13, 1.14 execute.c, 1.89, 1.90 file.c, 1.62, 1.63 int.c, 1.21, 1.22 lex.l, 1.72, 1.73 scope.c, 1.29, 1.30 string.c, 1.16, 1.17 value.h, 1.101, 1.102

Keith Packard commit at keithp.com
Fri Apr 16 14:41:55 PDT 2004


Committed by: keithp

Update of /local/src/CVS/nickle
In directory home.keithp.com:/tmp/cvs-serv10275

Modified Files:
	ChangeLog builtin-command.c builtin-environ.c builtin-file.c 
	builtin-sockets.c builtin-string.c configure.in edit.c 
	execute.c file.c int.c lex.l scope.c string.c value.h 
Log Message:
2004-04-16  Keith Packard  <keithp at keithp.com>

	* builtin-command.c: (command_name), (do_Command_new_common),
	(do_Command_delete):
	* builtin-environ.c: (do_Environ_get), (do_Environ_check),
	(do_Environ_unset), (do_Environ_set):
	* builtin-file.c: (do_File_print), (do_File_open),
	(do_File_filter), (do_File_reopen), (do_File_string_read):
	* builtin-sockets.c: (address_lookup):
	* builtin-string.c: (do_String_length), (do_String_new),
	(do_String_index), (do_String_substr):
	* configure.in:
	* edit.c: (EditFile):
	* execute.c: (ThreadOpArray):
	* file.c: (FilePutsc), (FileStringWidth), (FilePutString),
	(FileVPrintf):
	* int.c: (IntPrint):
	* lex.l:
	* scope.c: (NamespaceLocate):
	* string.c: (StringPlus), (StringEqual), (StringLess),
	(StringPrint), (StringNextChar), (StringGet), (StringLength),
	(StrzPart), (StringHash), (NewString):
	* value.h:
	Change string representation to counted rather than
	null-terminated.
	Allow nulls in the middle of strings.
	Trap strings with nulls passed to the operating system.
	Raise exception when attempting to access the null which
	is stored off the end of the string.


Index: ChangeLog
===================================================================
RCS file: /local/src/CVS/nickle/ChangeLog,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -d -r1.39 -r1.40
--- a/ChangeLog	16 Apr 2004 18:19:08 -0000	1.39
+++ b/ChangeLog	16 Apr 2004 21:41:52 -0000	1.40
@@ -1,3 +1,33 @@
+2004-04-16  Keith Packard  <keithp at keithp.com>
+
+	* builtin-command.c: (command_name), (do_Command_new_common),
+	(do_Command_delete):
+	* builtin-environ.c: (do_Environ_get), (do_Environ_check),
+	(do_Environ_unset), (do_Environ_set):
+	* builtin-file.c: (do_File_print), (do_File_open),
+	(do_File_filter), (do_File_reopen), (do_File_string_read):
+	* builtin-sockets.c: (address_lookup):
+	* builtin-string.c: (do_String_length), (do_String_new),
+	(do_String_index), (do_String_substr):
+	* configure.in:
+	* edit.c: (EditFile):
+	* execute.c: (ThreadOpArray):
+	* file.c: (FilePutsc), (FileStringWidth), (FilePutString),
+	(FileVPrintf):
+	* int.c: (IntPrint):
+	* lex.l:
+	* scope.c: (NamespaceLocate):
+	* string.c: (StringPlus), (StringEqual), (StringLess),
+	(StringPrint), (StringNextChar), (StringGet), (StringLength),
+	(StrzPart), (StringHash), (NewString):
+	* value.h:
+	Change string representation to counted rather than
+	null-terminated.
+	Allow nulls in the middle of strings.
+	Trap strings with nulls passed to the operating system.
+	Raise exception when attempting to access the null which
+	is stored off the end of the string.
+
 2004-04-16  Bart Massey  <bart at cs.pdx.edu>
 
 	* string.5c: (parse_csv):

Index: builtin-command.c
===================================================================
RCS file: /local/src/CVS/nickle/builtin-command.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- a/builtin-command.c	27 Feb 2004 03:50:15 -0000	1.11
+++ b/builtin-command.c	16 Apr 2004 21:41:52 -0000	1.12
@@ -57,26 +57,20 @@
     EXIT ();
 }
 
-static Value
-do_Command_new_common (Value name, Value func, Bool names)
+static char *
+command_name (Value name)
 {
-    ENTER();
-    char	*cmd;
-    int		c;
+    char    *cmd_base = StrzPart (name, "argument must be valid name");
+    char    *cmd = cmd_base;
+    int	    c;
     
-    if (!ValueIsFunc(func))
-    {
-	RaiseStandardException (exception_invalid_argument,
-				"argument must be func",
-				2, NewInt (1), func);
-	RETURN (Void);
-    }
-    cmd = StringChars (&name->string);
+    if (!cmd_base)
+	return 0;
     while ((c = *cmd++))
     {
 	if (isupper (c) || islower (c))
 	    continue;
-	if (cmd != StringChars (&name->string) + 1)
+	if (cmd != cmd_base + 1)
 	{
 	    if (isdigit ((int)c) || c == '_')
 	     continue;
@@ -84,10 +78,27 @@
 	RaiseStandardException (exception_invalid_argument,
 				"argument must be valid name",
 				2, NewInt (0), name);
+	return 0;
+    }
+    return cmd_base;
+}
+
+static Value
+do_Command_new_common (Value name, Value func, Bool names)
+{
+    ENTER();
+    char    *cmd = command_name (name);
+    
+    if (!cmd)
+	RETURN (Void);
+    if (!ValueIsFunc(func))
+    {
+	RaiseStandardException (exception_invalid_argument,
+				"argument must be func",
+				2, NewInt (1), func);
 	RETURN (Void);
     }
-    CurrentCommands = NewCommand (CurrentCommands, 
-				  AtomId (StringChars (&name->string)),
+    CurrentCommands = NewCommand (CurrentCommands, AtomId (cmd),
 				  func, names);
     RETURN (Void);
 }
@@ -109,8 +120,11 @@
 {
     ENTER();
     Atom    id;
+    char    *cmd = command_name (name);
 
-    id = AtomId (StringChars (&name->string));
+    if (!cmd)
+	RETURN (Void);
+    id = AtomId (cmd);
     if (!CommandFind (CurrentCommands, id))
 	RETURN (FalseVal);
     CurrentCommands = CommandRemove (CurrentCommands, id);

Index: builtin-environ.c
===================================================================
RCS file: /local/src/CVS/nickle/builtin-environ.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- a/builtin-environ.c	27 Feb 2004 03:50:15 -0000	1.4
+++ b/builtin-environ.c	16 Apr 2004 21:41:52 -0000	1.5
@@ -46,9 +46,12 @@
 do_Environ_get (Value av)
 {
     ENTER ();
+    char    *name = StrzPart (av, "invalid environment variable name");
     char    *c;
 
-    c = getenv (StringChars (&av->string));
+    if (!name)
+	RETURN (Void);
+    c = getenv (name);
     if (!c) {
 	RaiseStandardException (exception_invalid_argument,
 				"name not available",
@@ -62,33 +65,31 @@
 do_Environ_check (Value av)
 {
     ENTER ();
-    char    *c;
+    char    *name = StrzPart (av, "invalid environment variable name");
 
-    c = getenv (StringChars (&av->string));
-    if (c)
+    if (!name)
+	RETURN (Void);
+    if (getenv (name))
 	RETURN (TrueVal);
     RETURN (FalseVal);
 }
 
-extern char **environ;
-
 Value
 do_Environ_unset (Value av)
 {
     ENTER ();
-    char *name = StringChars(&av->string);
-    int n = strlen(name);
-    while(*environ) {
-	if (!strncmp(*environ, name, n) && (*environ)[n] == '=') {
-	    char **tail = environ;
-	    while(*(tail+1))
-		tail++;
-	    *environ = *tail;
-	    *tail = 0;
-	    RETURN(TrueVal);
-	}
-	environ++;
+    char    *name = StrzPart (av, "invalid environment variable name");
+    
+    if (!name)
+	RETURN (Void);
+    
+#if HAVE_UNSETENV
+    if (getenv (name))
+    {
+	unsetenv (name);
+	RETURN (TrueVal);
     }
+#endif
     RETURN (FalseVal);
 }
 
@@ -96,14 +97,28 @@
 do_Environ_set (Value name, Value value)
 {
     ENTER ();
-    Value binding = NewString(strlen (StringChars(&name->string)) + 1 +
-			      strlen (StringChars(&value->string)));
-    (void) strcpy (StringChars(&binding->string),
-		   StringChars(&name->string));
-    (void) strcat (StringChars(&binding->string), "=");
-    (void) strcat (StringChars(&binding->string),
-		   StringChars(&value->string));
-    if (putenv (StringChars (&binding->string)) < 0)
-	RETURN (FalseVal);
-    RETURN (TrueVal);
+    char    *n = StrzPart (name, "invalid environment variable name");
+    char    *v = StrzPart (value, "invalid environment variable value");
+
+    if (!n || !v)
+	RETURN (Void);
+#if HAVE_SETENV
+    if (setenv (n, v, 1) >= 0)
+	RETURN (TrueVal);
+#else
+#if HAVE_PUTENV
+    {
+	Value	binding = Plus (name,
+				Plus (NewStrString ("="),
+				      value));
+	char	*b = StrzPart (binding, "invalid environment variable binding");
+
+	if (!b)
+	    RETURN (Void);
+	if (putenv (b) >= 0)
+	    RETURN (TrueVal);
+    }
+#endif
+#endif
+    RETURN (FalseVal);
 }

Index: builtin-file.c
===================================================================
RCS file: /local/src/CVS/nickle/builtin-file.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- a/builtin-file.c	16 Apr 2004 05:26:44 -0000	1.15
+++ b/builtin-file.c	16 Apr 2004 21:41:52 -0000	1.16
@@ -119,8 +119,13 @@
 	ThreadSleep (running, file, PriorityIo);
     else
     {
-	Print (file, value, *StringChars(&format->string), ibase, iwidth,
-	       iprec, *StringChars(&fill->string));
+	Print (file, value, 
+	       StringGet (StringChars (&format->string),
+			  format->string.length, 0),
+	       ibase, iwidth,
+	       iprec,
+	       StringGet (StringChars (&fill->string),
+			  fill->string.length, 0));
 	if (file->file.flags & FileOutputError)
 	{
 	    RaiseStandardException (exception_io_error, 
@@ -139,8 +144,12 @@
     Value	ret;
     int		err;
 
-    n = StringChars (&name->string);
-    m = StringChars (&mode->string);
+    n = StrzPart (name, "invalid file name");
+    if (!n)
+	RETURN (Void);
+    m = StrzPart (mode, "invalid file mode");
+    if (!m)
+	RETURN (Void);
     if (aborting)
 	RETURN (Void);
     ret = FileFopen (n, m, &err);
@@ -202,26 +211,31 @@
 do_File_filter (Value path, Value argv, Value filev)
 {
     ENTER ();
+    char    *p = StrzPart (path, "invalid program path");
     char    **args;
     int	    argc;
     Value   arg;
     Value   ret;
     int	    err;
 
+    if (!p)
+	RETURN (Void);
+    
     /* set up arguments */
     args = AllocateTemp ((ArrayLimits(&argv->array)[0] + 1) * sizeof (char *));
     for (argc = 0; argc < ArrayLimits(&argv->array)[0]; argc++)
     {
 	arg = ArrayValue (&argv->array, argc);
-	args[argc] = StringChars (&arg->string);
+	args[argc] = StrzPart (arg, "invalid argument");
+	if (!args[argc])
+	    RETURN (Void);
     }
     args[argc] = 0;
 
     /* run the filter */
     if (aborting)
 	RETURN(Void);
-    ret = FileFilter (StringChars (&path->string), args, 
-		      filev, &err);
+    ret = FileFilter (p, args, filev, &err);
     if (!ret)
     {
 	RaiseStandardException (exception_open_error,
@@ -259,8 +273,12 @@
     Value	ret;
     int		err;
 
-    n = StringChars (&name->string);
-    m = StringChars (&mode->string);
+    n = StrzPart (name, "invalid file name");
+    if (!n)
+	RETURN (Void);
+    m = StrzPart (mode, "invalid file mode");
+    if (!m)
+	RETURN (Void);
     if (aborting)
 	RETURN (Void);
     ret = FileReopen (n, m, file, &err);
@@ -279,10 +297,8 @@
 do_File_string_read (Value s)
 {
     ENTER ();
-    char    *str;
 
-    str = StringChars (&s->string);
-    RETURN (FileStringRead (str, strlen (str)));
+    RETURN (FileStringRead (StringChars (&s->string), s->string.length));
 }
 
 Value

Index: builtin-sockets.c
===================================================================
RCS file: /local/src/CVS/nickle/builtin-sockets.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- a/builtin-sockets.c	27 Feb 2004 03:50:15 -0000	1.13
+++ b/builtin-sockets.c	16 Apr 2004 21:41:52 -0000	1.14
@@ -133,11 +133,18 @@
 {
     struct hostent *host;
     struct servent *port;
-    char *hostchars = StringChars (&hostname->string);
-    char *portchars = StringChars (&portname->string);
+    char *hostchars;
+    char *portchars;
     char *endptr = 0;
     long int portnum;
 
+    hostchars = StrzPart (hostname, "invalid hostname");
+    if (!hostchars)
+	return False;
+    portchars = StrzPart (portname, "invalid portname");
+    if (!portchars)
+	return False;
+    
     if (*hostchars == '\0' || *portchars == '\0')
 	return False; /* FIXME: more here? */
 
@@ -157,7 +164,7 @@
     if (*endptr != '\0') /* non-numeric port specification */
     {
 	/* FIXME: this should not always be "tcp"! */
-	port = getservbyname (StringChars (&portname->string), "tcp");
+	port = getservbyname (portchars, "tcp");
 	if (port == 0)
 	    return False; /* FIXME: more here? */
 	addr->sin_port = port->s_port;

Index: builtin-string.c
===================================================================
RCS file: /local/src/CVS/nickle/builtin-string.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- a/builtin-string.c	16 Apr 2004 09:34:30 -0000	1.9
+++ b/builtin-string.c	16 Apr 2004 21:41:52 -0000	1.10
@@ -52,7 +52,7 @@
 {
     ENTER();
     Value ret;
-    ret = NewInt(StringLength(StringChars(&av->string)));
+    ret = NewInt(StringLength(StringChars(&av->string), av->string.length));
     RETURN (ret);
 }
 
@@ -79,7 +79,6 @@
 					 "new: array element not integer"),
 				s);
 	}
-	*s = '\0';
     }
     else
     {
@@ -88,7 +87,6 @@
 	ret = NewString (size);
 	s = StringChars (&ret->string);
 	s += StringPutChar (c, s);
-	*s = '\0';
     }
     RETURN (ret);
 }
@@ -98,9 +96,11 @@
 {
     ENTER();
     char *a, *b, *p;
+    long al;
     Value ret;
     int i;
     a = StringChars(&av->string);
+    al = av->string.length;
     b = StringChars(&bv->string);
     p = strstr(a, b);
     if (!p)
@@ -109,7 +109,7 @@
     while (a < p)
     {
 	int c;
-	a = StringNextChar (a, &c);
+	a = StringNextChar (a, &c, &al);
 	i++;
     }
     ret = NewInt(i);
@@ -123,8 +123,11 @@
     char *a, *rchars, *e;
     int b, c, al, size;
     Value ret;
+    long alen = av->string.length;
+    long elen;
+
     a = StringChars(&av->string);
-    al = StringLength (a);
+    al = StringLength (a, alen);
     b = IntPart(bv, "substr: index not integer");
     c = IntPart(cv, "substr: count not integer");
     if (c < 0) {
@@ -151,23 +154,23 @@
     while (b > 0)
     {
 	int ch;
-	a = StringNextChar (a, &ch);
+	a = StringNextChar (a, &ch, &alen);
 	b--;
     }
     /*
      * Find size of substring
      */
     e = a;
+    elen = alen;
     while (c > 0)
     {
 	int ch;
-	e = StringNextChar (e, &ch);
+	e = StringNextChar (e, &ch, &elen);
 	c--;
     }
     size = e - a;
     ret = NewString(size);
     rchars = StringChars(&ret->string);
-    strncpy(rchars, a, size);
-    rchars[size] = '\0';
+    memcpy (rchars, a, size);
     RETURN (ret);
 }

Index: configure.in
===================================================================
RCS file: /local/src/CVS/nickle/configure.in,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -d -r1.32 -r1.33
--- a/configure.in	16 Apr 2004 06:02:07 -0000	1.32
+++ b/configure.in	16 Apr 2004 21:41:52 -0000	1.33
@@ -69,7 +69,7 @@
 dnl Checks for library functions.
 AC_TYPE_SIGNAL
 AC_FUNC_VPRINTF
-AC_CHECK_FUNCS(gettimeofday hstrerror select sigaction sigrelse sigignore)
+AC_CHECK_FUNCS(unsetenv setenv putenv gettimeofday hstrerror select sigaction sigrelse sigignore)
 
 AC_FUNC_GETPGRP
 

Index: edit.c
===================================================================
RCS file: /local/src/CVS/nickle/edit.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- a/edit.c	27 Feb 2004 03:50:16 -0000	1.13
+++ b/edit.c	16 Apr 2004 21:41:52 -0000	1.14
@@ -80,9 +80,9 @@
     }
     else
     {
-	if (ValueIsString(file_name)) 
-	    edit (StringChars (&file_name->string));
-	else
-	    PrintError ("edit: non-string filename %v", file_name);
+	char	*name = StrzPart (file_name, "invalid filename");
+
+	if (name)
+	    edit (name);
     }
 }

Index: execute.c
===================================================================
RCS file: /local/src/CVS/nickle/execute.c,v
retrieving revision 1.89
retrieving revision 1.90
diff -u -d -r1.89 -r1.90
--- a/execute.c	16 Apr 2004 05:26:45 -0000	1.89
+++ b/execute.c	16 Apr 2004 21:41:52 -0000	1.90
@@ -758,14 +758,14 @@
 	if (aborting)
 	    break;
 	s = StringChars (&v->string);
-	if (i < 0 || StringLength (s) < i)
+	if (i < 0 || StringLength (s, v->string.length) <= i)
 	{
 	    RaiseStandardException (exception_invalid_binop_values,
 				    "String index out of bounds",
 				    2, value, v);
 	    break;
 	}
-	value = NewInt (StringGet (s, i));
+	value = NewInt (StringGet (s, v->string.length, i));
 	break;
     case rep_array:
 	if (stack != v->array.ndim)

Index: file.c
===================================================================
RCS file: /local/src/CVS/nickle/file.c,v
retrieving revision 1.62
retrieving revision 1.63
diff -u -d -r1.62 -r1.63
--- a/file.c	16 Apr 2004 08:24:58 -0000	1.62
+++ b/file.c	16 Apr 2004 21:41:52 -0000	1.63
@@ -1243,6 +1243,13 @@
 }
 
 void
+FilePutsc (Value file, char *s, long length)
+{
+    while (length--)
+	FileOutput (file, *s++);
+}
+
+void
 FilePutDoubleDigitBase (Value file, double_digit a, int base)
 {
     int	    digit;
@@ -1291,15 +1298,15 @@
 }
 
 int
-FileStringWidth (char *string, char format)
+FileStringWidth (char *string, long length, char format)
 {
     if (format == 's')
-	return StringLength (string);
+	return StringLength (string, length);
     else
     {
 	int	    width = 2;
 	int	    c;
-	while ((string = StringNextChar (string, &c)))
+	while ((string = StringNextChar (string, &c, &length)))
 	{
 	    if (c < ' ' || '~' < c)
 		switch (c) {
@@ -1309,6 +1316,7 @@
 		case '\b':
 		case '\f':
 		case '\v':
+		case '\0':
 		    width += 2;
 		    break;
 		default:
@@ -1325,15 +1333,15 @@
 }
 
 void
-FilePutString (Value f, char *string, char format)
+FilePutString (Value f, char *string, long length, char format)
 {
     if (format == 's')
-	FilePuts (f, string);
+	FilePutsc (f, string, length);
     else
     {
 	int c;
 	FileOutput (f, '"');
-	while ((string = StringNextChar (string, &c))) 
+	while ((string = StringNextChar (string, &c, &length))) 
 	{
 	    if (c < ' ')
 		switch (c) {
@@ -1354,6 +1362,8 @@
 		    break;
 		case '\v':
 		    FilePuts (f, "\\v");
+		case '\0':
+		    FilePuts (f, "\\0");
 		    break;
 		default:
 		    FileOutput (f, '\\');
@@ -1774,9 +1784,11 @@
 	    case 's':
 		(void) FilePuts (file, va_arg (args, char *));
 		break;
-	    case 'S':
-		FilePutString (file, va_arg (args, char *), 'v');
+	    case 'S': {
+		char *s = va_arg (args, char *);
+		FilePutString (file, s, strlen(s), 'v');
 		break;
+	    }
 	    case 'A':
 		(void) FilePuts (file, AtomName (va_arg (args, Atom)));
 		break;

Index: int.c
===================================================================
RCS file: /local/src/CVS/nickle/int.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- a/int.c	27 Feb 2004 03:50:16 -0000	1.21
+++ b/int.c	16 Apr 2004 21:41:52 -0000	1.22
@@ -235,6 +235,7 @@
     char    space[64], *s;
     char    letter;
     int	    neg;
+    long    len;
 
     if ('A' <= format && format <= 'Z')
 	letter = 'A';
@@ -274,7 +275,8 @@
 		*--s = '-';
 	}
     }
-    w = StringLength (s);
+    len = strlen (s);
+    w = StringLength (s, len);
     fraction_width = 0;
     if (prec >= 0)
     {
@@ -301,7 +303,7 @@
 	FileOutchar (f, fill);
 	width--;
     }
-    FilePuts (f, s);
+    FilePutsc (f, s, len);
     if (fraction_width)
     {
 	FileOutput (f, '.');

Index: lex.l
===================================================================
RCS file: /local/src/CVS/nickle/lex.l,v
retrieving revision 1.72
retrieving revision 1.73
diff -u -d -r1.72 -r1.73
--- a/lex.l	16 Apr 2004 03:37:12 -0000	1.72
+++ b/lex.l	16 Apr 2004 21:41:52 -0000	1.73
@@ -199,9 +199,8 @@
 	Value	v;
 
 	v = prompt ();
-	if (v && ValueIsString(v))
-	    p = StringChars (&v->string);
-	else
+	p = StrzPart (prompt (), "invalid prompt");
+	if (!p)
 	    p = "??? ";
 	for (;;)
 	{
@@ -406,20 +405,20 @@
 \'([^\n\']|\\\')*\'	{
 			ENTER ();
 			char	 *s;
+			long	len = yyleng - 1;
 			int	c;
-    			yytext[yyleng - 1] = '\0';
 			s = yytext + 1;
-			s = StringNextChar (s, &c);
+			s = StringNextChar (s, &c, &len);
 			if (c == '\\')
 			{
-			    if (!(s = StringNextChar (s, &c)))
+			    if (!(s = StringNextChar (s, &c, &len)))
 				c = 0;
 			    else if ('0' <= c && c <= '7')
 			    {
 				int	ch;
 				char    *ps = s;
 				c = c - '0';
-				while ((s = StringNextChar (s, &ch)) &&
+				while ((s = StringNextChar (s, &ch, &len)) &&
 				       '0' <= ch && ch <= '7')
 				{
 				    c = (c << 3) | (ch - '0');
@@ -439,28 +438,32 @@
 			ENTER ();
 			char	*d, *s;
 			int	c;
-    			yytext[yyleng - 1] = '\0';
-			yylval.value = NewString (yyleng-2);
+			long	len = yyleng - 2;
+
+			yylval.value = NewString (len);
 			d = StringChars (&yylval.value->string);
 			s = yytext + 1;
-			while ((s = StringNextChar (s, &c)))
+			while ((s = StringNextChar (s, &c, &len)))
 			{
 			    if (c == '\\')
 			    {
-				if (!(s = StringNextChar (s, &c)))
+				if (!(s = StringNextChar (s, &c, &len)))
 				    break;
 				if ('0' <= c && c <= '7')
 				{
 				    int	    ch;
     				    char    *ps = s;
+				    long    plen = len;
 				    c = c - '0';
-				    while ((s = StringNextChar (s, &ch)) &&
+				    while ((s = StringNextChar (s, &ch, &len)) &&
 					   '0' <= ch && ch <= '7')
 				    {
 					c = (c << 3) | (ch - '0');
 					ps = s;
+					plen = len;
 				    }
 				    s = ps;
+				    len = plen;
 				}
 				else
 				    c = lexEscape (c);
@@ -468,6 +471,7 @@
 			    d += StringPutChar (c, d);
 			}
 			*d = '\0';
+			yylval.value->string.length = d - StringChars(&yylval.value->string);
 			EXIT ();
 			REFERENCE (yylval.value);
 			return STRING_CONST;

Index: scope.c
===================================================================
RCS file: /local/src/CVS/nickle/scope.c,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -d -r1.29 -r1.30
--- a/scope.c	16 Apr 2004 05:26:45 -0000	1.29
+++ b/scope.c	16 Apr 2004 21:41:52 -0000	1.30
@@ -261,8 +261,8 @@
 	if (!namelist)
 	{
 	    if (complain)
-		FilePrintf (FileStdout, "No symbol \"%s\" in namespace\n",
-			    StringChars (&string->string));
+		FilePrintf (FileStdout, "No symbol %v in namespace\n",
+			    string);
 	    return False;
 	}
 	symbol = namelist->symbol;

Index: string.c
===================================================================
RCS file: /local/src/CVS/nickle/string.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- a/string.c	27 Feb 2004 03:50:16 -0000	1.16
+++ b/string.c	16 Apr 2004 21:41:52 -0000	1.17
@@ -26,19 +26,24 @@
     ENTER();
     Value	ret;
 
-    ret = NewString (strlen (StringChars(&av->string)) + 
-		     strlen (StringChars(&bv->string)));
-    (void) strcpy (StringChars(&ret->string),
-		   StringChars(&av->string));
-    (void) strcat (StringChars(&ret->string),
-		   StringChars(&bv->string));
+    ret = NewString (av->string.length + bv->string.length);
+    (void) memcpy (StringChars(&ret->string),
+		   StringChars(&av->string),
+		   av->string.length);
+    (void) memcpy (StringChars(&ret->string) + av->string.length,
+		   StringChars(&bv->string),
+		   bv->string.length);
     RETURN (ret);
 }
 
 static Value
 StringEqual (Value av, Value bv, int expandOk)
 {
-    if (!strcmp (StringChars (&av->string), StringChars(&bv->string)))
+    if (av->string.length != bv->string.length)
+	return FalseVal;
+    if (!memcmp (StringChars (&av->string), 
+		 StringChars(&bv->string),
+		 av->string.length))
 	return TrueVal;
     return FalseVal;
 }
@@ -46,7 +51,16 @@
 static Value
 StringLess (Value av, Value bv, int expandOk)
 {
-    if (strcmp (StringChars (&av->string), StringChars(&bv->string)) < 0)
+    long    len;
+    int	    c;
+
+    len = av->string.length;
+    if (len > bv->string.length)
+	len = bv->string.length;
+    c = memcmp (StringChars (&av->string), StringChars(&bv->string), len);
+    if (c < 0)
+	return TrueVal;
+    if (c == 0 && av->string.length < bv->string.length)
 	return TrueVal;
     return FalseVal;
 }
@@ -56,15 +70,16 @@
 StringPrint (Value f, Value av, char format, int base, int width, int prec, int fill)
 {
     char    *string = StringChars (&av->string);
+    long    len = av->string.length;
     int	    print_width;
     
-    print_width = FileStringWidth (string, format);
+    print_width = FileStringWidth (string, len, format);
     while (width > print_width)
     {
 	FileOutchar (f, fill);
 	width--;
     }
-    FilePutString (f, string, format);
+    FilePutString (f, string, len, format);
     while (-width > print_width)
     {
 	FileOutchar (f, fill);
@@ -74,12 +89,13 @@
 }
 
 char *
-StringNextChar (char *src, unsigned *dst)
+StringNextChar (char *src, unsigned *dst, long *len)
 {
     unsigned	result = *src++;
     
-    if (!result)
+    if (!*len)
 	return 0;
+    (*len)--;
     
     if (result & 0x80)
     {
@@ -95,9 +111,11 @@
 	{
 	    char c = *src++;
 
+	    (*len)--;
 	    if ((c & 0x80) == 0)
 	    {
 		src--;
+		(*len)++;
 		result = 0;
 		break;
 	    }
@@ -109,13 +127,13 @@
 }
 
 unsigned
-StringGet (char *src, int i)
+StringGet (char *src, long len, int i)
 {
     unsigned c;
 
     do
     {
-	src = StringNextChar (src, &c);
+	src = StringNextChar (src, &c, &len);
 	if (!src)
 	    return 0;
     } while (i-- > 0);
@@ -123,13 +141,13 @@
 }
 
 int
-StringLength (char *src)
+StringLength (char *src, long len)
 {
-    int	len = 0;
+    int	l = 0;
     unsigned c;
-    while ((src = StringNextChar (src, &c)))
-	len++;
-    return len;
+    while ((src = StringNextChar (src, &c, &len)))
+	l++;
+    return l;
 }
 
 int
@@ -164,17 +182,29 @@
     else return 0;
 }
 
+char *
+StrzPart (Value v, char *error)
+{
+    if (!ValueIsString (v) || strlen (StringChars(&v->string)) != v->string.length)
+    {
+	RaiseStandardException (exception_invalid_argument, error,
+				2, NewInt (0), v);
+	return 0;
+    }
+    return StringChars (&v->string);
+}
+
 #define hrot(i)	(((i) << 1) | ((i) >> (sizeof (HashValue) * 8 - 1)))
 
 static HashValue
 StringHash (Value av)
 {
     char	*string = StringChars (&av->string);
-    char	c;
+    long	len = av->string.length;
     HashValue	h = 0;
 
-    while ((c = *string++))
-	h = hrot(h) ^ (HashValue) c;
+    while (len--)
+	h = hrot(h) ^ (HashValue) *string++;
     return h;
 }
 
@@ -204,12 +234,14 @@
 };
 
 Value
-NewString (int len)
+NewString (long length)
 {
     ENTER ();
     Value   ret;
 
-    ret = ALLOCATE (&StringRep.data, sizeof (String) + len + 1);
+    ret = ALLOCATE (&StringRep.data, sizeof (String) + length + 1);
+    ret->string.length = length;
+    StringChars(&ret->string)[length] = '\0';
     RETURN (ret);
 }
 

Index: value.h
===================================================================
RCS file: /local/src/CVS/nickle/value.h,v
retrieving revision 1.101
retrieving revision 1.102
diff -u -d -r1.101 -r1.102
--- a/value.h	16 Apr 2004 05:26:45 -0000	1.101
+++ b/value.h	16 Apr 2004 21:41:52 -0000	1.102
@@ -551,7 +551,8 @@
 } Float;
 
 typedef struct _string {
-    BaseValue	base;
+    BaseValue	    base;
+    long	    length;
 } String;
 
 #define StringChars(s)	    ((char *) ((s) + 1))
@@ -939,7 +940,7 @@
 
 extern DataCachePtr	refCache;
 
-Value	NewString (int);
+Value	NewString (long length);
 Value	NewStrString (char *);
 Value	NewArray (Bool constant, Bool resizable, TypePtr type, int ndim, int *dims);
 void	ArrayResize (Value av, int dim, int size);
@@ -956,11 +957,12 @@
 
 Value	NewFile (int fd);
 Value	NewRefReal (BoxPtr box, int element, Value *re);
-char	*StringNextChar (char *src, unsigned *dst);
+char	*StringNextChar (char *src, unsigned *dst, long *length);
 int	StringPutChar (unsigned c, char *dest);
-int	StringLength (char *src);
+int	StringLength (char *src, long length);
 int	StringCharSize (unsigned c);
-unsigned    StringGet (char *src, int i);
+unsigned    StringGet (char *src, long len, int i);
+char	*StrzPart (Value, char *error);
 
 #ifdef HAVE_C_INLINE
 
@@ -1019,13 +1021,14 @@
 void	FileSetFd (int fd), FileResetFd (int fd);
 Bool	FileIsReadable (int fd);
 Bool	FileIsWritable (int fd);
+void	FilePutsc (Value, char *, long length);
 void	FilePuts (Value, char *);
 void	FilePutDoubleDigitBase (Value file, double_digit a, int base);
 void	FilePutUIntBase (Value file, unsigned int a, int base);
 void	FilePutIntBase (Value file, int a, int base);
 void	FilePutInt (Value, int);
-int	FileStringWidth (char *string, char format);
-void	FilePutString (Value f, char *string, char format);
+int	FileStringWidth (char *string, long length, char format);
+void	FilePutString (Value f, char *string, long length, char format);
 void	FilePutRep (Value f, Rep tag, Bool minimal);
 void	FilePutClass (Value f, Class storage, Bool minimal);
 void	FilePutPublish (Value f, Publish publish, Bool minimal);




More information about the Commit mailing list