diff --git a/COPYING b/COPYING
index e1887ed..86cf81a 100644
--- a/COPYING
+++ b/COPYING
@@ -339,4 +339,3 @@ consider it more useful to permit linking proprietary applications with the
 library.  If this is what you want to do, use the GNU Library General
 Public License instead of this License.
 
-
\ No newline at end of file
diff --git a/Makefile.in b/Makefile.in
index e429a6f..69ca2bf 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,5 +1,10 @@
 #               Unix Makefile for Bywater BASIC Interpreter
 
+##---------------------------------------------------------------##
+## NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, ##
+## 11/1995 (eidetics@cerf.net).                                  ##
+##---------------------------------------------------------------##
+
 srcdir = @srcdir@
 VPATH = @srcdir@
 
@@ -11,8 +16,12 @@ INSTALL_DATA = @INSTALL_DATA@
 
 DEFS = @DEFS@
 
-CFLAGS = -O
-LDFLAGS = -s
+# Revised by JBV
+#CFLAGS = -O
+CFLAGS = -g -ansi
+
+# Revised by JBV
+#LDFLAGS = -s
 
 prefix = /usr/local
 exec_prefix = $(prefix)
@@ -45,15 +54,21 @@ TESTFILES=	\
 	mlifthen.bas  on.bas	    onerr.bas	  onerrlbl.bas	ongosub.bas\
 	opentest.bas  option.bas    putget.bas	  random.bas	selcase.bas\
 	snglfunc.bas  stop.bas	    term.bas	  whilwend.bas	width.bas\
-	writeinp.bas
+	writeinp.bas  pascaltr.bas
 
 DISTFILES=	$(CFILES) $(HFILES) $(MISCFILES)
 
-all: bwbasic
+# Revised by JBV
+#all: bwbasic
+all: bwbasic renum
 
 bwbasic:	$(OFILES)
 		$(CC) $(OFILES) -lm -o $@ $(LDFLAGS)
 
+# Added by JBV
+renum:
+	$(CC) renum.c -o renum
+
 $(OFILES):      $(HFILES)
 
 .c.o:
@@ -86,8 +101,9 @@ distclean: clean
 realclean: distclean
 	rm -f TAGS
 
+# Version number changed from 2.10 to 2.20 by JBV
 dist: $(DISTFILES)
-	echo bwbasic-2.10 > .fname
+	echo bwbasic-2.20 > .fname
 	rm -rf `cat .fname`
 	mkdir `cat .fname`
 	ln $(DISTFILES) `cat .fname`
@@ -98,4 +114,3 @@ dist: $(DISTFILES)
 
 # Prevent GNU make v3 from overflowing arg limit on SysV.
 .NOEXPORT:
-
\ No newline at end of file
diff --git a/README b/README
index 3105e19..0570a25 100644
--- a/README
+++ b/README
@@ -1,14 +1,17 @@
 
 
-                        Bywater Software Announces
+                              README file for
 
 
-               Bywater BASIC Interpreter/Shell, version 2.10
+               Bywater BASIC Interpreter/Shell, version 2.20
                ---------------------------------------------
 
                     Copyright (c) 1993, Ted A. Campbell
                   for bwBASIC version 2.10, 11 October 1993
 
+               Version 2.20 modifications by Jon B. Volkoff,
+                             25 November 1995
+
 
 
 DESCRIPTION:
@@ -29,40 +32,50 @@ DESCRIPTION:
    for information on which you should contact the author.
 
 
-IMPROVEMENTS OVER PREVIOUS VERSION (1.11):
+IMPROVEMENTS OVER PREVIOUS VERSION (2.10):
+
+   * Plugged numerous memory leaks, resolved memory overruns and allocation
+     difficulties.
+
+   * General cleanup and bug fixes, too many to list in detail here.
+     The major problem areas addressed were:
+
+      - RUN command with file name argument
+      - nested and cascaded FOR-NEXT loops
+      - PRINT USING
+      - EOF, LOF functions
+      - string concatenation
+      - operator hierarchy
+      - multi-level expression evaluation
+      - hex constant interpretation
+      - hex and octal constants in INPUT and DATA statements
 
-   * now compilable on "stock" (older K&R specification) C compilers; 
+   * Added a CLOSE all files feature (when no argument supplied).
 
-   * implements ANSI-BASIC-style structured programming, with
-     called subroutines, multi-line functions, multi-line IF-THEN
-     ELSE statements, SELECT CASE statements, etc.;
+   * Added a unary minus sign operator.
 
-   * new enhancements to the interactive environment, such as DO NUM
-     and DO UNNUM to number or unnumber all program lines;
+   * Added a MID$ command to complement the MID$ function.
 
-   * addition of some hardware-specific commands such as CLS, LOCATE,
-     and INKEY$ (at present for IBM PC and compatibles, using the
-     Microsoft QuickC compiler), opening the way for more hardware-
-     specific commands and functions in the future; 
+   * Added a RENUM facility in a standalone program.
 
-   * general improvements to reliability and portability, including
-     more extensive testing than previous versions; 
+   * Added checking in configure for unistd.h (important on Sun systems).
 
 
 OBTAINING THE SOURCE CODE:
 
-   The source code for bwBASIC 2.10 will be posted to network news
-   groups and is available immediately by anonymous ftp. To obtain
-   the source code, ftp to site ftp.eng.umd.edu, cd to pub/basic and
-   get the file bwbasic-2.10.tar.gz.
+   The source code for bwBASIC 2.20 is available immediately by
+   anonymous ftp. To obtain the source code, ftp to site ftp.netcom.com,
+   cd to pub/rh/rhn and get the file bwbasic-2.20.uu. Or you may receive
+   a copy by e-mail by writing to Jon Volkoff at eidetics@cerf.net.
 
 
 COMMUNICATIONS:
 
-   email:  tcamp@delphi.com
+   email:  tcamp@delphi.com  (for Ted Campbell)
+           eidetics@cerf.net (for Jon Volkoff)
 
 
-A LIST OF BASIC COMMANDS AND FUNCTIONS IMPLEMENTED in bwBASIC 2.10:
+A LIST OF BASIC COMMANDS AND FUNCTIONS IMPLEMENTED in bwBASIC 2.20:
 
    Be aware that many of these commands and functions will not be
    available unless you have set certain flags in the header files.
@@ -96,7 +109,7 @@ A LIST OF BASIC COMMANDS AND FUNCTIONS IMPLEMENTED in bwBASIC 2.10:
    DIM variable(elements...)[variable(elements...)]...
    DO NUM|UNNUM
    DO [WHILE expression]
-   EDIT         (* depends on variable BWB.EDITOR$)
+   EDIT		(* depends on variable BWB.EDITOR$)
    ELSE
    ELSEIF
    END FUNCTION | IF | SELECT | SUB
@@ -110,7 +123,7 @@ A LIST OF BASIC COMMANDS AND FUNCTIONS IMPLEMENTED in bwBASIC 2.10:
    EXIT FOR|DO
    EXP( number )
    FIELD [#] device-number, number AS string-variable [, number AS string-variable...]
-   FILES filespec$      (* depends on variable BWB.FILES$)
+   FILES filespec$	(* depends on variable BWB.FILES$)
    FOR counter = start TO finish [STEP increment]
    FUNCTION function-definition
    GET [#] device-number [, record-number]
@@ -156,6 +169,7 @@ A LIST OF BASIC COMMANDS AND FUNCTIONS IMPLEMENTED in bwBASIC 2.10:
    RANDOMIZE number
    READ variable[, variable]...
    REM string
+   RENUM
    RESTORE line
    RETURN
    RIGHT$( string$, number-of-spaces )
diff --git a/bwb_cmd.c b/bwb_cmd.c
index a18445d..797fb61 100644
--- a/bwb_cmd.c
+++ b/bwb_cmd.c
@@ -46,6 +46,14 @@
 
 ***************************************************************/
 
+/*---------------------------------------------------------------*/
+/* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, */
+/* 11/1995 (eidetics@cerf.net).                                  */
+/*                                                               */
+/* Those additionally marked with "DD" were at the suggestion of */
+/* Dale DePriest (daled@cadence.com).                            */
+/*---------------------------------------------------------------*/
+
 #include <stdio.h>
 #include <math.h>
 #include <ctype.h>
@@ -710,7 +718,8 @@ bwb_on( l )
 
       /* get memory for line and buffer */
 
-      if ( ( oline = calloc( 1, sizeof( struct bwb_line ) ) ) == NULL )
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( oline = CALLOC( 1, sizeof( struct bwb_line ), "bwb_on") ) == NULL )
 	 {
 #if PROG_ERRORS
 	 bwb_error( "in bwb_on(): failed to find memory for oline" );
@@ -718,7 +727,8 @@ bwb_on( l )
 	 bwb_error( err_getmem );
 #endif
 	 }
-      if ( ( oline->buffer = calloc( 1, MAXSTRINGSIZE + 1 ) ) == NULL )
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( oline->buffer = CALLOC( 1, MAXSTRINGSIZE + 1, "bwb_on") ) == NULL )
 	 {
 #if PROG_ERRORS
 	 bwb_error( "in bwb_on(): failed to find memory for oline buffer" );
@@ -983,22 +993,27 @@ bwb_run( l )
          bwb_error( bwb_ebuf );
          }
       bwb_fload( input );		/* load program */
-      bwb_run( &CURTASK bwb_start );            /* and call bwb_run() recursively */
+
+      /* Next line removed by JBV (unnecessary recursion asks for trouble) */
+      /* bwb_run( &CURTASK bwb_start ); */         /* and call bwb_run() recursively */
+      current = &CURTASK bwb_start; /* JBV */
       }
 
    /* else if it is a line number, execute the program in memory
       at that line number */
 
