[Commit] nickle ChangeLog, 1.64, 1.65 abort.5c, 1.5, 1.6 arc4.5c, 1.5, 1.6 builtin-command.c, 1.12, 1.13 builtin-debug.c, 1.6, 1.7 builtin-environ.c, 1.5, 1.6 builtin-file.c, 1.16, 1.17 builtin-math.c, 1.10, 1.11 builtin-semaphore.c, 1.4, 1.5 builtin-sockets.c, 1.14, 1.15 builtin-string.c, 1.10, 1.11 builtin-thread.c, 1.4, 1.5 builtin-toplevel.c, 1.25, 1.26 builtin.5c, 1.7, 1.8 builtin.c, 1.18, 1.19 builtin.h, 1.8, 1.9 command.5c, 1.19, 1.20 compile.c, 1.154, 1.155 ctype.5c, 1.2, 1.3 debug.c, 1.33, 1.34 file.5c, 1.2, 1.3 file.c, 1.63, 1.64 func.c, 1.22, 1.23 gram.y, 1.134, 1.135 history.5c, 1.4, 1.5 lex.l, 1.74, 1.75 math.5c, 1.38, 1.39 mutex.5c, 1.8, 1.9 nickle.h, 1.117, 1.118 parse-args.5c, 1.1, 1.2 pretty.c, 1.69, 1.70 printf.5c, 1.8, 1.9 prng.5c, 1.10, 1.11 scanf.5c, 1.19, 1.20 socket.5c, 1.1, 1.2 string.5c, 1.8, 1.9 string.c, 1.17, 1.18 symbol.c, 1.19, 1.20 value.h, 1.104, 1.105

Keith Packard commit at keithp.com
Tue Jun 8 02:30:57 PDT 2004


Committed by: keithp

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

Modified Files:
	ChangeLog abort.5c arc4.5c builtin-command.c builtin-debug.c 
	builtin-environ.c builtin-file.c builtin-math.c 
	builtin-semaphore.c builtin-sockets.c builtin-string.c 
	builtin-thread.c builtin-toplevel.c builtin.5c builtin.c 
	builtin.h command.5c compile.c ctype.5c debug.c file.5c file.c 
	func.c gram.y history.5c lex.l math.5c mutex.5c nickle.h 
	parse-args.5c pretty.c printf.5c prng.5c scanf.5c socket.5c 
	string.5c string.c symbol.c value.h 
Log Message:
2004-06-08  Keith Packard  <keithp at keithp.com>
version 2.40

	* abort.5c:
	* arc4.5c:
	* builtin-command.c: (import_Command_namespace),
	(do_Command_pretty_print):
	* builtin-debug.c: (import_Debug_namespace):
	* builtin-environ.c: (import_Environ_namespace):
	* builtin-file.c: (import_File_namespace):
	* builtin-math.c: (import_Math_namespace):
	* builtin-semaphore.c: (import_Semaphore_namespace):
	* builtin-sockets.c: (import_Socket_namespace):
	* builtin-string.c: (import_String_namespace):
	* builtin-thread.c: (import_Thread_namespace):
	* builtin-toplevel.c: (import_Toplevel_namespace):
	* builtin.5c:
	* builtin.c: (BuiltinType), (BuiltinException),
	(BuiltinAddException), (BuiltinAddFunction), (BuiltinInit):
	* builtin.h:
	* command.5c:
	* compile.c: (CompileComprehension):
	* ctype.5c:
	* debug.c: (do_Debug_dump):
	* file.5c:
	* file.c: (FileFopen):
	* func.c: (MarkFuncCode), (NewFuncCode), (MarkBuiltinCode),
	(NewBuiltinCode):
	* gram.y:
	* history.5c:
	* lex.l:
	* math.5c:
	* mutex.5c:
	* nickle.h:
	* parse-args.5c:
	* pretty.c: (PrettyDoc), (PrettyBody), (doPrettyPrint),
	(PrettyPrint):
	* printf.5c:
	* prng.5c:
	* scanf.5c:
	* socket.5c:
	* string.5c:
	* string.c: (NewCharString):
	* symbol.c: (SymbolExceptionMark), (NewSymbolException):
	* value.h:
	Add doc strings to all functions and exceptions.


Index: ChangeLog
===================================================================
RCS file: /local/src/CVS/nickle/ChangeLog,v
retrieving revision 1.64
retrieving revision 1.65
diff -u -d -r1.64 -r1.65
--- a/ChangeLog	3 Jun 2004 07:46:23 -0000	1.64
+++ b/ChangeLog	8 Jun 2004 09:30:53 -0000	1.65
@@ -1,3 +1,50 @@
+2004-06-08  Keith Packard  <keithp at keithp.com>
+version 2.40
+
+	* abort.5c:
+	* arc4.5c:
+	* builtin-command.c: (import_Command_namespace),
+	(do_Command_pretty_print):
+	* builtin-debug.c: (import_Debug_namespace):
+	* builtin-environ.c: (import_Environ_namespace):
+	* builtin-file.c: (import_File_namespace):
+	* builtin-math.c: (import_Math_namespace):
+	* builtin-semaphore.c: (import_Semaphore_namespace):
+	* builtin-sockets.c: (import_Socket_namespace):
+	* builtin-string.c: (import_String_namespace):
+	* builtin-thread.c: (import_Thread_namespace):
+	* builtin-toplevel.c: (import_Toplevel_namespace):
+	* builtin.5c:
+	* builtin.c: (BuiltinType), (BuiltinException),
+	(BuiltinAddException), (BuiltinAddFunction), (BuiltinInit):
+	* builtin.h:
+	* command.5c:
+	* compile.c: (CompileComprehension):
+	* ctype.5c:
+	* debug.c: (do_Debug_dump):
+	* file.5c:
+	* file.c: (FileFopen):
+	* func.c: (MarkFuncCode), (NewFuncCode), (MarkBuiltinCode),
+	(NewBuiltinCode):
+	* gram.y:
+	* history.5c:
+	* lex.l:
+	* math.5c:
+	* mutex.5c:
+	* nickle.h:
+	* parse-args.5c:
+	* pretty.c: (PrettyDoc), (PrettyBody), (doPrettyPrint),
+	(PrettyPrint):
+	* printf.5c:
+	* prng.5c:
+	* scanf.5c:
+	* socket.5c:
+	* string.5c:
+	* string.c: (NewCharString):
+	* symbol.c: (SymbolExceptionMark), (NewSymbolException):
+	* value.h:
+	Add doc strings to all functions and exceptions.
+
 2004-06-03  Keith Packard  <keithp at keithp.com>
 version 2.39
 

Index: abort.5c
===================================================================
RCS file: /local/src/CVS/nickle/abort.5c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- a/abort.5c	7 Jul 2003 02:24:47 -0000	1.5
+++ b/abort.5c	8 Jun 2004 09:30:53 -0000	1.6
@@ -3,22 +3,32 @@
 
     public exception aborting(string);
 
