From 92f5c4f26aeb95d2b70fe73875bc98304c87549b Mon Sep 17 00:00:00 2001
From: Travis Cross <tc@traviscross.com>
Date: Sat, 5 Apr 2014 05:31:57 +0000
Subject: [PATCH] Pull in new upstream my-basic

ref: http://my-basic.googlecode.com/svn/trunk@57
---
 my_basic.c | 45 ++++++++++++++++++++++++++++++++++++---------
 my_basic.h |  7 ++++++-
 2 files changed, 42 insertions(+), 10 deletions(-)

diff --git a/my_basic.c b/my_basic.c
index f0af683b64..dcc30fa0a5 100644
--- a/my_basic.c
+++ b/my_basic.c
@@ -3,7 +3,7 @@
 **
 ** For the latest info, see http://code.google.com/p/my-basic/
 **
-** Copyright (c) 2011 - 2013 Tony & Tony's Toy Game Development Team
+** Copyright (c) 2011 - 2014 paladin_t
 **
 ** Permission is hereby granted, free of charge, to any person obtaining a copy of
 ** this software and associated documentation files (the "Software"), to deal in
@@ -66,9 +66,9 @@ extern "C" {
 /** Macros */
 #define _VER_MAJOR 1
 #define _VER_MINOR 0
-#define _VER_REVISION 37
+#define _VER_REVISION 40
 #define _MB_VERSION ((_VER_MAJOR * 0x01000000) + (_VER_MINOR * 0x00010000) + (_VER_REVISION))
-#define _MB_VERSION_STRING "1.0.0037"
+#define _MB_VERSION_STRING "1.0.0040"
 
 /* Uncomment this line to treat warnings as error */
 /*#define _WARING_AS_ERROR*/
@@ -198,12 +198,15 @@ static const char* _ERR_DESC[] = {
 	"Integer expected",
 	"ELSE statement expected",
 	"TO statement expected",
+	"NEXT statement expected",
 	"UNTIL statement expected",
 	"Loop variable expected",
 	"Jump label expected",
+	"Variable expected",
 	"Invalid identifier usage",
 	"Calculation error",
 	"Divide by zero",
+	"MOD by zero",
 	"Invalid expression",
 	"Out of memory",
 	/** Extended abort */
@@ -469,7 +472,7 @@ static _object_t* _exp_assign = 0;
 		val->data.integer = strcmp(_str1, _str2) __optr 0; \
 	} while(0)
 
-#define _proc_div_by_zero(__s, __tuple, __exit, __result) \
+#define _proc_div_by_zero(__s, __tuple, __exit, __result, __kind) \
 	do { \
 		_object_t opndv1; \
 		_object_t opndv2; \
@@ -493,7 +496,7 @@ static _object_t* _exp_assign = 0;
 				val->type = _DT_REAL; \
 				val->data.integer = _FINF; \
 			} \
-			_handle_error_on_obj((__s), SE_RN_DIVIDE_BY_ZERO, ((__tuple) && *(__tuple)) ? ((_object_t*)(((_tuple3_t*)(*(__tuple)))->e1)) : 0, MB_FUNC_WARNING, __exit, __result); \
+			_handle_error_on_obj((__s), __kind, ((__tuple) && *(__tuple)) ? ((_object_t*)(((_tuple3_t*)(*(__tuple)))->e1)) : 0, MB_FUNC_WARNING, __exit, __result); \
 		} \
 	} while(0)
 