-   else
-      {
+   /* Removed by JBV */
+   /* else
+      { */
 
-      if ( current == NULL )
-         {
+      /* Removed by JBV */
+      /* if ( current == NULL )
+         { */
 
-         if ( e != NULL )
-            {
+         /* Added expression type check and changed loop boundaries (JBV) */
+         if (( e != NULL ) && ( e->type != STRING ))
+         {
             go_lnumber = (int) exp_getnval( e );
-            }
 
 #if INTENSIVE_DEBUG
          sprintf( bwb_ebuf, "in bwb_run(): element detected <%s>, lnumber <%d>",
@@ -1015,6 +1030,8 @@ bwb_run( l )
             }
          }
 
+      /*    } */ /* Removed by JBV */
+
       if ( current == NULL )
          {
          sprintf( bwb_ebuf, err_lnnotfound, go_lnumber );
@@ -1037,7 +1054,7 @@ bwb_run( l )
       CURTASK exsc = 0;
       bwb_setexec( current, 0, EXEC_NORM );
 
-      }
+   /*    } */ /* Removed by JBV */
 
 #if INTENSIVE_DEBUG
    sprintf( bwb_ebuf, "in bwb_run(): function complete." );
@@ -1178,6 +1195,7 @@ bwb_xload( l )
 #endif
    {
    FILE *loadfile;
+   struct exp_ese *e; /* JBV */
 
    /* Get an argument for filename */
 
@@ -1188,13 +1206,31 @@ bwb_xload( l )
       case '\n':
       case '\r':
       case ':':
+         bwb_error( err_nofn ); /* Added by JBV (bug found by DD) */
 
          return bwb_zline( l );
       default:
          break;
       }
 
-   bwb_const( l->buffer, CURTASK progfile, &( l->position ) );
+   /* Section added by JBV (bug found by DD) */
+   e = bwb_exp( l->buffer, FALSE, &( l->position ) );
+   if ( e->type != STRING )
+      {
+#if PROG_ERRORS
+      sprintf( bwb_ebuf, "in bwb_xload(): Missing filespec" );
+      bwb_error( bwb_ebuf );
+#else
+      bwb_error( err_syntax );
+#endif
+
+      return bwb_zline( l );
+      }
+
+   /* This line removed by JBV (no longer required) */
+   /* bwb_const( l->buffer, CURTASK progfile, &( l->position ) ); */
+   str_btoc( CURTASK progfile, exp_getsval( e ) ); /* JBV */
+
    if ( ( loadfile = fopen( CURTASK progfile, "r" )) == NULL )
       {
       sprintf( bwb_ebuf, err_openfile, CURTASK progfile );
@@ -1214,7 +1250,7 @@ bwb_xload( l )
         FUNCTION:       bwb_save()
 
 	DESCRIPTION:    This C function implements the BASIC
-			LOAD command.
+			SAVE command.
 
    	SYNTAX:		SAVE file-name
 
@@ -1231,6 +1267,7 @@ bwb_save( l )
    {
    FILE *outfile;
    static char filename[ MAXARGSIZE ];
+   struct exp_ese *e; /* JBV */
 
 #if INTENSIVE_DEBUG
    sprintf( bwb_ebuf, "in bwb_save(): entered function." );
@@ -1253,7 +1290,24 @@ bwb_save( l )
          break;
       }
 
-   bwb_const( l->buffer, filename, &( l->position ) );
+   /* Section added by JBV (bug found by DD) */
+   e = bwb_exp( l->buffer, FALSE, &( l->position ) );
+   if ( e->type != STRING )
+      {
+#if PROG_ERRORS
+      sprintf( bwb_ebuf, "in bwb_save(): Missing filespec" );
+      bwb_error( bwb_ebuf );
+#else
+      bwb_error( err_syntax );
+#endif
+
+      return bwb_zline( l );
+      }
+
+   /* This line removed by JBV (no longer required) */
+   /* bwb_const( l->buffer, filename, &( l->position ) ); */
+   str_btoc( filename, exp_getsval( e ) ); /* JBV */
+
    if ( ( outfile = fopen( filename, "w" )) == NULL )
       {
       sprintf( bwb_ebuf, err_openfile, filename );
@@ -1476,7 +1530,7 @@ xl_line( file, l )
    if (( file == stdout ) || ( file == stderr ))
       {
 
-      if ( l->xnum == TRUE )
+      if ( l->xnum == (char) TRUE ) /* Better recast this one (JBV) */
 	 {
 	 sprintf( tbuf, "%7d: %s\n", l->number, l->buffer );
 	 }
@@ -1490,7 +1544,7 @@ xl_line( file, l )
    else
       {
 
-      if ( l->xnum == TRUE )
+      if ( l->xnum == (char) TRUE ) /* Better recast this one (JBV) */
 	 {
 	 fprintf( file, "%d %s\n", l->number, l->buffer );
 	 }
@@ -1556,7 +1610,8 @@ bwb_delete( l )
       {
       if ( current != l )
          {
-         if (( current->xnum == TRUE ) && ( current->number == s ))
+         /* Following line revised by JBV */
+         if (( current->xnum == (char) TRUE ) && ( current->number == s ))
             {
             f = TRUE;
             previous = p;
@@ -1589,7 +1644,8 @@ bwb_delete( l )
          {
          if ( current != l )
             {
-            if (( current->xnum == TRUE) &&  ( current->number == e ))
+            /* Following line revised by JBV */
+            if (( current->xnum == (char) TRUE) &&  ( current->number == e ))
                {
 #if INTENSIVE_DEBUG
 	       sprintf( bwb_ebuf, "in bwb_delete(): end line number is <%d>",
@@ -1989,7 +2045,9 @@ bwb_xnew( l )
       {
       if ( wait != TRUE )
          {
-         free( previous );
+         /* Revised to FREE pass-thru call by JBV */
+         FREE( previous, "bwb_xnew" );
+         previous = NULL; /* JBV */
          }
       wait = FALSE;
       previous = current;
@@ -2214,4 +2272,3 @@ bwb_zline( l )
    }
 
 
-
\ No newline at end of file
diff --git a/bwb_cnd.c b/bwb_cnd.c
index 4a16682..d2368ee 100644
--- a/bwb_cnd.c
+++ b/bwb_cnd.c
@@ -23,6 +23,14 @@
 
 ***************************************************************/
 
+/*---------------------------------------------------------------*/
+/* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, */
+/* 11/1995 (eidetics@cerf.net).                                  */
+/*                                                               */
+/* Those additionally marked with "DD" were at the suggestion of */
+/* Dale DePriest (daled@cadence.com).                            */
+/*---------------------------------------------------------------*/
+
 #include <stdio.h>
 #include <math.h>
 #include <ctype.h>
@@ -180,7 +188,11 @@ bwb_if( l )
          }
       else
          {
-         bwb_setexec( endif_line, 0, CURTASK excs[ CURTASK exsc ].code );
+         /* Following line incorrect, replaced by next two (bug found by DD) */
+         /* bwb_setexec( endif_line, 0, CURTASK excs[ CURTASK exsc ].code ); */
+
+         bwb_incexec(); /* JBV */
+         bwb_setexec( endif_line, 0, EXEC_IFFALSE ); /* JBV */
          endif_line->position = 0;
          return endif_line;
          }
@@ -265,13 +277,14 @@ bwb_if( l )
       if ( els != FALSE )
          {
          l->position = els + strlen( CMD_ELSE ) + 1;
-         bwb_setexec( l, els, EXEC_NORM );
+         /* bwb_setexec( l, els, EXEC_NORM ); */ /* Nope (JBV) */
+         bwb_setexec( l, els, CURTASK excs[ CURTASK exsc ].code ); /* JBV */
 	 return l;
 	 }
       }
 
    /* if neither then nor else were found, advance to next line */
-   /* DO NOT advance to next segment (only if TRUE should we do that */
+   /* DO NOT advance to next segment (only if TRUE should we do that) */
 
    l->next->position = 0;
    return l->next;
@@ -437,7 +450,13 @@ bwb_else( l )
    /* If the code is EXEC_NORM, then this is a continuation of a single-
       line IF...THEN...ELSE... statement and we should return */
 
-   if ( CURTASK excs[ CURTASK exsc ].code == EXEC_NORM )
+   /*----------------------------------------------------------------------*/
+   /* Well, not really... better to check for EXEC_IFTRUE or EXEC_IFFALSE, */
+   /* and if not equal, then blow entirely out of current line (JBV)       */
+   /*----------------------------------------------------------------------*/
+
+   /* Section removed by JBV */
+   /* if ( CURTASK excs[ CURTASK exsc ].code == EXEC_NORM )
       {
 
 #if INTENSIVE_DEBUG
@@ -446,6 +465,20 @@ bwb_else( l )
 #endif
 
       return bwb_zline( l );
+      } */
+
+   /* Section added by JBV */
+   if (( CURTASK excs[ CURTASK exsc ].code != EXEC_IFTRUE ) &&
+   ( CURTASK excs[ CURTASK exsc ].code != EXEC_IFFALSE ))
+      {
+
+#if INTENSIVE_DEBUG
+      sprintf( bwb_ebuf, "in bwb_else(): no EXEC_IFTRUE or EXEC_IFFALSE" );
+      bwb_debug( bwb_ebuf );
+#endif
+
+      l->next->position = 0;
+      return l->next;
       }
 
    endif_line = find_endif( l, &else_line );
@@ -1751,6 +1784,14 @@ bwb_for( l )
    bwb_debug( bwb_ebuf );
 #endif
 
+   /*--------------------------------------------------------------*/
+   /* Make sure we are in the right FOR-NEXT level!                */
+   /* If we aren't (which could happen for legit reasons), fix the */
+   /* exec stack.                                                  */
+   /* JBV, 9/20/95                                                 */
+   /*--------------------------------------------------------------*/
+   if (v == CURTASK excs[ CURTASK exsc].local_variable) bwb_decexec();
+
    /* at this point one should find an equals sign ('=') */
 
    adv_ws( l->buffer, &( l->position ) );
@@ -1972,9 +2013,7 @@ bwb_next( l )
 #endif
    {
    char tbuf[ MAXSTRINGSIZE + 1 ];
-#if INTENSIVE_DEBUG
-   struct bwb_variable *v;
-#endif
+   struct bwb_variable *v; /* Relocated from INTENSIVE_DEBUG (JBV) */
 
 #if INTENSIVE_DEBUG
    sprintf( bwb_ebuf, "in bwb_next(): entered function, cmdnum <%d> exsc level <%d> code <%d>",
@@ -1997,13 +2036,19 @@ bwb_next( l )
 
    /* read the argument, if there is one */
 
+   /* Relocated from MULTISEG_LINES (JBV) */
+   exp_getvfname( &( l->buffer[ l->position ] ), tbuf );
+
+   if (strlen(tbuf) != 0)
+   {
+   /* Relocated from INTENSIVE_DEBUG (JBV) */
+   v = var_find( tbuf );
+
 #if MULTISEG_LINES                   /* not currently needed otherwise */
 
-   exp_getvfname( &( l->buffer[ l->position ] ), tbuf );
    l->position += strlen( tbuf );
 
 #if INTENSIVE_DEBUG
-   v = var_find( tbuf );
    sprintf( bwb_ebuf, "in bwb_next(): variable name detected <%s>.", v->name );
    bwb_debug( bwb_ebuf );
 #endif
@@ -2011,6 +2056,15 @@ bwb_next( l )
 
    /* decrement or increment the value */
 
+   /*--------------------------------------------------------------*/
+   /* Make sure we are in the right FOR-NEXT level!                */
+   /* If we aren't (which could happen for legit reasons), fix the */
+   /* exec stack.                                                  */
+   /* JBV, 9/20/95                                                 */
+   /*--------------------------------------------------------------*/
+   while (v != CURTASK excs[ CURTASK exsc].local_variable) bwb_decexec();
+   }
+
    var_setnval( CURTASK excs[ CURTASK exsc ].local_variable,
       var_getnval( CURTASK excs[ CURTASK exsc ].local_variable )
       + (bnumber) CURTASK excs[ CURTASK exsc ].for_step );
@@ -2077,12 +2131,14 @@ bwb_next( l )
       = CURTASK excs[ CURTASK exsc ].for_position;
    bwb_setexec( CURTASK excs[ CURTASK exsc ].for_line,
       CURTASK excs[ CURTASK exsc ].for_position, EXEC_FOR );
+
+   return CURTASK excs[ CURTASK exsc ].for_line; /* Added (JBV) */
 #else
    bwb_setexec( CURTASK excs[ CURTASK exsc - 1 ].line,
       CURTASK excs[ CURTASK exsc - 1 ].position, EXEC_FOR );
-#endif
 
-   return CURTASK excs[ CURTASK exsc - 1 ].line;
+   return CURTASK excs[ CURTASK exsc - 1 ].line; /* Relocated (JBV) */
+#endif
 
    }
 
@@ -2168,7 +2224,8 @@ bwb_exitfor( l )
    /* set the next line in the exec stack */
 
    next_line->position = 0;
-   bwb_setexec( next_line, 0, EXEC_NORM );
+   /* bwb_setexec( next_line, 0, EXEC_NORM ); */  /* WRONG (JBV) */
+   bwb_setexec( next_line, 0, CURTASK excs[ CURTASK exsc ].code ); /* JBV */
 
    return next_line;
 
@@ -2405,5 +2462,3 @@ var_setnval( v, i )
 
    }
 
-
-
\ No newline at end of file
diff --git a/bwb_dio.c b/bwb_dio.c
index 6f4759f..5da4dce 100644
--- a/bwb_dio.c
+++ b/bwb_dio.c
@@ -23,6 +23,11 @@
 
 ***************************************************************/
 
+/*---------------------------------------------------------------*/
+/* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, */
+/* 11/1995 (eidetics@cerf.net).                                  */
+/*---------------------------------------------------------------*/
+
 #include <stdio.h>
 
 #include "bwbasic.h"
@@ -352,7 +357,7 @@ bwb_open( l )
       if ( e->type == STRING )
          {
 #if PROG_ERRORS
-         bwb_error( "String where number was expected for record length" );
+         bwb_error( "String where number was expected for dev number" );
 #else
          bwb_error( err_syntax );
 #endif
@@ -490,6 +495,9 @@ bwb_open( l )
 
    /* assign values to device table */
 
+   /* Random mode has a default record length (JBV) */
+   if (mode == DEVMODE_RANDOM && rlen == -1) rlen = 128;
+
    dev_table[ req_devnumber ].mode = mode;
    dev_table[ req_devnumber ].cfp = fp;
    dev_table[ req_devnumber ].reclen = rlen;
@@ -497,11 +505,17 @@ bwb_open( l )
    dev_table[ req_devnumber ].loc = 0;
    strcpy( dev_table[ req_devnumber ].filename, devname );
 
+   /* File length finding routine, added by JBV */
+   fseek( dev_table[ req_devnumber ].cfp, 0, SEEK_END );
+   dev_table[ req_devnumber ].lof = ftell( dev_table[ req_devnumber ].cfp );
+   fseek( dev_table[ req_devnumber ].cfp, 0, SEEK_SET );
+
    /* allocate a character buffer for random access */
 
    if (( mode == DEVMODE_RANDOM ) && ( previous_buffer != TRUE ))
       {
-      if ( ( dev_table[ req_devnumber ].buffer = calloc( rlen + 1, 1 )) == NULL )
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( dev_table[ req_devnumber ].buffer = CALLOC( rlen + 1, 1, "bwb_open" )) == NULL )
 	 {
 #if PROG_ERRORS
 	 bwb_error( "in bwb_open(): failed to find memory for device buffer" );
@@ -552,14 +566,21 @@ bwb_close( l )
    {
    struct exp_ese *e;
    char atbuf[ MAXSTRINGSIZE + 1 ];
+   int blanket_close; /* JBV */
+   register int n; /* JBV */
+
+   blanket_close = -1; /* JBV */
+   req_devnumber = 0; /* JBV */
 
    /* loop to get device numbers to close */
 
    do
       {
 
+      if ( l->buffer[ l->position ] == ',' && blanket_close == 0)
+         ++( l->position); /* JBV */
       adv_ws( l->buffer, &( l->position ) );
-      if ( l->buffer[ l->position ] =='#' )
+      if ( l->buffer[ l->position ] == '#')
          {
          ++( l->position );
          }
@@ -579,7 +600,31 @@ bwb_close( l )
          return bwb_zline( l );
          }
 
-      req_devnumber = (int) exp_getnval( e );
+      /*-------------------------------------------------------------*/
+      /* Added the following section for blanket close feature (JBV) */
+      /*-------------------------------------------------------------*/
+      if (blanket_close == -1)
+      if (strlen(atbuf) != 0) blanket_close = 0;
+      else blanket_close = 1;
+
+      if (blanket_close == 0) req_devnumber = (int) exp_getnval( e );
+      else
+      {
+          ++req_devnumber;
+
+          /* Find the next device in use */
+          for (n = req_devnumber; n < DEF_DEVICES; ++n)
+          {
+              req_devnumber = -1;
+              if (( dev_table[ n ].mode != DEVMODE_CLOSED ) &&
+                 ( dev_table[ n ].mode != DEVMODE_AVAILABLE ) )
+              {
+                  req_devnumber = n;
+                  break;
+              }
+          }
+          if (req_devnumber == -1) break; /* Skidoo if no more to close */
+      }
 
 #if INTENSIVE_DEBUG
       sprintf( bwb_ebuf, "in bwb_close(): requested device number <%d>",
@@ -633,13 +678,20 @@ bwb_close( l )
 
       dev_table[ req_devnumber ].mode = DEVMODE_CLOSED;
 
+      /* Revised to FREE pass-thru call by JBV */
+      if ( dev_table[ req_devnumber ].buffer != NULL )
+      {
+          FREE( dev_table[ req_devnumber ].buffer, "bwb_close" ); /* JBV */
+          dev_table[ req_devnumber ].buffer = NULL; /* JBV */
+      }
+
       /* eat up any remaining whitespace */
 
       adv_ws( l->buffer, &( l->position ) );
 
       }
 
-   while ( l->buffer[ l->position ] == ',' );
+   while ( l->buffer[ l->position ] == ',' || blanket_close == 1); /* JBV */
 
    /* return next line number in sequence */
 
@@ -680,7 +732,9 @@ bwb_chdir( l )
    if ( init == FALSE )
       {
       init = TRUE;
-      if ( ( atbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
+
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( atbuf = CALLOC( MAXSTRINGSIZE + 1, sizeof( char ), "bwb_chdir" )) == NULL )
          {
 #if PROG_ERRORS
 	 bwb_error( "in bwb_chdir(): failed to find memory for atbuf" );
@@ -758,7 +812,9 @@ bwb_rmdir( l )
    if ( init == FALSE )
       {
       init = TRUE;
-      if ( ( atbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
+
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( atbuf = CALLOC( MAXSTRINGSIZE + 1, sizeof( char ), "bwb_rmdir" )) == NULL )
          {
 #if PROG_ERRORS
 	 bwb_error( "in rmdir(): failed to find memory for atbuf" );
@@ -835,7 +891,9 @@ bwb_mkdir( l )
    if ( init == FALSE )
       {
       init = TRUE;
-      if ( ( atbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
+
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( atbuf = CALLOC( MAXSTRINGSIZE + 1, sizeof( char ), "bwb_mkdir" )) == NULL )
          {
 #if PROG_ERRORS
 	 bwb_error( "in bwb_mkdir(): failed to find memory for atbuf" );
@@ -916,7 +974,9 @@ bwb_kill( l )
    if ( init == FALSE )
       {
       init = TRUE;
-      if ( ( atbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
+
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( atbuf = CALLOC( MAXSTRINGSIZE + 1, sizeof( char ), "bwb_kill" )) == NULL )
          {
 #if PROG_ERRORS
 	 bwb_error( "in bwb_kill(): failed to find memory for atbuf" );
@@ -998,7 +1058,9 @@ bwb_name( l )
    if ( init == FALSE )
       {
       init = TRUE;
-      if ( ( atbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
+
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( atbuf = CALLOC( MAXSTRINGSIZE + 1, sizeof( char ), "bwb_name" )) == NULL )
          {
 #if PROG_ERRORS
 	 bwb_error( "in bwb_name(): failed to find memory for atbuf" );
@@ -1006,7 +1068,8 @@ bwb_name( l )
 	 bwb_error( err_getmem );
 #endif
 	 }
-      if ( ( btbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( btbuf = CALLOC( MAXSTRINGSIZE + 1, sizeof( char ), "bwb_name" )) == NULL )
 	 {
 #if PROG_ERRORS
 	 bwb_error( "in bwb_name(): failed to find memory for btbuf" );
@@ -1269,7 +1332,9 @@ bwb_field( l )
 #if DONTDOTHIS
       if ( b->sbuffer != NULL )
 	 {
-	 free( b->sbuffer );
+         /* Revised to FREE pass-thru call by JBV */
+	 FREE( b->sbuffer, "bwb_field" );
+	 b->sbuffer = NULL; /* JBV */
 	 }
 #endif
 
@@ -1281,7 +1346,7 @@ bwb_field( l )
 
 #if INTENSIVE_DEBUG
       sprintf( bwb_ebuf, "in bwb_field(): buffer <%lXh> var <%s> buffer <%lXh>",
-         (long) dev_table[ dev_number ].buffer, v->name, (long) b->buffer );
+         (long) dev_table[ dev_number ].buffer, v->name, (long) b->sbuffer );
       bwb_debug( bwb_ebuf );
 #endif
 
@@ -1466,7 +1531,7 @@ dio_lrset( l, rset )
 
 #if INTENSIVE_DEBUG
    sprintf( bwb_ebuf, "in dio_lrset(): startpos <%d> buffer <%lX>",
-      startpos, (long) d->buffer );
+      startpos, (long) d->sbuffer );
    bwb_debug( bwb_ebuf );
 #endif
 
@@ -1510,6 +1575,7 @@ bwb_get( l )
    register int i;
    struct exp_ese *e;
    char atbuf[ MAXSTRINGSIZE + 1 ];
+   long offset; /* JBV */
 
    /* first read device number */
 
@@ -1583,9 +1649,10 @@ bwb_get( l )
 
    /* wind the c file up to the proper point */
 
-   if ( fseek( dev_table[ dev_number ].cfp,
-      (long) (( rec_number - 1 ) * dev_table[ dev_number ].reclen ),
-      SEEK_SET ) != 0 )
+   /* Added by JBV */
+   offset = (long) (( rec_number - 1 ) * dev_table[ dev_number ].reclen);
+
+   if ( fseek( dev_table[ dev_number ].cfp, offset, SEEK_SET ) != 0 )
       {
 #if PROG_ERRORS
       sprintf( bwb_ebuf, "in bwb_get(): fseek() failed, rec number <%d> offset <%ld>",
@@ -1599,6 +1666,7 @@ bwb_get( l )
 
    /* read the requested bytes into the buffer */
 
+   dev_table[ dev_number ].loc = offset; /* Slight bug fix (JBV) */
    for ( i = 0; i < dev_table[ dev_number ].reclen; ++i )
       {
       dev_table[ dev_number ].buffer[ i ] =
@@ -1639,6 +1707,7 @@ bwb_put( l )
    register int i;
    struct exp_ese *e;
    char atbuf[ MAXSTRINGSIZE + 1 ];
+   long offset; /* JBV */
 
    /* first read device number */
 
@@ -1649,7 +1718,23 @@ bwb_put( l )
       }
 
    adv_element( l->buffer, &( l->position ), atbuf );
-   dev_number = atoi( atbuf );
+/*   dev_number = atoi( atbuf ); */  /* Not quite right (JBV) */
+
+   /* Added by JBV */
+   pos = 0;
+   e = bwb_exp( atbuf, FALSE, &pos );
+
+   if ( e->type != NUMBER )
+      {
+#if PROG_ERRORS
+      bwb_error( "in bwb_put(): Number was expected for device number" );
+#else
+      bwb_error( err_syntax );
+#endif
+      return bwb_zline( l );
+      }
+
+   dev_number = (int) exp_getnval( e );
 
 #if INTENSIVE_DEBUG
    sprintf( bwb_ebuf, "in bwb_put(): device <%d>", dev_number );
@@ -1709,9 +1794,10 @@ bwb_put( l )
 
    /* wind the c file up to the proper point */
 
-   if ( fseek( dev_table[ dev_number ].cfp,
-      (long) (( rec_number - 1 ) * dev_table[ dev_number ].reclen ),
-      SEEK_SET ) != 0 )
+   /* Added by JBV */
+   offset = (long) (( rec_number - 1 ) * dev_table[ dev_number ].reclen);
+
+   if ( fseek( dev_table[ dev_number ].cfp, offset, SEEK_SET ) != 0 )
       {
 #if PROG_ERRORS
       sprintf( bwb_ebuf, "in bwb_get(): fseek() failed, rec number <%d> offset <%ld>",
@@ -1732,6 +1818,7 @@ bwb_put( l )
 
    /* write the requested bytes to the file */
 
+   dev_table[ dev_number ].loc = offset; /* Slight bug fix (JBV) */
    for ( i = 0; i < dev_table[ dev_number ].reclen; ++i )
       {
       fputc( dev_table[ dev_number ].buffer[ i ],
@@ -1804,4 +1891,3 @@ dio_flush( dev_number )
 #endif				/* COMMON_CMDS */
 
 
-
\ No newline at end of file
diff --git a/bwb_elx.c b/bwb_elx.c
index a35fd92..f9f91b0 100644
--- a/bwb_elx.c
+++ b/bwb_elx.c
@@ -23,6 +23,14 @@
 
 ****************************************************************/
 
+/*---------------------------------------------------------------*/
+/* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, */
+/* 11/1995 (eidetics@cerf.net).                                  */
+/*                                                               */
+/* Those additionally marked with "DD" were at the suggestion of */
+/* Dale DePriest (daled@cadence.com).                            */
+/*---------------------------------------------------------------*/
+
 #include <stdio.h>
 #include <ctype.h>
 #include <math.h>
@@ -193,7 +201,8 @@ exp_strconst( expression )
 
    /* read the string up until the next double quotation mark */
 
-   while( expression[ e_pos ] != '\"' )
+   /* While yer at it, check for a null terminator too (JBV, found by DD) */
+   while(( expression[ e_pos ] != '\"') && ( expression[ e_pos ] != '\0' ))
       {
       CURTASK exps[ CURTASK expsc ].string[ s_pos ] = expression[ e_pos ];
       ++e_pos;
@@ -219,7 +228,11 @@ exp_strconst( expression )
 
    /* advance past last double quotation mark */
 
-   ++CURTASK exps[ CURTASK expsc ].pos_adv;
+   /*-------------------------------------------------------------*/
+   /* Of course, it doesn't hurt to make sure it's really a quote */
+   /* (JBV, found by DD)                                          */
+   /*-------------------------------------------------------------*/
+   if ( expression[ e_pos ] == '\"' ) ++CURTASK exps[ CURTASK expsc ].pos_adv;
 
    /* return */
 
@@ -654,6 +667,8 @@ exp_numconst( expression )
                case 'd':
                case 'E':
                case 'e':
+               case 'F': /* Don't forget these! (JBV) */
+               case 'f':
                   CURTASK exps[ CURTASK expsc ].string[ s_pos ] = expression[ CURTASK exps[ CURTASK expsc ].pos_adv ];
 
                   ++CURTASK exps[ CURTASK expsc ].pos_adv;  /* advance to next character */
@@ -718,7 +733,8 @@ exp_function( expression )
    int paren_level;
    int n_args;
    struct bwb_variable *v;
-   struct bwb_variable argv[ MAX_FARGS ];
+   /* struct bwb_variable argv[ MAX_FARGS ]; */ /* Removed by JBV */
+   struct bwb_variable *argv; /* Added by JBV */
    bstring *b;
 #if INTENSIVE_DEBUG
    char tbuf[ MAXSTRINGSIZE + 1 ];
@@ -728,6 +744,18 @@ exp_function( expression )
    bwb_debug( bwb_ebuf );
 #endif
 
+   /*-----------------------------------------------------------*/
+   /* Added by JBV                                              */
+   /* Required because adding a simple "static" modifier in the */
+   /* argv declaration doesn't work for recursive calls!        */
+   /*-----------------------------------------------------------*/
+   if ( ( argv = (struct bwb_variable *) CALLOC( MAX_FARGS,
+      sizeof( struct bwb_variable ), "exp_function" )) == NULL )
+      {
+      bwb_error( err_getmem );
+      return NULL;
+      }
+
    /* assign pointers to argument stack */
 
    /* get the function name */
@@ -1014,6 +1042,13 @@ exp_function( expression )
    v = CURTASK exps[ CURTASK expsc ].function->vector ( n_args, &( argv[ 0 ] ),
       CURTASK exps[ CURTASK expsc ].function->id );
 
+   /*-------------------------------------------------*/
+   /* Now free the argv memory                        */
+   /* (some other less fortunate routine may need it) */
+   /* JBV, 10/95                                      */
+   /*-------------------------------------------------*/
+   FREE( argv, "exp_function" );
+
 #if INTENSIVE_DEBUG
    sprintf( bwb_ebuf, "in exp_function(): return from function vector, type <%c>",
       v->type );
@@ -1117,7 +1152,7 @@ exp_variable( expression )
       {
 #if INTENSIVE_DEBUG
       sprintf( bwb_ebuf, "in exp_variable(): variable <%s> has 1 dimension",
-	 CURTASK exps[ CURTASK expsc ].xvar->name );
+         CURTASK exps[ CURTASK expsc ].xvar->name );
       bwb_debug( bwb_ebuf );
 #endif
       pos = strlen( v->name );
@@ -1128,10 +1163,8 @@ exp_variable( expression )
    else
       {
 #if INTENSIVE_DEBUG
-      sprintf( bwb_ebuf, "in exp_variable(): level <%d> variable <%s> has <%d> dimensions",
-	 CURTASK expsc,
-	 v->name,
-	 v->dimensions );
+      sprintf( bwb_ebuf, "in exp_variable(): variable <%s> has > 1 dimensions",
+         CURTASK exps[ CURTASK expsc ].xvar->name );
       bwb_debug( bwb_ebuf );
 #endif
       dim_getparams( expression, &pos, &n_params, &pp );
@@ -1144,25 +1177,18 @@ exp_variable( expression )
       }
 
 #if INTENSIVE_DEBUG
-   if ( v->dimensions > 1 )
+   for ( n = 0; n < v->dimensions; ++ n )
       {
-      sprintf( bwb_ebuf, "in exp_variable(): exec stack level <%d>",
-	 CURTASK exsc );
+      sprintf( bwb_ebuf, "in exp_variable(): var <%s> array_pos element <%d> is <%d>.",
+         v->name, n, v->array_pos[ n ] );
       bwb_debug( bwb_ebuf );
-      for ( n = 0; n < v->dimensions; ++n )
-	 {
-	 sprintf( bwb_ebuf, "   variable <%s> array_pos element <%d> is <%d>.",
-	    v->name, n, v->array_pos[ n ] );
-	 bwb_debug( bwb_ebuf );
-	 }
       }
 #endif
 
    /* assign the type and value at this level */
 
    CURTASK exps[ CURTASK expsc ].type = (char) v->type;
-   CURTASK exps[ CURTASK expsc ].xvar = v;
-
+   
    switch( v->type )
       {
       case STRING:
@@ -1180,7 +1206,7 @@ exp_variable( expression )
          break;
       default:
          CURTASK exps[ CURTASK expsc ].nval = var_getnval( v );
-	 break;
+         break;
       }
 
 #if INTENSIVE_DEBUG
diff --git a/bwb_exp.c b/bwb_exp.c
index 1381d77..f8e5724 100644
--- a/bwb_exp.c
+++ b/bwb_exp.c
@@ -23,6 +23,11 @@
 
 ****************************************************************/
 
+/*---------------------------------------------------------------*/
+/* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, */
+/* 11/1995 (eidetics@cerf.net).                                  */
+/*---------------------------------------------------------------*/
+
 #include <stdio.h>
 #include <ctype.h>
 #include <math.h>
@@ -71,7 +76,7 @@ bwb_exp( expression, assignment, position )
    entry_level = CURTASK expsc;
    err_condition = FALSE;
 
-   /* advance past whitespace or beginningg of line segment */
+   /* advance past whitespace or beginning of line segment */
 
 #if MULTISEG_LINES
    if ( expression[ *position ] == ':' )
@@ -192,6 +197,7 @@ bwb_exp( expression, assignment, position )
          case OP_XOR:
          case OP_IMPLIES:
          case OP_EQUIV:
+         case OP_NEGATION: /* JBV */
 
 #if INTENSIVE_DEBUG
             sprintf( bwb_ebuf, "in bwb_exp(): operator detected." );
@@ -595,7 +601,7 @@ exp_findop( expression )
       {
 
 #if INTENSIVE_DEBUG
-      sprintf( bwb_ebuf, "in bwb_findop() loop position <%d> char 0x%x",
+      sprintf( bwb_ebuf, "in exp_findop() loop position <%d> char 0x%x",
 	 c, expression[ position ] );
       bwb_debug( bwb_ebuf );
 #endif
@@ -692,8 +698,8 @@ exp_findop( expression )
 	FUNCTION:       exp_isnc()
 
 	DESCRIPTION:    This function reads the expression to find
-			if a logical or mathematical operation is
-			required at this point.
+			if a numerical constant is present at this
+			point.
 
 ***************************************************************/
 
@@ -706,6 +712,7 @@ exp_isnc( expression )
    char *expression;
 #endif
    {
+   char tbuf[ MAXVARNAMESIZE + 1 ]; /* JBV */
 
    switch( expression[ 0 ] )
       {
@@ -752,6 +759,20 @@ exp_isnc( expression )
             return OP_NULL;
             }
 
+         /*--------------------------------------------------------*/
+         /* Check for unary minus sign added by JBV.               */
+         /* Could be prefixing a parenthetical expression or a     */
+         /* variable name.                                         */
+         /* But parentheses won't show up in expression (cbuf), so */
+         /* just check for expression and variable name lengths.   */
+         /*--------------------------------------------------------*/
+         if (expression[0] == '-')
+         {
+             if (strlen(expression) == 1) return OP_NEGATION;
+             exp_getvfname(&expression[1], tbuf);
+             if (strlen(tbuf) != 0) return OP_NEGATION;
+         }
+
          /* failing these tests, the argument must be a numerical
             constant preceded by a plus or minus sign */
 
@@ -1112,7 +1133,7 @@ exp_getvfname( source, destination )
    while( source[ s_pos ] != '\0' )
       {
 
-      /* all aphabetical characters are acceptable */
+      /* all alphabetical characters are acceptable */
 
       if ( isalpha( source[ s_pos ] ) != 0 )
 
diff --git a/bwb_fnc.c b/bwb_fnc.c
index 50270ea..3a1dc19 100644
--- a/bwb_fnc.c
+++ b/bwb_fnc.c
@@ -24,6 +24,11 @@
 
 ****************************************************************/
 
+/*---------------------------------------------------------------*/
+/* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, */
+/* 11/1995 (eidetics@cerf.net).                                  */
+/*---------------------------------------------------------------*/
+
 #define FSTACKSIZE      32
 
 #include <stdio.h>
@@ -130,7 +135,9 @@ fnc_find( buffer )
    if ( init == FALSE )
       {
       init = TRUE;
-      if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
+
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( tbuf = CALLOC( MAXSTRINGSIZE + 1, sizeof( char ), "fnc_find" )) == NULL )
          {
 #if PROG_ERRORS
 	 bwb_error( "in fnc_find(): failed to find memory for tbuf" );
@@ -314,7 +321,9 @@ fnc_date( argc, argv, unique_id )
       {
       init = TRUE;
       var_make( &nvar, STRING );
-      if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
+
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( tbuf = CALLOC( MAXSTRINGSIZE + 1, sizeof( char ), "fnc_date" )) == NULL )
          {
 #if PROG_ERRORS
          bwb_error( "in fnc_date(): failed to get memory for tbuf" );
@@ -368,7 +377,9 @@ fnc_time( argc, argv, unique_id )
       {
       init = TRUE;
       var_make( &nvar, STRING );
-      if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
+
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( tbuf = CALLOC( MAXSTRINGSIZE + 1, sizeof( char ), "fnc_time" )) == NULL )
          {
 #if PROG_ERRORS
          bwb_error( "in fnc_time(): failed to get memory for tbuf" );
@@ -516,7 +527,9 @@ fnc_len( argc, argv, unique_id )
       {
       init = TRUE;
       var_make( &nvar, NUMBER );
-      if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
+
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( tbuf = CALLOC( MAXSTRINGSIZE + 1, sizeof( char ), "fnc_len" )) == NULL )
          {
 #if PROG_ERRORS
          bwb_error( "in fnc_len(): failed to get memory for tbuf" );
@@ -637,8 +650,9 @@ fnc_timer( argc, argv, unique_id  )
       }
 
    time( &now );
+   /* Following statement was (bnumber) (JBV) */
    * var_findnval( &nvar, nvar.array_pos )
-      = (float) fmod( (bnumber) now, (bnumber) (60*60*24));
+      = (float) fmod( (double) now, (double) (60*60*24));
 
    return &nvar;
    }
@@ -952,7 +966,9 @@ fnc_asc( argc, argv, unique_id )
       {
       init = TRUE;
       var_make( &nvar, NUMBER );
-      if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
+
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( tbuf = CALLOC( MAXSTRINGSIZE + 1, sizeof( char ), "fnc_asc" )) == NULL )
          {
 #if PROG_ERRORS
          bwb_error( "in fnc_asc(): failed to get memory for tbuf" );
@@ -1046,7 +1062,9 @@ fnc_string( argc, argv, unique_id )
       {
       init = TRUE;
       var_make( &nvar, STRING );
-      if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
+
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( tbuf = CALLOC( MAXSTRINGSIZE + 1, sizeof( char ), "fnc_string" )) == NULL )
          {
 #if PROG_ERRORS
          bwb_error( "in fnc_string(): failed to get memory for tbuf" );
@@ -1097,7 +1115,7 @@ fnc_string( argc, argv, unique_id )
 
 #if INTENSIVE_DEBUG
    sprintf( bwb_ebuf, "in fnc_string(): argument <%s> arg type <%c>, length <%d>",
-      argv[ 1 ].string, argv[ 1 ].type, length );
+      tbuf, argv[ 1 ].type, length );
    bwb_debug( bwb_ebuf );
    sprintf( bwb_ebuf, "in fnc_string(): type <%c>, c <0x%x>=<%c>",
       argv[ 1 ].type, c, c );
@@ -1320,7 +1338,9 @@ fnc_space( argc, argv, unique_id )
       {
       init = TRUE;
       var_make( &nvar, (int) STRING );
-      if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
+
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( tbuf = CALLOC( MAXSTRINGSIZE + 1, sizeof( char ), "fnc_space" )) == NULL )
          {
 #if PROG_ERRORS
          bwb_error( "in fnc_space(): failed to get memory for tbuf" );
@@ -1513,7 +1533,7 @@ fnc_erl( argc, argv, unique_id )
 
         DESCRIPTION:    This C function implements the BASIC
 			LOC() function. As implemented here,
-			this only workd for random-acess files.
+			this only works for random-acess files.
 
 	SYNTAX:		LOC( device-number )
 
@@ -1611,6 +1631,7 @@ fnc_eof( argc, argv, unique_id )
    static struct bwb_variable nvar;
    static int init = FALSE;
    int dev_number;
+   int cur_pos, end_pos; /* JBV */
 
 #if INTENSIVE_DEBUG
    sprintf( bwb_ebuf, "in fnc_loc(): received f_arg <%f> ",
@@ -1661,7 +1682,19 @@ fnc_eof( argc, argv, unique_id )
       bwb_error( err_devnum );
       * var_findnval( &nvar, nvar.array_pos ) = (bnumber) TRUE;
       }
-   else if ( feof( dev_table[ dev_number ].cfp ) == 0 )
+
+   /*------------------------------------------------------*/
+   /* feof() finds EOF when you read past the end of file. */
+   /* This is not how BASIC works, at least not GWBASIC.   */
+   /* The EOF function should return an EOF indication     */
+   /* when you are <at> the end of the file, not past it.  */
+   /* This routine was modified to reflect this.           */
+   /* (JBV, 10/15/95)                                      */
+   /*------------------------------------------------------*/
+
+   /*  else if ( feof( dev_table[ dev_number ].cfp ) == 0 ) */
+   else if ( ftell( dev_table[ dev_number ].cfp ) !=
+   dev_table [ dev_number ].lof )
       {
       * var_findnval( &nvar, nvar.array_pos ) = (bnumber) FALSE;
       }
@@ -1698,10 +1731,12 @@ fnc_lof( argc, argv, unique_id )
    static struct bwb_variable nvar;
    static int init = FALSE;
    int dev_number;
-#if UNIX_CMDS
+
+/* Following section no longer needed, removed by JBV */
+/* #if UNIX_CMDS
    static struct stat statbuf;
    int r;
-#endif
+#endif */
 
 #if INTENSIVE_DEBUG
    sprintf( bwb_ebuf, "in fnc_lof(): received f_arg <%f> ",
@@ -1742,7 +1777,8 @@ fnc_lof( argc, argv, unique_id )
 
    /* stat the file */
 
-#if UNIX_CMDS
+/* Following section no longer needed, removed by JBV */
+/* #if UNIX_CMDS
 
    r = stat( dev_table[ dev_number ].filename, &statbuf );
 
@@ -1760,13 +1796,15 @@ fnc_lof( argc, argv, unique_id )
       return NULL;
       }
 
-   * var_findnval( &nvar, nvar.array_pos ) = (bnumber) statbuf.st_size;
+   * var_findnval( &nvar, nvar.array_pos ) = (bnumber) statbuf.st_size; */
 
-#else
+/* #else */  /* Removed by JBV, no longer needed */
 
-   * var_findnval( &nvar, nvar.array_pos ) = (bnumber) FALSE;
+   /* * var_findnval( &nvar, nvar.array_pos ) = (bnumber) FALSE; */
+   * var_findnval( &nvar, nvar.array_pos ) =
+      (bnumber) dev_table[ dev_number ].lof; /* JBV */
 
-#endif
+/* #endif */  /* Removed by JBV, no longer needed */
 
    return &nvar;
    }
@@ -1806,7 +1844,9 @@ fnc_test( argc, argv, unique_id )
       {
       init = TRUE;
       var_make( &rvar, NUMBER );
-      if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
+
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( tbuf = CALLOC( MAXSTRINGSIZE + 1, sizeof( char ), "fnc_test" )) == NULL )
          {
 #if PROG_ERRORS
          bwb_error( "in fnc_test(): failed to get memory for tbuf" );
diff --git a/bwb_inp.c b/bwb_inp.c
index bd70c0c..20b5919 100644
--- a/bwb_inp.c
+++ b/bwb_inp.c
@@ -29,6 +29,11 @@
 
 ***************************************************************/
 
+/*---------------------------------------------------------------*/
+/* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, */
+/* 11/1995 (eidetics@cerf.net).                                  */
+/*---------------------------------------------------------------*/
+
 #include <stdio.h>
 #include <ctype.h>
 #include <math.h>
@@ -47,6 +52,7 @@ static int inp_assign( char *b, struct bwb_variable *v );
 static int inp_advws( FILE *f );
 static int inp_xgetc( FILE *f, int is_string );
 static int inp_eatcomma( FILE *f );
+static bnumber inp_numconst( char *expression ); /* JBV */
 #else
 static struct bwb_line *bwb_xinp();
 static struct bwb_line *inp_str();
@@ -55,10 +61,12 @@ static int inp_assign();
 static int inp_advws();
 static int inp_xgetc();
 static int inp_eatcomma();
+static bnumber inp_numconst(); /* JBV */
 #endif
 
 static char_saved = FALSE;
 static cs;
+static int last_inp_adv_rval = FALSE; /* JBV */
 
 /***************************************************************
 
@@ -621,7 +629,15 @@ bwb_input( l )
 
       /* advance past semicolon to beginning of variable */
 
-      suppress_qm = inp_adv( l->buffer, &( l->position ) );
+      /*--------------------------------------------------------*/
+      /* Since inp_const was just called and inp_adv is called  */
+      /* within that, it will have already noted and passed the */
+      /* comma by the time it gets here.  Therefore one must    */
+      /* refer instead to the last returned value for inp_adv!  */
+      /* (JBV, 10/95)                                           */
+      /*--------------------------------------------------------*/
+      /* suppress_qm = inp_adv( l->buffer, &( l->position ) ); */
+      suppress_qm = last_inp_adv_rval;
 
       /* print the prompt string */
 
@@ -772,7 +788,12 @@ bwb_xinp( l, f )
                tbuf );
             bwb_debug( bwb_ebuf );
 #endif
-            * var_findnval( v, v->array_pos ) = (bnumber) atof( tbuf );
+            /*------------------------------------------------------------*/
+            /* atof call replaced by inp_numconst, gets all input formats */
+            /* (JBV, 10/95)                                               */
+            /*------------------------------------------------------------*/
+            /* * var_findnval( v, v->array_pos ) = (bnumber) atof( tbuf ); */
+            * var_findnval( v, v->array_pos ) = inp_numconst( tbuf );
             break;
          }				/* end of switch for type-specific input */
 
@@ -801,7 +822,7 @@ bwb_xinp( l, f )
         FUNCTION:       inp_advws()
 
 	DESCRIPTION:    This C function advances past whitespace
-			inoput from a particular file or device.
+			input from a particular file or device.
 
 ***************************************************************/
 
@@ -1118,7 +1139,12 @@ inp_assign( b, v )
             }
          else
             {
-            *( var_findnval( v, v->array_pos )) = (bnumber) atof( b );
+            /*------------------------------------------------------------*/
+            /* atof call replaced by inp_numconst, gets all input formats */
+            /* (JBV, 10/95)                                               */
+            /*------------------------------------------------------------*/
+            /* *( var_findnval( v, v->array_pos )) = (bnumber) atof( b ); */
+            *( var_findnval( v, v->array_pos )) = inp_numconst( b );
             }
          break;
 
@@ -1178,8 +1204,10 @@ inp_adv( b, c )
          case '\0':		/* end of line */
          case ':': 		/* end of line segment */
             rval = TRUE;
+            last_inp_adv_rval = rval; /* JBV */
             return rval;
          default:
+            last_inp_adv_rval = rval; /* JBV */
             return rval;
          }
       }
@@ -1318,6 +1346,8 @@ bwb_line( l )
    FILE *inp_device;
    char tbuf[ MAXSTRINGSIZE + 1 ];
    char pstring[ MAXSTRINGSIZE + 1 ];
+   struct exp_ese *e; /* JBV */
+   int pos; /* JBV */
 
    /* assign default values */
 
@@ -1351,7 +1381,10 @@ bwb_line( l )
       ++l->position;
       adv_element( l->buffer, &( l->position ), tbuf );
       adv_ws( l->buffer, &( l->position ));
-      dev_no = atoi( tbuf );
+      /* dev_no = atoi( tbuf ); */  /* We really need more, added next (JBV) */
+      pos = 0;
+      e = bwb_exp( tbuf, FALSE, &pos );
+      dev_no = (int) exp_getnval( e );
 
 #if INTENSIVE_DEBUG
       sprintf( bwb_ebuf, "in bwb_line(): file number requested <%d>", dev_no );
@@ -1437,4 +1470,446 @@ bwb_line( l )
 
 #endif				/* COMMON_CMDS */
 
-
\ No newline at end of file
+/***************************************************************
+
+        FUNCTION:	inp_numconst()
+
+        DESCRIPTION:	This function interprets a numerical
+			constant.  Added by JBV 10/95
+
+***************************************************************/
+
+#if ANSI_C
+bnumber
+inp_numconst( char *expression )
+#else
+bnumber
+inp_numconst( expression )
+   char *expression;
+#endif
+   {
+   int base;                            /* numerical base for the constant */
+   static struct bwb_variable mantissa; /* mantissa of floating-point number */
+   static int init = FALSE;		/* is mantissa variable initialized? */
+   int exponent;                        /* exponent for floating point number */
+   int man_start;                       /* starting point of mantissa */
+   int s_pos;                           /* position in build string */
+   int build_loop;
+   int need_pm;
+   int i;
+   bnumber d;
+
+   /* Expression stack stuff */
+   char type;
+   bnumber nval;
+   char string[ MAXSTRINGSIZE + 1 ];
+   int pos_adv;
+
+   /* initialize the variable if necessary */
+
+#if INTENSIVE_DEBUG
+   strcpy( mantissa.name, "(mantissa)" );
+#endif
+
+   if ( init == FALSE )
+      {
+      init = TRUE;
+      var_make( &mantissa, NUMBER );
+      }
+
+   /* be sure that the array_pos[ 0 ] for mantissa is set to dim_base;
+      this is necessary because mantissa might be used before dim_base
+      is set */
+
+   mantissa.array_pos[ 0 ] = dim_base;
+
+#if INTENSIVE_DEBUG
+   sprintf( bwb_ebuf, "in inp_numconst(): received <%s>, eval <%c>",
+      expression, expression[ 0 ] );
+   bwb_debug( bwb_ebuf );
+#endif
+
+   need_pm = FALSE;
+   nval = (bnumber) 0;
+
+   /* check the first character(s) to determine numerical base
+      and starting point of the mantissa */
+
+   switch( expression[ 0 ] )
+      {
+      case '-':
+      case '+':
+      case '0':
+      case '1':
+      case '2':
+      case '3':
+      case '4':
+      case '5':
+      case '6':
+      case '7':
+      case '8':
+      case '9':
+      case '.':
+         base = 10;                     /* decimal constant */
+	 man_start = 0;                 /* starts at position 0 */
+	 need_pm = FALSE;
+         break;
+      case '&':                         /* hex or octal constant */
+         if ( ( expression[ 1 ] == 'H' ) || ( expression[ 1 ] == 'h' ))
+            {
+            base = 16;                  /* hexadecimal constant */
+            man_start = 2;              /* starts at position 2 */
+            }
+         else
+            {
+            base = 8;                   /* octal constant */
+            if ( ( expression[ 1 ] == 'O' ) || ( expression[ 1 ] == 'o' ))
+               {
+               man_start = 2;           /* starts at position 2 */
+               }
+            else
+               {
+               man_start = 1;           /* starts at position 1 */
+               }
+            }
+         break;
+      default:
+
+#if PROG_ERRORS
+         sprintf( bwb_ebuf, "expression <%s> is not a numerical constant.",
+            expression );
+         bwb_error( bwb_ebuf );
+#else
+         bwb_error( err_syntax );
+#endif
+         return (bnumber) 0;
+      }
+
+   /* now build the mantissa according to the numerical base */
+
+   switch( base )
+      {
+
+      case 10:                          /* decimal constant */
+
+         /* initialize counters */
+
+         pos_adv = man_start;
+         type = NUMBER;
+         string[ 0 ] = '\0';
+         s_pos = 0;
+         exponent = 0;
+         build_loop = TRUE;
+
+         /* loop to build the string */
+
+         while ( build_loop == TRUE )
+            {
+            switch( expression[ pos_adv ] )
+               {
+               case '-':                        /* prefixed plus or minus */
+               case '+':
+
+                  /* in the first position, a plus or minus sign can
+                     be added to the beginning of the string to be
+                     scanned */
+
+                  if ( pos_adv == man_start )
+                     {
+                     string[ s_pos ] = expression[ pos_adv ];
+                     ++pos_adv;  /* advance to next character */
+                     ++s_pos;
+                     string[ s_pos ] = '\0';
+                     }
+
+                  /* but in any other position, the plus or minus sign
+                     must be taken as an operator and thus as terminating
+                     the string to be scanned */
+
+                  else
+                     {
+                     build_loop = FALSE;
+                     }
+                  break;
+               case '.':                        /* note at least single precision */
+               case '0':                        /* or ordinary digit */
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9':
+                  string[ s_pos ] = expression[ pos_adv ];
+                  ++pos_adv;  /* advance to next character */
+                  ++s_pos;
+                  string[ s_pos ] = '\0';
+                  break;
+
+	       case '#':                        /* Microsoft-type precision indicator; ignored but terminates */
+	       case '!':                        /* Microsoft-type precision indicator; ignored but terminates */
+		  ++pos_adv;  /* advance to next character */
+		  type = NUMBER;
+		  exponent = FALSE;
+		  build_loop = FALSE;
+		  break;
+
+	       case 'E':                        /* exponential, single precision */
+               case 'e':
+                  ++pos_adv;  /* advance to next character */
+                  type = NUMBER;
+		  exponent = TRUE;
+                  build_loop = FALSE;
+		  break;
+
+               case 'D':                        /* exponential, double precision */
+               case 'd':
+                  ++pos_adv;  /* advance to next character */
+                  type = NUMBER;
+		  exponent = TRUE;
+                  build_loop = FALSE;
+                  break;
+
+               default:                         /* anything else, terminate */
+                  build_loop = FALSE;
+                  break;
+               }
+
+            }
+
+         /* assign the value to the mantissa variable */
+         
+#if NUMBER_DOUBLE
+         sscanf( string, "%lf", var_findnval( &mantissa, mantissa.array_pos ));
+#else
+         sscanf( string, "%f", var_findnval( &mantissa, mantissa.array_pos ));
+#endif
+
+#if INTENSIVE_DEBUG
+         sprintf( bwb_ebuf, "in inp_numconst(): read mantissa, string <%s> val <%lf>",
+            string, var_getnval( &mantissa ) );
+         bwb_debug( bwb_ebuf );
+#endif
+
+         /* test if integer bounds have been exceeded */
+
+         if ( type == NUMBER )
+            {
+            i = (int) var_getnval( &mantissa );
+            d = (bnumber) i;
+            if ( d != var_getnval( &mantissa ))
+               {
+               type = NUMBER;
+#if INTENSIVE_DEBUG
+               sprintf( bwb_ebuf, "in inp_numconst(): integer bounds violated, promote to NUMBER" );
+               bwb_debug( bwb_ebuf );
+#endif               
+               }
+            }
+
+         /* read the exponent if there is one */
+
+         if ( exponent == TRUE )
+            {
+
+	    /* allow a plus or minus once at the beginning */
+
+	    need_pm = TRUE;
+
+	    /* initialize counters */
+
+            string[ 0 ] = '\0';
+            s_pos = 0;
+            build_loop = TRUE;
+
+            /* loop to build the string */
+
+            while ( build_loop == TRUE )
+               {
+               switch( expression[ pos_adv ] )
+                  {
+		  case '-':                        /* prefixed plus or minus */
+                  case '+':
+
+		     if ( need_pm == TRUE )        /* only allow once */
+			{
+			string[ s_pos ] = expression[ pos_adv ];
+			++pos_adv;  /* advance to next character */
+			++s_pos;
+			string[ s_pos ] = '\0';
+			}
+		     else
+			{
+			build_loop = FALSE;
+			}
+		     break;
+
+		  case '0':                        /* or ordinary digit */
+                  case '1':
+                  case '2':
+                  case '3':
+                  case '4':
+                  case '5':
+                  case '6':
+                  case '7':
+                  case '8':
+                  case '9':
+
+                     string[ s_pos ] = expression[ pos_adv ];
+                     ++pos_adv;  /* advance to next character */
+                     ++s_pos;
+		     string[ s_pos ] = '\0';
+		     need_pm = FALSE;
+                     break;
+
+                  default:                         /* anything else, terminate */
+                     build_loop = FALSE;
+                     break;
+                  }
+
+               }                                /* end of build loop for exponent */
+
+            /* assign the value to the user variable */
+
+#if NUMBER_DOUBLE
+            sscanf( string, "%lf", &nval );
+#else
+            sscanf( string, "%f", &nval );
+#endif
+
+#if INTENSIVE_DEBUG
+	    sprintf( bwb_ebuf, "in inp_numconst(): exponent is <%d>",
+               (int) nval );
+            bwb_debug( bwb_ebuf );
+#endif
+
+            }                           /* end of exponent search */
+
+         if ( nval == (bnumber) 0 )
+            {
+            nval = var_getnval( &mantissa );
+            }
+         else
+            {
+            nval = var_getnval( &mantissa )
+               * pow( (bnumber) 10.0, (bnumber) nval );
+            }
+
+         break;
+
+      case 8:                           /* octal constant */
+
+         /* initialize counters */
+
+         pos_adv = man_start;
+         type = NUMBER;
+         string[ 0 ] = '\0';
+         s_pos = 0;
+         exponent = 0;
+         build_loop = TRUE;
+
+         /* loop to build the string */
+
+         while ( build_loop == TRUE )
+            {
+            switch( expression[ pos_adv ] )
+               {
+               case '0':                        /* or ordinary digit */
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+                  string[ s_pos ] = expression[ pos_adv ];
+                  ++pos_adv;  /* advance to next character */
+                  ++s_pos;
+                  string[ s_pos ] = '\0';
+                  break;
+
+               default:                         /* anything else, terminate */
+                  build_loop = FALSE;
+                  break;
+               }
+
+            }
+
+         /* now scan the string to determine the number */
+
+         sscanf( string, "%o", &i );
+         nval = (bnumber) i;
+
+         break;
+
+      case 16:                          /* hexadecimal constant */
+
+         /* initialize counters */
+
+         pos_adv = man_start;
+         type = NUMBER;
+         string[ 0 ] = '\0';
+         s_pos = 0;
+         exponent = 0;
+         build_loop = TRUE;
+
+         /* loop to build the string */
+
+         while ( build_loop == TRUE )
+            {
+            switch( expression[ pos_adv ] )
+               {
+               case '0':                        /* or ordinary digit */
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9':
+               case 'A':
+               case 'a':
+               case 'B':
+               case 'b':
+               case 'C':
+               case 'c':
+               case 'D':
+               case 'd':
+               case 'E':
+               case 'e':
+               case 'F': /* Don't forget these! (JBV) */
+               case 'f':
+                  string[ s_pos ] = expression[ pos_adv ];
+
+                  ++pos_adv;  /* advance to next character */
+                  ++s_pos;
+                  string[ s_pos ] = '\0';
+                  break;
+
+               default:                         /* anything else, terminate */
+                  build_loop = FALSE;
+                  break;
+               }
+
+            }
+
+         /* now scan the string to determine the number */
+
+         sscanf( string, "%x", &i );
+         nval = (bnumber) i;
+         break;
+      }
+
+#if INTENSIVE_DEBUG
+   sprintf( bwb_ebuf, "in inp_numconst(): precision <%c> value <%lf>",
+      type, nval );
+   bwb_debug( bwb_ebuf );
+#endif
+
+   return nval;
+
+   }
diff --git a/bwb_int.c b/bwb_int.c
index e81396d..5c44451 100644
--- a/bwb_int.c
+++ b/bwb_int.c
@@ -23,6 +23,14 @@
 
 ***************************************************************/
 
+/*---------------------------------------------------------------*/
+/* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, */
+/* 11/1995 (eidetics@cerf.net).                                  */
+/*                                                               */
+/* Those additionally marked with "DD" were at the suggestion of */
+/* Dale DePriest (daled@cadence.com).                            */
+/*---------------------------------------------------------------*/
+
 #include <stdio.h>
 #include <ctype.h>
 
@@ -85,7 +93,7 @@ adv_element( buffer, pos, element )
          case '=':
          case ' ':
          case '\t':
-         case '\0':
+         /* case '\0': */ /* Removed by JBV (found by DD) */
          case '\n':
          case '\r':
             if ( str_const == TRUE )
@@ -101,6 +109,15 @@ adv_element( buffer, pos, element )
                }
             break;
 
+         case '\0':                     /* Added by JBV (found by DD) */
+            if ( str_const == TRUE )    /* termination of string constant */
+               {
+               element[ e_pos ] = '\"';
+               element[ ++e_pos ] = '\0';
+               }
+            return TRUE;
+            break;
+
          case '\"':                     /* string constant */
             element[ e_pos ] = buffer[ *pos ];
             ++e_pos;
@@ -328,7 +345,9 @@ line_start( buffer, pos, lnpos, lnum, cmdpos, cmdnum, startpos )
    if ( init == FALSE )
       {
       init = TRUE;
-      if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
+
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( tbuf = CALLOC( MAXSTRINGSIZE + 1, sizeof( char ), "line_start")) == NULL )
          {
 #if PROG_ERRORS
 	 bwb_error( "in line_start(): failed to get memory for tbuf" );
@@ -736,7 +755,9 @@ bwb_numseq( buffer, start, end )
    if ( init == FALSE )
       {
       init = TRUE;
-      if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
+
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( tbuf = CALLOC( MAXSTRINGSIZE + 1, sizeof( char ), "bwb_numseq")) == NULL )
          {
 #if PROG_ERRORS
 	 bwb_error( "in bwb_numseq(): failed to find memory for tbuf" );
@@ -867,7 +888,14 @@ bwb_freeline( l )
 
    /* free arguments if there are any */
 
-   free( l );
+   /* Revised to FREE pass-thru calls by JBV */
+   if (l->buffer != NULL)
+   {
+       FREE( l->buffer, "bwb_freeline" );
+       l->buffer = NULL; /* JBV */
+   }
+   FREE( l, "bwb_freeline" );
+   l = NULL; /* JBV */
 
    return TRUE;
    }
@@ -952,4 +980,3 @@ is_eol( buffer, position )
 
    }
 
-
\ No newline at end of file
diff --git a/bwb_mes.h b/bwb_mes.h
index fcaba1f..f8f5903 100644
--- a/bwb_mes.h
+++ b/bwb_mes.h
@@ -23,6 +23,10 @@
 
 ***************************************************************/
 
+/*---------------------------------------------------------------*/
+/* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, */
+/* 11/1995 (eidetics@cerf.net).                                  */
+/*---------------------------------------------------------------*/
 
 #ifndef TRUE
 #define TRUE    1
@@ -391,6 +395,7 @@
 #define CMD_DEFINT	"DEFINT"
 #define CMD_DEFSNG	"DEFSNG"
 #define CMD_DEFSTR	"DEFSTR"
+#define CMD_MID		"MID$"
 #define CMD_CALL	"CALL"
 #define CMD_SUB		"SUB"
 #define CMD_FUNCTION	"FUNCTION"
@@ -409,6 +414,7 @@
 #define CMD_RANDOMIZE	"RANDOMIZE"
 #define CMD_FILES	"FILES"
 #define CMD_EDIT	"EDIT"
+#define CMD_RENUM	"RENUM"
 #define CMD_ERASE	"ERASE"
 #define CMD_SWAP	"SWAP"
 #define CMD_NAME	"NAME"
@@ -471,4 +477,3 @@ extern char err_noprogfile[];
 
 
 
-
\ No newline at end of file
diff --git a/bwb_mth.c b/bwb_mth.c
index 7df2c88..e3aac97 100644
--- a/bwb_mth.c
+++ b/bwb_mth.c
@@ -23,6 +23,11 @@
 
 ****************************************************************/
 
+/*---------------------------------------------------------------*/
+/* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, */
+/* 11/1995 (eidetics@cerf.net).                                  */
+/*---------------------------------------------------------------*/
+
 #include <stdio.h>
 #include <ctype.h>
 #include <math.h>
@@ -154,8 +159,9 @@ fnc_core( argc, argv, unique_id  )
    switch( unique_id )
       {
       case F_ABS:
+         /* Added double recast here (JBV) */
 	 * var_findnval( &nvar, nvar.array_pos ) =
-	    (bnumber) fabs( var_getnval( &( argv[ 0 ] ) ) );
+	    (bnumber) fabs( (double) var_getnval( &( argv[ 0 ] ) ) );
 	 break;
       case F_ATN:
 	 * var_findnval( &nvar, nvar.array_pos )
@@ -166,8 +172,9 @@ fnc_core( argc, argv, unique_id  )
 	    = (bnumber) cos( (double) var_getnval( &( argv[ 0 ] ) ) );
 	 break;
       case F_EXP:
+         /* Added double recast here (JBV) */
 	 * var_findnval( &nvar, nvar.array_pos )
-	    = (bnumber) exp( var_getnval( &( argv[ 0 ] ) ) );
+	    = (bnumber) exp( (double) var_getnval( &( argv[ 0 ] ) ) );
 	 break;
       case F_INT:
 	 * var_findnval( &nvar, nvar.array_pos )
@@ -178,7 +185,9 @@ fnc_core( argc, argv, unique_id  )
 	    = (bnumber) log( (double) var_getnval( &( argv[ 0 ] ) ) );
 	 break;
       case F_RND:
-	 * var_findnval( &nvar, nvar.array_pos ) = (float) rand() / RAND_MAX;
+         /* Added bnumber recast here (JBV) */
+	 * var_findnval( &nvar, nvar.array_pos )
+	    = (bnumber) ( (float) rand() / RAND_MAX );
 	 break;
       case F_SGN:
 	 nval = var_getnval( &( argv[ 0 ] ));
@@ -296,8 +305,9 @@ fnc_abs( argc, argv, unique_id  )
    bwb_debug( bwb_ebuf );
 #endif
 
+   /* Added double recast here (JBV) */
    * var_findnval( &nvar, nvar.array_pos ) = 
-      (bnumber) fabs( var_getnval( &( argv[ 0 ] ) ) );
+      (bnumber) fabs( (double) var_getnval( &( argv[ 0 ] ) ) );
 
    return &nvar;
 
@@ -339,7 +349,9 @@ fnc_rnd( argc, argv, unique_id  )
       var_make( &nvar, NUMBER );
       }
 
-   * var_findnval( &nvar, nvar.array_pos ) = (float) rand() / RAND_MAX;
+   /* Added bnumber recast here (JBV) */
+   * var_findnval( &nvar, nvar.array_pos )
+      = (bnumber) ( (float) rand() / RAND_MAX );
 
    return &nvar;
    }
@@ -987,8 +999,9 @@ fnc_exp( argc, argv, unique_id )
 
    /* assign values */
 
+   /* Added double recast here (JBV) */
    * var_findnval( &nvar, nvar.array_pos ) 
-      = (bnumber) exp( var_getnval( &( argv[ 0 ] ) ) );
+      = (bnumber) exp( (double) var_getnval( &( argv[ 0 ] ) ) );
 
    return &nvar;
    }
@@ -1030,7 +1043,9 @@ fnc_val( argc, argv, unique_id )
       {
       init = TRUE;
       var_make( &nvar, NUMBER );
-      if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
+
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( tbuf = CALLOC( MAXSTRINGSIZE + 1, sizeof( char ), "fnc_val" )) == NULL )
          {
 #if PROG_ERRORS
          bwb_error( "in fnc_val(): failed to get memory for tbuf" );
@@ -1078,6 +1093,9 @@ fnc_val( argc, argv, unique_id )
    /* read the value */
 
    str_btoc( tbuf, var_getsval( &( argv[ 0 ] ) ));
+   if ( strlen( tbuf ) == 0 ) /* JBV */
+      *var_findnval( &nvar, nvar.array_pos ) = (bnumber) 0;
+   else
 #if NUMBER_DOUBLE
    sscanf( tbuf, "%lf",
        var_findnval( &nvar, nvar.array_pos ) );
@@ -1122,7 +1140,9 @@ fnc_str( argc, argv, unique_id )
       {
       init = TRUE;
       var_make( &nvar, STRING );
-      if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
+
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( tbuf = CALLOC( MAXSTRINGSIZE + 1, sizeof( char ), "fnc_str" )) == NULL )
          {
 #if PROG_ERRORS
          bwb_error( "in fnc_str(): failed to get memory for tbuf" );
@@ -1203,7 +1223,9 @@ fnc_hex( argc, argv, unique_id )
       {
       init = TRUE;
       var_make( &nvar, STRING );
-      if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
+
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( tbuf = CALLOC( MAXSTRINGSIZE + 1, sizeof( char ), "fnc_hex" )) == NULL )
          {
 #if PROG_ERRORS
          bwb_error( "in fnc_hex(): failed to get memory for tbuf" );
@@ -1278,7 +1300,9 @@ fnc_oct( argc, argv, unique_id )
       {
       init = TRUE;
       var_make( &nvar, STRING );
-      if ( ( tbuf = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
+
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( tbuf = CALLOC( MAXSTRINGSIZE + 1, sizeof( char ), "fnc_oct" )) == NULL )
          {
 #if PROG_ERRORS
          bwb_error( "in fnc_oct(): failed to get memory for tbuf" );
@@ -1314,7 +1338,9 @@ fnc_oct( argc, argv, unique_id )
 
    /* format as octal integer */
 
-   sprintf( tbuf, "%o", (int) var_getnval( &( argv[ 0 ] ) ) );
+   /* Revised by JBV */
+   /* sprintf( tbuf, "%o", (int) var_getnval( &( argv[ 0 ] ) ) ); */
+   sprintf( tbuf, "%o", (int) trnc_int( (bnumber) var_getnval( &( argv[ 0 ] )) ) );
    str_ctob( var_findsval( &nvar, nvar.array_pos ), tbuf );
    return &nvar;
    }
@@ -1388,6 +1414,7 @@ fnc_mki( argc, argv, unique_id  )
    for ( i = 0; i < sizeof( int ); ++i )
       {
       tbuf[ i ] = an_integer.the_chars[ i ];
+      tbuf[ i + 1 ] = '\0';
       }
    b = var_getsval( &nvar );
    b->length = sizeof( int );
@@ -1545,6 +1572,7 @@ fnc_mks( argc, argv, unique_id  )
    for ( i = 0; i < sizeof( float ); ++i )
       {
       tbuf[ i ] = a_float.the_chars[ i ];
+      tbuf[ i + 1 ] = '\0';
       }
    b = var_getsval( &nvar );
    b->length = sizeof( float );
@@ -1807,7 +1835,7 @@ fnc_cvs( argc, argv, unique_id  )
 	DESCRIPTION:    This C function implements the BASIC
 			function CSNG().  As implemented,
 			this is a pseudo-function, since
-			all bwBASIC numerial values have the
+			all bwBASIC numerical values have the
 			same precision.
 
 	SYNTAX:		CSNG( number )
@@ -1955,18 +1983,19 @@ trnc_int( x )
    bnumber x;
 #endif
    {
-   bnumber sign;
+   double sign; /* Was bnumber (JBV) */
 
    if ( x < (bnumber) 0.0 )
       {
-      sign = (bnumber) -1.0;
+      sign = (double) -1.0; /* Was bnumber (JBV) */
       }
    else
       {
-      sign = (bnumber) 1.0;
+      sign = (double) 1.0; /* Was bnumber (JBV) */
       }
 
-   return (bnumber) ( floor( fabs( x )) * sign );
+   /* Added double recast here (JBV) */
+   return (bnumber) ( floor( fabs( (double) x )) * sign );
    }
 
 /***************************************************************
@@ -1991,27 +2020,27 @@ round_int( x )
 
    if ( x < (bnumber) 0.00 )
       {
-      if ( (bnumber) fabs( (bnumber) floor( x ) - x ) < (bnumber) 0.500 )
+      /* Added double recasts here (JBV) */
+      if ( (bnumber) fabs( (bnumber) floor( (double) x ) - x ) < (bnumber) 0.500 )
 	 {
-	 return (bnumber) floor( x );
+	 return (bnumber) floor( (double) x );
 	 }
       else
 	 {
-	 return (bnumber) ceil( x );
+	 return (bnumber) ceil( (double) x );
 	 }
       }
    else
       {
-      if ( ( x - (bnumber) floor( x )) < (bnumber) 0.500 )
+      if ( ( x - (bnumber) floor( (double) x )) < (bnumber) 0.500 )
 	 {
-	 return (bnumber) floor( x );
+	 return (bnumber) floor( (double) x );
 	 }
       else
 	 {
-	 return (bnumber) ceil( x );
+	 return (bnumber) ceil( (double) x );
 	 }
       }
    }
 
 
-
\ No newline at end of file
diff --git a/bwb_ops.c b/bwb_ops.c
index bb2bb3e..3cfd103 100644
--- a/bwb_ops.c
+++ b/bwb_ops.c
@@ -23,6 +23,11 @@
 
 ****************************************************************/
 
+/*---------------------------------------------------------------*/
+/* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, */
+/* 11/1995 (eidetics@cerf.net).                                  */
+/*---------------------------------------------------------------*/
+
 #include <stdio.h>
 #include <ctype.h>
 #include <math.h>
@@ -52,6 +57,7 @@ static int op_or( int level, int precision );
 static int op_and( int level, int precision );
 static int op_not( int level, int precision );
 static int op_xor( int level, int precision );
+static int op_negation( int level, int precision ); /* JBV */
 static int op_islevelstr( int level );
 static int op_getprecision( int level );
 static int op_isoperator( int operation );
@@ -76,6 +82,7 @@ static int op_or();
 static int op_and();
 static int op_not();
 static int op_xor();
+static int op_negation(); /* JBV */
 static int op_islevelstr();
 static int op_getprecision();
 static int op_isoperator();
@@ -312,6 +319,10 @@ op_oplevel( level )
             op_exponent( level, precision );
             break;
 
+         case OP_NEGATION: /* JBV */
+            op_negation( level, precision );
+            break;
+
          default:
 #if PROG_ERRORS
             sprintf( bwb_ebuf, "PROGRAMMING ERROR: operator <%d> not (yet) supported.", CURTASK exps[ level ].operation );
@@ -395,8 +406,10 @@ op_add( level, precision )
 #endif
    {
    int error_condition;
+   static bstring b; /* JBV */
 
    error_condition = FALSE;
+   b.rab = FALSE; /* JBV */
 
    switch( precision )
       {
@@ -435,8 +448,15 @@ op_add( level, precision )
             bwb_debug( bwb_ebuf );
 #endif
 
-            str_cat( exp_getsval( &( CURTASK exps[ level - 1 ] ) ), 
-               exp_getsval( &( CURTASK exps[ level + 1 ] ) ) );
+            /* Removed by JBV (incomplete, modifies wrong string variable!) */
+            /* str_cat( exp_getsval( &( CURTASK exps[ level - 1 ] ) ), 
+               exp_getsval( &( CURTASK exps[ level + 1 ] ) ) ); */
+
+            /* Added by JBV */
+            str_btob( &b, exp_getsval( &( CURTASK exps[ level - 1 ] ) ) );
+            str_cat( &b, exp_getsval( &( CURTASK exps[ level + 1 ] ) ) );
+            str_btob( &( CURTASK exps[ level - 1 ].sval ), &b );
+            CURTASK exps[ level - 1 ].operation = CONST_STRING;
 
 #if INTENSIVE_DEBUG
             sprintf( bwb_ebuf, "in op_add(): str_cat() returns <%d>-byte string to level <%d>",
@@ -730,11 +750,7 @@ op_assign( level, precision )
 
       case NUMBER:
          * var_findnval( CURTASK exps[ level - 1 ].xvar, 
-#ifdef OLDWAY
-	    CURTASK exps[ level - 1 ].xvar->array_pos )  =
-#else
-	    CURTASK exps[ level - 1 ].array_pos )  =
-#endif
+            CURTASK exps[ level - 1 ].array_pos ) =
             CURTASK exps[ level - 1 ].nval = 
             exp_getnval( &( CURTASK exps[ level + 1 ] ) );
          break;
@@ -1522,7 +1538,7 @@ op_intdiv( level, precision )
 	FUNCTION:       op_or()
 
 	DESCRIPTION:    This function compares two integers and
-			performs a logical NOT on them.
+			performs a logical OR on them.
 
 ***************************************************************/
 
@@ -1579,7 +1595,7 @@ op_or( level, precision )
 	FUNCTION:       op_and()
 
 	DESCRIPTION:    This function compares two integers and
-			performs a logical NOT on them.
+			performs a logical AND on them.
 
 ***************************************************************/
 
@@ -1636,8 +1652,8 @@ op_and( level, precision )
 
 	FUNCTION:       op_not()
 
-	DESCRIPTION:    This function compares two integers and
-			performs a logical NOT on them.
+	DESCRIPTION:    This function performs a logical NOT on
+			the integer to the right.
 
 ***************************************************************/
 
@@ -1682,7 +1698,7 @@ op_not( level, precision )
 
 #if INTENSIVE_DEBUG
          sprintf( bwb_ebuf, "in op_not(): result is <%d>, precision <%c>",
-            (int) r, precision );
+            (unsigned int) exp_getnval( &( CURTASK exps[ level ] )), precision );
          bwb_debug( bwb_ebuf );
 #endif
 
@@ -1713,7 +1729,7 @@ op_not( level, precision )
 	FUNCTION:       op_xor()
 
 	DESCRIPTION:    This function compares two integers and
-			performs a logical NOT on them.
+			performs a logical XOR on them.
 
 ***************************************************************/
 
@@ -1767,6 +1783,83 @@ op_xor( level, precision )
 
 /***************************************************************
 
+	FUNCTION:       op_negation()
+
+	DESCRIPTION:    This function performs a negation on the
+			element to the right.
+			Added by JBV 10/95
+
+***************************************************************/
+
+#if ANSI_C
+static int
+op_negation( int level, int precision )
+#else
+static int
+op_negation( level, precision )
+   int level;
+   int precision;
+#endif
+   {
+
+   switch( precision )
+      {
+      case STRING:
+
+
+         /* both sides of the operation should be numbers for
+            logical comparison; if not, report an error */
+
+#if PROG_ERRORS
+         sprintf( bwb_ebuf, "Strings cannot be compared logically." );
+         bwb_error( bwb_ebuf );
+#else
+         bwb_error( err_mismatch );
+#endif
+
+         break;
+
+      default:
+
+#if INTENSIVE_DEBUG
+         sprintf( bwb_ebuf, "in op_negation(): argument is <%f>, precision <%c>",
+            exp_getnval( &( CURTASK exps[ level + 1 ] )), precision );
+         bwb_debug( bwb_ebuf );
+#endif
+
+         CURTASK exps[ level ].nval = (bnumber)
+            -( exp_getnval( &( CURTASK exps[ level + 1 ] )) );
+
+#if INTENSIVE_DEBUG
+         sprintf( bwb_ebuf, "in op_negation(): result is <%f>, precision <%c>",
+            exp_getnval( &( CURTASK exps[ level ] )), precision );
+         bwb_debug( bwb_ebuf );
+#endif
+
+         break;
+      }
+
+   /* set variable type to requested precision (JBV) */
+
+   CURTASK exps[ level ].type = (char) precision;
+   CURTASK exps[ level ].operation = NUMBER;
+
+   /* decrement the stack once */
+
+   op_pulldown( 1 );
+
+#if INTENSIVE_DEBUG
+   sprintf( bwb_ebuf, "in op_negation(): CURTASK expsc <%d>, level <%d> result <%f>",
+      CURTASK expsc, level, CURTASK exps[ CURTASK expsc ].nval );
+   bwb_debug( bwb_ebuf );
+#endif
+
+   return TRUE;
+
+   }
+
+/***************************************************************
+
 	FUNCTION:       op_islevelstr()
 
 	DESCRIPTION:    This function determines whether the
@@ -1903,8 +1996,18 @@ op_pulldown( how_far )
    while ( CURTASK expsc >= ( level + how_far ) )
       {
 
+      /*------------------------------------------------------*/
+      /* But before memcpy, deallocate sbuffer for level, and */
+      /* afterwards, set sbuffer for level + how_far to NULL! */
+      /* Else konfusion reigns the next time around... (JBV)  */
+      /*------------------------------------------------------*/
+
+      if( CURTASK exps[ level ].sval.sbuffer != NULL ) /* JBV */
+         FREE( CURTASK exps[ level ].sval.sbuffer, "op_pulldown" );
       memcpy( &CURTASK exps[ level ], &CURTASK exps[ level + how_far ],
          (size_t) ( sizeof( struct exp_ese )) );
+      CURTASK exps[ level + how_far ].sval.sbuffer = NULL; /* JBV */
+
       ++level;
 
       }
diff --git a/bwb_par.c b/bwb_par.c
index db05e98..38e0a5f 100644
--- a/bwb_par.c
+++ b/bwb_par.c
@@ -25,6 +25,11 @@
 
 ***************************************************************/
 
+/*---------------------------------------------------------------*/
+/* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, */
+/* 11/1995 (eidetics@cerf.net).                                  */
+/*---------------------------------------------------------------*/
+
 #include <stdio.h>
 
 #include "bwbasic.h"
@@ -69,7 +74,8 @@ bwb_newtask( task_requested )
 
    /* get memory for task structure */
 
-   if ( ( bwb_tasks[ task_requested ] = calloc( 1, sizeof( struct bwb_task ) ) )
+   /* Revised to CALLOC pass-thru call by JBV */
+   if ( ( bwb_tasks[ task_requested ] = CALLOC( 1, sizeof( struct bwb_task ), "bwb_newtask" ) )
       == NULL )
       {
 #if PROG_ERRORS
@@ -107,4 +113,3 @@ bwb_newtask( task_requested )
 #endif
 
 
-
\ No newline at end of file
diff --git a/bwb_prn.c b/bwb_prn.c
index baf0377..5085b0a 100644
--- a/bwb_prn.c
+++ b/bwb_prn.c
@@ -23,6 +23,11 @@
 
 ***************************************************************/
 
+/*---------------------------------------------------------------*/
+/* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, */
+/* 11/1995 (eidetics@cerf.net).                                  */
+/*---------------------------------------------------------------*/
+
 #include <stdio.h>
 #include <ctype.h>
 #include <math.h>
@@ -103,7 +108,9 @@ bwb_print( l )
    if ( init == FALSE )
       {
       init = TRUE;
-      if ( ( s_buffer = calloc( MAXSTRINGSIZE + 1, sizeof(char) ) ) == NULL )
+
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( s_buffer = CALLOC( MAXSTRINGSIZE + 1, sizeof(char), "bwb_print") ) == NULL )
          {
 #if PROG_ERRORS
          bwb_error( "in bwb_print(): failed to get memory for s_buffer" );
@@ -232,6 +239,9 @@ bwb_xprint( l, f )
    static char *element;
    static char *prnbuf;
    static int init = FALSE;
+   register int i, j; /* JBV */
+   int dig_pos, dec_pos; /* JBV */
+   char tbuf[ MAXSTRINGSIZE + 1 ]; /* JBV */
 #if INTENSIVE_DEBUG || TEST_BSTRING
    bstring *b;
 #endif
@@ -241,7 +251,9 @@ bwb_xprint( l, f )
    if ( init == FALSE )
       {
       init = TRUE;
-      if ( ( format_string = calloc( MAXSTRINGSIZE + 1, sizeof(char) ) ) == NULL )
+
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( format_string = CALLOC( MAXSTRINGSIZE + 1, sizeof(char), "bwb_xprint") ) == NULL )
          {
 #if PROG_ERRORS
          bwb_error( "in bwb_xprint(): failed to get memory for format_string" );
@@ -249,7 +261,8 @@ bwb_xprint( l, f )
          bwb_error( err_getmem );
 #endif
          }
-      if ( ( output_string = calloc( MAXSTRINGSIZE + 1, sizeof(char) ) ) == NULL )
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( output_string = CALLOC( MAXSTRINGSIZE + 1, sizeof(char), "bwb_xprint") ) == NULL )
          {
 #if PROG_ERRORS
          bwb_error( "in bwb_xprint(): failed to get memory for output_string" );
@@ -257,7 +270,8 @@ bwb_xprint( l, f )
          bwb_error( err_getmem );
 #endif
          }
-      if ( ( element = calloc( MAXSTRINGSIZE + 1, sizeof(char) ) ) == NULL )
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( element = CALLOC( MAXSTRINGSIZE + 1, sizeof(char), "bwb_xprint") ) == NULL )
          {
 #if PROG_ERRORS
          bwb_error( "in bwb_xprint(): failed to get memory for element buffer" );
@@ -265,7 +279,8 @@ bwb_xprint( l, f )
          bwb_error( err_getmem );
 #endif
          }
-      if ( ( prnbuf = calloc( MAXSTRINGSIZE + 1, sizeof(char) ) ) == NULL )
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( prnbuf = CALLOC( MAXSTRINGSIZE + 1, sizeof(char), "bwb_xprint") ) == NULL )
          {
 #if PROG_ERRORS
          bwb_error( "in bwb_xprint(): failed to get memory for prnbuf" );
@@ -425,8 +440,9 @@ bwb_xprint( l, f )
                   bwb_error( err_mismatch );
 #endif
                   }
-               sprintf( output_string, "%.*s", format->width,
-                  element );
+               if ( format->width == -1 ) /* JBV */
+                  sprintf( output_string, "%s", element );
+               else sprintf( output_string, "%.*s", format->width, element );
 
 #if INTENSIVE_DEBUG
                sprintf( bwb_ebuf, "in bwb_xprint(): output string <%s>",
@@ -434,7 +450,7 @@ bwb_xprint( l, f )
                bwb_debug( bwb_ebuf );
 #endif
 
-               prn_xprintf( f, output_string );
+               prn_xxprintf( f, output_string ); /* Was prn_xprintf (JBV) */
                break;
 
 	    case NUMBER:
@@ -449,22 +465,116 @@ bwb_xprint( l, f )
 
 	       if ( format->exponential == TRUE )
 		  {
-		  sprintf( output_string, "%e",
-		     exp_getnval( e ) );
+                  /*------------------------------------------------------*/
+                  /* NOTE: Width and fill have no effect on C exponential */
+                  /* format (JBV)                                         */
+                  /*------------------------------------------------------*/
+		  if ( format->sign == TRUE ) /* Added by JBV */
+                     sprintf( output_string, "%+e", exp_getnval( e ) );
+		  else
+                     sprintf( output_string, "%e", exp_getnval( e ) );
 		  }
 	       else
 		  {
+                  /*---------------------------------------------------*/
+                  /* NOTE: Minus, commas, and money are only valid for */
+                  /* floating point format (JBV)                       */
+                  /*---------------------------------------------------*/
+		  if ( format->sign == TRUE ) /* Added by JBV */
+		  sprintf( output_string, "%+*.*f",
+		     format->width, format->precision, exp_getnval( e ) );
+		  else if ( format->minus == TRUE ) /* Added by JBV */
+                  {
+		      sprintf( output_string, "%*.*f",
+		         format->width, format->precision, exp_getnval( e ) );
+                      for (i = 0; i < strlen( output_string ); ++i )
+                      {
+                          if ( output_string[ i ] != ' ' )
+                          {
+                              if ( output_string[ i ] == '-' )
+                              {
+                                  output_string[ i ] = ' ';
+                                  strcat( output_string, "-" );
+                              }
+                              else strcat( output_string, " " );
+                              break;
+                          }
+                      }
+                  }
+		  else
 		  sprintf( output_string, "%*.*f",
 		     format->width, format->precision, exp_getnval( e ) );
+
+                  if ( format->commas == TRUE ) /* Added by JBV */
+                  {
+                      dig_pos = -1;
+                      dec_pos = -1;
+                      for ( i = 0; i < strlen( output_string ); ++i )
+                      {
+                          if ( ( isdigit( output_string[ i ] ) != 0 )
+                          && ( dig_pos == -1 ) )
+                             dig_pos = i;
+                          if ( ( output_string[ i ] == '.' )
+                          && ( dec_pos == -1 ) )
+                             dec_pos = i;
+                          if ( ( dig_pos != -1 ) && ( dec_pos != -1 ) ) break;
+                      }
+                      if ( dec_pos == -1 ) dec_pos = strlen( output_string );
+                      j = 0;
+                      for ( i = 0; i < strlen( output_string ); ++i )
+                      {
+                          if ( ( ( dec_pos - i ) % 3 == 0 )
+                          && ( i > dig_pos ) && ( i < dec_pos ) )
+                          {
+                              tbuf[ j ] = ',';
+                              ++j;
+                              tbuf[ j ] = '\0';
+                          }
+                          tbuf[ j ] = output_string[ i ];
+                          ++j;
+                          tbuf[ j ] = '\0';
+                      }
+                      strcpy( output_string,
+                         &tbuf[ strlen( tbuf ) - strlen( output_string ) ] );
+                  }
+
+                  if ( format->money == TRUE ) /* Added by JBV */
+                  {
+                      for ( i = 0; i < strlen( output_string ); ++i )
+                      {
+                          if ( output_string[ i ] != ' ' )
+                          {
+                              if ( i > 0 )
+                              {
+                                  if ( isdigit( output_string[ i ] ) == 0 )
+                                  {
+                                      output_string[ i - 1 ]
+                                         = output_string[ i ];
+                                      output_string[ i ] = '$';
+                                  }
+                                  else output_string[ i - 1 ] = '$';
+                              }
+                              break;
+                          }
+                      }
+                  }
+
 		  }
 
+                  if ( format->fill == '*' ) /* Added by JBV */
+                  for ( i = 0; i < strlen( output_string ); ++i )
+                  {
+                     if ( output_string[ i ] != ' ' ) break;
+                     output_string[ i ] = '*';
+                  }
+
 #if INTENSIVE_DEBUG
 	       sprintf( bwb_ebuf, "in bwb_xprint(): output number <%f> string <%s>",
 		  exp_getnval( e ), output_string );
 	       bwb_debug( bwb_ebuf );
 #endif
 
-               prn_xprintf( f, output_string );
+               prn_xxprintf( f, output_string ); /* Was prn_xprintf (JBV) */
                break;
 
 	    default:
@@ -521,7 +631,9 @@ bwb_xprint( l, f )
             break;
 #endif
          case ',':		/* tab over */
-            xputc( f, '\t' );
+            /* Tab only if there's no format specification! (JBV) */
+            if (( fs_pos == -1 ) || ( strlen( element ) == 0 ))
+               xputc( f, '\t' );
             ++l->position;
             adv_ws( l->buffer, &( l->position ) );
             break;
@@ -536,6 +648,9 @@ bwb_xprint( l, f )
 
       }				/* end of loop through print elements */
 
+   if (( fs_pos > -1 ) && ( strlen( element ) > 0 ))
+      format = get_prnfmt( format_string, &fs_pos, f ); /* Finish up (JBV) */
+
    /* call prn_cr() to print a CR if it is not overridden by a
       concluding ';' mark */
 
@@ -593,7 +708,7 @@ get_prnfmt( buffer, position, f )
 
    /* advance past whitespace */
 
-   adv_ws( buffer, position );
+   /* adv_ws( buffer, position ); */  /* Don't think we want this (JBV) */
 
    /* check first character: a lost can be decided right here */
 
@@ -610,7 +725,9 @@ get_prnfmt( buffer, position, f )
       switch( buffer[ *position ] )
          {
          case ' ':		/* end of this format segment */
-            loop = FALSE;
+            xxputc( f, buffer[ *position ] ); /* Gotta output it (JBV) */
+            ++( *position ); /* JBV */
+            if (retstruct.type != FALSE) loop = FALSE; /* JBV */
             break;
          case '\0':		/* end of format string */
          case '\n':
@@ -619,13 +736,20 @@ get_prnfmt( buffer, position, f )
             return &retstruct;
          case '_':		/* print next character as literal */
             ++( *position );
-            xputc( f, buffer[ *position ] );
+            xxputc( f, buffer[ *position ] ); /* Not xputc, no tabs (JBV) */
             ++( *position );
             break;
 
 	 case '!':
             retstruct.type = STRING;
             retstruct.width = 1;
+            ++( *position ); /* JBV */
+            return &retstruct;
+
+	 case '&': /* JBV */
+            retstruct.type = STRING;
+            retstruct.width = -1; 
+            ++( *position );
             return &retstruct;
 
 	 case '\\':
@@ -649,18 +773,22 @@ get_prnfmt( buffer, position, f )
                }
             return &retstruct;
          case '$':
+            ++retstruct.width; /* JBV */
             ++( *position );
             retstruct.money = TRUE;
             if ( buffer[ *position ] == '$' )
                {
+               ++retstruct.width; /* JBV */
                ++( *position );
                }
             break;
          case '*':
+            ++retstruct.width; /* JBV */
             ++( *position );
             retstruct.fill = '*';
             if ( buffer[ *position ] == '*' )
                {
+               ++retstruct.width; /* JBV */
                ++( *position );
                }
             break;
@@ -670,14 +798,17 @@ get_prnfmt( buffer, position, f )
             break;
          case '#':
             retstruct.type = NUMBER;		/* for now */
-            ++( *position );
-            for ( retstruct.width = 1; buffer[ *position ] == '#'; ++( *position ) )
+            /* ++( *position ); */  /* Removed by JBV */
+            /* The initial condition shouldn't be retstruct.width = 1 (JBV) */
+            for ( ; buffer[ *position ] == '#'; ++( *position ) )
                {
                ++retstruct.width;
                }
             if ( buffer[ *position ] == ',' )
                {
                retstruct.commas = TRUE;
+               ++retstruct.width; /* JBV */
+               ++( *position ); /* JBV */
                }
             if ( buffer[ *position ] == '.' )
                {
@@ -706,6 +837,11 @@ get_prnfmt( buffer, position, f )
                }
             return &retstruct;
 
+	 default: /* JBV */
+            xxputc( f, buffer[ *position ] ); /* Gotta output it (JBV) */
+            ++( *position );
+            break;
+
          }
       }					/* end of loop */
 
@@ -838,6 +974,42 @@ prn_xprintf( f, buffer )
 
 /***************************************************************
 
+        FUNCTION:       prn_xxprintf()
+
+	DESCRIPTION:    This function outputs a null-terminated
+			string to a specified file or output
+			device without expanding tabs.
+			Added by JBV 10/95
+
+***************************************************************/
+
+#if ANSI_C
+int
+prn_xxprintf( FILE *f, char *buffer )
+#else
+int
+prn_xxprintf( f, buffer )
+   FILE *f;
+   char *buffer;
+#endif
+   {
+   char *p;
+
+   /* DO NOT try anything so stupid as to run bwb_debug() from
+      here, because it will create an endless loop. And don't
+      ask how I know. */
+
+   for ( p = buffer; *p != '\0'; ++p )
+      {
+      xxputc( f, *p );
+      }
+
+   return TRUE;
+
+   }
+
+/***************************************************************
+
         FUNCTION:       xputc()
 
 	DESCRIPTION:    This function outputs a character to a
@@ -1111,11 +1283,11 @@ prn_precision( v )
 
 #if INTENSIVE_DEBUG
       sprintf( bwb_ebuf, "in prn_precision(): fmod( %f, %f ) = %.12f",
-         nval, d, fmod( nval, d ) );
+         nval, d, fmod( (double) nval, (double) d ) );
       bwb_debug( bwb_ebuf );
 #endif
 
-      if ( fmod( nval, d ) < 0.0000001 )
+      if ( fmod( (double) nval, (double) d ) < 0.0000001 ) /* JBV */
          {
          return r;
          }
@@ -1187,6 +1359,8 @@ bwb_lerror( l )
    {
    char tbuf[ MAXSTRINGSIZE + 1 ];
    int n;
+   struct exp_ese *e; /* JBV */
+   int pos; /* JBV */
 
 #if INTENSIVE_DEBUG
    sprintf( bwb_ebuf, "in bwb_lerror(): entered function " );
@@ -1211,7 +1385,12 @@ bwb_lerror( l )
    /* get the variable name or numerical constant */
 
    adv_element( l->buffer, &( l->position ), tbuf );
-   n = atoi( tbuf );
+   /* n = atoi( tbuf ); */  /* Removed by JBV */
+
+   /* Added by JBV */
+   pos = 0;
+   e = bwb_exp( tbuf, FALSE, &pos );
+   n = (int) exp_getnval( e );
 
 #if INTENSIVE_DEBUG
    sprintf( bwb_ebuf, "in bwb_lerror(): error number is <%d> ", n );
diff --git a/bwb_stc.c b/bwb_stc.c
index eaf7482..96c6bed 100644
--- a/bwb_stc.c
+++ b/bwb_stc.c
@@ -29,6 +29,11 @@
 
 ***************************************************************/
 
+/*---------------------------------------------------------------*/
+/* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, */
+/* 11/1995 (eidetics@cerf.net).                                  */
+/*---------------------------------------------------------------*/
+
 #include <stdio.h>
 #include <ctype.h>
 
@@ -184,12 +189,22 @@ fslt_clear()
       while ( c != NULL )
          {
          n = c->next;
-         free( c );
+
+         /* Revised to FREE pass-thru call by JBV */
+         FREE( c, "fslt_clear" );
          c = n;
          }
 
       next = current->next;
-      free( current );
+
+      /* Revised to FREE pass-thru calls by JBV */
+      if (current->name != NULL)
+      {
+          FREE( current->name, "fslt_clear" ); /* JBV */
+          current->name = NULL; /* JBV */
+      }
+      FREE( current, "fslt_clear" );
+      current = NULL; /* JBV */
       }
 
    /* reset linkage */
@@ -360,6 +375,18 @@ scan_element( buffer, pos, element )
                }
             break;
 
+         case '(':                     /* MID$ command termination (JBV) */
+            /* If MID$ is here, get out */
+            if (strcmp(element, CMD_MID) == 0)
+               return TRUE;
+
+            /* else add it to the accumulation element */
+            element[ e_pos ] = buffer[ *pos ];
+            ++e_pos;
+            ++( *pos );
+            element[ e_pos ] = '\0';
+            break;
+
          default:
             element[ e_pos ] = buffer[ *pos ];
             ++e_pos;
@@ -428,7 +455,8 @@ fslt_add( line, position, code )
 
    /* get memory for name buffer */
 
-   if ( ( name = calloc( 1, strlen( tbuf ) + 1 ) ) == NULL )
+   /* Revised to CALLOC pass-thru call by JBV */
+   if ( ( name = CALLOC( 1, strlen( tbuf ) + 1, "fslt_add" ) ) == NULL )
       {
 #if PROG_ERRORS
       bwb_error( "in fslt_add(): failed to get memory for name buffer" );
@@ -442,7 +470,7 @@ fslt_add( line, position, code )
 
    /* get memory for fslt structure */
 
-   if ( ( f = calloc( 1, sizeof( struct fslte ) ) ) == NULL )
+   if ( ( f = CALLOC( 1, sizeof( struct fslte ), "fslt_add" ) ) == NULL )
       {
 #if PROG_ERRORS
       bwb_error( "in fslt_add(): failed to get memory for fslt structure" );
@@ -1898,7 +1926,7 @@ var_pos( firstvar, p )
 	FUNCTION:       fslt_addcallvar()
 
 	DESCRIPTION:    This function adds a calling variable
-			to the FUNCTION-SUB lookuop table at
+			to the FUNCTION-SUB lookup table at
 			a specific level.
 
 ***************************************************************/
@@ -1932,7 +1960,7 @@ fslt_addcallvar( v )
 
 /***************************************************************
 
-	FUNCTION:       expufnc()
+	FUNCTION:       exp_ufnc()
 
         DESCRIPTION:	This C function interprets a user-defined
 			function, returning its value at the current
@@ -2158,7 +2186,7 @@ exp_ufnc( expression )
 	FUNCTION:       fslt_addlocalvar()
 
 	DESCRIPTION:    This function adds a local variable
-			to the FUNCTION-SUB lookuop table at
+			to the FUNCTION-SUB lookup table at
 			a specific level.
 
 ***************************************************************/
@@ -2275,4 +2303,3 @@ is_label( buffer )
    }
 
 
-
\ No newline at end of file
diff --git a/bwb_str.c b/bwb_str.c
index 7259d7c..4699b20 100644
--- a/bwb_str.c
+++ b/bwb_str.c
@@ -23,6 +23,11 @@
 
 ***************************************************************/
 
+/*---------------------------------------------------------------*/
+/* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, */
+/* 11/1995 (eidetics@cerf.net).                                  */
+/*---------------------------------------------------------------*/
+
 #include <stdio.h>
 
 #include "bwbasic.h"
@@ -64,7 +69,8 @@ str_btob( d, s )
 
    /* get memory for new buffer */
 
-   if ( ( t = (char *) calloc( s->length + 1, 1 )) == NULL )
+   /* Following section removed by JBV (no more mass string reallocation) */
+   /* if ( ( t = (char *) CALLOC( s->length + 1, 1, "str_btob" )) == NULL )
       {
 #if PROG_ERRORS
       bwb_error( "in str_btob(): failed to get memory for new buffer" );
@@ -72,14 +78,30 @@ str_btob( d, s )
       bwb_error( err_getmem );
 #endif
       return FALSE;
-      }
+      } */
 
-   /* write the c string to the b string */
+   /* Only one of these two conditions necessitates reallocation (JBV) */
+   if ( ( d->sbuffer == NULL ) || ( d->rab == TRUE ) )
+   {
+      if ( ( t = (char *) CALLOC( MAXSTRINGSIZE + 1, 1, "str_btob" )) == NULL )
+         {
+#if PROG_ERRORS
+         bwb_error( "in str_btob(): failed to get memory for new buffer" );
+#else
+         bwb_error( err_getmem );
+#endif
+         return FALSE;
+         }
+   }
+   else t = d->sbuffer; /* Leave well enough alone (JBV) */
+
+   /* write the b string to the temp c string */
 
    t[ 0 ] = '\0';
    for ( i = 0; i < (int) s->length; ++i )
       {
       t[ i ] = s->sbuffer[ i ];
+      t[ i + 1 ] = '\0'; /* JBV */
 #if INTENSIVE_DEBUG
       tbuf[ i ] = s->sbuffer[ i ];
       tbuf[ i + 1 ] = '\0';
@@ -96,18 +118,22 @@ str_btob( d, s )
       }
 #endif
 
-   if (( d->rab != TRUE ) && ( d->sbuffer != NULL ))
+   /* Following section removed by JBV (no more mass string reallocation) */
+   /* if (( d->rab != TRUE ) && ( d->sbuffer != NULL ))
       {
 #if INTENSIVE_DEBUG
       sprintf( tbuf, "in str_btob(): deallocating string memory" );
       bwb_debug ( tbuf );
 #endif
-      free( d->sbuffer );
+      FREE( d->sbuffer, "str_btob" );
+      d->sbuffer = NULL;
       }
    else
       {
       d->rab = (char) FALSE;
-      }
+      } */
+
+   d->rab = (char) FALSE; /* JBV */
 
    /* reassign buffer */
 
@@ -162,7 +188,21 @@ str_ctob( s, buffer )
 
    /* get memory for new buffer */
 
-   if ( ( t = (char *) calloc( strlen( buffer ) + 1, 1 )) == NULL )
+   /* Following section removed by JBV (no more mass string reallocation) */
+   /* if ( ( t = (char *) CALLOC( strlen( buffer ) + 1, 1, "str_ctob" )) == NULL )
+      {
+#if PROG_ERRORS
+      bwb_error( "in str_ctob(): failed to get memory for new buffer" );
+#else
+      bwb_error( err_getmem );
+#endif
+      return FALSE;
+      } */
+
+   /* Only one of these two conditions necessitates reallocation (JBV) */
+   if ( ( s->sbuffer == NULL ) || ( s->rab == TRUE ) )
+   {
+   if ( ( t = (char *) CALLOC( MAXSTRINGSIZE + 1, 1, "str_ctob" )) == NULL )
       {
 #if PROG_ERRORS
       bwb_error( "in str_ctob(): failed to get memory for new buffer" );
@@ -171,13 +211,16 @@ str_ctob( s, buffer )
 #endif
       return FALSE;
       }
+   }
+   else t = s->sbuffer; /* Leave well enough alone (JBV) */
 
-   /* write the c string to the b string */
+   /* write the c string to the temp c string */
 
    t[ 0 ] = '\0';
    for ( i = 0; i < (int) strlen( buffer ); ++i )
       {
       t[ i ] = buffer[ i ];
+      t[ i + 1 ] = '\0'; /* JBV */
 #if INTENSIVE_DEBUG
       tbuf[ i ] = buffer[ i ];
       tbuf[ i + 1 ] = '\0';
@@ -194,14 +237,18 @@ str_ctob( s, buffer )
       }
 #endif
 
-   if (( s->rab != TRUE ) && ( s->sbuffer != NULL ))
+   /* Following section removed by JBV (no more mass string reallocation) */
+   /* if (( s->rab != TRUE ) && ( s->sbuffer != NULL ))
       {
-      free( s->sbuffer );
+      FREE( s->sbuffer, "str_ctob" );
+      s->sbuffer = NULL;
       }
    else
       {
       s->rab = (char) FALSE;
-      }
+      } */
+
+   s->rab = (char) FALSE; /* JBV */
 
    /* reassign buffer */
 
@@ -351,5 +398,3 @@ str_cmp( a, b )
    }
 
 
-
-
\ No newline at end of file
diff --git a/bwb_tbl.c b/bwb_tbl.c
index 8484330..1d5b8ca 100644
--- a/bwb_tbl.c
+++ b/bwb_tbl.c
@@ -24,6 +24,11 @@
 
 ***************************************************************/
 
+/*---------------------------------------------------------------*/
+/* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, */
+/* 11/1995 (eidetics@cerf.net).                                  */
+/*---------------------------------------------------------------*/
+
 #include <stdio.h>
 
 #include "bwbasic.h"
@@ -71,6 +76,7 @@ struct bwb_command bwb_cmdtable[ COMMANDS ] =
       { CMD_DEFINT,       bwb_dint },
       { CMD_DEFSNG,       bwb_dsng },
       { CMD_DEFSTR,       bwb_dstr },
+      { CMD_MID,          bwb_mid }, /* Added this extension (JBV) */
 #if IMP_CMDCLS
       { CMD_CLS,          bwb_cls },
 #endif
@@ -120,6 +126,7 @@ struct bwb_command bwb_cmdtable[ COMMANDS ] =
       { CMD_RSET,         bwb_rset },
       { CMD_FIELD,        bwb_field },
       { CMD_LINE,         bwb_line },
+      { CMD_RENUM,        bwb_renum }, /* Added this extension (JBV) */
 #endif
 
       /* The remainder are the core functions defined for ANSI Minimal BASIC */
@@ -243,30 +250,31 @@ struct bwb_function bwb_prefuncs[ FUNCTIONS ] =
 
 struct bwb_op exp_ops[ N_OPERATORS ] =
    {
-   { "NOT",     OP_NOT,         12 },   /* multiple-character operators */
+   { "NOT",     OP_NOT,         2  },   /* multiple-character operators */
    { "AND",     OP_AND,         13 },   /* should be tested first because */
    { "OR",      OP_OR,          14 },   /* e.g. a ">=" would be matched */
    { "XOR",     OP_XOR,         15 },   /* as "=" if the single-character */
    { "IMP",     OP_IMPLIES,     16 },   /* operator came first */
    { "EQV",     OP_EQUIV,       17 },
-   { "MOD",     OP_MODULUS,     4  },
-   { "<>",      OP_NOTEQUAL,    7  },
-   { "<=",      OP_LTEQ,        10 },
-   { "=<",      OP_LTEQ,        10 },   /* allow either form */
-   { ">=",      OP_GTEQ,        11 },
-   { "=>",      OP_GTEQ,        11 },   /* allow either form */
-   { "<",       OP_LESSTHAN,    8  },
-   { ">",       OP_GREATERTHAN, 9  },
+   { "MOD",     OP_MODULUS,     5  },
+   { "<>",      OP_NOTEQUAL,    8  },
+   { "<=",      OP_LTEQ,        11 },
+   { "=<",      OP_LTEQ,        11 },   /* allow either form */
+   { ">=",      OP_GTEQ,        12 },
+   { "=>",      OP_GTEQ,        12 },   /* allow either form */
+   { "<",       OP_LESSTHAN,    9  },
+   { ">",       OP_GREATERTHAN, 10 },
    { "^",       OP_EXPONENT,    0  },
-   { "*",       OP_MULTIPLY,    2  },
-   { "/",       OP_DIVIDE,      2  },
-   { "\\",      OP_INTDIVISION, 3  },
-   { "+",       OP_ADD,         5  },
-   { "-",       OP_SUBTRACT,    5  },
-   { "=",       OP_EQUALS,      6  },
-   { "=",       OP_ASSIGN,      6  },   /* don't worry: OP_EQUALS will be converted to OP_ASSIGN if necessary */
-   { ";",       OP_STRJOIN,     18 },
-   { ",",       OP_STRTAB,      19 }
+   { "*",       OP_MULTIPLY,    3  },
+   { "/",       OP_DIVIDE,      3  },
+   { "\\",      OP_INTDIVISION, 4  },
+   { "+",       OP_ADD,         6  },
+   { "-",       OP_SUBTRACT,    6  },
+   { "=",       OP_EQUALS,      7  },
+   { "=",       OP_ASSIGN,      18 },   /* don't worry: OP_EQUALS will be converted to OP_ASSIGN if necessary */
+   { ";",       OP_STRJOIN,     19 },
+   { ",",       OP_STRTAB,      20 },
+   { "-",       OP_NEGATION,    1  }    /* Right below exponentiation (JBV) */
    };
 
 /* Error messages used more than once */
@@ -332,4 +340,3 @@ char *err_table[ N_ERRORS ] =
    };
 
 
-
\ No newline at end of file
diff --git a/bwb_tcc.c b/bwb_tcc.c
index 593d2b2..52e870d 100644
--- a/bwb_tcc.c
+++ b/bwb_tcc.c
@@ -2,4 +2,3 @@
    establish a larger-than-usual stack of 8192 bytes for bwBASIC */
 
 extern unsigned _stklen = 8192U;
-
\ No newline at end of file
diff --git a/bwb_var.c b/bwb_var.c
index fe56dc1..eddb92b 100644
--- a/bwb_var.c
+++ b/bwb_var.c
@@ -29,6 +29,11 @@
 
 ***************************************************************/
 
+/*---------------------------------------------------------------*/
+/* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, */
+/* 11/1995 (eidetics@cerf.net).                                  */
+/*---------------------------------------------------------------*/
+
 #include <stdio.h>
 #include <ctype.h>
 #include <math.h>
@@ -162,6 +167,8 @@ bwb_erase( l )
    struct bwb_variable *v;
    struct bwb_variable *p;		/* previous variable in linked list */
    char tbuf[ MAXSTRINGSIZE + 1 ];
+   bstring *sp; /* JBV */
+   register int n; /* JBV */
 
    /* loop while arguments are available */
 
@@ -200,17 +207,39 @@ bwb_erase( l )
 
       /* deallocate memory */
 
-      free( v->array_sizes );
-      free( v->array_pos );
+      /* Revised to FREE pass-thru calls by JBV */
+      FREE( v->array_sizes, "bwb_erase" );
+      v->array_sizes = NULL; /* JBV */
+      FREE( v->array_pos , "bwb_erase");
+      v->array_pos = NULL; /* JBV */
       if ( v->type == NUMBER )
 	 {
-	 free( v->memnum );
+         /* Revised to FREE pass-thru call by JBV */
+	 FREE( v->memnum, "bwb_erase" );
+	 v->memnum = NULL; /* JBV */
 	 }
       else
 	 {
-	 free( v->memstr );
+		/* Following section added by JBV */
+		sp = v->memstr;
+		for ( n = 0; n < (int) v->array_units; ++n )
+		{
+			if ( sp[ n ].sbuffer != NULL )
+			{
+                                /* Revised to FREE pass-thru call by JBV */
+				FREE( sp[ n ].sbuffer, "bwb_erase" );
+				sp[ n ].sbuffer = NULL;
+			}
+			sp[ n ].rab = FALSE;
+			sp[ n ].length = 0;
+		}
+         /* Revised to FREE pass-thru call by JBV */
+	 FREE( v->memstr, "bwb_erase" );
+	 v->memstr = NULL; /* JBV */
 	 }
-      free( v );
+      /* Revised to FREE pass-thru call by JBV */
+      FREE( v, "bwb_erase" );
+      v = NULL; /* JBV */
 
       /* check for comma */
 
@@ -412,7 +441,8 @@ bwb_clear( l )
                   {
 		  if ( sp[ n ].sbuffer != NULL )
 		     {
-		     free( sp[ n ].sbuffer );
+                     /* Revised to FREE pass-thru call by JBV */
+		     FREE( sp[ n ].sbuffer, "bwb_clear" );
 		     sp[ n ].sbuffer = NULL;
                      }
                   sp[ n ].rab = FALSE;
@@ -447,6 +477,8 @@ var_delcvars()
    {
    struct bwb_variable *v;
    struct bwb_variable *p;		/* previous variable */
+   bstring *sp; /* JBV */
+   register int n; /* JBV */
 
    p = &CURTASK var_start;
    for ( v = CURTASK var_start.next; v != &CURTASK var_end; v = v->next )
@@ -462,15 +494,35 @@ var_delcvars()
 
             /* deallocate memory */
 
-            free( v->array_sizes );
-            free( v->array_pos );
+            /* Revised to FREE pass-thru calls by JBV */
+            FREE( v->array_sizes, "var_delcvars" );
+            v->array_sizes = NULL; /* JBV */
+            FREE( v->array_pos, "var_delcvars" );
+            v->array_pos = NULL; /* JBV */
 	    if ( v->type == NUMBER )
 	       {
-	       free( v->memnum );
+               /* Revised to FREE pass-thru call by JBV */
+	       FREE( v->memnum, "var_delcvars" );
+	       v->memnum = NULL; /* JBV */
 	       }
 	    else
 	       {
-	       free( v->memstr );
+		/* Following section added by JBV */
+		sp = v->memstr;
+		for ( n = 0; n < (int) v->array_units; ++n )
+		{
+			if ( sp[ n ].sbuffer != NULL )
+			{
+                                /* Revised to FREE pass-thru call by JBV */
+				FREE( sp[ n ].sbuffer, "var_delcvars" );
+				sp[ n ].sbuffer = NULL;
+			}
+			sp[ n ].rab = FALSE;
+			sp[ n ].length = 0;
+		}
+               /* Revised to FREE pass-thru call by JBV */
+	       FREE( v->memstr, "var_delcvars" );
+	       v->memstr = NULL; /* JBV */
 	       }
             }
 
@@ -480,7 +532,9 @@ var_delcvars()
 
          /* deallocate the variable itself */
 
-         free( v );
+         /* Revised to FREE pass-thru call by JBV */
+         FREE( v, "var_delcvars" );
+         v = NULL; /* JBV */
 
          }
 
@@ -617,6 +671,246 @@ bwb_dstr( l )
 
 /***********************************************************
 
+        FUNCTION:	bwb_mid()
+
+	DESCRIPTION:    This function implements the BASIC
+			MID$ command.
+
+			Same as MID$ function, except it will set
+			the desired substring and not return its
+			value.  Added by JBV 10/95
+
+	SYNTAX:		MID$( string-variable$, start-position-in-string
+			[, number-of-spaces ] ) = expression
+
+***********************************************************/
+
+#if ANSI_C
+struct bwb_line *
+bwb_mid( struct bwb_line *l )
+#else
+struct bwb_line *
+bwb_mid( l )
+   struct bwb_line *l;
+#endif
+   {
+   char tbuf[ MAXSTRINGSIZE + 1 ];
+   char source_string[ MAXSTRINGSIZE + 1 ];
+   struct bwb_variable *v;
+   static int pos;
+   bstring *d;
+   int *pp;
+   int n_params;
+   int p;
+   register int n;
+   int startpos, numchars, endpos;
+   int source_counter, source_length, target_length;
+   int target_terminate;
+   struct exp_ese *e;
+
+#if INTENSIVE_DEBUG
+   sprintf( bwb_ebuf, "in bwb_mid(): MID$ command" );
+   bwb_debug( bwb_ebuf );
+#endif
+
+   /* Get past left parenthesis */
+   adv_ws( l->buffer, &( l->position ) );
+   ++( l->position );
+   adv_ws( l->buffer, &( l->position ) );
+
+   /* Get variable name and find variable */
+   bwb_getvarname( l->buffer, tbuf, &( l->position ) );
+   v = var_find( tbuf );
+   if ( v == NULL )
+      {
+#if PROG_ERRORS
+      sprintf( bwb_ebuf, "in bwb_mid(): failed to find variable" );
+      bwb_error( bwb_ebuf );
+#else
+      bwb_error( err_syntax );
+#endif
+      }
+
+   if ( v->type != STRING )
+      {
+#if PROG_ERRORS
+      sprintf( bwb_ebuf, "in bwb_mid(): assignment must be to string variable" );
+      bwb_error( bwb_ebuf );
+#else
+      bwb_error( err_syntax );
+#endif
+      }
+
+   /* read subscripts */
+   pos = 0;
+   if ( ( v->dimensions == 1 ) && ( v->array_sizes[ 0 ] == 1 ))
+      {
+#if INTENSIVE_DEBUG
+      sprintf( bwb_ebuf, "in bwb_mid(): variable <%s> has 1 dimension",
+         v->name );
+     bwb_debug( bwb_ebuf );
+#endif
+      n_params = 1;
+      pp = &p;
+      pp[ 0 ] = dim_base;
+      }
+   else
+      {
+#if INTENSIVE_DEBUG
+      sprintf( bwb_ebuf, "in bwb_mid(): variable <%s> has > 1 dimensions",
+         v->name );
+      bwb_debug( bwb_ebuf );
+#endif
+      dim_getparams( l->buffer, &( l->position ), &n_params, &pp );
+      }
+
+   CURTASK exps[ CURTASK expsc ].pos_adv = pos;
+   for ( n = 0; n < v->dimensions; ++n )
+      {
+      v->array_pos[ n ] = pp[ n ];
+      }
+
+   /* get bstring pointer */
+   d = var_findsval( v, pp );
+
+   /* Get past next comma and white space */
+   adv_ws( l->buffer, &( l->position ) );
+   ++( l->position );
+   adv_ws( l->buffer, &( l->position ) );
+
+   /* Get starting position (expression) */
+   adv_element( l->buffer, &( l->position ), tbuf );
+   pos = 0;
+   e = bwb_exp( tbuf, FALSE, &pos );
+   startpos = (int) exp_getnval( e );
+
+#if INTENSIVE_DEBUG
+   sprintf( bwb_ebuf, "in bwb_mid(): startpos <%d> buffer <%lX>",
+      startpos, (long) d->sbuffer );
+   bwb_debug( bwb_ebuf );
+#endif
+
+   /* Get past next comma and white space (if they exist) */
+   adv_ws( l->buffer, &( l->position ) );
+   if (l->buffer[l->position] == ',')
+      {
+      target_terminate = 0;
+      ++( l->position );
+      adv_ws( l->buffer, &( l->position ) );
+      adv_element( l->buffer, &( l->position ), tbuf );
+      pos = 0;
+      e = bwb_exp( tbuf, FALSE, &pos );
+      numchars = (int) exp_getnval( e );
+      if ( numchars == 0 )
+         {
+#if PROG_ERRORS
+         sprintf( bwb_ebuf, "in bwb_mid(): destination string no. of chars out of range" );
+         bwb_error( bwb_ebuf );
+#else
+         bwb_error( "Argument out of range" );
+#endif
+         }
+      }
+   else
+      {
+      target_terminate = 1;
+      numchars = 0;
+      }
+
+   if ( numchars < 0 )
+      {
+#if PROG_ERRORS
+      sprintf( bwb_ebuf, "in bwb_mid(): negative string length" );
+      bwb_error( bwb_ebuf );
+#else
+      bwb_error( "Negative string length" );
+#endif
+      }
+
+#if INTENSIVE_DEBUG
+   sprintf( bwb_ebuf, "in bwb_mid(): numchars <%d> target_terminate <%d>", numchars, target_terminate );
+   bwb_debug( bwb_ebuf );
+#endif
+
+   /* Get past equal sign */
+   adv_ws( l->buffer, &( l->position ) );
+   if (l->buffer[l->position] == ')')
+      {
+      ++(l->position);
+      adv_ws( l->buffer, &( l->position ) );
+      }
+   ++(l->position);
+   adv_ws( l->buffer, &( l->position ) );
+
+   /* Evaluate string expression */
+   e = bwb_exp( l->buffer, FALSE, &( l->position ) );
+   if ( e->type != STRING )
+      {
+#if PROG_ERRORS
+      sprintf( bwb_ebuf, "in bwb_mid(): assignment must be from string expression" );
+      bwb_error( bwb_ebuf );
+#else
+      bwb_error( err_syntax );
+#endif
+      }
+
+   /* Prepare to MID the string */
+   str_btoc( source_string, exp_getsval( e ) );
+   str_btoc( tbuf, d );
+   target_length = strlen( tbuf );
+   if ( startpos > ( target_length + 1 ) )
+      {
+#if PROG_ERRORS
+      sprintf( bwb_ebuf, "in bwb_mid(): non-contiguous string created" );
+      bwb_error( bwb_ebuf );
+#else
+      bwb_error( "Non-contiguous string created" );
+#endif
+      }
+
+   if ( startpos < 1 )
+      {
+#if PROG_ERRORS
+      sprintf( bwb_ebuf, "in bwb_mid(): destination string start position out of range" );
+      bwb_error( bwb_ebuf );
+#else
+      bwb_error( "Argument out of range" );
+#endif
+      }
+
+   source_length = strlen( source_string );
+   if ( numchars == 0 ) numchars = source_length;
+   endpos = startpos + numchars - 1;
+
+   /* MID the string */
+   if ( endpos < startpos ) tbuf[ startpos - 1 ] = '\0';
+   else
+      {
+      source_counter = 0;
+      for ( n = startpos - 1; n < endpos; ++n )
+         {
+         if ( source_counter < source_length )
+            tbuf[ n ] = source_string[ source_counter ];
+         else
+            tbuf[ n ] = ' ';
+         ++source_counter;
+         }
+      /* Terminate if indicated or characters were added */
+      if ( ( endpos > target_length ) || ( target_terminate == 1 ) )
+         tbuf[ endpos ] = '\0';
+      }
+   str_ctob( d, tbuf );
+
+#if MULTISEG_LINES
+   adv_eos( l->buffer, &( l->position ));
+#endif
+
+   return bwb_zline( l );
+
+   }
+
+/***********************************************************
+
         Function:	var_defx()
 
 	DESCRIPTION:    This function is a generalized DEFxxx handler.
@@ -886,6 +1180,7 @@ bwb_getvarname( lb, sb, n )
          case ';':
          case '(':              /* beginning of parameter list for dimensioned array */
          case '+':              /* add variables */
+         case '=':              /* Don't forget this one (JBV) */
             sb[ s ] = 0;
             return TRUE;
          default:
@@ -1029,7 +1324,8 @@ var_new( name )
 
    /* get memory for new variable */
 
-   if ( ( v = (struct bwb_variable *) calloc( 1, sizeof( struct bwb_variable ) ))
+   /* Revised to CALLOC pass-thru call by JBV */
+   if ( ( v = (struct bwb_variable *) CALLOC( 1, sizeof( struct bwb_variable ), "var_new" ))
       == NULL )
       {
       bwb_error( err_getmem );
@@ -1299,7 +1595,8 @@ bwb_dim( l )
 
          /* assign memory for parameters */
 
-         if ( ( newvar->array_sizes = (int *) calloc( n_params, sizeof( int )  )) == NULL )
+         /* Revised to CALLOC pass-thru call by JBV */
+         if ( ( newvar->array_sizes = (int *) CALLOC( n_params, sizeof( int ), "bwb_dim"  )) == NULL )
             {
 #if PROG_ERRORS
             sprintf( bwb_ebuf, "in line %d: Failed to find memory for array_sizes for <%s>",
@@ -1323,7 +1620,8 @@ bwb_dim( l )
 
          /* assign memory for current position */
 
-         if ( ( newvar->array_pos = (int *) calloc( n_params, sizeof( int ) )) == NULL )
+         /* Revised to CALLOC pass-thru call by JBV */
+         if ( ( newvar->array_pos = (int *) CALLOC( n_params, sizeof( int ), "bwb_dim" )) == NULL )
             {
 #if PROG_ERRORS
             sprintf( bwb_ebuf, "in line %d: Failed to find memory for array_pos for <%s>",
@@ -1364,8 +1662,13 @@ bwb_dim( l )
         	  (long) ( newvar->array_units + 1 ) * sizeof( bstring ));
                bwb_debug( bwb_ebuf );
 #endif
-	       if ( ( newvar->memnum = calloc( newvar->array_units, sizeof( bstring) )) == NULL )
-		  {
+               /*------------------------------------------------------*/
+               /* memnum, not memstr, was used here -- incorrect (JBV) */
+               /* Revised to CALLOC pass-thru call by JBV              */
+               /*------------------------------------------------------*/
+               if ( ( newvar->memstr = (bstring *)
+                  CALLOC( newvar->array_units, sizeof( bstring), "bwb_dim" )) == NULL )
+               {
 #if PROG_ERRORS
                   sprintf( bwb_ebuf, "in line %d: Failed to find memory for array <%s>",
                      l->number, newvar->name );
@@ -1385,8 +1688,10 @@ bwb_dim( l )
         	  (long) ( newvar->array_units + 1 ) * sizeof( double ));
                bwb_debug( bwb_ebuf );
 #endif
+
+               /* Revised to CALLOC pass-thru call by JBV */
                if ( ( np = (bnumber *)
-                  calloc( newvar->array_units, sizeof( bnumber ) )) == NULL )
+                  CALLOC( newvar->array_units, sizeof( bnumber ), "bwb_dim" )) == NULL )
                   {
 #if PROG_ERRORS
                   sprintf( bwb_ebuf, "in line %d: Failed to find memory for array <%s>",
@@ -1544,6 +1849,9 @@ dim_getparams( buffer, pos, n_params, pp )
    int x_pos, s_pos;
    struct exp_ese *e;
    char tbuf[ MAXSTRINGSIZE + 1 ];
+#if INTENSIVE_DEBUG
+   register int n;
+#endif
 
    /* set initial values */
 
@@ -1825,8 +2133,7 @@ var_findnval( v, pp )
    for ( n = 0; n < v->dimensions; ++n )
       {
       sprintf( bwb_ebuf,
-	 "in var_findnval(): dimensioned variable <%s> pos <%d> <%d>.",
-	 v->name,
+         "in var_findnval(): dimensioned variable pos <%d> <%d>.",
          n, pp[ n ] );
       bwb_debug( bwb_ebuf );
       }
@@ -1864,6 +2171,8 @@ var_findsval( v, pp )
    bstring *p;
 
 #if INTENSIVE_DEBUG
+   register int n;
+
    sprintf( bwb_ebuf, "in var_findsval(): entered, var <%s>", v->name );
    bwb_debug( bwb_ebuf );
 #endif
@@ -2014,6 +2323,8 @@ var_make( v, type )
    {
    size_t data_size;
    bstring *b;
+   bstring *sp; /* JBV */
+   register int n; /* JBV */
 #if TEST_BSTRING
    static int tnumber = 0;
 #endif
@@ -2032,9 +2343,48 @@ var_make( v, type )
 
    /* get memory for array */
 
+   /* First kleanup the joint (JBV) */
+   if (v->memnum != NULL)
+   {
+       /* Revised to FREE pass-thru call by JBV */
+       FREE(v->memnum, "var_make");
+       v->memnum = NULL;
+   }
+   if (v->memstr != NULL)
+   {
+       /* Remember to deallocate those far-flung branches! (JBV) */
+       sp = v->memstr;
+       for ( n = 0; n < (int) v->array_units; ++n )
+       {
+           if ( sp[ n ].sbuffer != NULL )
+           {
+               /* Revised to FREE pass-thru call by JBV */
+               FREE( sp[ n ].sbuffer, "var_make" );
+               sp[ n ].sbuffer = NULL;
+           }
+           sp[ n ].rab = FALSE;
+           sp[ n ].length = 0;
+       }
+       /* Revised to FREE pass-thru call by JBV */
+       FREE(v->memstr, "var_make");
+       v->memstr = NULL;
+   }
+   /* Revised to FREE pass-thru calls by JBV */
+   if (v->array_sizes != NULL)
+   {
+       FREE(v->array_sizes, "var_make");
+       v->array_sizes = NULL; /* JBV */
+   }
+   if (v->array_pos != NULL)
+   {
+       FREE(v->array_pos, "var_make");
+       v->array_pos = NULL; /* JBV */
+   }
+
    if ( v->type == NUMBER )
       {
-      if ( ( v->memnum = calloc( 2, sizeof( bnumber ) )) == NULL )
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( v->memnum = CALLOC( 2, sizeof( bnumber ), "var_make" )) == NULL )
 	 {
 	 bwb_error( err_getmem );
 	 return FALSE;
@@ -2042,7 +2392,8 @@ var_make( v, type )
       }
    else
       {
-      if ( ( v->memstr = calloc( 2, sizeof( bstring ) )) == NULL )
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( v->memstr = CALLOC( 2, sizeof( bstring ), "var_make" )) == NULL )
 	 {
 	 bwb_error( err_getmem );
 	 return FALSE;
@@ -2051,13 +2402,15 @@ var_make( v, type )
 
    /* get memory for array_sizes and array_pos */
 
-   if ( ( v->array_sizes = (int *) calloc( 2, sizeof( int ) )) == NULL )
+   /* Revised to CALLOC pass-thru call by JBV */
+   if ( ( v->array_sizes = (int *) CALLOC( 2, sizeof( int ), "var_make" )) == NULL )
       {
       bwb_error( err_getmem );
       return FALSE;
       }
 
-   if ( ( v->array_pos = (int *) calloc( 2, sizeof( int ) )) == NULL )
+   /* Revised to CALLOC pass-thru call by JBV */
+   if ( ( v->array_pos = (int *) CALLOC( 2, sizeof( int ), "var_make" )) == NULL )
       {
       bwb_error( err_getmem );
       return FALSE;
diff --git a/bwbasic.c b/bwbasic.c
index 2e2cde5..5c4f37e 100644
--- a/bwbasic.c
+++ b/bwbasic.c
@@ -28,6 +28,11 @@
 
 ***************************************************************/
 
+/*---------------------------------------------------------------*/
+/* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, */
+/* 11/1995 (eidetics@cerf.net).                                  */
+/*---------------------------------------------------------------*/
+
 #include <stdio.h>
 #include <ctype.h>
 #include <math.h>
@@ -153,7 +158,8 @@ bwb_init( argc, argv )
    /* Memory allocation */
    /* eXecute TeXT stack */
 
-   if ( ( xtxts = calloc( XTXTSTACKSIZE, sizeof( struct xtxtsl ) ) ) == NULL )
+   /* Revised to CALLOC pass-thru call by JBV */
+   if ( ( xtxts = CALLOC( XTXTSTACKSIZE, sizeof( struct xtxtsl ), "bwb_init") ) == NULL )
       {
 #if PROG_ERRORS
       bwb_error( "in bwb_init(): failed to find memory for xtxts" );
@@ -164,7 +170,8 @@ bwb_init( argc, argv )
 
    /* expression stack */
 
-   if ( ( exps = calloc( ESTACKSIZE, sizeof( struct exp_ese ) ) ) == NULL )
+   /* Revised to CALLOC pass-thru call by JBV */
+   if ( ( exps = CALLOC( ESTACKSIZE, sizeof( struct exp_ese ), "bwb_init") ) == NULL )
       {
 #if PROG_ERRORS
       bwb_error( "in bwb_init(): failed to find memory for exps" );
@@ -175,7 +182,8 @@ bwb_init( argc, argv )
 
    /* EXEC stack */
 
-   if ( ( excs = calloc( EXECLEVELS, sizeof( struct exse ) ) ) == NULL )
+   /* Revised to CALLOC pass-thru call by JBV */
+   if ( ( excs = CALLOC( EXECLEVELS, sizeof( struct exse ), "bwb_init") ) == NULL )
       {
 #if PROG_ERRORS
       bwb_error( "in bwb_init(): failed to find memory for excs" );
@@ -197,8 +205,8 @@ bwb_init( argc, argv )
    exsc = -1;
    expsc = 0;
    xtxtsc = 0;
-   bwb_start.position = 1;
-   bwb_l = &bwb_start;
+   bwb_start.position = 0;
+   bwb_l = &bwb_start; 
 
    var_init( 0 );
    fnc_init( 0 );
@@ -208,7 +216,8 @@ bwb_init( argc, argv )
 
    /* character buffers */
 
-   if ( ( bwb_ebuf = calloc( MAXSTRINGSIZE + 1, sizeof(char) ) ) == NULL )
+   /* Revised to CALLOC pass-thru call by JBV */
+   if ( ( bwb_ebuf = CALLOC( MAXSTRINGSIZE + 1, sizeof(char), "bwb_init") ) == NULL )
       {
 #if PROG_ERRORS
       bwb_error( "in bwb_init(): failed to find memory for bwb_ebuf" );
@@ -216,7 +225,8 @@ bwb_init( argc, argv )
       bwb_error( err_getmem );
 #endif
       }
-   if ( ( read_line = calloc( MAXREADLINESIZE + 1, sizeof(char) ) ) == NULL )
+   /* Revised to CALLOC pass-thru call by JBV */
+   if ( ( read_line = CALLOC( MAXREADLINESIZE + 1, sizeof(char), "bwb_init") ) == NULL )
       {
 #if PROG_ERRORS
       bwb_error( "in bwb_init(): failed to find memory for read_line" );
@@ -248,7 +258,8 @@ bwb_init( argc, argv )
    /* assign memory for the device table */
 
 #if COMMON_CMDS
-   if ( ( dev_table = calloc( DEF_DEVICES, sizeof( struct dev_element ) ) ) == NULL )
+   /* Revised to CALLOC pass-thru call by JBV */
+   if ( ( dev_table = CALLOC( DEF_DEVICES, sizeof( struct dev_element ), "bwb_init") ) == NULL )
       {
 #if PROG_ERRORS
       bwb_error( "in bwb_init(): failed to find memory for dev_table" );
@@ -399,9 +410,9 @@ bwb_init( argc, argv )
    ++program_run;
    if (( argc > 1 ) && ( program_run == 1 ))
       {
-      if ( ( input = fopen( argv[ 1 ], "r" )) == NULL )
+      strcpy( CURTASK progfile, argv[ 1 ] ); /* JBV */
+      if ( ( input = fopen( CURTASK progfile, "r" )) == NULL ) /* JBV */
          {
-         strcpy( CURTASK progfile, argv[ 1 ] );
          strcat( CURTASK progfile, ".bas" );
          if ( ( input = fopen( CURTASK progfile, "r" )) == NULL )
             {
@@ -412,7 +423,7 @@ bwb_init( argc, argv )
          }
       if ( input != NULL )
          {
-         strcpy( CURTASK progfile, argv[ 1 ] );
+         /* strcpy( CURTASK progfile, argv[ 1 ] ); */  /* Removed by JBV */
 #if INTENSIVE_DEBUG
          sprintf( bwb_ebuf, "in main(): progfile is <%s>.", CURTASK progfile );
          bwb_debug( bwb_ebuf );
@@ -442,6 +453,7 @@ bwb_interact( void )
 bwb_interact()
 #endif
    {
+   char tbuf[ MAXSTRINGSIZE + 1 ]; /* JBV */
 
 #if INTENSIVE_DEBUG
    sprintf( bwb_ebuf, "in bwb_interact(): ready to read from keyboard" );
@@ -451,6 +463,7 @@ bwb_interact()
    /* take input from keyboard */
 
    bwb_gets( read_line );
+   bwb_stripcr( read_line ); /* JBV */
 
    /* If there is no line number, execute the line as received */
 
@@ -459,6 +472,17 @@ bwb_interact()
       bwb_xtxtline( read_line );
       }
 
+   /*-----------------------------------------------------------------*/
+   /* Another possibility: if read_line is a numeric constant, delete */
+   /* the indicated line number (JBV)                                 */
+   /*-----------------------------------------------------------------*/
+   else if ( is_numconst( read_line ) == TRUE )
+   {
+       strcpy(tbuf, read_line);
+       sprintf(read_line, "delete %s\0", tbuf);
+       bwb_xtxtline( read_line );
+   }
+
    /* If there is a line number, add the line to the file in memory */
 
    else
@@ -553,7 +577,9 @@ bwb_ladd( buffer, replace )
    if ( init == FALSE )
       {
       init = TRUE;
-      if ( ( s_buffer = calloc( (size_t) MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
+
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( s_buffer = CALLOC( (size_t) MAXSTRINGSIZE + 1, sizeof( char ), "bwb_ladd" )) == NULL )
 	 {
 #if PROG_ERRORS
 	 bwb_error( "in bwb_ladd(): failed to find memory for s_buffer" );
@@ -571,7 +597,8 @@ bwb_ladd( buffer, replace )
 
    /* get memory for this line */
 
-   if ( ( l = (struct bwb_line *) calloc( (size_t) 1, sizeof( struct bwb_line ) )) == NULL )
+   /* Revised to CALLOC pass-thru call by JBV */
+   if ( ( l = (struct bwb_line *) CALLOC( (size_t) 1, sizeof( struct bwb_line ), "bwb_ladd")) == NULL )
       {
 #if PROG_ERRORS
       bwb_error( "in bwb_ladd(): failed to find memory for new line" );
@@ -648,7 +675,7 @@ bwb_ladd( buffer, replace )
 
       /* replace a previously existing line */
 
-      if ( ( l->xnum == TRUE )
+      if ( ( l->xnum == (char) TRUE ) /* Better recast this one (JBV) */
          && ( previous->number == l->number )
 	 && ( replace == TRUE )
 	 )
@@ -666,7 +693,10 @@ bwb_ladd( buffer, replace )
 
          /* free the current line */
 
-         free( l );
+         /* Revised to FREE pass-thru calls by JBV */
+         /* if (l->buffer != NULL) FREE( l->buffer, "bwb_ladd" ); */
+         /* FREE( l, "bwb_ladd" ); */
+         bwb_freeline( l ); /* JBV */
 
          /* and return */
 
@@ -724,8 +754,10 @@ bwb_ladd( buffer, replace )
 
    /* attempt to link line number has failed; free memory */
 
-   free( l->buffer );
-   free( l );
+   /* Revised to FREE pass-thru calls by JBV */
+   /* if (l->buffer != NULL) FREE( l->buffer, "bwb_ladd" ); */
+   /* FREE( l, "bwb_ladd" ); */
+   bwb_freeline( l ); /* JBV */
 
    sprintf( bwb_ebuf, ERR_LINENO );
    bwb_error( bwb_ebuf );
@@ -810,14 +842,16 @@ bwb_xtxtline( buffer )
    bwb_debug( bwb_ebuf );
 #endif
 
-   if ( CURTASK xtxts[ CURTASK xtxtsc ].l.buffer != NULL )
-      {
-#if INTENSIVE_DEBUG
-      sprintf( bwb_ebuf, "in bwb_xtxtline(): freeing buffer memory" );
-      bwb_debug( bwb_ebuf );
-#endif
-      free( CURTASK xtxts[ CURTASK xtxtsc ].l.buffer );
-      }
+/* Removed by JBV (no longer needed, done by ln_asbuf) */
+/*   if ( CURTASK xtxts[ CURTASK xtxtsc ].l.buffer != NULL )
+      { */
+/* #if INTENSIVE_DEBUG */
+/*      sprintf( bwb_ebuf, "in bwb_xtxtline(): freeing buffer memory" );
+      bwb_debug( bwb_ebuf ); */
+/* #endif */
+        /* Revised to FREE pass-thru call by JBV */
+/*      FREE( CURTASK xtxts[ CURTASK xtxtsc ].l.buffer, "bwb_xtxtline" );
+      } */
 
    /* copy the whole line to the line structure buffer */
 
@@ -938,8 +972,10 @@ bwb_decexec()
    if ( CURTASK excs[ CURTASK exsc ].code == EXEC_ON )
       {
 
-      free( CURTASK excs[ CURTASK exsc ].while_line->buffer );
-      free( CURTASK excs[ CURTASK exsc ].while_line );
+      /* Revised to FREE pass-thru calls by JBV */
+      /* FREE( CURTASK excs[ CURTASK exsc ].while_line->buffer, "bwb_decexec" ); */
+      /* FREE( CURTASK excs[ CURTASK exsc ].while_line, "bwb_decexec" ); */
+      bwb_freeline( CURTASK excs[ CURTASK exsc ].while_line ); /* JBV */
 
       bwb_decexec();
       }
@@ -1236,14 +1272,18 @@ ln_asbuf( l, s )
 #endif
    {
 
-#if DONTDOTHIS			/* but why not? */
+/* Reinstated by JBV */
+/* #if DONTDOTHIS */		/* but why not? */
    if ( l->buffer != NULL )
       {
-      free( l->buffer );
+      /* Revised to FREE pass-thru call by JBV */
+      FREE( l->buffer, "ln_asbuf" );
+      l->buffer = NULL; /* JBV */
       }
-#endif
+/* #endif */
 
-   if ( ( l->buffer = calloc( strlen( s ) + 2, sizeof( char ) ) )
+   /* Revised to CALLOC pass-thru call by JBV */
+   if ( ( l->buffer = CALLOC( strlen( s ) + 2, sizeof( char ), "ln_asbuf") )
       == NULL )
       {
 #if PROG_ERRORS
@@ -1341,7 +1381,9 @@ break_mes( x )
    if ( init == FALSE )
       {
       init = TRUE;
-      if ( ( tmp_buffer = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
+
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( tmp_buffer = CALLOC( MAXSTRINGSIZE + 1, sizeof( char ), "break_mes")) == NULL )
          {
 #if PROG_ERRORS
 	 bwb_error( "in break_mes(): failed to find memory for tmp_buffer" );
@@ -1448,3 +1490,50 @@ is_ln( buffer )
    }
 
 
+/***************************************************************
+
+	FUNCTION:       CALLOC()
+
+	DESCRIPTION:    Pass-thru function to calloc() for debugging
+			purposes.  Added by JBV 10/95
+
+***************************************************************/
+
+void *
+#if ANSI_C
+CALLOC( size_t nelem, size_t elsize, char *str )
+#else
+CALLOC( nelem, elsize, str )
+   size_t nelem;
+   size_t elsize;
+   char *str;
+#endif
+{
+    void *ptr;
+
+    ptr = calloc(nelem, elsize);
+    /* printf("%x %x\n", ptr, mallocblksize(ptr)); */
+    return ptr;
+}
+
+/***************************************************************
+
+	FUNCTION:       FREE()
+
+	DESCRIPTION:    Pass-thru function to free() for debugging
+			purposes.  Added by JBV 10/95
+
+***************************************************************/
+
+void
+#if ANSI_C
+FREE( void *ptr, char *str )
+#else
+FREE( ptr, str )
+   void *ptr;
+   char *str;
+#endif
+{
+    /* printf("%x\n", ptr); */
+    free(ptr);
+}
diff --git a/bwbasic.doc b/bwbasic.doc
index 163b5d9..934691c 100644
--- a/bwbasic.doc
+++ b/bwbasic.doc
@@ -271,27 +271,27 @@ CONTENTS:
    bwBASIC recognizes the following operators, with their level
    of precedence given (1 = highest):
 
-      ^                 1       exponentiation
-      *                 2       multiplication
-      /                 2       division
-      \                 3       integer division
-      +                 5       addition
-      -                 5       subtraction
-      =                 6       equality or assignment
-      MOD               4       modulus (remainder) arithmetic
-      <>                7       inequality
-      <                 8       less than
-      >                 9       greater than
-      <=                10      less than or equal to
-      =<                10      less than or equal to
-      >=                11      greater than or equal to
-      =>                11      greater than or equal to
-      NOT               12      negation
-      AND               13      conjunction
-      OR                14      disjunction
-      XOR               15      exclusive or
-      IMP               16      implication
-      EQV               17      equivalence
+      ^ 		1 	exponentiation
+      *			2 	multiplication
+      /			2	division
+      \			3 	integer division
+      +			5 	addition
+      -			5 	subtraction
+      =			6 	equality or assignment
+      MOD		4	modulus (remainder) arithmetic
+      <>		7	inequality
+      <			8	less than
+      >			9	greater than
+      <=		10	less than or equal to
+      =<		10	less than or equal to
+      >=		11	greater than or equal to
+      =>		11	greater than or equal to
+      NOT		12	negation
+      AND		13	conjunction
+      OR		14	disjunction
+      XOR		15	exclusive or
+      IMP		16	implication
+      EQV		17	equivalence
 
    4.h. Numerical Precision (NOT)
 
@@ -312,30 +312,30 @@ CONTENTS:
    associated command or function to be implemented.  These flags
    are as follows:
 
-   (core)               Commands and Functions in any implementation of
-                        bwBASIC; these are the ANSI Minimal BASIC core
+   (core)		Commands and Functions in any implementation of
+   			bwBASIC; these are the ANSI Minimal BASIC core
 
-   INTERACTIVE          Commands supporting the interactive programming
-                        environment
+   INTERACTIVE		Commands supporting the interactive programming
+   			environment
 
-   COMMON_CMDS          Commands beyond ANSI Minimal BASIC which are common
-                        to Full ANSI BASIC and Microsoft BASICs
+   COMMON_CMDS		Commands beyond ANSI Minimal BASIC which are common
+   			to Full ANSI BASIC and Microsoft BASICs
 
-   COMMON_FUNCS         Functions beyond the ANSI Mimimal BASIC core, but
-                        common to both ANSI Full BASIC and Microsoft-style
-                        BASIC varieties
+   COMMON_FUNCS		Functions beyond the ANSI Mimimal BASIC core, but
+   			common to both ANSI Full BASIC and Microsoft-style
+   			BASIC varieties
 
-   UNIX_CMDS            Commands which require Unix-style directory and
-                        environment routines not specified in C
+   UNIX_CMDS		Commands which require Unix-style directory and
+   			environment routines not specified in C
 
-   STRUCT_CMDS          Commands related to structured programming; all
-                        of these are part of the Full ANSI BASIC standard
+   STRUCT_CMDS		Commands related to structured programming; all
+   			of these are part of the Full ANSI BASIC standard
 
-   ANSI_FUNCS           Functions unique to ANSI Full BASIC
+   ANSI_FUNCS		Functions unique to ANSI Full BASIC
 
-   MS_CMDS              Commands unique to Microsoft BASICs
+   MS_CMDS		Commands unique to Microsoft BASICs
 
-   MS_FUNCS             Functions unique to Microsoft BASICs
+   MS_FUNCS		Functions unique to Microsoft BASICs
 
 
    ------------------------------------------
@@ -379,7 +379,7 @@ CONTENTS:
    Description:  CASE introduces an element of a SELECT CASE statement
                  (see SELECT CASE). CASE IF introduces a conditional
                  SELECT CASE element, and CASE ELSE introduces a
-                 default SELECT CASE element.
+		 default SELECT CASE element.
 
    Dependencies: STRUCT_CMDS
 
@@ -548,8 +548,8 @@ CONTENTS:
                  As implemented under bwBASIC, DATE$ cannot be used for
                  assignment (i.e., to set the system date).
 
-   Note:         bwBASIC presently (v2.10) does not allow assignment
-                 to a function.
+   Note:	 bwBASIC presently (v2.10) does not allow assignment
+		 to a function.
 
    Dependencies: COMMON_FUNCS
 
@@ -783,7 +783,7 @@ CONTENTS:
    Command:      EXIT [FOR]
 
    Description:  EXIT by itself exits from a DO...LOOP loop;
-                 EXIT FOR exits from a FOR...NEXT loop.
+   		 EXIT FOR exits from a FOR...NEXT loop.
 
    Dependencies: STRUCT_CMDS
 
@@ -913,9 +913,9 @@ CONTENTS:
    Function:     INKEY$
 
    Description:  INKEY$ reads the status of the keyboard, and a single
-                 keypress, if available. If a keypress is not available,
-                 then INKEY$ immediately returns a null string ("").
-                 Currently (v2.10) implemented in bwx_iqc.c only.
+   		 keypress, if available. If a keypress is not available,
+   		 then INKEY$ immediately returns a null string ("").
+   		 Currently (v2.10) implemented in bwx_iqc.c only.
 
    Dependencies: IMP_IQC and IMP_CMDLOC
 
@@ -944,8 +944,8 @@ CONTENTS:
                  As implemented in bwBASIC, INSTR cannot be used for
                  assignments.
 
-   Note:         bwBASIC presently (v2.10) does not allow assignment
-                 to a function.
+   Note:	 bwBASIC presently (v2.10) does not allow assignment
+		 to a function.
 
    Dependencies: MS_FUNCS
 
@@ -1039,7 +1039,7 @@ CONTENTS:
    Command:      LOCATE line, column
 
    Description:  LOCATE addresses trhe curor to a specified line and
-                 column. Currently (v2.10) implemented in bwx_iqc.c only.
+		 column. Currently (v2.10) implemented in bwx_iqc.c only.
 
    Dependencies: IMP_IQC and IMP_CMDLOC
 
@@ -1237,29 +1237,29 @@ CONTENTS:
                  a number of formatting marks may appear in the format
                  string:
 
-                    !   prints the first character of a string
+                    !	prints the first character of a string
 
-                    \\  prints 2+x characters of a string, where x =
+                    \\	prints 2+x characters of a string, where x =
                         the number of spaces between the backslashes
 
-                    &   variable-length string field
+                    &	variable-length string field
 
-                    #   represents a single digit in output format for
-                        a number
+                    #	represents a single digit in output format for
+                    	a number
 
-                    .   decimal point in a number
+                    .	decimal point in a number
 
-                    +   sign of a number (will output + or -)
+                    +	sign of a number (will output + or -)
 
-                    -   trailing minus after a number
+                    -	trailing minus after a number
 
-                    **  fill leading spaces with asterisks
+                    **	fill leading spaces with asterisks
 
-                    $$  output dollar sign in front of a number
+                    $$	output dollar sign in front of a number
 
-                    ^^  output number in exponential format
+                    ^^	output number in exponential format
 
-                    _   output next character literally
+                    _	output next character literally
 
                  As currently implemented, the exponential format
                  will be that used by the C compiler.
@@ -1281,8 +1281,8 @@ CONTENTS:
    Command:      QUIT
 
    Description:  QUIT is a synonym for SYSTEM; with INTERACTIVE
-                 environment, it exits the program to the 
-                 operating system (or the calling program).
+		 environment, it exits the program to the 
+		 operating system (or the calling program).
 
    Dependencies: INTERACTIVE
 
@@ -1542,8 +1542,8 @@ CONTENTS:
                  As implemented under bwBASIC, TIME$ cannot be used for
                  assignment (i.e., to set the system time).
 
-   Note:         bwBASIC presently (v2.10) does not allow assignment
-                 to a function.
+   Note:	 bwBASIC presently (v2.10) does not allow assignment
+		 to a function.
 
    Dependencies: COMMON_FUNCS
 
@@ -1677,107 +1677,107 @@ CONTENTS:
    ting-system-specific functions or terminal-specific functions
    that cannot be universally provided. Some specific examples:
 
-   CLOAD        Relies on CP/M or MSDOS conventions for binary
+   CLOAD	Relies on CP/M or MSDOS conventions for binary
                 executable files. 
 
-   CONT         See RESUME below (programmer ignorance?).
+   CONT		See RESUME below (programmer ignorance?).
 
-   DEF USR      Relies on CP/M or MSDOS conventions for binary
+   DEF USR	Relies on CP/M or MSDOS conventions for binary
                 executable files. 
 
-   FRE()        The ability to report the amount of free memory
-                remaining is system-specific due to varying patterns
-                of memory allocation and access; consequently this
-                ability is not present in ANSI or earlier versions 
+   FRE()	The ability to report the amount of free memory
+		remaining is system-specific due to varying patterns
+		of memory allocation and access; consequently this
+		ability is not present in ANSI or earlier versions 
                 of C and this function is not available in bwBASIC.
 
-   INPUT$()     C by itself is not able to read unechoed keyboard 
-                input, and can read keyboard input only after a 
-                Carriage-Return has been entered.
+   INPUT$()	C by itself is not able to read unechoed keyboard 
+		input, and can read keyboard input only after a 
+		Carriage-Return has been entered.
 
-   INP          Calls to hardware ports, like machine-language
-                routines, are highly system-specific and cannot
-                be implemented in C alone.
+   INP		Calls to hardware ports, like machine-language
+   		routines, are highly system-specific and cannot
+   		be implemented in C alone.
 
-   LLIST        See LPRINT below.
+   LLIST	See LPRINT below.
 
-   LPOS         See LPRINT below.
+   LPOS		See LPRINT below.
 
-   LPRINT       and LLIST, etc., require access to a printer device,
-                and this varies from one system to another. Users
-                might try OPENing the printer device on their own
-                operating system (e.g., "/dev/lp" on Unix systems,
-                or "PRN" under DOS) and see if printing can be done
-                from bwBASIC in this way.
+   LPRINT	and LLIST, etc., require access to a printer device,
+   		and this varies from one system to another. Users
+   		might try OPENing the printer device on their own
+   		operating system (e.g., "/dev/lp" on Unix systems,
+   		or "PRN" under DOS) and see if printing can be done
+   		from bwBASIC in this way.
 
-   NULL         In this case, I am convinced that NULL is no longer
-                necessary, since very few printers now require NULLs
-                at the end of lines.
+   NULL		In this case, I am convinced that NULL is no longer
+		necessary, since very few printers now require NULLs
+		at the end of lines.
 
-   OUT          See INP above (calls to hardware ports).
+   OUT		See INP above (calls to hardware ports).
 
-   PEEK()       PEEK and POKE enabled earlier BASICs to address
-                particular memory locations. Although bwBASIC
-                could possibly implement this command (POKE) and
-                this function (PEEK()), the limitation would be
-                highly limited by the different systems for
-                memory access in different systems.
+   PEEK()	PEEK and POKE enabled earlier BASICs to address
+   		particular memory locations. Although bwBASIC
+   		could possibly implement this command (POKE) and
+   		this function (PEEK()), the limitation would be
+   		highly limited by the different systems for
+   		memory access in different systems.
 
-   POKE         see PEEK() above.
+   POKE		see PEEK() above.
 
-   RENUM        Since unnumbered lines can be entered and
-                executed under bwBASIC, it would not be
-                possible to implement a RENUM routine.
-                Instead, bwBASIC uses DO NUM and DO UNNUM.
+   RENUM	Since unnumbered lines can be entered and
+   		executed under bwBASIC, it would not be
+   		possible to implement a RENUM routine.
+   		Instead, bwBASIC uses DO NUM and DO UNNUM.
 
-   RESUME       Is this possible under C? If so, I
-                simply have failed to figure it out yet.
-                Mea culpa (but not maxima).
+   RESUME	Is this possible under C? If so, I
+   		simply have failed to figure it out yet.
+   		Mea culpa (but not maxima).
 
-   USR          See CALL and DEF USR above (machine language
-                subroutines).
+   USR		See CALL and DEF USR above (machine language
+   		subroutines).
 
-   VARPTR       See PEEK and POKE above.
+   VARPTR	See PEEK and POKE above.
 
-   WAIT         See INP and OUT above.
+   WAIT		See INP and OUT above.
 
    There are other commands, functions, and implementation details
    that I am working on, and which are on the agenda list for future
    versions of bwBASIC.  These agenda include:
 
-   PARACT       i.e., the ability to execute PARallel ACTions. This
-                is described in ANSI BASIC, although I have not seen it
-                implemented before.  It will offer a rough, non-
-                preemptive form of multitasking within the scope
-                of a BASIC program. Programmers will note points at which
-                there are already hooks for PARACT in bwBASIC.
-
-   XMEM         PC-type computers need to be able to use extended
-                memory.  If we could use extended memory for program
-                lines, variables, and function defitions, we could
-                write much longer programs.  This would entail,
-                however, a fairly serious rewriting of the program
-                to utilize memory handles for these storage features
-                instead of direct memory pointers.
-
-   Windows      The addition of memory handles in addition to the
-                non-preemptive execution of program lines (in a
-                crude form, already present) will make it possible
-                to develop implementations for Windows and perhaps
-                for other graphical user interfaces.  But what form
-                should this take?  I have in mind presently a BASIC
-                that would run in the background, appearing only
-                as an icon in the GUI space, with pop-up editors
-                and output windows. Thus, the interpreted language
-                would serve a purpose something like 'cron' (a task
-                scheduler) under Unix systems. You may have some
-                reflections that would help me in this.
-
-   Graphics     Here we face fairly critical differences in different
-                styles and implementations of graphics, e.g., between
-                GWBASIC, ANSI BASIC, VisualBASIC, etc. But it's
-                possible that Graphics commands and functions could
-                be added. These would all be implementation-specific.
+   PARACT	i.e., the ability to execute PARallel ACTions. This
+   		is described in ANSI BASIC, although I have not seen it
+   		implemented before.  It will offer a rough, non-
+   		preemptive form of multitasking within the scope
+   		of a BASIC program. Programmers will note points at which
+   		there are already hooks for PARACT in bwBASIC.
+
+   XMEM		PC-type computers need to be able to use extended
+   		memory.  If we could use extended memory for program
+   		lines, variables, and function defitions, we could
+   		write much longer programs.  This would entail,
+   		however, a fairly serious rewriting of the program
+   		to utilize memory handles for these storage features
+   		instead of direct memory pointers.
+
+   Windows	The addition of memory handles in addition to the
+   		non-preemptive execution of program lines (in a
+   		crude form, already present) will make it possible
+   		to develop implementations for Windows and perhaps
+   		for other graphical user interfaces.  But what form
+   		should this take?  I have in mind presently a BASIC
+   		that would run in the background, appearing only
+   		as an icon in the GUI space, with pop-up editors
+   		and output windows. Thus, the interpreted language
+		would serve a purpose something like 'cron' (a task
+		scheduler) under Unix systems. You may have some
+		reflections that would help me in this.
+
+   Graphics	Here we face fairly critical differences in different
+   		styles and implementations of graphics, e.g., between
+   		GWBASIC, ANSI BASIC, VisualBASIC, etc. But it's
+   		possible that Graphics commands and functions could
+   		be added. These would all be implementation-specific.
 
    The ANSI Standard for full BASIC does not specify which particular
    commands or functions must be implemented, and in fact the standard
@@ -1878,3 +1878,4 @@ CONTENTS:
 9. COMMUNICATIONS:
 
    email:  tcamp@delphi.com
+
diff --git a/bwbasic.h b/bwbasic.h
index 7dc15e1..24928e7 100644
--- a/bwbasic.h
+++ b/bwbasic.h
@@ -23,6 +23,10 @@
 
 ***************************************************************/
 
+/*---------------------------------------------------------------*/
+/* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, */
+/* 11/1995 (eidetics@cerf.net).                                  */
+/*---------------------------------------------------------------*/
 
 #ifndef TRUE
 #define TRUE    -1
@@ -37,7 +41,7 @@
 
 /* Version number */
 
-#define VERSION         "2.10"          /* Current version number */
+#define VERSION         "2.20"          /* Current version number */
 
 /***************************************************************
 
@@ -50,10 +54,14 @@
 			It is the most minimal, but the most
 			universal hardware implementation.
 
+			If you pick IMP_TTY then check the settings
+			in bwx_tty.h for your system.
+
 ***************************************************************/
 
 #define IMP_TTY         TRUE     /* simple TTY-style interface using stdio */
 #define IMP_IQC         FALSE    /* IBM PC, Microsoft QuickC Compiler */
+#define ALLOW_RENUM     TRUE     /* Added by JBV */
 
 #if IMP_TTY
 #include "bwx_tty.h"
@@ -109,6 +117,11 @@
 #define HAVE_STDLIB	FALSE	/* Compiler has <stdlib.h> header */
 #endif
 
+/* configure sets this (section added by JBV) */
+#ifndef HAVE_UNISTD
+#define HAVE_UNISTD	FALSE	/* Compiler has <unistd.h> header */
+#endif
+
 #ifdef __STDC__
 #define HAVE_SYSTYPES	TRUE
 #else
@@ -149,8 +162,8 @@
 
 #if CFG_CUSTOM
 #define COMMAND_SHELL   TRUE		/* allow command shell processing */
-#define PROFILE         FALSE           /* interpret profile at beginning */
-#define NUMBER_DOUBLE	FALSE		/* define BASIC number as double: default is float*/
+#define PROFILE         TRUE            /* interpret profile at beginning */
+#define NUMBER_DOUBLE	TRUE		/* define BASIC number as double: default is float*/
 #define MULTISEG_LINES  TRUE            /* allow multi-segment lines delimited by ':' */
 #define PARACT		FALSE		/* Implement PARallen ACTion (Multi-tasking) interpreter */
 #define INTERACTIVE	TRUE		/* interactive programming environment and related commands */
@@ -191,10 +204,13 @@
 
 			You can specify debugging options here.
 
+			Defining DEBUG true provides some useful commands:
+			CMDS, VARS, FNCS
+
 ***************************************************************/
 
-#define DEBUG           FALSE		/* current debugging */
-#define PROG_ERRORS     FALSE  		/* identify serious programming errors */
+#define DEBUG           FALSE  	/* current debugging */
+#define PROG_ERRORS     FALSE  	/* identify serious programming errors */
 					/* and print extensive error messages */
 					/* This will override messages defined in */
 					/* bwb_mes.h, and almost all messages will be in English */
@@ -212,7 +228,11 @@
 
 	bwbasic.h:	This ends the section of definitions that
 			users of bwBASIC will normally need to
-			specify. The following are internally defined
+			specify. The following are internally defined.
+
+			Note that you may need to set up the default
+			FILES command and the default editor below.
+			See Part I-G
 
 ***************************************************************/
 
@@ -297,6 +317,11 @@
 #include <stdlib.h>
 #endif
 
+/* Section added by JBV */
+#if HAVE_UNISTD
+#include <unistd.h>
+#endif
+
 #if HAVE_SYSTYPES
 #include <sys/types.h>
 #endif
@@ -319,7 +344,7 @@
 #define CMDS_DIR	0
 #endif
 #if COMMON_CMDS
-#define CMDS_COMMON	24
+#define CMDS_COMMON	25 /* Was 24 (JBV) */
 #else
 #define CMDS_COMMON	0
 #endif
@@ -376,9 +401,22 @@
 /* ERROR:  MULTISEG_LINES and STRUCT_CMDS cannot be defined together! */
 #endif
 
-#define DEF_EDITOR      ""              /* default editor */
-#define DEF_FILES       ""              /* default "files" command */
-#define DEF_COLORS      0               /* default # of colors */
+/***************************************************************
+
+	bwbasic.h:	Part I-G: Define User Defaults
+
+			Defining your default editor and files commands
+			is a good idea. You must supply the file name
+			for the editor to use.  These defaults can be
+			changed from inside the program or in your profile
+			program by setting the appropriate variables
+			shown below.
+
+***************************************************************/
+
+#define DEF_EDITOR      "vi"            /* default editor */
+#define DEF_FILES       "ls -Fx"         /* default "files" command */
+#define DEF_COLORS      256             /* default # of colors */
 #define DEFVNAME_EDITOR "BWB.EDITOR$"   /* default variable name for EDITOR */
 #define DEFVNAME_PROMPT "BWB.PROMPT$"   /* default variable name for PROMPT */
 #define DEFVNAME_FILES  "BWB.FILES$"    /* default variable name for FILES */
@@ -400,9 +438,9 @@
 #define MAX_DIMS	64		/* maximum # of dimensions */
 #define ESTACKSIZE      64              /* elements in expression stack */
 #define XTXTSTACKSIZE   16              /* elements in eXecute TeXT stack */
-#define N_OPERATORS     24              /* number of operators defined */
+#define N_OPERATORS     25              /* number of operators defined */
 #define N_ERRORS	25		/* number of errors defined */
-#define MAX_PRECEDENCE  19              /* highest (last) level of precedence */
+#define MAX_PRECEDENCE  20              /* highest (last) level of precedence */
 #define MININTSIZE      -32767          /* minimum integer size */
 #define MAXINTSIZE       32767          /* maximum integer size */
 #define DEF_SUBSCRIPT   11              /* default subscript */
@@ -622,6 +660,7 @@ struct dev_element
    int reclen;                          /* record length for random access */
    int next_record;			/* next record to read/write */
    int loc;				/* location in file */
+   int lof;				/* length of file in bytes (JBV) */
    char filename[ MAXFILENAMESIZE + 1 ];/* filename */
    FILE *cfp;                           /* C file pointer for this device */
    char *buffer;			/* pointer to character buffer for random access */
@@ -783,6 +822,8 @@ extern struct bwb_op exp_ops[ N_OPERATORS ]; /* the table itself, filled in in b
 ***************************************************************/
 
 #if ANSI_C
+extern void *CALLOC(size_t nelem, size_t elsize, char *str); /* JBV */
+extern void FREE(void *ptr, char *str); /* JBV */
 extern void bwb_init( int argc, char **argv );
 extern int bwb_fload( FILE *file );
 extern int bwb_ladd( char *buffer, int replace );
@@ -853,6 +894,7 @@ extern struct bwb_line *bwb_ddbl( struct bwb_line *l );
 extern struct bwb_line *bwb_dint( struct bwb_line *l );
 extern struct bwb_line *bwb_dsng( struct bwb_line *l );
 extern struct bwb_line *bwb_dstr( struct bwb_line *l );
+extern struct bwb_line *bwb_mid( struct bwb_line *l );
 extern struct bwb_line *bwb_clear( struct bwb_line *l );
 extern struct bwb_line *bwb_erase( struct bwb_line *l );
 extern struct bwb_line *bwb_swap( struct bwb_line *l );
@@ -941,6 +983,7 @@ extern int prn_precision( struct bwb_variable *v );
 extern int * prn_getcol( FILE *f );
 extern int prn_getwidth( FILE *f );
 extern int prn_xprintf( FILE *f, char *buffer );
+extern int prn_xxprintf( FILE *f, char *buffer ); /* JBV */
 extern int bwb_strtoupper( char *buffer );
 extern int getcmdnum( char *cmdstr );
 
@@ -1008,12 +1051,16 @@ extern struct bwb_line *bwb_renum( struct bwb_line *l );
 #endif
 
 #if UNIX_CMDS
+#if !HAVE_UNISTD /* Not needed if one has <unistd.h> (JBV) */
 extern int rmdir( char *path );
 extern int chdir( char *path );
+#endif
+#if !HAVE_SYSSTAT /* Not needed if one has <sys/stat.h> (JBV) */
 #if MKDIR_ONE_ARG
 extern int mkdir( char *path );
 #else
 extern int mkdir( char *path, unsigned short permissions );
+#endif /* JBV */
 #endif
 #endif
 
@@ -1081,6 +1128,8 @@ extern struct bwb_variable *fnc_test( int argc, struct bwb_variable *argv, int u
 
 #else                                   /* ANSI_C */
 
+extern void *CALLOC(); /* JBV */
+extern void FREE(); /* JBV */
 extern void bwb_init();
 extern int bwb_fload();
 extern int bwb_ladd();
@@ -1151,6 +1200,7 @@ extern struct bwb_line *bwb_ddbl();
 extern struct bwb_line *bwb_dint();
 extern struct bwb_line *bwb_dsng();
 extern struct bwb_line *bwb_dstr();
+extern struct bwb_line *bwb_mid();
 extern struct bwb_line *bwb_clear();
 extern struct bwb_line *bwb_erase();
 extern struct bwb_line *bwb_swap();
@@ -1238,6 +1288,7 @@ extern int prn_precision();
 extern int * prn_getcol();
 extern int prn_getwidth();
 extern int prn_xprintf();
+extern int prn_xxprintf(); /* JBV */
 extern int bwb_strtoupper();
 extern int getcmdnum();
 
diff --git a/bwbtest/pascaltr.bas b/bwbtest/pascaltr.bas
index ed61655..09e7555 100644
--- a/bwbtest/pascaltr.bas
+++ b/bwbtest/pascaltr.bas
@@ -14,4 +14,3 @@
 230           print 
 240   next i
 250   end
-
diff --git a/bwx_iqc.c b/bwx_iqc.c
index 48545a7..15325d2 100644
--- a/bwx_iqc.c
+++ b/bwx_iqc.c
@@ -25,6 +25,14 @@
 
 ***************************************************************/
 
+/*---------------------------------------------------------------*/
+/* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, */
+/* 11/1995 (eidetics@cerf.net).                                  */
+/*                                                               */
+/* Those additionally marked with "DD" were at the suggestion of */
+/* Dale DePriest (daled@cadence.com).                            */
+/*---------------------------------------------------------------*/
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <setjmp.h>
@@ -303,7 +311,9 @@ bwx_shell( struct bwb_line *l )
    if ( init == FALSE )
       {
       init = TRUE;
-      if ( ( s_buffer = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
+
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( s_buffer = CALLOC( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
 	 {
 	 bwb_error( err_getmem );
 	 return FALSE;
@@ -425,9 +435,63 @@ bwb_edit( struct bwb_line *l )
    system( tbuf );
 #endif
 
+   /* open edited file for read */
+
+   if ( ( loadfile = fopen( CURTASK progfile, "r" )) == NULL )
+      {
+      sprintf( bwb_ebuf, err_openfile, CURTASK progfile );
+      bwb_error( bwb_ebuf );
+
+      iqc_setpos();
+      return bwb_zline( l );
+      }
+
    /* clear current contents */
 
-   bwb_new( l );
+   bwb_new( l ); /* Relocated by JBV (bug found by DD) */
+
+   /* and (re)load the file into memory */
+
+   bwb_fload( loadfile );
+
+
+   iqc_setpos();
+   return bwb_zline( l );
+   }
+
+/***************************************************************
+
+        FUNCTION:       bwb_renum()
+
+	DESCRIPTION:    This function implements the BASIC RENUM
+			command by shelling out to a default
+			renumbering program called "renum".
+			Added by JBV 10/95
+
+	SYNTAX:		RENUM
+
+***************************************************************/
+
+#if ANSI_C
+struct bwb_line *
+bwb_renum( struct bwb_line *l )
+#else
+struct bwb_line *
+bwb_renum( l )
+   struct bwb_line *l;
+#endif
+   {
+   char tbuf[ MAXSTRINGSIZE + 1 ];
+   FILE *loadfile;
+
+   sprintf( tbuf, "renum %s\0", CURTASK progfile );
+
+#if INTENSIVE_DEBUG
+   sprintf( bwb_ebuf, "in bwb_renum(): command line <%s>", tbuf );
+   bwb_debug( bwb_ebuf );
+#else
+   system( tbuf );
+#endif
 
    /* open edited file for read */
 
@@ -440,6 +504,10 @@ bwb_edit( struct bwb_line *l )
       return bwb_zline( l );
       }
 
+   /* clear current contents */
+
+   bwb_new( l ); /* Relocated by JBV (bug found by DD) */
+
    /* and (re)load the file into memory */
 
    bwb_fload( loadfile );
@@ -530,7 +598,7 @@ fnc_inkey( int argc, struct bwb_variable *argv )
    if ( init == FALSE )
       {
       init = TRUE;
-      var_make( &nvar, STRING );
+      var_make( &nvar, STRING, "fnc_inkey" );
       }
 
    /* check arguments */
diff --git a/bwx_iqc.h b/bwx_iqc.h
index 95ae38b..d888420 100644
--- a/bwx_iqc.h
+++ b/bwx_iqc.h
@@ -37,4 +37,3 @@
 #define MKDIR_ONE_ARG	TRUE		/* TRUE if your mkdir has but one argument;
 					   FALSE if it has two */
 #define PERMISSIONS	493		/* permissions to set in Unix-type system */
-
\ No newline at end of file
diff --git a/bwx_tty.c b/bwx_tty.c
index 22a5279..41c6759 100644
--- a/bwx_tty.c
+++ b/bwx_tty.c
@@ -28,17 +28,25 @@
 
 ***************************************************************/
 
+/*---------------------------------------------------------------*/
+/* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, */
+/* 11/1995 (eidetics@cerf.net).                                  */
+/*                                                               */
+/* Those additionally marked with "DD" were at the suggestion of */
+/* Dale DePriest (daled@cadence.com).                            */
+/*---------------------------------------------------------------*/
+
 #include <stdio.h>
 
 #include "bwbasic.h"
 #include "bwb_mes.h"
 
-#if HAVE_LONGJMP
+#if HAVE_LONGJUMP /* Revised by JBV (bug found by DD) */
 #include <setjmp.h>
 #endif
 
 extern int prn_col;
-#if HAVE_LONGJMP
+#if HAVE_LONGJUMP /* Revised by JBV (bug found by DD) */
 extern jmp_buf mark;
 #endif
 
@@ -69,7 +77,7 @@ main( argc, argv )
 
    bwb_init( argc, argv );
 
-#if HAVE_LONGJMP
+#if HAVE_LONGJUMP /* Revised by JBV (bug found by DD) */
 #if INTERACTIVE
    setjmp( mark );
 #endif
@@ -82,7 +90,8 @@ main( argc, argv )
       bwb_mainloop();
       }
 
-   bwx_terminate();			/* in case of ^D exit in Unix systems */
+      bwx_terminate();			/* allow ^D (Unix) exit with grace */
+
 
    }
 
@@ -267,9 +276,6 @@ void
 bwx_terminate()
 #endif
    {
-#if INTENSIVE_DEBUG
-   fprintf( stderr, "Normal Termination\n" );
-#endif
    exit( 0 );
    }
 
@@ -301,7 +307,9 @@ bwx_shell( l )
    if ( init == FALSE )
       {
       init = TRUE;
-      if ( ( s_buffer = calloc( MAXSTRINGSIZE + 1, sizeof( char ) )) == NULL )
+
+      /* Revised to CALLOC pass-thru call by JBV */
+      if ( ( s_buffer = CALLOC( MAXSTRINGSIZE + 1, sizeof( char ), "bwx_shell" )) == NULL )
 	 {
 	 bwb_error( err_getmem );
 	 return FALSE;
@@ -425,9 +433,61 @@ bwb_edit( l )
    system( tbuf );
 #endif
 
+   /* open edited file for read */
+
+   if ( ( loadfile = fopen( CURTASK progfile, "r" )) == NULL )
+      {
+      sprintf( bwb_ebuf, err_openfile, CURTASK progfile );
+      bwb_error( bwb_ebuf );
+
+      return bwb_zline( l );
+      }
+
    /* clear current contents */
 
-   bwb_new( l );
+   bwb_new( l ); /* Relocated by JBV (bug found by DD) */
+
+   /* and (re)load the file into memory */
+
+   bwb_fload( loadfile );
+
+
+   return bwb_zline( l );
+   }
+
+/***************************************************************
+
+        FUNCTION:       bwb_renum()
+
+	DESCRIPTION:    This function implements the BASIC RENUM
+			command by shelling out to a default
+			renumbering program called "renum".
+			Added by JBV 10/95
+
+	SYNTAX:		RENUM
+
+***************************************************************/
+
+#if ANSI_C
+struct bwb_line *
+bwb_renum( struct bwb_line *l )
+#else
+struct bwb_line *
+bwb_renum( l )
+   struct bwb_line *l;
+#endif
+   {
+   char tbuf[ MAXSTRINGSIZE + 1 ];
+   FILE *loadfile;
+
+   sprintf( tbuf, "renum %s\0", CURTASK progfile );
+
+#if INTENSIVE_DEBUG
+   sprintf( bwb_ebuf, "in bwb_renum(): command line <%s>", tbuf );
+   bwb_debug( bwb_ebuf );
+#else
+   system( tbuf );
+#endif
 
    /* open edited file for read */
 
@@ -439,6 +499,10 @@ bwb_edit( l )
       return bwb_zline( l );
       }
 
+   /* clear current contents */
+
+   bwb_new( l ); /* Relocated by JBV (bug found by DD) */
+
    /* and (re)load the file into memory */
 
    bwb_fload( loadfile );
diff --git a/bwx_tty.h b/bwx_tty.h
index 76fe9a9..02c8e50 100644
--- a/bwx_tty.h
+++ b/bwx_tty.h
@@ -27,6 +27,11 @@
 
 ***************************************************************/
 
+/*---------------------------------------------------------------*/
+/* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, */
+/* 11/1995 (eidetics@cerf.net).                                  */
+/*---------------------------------------------------------------*/
+
 #define IMP_IDSTRING    "TTY"           /* unique ID string for this implementation */
 
 /* Definitions indicating which commands and functions are implemented */
@@ -36,8 +41,7 @@
 #define IMP_CMDLOC	0		/* 0 if LOCATE is not implemented, 1 if it is */
 #define IMP_CMDCOLOR    0               /* 0 if COLOR is not implemented, 1 if it is */
 
-#define UNIX_CMDS       FALSE
+#define UNIX_CMDS       TRUE  /* It better be for UNIX systems (JBV) */
 #define MKDIR_ONE_ARG   FALSE           /* TRUE if your mkdir has but one argument;
 					   FALSE if it has two */
-#define PERMISSIONS	493		/* permissions to set in Unix-type system */
-
\ No newline at end of file
+#define PERMISSIONS	644		/* permissions to set in Unix-type system */
diff --git a/configur b/configure
old mode 100644
new mode 100755
similarity index 94%
rename from configur
rename to configure
index 62e07ec..173df74
--- a/configur
+++ b/configure
@@ -22,6 +22,10 @@
 # Ignores all args except --srcdir, --prefix, --exec-prefix, --no-create, and
 # --with-PACKAGE unless this script has special code to handle it.
 
+##---------------------------------------------------------------##
+## NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, ##
+## 11/1995 (eidetics@cerf.net).                                  ##
+##---------------------------------------------------------------##
 
 for arg
 do
@@ -213,6 +217,17 @@ if test -z "$err"; then
 fi
 rm -f conftest*
 
+# unistd.h checking added by JBV
+echo checking for unistd.h
+cat > conftest.c <<EOF
+#include <unistd.h>
+EOF
+err=`eval "$CPP $DEFS conftest.c 2>&1 >/dev/null"`
+if test -z "$err"; then
+  DEFS="$DEFS -DHAVE_UNISTD=1"
+fi
+rm -f conftest*
+
 echo checking for raise
 cat > conftest.c <<EOF
 #include <sys/types.h>
@@ -300,4 +315,3 @@ EOF
 chmod +x config.status
 test -n "$no_create" || ./config.status
 
-
\ No newline at end of file
diff --git a/configur.in b/configure.in
similarity index 87%
rename from configur.in
rename to configure.in
index b5e53dd..8baa146 100644
--- a/configur.in
+++ b/configure.in
@@ -6,7 +6,7 @@ AC_PROG_INSTALL
 AC_SIZE_T
 AC_HEADER_CHECK(string.h, AC_DEFINE(HAVE_STRING))
 AC_HEADER_CHECK(stdlib.h, AC_DEFINE(HAVE_STDLIB))
+AC_HEADER_CHECK(unistd.h, AC_DEFINE(HAVE_UNISTD))
 AC_COMPILE_CHECK(raise, [#include <sys/types.h>
 #include <signal.h>], [raise(1);], AC_DEFINE(HAVE_RAISE))
 AC_OUTPUT(Makefile)
-
\ No newline at end of file
diff --git a/renum.c b/renum.c
new file mode 100644
index 0000000..227fa8c
--- /dev/null
+++ b/renum.c
@@ -0,0 +1,545 @@
+/*-------------------------------------------------------------------*/
+/* renum.c -- Renumbers a BASIC program in an ASCII file.            */
+/* Originally written in HP 2000 BASIC by David Lance Robinson, 1977 */
+/* Adapted to MS BASIC and translated to C 4/1995 by Jon B. Volkoff  */
+/* (eidetics@cerf.net)                                               */
+/*-------------------------------------------------------------------*/
+
+#include <stdio.h>
+
+int instr();
+char *midstr1();
+char *midstr2();
+void binary_search(void);
+
+int f2, l2, n, x;
+int sidx[1500][2];
+char rstr[255];
+
+main(argc, argv)
+   int argc;
+   char *argv[];
+{
+   int f, d, s, p, s1, t, l, g;
+   int c, f1, c1, i, f8, r, l1, l3;
+   int v1, f6, l6, b, f9, x9, b1, p8, p9, a, d9;
+   char pstr[255], sstr[255], f9str[255], s9str[255], tempstr[255];
+   FILE *fdin, *fdout;
+   int skip, bp, temp, getout, disp_msg;
+
+   f = 1;
+
+   if (argc > 1) strcpy(pstr, argv[1]);
+   else
+   {
+      printf("Program in file? ");
+      gets(pstr);
+   }
+   if (strlen(pstr) == 0) strcpy(pstr, "0.doc");
+
+   fdin = fopen(pstr, "r");
+   if (fdin == NULL)
+   {
+      printf("Unable to open input file\n");
+      exit(1);
+   }
+   strcpy(f9str, pstr);
+
+   strcpy(pstr, "editfl");
+   fdout = fopen(pstr, "w");
+   if (fdout == NULL)
+   {
+      printf("Unable to open editfl output file\n");
+      exit(1);
+   }
+
+   /* Main program begins here */
+   s = 0; l2 = 0; d = 0;
+   f2 = 10000;
+   printf ("PLEASE WAIT A FEW SECONDS!\n");
+   while (fgets(pstr, 255, fdin) != NULL)
+   {
+      pstr[strlen(pstr) - 1] = '\0';
+      p = instr(pstr, " ");
+      if (p != 0 && p <= 5)
+      {
+         n = atoi(midstr2(pstr, 1, p));
+         if (n != 0)
+         {
+            s++;
+            sidx[s][0] = n;
+            s1 = s;
+            while (s1 >= 2)
+            {
+               s1--;
+               if (sidx[s1][0] < sidx[s1 + 1][0]) break;
+               if (sidx[s1][0] == sidx[s1 + 1][0])
+               {
+                  printf("ERROR !!! MORE THAN ONE STATEMENT FOR A ");
+                  printf("STATEMENT NUMBER\n");
+                  exit(1);
+               }
+
+               t = sidx[s1][0];
+               sidx[s1][0] = sidx[s1 + 1][0];
+               sidx[s1 + 1][0] = t;
+            }
+         }
+      }
+   }
+   fclose(fdin);
+
+   if (s == 0)
+   {
+      printf("NO PROGRAM IS IN THE FILE!\n");
+      exit(1);
+   }
+
+   for (l = 1; l <= s; l++)
+      sidx[l][1] = sidx[l][0];
+   g = 1;
+   disp_msg = 1;
+
+   /*------------------------------------------------------------------------*/
+   /* Find out how and what to renumber (using HP BASIC renumber parameters) */
+   /* MS BASIC renumber is: RENUM (newnum) (,(oldnum) (,increment))          */
+   /*------------------------------------------------------------------------*/
+
+   while(1)
+   {
+      if (disp_msg == 1)
+      {
+         printf("RENUMBER (-starting number (,interval (,first statement ");
+         printf("(,last))))\n");
+         disp_msg = 0;
+      }
+
+      skip = 0;
+      bp = 0;
+      printf("RENUMBER-");
+      gets(pstr);
+      p = strlen(pstr);
+
+      if (g == 0)
+      {
+         if (strlen(pstr) == 0) break;
+         if (p == 0) skip = 1;
+         else
+         {
+            t = atoi(midstr2(pstr, 1, 1));
+            if (t == 0) break;
+         }
+      }
+
+      if (strlen(pstr) == 0) skip = 1;
+
+      if (skip == 0)
+      {
+         c = instr(pstr, ",");
+         temp = 0; if (c != 0) temp = -1;
+         f1 = atoi(midstr2(pstr, 1, p + temp*(p - c + 1)));
+         if (f1 == 0) bp = 1;
+         if (c == 0) skip = 2;
+      }
+
+      if (skip == 0 && bp == 0)
+      {
+         c1 = instr(midstr1(pstr, c + 1), ",") + c;
+         temp = 0; if (c1 != c) temp = -1;
+         i = atoi(midstr2(pstr, c + 1, p + temp*(p - c1 + 1) - c));
+         if (i == 0) bp = 1;
+         if (c1 == c) skip = 3;
+      }
+
+      if (skip == 0 && bp == 0)
+      {
+         c = instr(midstr1(pstr, c1 + 1), ",") + c1;
+         temp = 0; if (c != c1) temp = -1;
+         f8 = atoi(midstr2(pstr, c1 + 1, p + temp*(p - c + 1) - c1));
+         if (f8 == 0) bp = 1;
+         if (c == c1) skip = 4;
+      }
+
+      if (skip == 0 && bp == 0)
+      {
+         l = atoi(midstr1(pstr, c + 1));
+         if (l == 0) bp = 1;
+      }
+
+      if (bp == 0) switch (skip)
+      {
+         case 1:
+            f1 = 10;
+            i = 10;
+            f8 = 1;
+            l = 99999;
+            break;
+
+         case 2:
+            i = 10;
+            f8 = 1;
+            l = 99999;
+            break;
+
+         case 3:
+            f8 = 1;
+            l = 99999;
+            break;
+
+         case 4:
+            l = 99999;
+            break;
+      }
+
+      if (f1 < 1 || i == 0 || f8 < 1 || l < 1) bp = 1;
+
+      if (f1 > 99999 || i > 99999 || f8 > 99999 || l > 99999 || f8 > l)
+         bp = 1;
+
+      c = 0;
+      for (r = 1; r <= s; r++)
+         if (sidx[r][0] >= f8 && sidx[r][0] <= l) c = c + 1;
+      if (c == 0)
+      {
+         printf("There is nothing to renumber !!\n");
+         disp_msg = 1;
+      }
+
+      /*------------------------------------*/
+      /* Make list of new statement numbers */
+      /*------------------------------------*/
+
+      l1 = f1 + (c - 1)*i;
+      if (l1 < 1 || l1 > 99999) bp = 1;
+
+      x = 0; c = 0;
+      if (bp == 0 && disp_msg == 0) for (r = 1; r <= s; r++)
+      {
+         if (sidx[r][0] < f8 || sidx[r][0] > l)
+         if (sidx[r][1] >= f1 && sidx[r][1] <= l1)
+         {
+            printf("SEQUENCE NUMBER OVERLAP\n");
+            exit(1);
+         }
+         else {}
+         else
+         {
+            if (sidx[r][0] != f1 + c*i)
+            {
+               if (x == 0)
+               {
+                  if (r < f2) f2 = r;
+                  x = 1;
+               }
+
+               if (r > l2) l2 = r;
+            }
+
+            sidx[r][1] = f1 + c*i;
+            c++;
+            l3 = r;
+         }
+      }
+
+      if (bp == 0 && disp_msg == 0) g = 0;
+
+      if (bp == 1) printf("BAD PARAMETER\n");
+   }
+
+   /*-------------------*/
+   /* Start renumbering */
+   /*-------------------*/
+
+   if (l2 == 0)
+   {
+      printf("NOTHING RENUMBERED!\n");
+      exit(1);
+   }
+
+   printf("RENUMBERING\n");
+/*   for (r = 1; r <= s; r ++)
+      printf("%d -> %d\n", sidx[r][0], sidx[r][1]); */
+
+   printf("VERIFY? ");
+   gets(pstr);
+   v1 = 0;
+   if (strcmp(midstr2(pstr, 1, 1), "N") == 0) v1 = 1;
+
+   fdin = fopen(f9str, "r");
+   if (fdin == NULL)
+   {
+      printf("Unable to open input file\n");
+      exit(1);
+   }
+
+   f6 = sidx[f2][0];
+   l6 = sidx[l2][0];
+
+   while (fgets(pstr, 255, fdin) != NULL)
+   {
+      pstr[strlen(pstr) - 1] = '\0';
+      b = instr(pstr, " ");
+      if (b != 0)
+      {
+         n = atoi(midstr2(pstr, 1, b));
+         if (n != 0)
+         {
+            if (n >= f6 && n <= l6)
+            {
+               binary_search();
+               if (x == 0)
+               {
+                  strcat(rstr, midstr1(pstr, b));
+                  strcpy(pstr, rstr);
+                  b = instr(pstr, " ");
+               }
+            }
+            b++;
+
+            /*-------------------------------------------------------------*/
+            /* There are differences, of course, between processing for HP */
+            /* BASIC and MS BASIC.                                         */
+            /*                                                             */
+            /* CONVERT, PRINT USING, and MAT PRINT USING changes are not   */
+            /* applicable in MS BASIC.                                     */
+            /*                                                             */
+            /* Had to also add capability for multiple statements here.    */
+            /*-------------------------------------------------------------*/
+
+            while(1)
+            {
+               if (strcmp(midstr2(pstr, b, 3), "REM") == 0 ||
+               strcmp(midstr2(pstr, b, 1), "'") == 0) break;
+
+               f9 = 0;
+               skip = 0;
+               for (x9 = b; x9 <= strlen(pstr); x9++)
+               {
+                  if ((char)(*midstr2(pstr, x9, 1)) == 34) 
+                  {
+                     if (f9 == 0)
+                        f9 = 1;
+                     else
+                        f9 = 0;
+                  }
+                  else if (strcmp(midstr2(pstr, x9, 1), ":") == 0 &&
+                  f9 == 0)
+                  {
+                     b1 = x9 - 1;
+                     skip = 1;
+                     break;
+                  }
+               }
+               if (skip == 0) b1 = strlen(pstr);
+
+               t = instr("GOSGOTIF ON RESRET", midstr2(pstr, b, 3));
+
+               temp = (t + 5)/3;
+               if (temp != 1)
+               {
+                  if (temp == 2 || temp == 3 || temp == 4 || temp == 6 ||
+                  temp == 7)
+                  {
+                     /*-------------------------------------------------*/
+                     /* Change GOSUB, GOTO, IF, RESTORE, RESUME, RETURN */
+                     /* routine.                                        */
+                     /* Go word by word through the statement.          */
+                     /*-------------------------------------------------*/
+                     getout = 0;
+                     p8 = b;
+                     strcpy(s9str, " ");
+                  }
+                  else if (temp == 5)
+                  {
+                     /*---------------------------------------------------*/
+                     /* Change ON event/expression GOSUB/GOTO routine.    */
+                     /* Find starting point appropriate to this statement */
+                     /* type.                                             */
+                     /*---------------------------------------------------*/
+                     getout = 1;
+                     for (x9 = b1; x9 >= b; x9--)
+                     {
+                        if (strcmp(midstr2(pstr, x9, 1), " ") == 0)
+                        {
+                           p8 = x9 + 1;
+                           getout = 0;
+                           break;
+                        }
+                     }
+
+                     if (getout == 0) strcpy(s9str, ",");
+                  }
+
+                  /* Start looping here */
+                  if (getout == 0) while(1)
+                  {
+                     f9 = 0;
+                     skip = 0;
+                     for (x9 = p8; x9 <= b1; x9++)
+                     {
+                        if ((char)(*midstr2(pstr, x9, 1)) == 34)
+                        {
+                           if (f9 == 0)
+                              f9 = 1;
+                           else
+                              f9 = 0;
+                        }
+                        else if (strcmp(midstr2(pstr, x9, 1), s9str) == 0 &&
+                        f9 == 0)
+                        {
+                           p9 = x9 - 1;
+                           skip = 1;
+                           break;
+                        }
+                     }
+                     if (skip == 0) p9 = b1;
+
+                     skip = 0;
+                     for (x9 = p8; x9 <= p9; x9++)
+                     {
+                        a = (char)(*midstr2(pstr, x9, 1));
+                        if (a < 48 || a > 57)
+                        {
+                           skip = 1;
+                           break;
+                        }
+                     }
+
+                     if (skip == 0)
+                     {
+                        /*---------------------*/
+                        /* Found a line number */
+                        /*---------------------*/
+                        n = atoi(midstr2(pstr, p8, p9 - p8 + 1));
+                        if (n != 0)
+                        {
+                           if (n >= f6 && n <= l6)
+                           {
+                              binary_search();
+                              if (x == 0)
+                              {
+                                 if (p9 == strlen(pstr))
+                                 {
+                                    strcpy(tempstr, midstr2(pstr, 1, p8 - 1));
+                                    strcat(tempstr, rstr);
+                                    strcpy(pstr, tempstr);
+                                 }
+                                 else
+                                 {
+                                    strcpy(tempstr, midstr2(pstr, 1, p8 - 1));
+                                    strcat(tempstr, rstr);
+                                    strcat(tempstr, midstr1(pstr, p9 + 1));
+                                    strcpy(pstr, tempstr);
+                                 }
+
+                                 /*-----------------------------------*/
+                                 /* Adjust indices to account for new */
+                                 /* substring length, if any.         */
+                                 /*-----------------------------------*/
+                                 d9 = strlen(rstr) - (p9 - p8 + 1);
+                                 p9 = p9 + d9;
+                                 b1 = b1 + d9;
+                              }
+                           }
+                        }
+                     }
+
+                     p8 = p9 + 2;
+                     if (p8 > b1) break;
+                  }
+               }
+
+               /*--------------------------------------------------*/
+               /* No more words to process in the statement, go to */
+               /* next statement.                                  */
+               /*--------------------------------------------------*/
+               if (b1 == strlen(pstr)) break;
+               b = b1 + 2;
+            }
+         }
+      }
+
+      fprintf(fdout, "%s\n", pstr);
+      if (v1 == 0) printf("%s\n", pstr);
+   }
+
+   fclose(fdin);
+   fclose(fdout);
+   sprintf(tempstr, "mv editfl %s\0", f9str);
+   system(tempstr);
+}
+
+
+int instr(astr, bstr)
+   char *astr, *bstr;
+{
+   int p;
+
+   p = strstr(astr, bstr);
+   if (p == NULL) p = (int)(astr) - 1;
+   p = p - (int)(astr) + 1;
+
+   return p;
+}
+
+
+char *midstr1(astr, start)
+   char *astr;
+   int start;
+{
+   static char tempstr[255];
+   char *startptr;
+
+   strcpy(tempstr, astr);
+   startptr = (char *)((long)(tempstr) + start - 1);
+
+   return startptr;
+}
+
+
+char *midstr2(astr, start, len)
+   char *astr;
+   int start, len;
+{
+   static char tempstr[255];
+   char *startptr, *endptr;
+
+   strcpy(tempstr, astr);
+   startptr = (char *)((long)(tempstr) + start - 1);
+   endptr = (char *)((long)(tempstr) + start + len - 1);
+   strcpy(endptr, "\0");
+
+   return startptr;
+}
+
+
+void binary_search(void)
+{
+   int f5, l5, m;
+
+   f5 = f2;
+   l5 = l2 + 1;
+
+   while(1)
+   {
+      m = (f5 + l5)/2;
+
+      if (sidx[m][0] == n)
+      {
+         sprintf(rstr, "%d\0", sidx[m][1]);
+         x = 0;
+         return;
+      }
+
+      if (m == f5 || m == l5)
+      {
+         x = 1;
+         return;
+      }
+
+      if (sidx[m][0] < n)
+         f5 = m;
+      else
+         l5 = m;
+   }
+}