-    public void abort(string reason, args ...) {
+    public void abort(string reason, args ...) 
+	/*
+	 * Print a stack trace and raise aborting (vsprintf (reason, args))
+	 */
+    {
 	Debug::trace(Thread::current(), trace_depth);
 	string reasonmsg = File::vsprintf(reason, args);
 	raise aborting(reasonmsg);
     }
 
-    public void assert(bool ok, string failure, args ...) {
-	if (!ok) {
-	    string failmsg = File::vsprintf(failure, args);
-	    abort(failmsg);
-	}
+    public void assert(bool ok, string failure, args ...) 
+	/*
+	 * If 'ok' is false, abort (failure, args ...);
+	 */
+    {
+	if (!ok)
+	    abort(failure, args ...);
     }
 
     public bool do_debug = true;
 
-    public void debug(string fmt, args ...) {
+    public void debug(string fmt, args ...) 
+	/*
+	 * Print to stderr, controlled by 'do_debug' global
+	 */
+    {
 	if (do_debug)
 	    File::vfprintf(stderr, fmt + "\n", args);
     }

Index: arc4.5c
===================================================================
RCS file: /local/src/CVS/nickle/arc4.5c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- a/arc4.5c	9 Aug 2002 06:02:13 -0000	1.5
+++ b/arc4.5c	8 Jun 2004 09:30:53 -0000	1.6
@@ -11,13 +11,14 @@
   global int[256] state = {};
   global int p1, p2;
 
-  /*
-   * First argument is number of times to iterate the
-   * initial scramble.  10 seems good for most apps.
-   * Second argument is integer key: largest useful key is
-   * 8 * 62 bits.
-   */
-  public void nsetkey(int nn, int k) {
+  public void nsetkey(int nn, int k) 
+    /*
+     * First argument is number of times to iterate the
+     * initial scramble.  10 seems good for most apps.
+     * Second argument is integer key: largest useful key is
+     * 8 * 62 bits.
+     */
+  {
     int i, j, n, ii;
     int[64] key = {};
 
@@ -43,8 +44,11 @@
     p1 = p2 = 0;
   }
 
-  /* Get the next byte from the stream */
-  public int streambyte() {
+  public int streambyte() 
+    /*
+     * Get the next byte from the stream 
+     */
+  {
     p1 = (p1 + 1) & 0xff;
     p2 = (p2 + state[p1]) & 0xff;
     int tmp = state[p1];
@@ -55,4 +59,3 @@
   }
   
 }
-

Index: builtin-command.c
===================================================================
RCS file: /local/src/CVS/nickle/builtin-command.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- a/builtin-command.c	16 Apr 2004 21:41:52 -0000	1.12
+++ b/builtin-command.c	8 Jun 2004 09:30:53 -0000	1.13
@@ -24,27 +24,63 @@
 {
     ENTER ();
     static const struct fbuiltin_1 funcs_1[] = {
-        { do_Command_delete, "delete", "b", "s" },
-        { do_Command_edit, "edit", "v", "A*s" },
-	{ do_Command_display, "display", "v", "p" },
-	{ do_Command_valid_name, "valid_name", "b", "A*s" },
+        { do_Command_delete, "delete", "b", "s", "\n"
+	    " bool delete(string command)\n"
+	    "\n"
+	    " Remove 'command' from the set of valid commands\n" },
+        { do_Command_edit, "edit", "v", "A*s", "\n"
+	    " void edit(string[*] function)\n"
+	    "\n"
+	    " Invoke $EDITOR on 'function', parse the file when done\n" },
+	{ do_Command_display, "display", "v", "p", "\n"
+	    " void display (poly value)\n"
+	    "\n"
+	    " Built-in display primitive for read/eval/print loop" },
+	{ do_Command_valid_name, "valid_name", "b", "A*s", "\n"
+	    " bool valid_name (string[*] name)\n"
+	    "\n"
+	    " Check for a symbol table entry\n" },
         { 0 }
     };
 
     static const struct fbuiltin_2 funcs_2[] = {
-        { do_Command_new, "new", "v", "sp" },
-        { do_Command_new_names, "new_names", "v", "sp" },
+        { do_Command_new, "new", "v", "sp", "\n"
+	    " void new (string name, poly f)\n"
+	    "\n"
+	    " Create a new command which calls 'f'.\n"
+	    " 'f' will be invoked with an array of values\n" },
+        { do_Command_new_names, "new_names", "v", "sp", "\n"
+	    " void new_names (string name, poly f)\n"
+	    "\n"
+	    " Create a new command which calls 'f' with literal arguments.\n"
+	    " 'f' will be invoked with an array of strings\n" },
         { 0 }
     };
 
     static const struct fbuiltin_4 funcs_4[] = {
-	{ do_Command_lex_input, "lex_input", "b", "fsbb" },
+	{ do_Command_lex_input, "lex_input", "b", "fsbb", "\n"
+	    " bool lex_input (file f, string name, bool after, bool interactive)"
+	    "\n"
+	    " Add 'f' to the list of files to be read by the lexer.\n"
+	    " 'name' will be used when reporting parse errors.\n"
+	    " If 'after', the specified file will be read when all other\n"
+	    " input sources are exhausted.\n"
+	    " If 'interactive', the lexer will display prompts as if\n"
+	    " input was coming from a terminal.\n" },
         { 0 }
     };
 
     static const struct fbuiltin_v funcs_v[] = {
-        { do_Command_undefine, "undefine", "v", ".A*s" },
-        { do_Command_pretty_print, "pretty_print", "v", "f.A*s" },
+        { do_Command_undefine, "undefine", "v", ".A*s", "\n"
+	    " void undefine (string[*] ... name)\n"
+	    "\n"
+	    " removes 'name' from its namespace\n" },
+        { do_Command_pretty_print, "pretty_print", "v", "f.A*s", "\n"
+	    " void pretty_print (file f, string[*] ... name)\n"
+	    "\n"
+	    " Prints the variable and value in a format capable of\n"
+	    " reproducing the value if fed back to the parser\n" },
+	
         { 0 }
     };
 
@@ -148,6 +184,8 @@
 	names = args[i];
 	if (NamespaceLocate (names, &namespace, &symbol, &publish, True))
 	    PrettyPrint (f, publish, symbol);
+	else
+	    PrettyPrint (f, publish_public, 0);
     }
     RETURN (Void);
 }

Index: builtin-debug.c
===================================================================
RCS file: /local/src/CVS/nickle/builtin-debug.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- a/builtin-debug.c	27 Feb 2004 03:50:15 -0000	1.6
+++ b/builtin-debug.c	8 Jun 2004 09:30:53 -0000	1.7
@@ -29,25 +29,58 @@
 {
     ENTER ();
     static const struct fbuiltin_0 funcs_0[] = {
-        { do_Debug_collect, "collect", "v", "" },
-        { do_Debug_done, "done", "v", "" },
-        { do_Debug_down, "down", "b", "" },
-        { do_Debug_up, "up", "b", "" },
-	{ do_Debug_help, "help", "v", ""},
-	{ do_Debug_mem_collect, "mem_collect", "v", "" },
+        { do_Debug_collect, "collect", "v", "", "\n"
+	    " void collect ()\n"
+	    "\n"
+	    " Invokes the garbage collector\n" },
+        { do_Debug_done, "done", "v", "", "\n"
+	    " void done ()\n"
+	    "\n"
+	    " Terminates the debugger, returning control\n"
+	    " to the enclosing non-debugging read/eval/print loop.\n" },
+        { do_Debug_down, "down", "b", "", "\n"
+	    " bool down ()\n"
+	    "\n"
+	    " Moves the current debug context one frame down the call chain.\n"
+	    " Returns whether this was possible or not.\n" },
+        { do_Debug_up, "up", "b", "", "\n"
+	    " bool up ()\n"
+	    "\n"
+	    " Moves the current debug context one frame up the call chain.\n"
+	    " Returns whether this was possible or not.\n" },
+	{ do_Debug_help, "help", "v", "", "\n"
+	    " void help ()\n"
+	    "\n"
+	    " Displays a bit of help for using the debugger.\n"	},
 #ifdef MEM_TRACE
-	{ do_Debug_dump_active, "dump_active", "v", "" },
+	{ do_Debug_dump_active, "dump_active", "v", "", "\n"
+	    " void dump_active ()\n"
+	    "\n"
+	    " Dump out active memory usage.\n" },
 #endif
         { 0 }
     };
 
     static const struct fbuiltin_1 funcs_1[] = {
-        { do_Debug_dump, "dump", "v", "p" },
+        { do_Debug_dump, "dump", "v", "p", "\n"
+	    " void dump (poly f)\n"
+	    "\n"
+	    " Dump out bytecodes for function 'f'.\n" },
         { 0 }
     };
 
     static const struct fbuiltin_v funcs_v[] = {
-        { do_Thread_trace, "trace", "v", ".p" },
+        { do_Thread_trace, "trace", "v", ".p", "\n"
+	    " void trace ()\n"
+	    " void trace (continuation c)\n"
+	    " void trace (thread t)\n"
+	    " void trace (continuation c, int depth)\n"
+	    " void trace (thread t, int depth)\n"
+	    "\n"
+	    " Display a stack trace for a thread or continuation.\n"
+	    " While debugging, there is a default continuation of the\n"
+	    " thread being debugged.\n"
+	    " If 'depth' is not provided, it will show 20 frames.\n" },
         { 0 }
     };
 

Index: builtin-environ.c
===================================================================
RCS file: /local/src/CVS/nickle/builtin-environ.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- a/builtin-environ.c	16 Apr 2004 21:41:52 -0000	1.5
+++ b/builtin-environ.c	8 Jun 2004 09:30:53 -0000	1.6
@@ -24,14 +24,29 @@
 {
     ENTER ();
     static const struct fbuiltin_1 funcs_1[] = {
-        { do_Environ_check, "check", "b", "s" },
-        { do_Environ_get, "get", "s", "s" },
-        { do_Environ_unset, "unset", "b", "s" },
+        { do_Environ_check, "check", "b", "s", "\n"
+	    " bool check (string name)\n"
+	    "\n"
+	    " Test whether 'name' is in the environment\n" },
+        { do_Environ_get, "get", "s", "s", "\n"
+	    " string get (string name)\n"
+	    "\n"
+	    " Return a value from the environment.\n"
+	    " raise invalid_argument if 'name' isn't in the environment.\n" },
+        { do_Environ_unset, "unset", "b", "s", "\n"
+	    " bool unset (string name)\n"
+	    "\n"
+	    " Remove 'name' from the environment.\n"
+	    " Returns 'true' if 'name' was in the environment.\n" },
         { 0 }
     };
 
     static const struct fbuiltin_2 funcs_2[] = {
-        { do_Environ_set, "set", "b", "ss" },
+        { do_Environ_set, "set", "b", "ss", "\n"
+	    " bool set (string name, string value)\n"
+	    "\n"
+	    " Places 'name' with 'value' in the environment.\n"
+	    " Returns false if it didn't work for some reason.\n" },
         { 0 }
     };
 

Index: builtin-file.c
===================================================================
RCS file: /local/src/CVS/nickle/builtin-file.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- a/builtin-file.c	16 Apr 2004 21:41:52 -0000	1.16
+++ b/builtin-file.c	8 Jun 2004 09:30:53 -0000	1.17
@@ -19,61 +19,167 @@
 
 NamespacePtr FileNamespace;
 
-struct ebuiltin {
-    char		*name;
-    StandardException	exception;
-    char		*args;
-};
-
-
 void
 import_File_namespace()
 {
     ENTER ();
     static const struct fbuiltin_0 funcs_0[] = {
-        { do_File_string_write, "string_write", "f", "" },
-	{ do_File_mkpipe, "mkpipe", "A*f", "" },
+        { do_File_string_write, "string_write", "f", "", "\n"
+	    " file string_write ()\n"
+	    "\n"
+	    " Returns a writable file which can be converted to\n"
+	    " a string with string_string.\n"
+	},
+	{ do_File_mkpipe, "mkpipe", "A*f", "", "\n"
+	    " file[*] mkpipe ()\n"
+	    "\n"
+	    " Returns an array of two file objects representing\n"
+	    " the endpoints of a pipe.\n"
+	    " Data written to [1] will be available for reading on [0].\n" },
         { 0 }
     };
 
     static const struct fbuiltin_1 funcs_1[] = {
-        { do_File_clear_error, "clear_error", "v", "f" },
-        { do_File_close, "close", "v", "f" },
-        { do_File_end, "end", "b", "f" },
-        { do_File_error, "error", "b", "f" },
-        { do_File_flush, "flush", "v", "f" },
-        { do_File_getb, "getb", "i", "f" },
-	{ do_File_getc, "getc", "i", "f" },
-        { do_File_string_read, "string_read", "f", "s" },
-        { do_File_string_string, "string_string", "s", "f" },
-	{ do_File_isatty, "isatty", "b", "f" },
+        { do_File_clear_error, "clear_error", "v", "f", "\n"
+	    " void clear_error (file f)\n"
+	    "\n"
+	    " Clear any error or end-of-file condition on 'f'.\n" },
+        { do_File_close, "close", "v", "f", "\n"
+	    " void close (file f)\n"
+	    "\n"
+	    " Close 'f'.  Note that files will automatically be closed\n"
+	    " at some point after they become unreachable.  This function\n"
+	    " simply provides a mechanism for causing it to happen at\n"
+	    " a specific point in time.\n" },
+        { do_File_end, "end", "b", "f", "\n"
+	    " bool end (file f)\n"
+	    "\n"
+	    " Returns true if 'f' is at the end of file.\n"
+	    " This often entails attempting to read a character from 'f'\n"
+	    " if the end has not already been discovered.\n" },
+        { do_File_error, "error", "b", "f", "\n"
+	    " bool error (file f)\n"
+	    "\n"
+	    " Returns true if 'f' has an error condition set.\n" },
+        { do_File_flush, "flush", "v", "f", "\n"
+	    " void flush (file f)\n"
+	    "\n"
+	    " Force any pending output to be delivered to the OS.\n" },
+        { do_File_getb, "getb", "i", "f", "\n"
+	    " int getb (file f)\n"
+	    "\n"
+	    " Return the next byte of data from 'f'.\n" },
+	{ do_File_getc, "getc", "i", "f", "\n"
+	    " int getc (file f)\n"
+	    "\n"
+	    " Return the next character from 'f'.\n" },
+        { do_File_string_read, "string_read", "f", "s", "\n"
+	    " file string_read (string s)\n"
+	    "\n"
+	    " Create a file which when read will return successive"
+	    " characters from 's'.\n" },
+        { do_File_string_string, "string_string", "s", "f", "\n"
+	    " string string_string (file f)\n"
+	    "\n"
+	    " Returns the contents 'f', which must be a file that was\n"
+	    " created with string_write.\n" },
+	{ do_File_isatty, "isatty", "b", "f", "\n"
+	    " bool isatty (file f)\n"
+	    "\n"
+	    " Return whether 'f' is associated with an interactive\n"
+	    " terminal device\n" },
         { 0 }
     };
 
     static const struct fbuiltin_2 funcs_2[] = {
-        { do_File_open, "open", "f", "ss" },
-        { do_File_putb, "putb", "i", "if" },
-	{ do_File_putc, "putc", "i", "if" },
-        { do_File_setbuf, "setbuffer", "i", "fi" },
-        { do_File_ungetb, "ungetb", "i", "if" },
-	{ do_File_ungetc, "ungetc", "i", "if" },
+        { do_File_open, "open", "f", "ss", "\n"
+	    " file open (string name, string mode)\n"
+	    "\n"
+	    " Open file 'name' where 'mode' is one of:\n"
+	    "   \"r\":  read only\n"
+	    "   \"r+\": read-write\n"
+	    "   \"w\":  write only (created or truncated)\n"
+	    "   \"w+\": read-write (created or truncated)\n"
+	    "   \"a\":  write-only for appending (created if needed)\n"
+	    "   \"a+\": read-write for appending (created if needed)\n"
+	    " Raises open_error if the file cannot be opened.\n" },
+        { do_File_putb, "putb", "i", "if", "\n"
+	    " int putb (int b, file f)\n"
+	    "\n"
+	    " Write the byte 'b' to 'f'.\n" },
+	{ do_File_putc, "putc", "i", "if", "\n"
+	    " int putc (int c, file f)\n"
+	    "\n"
+	    " Write the character 'c' to 'f'.\n" },
+        { do_File_setbuf, "setbuffer", "i", "fi", "\n"
+	    " int setbuffer (file f, int mode)\n"
+	    "\n"
+	    " Change buffering of 'f' to 'mode', which is one of:\n"
+	    "   0:    normal block buffering.\n"
+	    "   1:    line buffering.\n"
+	    "   2:    unbuffered.\n"
+	    " Returns 'mode'.\n" },
+        { do_File_ungetb, "ungetb", "i", "if", "\n"
+	    " int ungetb (int b, file f)\n"
+	    "\n"
+	    " Pushes the byte 'b' back on file 'f'.\n" },
+	{ do_File_ungetc, "ungetc", "i", "if", "\n"
+	    " int ungetc (int c, file f)\n"
+	    "\n"
+	    " Pushes the character 'c' back on file 'f'.\n" },
         { 0 }
     };
 
     static const struct fbuiltin_3 funcs_3[] = {
-        { do_File_filter, "filter", "i", "sA*sA*f" },
-	{ do_File_reopen, "reopen", "f", "ssf" },
+        { do_File_filter, "filter", "i", "sA*sA*f", "\n"
+	    " int filter (string program, string[*] argv, file[3] f)\n"
+	    "\n"
+	    " Fork and execute 'program' using 'argv' for arguments and\n"
+	    " f as stdin, stdout and stderr (respectively).\n" },
+	{ do_File_reopen, "reopen", "f", "ssf", "\n"
+	    " file reopen (string name, string mode, file f)\n"
+	    "\n"
+	    " Change which file 'f' is associated with to 'name',\n"
+	    " opening it with 'mode' as in the open function.\n" },
         { 0 }
     };
 
     static const struct fbuiltin_7 funcs_7[] = {
-        { do_File_print, "print", "v", "fpsiiis" },
+        { do_File_print, "print", "v", "fpsiiis", "\n"
+	    " void print (file f, poly v, string format, int base,\n"
+	    "             int width, int precision, string fill)\n"
+	    "\n"
+	    " Print 'v' to 'f'.\n"
+	    " 'format' is one of:\n"
+	    "    \"v\":   Reparsable representation.\n"
+	    "    \"g\":   Human readable representation.\n"
+	    "    \"d\":   Integer portion of a number.\n"
+	    "    \"f\":   iii.fff format floating point.\n"
+	    "    \"e\":   i.fff'e'ee format floating point.\n"
+	    "    \"c\":   Integer printed as a character.\n"
+	    "    \"s\":   String printed without quotes.\n"
+	    " Any number will be represented using 'base' numerals.\n"
+	    " The output will be at most 'width' characters unless it\n"
+	    " won't fit in that size.\n"
+	    " Any decimal part will be limited to 'precision' characters.\n"
+	    " If 'precision' is -1, sufficient characters will be printed\n"
+	    " to precisely represent the number.\n"
+	    " Any extra characters will be filled with 'fill'.\n" },
         { 0 }
     };
 
     static const struct ebuiltin excepts[] = {
-	{"open_error",		exception_open_error,		"sEs" },
-	{"io_error",		exception_io_error,		"sEf" },
+	{"open_error",		exception_open_error,		"sEs", "\n"
+	    " open_error (string message, error_type error, string name)\n"
+	    "\n"
+	    " Raised when an open attempt fails.\n"
+	    " 'message' is a printable error string.\n"
+	    " 'error' is a symbolic error code.\n"
+	    " 'name' is the filename which failed.\n" },
+	{"io_error",		exception_io_error,		"sEf", "\n"
+	    " io_error (string message, error_type error, file f)\n"
+	    "\n"
+	    " Raised when an i/o error occurs.\n" },
 	{0,			0 },
     };
 
@@ -89,7 +195,7 @@
     BuiltinFuncs7 (&FileNamespace, funcs_7);
 
     for (e = excepts; e->name; e++)
-	BuiltinAddException (&FileNamespace, e->exception, e->name, e->args);
+	BuiltinAddException (&FileNamespace, e->exception, e->name, e->args, e->doc);
 
     s = NewSymbolType (AtomId("errorType"), typeFileError);
     NamespaceAddName (FileNamespace, s, publish_public);

Index: builtin-math.c
===================================================================
RCS file: /local/src/CVS/nickle/builtin-math.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- a/builtin-math.c	27 Feb 2004 03:50:15 -0000	1.10
+++ b/builtin-math.c	8 Jun 2004 09:30:53 -0000	1.11
@@ -24,12 +24,21 @@
 {
     ENTER ();
     static const struct fbuiltin_1 funcs_1[] = {
-        { do_Math_popcount, "popcount", "i", "i" },
+        { do_Math_popcount, "popcount", "i", "i", "\n"
+	    " int popcount (int i)\n"
+	    "\n"
+	    " Return the number of '1' bits in 'i'.\n" },
         { 0 }
     };
     static const struct fbuiltin_2 funcs_2[] = {
-        { do_Math_assignpow, "assign_pow", "n", "*Ri" },
-        { do_Math_pow, "pow", "n", "Ri" },
+        { do_Math_assignpow, "assign_pow", "n", "*Ri", "\n"
+	    " real assign_pow (*real a, int b)\n"
+	    "\n"
+	    " Return *a ** b, also storing that result back in *a.\n" },
+        { do_Math_pow, "pow", "n", "Ri", "\n"
+	    " real pow (real a, int b)\n"
+	    "\n"
+	    " Return a ** b.\n" },
         { 0 }
     };
 

Index: builtin-semaphore.c
===================================================================
RCS file: /local/src/CVS/nickle/builtin-semaphore.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- a/builtin-semaphore.c	27 Feb 2004 03:50:15 -0000	1.4
+++ b/builtin-semaphore.c	8 Jun 2004 09:30:53 -0000	1.5
@@ -24,14 +24,31 @@
 {
     ENTER ();
     static const struct fbuiltin_1 funcs_1[] = {
-        { do_Semaphore_signal, "signal", "v", "S" },
-        { do_Semaphore_test, "test", "b", "S" },
-        { do_Semaphore_wait, "wait", "v", "S" },
+        { do_Semaphore_signal, "signal", "v", "S", "\n"
+	    " void signal (semaphore s)\n"
+	    "\n"
+	    " Increment the count in 's' by one.\n"
+	    " If the count is <= 0, wakeup one thread waiting on 's'.\n" },
+        { do_Semaphore_test, "test", "b", "S", "\n"
+	    " bool test (semaphore s)\n"
+	    "\n"
+	    " Return false if a 'wait' call would block, else\n"
+	    " 'wait' on 's' and return true.\n" },
+        { do_Semaphore_wait, "wait", "v", "S", "\n"
+	    " void wait (semaphore s)\n"
+	    "\n"
+	    " Decrement the count in 's' by one.\n"
+	    " If the count is < 0, wait until awoken when 's' is signalled.\n" },
         { 0 }
     };
 
     static const struct fbuiltin_v funcs_v[] = {
-        { do_Semaphore_new, "new", "S", ".i" },
+        { do_Semaphore_new, "new", "S", ".i", "\n"
+	    " semaphore new ()\n"
+	    " semaphore new (int init)\n"
+	    "\n"
+	    " Create a new semaphore.\n"
+	    " Set the initial count to 'init' if provided, else 0.\n" },
         { 0 }
     };
 

Index: builtin-sockets.c
===================================================================
RCS file: /local/src/CVS/nickle/builtin-sockets.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- a/builtin-sockets.c	16 Apr 2004 21:41:52 -0000	1.14
+++ b/builtin-sockets.c	8 Jun 2004 09:30:53 -0000	1.15
@@ -47,26 +47,55 @@
     ENTER ();
 
     static const struct fbuiltin_0 funcs_0[] = {
-	{ do_Socket_gethostname, "gethostname", "s", "" },
+	{ do_Socket_gethostname, "gethostname", "s", "", "\n"
+	    " string gethostname ()\n"
+	    "\n"
+	    " Get the current hostname.\n" },
 	{ 0 },
     };
 
     static const struct fbuiltin_1 funcs_1[] = {
-        { do_Socket_create, "create", "f", "i" },
-        { do_Socket_accept, "accept", "f", "f" },
-	{ do_Socket_getsockname, "getsockname", "a", "f" },
+        { 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"
+	    " Return a socket for the next connection on 'listen'.\n" },
+	{ do_Socket_getsockname, "getsockname", "a", "f", "\n"
+	    " sockaddr getsockname (file socket)\n"
+	    "\n"
+	    " Returns the address and port of 'socket'.\n" },
         { 0 }
     };
 
     static const struct fbuiltin_2 funcs_2[] = {
-        { do_Socket_listen, "listen", "v", "fi" },
-        { do_Socket_shutdown, "shutdown", "v", "fi" },
+        { do_Socket_listen, "listen", "v", "fi", "\n"
+	    " void listen (file socket, int length)\n"
+	    "\n"
+	    " Establish a listen queue on 'f' of length 'i' (max 5).\n"	},
+        { do_Socket_shutdown, "shutdown", "v", "fi", "\n"
+	    " void shutdown (file socket, int dir)\n"
+	    "\n"
+	    " Shut communication in 'dir' direction:\n"
+	    "   SHUT_RD:    shut down reading.\n"
+	    "   SHUT_WR:    shut down writing.\n"
+	    "   SHUT_RDWR:  shut down reading and writing.\n" },
         { 0 }
     };
 
     static const struct fbuiltin_3 funcs_3[] = {
-        { do_Socket_connect, "connect", "v", "fss" },
-        { do_Socket_bind, "bind", "v", "fss" },
+        { do_Socket_connect, "connect", "v", "fss", "\n"
+	    " void connect (file socket, string host, string port)\n"
+	    "\n"
+	    " Connect 'socket' to 'host', 'port'.\n" },
+        { do_Socket_bind, "bind", "v", "fss", "\n"
+	    " void bind (file socket, string host, string port)\n"
+	    "\n"
+	    " Bind 'socket' to 'host', 'port'.\n" },
         { 0 }
     };
 

Index: builtin-string.c
===================================================================
RCS file: /local/src/CVS/nickle/builtin-string.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- a/builtin-string.c	16 Apr 2004 21:41:52 -0000	1.10
+++ b/builtin-string.c	8 Jun 2004 09:30:53 -0000	1.11
@@ -24,18 +24,35 @@
 {
     ENTER ();
     static const struct fbuiltin_1 funcs_1[] = {
-        { do_String_length, "length", "i", "s" },
-        { do_String_new, "new", "s", "p" },
+        { do_String_length, "length", "i", "s", "\n"
+	    " int length (string s)\n"
+	    "\n"
+	    " Return the number of characters in 's'.\n" },
+        { do_String_new, "new", "s", "p", "\n"
+	    " string new (int c)\n"
+	    " string new (int[*] a)\n"
+	    "\n"
+	    " With 'c', return a single character string containing it.\n"
+	    " With 'a', return a string constructed from the list of\n"
+	    " characters in 'a'.\n" },
         { 0 }
     };
 
     static const struct fbuiltin_2 funcs_2[] = {
-        { do_String_index, "index", "i", "ss" },
+        { do_String_index, "index", "i", "ss", "\n"
+	    " int index (string str, string substr)\n"
+	    "\n"
+	    " Return the index of the first location of 'substr'\n"
+	    " within 'str', -1 if not found.\n" },
         { 0 }
     };
 
     static const struct fbuiltin_3 funcs_3[] = {
-        { do_String_substr, "substr", "s", "sii" },
+        { do_String_substr, "substr", "s", "sii", "\n" 
+	    " string substr (string str, int first, int len)\n"
+	    "\n"
+	    " Return a string containing characters in 'str' starting at\n"
+	    " 'first' for 'len' characters.\n" },
         { 0 }
     };
 

Index: builtin-thread.c
===================================================================
RCS file: /local/src/CVS/nickle/builtin-thread.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- a/builtin-thread.c	27 Feb 2004 03:50:15 -0000	1.4
+++ b/builtin-thread.c	8 Jun 2004 09:30:53 -0000	1.5
@@ -24,26 +24,54 @@
 {
     ENTER ();
     static const struct fbuiltin_0 funcs_0[] = {
-        { do_Thread_cont, "cont", "i", "" },
-        { do_Thread_current, "current", "t", "" },
-        { do_Thread_list, "list", "v", "" },
+        { do_Thread_cont, "cont", "i", "", "\n"
+	    " int cont ()\n"
+	    "\n"
+	    " Restarts any interrupted threads.\n" },
+        { do_Thread_current, "current", "t", "", "\n"
+	    " thread current ()\n"
+	    "\n"
+	    " Return the current thread\n" },
+        { do_Thread_list, "list", "v", "", "\n"
+	    " void list ()\n"
+	    "\n"
+	    " Display a list of the known threads.\n" },
         { 0 }
     };
 
     static const struct fbuiltin_1 funcs_1[] = {
-        { do_Thread_get_priority, "get_priority", "i", "t" },
-        { do_Thread_id_to_thread, "id_to_thread", "t", "i" },
-        { do_Thread_join, "join", "p", "t" },
+        { do_Thread_get_priority, "get_priority", "i", "t", "\n"
+	    " int get_priority (thread t)\n"
+	    "\n"
+	    " Return the scheduling priority for 't'.\n" },
+        { do_Thread_id_to_thread, "id_to_thread", "t", "i", "\n"
+	    " thread id_to_thread (int id)\n"
+	    "\n"
+	    " Return the thread identified by 'id'.\n" },
+        { do_Thread_join, "join", "p", "t", "\n"
+	    " poly join (thread t)\n"
+	    "\n"
+	    " Await the completion of 't' and return its return value.\n" },
         { 0 }
     };
 
     static const struct fbuiltin_2 funcs_2[] = {
-        { do_Thread_set_priority, "set_priority", "i", "ti" },
+        { do_Thread_set_priority, "set_priority", "i", "ti", "\n"
+	    " int set_priority (thread t, int priority)\n"
+	    "\n"
+	    " Set 't's scheduling priority to 'priority'.\n"
+	    " Return 'priority.\n" },
         { 0 }
     };
 
     static const struct fbuiltin_v funcs_v[] = {
-        { do_Thread_kill, "kill", "i", ".t" },
+        { do_Thread_kill, "kill", "i", ".t", "\n"
+	    " int kill (thread t ...)\n"
+	    "\n"
+	    " If no threads are provided, kill a thread being debugged.\n"
+	    " Otherwise, kill all of the threads provided.\n"
+	    " Return the number of threads killed that weren't already\n"
+	    " finished.\n" },
         { 0 }
     };
 

Index: builtin-toplevel.c
===================================================================
RCS file: /local/src/CVS/nickle/builtin-toplevel.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- a/builtin-toplevel.c	13 May 2004 21:16:52 -0000	1.25
+++ b/builtin-toplevel.c	8 Jun 2004 09:30:53 -0000	1.26
@@ -22,104 +22,226 @@
 {
     ENTER ();
     static const struct fbuiltin_0 funcs_0[] = {
-        { do_getbyte, "getbyte", "i", "" },
-        { do_time, "time", "i", "" },
-	{ do_hash_new, "hash_new", "Hpp", "" },
+        { do_time, "time", "i", "", "\n"
+	    " int time ()\n"
+	    "\n"
+	    " Return seconds since Jan 1, 1970 00:00 GMT\n" },
         { 0 }
     };
 
     static const struct fbuiltin_1 funcs_1[] = {
-        { do_abs, "abs", "n", "R" },
-        { do_bit_width, "bit_width", "i", "i" },
-        { do_ceil, "ceil", "i", "R" },
-        { do_denominator, "denominator", "i", "R" },
-        { do_dim, "dim", "i", "A*p" },
-        { do_dims, "dims", "A*i", "Ap" },
-        { do_exit, "exit", "v", "i" },
-        { do_exponent, "exponent", "i", "R" },
-        { do_floor, "floor", "i", "R" },
-	{ do_func_args, "func_args", "i", "p" },
-        { do_is_array, "is_array", "b", "p" },
-        { do_is_continuation, "is_continuation", "b", "p" },
-        { do_is_file, "is_file", "b", "p" },
-        { do_is_func, "is_func", "b", "p" },
-        { do_is_int, "is_int", "b", "p" },
-        { do_is_number, "is_number", "b", "p" },
-        { do_is_rational, "is_rational", "b", "p" },
-        { do_is_ref, "is_ref", "b", "p" },
-        { do_is_semaphore, "is_semaphore", "b", "p" },
-        { do_is_string, "is_string", "b", "p" },
-        { do_is_struct, "is_struct", "b", "p" },
-        { do_is_thread, "is_thread", "b", "p" },
-        { do_is_bool, "is_bool", "b", "p" },
-        { do_is_void, "is_void", "b", "p" },
-        { do_is_uninit, "is_uninit", "b", "*p" },
-        { do_mantissa, "mantissa", "r", "R" },
-        { do_numerator, "numerator", "i", "R" },
-        { do_precision, "precision", "i", "R" },
-        { do_profile, "profile", "b", "b" },
-        { do_putbyte, "putbyte", "i", "i" },
-        { do_reference, "reference", "*p", "p" },
-        { do_sign, "sign", "i", "R" },
-        { do_sleep, "sleep", "v", "i" },
-        { do_string_to_real, "string_to_real", "R", "s" },
-	{ do_hash, "hash", "i", "p" },
-	{ do_hash_keys, "hash_keys", "Ap", "Hpp" },
+        { do_abs, "abs", "R", "R", "\n"
+	    " real abs (real r)\n"
+	    "\n"
+	    " Return absolute value of 'r'.\n" },
+        { do_bit_width, "bit_width", "i", "i", "\n"
+	    " int bit_width (int i)\n"
+	    "\n"
+	    " Return width of binary representation of abs('i').\n" },
+        { do_ceil, "ceil", "i", "R", "\n"
+	    " int ceil (real r)\n"
+	    "\n"
+	    " Return the nearest integer no smaller than 'r'.\n" },
+        { do_denominator, "denominator", "i", "r",
+	    " int denominator (rational r)\n"
+	    "\n"
+	    " Return the denominator of 'r'\n" },
+        { do_dim, "dim", "i", "A*p", "\n"
+	    " int dim (poly[*] a)\n"
+	    "\n"
+	    " Return the dimension of 'a'.\n" },
+        { do_dims, "dims", "A*i", "Ap", "\n"
+	    " int[*] dims (poly[] a)\n"
+	    "\n"
+	    " Return an array containing the list of dimensions of 'a'.\n" },
+        { do_exit, "exit", "v", "i", "\n"
+	    " void exit (int i)\n"
+	    "\n"
+	    " Exit from the nickle environment with code 'i'.\n" },
+        { do_exponent, "exponent", "i", "R", "\n"
+	    " int exponent (real r)\n"
+	    "\n"
+	    " Return the exponent of the imprecise value 'r'.\n" },
+        { do_floor, "floor", "i", "R", "\n"
+	    " int floor (real r)\n"
+	    "\n"
+	    " Return the nearest integer no larger than 'r'.\n" },
+	{ do_func_args, "func_args", "i", "p", "\n"
+	    " int func_args (poly f)\n"
+	    "\n"
+	    " Return the number of arguments required by function 'f'.\n" },
+        { do_is_array, "is_array", "b", "p", "\n"
+	    " bool is_array (poly v)\n"
+	    "\n"
+	    " Return whether 'v' is an array value.\n" },
+        { do_is_continuation, "is_continuation", "b", "p" , "\n"
+	    " bool is_continuation (poly v)\n"
+	    "\n"
+	    " Return whether 'v' is an continuation value.\n" },
+        { do_is_file, "is_file", "b", "p" , "\n"
+	    " bool is_file (poly v)\n"
+	    "\n"
+	    " Return whether 'v' is an file value.\n" },
+        { do_is_func, "is_func", "b", "p" , "\n"
+	    " bool is_func (poly v)\n"
+	    "\n"
+	    " Return whether 'v' is an func value.\n" },
+        { do_is_int, "is_int", "b", "p" , "\n"
+	    " bool is_int (poly v)\n"
+	    "\n"
+	    " Return whether 'v' is an int value.\n" },
+        { do_is_number, "is_number", "b", "p" , "\n"
+	    " bool is_number (poly v)\n"
+	    "\n"
+	    " Return whether 'v' is an numeric value.\n" },
+        { do_is_rational, "is_rational", "b", "p" , "\n"
+	    " bool is_rational (poly v)\n"
+	    "\n"
+	    " Return whether 'v' is an rational value.\n" },
+        { do_is_ref, "is_ref", "b", "p" , "\n"
+	    " bool is_ref (poly v)\n"
+	    "\n"
+	    " Return whether 'v' is an ref value.\n" },
+        { do_is_semaphore, "is_semaphore", "b", "p" , "\n"
+	    " bool is_semaphore (poly v)\n"
+	    "\n"
+	    " Return whether 'v' is an semaphore value.\n" },
+        { do_is_string, "is_string", "b", "p" , "\n"
+	    " bool is_string (poly v)\n"
+	    "\n"
+	    " Return whether 'v' is an string value.\n" },
+        { do_is_struct, "is_struct", "b", "p" , "\n"
+	    " bool is_struct (poly v)\n"
+	    "\n"
+	    " Return whether 'v' is an struct value.\n" },
+        { do_is_thread, "is_thread", "b", "p" , "\n"
+	    " bool is_thread (poly v)\n"
+	    "\n"
+	    " Return whether 'v' is an thread value.\n" },
+        { do_is_bool, "is_bool", "b", "p" , "\n"
+	    " bool is_bool (poly v)\n"
+	    "\n"
+	    " Return whether 'v' is an bool value.\n" },
+        { do_is_void, "is_void", "b", "p" , "\n"
+	    " bool is_void (poly v)\n"
+	    "\n"
+	    " Return whether 'v' is an void value.\n" },
+        { do_is_uninit, "is_uninit", "b", "*p", "\n"
+	    " bool is_uninit (*poly r)\n"
+	    "\n"
+	    " Return whether 'r' references uninitialized storage.\n" },
+        { do_mantissa, "mantissa", "r", "R", "\n"
+	    " rational mantissa (real r)\n"
+	    "\n"
+	    " Return the mantissa of 'r' as a rational between 0 and 1.\n" },
+        { do_numerator, "numerator", "i", "r", "\n"
+	    " int numerator (rational r)\n"
+	    "\n"
+	    " Return the numerator of 'r'.\n" },
+        { do_precision, "precision", "i", "R", "\n"
+	    " int precision (real r)\n"
+	    "\n"
+	    " Return the number of bits in the\n"
+	    " representation of the mantissa of 'r'.\n"	},
+        { do_profile, "profile", "b", "b", "\n"
+	    " bool profile (bool enable)\n"
+	    "\n"
+	    " Set profiling on/off.\n"
+	    " Returns previous profiling state.\n" },
+        { do_reference, "reference", "*p", "p", "\n"
+	    " *poly reference (poly value)\n"
+	    "\n"
+	    " Returns &value.\n" },
+        { do_sign, "sign", "i", "R", "\n"
+	    " int sign (real r)\n"
+	    " Return -1, 0, 1 for negative, zero or positive 'r'.\n" },
+        { do_sleep, "sleep", "v", "i", "\n"
+	    " void sleep (int milliseconds)\n"
+	    "\n"
+	    " Pause thread execution for 'milliseconds'.\n" },
+        { do_string_to_real, "string_to_real", "R", "s", "\n"
+	    " real string_to_real (string s)\n"
+	    "\n"
+	    " Parse a string representation of a numeric value.\n" },
+	{ do_hash, "hash", "i", "p", "\n"
+	    " int hash (poly p)\n"
+	    "\n"
+	    " Return an integer based on 'p' such that any value equal\n"
+	    " to 'p' will return the same integer.\n" },
+	{ do_hash_keys, "hash_keys", "Ap", "Hpp", "\n"
+	    " poly[] hash_keys (poly[poly] h)\n"
+	    "\n"
+	    " Return an array containing all of the key in 'h'.\n"
+	    " The order within the array is undefined.\n" },
         { 0 }
     };
 
     static const struct fbuiltin_2 funcs_2[] = {
-        { do_gcd, "gcd", "i", "ii" },
-        { do_setjmp, "setjmp", "p", "*cp" },
-        { do_xor, "xor", "i", "ii" },
-	{ do_setdims, "setdims", "v", "ApAi" },
-	{ do_setdim, "setdim", "v", "Api" },
-	{ do_hash_get, "hash_get", "p", "Hppp" },
-	{ do_hash_del, "hash_del", "v", "Hppp" },
-	{ do_hash_test, "hash_test", "b", "Hppp" },
+        { do_gcd, "gcd", "i", "ii", "\n"
+	    " int gcd (int a, int b)\n"
+	    "\n"
+	    " Return the greatest common divisor of 'a' and 'b'.\n" },
+        { do_setjmp, "setjmp", "p", "*cp", "\n"
+	    " poly setjmp (*continuation c, poly v)\n"
+	    "\n"
+	    " On direct invocation, create a continuation and store\n"
+	    " that in *'c'.  Then return 'v'.\n"
+	    " Subsequent invocations of longjmp with *'c' will appear\n"
+	    " to return from 'setjmp' with the value passed to longjmp.\n" },
+	{ do_setdims, "setdims", "v", "ApA*i", "\n"
+	    " void setdims (poly[] a, int[*] dimensions)\n"
+	    "\n"
+	    " Set the dimensions of resizable array 'a' to 'dimensions'.\n"
+	    " dim(dimensionss) must be the same as dim(dims(a)).\n" },
+	{ do_setdim, "setdim", "v", "A.pi", "\n"
+	    " void setdim (poly[...] a, int dimension)\n"
+	    "\n"
+	    " Set the dimension of 'a' to 'dimension'.\n" },
+	{ do_hash_del, "hash_del", "v", "Hppp", "\n"
+	    " void hash_del (poly[poly] h, poly key)\n"
+	    "\n"
+	    " Delete any hash value in 'h' associated with 'key'.\n" },
+	{ do_hash_test, "hash_test", "b", "Hppp", "\n"
+	    " bool hash_test (poly[poly] h, poly key)\n"
+	    "\n"
+	    " Return whether 'h' contains 'key'.\n" },
         { 0 }
     };
 
     static const struct fbuiltin_2j funcs_2j[] = {
-        { do_longjmp, "longjmp", "p", "cp" },
+        { do_longjmp, "longjmp", "v", "cp", "\n"
+	    " void longjmp (continuation c, poly v)\n"
+	    "\n"
+	    " Relocate execution to that saved in 'c', making the\n"
+	    " setjmp call there appear to return 'v'.\n" },
         { 0 }
     };
 
-    static const struct fbuiltin_3 funcs_3[] = {
-	{ do_hash_set, "hash_set", "v", "Hpppp" },
-	{ 0 }
-    };
-
     static const struct fbuiltin_v funcs_v[] = {
-        { do_imprecise, "imprecise", "R", "R.i" },
-        { do_string_to_integer, "string_to_integer", "i", "s.i" },
+        { do_imprecise, "imprecise", "R", "R.i", "\n"
+	    " real imprecise (real r)\n"
+	    " real imprecise (real r, int precision)\n"
+	    "\n"
+	    " Return an imprecise number.\n"
+	    " The precision will be 'precision' if supplied, else 256.\n" },
+        { do_string_to_integer, "string_to_integer", "i", "s.i", "\n"
+	    " int string_to_integer (string s)\n"
+	    " int string_to_integer (string s, int base)\n"
+	    "\n"
+	    " Parse 's' as an integer.\n"
+	    " Use 'base' if supplied, else autodetect.\n" },
         { 0 }
     };
 
     BuiltinFuncs0 (/*parent*/ 0, funcs_0);
     BuiltinFuncs1 (/*parent*/ 0, funcs_1);
     BuiltinFuncs2 (/*parent*/ 0, funcs_2);
-    BuiltinFuncs3 (/*parent*/ 0, funcs_3);
     BuiltinFuncs2J (/*parent*/ 0, funcs_2j);
     BuiltinFuncsV (/*parent*/ 0, funcs_v);
     EXIT ();
 }
 
 Value 
-do_getbyte ()
-{
-    ENTER ();
-    RETURN (do_File_getb (FileStdin));
-}
-
-Value 
-do_putbyte (Value v)
-{
-    ENTER ();
-    RETURN (do_File_putb (v, FileStdout));
-}
-
-Value 
 do_gcd (Value a, Value b)
 {
     ENTER ();
@@ -127,13 +249,6 @@
 }
 
 Value
-do_xor (Value a, Value b)
-{
-    ENTER ();
-    RETURN (Lxor (a, b));
-}
-
-Value
 do_time (void)
 {
     ENTER ();
@@ -790,11 +905,6 @@
     return NewHash (False, typePoly, typePoly);
 }
 
-Value	do_hash_get (Value hv, Value key)
-{
-    return HashGet (hv, key);
-}
-
 Value	do_hash_del (Value hv, Value key)
 {
     HashDelete (hv, key);
@@ -811,8 +921,3 @@
     return HashKeys (hv);
 }
 
-Value	do_hash_set (Value hv, Value key, Value value)
-{
-    HashSet (hv, key, value);
-    return Void;
-}

Index: builtin.5c
===================================================================
RCS file: /local/src/CVS/nickle/builtin.5c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- a/builtin.5c	16 Apr 2004 07:46:02 -0000	1.7
+++ b/builtin.5c	8 Jun 2004 09:30:53 -0000	1.8
@@ -14,12 +14,23 @@
     if (Environ::check("NICKLEPATH"))
 	nickle_path = Environ::get("NICKLEPATH");
 
-    public bool lex_file (string name) {
+    public bool lex_file (string name) 
+	/*
+	 * Push the file 'name' into the lexer and read input
+	 * from there until exhausted.  Then return to the current
+	 * file.
+	 */
+    {
 	return Command::lex_input (File::open (name, "r"), name, false, false);
     }
 	
     /* currently just does ~ expansion */
-    public string glob(string filename) {
+    public string glob(string filename) 
+	/*
+	 * Expand any leading ~/ in 'filename' to the value of the
+	 * HOME environment variable and return the resulting string
+	 */
+    {
 	if (filename[0] == '~' && filename[1] == '/') {
 	    exception bad_glob();
 	    if (!Environ::check("HOME"))
@@ -53,7 +64,13 @@
 	return String::substr (path, i + 1, l - i - 1);
     }
     
-    public bool lex_library (string name) {
+    public bool lex_library (string name) 
+	/*
+	 * Search 'nickle_path' for the file 'name' and push any
+	 * found file into the lexer.  Returns whether any
+	 * file was found and read.
+	 */
+    {
 	for (string path = nickle_path;
 	     path != "";
 	     path = path_rest (path))
@@ -69,7 +86,11 @@
 	return false;
     }
     
-    public bool lex_string (string s) {
+    public bool lex_string (string s) 
+	/*
+	 * Push 's' into the lexer input stack
+	 */
+    {
 	return Command::lex_input (File::string_read (s), s, false, false);
     }
 

Index: builtin.c
===================================================================
RCS file: /local/src/CVS/nickle/builtin.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- a/builtin.c	26 May 2004 05:52:53 -0000	1.18
+++ b/builtin.c	8 Jun 2004 09:30:53 -0000	1.19
@@ -35,13 +35,6 @@
     NamespacePtr    *namespace;
 };
 
-struct ebuiltin {
-    char		*name;
-    StandardException	exception;
-    char		*args;
-    NamespacePtr	*namespace;
-};
-
 static const struct sbuiltin svars[] = {
     { "> ",	    "prompt" },
     { "+ ",	    "prompt2" },
@@ -80,14 +73,46 @@
 };
 
 static const struct ebuiltin excepts[] = {
-    {"uninitialized_value",	exception_uninitialized_value,	"s" },
-    {"invalid_argument",	exception_invalid_argument,	"sip" },
-    {"readonly_box",		exception_readonly_box,		"sp" },
-    {"invalid_array_bounds",	exception_invalid_array_bounds,	"spp" },
-    {"divide_by_zero",		exception_divide_by_zero,	"snn" },
-    {"invalid_struct_member",	exception_invalid_struct_member,"sps" },
-    {"invalid_binop_values",	exception_invalid_binop_values,	"spp" },
-    {"invalid_unop_value",	exception_invalid_unop_value,	"sp" },
+    {"uninitialized_value",	exception_uninitialized_value,	"s", "\n"
+	" uninitialized_value (string message)\n"
+	"\n"
+	" Attempting to fetch from uninitialized storage.\n"
+	" 'message' indicates the error context.\n" },
+    {"invalid_argument",	exception_invalid_argument,	"sip", "\n"
+	" invalid_argument (string message, int id, poly value)\n"
+	"\n"
+	" Function argument 'id' couldn't accept 'value'.\n"
+	" 'message' indicates the error context.\n" },
+    {"readonly_box",		exception_readonly_box,		"sp", "\n"
+	" readonly_box (string message, poly value)\n"
+	"\n"
+	" Attempting to store 'value' in const storage.\n"
+	" 'message' indicates the error context.\n" },
+    {"invalid_array_bounds",	exception_invalid_array_bounds,	"spp", "\n"
+	" invalid_array_bounds (string message, poly box, poly index)\n"
+	"\n"
+	" Attempt to index outside of array or do pointer arithmetic\n"
+	" on a pointer not referencing an array.\n"
+	" 'message' indicates the error context.\n" },
+    {"divide_by_zero",		exception_divide_by_zero,	"sRR", "\n"
+	" divide_by_zero (string message, real num, real den)\n"
+	"\n"
+	" Division or modulus by zero.\n"
+	" 'message' indicates the error context.\n" },
+    {"invalid_struct_member",	exception_invalid_struct_member,"sps", "\n"
+	" invalid_struct_member (string message, poly struct, string member)\n"
+	"\n"
+	" 'member' is not in 'value'.\n" },
+    {"invalid_binop_values",	exception_invalid_binop_values,	"spp",
+	" invalid_binop_values (string message, poly left, poly right)\n"
+	"\n"
+	" 'left' and 'right' aren't compatible with a binary operator.\n"
+	" 'message' indicates which operator is problematic.\n" },
+    {"invalid_unop_value",	exception_invalid_unop_value,	"sp", "\n"
+	" invalid_unop_value (string message, poly value)\n"
+	"\n"
+	" 'value' isn't compatible with a unary operator.\n"
+	" 'message' indicates which operator is problematic.\n" },
     {0,				0 },
 };
 
@@ -123,6 +148,7 @@
     Bool    ref = False;
     Bool    array = False;
     Bool    hash = False;
+    Bool    resizable = False;
     Expr    *dims = 0;
     Type    *k;
     
@@ -136,8 +162,10 @@
     {
 	array = True;
 	format++;
-	while (*format == '*')
+	while (*format == '*' || *format == '.')
 	{
+	    if (*format == '.')
+		resizable = True;
 	    dims = NewExprComma (0, dims);
 	    format++;
 	}
@@ -171,7 +199,7 @@
     if (ref)
 	t = NewTypeRef (t, False);
     if (array)
-	t = NewTypeArray (t, dims, False);
+	t = NewTypeArray (t, dims, resizable);
     if (hash)
 	t = NewTypeHash (t, k);
     *type = t;
@@ -222,18 +250,23 @@
 SymbolPtr
 BuiltinException (NamespacePtr  *namespacep,
 		  char		*string,
-		  Type		*type)
+		  Type		*type,
+		  char		*doc)
 {
     ENTER ();
+    Value   doc_value = doc ? NewStrString (doc) : Void;
+    
     RETURN (BuiltinAddName (namespacep, 
-			    NewSymbolException (AtomId (string), type)));
+			    NewSymbolException (AtomId (string),
+						type, doc_value)));
 }
 
 void
 BuiltinAddException (NamespacePtr	*namespacep, 
 		     StandardException	exception,
 		     char		*name,
-		     char		*format)
+		     char		*format,
+		     char		*doc)
 {
     ENTER ();
     SymbolPtr	sym;
@@ -243,14 +276,16 @@
 
     args = BuiltinArgType (format, &argc);
     type = NewTypeFunc (typePoly, args);
-    sym = BuiltinException (namespacep, name, NewTypeFunc (typePoly, args));
+    sym = BuiltinException (namespacep, name,
+			    NewTypeFunc (typePoly, args),
+			    doc);
     RegisterStandardException (exception, sym);
     EXIT ();
 }
 
 void
 BuiltinAddFunction (NamespacePtr *namespacep, char *name, char *ret_format,
-		    char *format, BuiltinFunc f, Bool jumping)
+		    char *format, BuiltinFunc f, Bool jumping, char *doc)
 {
     ENTER ();
     Value	func;
@@ -262,7 +297,7 @@
     args = BuiltinArgType (format, &argc);
     BuiltinType (ret_format, &ret);
     sym = BuiltinSymbol (namespacep, name, NewTypeFunc (ret, args));
-    func =  NewFunc (NewBuiltinCode (ret, args, argc, f, jumping), 0);
+    func =  NewFunc (NewBuiltinCode (ret, args, argc, f, jumping, doc), 0);
     BoxValueSet (sym->global.value, 0, func);
     EXIT ();
 }
@@ -347,7 +382,7 @@
 
     /* Import standard exceptions */
     for (e = excepts; e->name; e++)
-	BuiltinAddException (e->namespace, e->exception, e->name, e->args);
+	BuiltinAddException (0, e->exception, e->name, e->args, e->doc);
 
     EXIT ();
 }

Index: builtin.h
===================================================================
RCS file: /local/src/CVS/nickle/builtin.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- a/builtin.h	27 Feb 2004 03:50:15 -0000	1.8
+++ b/builtin.h	8 Jun 2004 09:30:53 -0000	1.9
@@ -30,17 +30,26 @@
 SymbolPtr
 BuiltinException (NamespacePtr  *namespacep,
 		  char		*string,
-		  Type		*type);
+		  Type		*type,
+		  char		*doc);
+
+struct ebuiltin {
+    char		*name;
+    StandardException	exception;
+    char		*args;
+    char		*doc;
+};
 
 void
 BuiltinAddException (NamespacePtr	*namespacep, 
 		     StandardException	exception,
 		     char		*name,
-		     char		*format);
+		     char		*format,
+		     char		*doc);
 
 void
 BuiltinAddFunction (NamespacePtr *namespacep, char *name, char *ret_format,
-		    char *format, BuiltinFunc f, Bool jumping);
+		    char *format, BuiltinFunc f, Bool jumping, char *doc);
 
 #define BuiltinFuncStructDef(stype, functype) \
     struct stype { \
@@ -48,13 +57,14 @@
         char *name; \
         char *ret; \
         char *args; \
+	char *doc; \
     }
 
 #define BuiltinFuncsGeneric(ns, funcs, stype, bitem, jump) do { \
     BuiltinFunc f; const struct stype *fi; \
     for (fi = (funcs); fi->name; fi++) { \
 	f.bitem = fi->func; \
-	BuiltinAddFunction ((ns), fi->name, fi->ret, fi->args, f, jump); \
+	BuiltinAddFunction ((ns), fi->name, fi->ret, fi->args, f, jump, fi->doc); \
     } } while (0)
 
 typedef Value (*fbuiltin_v_func) (int, Value *);

Index: command.5c
===================================================================
RCS file: /local/src/CVS/nickle/command.5c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- a/command.5c	1 Apr 2004 15:48:23 -0000	1.19
+++ b/command.5c	8 Jun 2004 09:30:53 -0000	1.20
@@ -5,7 +5,14 @@
      * interpreter
      */
     
-    public void display (poly v) {
+    public void display (poly v) 
+	/*
+	 * Used by the top-level read/eval/print loop.
+	 * For non-void 'v', 
+	 *   Prints out 'v' in the current default format.
+	 *   Inserts 'v' into the history.
+	 */
+    {
 	if (is_void (v))
 	    return;
 	History::insert (v);
@@ -13,7 +20,17 @@
 	putchar ('\n');
     }
 
-    public void display_base (poly v, int base) {
+    public void display_base (poly v, int base) 
+	/*
+	 * Used by the top-level read/eval/print loop
+	 * when '# base' is appended to an expression.
+	 * For non-void 'v',
+	 *  Prints out 'v' in 'base'.
+	 *  Inserts 'v' into the history.
+	 */
+    {
+	if (is_void (v))
+	    return;
 	History::insert (v);
 	File::print (stdout, v, "g", base, 0, -1, " ");
 	putchar ('\n');

Index: compile.c
===================================================================
RCS file: /local/src/CVS/nickle/compile.c,v
retrieving revision 1.154
retrieving revision 1.155
diff -u -d -r1.154 -r1.155
--- a/compile.c	26 May 2004 08:59:23 -0000	1.154
+++ b/compile.c	8 Jun 2004 09:30:53 -0000	1.155
@@ -1610,7 +1610,8 @@
      */
     lambda = NewExprCode (NewFuncCode (type,
 				       args,
-				       body),
+				       body,
+				       Void),
 			  0);
     obj = _CompileExpr (obj, lambda, True, stat, code);
     expr->tree.left->base.type = lambda->base.type;

Index: ctype.5c
===================================================================
RCS file: /local/src/CVS/nickle/ctype.5c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- a/ctype.5c	11 Sep 2002 09:01:30 -0000	1.2
+++ b/ctype.5c	8 Jun 2004 09:30:54 -0000	1.3
@@ -6,28 +6,35 @@
 
 namespace Ctype {
 
-    /*
-     * As with C ctype.h, things outside the ASCII range
-     * are not handled here.  Unlike C ctype.h, we handle
-     * this case cleanly.
-     */
-    public bool isascii(int ch) {
+    public bool isascii(int ch) 
+	/*
+	 * As with C ctype.h, things outside the ASCII range
+	 * are not handled here.  Unlike C ctype.h, we handle
+	 * this case cleanly.
+	 */
+    {
 	return ch >= 0 && ch <= 127;
     }
     
     /* The characteristic vector of sets of ASCII chars. */
     public typedef bool[128] charset;
 
-    /* Make a characteristic vector from a characteristic function. */
-    public charset make_charset(bool(int) cfun) {
+    public charset make_charset(bool(int) cfun) 
+	/*
+	 * Make a characteristic vector from a characteristic function. 
+	 */
+    {
 	charset result;
 	for (int i = 0; i < 128; i++)
 	    result[i] = cfun(i);
 	return result;
     }
 
-    /* Test whether a particular char is in a charset. */
-    public bool member(charset v, int ch) {
+    public bool member(charset v, int ch) 
+	/*
+	 * Test whether a particular char is in a charset. 
+	 */
+    {
 	return isascii(ch) && v[ch];
     }
 
@@ -38,7 +45,11 @@
      */
 
 
-    public bool isupper(int ch) {
+    public bool isupper(int ch) 
+	/*
+	 * Return whether 'ch' is uppercase.
+	 */
+    {
 	static bool cfun(int ch) {
 	    return ch >= 'A' && ch <= 'Z';
 	}
@@ -46,7 +57,11 @@
 	return member(v, ch);
     }
 
-    public bool islower(int ch) {
+    public bool islower(int ch) 
+	/*
+	 * Return whether 'ch' is lowercase.
+	 */
+    {
 	static bool cfun(int ch) {
 	    return ch >= 'a' && ch <= 'z';
 	}
@@ -54,7 +69,11 @@
 	return member(v, ch);
     }
 
-    public bool isdigit(int ch) {
+    public bool isdigit(int ch) 
+	/*
+	 * Return whether 'ch' is a digit
+	 */
+    {
 	static bool cfun(int ch) {
 	    return ch >= '0' && ch <= '9';
 	}
@@ -62,11 +81,19 @@
 	return member(v, ch);
     }
 
-    public bool isblank(int ch) {
+    public bool isblank(int ch) 
+	/*
+	 * Return whether 'ch' is a space or tab
+	 */
+    {
 	return ch == ' ' || ch == '\t';
     }
 
-    public bool iscntrl(int ch) {
+    public bool iscntrl(int ch)
+	/*
+	 * Return whether 'ch' is a control character
+	 */
+    {
 	static bool cfun(int ch) {
 	    return ch >= 0 && ch <= 31;
 	}
@@ -74,7 +101,11 @@
 	return member(v, ch);
     }
 
-    public bool isgraph(int ch) {
+    public bool isgraph(int ch) 
+	/*
+	 * Return whether 'ch' is a visible character
+	 */	
+    {
 	static bool cfun(int ch) {
 	    return ch > ' ' && ch < 127;
 	}
@@ -82,7 +113,11 @@
 	return member(v, ch);
     }
 
-    public bool isprint(int ch) {
+    public bool isprint(int ch) 
+	/*
+	 * Return whether 'ch' is a printable character
+	 */	
+    {
 	static bool cfun(int ch) {
 	    return ch >= ' ' && ch < 127;
 	}
@@ -90,7 +125,11 @@
 	return member(v, ch);
     }
 	
-    public bool isspace(int ch) {
+    public bool isspace(int ch)
+	/*
+	 * Return whether 'ch' is whitespace
+	 */	
+    {
 	static bool cfun(int ch) {
 	       int[*] sc = {' ', '\f', '\n', '\r', '\t', '\v'};
 	       for (int i = 0; i < dim(sc); i++)
@@ -102,7 +141,11 @@
 	return member(v, ch);
     }
 
-    public bool isalpha(int ch) {
+    public bool isalpha(int ch) 
+	/*
+	 * Return whether 'ch' is a latin letter
+	 */	
+    {
 	static bool cfun(int ch) {
 	    return islower(ch) || isupper(ch);
 	}
@@ -110,7 +153,11 @@
 	return member(v, ch);
     }
 
-    public bool isalnum(int ch) {
+    public bool isalnum(int ch)
+	/*
+	 * Return whether 'ch' is a letter or digit
+	 */
+    {
 	static bool cfun(int ch) {
 	    return isalpha(ch) || isdigit(ch);
 	}
@@ -118,7 +165,11 @@
 	return member(v, ch);
     }
     
-    public bool ispunct(int ch) {
+    public bool ispunct(int ch)
+	/*
+	 * Return whether 'ch' is punctuation
+	 */
+    {
 	static bool cfun(int ch) {
 	    return isgraph(ch) && !isalnum(ch);
 	}
@@ -126,19 +177,33 @@
 	return member(v, ch);
     }
 
-    public int tolower(int ch) {
+    public int tolower(int ch) 
+	/*
+	 * If 'ch' is upper case, return the lower case version
+	 * else return 'ch'
+	 */
+    {
 	if (isupper(ch))
 	    return ch - 'A' + 'a';
 	return ch;
     }
 
-    public int toupper(int ch) {
+    public int toupper(int ch) 
+	/*
+	 * If 'ch' is lower case, return the upper case version
+	 * else return 'ch'
+	 */
+    {
 	if (islower(ch))
 	    return ch - 'a' + 'A';
 	return ch;
     }
 
-    public bool isxdigit(int ch) {
+    public bool isxdigit(int ch) 
+	/*
+	 * Return whether 'ch' is a hexidecimal digit
+	 */
+    {
 	static bool cfun(int ch) {
 	    if (isdigit(ch))
 		return true;

Index: debug.c
===================================================================
RCS file: /local/src/CVS/nickle/debug.c,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -d -r1.33 -r1.34
--- a/debug.c	27 Feb 2004 03:50:15 -0000	1.33
+++ b/debug.c	8 Jun 2004 09:30:54 -0000	1.34
@@ -184,6 +184,14 @@
     ENTER ();
     CodePtr code;
     
+    if (!ValueIsFunc (f))
+    {
+	RaiseStandardException (exception_invalid_argument,
+				"dump: not a function",
+				1,
+				NewInt (0), f);
+	RETURN (Void);
+    }
     code = f->func.code;
     if (code->base.builtin)
     {
@@ -201,13 +209,6 @@
     RETURN (Void);
 }
 
-Value
-do_Debug_mem_collect (void)
-{
-    MemCollect ();
-    return Void;
-}
-
 #ifdef MEM_TRACE
 Value
 do_Debug_dump_active (void)

Index: file.5c
===================================================================
RCS file: /local/src/CVS/nickle/file.5c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- a/file.5c	13 Oct 2003 06:15:24 -0000	1.2
+++ b/file.5c	8 Jun 2004 09:30:54 -0000	1.3
@@ -15,7 +15,11 @@
     } childfd;
 
     /* this is what happens when you fork() */
-    public int mkchild(string path, string[*] argv, childfd fds ...) {
+    public int mkchild(string path, string[*] argv, childfd fds ...) 
+	/*
+	 * Call filter transforming 'fds' into an array of three files
+	 */
+    {
 	file[3] filter_fds = { stdnull, ... };
 	for (int i = 0; i < dim(fds); i++) {
 	    union switch(fds[i]) {
@@ -30,21 +34,50 @@
     public namespace FileGlobals {
 
 	public int getchar ()
+	    /*
+	     * return getc (stdin);
+	     */
 	{
 	    return File::getc (stdin);
 	}
 
 	public void ungetchar (int ch)
+	    /*
+	     * return ungetc (ch, stdin);
+	     */
 	{
 	    File::ungetc (ch, stdin);
 	}
 
 	public void putchar (int c)
+	    /*
+	     * return putc (c, stdout)
+	     */
 	{
 	    putc (c, stdout);
 	}
 
+	public int getbyte ()
+	    /*
+	     * return getb (stdin);
+	     */
+	{
+	    return File::getb (stdin);
+	}
+
+	public void putbyte (int b)
+	    /*
+	     * return putb (b, stdout);
+	     */
+	{
+	    File::putb (b, stdout);
+	}
+
 	public string fgets (file f)
+	    /*
+	     * Return a line from 'f' as a string.
+	     * The trailing newline will be stripped off.
+	     */
 	{
 	    string	s;
 	    int	c;
@@ -64,6 +97,9 @@
 	}
 
 	public string gets ()
+	    /*
+	     * return fgets (stdin);
+	     */
 	{
 	    return fgets (stdin);
 	}

Index: file.c
===================================================================
RCS file: /local/src/CVS/nickle/file.c,v
retrieving revision 1.63
retrieving revision 1.64
diff -u -d -r1.63 -r1.64
--- a/file.c	16 Apr 2004 21:41:52 -0000	1.63
+++ b/file.c	8 Jun 2004 09:30:54 -0000	1.64
@@ -686,7 +686,7 @@
 	}
 	else
 	    oflags = 1;
-	oflags |= O_TRUNC|O_CREAT|O_APPEND;
+	oflags |= O_CREAT|O_APPEND;
 	flags |= FileWritable;
 	break;
     }

Index: func.c
===================================================================
RCS file: /local/src/CVS/nickle/func.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- a/func.c	27 Feb 2004 03:50:16 -0000	1.22
+++ b/func.c	8 Jun 2004 09:30:54 -0000	1.23
@@ -14,6 +14,7 @@
 
     MemReference (fc->base.type);
     MemReference (fc->base.args);
+    MemReference (fc->base.doc);
     MemReference (fc->code);
     MemReference (fc->body.obj);
     MemReference (fc->body.dynamics);
@@ -37,7 +38,7 @@
 }
 
 CodePtr
-NewFuncCode (Type *type, ArgType *args, ExprPtr code)
+NewFuncCode (Type *type, ArgType *args, ExprPtr code, Value doc)
 {
     ENTER ();
     CodePtr	fc;
@@ -51,6 +52,7 @@
     fc->base.name = 0;
     fc->base.previous = 0;
     fc->base.func = fc;
+    fc->base.doc = doc;
     
     fc->func.code = code;
     
@@ -71,13 +73,14 @@
 
     MemReference (bc->base.type);
     MemReference (bc->base.args);
+    MemReference (bc->base.doc);
 }
 
 DataType BuiltinCodeType = { MarkBuiltinCode, 0, "BuiltinCodeType" };
 
 CodePtr
 NewBuiltinCode (Type *type, ArgType *args, int argc, 
-		BuiltinFunc builtin, Bool needsNext)
+		BuiltinFunc builtin, Bool needsNext, char *doc)
 {
     ENTER ();
     CodePtr bc;
@@ -90,6 +93,7 @@
     bc->base.args = args;
     bc->base.name = 0;
     bc->base.previous = 0;
+    bc->base.doc = doc ? NewStrString (doc) : Void;
     
     bc->builtin.needsNext = needsNext;
     bc->builtin.b = builtin;

Index: gram.y
===================================================================
RCS file: /local/src/CVS/nickle/gram.y,v
retrieving revision 1.134
retrieving revision 1.135
diff -u -d -r1.134 -r1.135
--- a/gram.y	3 Jun 2004 07:46:23 -0000	1.134
+++ b/gram.y	8 Jun 2004 09:30:54 -0000	1.135
@@ -58,6 +58,7 @@
  */
 int ignorenl;
 int notCommand;
+int seeComment;
 NamespacePtr	LexNamespace;
 int funcDepth;
 
@@ -139,6 +140,7 @@
 %type  <expr>	    comma_expr
 %type  <ints>	    assignop
 %type  <value>	    opt_integer integer
+%type  <value>	    doc_string opt_comment
 %type  <expr>	    opt_arrayinit arrayinit arrayelts  arrayelt
 %type  <expr>	    opt_hashinit hashinit hashelts hashelt hashvalue
 %type  <expr>	    structinit structelts structelt
@@ -161,6 +163,7 @@
 %token <value>	    TEN_NUM OCTAL0_NUM OCTAL_NUM BINARY_NUM HEX_NUM
 %token <value>	    TEN_FLOAT OCTAL0_FLOAT OCTAL_FLOAT BINARY_FLOAT HEX_FLOAT
 %token <value>	    CHAR_CONST STRING_CONST POLY_CONST THREAD_CONST
+%token <value>	    COMMENT_CONST
 %token <value>	    VOIDVAL BOOLVAL
 %token		    DARROW
 
@@ -481,7 +484,7 @@
 		| block
 		| SEMI
 		    { $$ = NewExprTree(SEMI, (Expr *) 0, (Expr *) 0); }
-		| func_decl opt_func_body namespace_end
+		| func_decl doc_string opt_func_body namespace_end
 		    { 
 			DeclList    *decl = $1.decl;
 			SymbolPtr   symbol = decl->symbol;
@@ -493,12 +496,13 @@
 
 			if (symbol)
 			{
-			    if ($2)
+			    if ($3)
 			    {
 				symbol->symbol.forward = False;
 				ParseCanonType (ret, False);
 				decl->init = NewExprCode (NewFuncCode (ret,
 								       argType,
+								       $3,
 								       $2),
 							  NewExprAtom (symbol->symbol.name, symbol, False));
 			    }
@@ -507,7 +511,7 @@
 			}
 			$$ = NewExprDecl (FUNC, decl, class, type, publish);
 		    }
-		| opt_publish EXCEPTION ignorenl NAME namespace_start opt_argdecls namespace_end SEMI attendnl
+		| opt_publish EXCEPTION ignorenl NAME namespace_start opt_argdecls namespace_end doc_string SEMI attendnl
 		    { 
 			DeclListPtr decl;
 
@@ -515,6 +519,7 @@
 			decl->symbol = ParseNewSymbol ($1, 
 						       class_exception, 
 						       typePoly, $4);
+			decl->symbol->exception.doc = $8;
 			$$ = NewExprDecl (EXCEPTION,
 					  decl,
 					  class_exception,
@@ -641,8 +646,11 @@
 		|   
 		    { $$ = 0; }
 		;
-catch		: CATCH fullname namespace_start args block namespace_end
-		    { $$ = NewExprCode (NewFuncCode (typePrim[rep_void], $4, $5), $2); }
+catch		: CATCH fullname namespace_start args doc_string block namespace_end
+		    { $$ = NewExprCode (NewFuncCode (typePrim[rep_void],
+						     $4, $6, $5),
+					$2); 
+		    }
 		;
 opt_func_body	: func_body
 		| SEMI
@@ -659,6 +667,16 @@
 					  NewExprTree (OC, 0, 0));
 		    }
 		;
+see_comment	:
+		    { seeComment = 1; }
+		;
+doc_string	: see_comment opt_comment 
+		    { seeComment = 0; $$ = $2; }
+		;
+opt_comment	: COMMENT_CONST
+		|
+		    { $$ = Void; }
+		;
 case_block	: block_start cases block_end
 		    { $$ = $2; }
 		;
@@ -1204,10 +1222,10 @@
 			    $$ = NewExprTree($2, $1, $3); 
 			}
 		    }
-		| opt_type FUNC namespace_start args func_right namespace_end	    	%prec ASSIGN
+		| opt_type FUNC namespace_start args doc_string func_right namespace_end	    	%prec ASSIGN
 		    {
 			ParseCanonType ($1, False);
-			$$ = NewExprCode (NewFuncCode ($1, $4, $5), 0); 
+			$$ = NewExprCode (NewFuncCode ($1, $4, $6, $5), 0); 
 		    }
 		| MOD integer						%prec THREADID
 		    {   Value	t;
@@ -1940,7 +1958,7 @@
 	    s = NewSymbolAuto (name, type);
 	    break;
 	case class_exception:
-	    s = NewSymbolException (name, type);
+	    s = NewSymbolException (name, type, Void);
 	    break;
 	case class_typedef:
 	    /*

Index: history.5c
===================================================================
RCS file: /local/src/CVS/nickle/history.5c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- a/history.5c	14 Aug 2002 03:29:39 -0000	1.4
+++ b/history.5c	8 Jun 2004 09:30:54 -0000	1.5
@@ -6,56 +6,39 @@
  */
 
 namespace History {
-    typedef listrec;
-
-    typedef union {
-	*listrec    ref;
-	void	    end;
-    } list;
-
-    typedef struct {
-	poly	value;
-	list	next;
-    } listrec;
-
-    list   head = list.end;
-    int	    count = 0;
-    *list  tail = &head;
+    
+    poly[...]	hist = {};
     
     public void insert (poly v)
+	/*
+	 * Insert 'v' in the history list
+	 */
     {
-	if (is_void (v))
-	    return;
-	list	new = (list.ref) reference ((listrec) { 
-	    next = list.end,
-	    value = v });
-	*tail = new;
-	tail = &new.ref->next;
-	++count;
-    }
-
-    list elt (list l, int id)
-    {
-	if (id <= 0) return l;
-	return elt (l.ref->next, id-1);
+	hist[dim(hist)] = v;
     }
 
     public poly fetch (int id)
+	/*
+	 * Fetch history element 'id'
+	 */
     {
-	if (count == 0)
+	if (dim(hist) == 0)
 	    return <>;
 	if (id <= 0)
-	    return elt (head, count+id-1).ref->value;
+	    return hist[dim(hist)+id-1];
 	else
-	    return elt (head, id-1).ref->value;
+	    return hist[id-1];
     }
 
     public void show (string format, int args...)
+	/*
+	 * show history elements
+	 */
     {
-	int	from = 10, to = count;
-	list	f, t;
+	int	from = 10, to = dim(hist);
+	int	id;
 	
-	if (count == 0)
+	if (dim(hist) == 0)
 	    return;
 
 	if (dim(args) >= 1)
@@ -65,18 +48,15 @@
 	    to = args[1];
 	else
 	{
-	    from = count - from;
+	    from = dim(hist) - from;
 	    if (from < 1)
 		from = 1;
 	}
-	f = elt (head, from - 1);
-	t = elt (head, to - 1).ref->next;
-	while (f != t)
+	for (id = from; id <= to; id++)
 	{
 	    printf ("$%-4d\t", from);
-	    printf (format, f.ref->value);
+	    printf (format, fetch (id));
 	    printf ("\n");
-	    f = f.ref->next;
 	    from++;
 	}
     }

Index: lex.l
===================================================================
RCS file: /local/src/CVS/nickle/lex.l,v
retrieving revision 1.74
retrieving revision 1.75
diff -u -d -r1.74 -r1.75
--- a/lex.l	3 Jun 2004 06:55:24 -0000	1.74
+++ b/lex.l	8 Jun 2004 09:30:54 -0000	1.75
@@ -31,6 +31,7 @@
 LexInput    *lexInput;
 extern int  ignorenl;
 extern int  notCommand;
+extern int  seeComment;
 #define	    FILE_END_CHAR	-2
     
 static void lexInputMark (void *object)
@@ -292,7 +293,15 @@
 
 %}
 %%
-"/\052"		skipcomment();
+"/\052"		{   
+		    if (seeComment) 
+		    {
+			yylval.value = lexdoc ();
+			return COMMENT_CONST;
+		    }
+		    else
+			skipcomment (); 
+		}
 ^[ \t]*#	skipline();
 auto		{ yylval.class = class_auto; return AUTO; }
 const		{ yylval.class = class_const; return CONST; }
@@ -609,6 +618,45 @@
     }
 }
 
+
+Value
+lexdoc (void)
+{
+    int	    c;
+    Value   s = NewStrString ("");
+
+    c = input();
+    if (lexInput->at_eof)
+    {
+bail:	
+        yyerror ("Missing */ at end of file");
+        return Void;
+    }
+    for (;;) {
+	Bool skip = False;
+	while (c != EOF && c != '*')
+	{
+	    if (skip && c != ' ' && c != '\t')
+		skip = False;
+	    if (!skip)
+		s = Plus (s, NewCharString (c));
+	    if (c == '\n')
+		skip = True;
+	    c = input();
+	    if (c == EOF || lexInput->at_eof)
+		goto bail;
+	}
+	c = input();
+	if (c == EOF || lexInput->at_eof)
+	    goto bail;
+	if (c == '/')
+	    break;
+	if (!skip)
+	    s = Plus (s, NewCharString ('*'));
+    }
+    return s;
+}
+
 void
 skipcomment (void)
 {

Index: math.5c
===================================================================
RCS file: /local/src/CVS/nickle/math.5c,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -d -r1.38 -r1.39
--- a/math.5c	27 Feb 2004 05:05:18 -0000	1.38
+++ b/math.5c	8 Jun 2004 09:30:54 -0000	1.39
@@ -8,6 +8,10 @@
      256);
 
     public real sqrt (real v)
+	/*
+	 * Returns square root of v to the same precision as 'v'.
+	 * If v is precise and has a precise square root, returns that.
+	 */
     {
 	if (v < 0)
 	    raise invalid_argument ("sqrt of negative number", 0, v);
@@ -51,6 +55,10 @@
     }
 
     public real cbrt (real v)
+	/*
+	 * Returns cube root of v to the same precision as 'v'.
+	 * If v is precise and has a precise cube root, returns that.
+	 */
     {
 	real real_cbrt(real v)
 	{
@@ -94,6 +102,9 @@
     }
 
     public real exp (real v)
+	/*
+	 * Return e ** v;
+	 */
     {
 	if (v < 0)
 	    return 1/exp(-v);
@@ -151,6 +162,9 @@
     }
 
     public real log (real a)
+	/*
+	 * Return natural logarithm of 'a'
+	 */
     {
 	/*
 	 * Copyright (c) 1985 Regents of the University of California.
@@ -390,6 +404,9 @@
      * log10(e) = log(e) / log(10) = 1/log(10)
      */
     public real log10 (real a)
+	/*
+	 * Return base-10 log of 'a'
+	 */
     {
 	static real	loge = 0;
 
@@ -405,6 +422,9 @@
      * log2(e) = log(e) / log(2) = 1/log(2)
      */
     public real log2 (real a)
+	/*
+	 * Return base-2 log of 'a'
+	 */
     {
 	static real	loge = 0;
 
@@ -414,13 +434,12 @@
 	return loge * log(a);
     }
     
-    /*
-     * Calculate pi using the formula:
-     *
-     *  PI = 24*atan (1/8) + 8*atan (1/57) + 4*atan (1/239);
-     */
-    
     real calculate_pi (int prec)
+	/*
+	 * Calculate pi using the formula:
+	 *
+	 *  PI = 24*atan (1/8) + 8*atan (1/57) + 4*atan (1/239);
+	 */
     {
 	/*
 	 * Estimate the number of digits available for
@@ -513,6 +532,9 @@
     }
     
     public real pi_value (int prec)
+	/*
+	 * Return pi at least as precise as 'prec'
+	 */
     {
 	static real local_pi = pi;
     
@@ -533,6 +555,9 @@
     }
     
     public real sin (real a)
+	/*
+	 * return sine (a)
+	 */
     {
 	/*
 	 * sin(x) = x - x**3/3! + x**5/5! ... 
@@ -592,6 +617,9 @@
     }
 
     public real cos (real a)
+	/*
+	 * return cosine (a)
+	 */
     {
 	/*
 	 * cos(x) = 1 - x**2/2! + x**4/4! - x**6/6! ... 
@@ -653,6 +681,9 @@
     }
     
     public void sin_cos (real a, *real sinp, *real cosp)
+	/*
+	 * Compute sine and cosine of 'a' simultaneously
+	 */
     {
 	real	c, s;
 
@@ -664,6 +695,9 @@
     }
     
     public real tan (real a)
+	/*
+	 * return tangent (a)
+	 */
     {
 	real	c, s;
 
@@ -673,6 +707,9 @@
     }
     
     public real atan (real v)
+	/*
+	 * return arctangent (v)
+	 */
     {
 	/* 
 	 * atan(x) = x - x**3/3 + x**5/5 - ...
@@ -749,6 +786,9 @@
      */
     
     public real asin (real v)
+	/*
+	 * return arcsine (v)
+	 */
     {
 	v = imprecise (v);
 	if (abs (v) > 1)
@@ -767,6 +807,9 @@
      *		= atan (sqrt(1-v**2) / v)
      */
     public real acos (real v)
+	/*
+	 * return arccosine (v)
+	 */
     {
 	v = imprecise(v);
 	if (abs (v) > 1)
@@ -784,6 +827,9 @@
      * atan (y/x)
      */
     public real atan2 (real y, real x)
+	/*
+	 * return atan (y/x), but adjust for quadrant correctly
+	 */
     {
 	y = imprecise (y);
 	x = imprecise (x);
@@ -813,6 +859,9 @@
      * These two are used for the '**' and '**=' operators
      */
     public real pow (real a, real b)
+	/*
+	 * return a ** b;
+	 */
     {
 	real    result;
 	if (is_int (b))
@@ -852,18 +901,29 @@
     }
 
     public real assign_pow (*real a, real b)
+	/*
+	 * return *a = *a ** b;
+	 */
     {
 	return *a = pow (*a, b);
     }
 
-    public real max(real arg, real args ...) {
+    public real max(real arg, real args ...) 
+	/*
+	 * Return maximum of all arguments
+	 */
+    {
 	for (int i = 0; i < dim(args); i++)
 	    if (arg < args[i])
 		arg = args[i];
 	return arg;
     }
 
-    public real min(real arg, real args ...) {
+    public real min(real arg, real args ...)
+	/*
+	 * Return minimum of all arguments
+	 */
+    {
 	for (int i = 0; i < dim(args); i++)
 	    if (arg > args[i])
 		arg = args[i];
@@ -875,7 +935,12 @@
      * Fast integer logarithm via binary search from below (no division).
      * Returns floor(log(n)/log(base)) with no rounding error
      */
-    public int ilog(int base, int n) {
+    public int ilog(int base, int n) 
+	/*
+	 * Fast integer logarithm via binary search from below (no division).
+	 * Returns floor(log(n)/log(base)) with no rounding error
+	 */
+    {
 	if (base <= 1)
 	    raise invalid_argument("ilog of bad base", 0, base);
 	if (n <= 0)

Index: mutex.5c
===================================================================
RCS file: /local/src/CVS/nickle/mutex.5c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- a/mutex.5c	27 Jul 2002 00:03:34 -0000	1.8
+++ b/mutex.5c	8 Jun 2004 09:30:54 -0000	1.9
@@ -31,10 +31,19 @@
 
     public typedef *mutex_struct mutex;
 
-    public exception deadlock (mutex m, thread self);
-    public exception notowned (mutex m, thread self, mutex_owner owner);
+    public exception deadlock (mutex m, thread self)
+	/*
+	 * raised when attempting to lock a mutex locked by self
+	 */;
+    public exception notowned (mutex m, thread self, mutex_owner owner)
+	/*
+	 * raised when attempting to release a mutex which is not locked
+	 */;
 
     public bool acquire (mutex m)
+	/*
+	 * Lock 'm'
+	 */
     {
 	if (m->owner == (mutex_owner.owner) Thread::current())
 	    raise deadlock (m, Thread::current ());
@@ -44,6 +53,10 @@
     }
 
     public bool try_acquire (mutex m)
+	/*
+	 * If 'm' is unlocked, acquire (m) and return true
+	 * else return false
+	 */
     {
 	if (m->owner == (mutex_owner.owner) Thread::current())
 	    raise deadlock (m, Thread::current());
@@ -54,6 +67,9 @@
     }
 
     public void release (mutex m)
+	/*
+	 * Unlock 'm'
+	 */
     {
 	if (m->owner != (mutex_owner.owner) Thread::current())
 	    raise notowned (m, Thread::current (), m->owner);
@@ -62,11 +78,17 @@
     }
 
     public mutex_owner owner (mutex m)
+	/*
+	 * Return owner of 'm'
+	 */
     {
 	return m->owner;
     }
     
     public mutex new ()
+	/*
+	 * Create new (unlocked) mutex
+	 */
     {
 	return reference ((mutex_struct) { 
 	    sem = Semaphore::new (1),

Index: nickle.h
===================================================================
RCS file: /local/src/CVS/nickle/nickle.h,v
retrieving revision 1.117
retrieving revision 1.118
diff -u -d -r1.117 -r1.118
--- a/nickle.h	28 May 2004 02:58:14 -0000	1.117
+++ b/nickle.h	8 Jun 2004 09:30:54 -0000	1.118
@@ -47,6 +47,7 @@
 
 typedef struct _symbolException {
     SymbolBase	    symbol;
+    Value	    doc;
 } SymbolException;
 
 typedef union _symbol {
@@ -59,7 +60,7 @@
 } Symbol;
 
 extern SymbolPtr    NewSymbolType (Atom name, Type *type);
-extern SymbolPtr    NewSymbolException (Atom name, Type *type);
+extern SymbolPtr    NewSymbolException (Atom name, Type *type, Value doc);
 extern SymbolPtr    NewSymbolConst (Atom name, Type *type);
 extern SymbolPtr    NewSymbolGlobal (Atom name, Type *type);
 extern SymbolPtr    NewSymbolArg (Atom name, Type *type);
@@ -253,6 +254,7 @@
     ExprPtr	name;
     CodePtr	previous;
     CodePtr	func;	    /* function context, usually self */
+    Value	doc;	    /* documentation */
 } CodeBase;
 
 /*
@@ -340,9 +342,9 @@
     BuiltinCode	builtin;
 } Code;
 
-CodePtr	NewFuncCode (Type *type, ArgType *args, ExprPtr code);
+CodePtr	NewFuncCode (Type *type, ArgType *args, ExprPtr code, Value doc);
 CodePtr	NewBuiltinCode (Type *type, ArgType *args, int argc, 
-			BuiltinFunc func, Bool needsNext);
+			BuiltinFunc func, Bool needsNext, char *doc);
 Value	NewFunc (CodePtr, FramePtr);
 
 typedef struct _farJump {
@@ -711,6 +713,7 @@
 Value	atov (char *, int), aetov (char *, int);
 extern int  ignorenl;
 void	skipcomment (void);
+Value	lexdoc (void);
 void	skipline (void);
 int	lexEscape (int);
 
@@ -942,7 +945,6 @@
 Value	do_Thread_cont (void);
 Value	do_Thread_current (void);
 Value	do_Thread_list (void);
-Value	do_getbyte (void);
 Value	do_time (void);
 Value	do_File_string_write (void);
 Value	do_Debug_up (void);
@@ -953,7 +955,6 @@
 Value	do_File_mkpipe (void);
 
 /* one argument builtins */
-Value	do_putbyte (Value);
 Value	do_sleep (Value);
 Value	do_exit (Value);
 Value	do_dim (Value);
@@ -1010,7 +1011,6 @@
 Value	do_Primitive_srandom (Value);
 Value	do_Debug_dump (Value);
 Value	do_Debug_dump_active (void);
-Value	do_Debug_mem_collect (void);
 Value	do_Command_delete (Value);
 Value	do_Command_edit (Value);
 Value	do_Command_display (Value);

Index: parse-args.5c
===================================================================
RCS file: /local/src/CVS/nickle/parse-args.5c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- a/parse-args.5c	18 May 2004 06:26:03 -0000	1.1
+++ b/parse-args.5c	8 Jun 2004 09:30:54 -0000	1.2
@@ -50,14 +50,22 @@
     void print_options(&(arg[*]) a) {
     }
 
-    public string basename(string path) {
+    public string basename(string path) 
+	/*
+	 * Return the filename part of 'path'
+	 */
+    {
 	int p = rindex(path, "/");
 	if (p == -1)
 	    return path;
 	return substr(path, p + 1, length(path) - p - 1);
     }
 
-    public void parseargs(&argdesc argd, &(string[*]) argv) {
+    public void parseargs(&argdesc argd, &(string[*]) argv) 
+	/*
+	 * Parse arguments in 'argv' according to 'argd'
+	 */
+    {
 	argd.prog_name = basename(argv[0]);
 
 	arg[int] arg_abbr_hash = {};

Index: pretty.c
===================================================================
RCS file: /local/src/CVS/nickle/pretty.c,v
retrieving revision 1.69
retrieving revision 1.70
diff -u -d -r1.69 -r1.70
--- a/pretty.c	20 May 2004 09:51:55 -0000	1.69
+++ b/pretty.c	8 Jun 2004 09:30:54 -0000	1.70
@@ -47,6 +47,7 @@
 static void PrettyArrayInit (Value f, Expr *e, int level, Bool nest, ProfileData *pd);
 static void PrettyStatement (Value f, Expr *e, int level, int blevel, Bool nest, ProfileData *pd);
 static void PrettyBody (Value f, CodePtr code, int level, Bool nest, ProfileData *pd);
+static void PrettyDoc (Value f, int level, Value doc, ProfileData *pd);
 
 static void
 PrettyIndent (Value f, Expr *e, int level, ProfileData *pd)
@@ -817,16 +818,51 @@
 }
 
 static void
+PrettyDoc (Value f, int level, Value doc, ProfileData *pd)
+{
+    char	*s = StringChars (&doc->string);
+    long    	len = doc->string.length;
+    unsigned	c;
+    Bool	newline = False;
+
+    PrettyIndent (f, 0, level, pd);
+    FilePuts (f, "/""*");
+    while ((s = StringNextChar (s, &c, &len)))
+    {
+	if (newline)
+	{
+	    PrettyIndent (f, 0, level, pd);
+	    FilePuts (f, " *");
+	    newline = False;
+	}
+	FileOutput (f, c);
+	if (c == '\n')
+	    newline = True;
+    }
+    if (newline)
+    {
+	PrettyIndent (f, 0, level, pd);
+	FileOutput (f, ' ');
+    }
+    FilePuts (f, "*""/");
+}
+
+static void
 PrettyBody (Value f, CodePtr code, int level, Bool nest, ProfileData *pd)
 {
     PrintArgs (f, code->base.args);
-    if (code->base.builtin)
+    if (code->base.doc != Void)
     {
-	FilePuts (f, " <builtin>");
+	FilePuts (f, "\n");
+	PrettyDoc (f, level + 1, code->base.doc, pd);
     }
-    else
+    if (nest)
     {
-	if (nest)
+	if (code->base.builtin)
+	{
+	    FilePuts (f, " <builtin>");
+	}
+	else
 	{
 	    FilePuts (f, "\n");
 	    PrettyIndent (f, 0, level, pd);
@@ -835,9 +871,9 @@
 	    PrettyIndent (f, 0, level, pd);
 	    FilePuts (f, "}");
 	}
-	else
-	    FilePuts (f, ";");
     }
+    else
+	FilePuts (f, ";");
 }
 
 void
@@ -920,15 +956,26 @@
 	FilePuts (f, "\n");
 	break;
     case class_namespace:
-	FilePrintf (f, "%p%C %A {\n", publish, symbol->symbol.class, symbol->symbol.name);
-	PrintNamespace (f, symbol->namespace.namespace, level + 1);
-	PrettyIndent (f, 0, level, 0);
-	FilePuts (f, "}\n");
+	FilePrintf (f, "%p%C %A", publish, symbol->symbol.class, symbol->symbol.name);
+	if (nest)
+	{
+	    FilePuts (f, " {\n");
+	    PrintNamespace (f, symbol->namespace.namespace, level + 1);
+	    PrettyIndent (f, 0, level, 0);
+	    FilePuts (f, "}\n");
+	}
+	else
+	    FilePuts (f, ";\n");
 	break;
     case class_exception:
 	FilePrintf (f, "%p%C %A ", publish, 
 		    symbol->symbol.class, symbol->symbol.name);
 	PrintArgs (f, symbol->symbol.type->func.args);
+	if (symbol->exception.doc != Void)
+	{
+	    FilePuts (f, "\n");
+	    PrettyDoc (f, level + 1, symbol->exception.doc, 0);
+	}
 	FilePuts (f, ";\n");
 	break;
     default:
@@ -942,6 +989,9 @@
 void
 PrettyPrint (Value f, Publish publish, SymbolPtr name)
 {
-    doPrettyPrint (f, publish, name, 0, True);
+    if (!name)
+	PrintNamespace (f, TopNamespace, 0);
+    else
+	doPrettyPrint (f, publish, name, 0, True);
 }
 

Index: printf.5c
===================================================================
RCS file: /local/src/CVS/nickle/printf.5c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- a/printf.5c	7 Feb 2004 00:46:58 -0000	1.8
+++ b/printf.5c	8 Jun 2004 09:30:54 -0000	1.9
@@ -9,9 +9,16 @@
     int default_output_precision = -1;
     int infinite_output_precision = -2;
 
-    public exception invalid_format (string format);
-    public exception too_many_arguments (string format, poly[*] args);
-    public exception too_few_arguments (string format, poly[*] args);
+    public exception too_many_arguments (string format, poly[*] args)
+	/*
+	 * Raised when too many arguments are passed to a printf
+	 * function
+	 */;
+    public exception too_few_arguments (string format, poly[*] args)
+	/*
+	 * Raised when too few arguments are passed to a printf
+	 * function
+	 */;
     
     void to_utf8 (int c, void(int c) f)
     {
@@ -31,6 +38,9 @@
     }
     
     public void vfprintf (file f, string format, poly[*] args)
+	/*
+	 * print 'args' to 'f' according to 'format'
+	 */
     {
 	/*
 	 * A private namespace to walk the format string 
@@ -189,16 +199,25 @@
     }
 
     public void fprintf (file f, string format, poly args...)
+	/*
+	 * print 'args' to 'f' according to 'format'
+	 */
     {
 	vfprintf (f, format, args);
     }
 
     public void vprintf (string format, poly[*] args)
+	/*
+	 * print 'args' to stdout according to 'format'
+	 */
     {
 	vfprintf (stdout, format, args);
     }
 
     public string vsprintf (string format, poly[*] args)
+	/*
+	 * print 'args' to a string according to 'format'
+	 */
     {
 	file	f = File::string_write ();
 	vfprintf (f, format, args);
@@ -208,11 +227,17 @@
     public namespace PrintfGlobals {
 
 	public void printf (string format, poly args...)
+	    /*
+	     * print 'args' to stdout according to 'format'
+	     */
 	{
 	    vprintf (format, args);
 	}
 
 	public string sprintf (string format, poly args...)
+	    /*
+	     * print 'args' to a string according to 'format'
+	     */
 	{
 	    return vsprintf (format, args);
 	}

Index: prng.5c
===================================================================
RCS file: /local/src/CVS/nickle/prng.5c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- a/prng.5c	10 Oct 2003 05:00:49 -0000	1.10
+++ b/prng.5c	8 Jun 2004 09:30:54 -0000	1.11
@@ -11,12 +11,20 @@
 
   global bool setkey = false;
 
-  public void srandom(int s) {
+  public void srandom(int s) 
+    /*
+     * Seed the PRNG with 's'
+     */
+  {
     ARC4::nsetkey(10, s);
     setkey = true;
   }
 
-  public void dev_srandom(int nbits) {
+  public void dev_srandom(int nbits) 
+    /*
+     * Use 'nbits' of /dev/urandom to seed the PRNG
+     */
+  {
     twixt(file f = open("/dev/urandom", "r"); close(f)) {
       int seed = 0;
       while (nbits >= 8) {
@@ -29,8 +37,11 @@
     }
   }
 
-  /* returns an n-*bit* random number in 0..(2**n)-1 */
-  public int randbits(int n) {
+  public int randbits(int n) 
+    /*
+     * returns an 'n'-*bit* random number in 0..(2**'n')-1 
+     */
+  {
     int q = n >> 3;
     int r = n & 7;
     if (!setkey)
@@ -43,12 +54,19 @@
     return acc;
   }
 
-  /* returns a random integer in the range 0..n-1 */
-  public int randint(int n) {
+  public int randint(int n) 
+    /* 
+     * Returns a random integer in the range 0..'n'-1 
+     */
+  {
     return randbits(32 + bit_width (n)) % n;
   }
 
-  public void shuffle(&poly[*] a) {
+  public void shuffle(&poly[*] a) 
+    /*
+     * Randomly shuffle 'a' in place
+     */
+  {
     int na = dim(a);
     for (int i = 0; i < na - 1; i++) {
       int j = randint(na - i) + i;

Index: scanf.5c
===================================================================
RCS file: /local/src/CVS/nickle/scanf.5c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- a/scanf.5c	26 May 2004 08:01:41 -0000	1.19
+++ b/scanf.5c	8 Jun 2004 09:30:54 -0000	1.20
@@ -3,6 +3,9 @@
  */
 extend namespace File {
     public int vfscanf (file f, string format, (*poly)[*] args)
+	/*
+	 * According to 'format', read from 'f' to 'args'
+	 */
     {
 	/* Skip whitespace */
 	void whitespace ()
@@ -169,11 +172,17 @@
     }
 
     public int fscanf (file f, string format, *poly args...)
+	/*
+	 * According to 'format', read from 'f' to 'args'
+	 */
     {
 	return vfscanf (f, format, args);
     }
 
     public int sscanf (string s, string format, *poly args...)
+	/*
+	 * According to 'format', read from 's' to 'args'
+	 */
     {
         file sf = string_read(s);
         int n = vfscanf (sf, format, args);
@@ -184,11 +193,17 @@
     public namespace ScanfGlobals {
 	
 	public int scanf (string format, *poly args...)
+	    /*
+	     * According to 'format', read from stdin to 'args'
+	     */
 	{
 	    return File::vfscanf (stdin, format, args);
 	}
 
 	public int vscanf (string format, (*poly)[*] args)
+	    /*
+	     * According to 'format', read from stdin to 'args'
+	     */
 	{
 	    return File::vfscanf (stdin, format, args);
 	}

Index: socket.5c
===================================================================
RCS file: /local/src/CVS/nickle/socket.5c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- a/socket.5c	11 Jun 2003 05:02:42 -0000	1.1
+++ b/socket.5c	8 Jun 2004 09:30:54 -0000	1.2
@@ -1,5 +1,9 @@
 extend namespace Socket {
-    public string addr_to_string (int addr) {
+    public string addr_to_string (int addr) 
+	/*
+	 * Return a dotted quad from 'addr'
+	 */
+    {
 	return sprintf ("%d.%d.%d.%d",
 			(addr >> 24) & 0xff,
 			(addr >> 16) & 0xff,
@@ -7,7 +11,11 @@
 			(addr) & 0xff);
     }
     
-    public int string_to_addr (string addr) {
+    public int string_to_addr (string addr) 
+	/*
+	 * Parse a dotted quad
+	 */
+    {
 	int r = File::sscanf (addr, "%d.%d.%d.%d", 
 			&(int a), &(int b), &(int c), &(int d));
 	if (r != 4)

Index: string.5c
===================================================================
RCS file: /local/src/CVS/nickle/string.5c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- a/string.5c	13 May 2004 22:17:20 -0000	1.8
+++ b/string.5c	8 Jun 2004 09:30:54 -0000	1.9
@@ -1,6 +1,11 @@
 extend namespace String {
 
-    public int rindex(string target, string pattern) {
+    public int rindex(string target, string pattern) 
+	/*
+	 * Return the right-most location of 'pattern'
+	 * in 'target'
+	 */
+    {
 	int pl = length(pattern);
 	for (int i = length(target) - pl; i >= 0; --i) {
 	    bool match_here() {
@@ -15,14 +20,23 @@
 	return -1;
     }
 
-    public string dirname(string name) {
-	int n = rindex(name, "/");
+    public string dirname(string path) 
+	/*
+	 * Return the directory portion of 'path'
+	 */
+    {
+	int n = rindex(path, "/");
 	if (n == -1)
 	    return ".";
-	return (substr(name, 0, n));
+	return (substr(path, 0, n));
     }
 
-    public string[*] split(string s, string sep) {
+    public string[*] split(string s, string sep) 
+	/*
+	 * Split 's' at 'sep' boundaries, returning
+	 * an array of the resulting pieces
+	 */
+    {
 	string[...] ss = {};
 	int i = -1;
 	int j = 0;
@@ -37,7 +51,11 @@
 	return ss;
     }
 
-    public string chomp(string s) {
+    public string chomp(string s) 
+	/*
+	 * Trim whitespace from begining and end of 's'
+	 */
+    {
 	int l = length(s);
 	int i = 0;
 	while(i < l && Ctype::isspace(s[i]))
@@ -48,7 +66,11 @@
 	return substr(s, i, j - i + 1);
     }
 
-    public bool inchars(int c, string s) {
+    public bool inchars(int c, string s) 
+	/*
+	 * Return whether 'c' is in 's'
+	 */
+    {
 	return index(String::new(c), s) >= 0;
     }
 
@@ -60,7 +82,11 @@
 
     typedef string(string) dequote_t;
     
-    public dequote_t make_dequote(quote_context q) {
+    public dequote_t make_dequote(quote_context q) 
+	/*
+	 * Construct a quote parsing function based on 'q'
+	 */
+    {
 	public string _dequote(string s) {
 	    string result = "";
 	    qstate t = qstate.normal;
@@ -106,7 +132,11 @@
 
     typedef (string[*])(string) parse_csv_t;
 
-    public parse_csv_t make_parse_csv(quote_context q) {
+    public parse_csv_t make_parse_csv(quote_context q) 
+	/*
+	 * Construct a CSV file parsing context from 'q'
+	 */
+    {
 	dequote_t dq = make_dequote(q);
 	public string[*] _parse_csv(string s) {
 	    string[...] ss = {};

Index: string.c
===================================================================
RCS file: /local/src/CVS/nickle/string.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- a/string.c	16 Apr 2004 21:41:52 -0000	1.17
+++ b/string.c	8 Jun 2004 09:30:54 -0000	1.18
@@ -255,3 +255,15 @@
     strcpy (StringChars (&ret->string), str);
     RETURN (ret);
 }
+
+Value
+NewCharString (int c)
+{
+    ENTER ();
+    int	    size = StringCharSize (c);
+    Value   ret = NewString (size);
+
+    StringPutChar (c, StringChars (&ret->string));
+    RETURN (ret);
+}
+

Index: symbol.c
===================================================================
RCS file: /local/src/CVS/nickle/symbol.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- a/symbol.c	27 Feb 2004 03:50:16 -0000	1.19
+++ b/symbol.c	8 Jun 2004 09:30:54 -0000	1.20
@@ -46,10 +46,21 @@
     MemReference (sn->namespace);
 }
 
+static void
+SymbolExceptionMark (void *object)
+{
+    SymbolException *se = object;
+
+    MemReference (se->symbol.next);
+    MemReference (se->symbol.type);
+    MemReference (se->doc);
+}
+
 DataType    SymbolTypeType = { SymbolTypeMark, 0, "SymbolTypeType" };
 DataType    SymbolGlobalType = { SymbolGlobalMark, 0, "SymbolGlobalType" };
 DataType    SymbolLocalType = { SymbolLocalMark, 0, "SymbolLocalType" };
 DataType    SymbolNamespaceType = { SymbolNamespaceMark, 0, "SymbolNamespaceType" };
+DataType    SymbolExceptionType = { SymbolExceptionMark, 0, "SymbolExceptionType" };
 
 SymbolPtr
 NewSymbolType (Atom name, Type *type)
@@ -67,17 +78,18 @@
 }
 
 SymbolPtr
-NewSymbolException (Atom name, Type *type)
+NewSymbolException (Atom name, Type *type, Value doc)
 {
     ENTER ();
     SymbolPtr	s;
 
-    s = ALLOCATE (&SymbolTypeType, sizeof (SymbolType));
+    s = ALLOCATE (&SymbolExceptionType, sizeof (SymbolException));
     s->symbol.next = 0;
     s->symbol.name = name;
     s->symbol.class = class_exception;
     s->symbol.type = type;
     s->symbol.forward = False;
+    s->exception.doc = doc;
     RETURN (s);
 }
 

Index: value.h
===================================================================
RCS file: /local/src/CVS/nickle/value.h,v
retrieving revision 1.104
retrieving revision 1.105
diff -u -d -r1.104 -r1.105
--- a/value.h	28 May 2004 02:58:14 -0000	1.104
+++ b/value.h	8 Jun 2004 09:30:54 -0000	1.105
@@ -961,6 +961,7 @@
 
 Value	NewString (long length);
 Value	NewStrString (char *);
+Value	NewCharString (int c);
 Value	NewArray (Bool constant, Bool resizable, TypePtr type, int ndim, int *dims);
 void	ArrayResize (Value av, int dim, int size);
 void	ArraySetDimensions (Value av, int *dims);




More information about the Commit mailing list