+mixed array support; *some bugfix

This commit is contained in:
tony 2015-04-13 22:32:41 +08:00
parent 29f72c4d8a
commit 2ff04a09bc
7 changed files with 156 additions and 38 deletions

View File

@ -1,3 +1,9 @@
Apr. 13 2015
Added mixed integer/float array support
Added warning prompt when passing strings to maths functions
Fixed a memory leak when storing strings in an array
Polisned the interpreter commands
Apr. 11 2015 Apr. 11 2015
Moved struct mb_interpreter_t from my_basic.h to my_basic.c Moved struct mb_interpreter_t from my_basic.h to my_basic.c
Added an mb_has_argument interface to tell whether there is any more argument Added an mb_has_argument interface to tell whether there is any more argument

View File

@ -78,7 +78,7 @@ extern "C" {
/** Macros */ /** Macros */
#define _VER_MAJOR 1 #define _VER_MAJOR 1
#define _VER_MINOR 0 #define _VER_MINOR 0
#define _VER_REVISION 48 #define _VER_REVISION 49
#define _MB_VERSION ((_VER_MAJOR * 0x01000000) + (_VER_MINOR * 0x00010000) + (_VER_REVISION)) #define _MB_VERSION ((_VER_MAJOR * 0x01000000) + (_VER_MINOR * 0x00010000) + (_VER_REVISION))
/* Uncomment this line to treat warnings as error */ /* Uncomment this line to treat warnings as error */
@ -190,9 +190,10 @@ static const char* _ERR_DESC[] = {
"Array subscript expected", "Array subscript expected",
"Structure not completed", "Structure not completed",
"Function expected", "Function expected",
"String expected",
"Variable or array identifier expected", "Variable or array identifier expected",
"Assign operator expected", "Assign operator expected",
"String expected",
"Number expected",
"Integer expected", "Integer expected",
"ELSE statement expected", "ELSE statement expected",
"TO statement expected", "TO statement expected",
@ -249,8 +250,11 @@ typedef struct _var_t {
typedef struct _array_t { typedef struct _array_t {
char* name; char* name;
_data_e type; _data_e type;
unsigned int count; #ifndef MB_SIMPLE_ARRAY
_data_e* types;
#endif /* MB_SIMPLE_ARRAY */
void* raw; void* raw;
unsigned int count;
int dimension_count; int dimension_count;
int dimensions[_MAX_DIMENSION_COUNT]; int dimensions[_MAX_DIMENSION_COUNT];
} _array_t; } _array_t;
@ -260,7 +264,9 @@ typedef struct _label_t {
_ls_node_t* node; _ls_node_t* node;
} _label_t; } _label_t;
typedef unsigned char _raw_t[sizeof(union { int_t i; real_t r; void* p; })]; typedef union _raw_u { int_t i; real_t r; void* p; } _raw_u;
typedef unsigned char _raw_t[sizeof(_raw_u)];
typedef struct _object_t { typedef struct _object_t {
_data_e type; _data_e type;
@ -1894,7 +1900,10 @@ int _calc_expression(mb_interpreter_t* s, _ls_node_t** l, _object_t** val) {
memset(arr_elem, 0, sizeof(_object_t)); memset(arr_elem, 0, sizeof(_object_t));
_ls_pushback(garbage, arr_elem); _ls_pushback(garbage, arr_elem);
arr_elem->type = arr_type; arr_elem->type = arr_type;
if(arr_type == _DT_REAL) { arr_elem->ref = true;
if(arr_type == _DT_INT) {
arr_elem->data.integer = arr_val.integer;
} else if(arr_type == _DT_REAL) {
arr_elem->data.float_point = arr_val.float_point; arr_elem->data.float_point = arr_val.float_point;
} else if(arr_type == _DT_STRING) { } else if(arr_type == _DT_STRING) {
arr_elem->data.string = arr_val.string; arr_elem->data.string = arr_val.string;
@ -2608,6 +2617,7 @@ int_t _get_size_of(_data_e type) {
/* Get the size of a data type */ /* Get the size of a data type */
int_t result = 0; int_t result = 0;
#ifdef MB_SIMPLE_ARRAY
if(type == _DT_INT) { if(type == _DT_INT) {
result = sizeof(int_t); result = sizeof(int_t);
} else if(type == _DT_REAL) { } else if(type == _DT_REAL) {
@ -2617,6 +2627,9 @@ int_t _get_size_of(_data_e type) {
} else { } else {
mb_assert(0 && "Unsupported"); mb_assert(0 && "Unsupported");
} }
#else /* MB_SIMPLE_ARRAY */
result = sizeof(_raw_u);
#endif /* MB_SIMPLE_ARRAY */
return result; return result;
} }
@ -2726,8 +2739,18 @@ bool_t _get_array_elem(mb_interpreter_t* s, _array_t* arr, unsigned int index, m
pos = (unsigned int)(elemsize * index); pos = (unsigned int)(elemsize * index);
rawptr = (void*)((intptr_t)arr->raw + pos); rawptr = (void*)((intptr_t)arr->raw + pos);
if(arr->type == _DT_REAL) { if(arr->type == _DT_REAL) {
#ifdef MB_SIMPLE_ARRAY
val->float_point = *((real_t*)rawptr); val->float_point = *((real_t*)rawptr);
*type = _DT_REAL; *type = _DT_REAL;
#else /* MB_SIMPLE_ARRAY */
if(arr->types[index] == _DT_REAL) {
val->float_point = *((real_t*)rawptr);
*type = _DT_REAL;
} else {
val->integer = *((int_t*)rawptr);
*type = _DT_INT;
}
#endif /* MB_SIMPLE_ARRAY */
} else if(arr->type == _DT_STRING) { } else if(arr->type == _DT_STRING) {
val->string = *((char**)rawptr); val->string = *((char**)rawptr);
*type = _DT_STRING; *type = _DT_STRING;
@ -2752,9 +2775,17 @@ bool_t _set_array_elem(mb_interpreter_t* s, _array_t* arr, unsigned int index, m
pos = (unsigned int)(elemsize * index); pos = (unsigned int)(elemsize * index);
rawptr = (void*)((intptr_t)arr->raw + pos); rawptr = (void*)((intptr_t)arr->raw + pos);
if(*type == _DT_INT) { if(*type == _DT_INT) {
#ifdef MB_SIMPLE_ARRAY
*((real_t*)rawptr) = (real_t)val->integer; *((real_t*)rawptr) = (real_t)val->integer;
#else /* MB_SIMPLE_ARRAY */
*((int_t*)rawptr) = val->integer;
arr->types[index] = _DT_INT;
#endif /* MB_SIMPLE_ARRAY */
} else if(*type == _DT_REAL) { } else if(*type == _DT_REAL) {
*((real_t*)rawptr) = val->float_point; *((real_t*)rawptr) = val->float_point;
#ifndef MB_SIMPLE_ARRAY
arr->types[index] = _DT_REAL;
#endif /* MB_SIMPLE_ARRAY */
} else if(*type == _DT_STRING) { } else if(*type == _DT_STRING) {
size_t _sl = strlen(val->string); size_t _sl = strlen(val->string);
*((char**)rawptr) = (char*)mb_malloc(_sl + 1); *((char**)rawptr) = (char*)mb_malloc(_sl + 1);
@ -2769,47 +2800,56 @@ bool_t _set_array_elem(mb_interpreter_t* s, _array_t* arr, unsigned int index, m
void _init_array(_array_t* arr) { void _init_array(_array_t* arr) {
/* Initialize an array */ /* Initialize an array */
int elemsize = 0; int elemsize = 0;
#ifndef MB_SIMPLE_ARRAY
unsigned int ul = 0;
#endif
mb_assert(arr); mb_assert(arr);
#ifdef MB_SIMPLE_ARRAY
elemsize = (int)_get_size_of(arr->type); elemsize = (int)_get_size_of(arr->type);
#else /* MB_SIMPLE_ARRAY */
elemsize = (int)_get_size_of(_DT_ANY);
#endif /* MB_SIMPLE_ARRAY */
mb_assert(arr->count > 0); mb_assert(arr->count > 0);
mb_assert(!arr->raw); mb_assert(!arr->raw);
arr->raw = (void*)mb_malloc(elemsize * arr->count); arr->raw = (void*)mb_malloc(elemsize * arr->count);
if(arr->raw) { if(arr->raw) {
memset(arr->raw, 0, elemsize * arr->count); memset(arr->raw, 0, elemsize * arr->count);
} }
#ifndef MB_SIMPLE_ARRAY
arr->types = (_data_e*)mb_malloc(sizeof(_data_e) * arr->count);
if(arr->types) {
for(ul = 0; ul < arr->count; ++ul) {
arr->types[ul] = _DT_INT;
}
}
#endif /* MB_SIMPLE_ARRAY */
} }
void _clear_array(_array_t* arr) { void _clear_array(_array_t* arr) {
/* Clear an array */ /* Clear an array */
char** strs = 0; char* str = 0;
int_t elemsize = 0;
unsigned int pos = 0;
void* rawptr = 0;
unsigned int ul = 0; unsigned int ul = 0;
mb_assert(arr); mb_assert(arr);
if(arr->raw) { if(arr->raw) {
switch(arr->type) { if(arr->type == _DT_STRING) {
case _DT_INT: /* Fall through */
case _DT_REAL:
safe_free(arr->raw);
break;
case _DT_STRING:
strs = (char**)arr->raw;
for(ul = 0; ul < arr->count; ++ul) { for(ul = 0; ul < arr->count; ++ul) {
if(strs[ul]) { elemsize = _get_size_of(arr->type);
safe_free(strs[ul]); pos = (unsigned int)(elemsize * ul);
rawptr = (void*)((intptr_t)arr->raw + pos);
str = *((char**)rawptr);
if(str) {
safe_free(str);
} }
} }
safe_free(arr->raw);
break;
default:
mb_assert(0 && "Unsupported");
break;
} }
safe_free(arr->raw);
arr->raw = 0; arr->raw = 0;
} }
} }
@ -2820,6 +2860,11 @@ void _destroy_array(_array_t* arr) {
_clear_array(arr); _clear_array(arr);
safe_free(arr->name); safe_free(arr->name);
#ifndef MB_SIMPLE_ARRAY
if(arr->types) {
safe_free(arr->types);
}
#endif /* MB_SIMPLE_ARRAY */
safe_free(arr); safe_free(arr);
} }
@ -4352,10 +4397,13 @@ int _core_neg(mb_interpreter_t* s, void** l) {
break; break;
default: default:
_handle_error_on_obj(s, SE_RN_NUMBER_EXPECTED, (l && *l) ? ((_object_t*)(((_tuple3_t*)(*l))->e1)) : 0, MB_FUNC_WARNING, _exit, result);
break; break;
} }
mb_check(mb_push_value(s, l, arg)); mb_check(mb_push_value(s, l, arg));
_exit:
return result; return result;
} }
@ -4646,16 +4694,28 @@ int _core_let(mb_interpreter_t* s, void** l) {
} }
} else if(arr) { } else if(arr) {
mb_value_u _val; mb_value_u _val;
if(val->type == _DT_INT) { switch(val->type) {
case _DT_INT:
_val.integer = val->data.integer; _val.integer = val->data.integer;
} else if(val->type == _DT_REAL) {
break;
case _DT_REAL:
_val.float_point = val->data.float_point; _val.float_point = val->data.float_point;
} else if(val->type == _DT_STRING) {
break;
case _DT_STRING:
_val.string = val->data.string; _val.string = val->data.string;
} else {
break;
default:
mb_assert(0 && "Unsupported"); mb_assert(0 && "Unsupported");
break;
} }
_set_array_elem(s, arr, arr_idx, &_val, &val->type); _set_array_elem(s, arr, arr_idx, &_val, &val->type);
if(val->type == _DT_STRING && !val->ref) {
safe_free(val->data.string);
}
} }
safe_free(val); safe_free(val);
@ -5323,10 +5383,13 @@ int _std_abs(mb_interpreter_t* s, void** l) {
break; break;
default: default:
_handle_error_on_obj(s, SE_RN_NUMBER_EXPECTED, (l && *l) ? ((_object_t*)(((_tuple3_t*)(*l))->e1)) : 0, MB_FUNC_WARNING, _exit, result);
break; break;
} }
mb_check(mb_push_value(s, l, arg)); mb_check(mb_push_value(s, l, arg));
_exit:
return result; return result;
} }
@ -5354,10 +5417,13 @@ int _std_sgn(mb_interpreter_t* s, void** l) {
break; break;
default: default:
_handle_error_on_obj(s, SE_RN_NUMBER_EXPECTED, (l && *l) ? ((_object_t*)(((_tuple3_t*)(*l))->e1)) : 0, MB_FUNC_WARNING, _exit, result);
break; break;
} }
mb_check(mb_push_int(s, l, arg.value.integer)); mb_check(mb_push_int(s, l, arg.value.integer));
_exit:
return result; return result;
} }
@ -5385,10 +5451,13 @@ int _std_sqr(mb_interpreter_t* s, void** l) {
break; break;
default: default:
_handle_error_on_obj(s, SE_RN_NUMBER_EXPECTED, (l && *l) ? ((_object_t*)(((_tuple3_t*)(*l))->e1)) : 0, MB_FUNC_WARNING, _exit, result);
break; break;
} }
mb_check(mb_push_value(s, l, arg)); mb_check(mb_push_value(s, l, arg));
_exit:
return result; return result;
} }
@ -5416,10 +5485,13 @@ int _std_floor(mb_interpreter_t* s, void** l) {
break; break;
default: default:
_handle_error_on_obj(s, SE_RN_NUMBER_EXPECTED, (l && *l) ? ((_object_t*)(((_tuple3_t*)(*l))->e1)) : 0, MB_FUNC_WARNING, _exit, result);
break; break;
} }
mb_check(mb_push_int(s, l, arg.value.integer)); mb_check(mb_push_int(s, l, arg.value.integer));
_exit:
return result; return result;
} }
@ -5447,10 +5519,13 @@ int _std_ceil(mb_interpreter_t* s, void** l) {
break; break;
default: default:
_handle_error_on_obj(s, SE_RN_NUMBER_EXPECTED, (l && *l) ? ((_object_t*)(((_tuple3_t*)(*l))->e1)) : 0, MB_FUNC_WARNING, _exit, result);
break; break;
} }
mb_check(mb_push_int(s, l, arg.value.integer)); mb_check(mb_push_int(s, l, arg.value.integer));
_exit:
return result; return result;
} }
@ -5478,10 +5553,13 @@ int _std_fix(mb_interpreter_t* s, void** l) {
break; break;
default: default:
_handle_error_on_obj(s, SE_RN_NUMBER_EXPECTED, (l && *l) ? ((_object_t*)(((_tuple3_t*)(*l))->e1)) : 0, MB_FUNC_WARNING, _exit, result);
break; break;
} }
mb_check(mb_push_int(s, l, arg.value.integer)); mb_check(mb_push_int(s, l, arg.value.integer));
_exit:
return result; return result;
} }
@ -5509,10 +5587,13 @@ int _std_round(mb_interpreter_t* s, void** l) {
break; break;
default: default:
_handle_error_on_obj(s, SE_RN_NUMBER_EXPECTED, (l && *l) ? ((_object_t*)(((_tuple3_t*)(*l))->e1)) : 0, MB_FUNC_WARNING, _exit, result);
break; break;
} }
mb_check(mb_push_int(s, l, arg.value.integer)); mb_check(mb_push_int(s, l, arg.value.integer));
_exit:
return result; return result;
} }
@ -5556,10 +5637,13 @@ int _std_sin(mb_interpreter_t* s, void** l) {
break; break;
default: default:
_handle_error_on_obj(s, SE_RN_NUMBER_EXPECTED, (l && *l) ? ((_object_t*)(((_tuple3_t*)(*l))->e1)) : 0, MB_FUNC_WARNING, _exit, result);
break; break;
} }
mb_check(mb_push_value(s, l, arg)); mb_check(mb_push_value(s, l, arg));
_exit:
return result; return result;
} }
@ -5587,10 +5671,13 @@ int _std_cos(mb_interpreter_t* s, void** l) {
break; break;
default: default:
_handle_error_on_obj(s, SE_RN_NUMBER_EXPECTED, (l && *l) ? ((_object_t*)(((_tuple3_t*)(*l))->e1)) : 0, MB_FUNC_WARNING, _exit, result);
break; break;
} }
mb_check(mb_push_value(s, l, arg)); mb_check(mb_push_value(s, l, arg));
_exit:
return result; return result;
} }
@ -5618,10 +5705,13 @@ int _std_tan(mb_interpreter_t* s, void** l) {
break; break;
default: default:
_handle_error_on_obj(s, SE_RN_NUMBER_EXPECTED, (l && *l) ? ((_object_t*)(((_tuple3_t*)(*l))->e1)) : 0, MB_FUNC_WARNING, _exit, result);
break; break;
} }
mb_check(mb_push_value(s, l, arg)); mb_check(mb_push_value(s, l, arg));
_exit:
return result; return result;
} }
@ -5649,10 +5739,13 @@ int _std_asin(mb_interpreter_t* s, void** l) {
break; break;
default: default:
_handle_error_on_obj(s, SE_RN_NUMBER_EXPECTED, (l && *l) ? ((_object_t*)(((_tuple3_t*)(*l))->e1)) : 0, MB_FUNC_WARNING, _exit, result);
break; break;
} }
mb_check(mb_push_value(s, l, arg)); mb_check(mb_push_value(s, l, arg));
_exit:
return result; return result;
} }
@ -5680,10 +5773,13 @@ int _std_acos(mb_interpreter_t* s, void** l) {
break; break;
default: default:
_handle_error_on_obj(s, SE_RN_NUMBER_EXPECTED, (l && *l) ? ((_object_t*)(((_tuple3_t*)(*l))->e1)) : 0, MB_FUNC_WARNING, _exit, result);
break; break;
} }
mb_check(mb_push_value(s, l, arg)); mb_check(mb_push_value(s, l, arg));
_exit:
return result; return result;
} }
@ -5711,10 +5807,13 @@ int _std_atan(mb_interpreter_t* s, void** l) {
break; break;
default: default:
_handle_error_on_obj(s, SE_RN_NUMBER_EXPECTED, (l && *l) ? ((_object_t*)(((_tuple3_t*)(*l))->e1)) : 0, MB_FUNC_WARNING, _exit, result);
break; break;
} }
mb_check(mb_push_value(s, l, arg)); mb_check(mb_push_value(s, l, arg));
_exit:
return result; return result;
} }
@ -5742,10 +5841,13 @@ int _std_exp(mb_interpreter_t* s, void** l) {
break; break;
default: default:
_handle_error_on_obj(s, SE_RN_NUMBER_EXPECTED, (l && *l) ? ((_object_t*)(((_tuple3_t*)(*l))->e1)) : 0, MB_FUNC_WARNING, _exit, result);
break; break;
} }
mb_check(mb_push_value(s, l, arg)); mb_check(mb_push_value(s, l, arg));
_exit:
return result; return result;
} }
@ -5773,10 +5875,13 @@ int _std_log(mb_interpreter_t* s, void** l) {
break; break;
default: default:
_handle_error_on_obj(s, SE_RN_NUMBER_EXPECTED, (l && *l) ? ((_object_t*)(((_tuple3_t*)(*l))->e1)) : 0, MB_FUNC_WARNING, _exit, result);
break; break;
} }
mb_check(mb_push_value(s, l, arg)); mb_check(mb_push_value(s, l, arg));
_exit:
return result; return result;
} }

