 
 	Serial.print( (long)i, DEC );
 	Serialprintln( " bytes saved." );
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Mass storage (files on desktop, banks of SD on device)
+#ifdef kIncludeMassStorage
+
+void cmd_msnew( void )
+{
+	Serialprintln( "NEW." );
+}
+
+void cmd_mslist( void )
+{
+	Serialprintln( "BANKS:" );
+}
+
+void cmd_mssave( char * line )
+{
+	if( *line == '\0' ) {
+		Serialprintln( "MSSAVE: No bank!" );
+		return;
+	}
+
+	Serialprint( "SAVE TO BANK " );
+	int bank = atoi( line );
+
+	if( bank < 0 || bank > 255 ) {
+		Serialprintln( "MSSAVE: Bad bank!" );
+		return;
+	}
+
+	Serial.print( (long)bank, DEC );
+	SerialprintNewline();
+}
+
+void cmd_msload( char * line )
+{
+	if( *line == '\0' ) {
+		Serialprintln( "MSLOAD: No bank!" );
+		return;
+	}
+
+	Serialprint( "LOAD FROM BANK " );
+	int bank = atoi( line );
+
+	if( bank < 0 || bank > 255 ) {
+		Serialprintln( "MSLOAD: Bad bank!" );
+		return;
+	}
+
+	Serial.print( (long)bank, DEC );
+	SerialprintNewline();
+}
+
+#endif
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+// buffer is used for keyboard input, as well as string manipulation routines
+#define kBufLen (32)
+char buffer[kBufLen];
+
+// PRINT_LINE for debugging
+#define PRINT_LINE( L ) \
+	{ \
+		for( char * tl = (L) ; *tl != '\n' && *tl != '\0' ; tl++ ) \
+			Serial.write( tl, 1 ); \
+		Serial.println( "" ); \
+	}
+
+////////////////////////////////////////////////////////////
+// Skip Number
+
+#define macroSKIP_NUMBER( A ) \
+	while(     (*A) >= '0' \
+		&& (*A) <= '9' \
+		&& (*A) != '\0' ) (A)++;
+
+void SkipNumber( char ** l )
+{
+	macroSKIP_NUMBER( *l );
+}
+#define SKIP_NUMBER( A ) \
+	SkipNumber( &A )
+
+
+////////////////////////////////////////////////////////////
+// Skip Whitespace
+
+#define macroSKIP_WHITESPACE( A ) \
+	while( (   (*A) == ' ' \
+		|| (*A) == '\t' \
+		|| (*A) == ',' \
+	        ) && (*A) != '\0' ) (A)++; /* parens here are IMPORTANT */
+
+void SkipWhitespace( char ** l )
+{
+	macroSKIP_WHITESPACE( *l );
+}
+
+#define SKIP_WHITESPACE( A ) \
+	SkipWhitespace( &A )
+
+////////////////////////////////////////////////////////////
+
+#define macroSKIP_UPPERCASE( x ) \
+	while(     (*x) >= 'A' \
+		&& (*x) <= 'Z' \
+		&& (*x) != '\0' ) (x)++;
+
+void SkipUppercase( char ** l )
+{
+	macroSKIP_UPPERCASE( *l );
+}
+
+#define SKIP_UPPERCASE( A ) \
+	SkipUppercase( &A )
+
+////////////////////////////////////////////////////////////
+
+int myAtoi( char * buf )
+{
+	int v = 0;
+	// find the integer starting at buf[0]
+	while( *buf <= '9' && *buf >= '0' && v<kBufLen  ) {
+		buffer[v++] = *buf;
+		buf++;
+	}
+	if( v == 0 ) {
+		// no number!
+		return -1;
+	}
+
+	buffer[v] = '\0';
+
+	// my atoi (save on library overhead)
+	v = 0;
+	buf = buffer;
+	while( *buf ) {
+		v *= 10;
+		v += (*buf)-'0';
+		buf++;
+	}
+	return v;
+}
+
+
+// same as the above, but it affects the line pointer
+int myAtoiP( char ** buf, int * next )
+{
+	if( *next == kJRSyntaxError ) return 0;
+	int v = myAtoi( *buf );
+	SKIP_NUMBER( *buf );
+	return v;
 }
 
 

        SetSerialDelay();
        
	Serialprintln( "BLuB " kBLuBVersion );
	delay( serialDelay );
	cmd_mem();

#ifdef USE_MORE_PROGRAMSPACE
	Serialprintln( "\nCommands:" );
	delay( serialDelay );
	//                   ------- ------- ------- ------- -------
	Serialprintln( "    help    mem     vars    new     list" );
	delay( serialDelay );
	Serialprintln( "    run     tron    troff" );
	delay( serialDelay );
	Serialprintln( "    elist   eload   esave   enew" );
	delay( serialDelay );
	//                   ------- ------- ------- ------- -------
#endif
}

char linebuf[kLineLen];
char * bptr;

int strMatches( char * haystack, const char * needle )
{
	if( !haystack || !needle ) return 0;

	while( *haystack != '\0' && *needle != '\0' )
	{
		if( *haystack != *needle ) return 0;

		haystack++;
		needle++;
	}

	if( *needle == '\0' ) return 1;
	return 0;
}

void loop()
{
	// print out something