@@ -1884,7 +1887,9 @@ void _set_current_error(mb_interpreter_t* s, mb_error_e err) {
 	/* Set current error information */
 	mb_assert(s && err >= 0 && err < _countof(_ERR_DESC));
 
-	s->last_error = err;
+	if(s->last_error == SE_NO_ERR) {
+		s->last_error = err;
+	}
 }
 
 const char* _get_error_desc(mb_error_e err) {
@@ -3771,6 +3776,20 @@ int mb_set_printer(mb_interpreter_t* s, mb_print_func_t p) {
 	return result;
 }
 
+int mb_gets(char* buf, int s) {
+	/* Safe stdin reader function */
+	int result = 0;
+	if(fgets(buf, s, stdin) == 0) {
+		fprintf(stderr, "Error reading.\n");
+		exit(1);
+	}
+	result = (int)strlen(buf);
+	if(buf[result - 1] == '\n')
+		buf[result - 1] = '\0';
+
+	return result;
+}
+
 /* ========================================================} */
 
 /*
@@ -3839,7 +3858,7 @@ int _core_div(mb_interpreter_t* s, void** l) {
 
 	mb_assert(s && l);
 
-	_proc_div_by_zero(s, l, _exit, result);
+	_proc_div_by_zero(s, l, _exit, result, SE_RN_DIVIDE_BY_ZERO);
 	_instruct_num_op_num(/, l);
 
 _exit:
@@ -3852,8 +3871,10 @@ int _core_mod(mb_interpreter_t* s, void** l) {
 
 	mb_assert(s && l);
 
+	_proc_div_by_zero(s, l, _exit, result, SE_RN_MOD_BY_ZERO);
 	_instruct_int_op_int(%, l);
 
+_exit:
 	return result;
 }
 
@@ -4513,6 +4534,9 @@ _to:
 				goto _exit;
 			}
 
+			if(!ast) {
+				_handle_error_on_obj(s, SE_RN_NEXT_EXPECTED, DON(ast), MB_FUNC_ERR, _exit, result);
+			}
 			obj = (_object_t*)(ast->data);
 		}
 
@@ -5623,8 +5647,11 @@ int _std_input(mb_interpreter_t* s, void** l) {
 	ast = (_ls_node_t*)(*l);
 	obj = (_object_t*)(ast->data);
 
+	if(!obj || obj->type != _DT_VAR) {
+		_handle_error_on_obj(s, SE_RN_VARIABLE_EXPECTED, DON(ast), MB_FUNC_ERR, _exit, result);
+	}
 	if(obj->data.variable->data->type == _DT_INT || obj->data.variable->data->type == _DT_REAL) {
-		gets(line);
+		mb_gets(line, sizeof(line));
 		obj->data.variable->data->type = _DT_INT;
 		obj->data.variable->data->data.integer = (int_t)strtol(line, &conv_suc, 0);
 		if(*conv_suc != '\0') {
@@ -5641,7 +5668,7 @@ int _std_input(mb_interpreter_t* s, void** l) {
 		}
 		obj->data.variable->data->data.string = (char*)mb_malloc(256);
 		memset(obj->data.variable->data->data.string, 0, 256);
-		gets(line);
+		mb_gets(line, sizeof(line));
 		strcpy(obj->data.variable->data->data.string, line);
 	} else {
 		result = MB_FUNC_ERR;
diff --git a/my_basic.h b/my_basic.h
index aeade77ec6..9524e9435e 100644
--- a/my_basic.h
+++ b/my_basic.h
@@ -3,7 +3,7 @@
 **
 ** For the latest info, see http://code.google.com/p/my-basic/
 **
-** Copyright (c) 2011 - 2013 Tony & Tony's Toy Game Development Team
+** Copyright (c) 2011 - 2014 paladin_t
 **
 ** Permission is hereby granted, free of charge, to any person obtaining a copy of
 ** this software and associated documentation files (the "Software"), to deal in
@@ -141,12 +141,15 @@ typedef enum mb_error_e {
 	SE_RN_INTEGER_EXPECTED,
 	SE_RN_ELSE_EXPECTED,
 	SE_RN_TO_EXPECTED,
+	SE_RN_NEXT_EXPECTED,
 	SE_RN_UNTIL_EXPECTED,
 	SE_RN_LOOP_VAR_EXPECTED,
 	SE_RN_JUMP_LABEL_EXPECTED,
+	SE_RN_VARIABLE_EXPECTED,
 	SE_RN_INVALID_ID_USAGE,
 	SE_RN_CALCULATION_ERROR,
 	SE_RN_DIVIDE_BY_ZERO,
+	SE_RN_MOD_BY_ZERO,
 	SE_RN_INVALID_EXPRESSION,
 	SE_RN_OUT_OF_MEMORY,
 	/** Extended abort */
@@ -226,6 +229,8 @@ MBAPI const char* mb_get_error_desc(mb_error_e err);
 MBAPI int mb_set_error_handler(mb_interpreter_t* s, mb_error_handler_t h);
 MBAPI int mb_set_printer(mb_interpreter_t* s, mb_print_func_t p);
 
+MBAPI int mb_gets(char* buf, int s);
+
 #ifdef MB_COMPACT_MODE
 #	pragma pack()
 #endif /* MB_COMPACT_MODE */