View File

@ -38,6 +38,10 @@ extern "C" {
# define MB_ENABLE_SOURCE_TRACE # define MB_ENABLE_SOURCE_TRACE
#endif /* MB_ENABLE_SOURCE_TRACE */ #endif /* MB_ENABLE_SOURCE_TRACE */
#ifndef MB_SIMPLE_ARRAY
# define MB_SIMPLE_ARRAY
#endif /* MB_SIMPLE_ARRAY */
#ifndef MB_COMPACT_MODE #ifndef MB_COMPACT_MODE
# define MB_COMPACT_MODE # define MB_COMPACT_MODE
#endif /* MB_COMPACT_MODE */ #endif /* MB_COMPACT_MODE */
@ -155,9 +159,10 @@ typedef enum mb_error_e {
SE_RN_ARRAY_SUBSCRIPT_EXPECTED, SE_RN_ARRAY_SUBSCRIPT_EXPECTED,
SE_RN_STRUCTURE_NOT_COMPLETED, SE_RN_STRUCTURE_NOT_COMPLETED,
SE_RN_FUNCTION_EXPECTED, SE_RN_FUNCTION_EXPECTED,
SE_RN_STRING_EXPECTED,
SE_RN_VAR_OR_ARRAY_EXPECTED, SE_RN_VAR_OR_ARRAY_EXPECTED,
SE_RN_ASSIGN_OPERATOR_EXPECTED, SE_RN_ASSIGN_OPERATOR_EXPECTED,
SE_RN_STRING_EXPECTED,
SE_RN_NUMBER_EXPECTED,
SE_RN_INTEGER_EXPECTED, SE_RN_INTEGER_EXPECTED,
SE_RN_ELSE_EXPECTED, SE_RN_ELSE_EXPECTED,
SE_RN_TO_EXPECTED, SE_RN_TO_EXPECTED,

Binary file not shown.

Binary file not shown.

View File

@ -62,8 +62,8 @@ IDI_ICON_MAIN ICON "icon.ico"
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,45 FILEVERSION 1,0,0,49
PRODUCTVERSION 1,0,0,45 PRODUCTVERSION 1,0,0,49
FILEFLAGSMASK 0x17L FILEFLAGSMASK 0x17L
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -81,13 +81,13 @@ BEGIN
VALUE "Comments", "MY-BASIC" VALUE "Comments", "MY-BASIC"
VALUE "CompanyName", "W. Renxin" VALUE "CompanyName", "W. Renxin"
VALUE "FileDescription", "MY-BASIC interpreter" VALUE "FileDescription", "MY-BASIC interpreter"
VALUE "FileVersion", "1, 0, 0, 48" VALUE "FileVersion", "1, 0, 0, 49"
VALUE "InternalName", "my_basic" VALUE "InternalName", "my_basic"
VALUE "LegalCopyright", "Copyright (C) 2011 - 2015 W. Renxin" VALUE "LegalCopyright", "Copyright (C) 2011 - 2015 W. Renxin"
VALUE "LegalTrademarks", "MY-BASIC" VALUE "LegalTrademarks", "MY-BASIC"
VALUE "OriginalFilename", "my_basic.exe" VALUE "OriginalFilename", "my_basic.exe"
VALUE "ProductName", "MY-BASIC" VALUE "ProductName", "MY-BASIC"
VALUE "ProductVersion", "1, 0, 0, 48" VALUE "ProductVersion", "1, 0, 0, 49"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View File

@ -120,7 +120,7 @@ static char* _get_code(_code_line_t* code) {
for(i = 0; i < code->count; ++i) { for(i = 0; i < code->count; ++i) {
result = strcat(result, code->lines[i]); result = strcat(result, code->lines[i]);
if(i != code->count - 1) { if(i != code->count - 1) {
result = strcat(result, "\r\n"); result = strcat(result, "\n");
} }
} }
@ -201,8 +201,9 @@ static int beep(struct mb_interpreter_t* s, void** l) {
static void _on_error(struct mb_interpreter_t* s, mb_error_e e, char* m, int p, unsigned short row, unsigned short col, int abort_code) { static void _on_error(struct mb_interpreter_t* s, mb_error_e e, char* m, int p, unsigned short row, unsigned short col, int abort_code) {
mb_unrefvar(s); mb_unrefvar(s);
mb_unrefvar(p);
if(SE_NO_ERR != e) { if(SE_NO_ERR != e) {
printf("Error:\n [POS] %d, [ROW] %d, [COL] %d,\n [CODE] %d, [MESSAGE] %s, [ABORT CODE] %d\n", p, row, col, e, m, abort_code); printf("Error:\n [LINE] %d, [COL] %d,\n [CODE] %d, [MESSAGE] %s, [ABORT CODE] %d\n", row, col, e, m, abort_code);
} }
} }
@ -251,9 +252,10 @@ static void _list_program(const char* sn, const char* cn) {
lsn = atoi(sn); lsn = atoi(sn);
lcn = atoi(cn); lcn = atoi(cn);
if(lsn == 0 && lcn == 0) { if(lsn == 0 && lcn == 0) {
char* txt = _get_code(c); long i = 0;
printf("%s\n", txt); for(i = 0; i < c->count; ++i) {
free(txt); printf("%d]%s\n", i + 1, c->lines[i]);
}
} else { } else {
long i = 0; long i = 0;
long e = 0; long e = 0;
@ -273,7 +275,7 @@ static void _list_program(const char* sn, const char* cn) {
if(i >= c->count) { if(i >= c->count) {
break; break;
} }
printf("%s\n", c->lines[i]); printf("%d]%s\n", i + 1, c->lines[i]);
} }
} }
} }