added files

This commit is contained in:
tony 2014-11-20 00:51:18 +08:00
commit 4d87b74c8e
22 changed files with 7594 additions and 0 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

135
HISTORY Normal file
View File

@ -0,0 +1,135 @@
May. 25 2014
Added a mb_set_inputer function which allows the user to specify an INPUT reader, thanks to Michael P. Welch for suggestion
Added a mb_remove_reserved_func function which allows the user to disable/remove a reserved statement
May. 22 2014
Fixed a crash bug when missing colon in a combined line, thanks to Michael P. Welch for pointing it out
Fixed a missing lexical cursor stepping bug in INPUT function
Mar. 17 2014
Added an XCode project
Added a safe stdin reader function mb_gets
Fixed a crash bug in INPUT function
Feb. 17 2014
Added mod by zero processing
Feb. 16 2014
Fixed a crash bug in _core_for, thanks to mummylauncher for pointing it out
Jul. 19 2013
Fixed a crash bug in _execute_statement, thanks to Jon Mayo for pointing it out
Feb. 25 2013
Fixed a cross routine multi-statement execution bug, thanks to Bruce Kendall for pointing it out
Fixed a memory corruption bug when loading a script file
Jan. 9 2013
Fixed a crash bug when using EDIT command
Dec. 14 2012
Added an invalid expression error handling
Added an out of memory error handling
Dec. 5 2012
Fixed a minus calculation bug, thanks to Bill Walker for pointing it out
Nov. 14 2012
Fixed a cross routine RETURN bug, thanks to Bruce Kendall for pointing it out
Sep. 12 2012
Fixed a bug in ASC
Fixed a label parsing, jumping bug, thanks to Ahmad Hawwash for pointing above two issues out
Fixed a crash bug in IF statement
Added divide by zero processing
Added calculation error raising
Sep. 1 2012
Fixed a redisposing bug when retrieving a string argument, thanks to Ahmad Hawwash for pointing it out
Fixed a memory leak after retrieving a composited string argument
Aug. 29 2012
Modified an odd string comparison behavior, thanks to Matthias Nott for testing it out
Added a warning system, disabled warning as default
Improved compatibility with GCC
Aug. 3 2012
Implemented memory occupation statistics
Improved compatibility on 64bit systems
Fixed some warnings under a stricter mode
Jul. 21 2012
Added a compatibility macro for PRINT a newline
Added an mb_attempt_func_end C API
Fixed a unary minus symbol parsing bug
Jul. 19 2012
Fixed a crash bug caused by a mistake in calculation priority table, thanks to Bruce Kendall for pointing it out
Jul. 10 2012
Implemented KILL command
Fixed a negative calculation bug
Added an invalid identifier usage error handling
Avoided some warnings on gcc
Jul. 5 2012
Implemented LIST, EDIT, LOAD, SAVE commands
Jul. 4 2012
Fixed some crash bugs
Fixed some memory leaks
Jul. 3 2012
Modified/added math functions: FLOOR, CEIL, FIX
Fixed an INPUT type issue
Changed float number formatting from using "%f" to "%g" in PRINT, thanks to Bruce Kendall for pointing above three issues out
Refactored the way to load a script file
Done several small improvements
Jun. 29 2012
Fixed a newline mistake in PRINT
Jun. 29 2012
Implemented customizable print functor
Improved PRINT statement
Fixed an infinity loop bug in RND function
Fixed some crash bugs
Jun. 28 2012
Fixed a cross routine RETURN bug, thanks to Bruce Kendall for pointing it out
Fixed some memory leaks
Refactored error position informing
Jun. 18 2012
Implemented user extended abort, thanks to Bruce Kendall for giving suggestion
Apr. 30 2012
Compress number to integer if necessary
Apr. 27 2012
Fixed a string connecting crash bug, thanks to Ahmad Hawwash for pointing it out
Improved portability on gcc
Aug. 3 2011
Fixed hashtable removing bug
Jun. 18 2011
Fixed some mistakes
Allowed underline character appear in an identifier
Apr. 15 2011
Fixed garbage collection and _label_t release bugs
Apr. 14 2011
Fixed some list / comparison operator bugs
Feb. 15 2011
Improved portability on Cocoa
Improved portability on VC++ 6.0
Fixed a suspend / resume bug
Feb. 9 2011
Fixed struct mb_interpreter_t declaration warnings on gcc
Feb. 1 2011
First release.

20
LICENSE Normal file
View File

@ -0,0 +1,20 @@
The MIT License
Copyright (c) 2011 - 2014 W. Renxin
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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

25
README Normal file
View File

@ -0,0 +1,25 @@
Introduction
MY-BASIC is a tiny cross-platform easy extendable BASIC interpreter written
in pure C with about 5000 lines of source code. Its grammar is similar
to structured BASIC in early era, but without line number. It is aimed to
be either an embeddable scripting language or a standalone interpreter. The
core is pretty light; all in a C source file and an associated header file.
You can combine MY-BASIC with an existing C / C++ / Objective-C project
easily, that can make them more powerful.
Main features
Written in clean ANSI C, source portable
Most GW-BASIC like syntax, but without line numbers
Small and fast
Not case-sensitive
Integer / float point / string / boolean / array data types support
IF - THEN - ELSE support
FOR - TO - STEP - NEXT / WHILE - WEND / DO - UNTIL support
GOTO / GOSUB - RETURN support
Numeric functions
String functions
Easy to embed into C / C++ / Objective-C projects
High expansibility
It is free
Moved from old repository: https://code.google.com/p/my-basic/

21
clean.cmd Normal file
View File

@ -0,0 +1,21 @@
@echo off
echo Cleaning, a moment please...
attrib *.suo -s -r -h
del /f /s /q *.suo
del /f /s /q *.user
del /f /s /q *.ncb
rd /s /q temp
del /f /s /q output\*.res
del /f /s /q output\*.dep
del /f /s /q output\*.htm
del /f /s /q output\*.ilk
del /f /s /q output\*.manifest
del /f /s /q output\*.obj
del /f /s /q output\*.pdb
del /f /s /q output\*.idb
del /f /s /q output\my_basic_d.exe
echo Cleaning done!

5922
core/my_basic.c Normal file

File diff suppressed because it is too large Load Diff

249
core/my_basic.h Normal file
View File

@ -0,0 +1,249 @@
/*
** This source file is part of MY-BASIC
**
** For the latest info, see https://github.com/paladin-t/my_basic/
**
** Copyright (c) 2011 - 2014 W. Renxin
**
** 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
** the Software without restriction, including without limitation the rights to
** use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
** the Software, and to permit persons to whom the Software is furnished to do so,
** subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in all
** copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
** FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
** COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
** IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __MY_BASIC_H__
#define __MY_BASIC_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#ifndef MBAPI
# define MBAPI
#endif /* MBAPI */
#ifndef MB_COMPACT_MODE
# define MB_COMPACT_MODE
#endif /* MB_COMPACT_MODE */
#ifdef MB_COMPACT_MODE
# pragma pack(1)
#endif /* MB_COMPACT_MODE */
#ifndef true
# define true (!0)
#endif
#ifndef false
# define false (0)
#endif
#ifndef bool_t
# define bool_t int
#endif
#ifndef byte_t
# define byte_t unsigned char
#endif
#ifndef int_t
# define int_t int
#endif
#ifndef real_t
# define real_t float
#endif
#ifndef _MSC_VER
# ifndef _strcmpi
# define _strcmpi strcasecmp
# endif /* _strcmpi */
#endif /* _MSC_VER */
#ifndef mb_assert
# define mb_assert(__a) do { ((void)(__a)); assert(__a); } while(0)
#endif /* mb_assert */
#ifndef mb_unrefvar
# define mb_unrefvar(__v) ((void)(__v))
#endif /* mb_unrefvar */
#ifndef MB_CODES
# define MB_CODES
# define MB_FUNC_OK 0
# define MB_FUNC_BYE 1001
# define MB_FUNC_WARNING 1002
# define MB_FUNC_ERR 1003
# define MB_FUNC_END 1004
# define MB_FUNC_SUSPEND 1005
# define MB_PARSING_ERR 3001
# define MB_LOOP_BREAK 5001
# define MB_LOOP_CONTINUE 5002
# define MB_SUB_RETURN 5101
# define MB_EXTENDED_ABORT 9001
#endif /* MB_CODES */
#ifndef mb_check
# define mb_check(__r) { int __hr = __r; if(__hr != MB_FUNC_OK) { return __hr; } }
#endif /* mb_check */
#ifndef mb_reg_fun
# define mb_reg_fun(__s, __f) mb_register_func(__s, #__f, __f)
#endif /* mb_reg_fun */
#ifndef mb_rem_fun
# define mb_rem_fun(__s, __f) mb_remove_func(__s, #__f)
#endif /* mb_rem_fun */
#ifndef mb_rem_res_fun
# define mb_rem_res_fun(__s, __f) mb_remove_reserved_func(__s, #__f)
#endif /* mb_rem_res_fun */
struct mb_interpreter_t;
typedef enum mb_error_e {
SE_NO_ERR = 0,
/** Common */
SE_CM_MB_OPEN_FAILED,
SE_CM_FUNC_EXISTS,
SE_CM_FUNC_NOT_EXISTS,
/** Parsing */
SE_PS_FILE_OPEN_FAILED,
SE_PS_SYMBOL_TOO_LONG,
SE_PS_INVALID_CHAR,
/** Running */
SE_RN_NOT_SUPPORTED,
SE_RN_EMPTY_PROGRAM,
SE_RN_SYNTAX,
SE_RN_INVALID_DATA_TYPE,
SE_RN_TYPE_NOT_MATCH,
SE_RN_ILLEGAL_BOUND,
SE_RN_DIMENSION_TOO_MUCH,
SE_RN_OPERATION_FAILED,
SE_RN_DIMENSION_OUT_OF_BOUND,
SE_RN_ARRAY_OUT_OF_BOUND,
SE_RN_LABEL_NOT_EXISTS,
SE_RN_NO_RETURN_POINT,
SE_RN_COLON_EXPECTED,
SE_RN_COMMA_OR_SEMICOLON_EXPECTED,
SE_RN_ARRAY_IDENTIFIER_EXPECTED,
SE_RN_OPEN_BRACKET_EXPECTED,
SE_RN_CLOSE_BRACKET_EXPECTED,
SE_RN_ARRAY_SUBSCRIPT_EXPECTED,
SE_RN_STRUCTURE_NOT_COMPLETED,
SE_RN_FUNCTION_EXPECTED,
SE_RN_STRING_EXPECTED,
SE_RN_VAR_OR_ARRAY_EXPECTED,
SE_RN_ASSIGN_OPERATOR_EXPECTED,
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 */
SE_EA_EXTENDED_ABORT,
} mb_error_e;
typedef enum mb_data_e {
MB_DT_NIL = -1,
MB_DT_INT = 0,
MB_DT_REAL,
MB_DT_STRING,
} mb_data_e;
typedef union mb_value_u {
int_t integer;
real_t float_point;
char* string;
} mb_value_u;
typedef struct mb_value_t {
mb_data_e type;
mb_value_u value;
} mb_value_t;
typedef void (* mb_error_handler_t)(struct mb_interpreter_t*, enum mb_error_e, char*, int, unsigned short, unsigned short, int);
typedef int (* mb_func_t)(struct mb_interpreter_t*, void**);
typedef int (* mb_print_func_t)(const char*, ...);
typedef int (* mb_input_func_t)(char*, int);
typedef struct mb_interpreter_t {
void* local_func_dict;
void* global_func_dict;
void* global_var_dict;
void* ast;
void* parsing_context;
void* running_context;
mb_error_e last_error;
int last_error_pos;
unsigned short last_error_row;
unsigned short last_error_col;
mb_error_handler_t error_handler;
mb_print_func_t printer;
mb_input_func_t inputer;
void* userdata;
} mb_interpreter_t;
MBAPI unsigned int mb_ver(void);
MBAPI const char* mb_ver_string(void);
MBAPI int mb_init(void);
MBAPI int mb_dispose(void);
MBAPI int mb_open(mb_interpreter_t** s);
MBAPI int mb_close(mb_interpreter_t** s);
MBAPI int mb_reset(mb_interpreter_t** s, bool_t clrf);
MBAPI int mb_register_func(mb_interpreter_t* s, const char* n, mb_func_t f);
MBAPI int mb_remove_func(mb_interpreter_t* s, const char* n);
MBAPI int mb_remove_reserved_func(mb_interpreter_t* s, const char* n);
MBAPI int mb_attempt_func_begin(mb_interpreter_t* s, void** l);
MBAPI int mb_attempt_func_end(mb_interpreter_t* s, void** l);
MBAPI int mb_attempt_open_bracket(mb_interpreter_t* s, void** l);
MBAPI int mb_attempt_close_bracket(mb_interpreter_t* s, void** l);
MBAPI int mb_pop_int(mb_interpreter_t* s, void** l, int_t* val);
MBAPI int mb_pop_real(mb_interpreter_t* s, void** l, real_t* val);
MBAPI int mb_pop_string(mb_interpreter_t* s, void** l, char** val);
MBAPI int mb_pop_value(mb_interpreter_t* s, void** l, mb_value_t* val);
MBAPI int mb_push_int(mb_interpreter_t* s, void** l, int_t val);
MBAPI int mb_push_real(mb_interpreter_t* s, void** l, real_t val);
MBAPI int mb_push_string(mb_interpreter_t* s, void** l, char* val);
MBAPI int mb_push_value(mb_interpreter_t* s, void** l, mb_value_t val);
MBAPI int mb_load_string(mb_interpreter_t* s, const char* l);
MBAPI int mb_load_file(mb_interpreter_t* s, const char* f);
MBAPI int mb_run(mb_interpreter_t* s);
MBAPI int mb_suspend(mb_interpreter_t* s, void** l);
MBAPI mb_error_e mb_get_last_error(mb_interpreter_t* s);
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_set_inputer(mb_interpreter_t* s, mb_input_func_t p);
MBAPI int mb_gets(char* buf, int s);
#ifdef MB_COMPACT_MODE
# pragma pack()
#endif /* MB_COMPACT_MODE */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __MY_BASIC_H__ */

20
my_basic.sln Normal file
View File

@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "my_basic", "my_basic.vcproj", "{6BBDF068-C7EB-4422-B5AF-8666948A02DE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
debug|Win32 = debug|Win32
release|Win32 = release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6BBDF068-C7EB-4422-B5AF-8666948A02DE}.debug|Win32.ActiveCfg = debug|Win32
{6BBDF068-C7EB-4422-B5AF-8666948A02DE}.debug|Win32.Build.0 = debug|Win32
{6BBDF068-C7EB-4422-B5AF-8666948A02DE}.release|Win32.ActiveCfg = release|Win32
{6BBDF068-C7EB-4422-B5AF-8666948A02DE}.release|Win32.Build.0 = release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

310
my_basic.vcproj Normal file
View File

@ -0,0 +1,310 @@
<?xml version="1.0" encoding="gb2312"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="my_basic"
ProjectGUID="{6BBDF068-C7EB-4422-B5AF-8666948A02DE}"
RootNamespace="lispy"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="debug|Win32"
OutputDirectory="output"
IntermediateDirectory="temp/debug"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
ExceptionHandling="0"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)\$(ProjectName)_d.exe"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="release|Win32"
OutputDirectory="output"
IntermediateDirectory="temp/release"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
ExceptionHandling="0"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="core"
>
<File
RelativePath=".\core\my_basic.c"
>
</File>
<File
RelativePath=".\core\my_basic.h"
>
</File>
</Filter>
<Filter
Name="doc"
>
<File
RelativePath=".\HISTORY"
>
</File>
<File
RelativePath=".\LICENSE"
>
</File>
<File
RelativePath=".\README"
>
</File>
</Filter>
<Filter
Name="sample"
>
<File
RelativePath=".\sample\sample01.bas"
>
<FileConfiguration
Name="debug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCustomBuildTool"
/>
</FileConfiguration>
<FileConfiguration
Name="release|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCustomBuildTool"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\sample\sample02.bas"
>
<FileConfiguration
Name="debug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCustomBuildTool"
/>
</FileConfiguration>
<FileConfiguration
Name="release|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCustomBuildTool"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\sample\sample03.bas"
>
<FileConfiguration
Name="debug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCustomBuildTool"
/>
</FileConfiguration>
<FileConfiguration
Name="release|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCustomBuildTool"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\sample\sample04.bas"
>
<FileConfiguration
Name="debug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCustomBuildTool"
/>
</FileConfiguration>
<FileConfiguration
Name="release|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCustomBuildTool"
/>
</FileConfiguration>
</File>
</Filter>
<Filter
Name="res"
>
<File
RelativePath=".\resource\icon.ico"
>
</File>
<File
RelativePath=".\resource\my_basic.rc"
>
</File>
<File
RelativePath=".\resource\resource.h"
>
</File>
</Filter>
<File
RelativePath=".\shell\main.c"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -0,0 +1,254 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
03F4D7391A1D00A1009F920C /* my_basic.c in Sources */ = {isa = PBXBuildFile; fileRef = 03F4D7351A1D00A1009F920C /* my_basic.c */; };
03F4D73A1A1D00A1009F920C /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 03F4D7381A1D00A1009F920C /* main.c */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
03F4D7281A1D0081009F920C /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
03F4D72A1A1D0081009F920C /* my_basic_mac */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = my_basic_mac; sourceTree = BUILT_PRODUCTS_DIR; };
03F4D7351A1D00A1009F920C /* my_basic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = my_basic.c; sourceTree = "<group>"; };
03F4D7361A1D00A1009F920C /* my_basic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = my_basic.h; sourceTree = "<group>"; };
03F4D7381A1D00A1009F920C /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
03F4D7271A1D0081009F920C /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
03F4D7211A1D0081009F920C = {
isa = PBXGroup;
children = (
03F4D7341A1D00A1009F920C /* core */,
03F4D7371A1D00A1009F920C /* shell */,
03F4D72B1A1D0081009F920C /* Products */,
);
sourceTree = "<group>";
};
03F4D72B1A1D0081009F920C /* Products */ = {
isa = PBXGroup;
children = (
03F4D72A1A1D0081009F920C /* my_basic_mac */,
);
name = Products;
sourceTree = "<group>";
};
03F4D7341A1D00A1009F920C /* core */ = {
isa = PBXGroup;
children = (
03F4D7351A1D00A1009F920C /* my_basic.c */,
03F4D7361A1D00A1009F920C /* my_basic.h */,
);
path = core;
sourceTree = "<group>";
};
03F4D7371A1D00A1009F920C /* shell */ = {
isa = PBXGroup;
children = (
03F4D7381A1D00A1009F920C /* main.c */,
);
path = shell;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
03F4D7291A1D0081009F920C /* my_basic_mac */ = {
isa = PBXNativeTarget;
buildConfigurationList = 03F4D7311A1D0081009F920C /* Build configuration list for PBXNativeTarget "my_basic_mac" */;
buildPhases = (
03F4D7261A1D0081009F920C /* Sources */,
03F4D7271A1D0081009F920C /* Frameworks */,
03F4D7281A1D0081009F920C /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = my_basic_mac;
productName = my_basic_mac;
productReference = 03F4D72A1A1D0081009F920C /* my_basic_mac */;
productType = "com.apple.product-type.tool";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
03F4D7221A1D0081009F920C /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0610;
ORGANIZATIONNAME = "W. Renxin";
TargetAttributes = {
03F4D7291A1D0081009F920C = {
CreatedOnToolsVersion = 6.1;
};
};
};
buildConfigurationList = 03F4D7251A1D0081009F920C /* Build configuration list for PBXProject "my_basic_mac" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 03F4D7211A1D0081009F920C;
productRefGroup = 03F4D72B1A1D0081009F920C /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
03F4D7291A1D0081009F920C /* my_basic_mac */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
03F4D7261A1D0081009F920C /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
03F4D73A1A1D00A1009F920C /* main.c in Sources */,
03F4D7391A1D00A1009F920C /* my_basic.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
03F4D72F1A1D0081009F920C /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
};
name = Debug;
};
03F4D7301A1D0081009F920C /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
};
name = Release;
};
03F4D7321A1D0081009F920C /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
03F4D7331A1D0081009F920C /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
03F4D7251A1D0081009F920C /* Build configuration list for PBXProject "my_basic_mac" */ = {
isa = XCConfigurationList;
buildConfigurations = (
03F4D72F1A1D0081009F920C /* Debug */,
03F4D7301A1D0081009F920C /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
03F4D7311A1D0081009F920C /* Build configuration list for PBXNativeTarget "my_basic_mac" */ = {
isa = XCConfigurationList;
buildConfigurations = (
03F4D7321A1D0081009F920C /* Debug */,
03F4D7331A1D0081009F920C /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 03F4D7221A1D0081009F920C /* Project object */;
}

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:my_basic_mac.xcodeproj">
</FileRef>
</Workspace>

BIN
output/my_basic.exe Normal file

Binary file not shown.

BIN
output/my_basic_mac Executable file

Binary file not shown.

BIN
resource/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

BIN
resource/my_basic.aps Normal file

Binary file not shown.

113
resource/my_basic.rc Normal file
View File

@ -0,0 +1,113 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// 中文(中华人民共和国) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
#ifdef _WIN32
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
#pragma code_page(936)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_ICON_MAIN ICON "icon.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,42
PRODUCTVERSION 1,0,0,42
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "080404b0"
BEGIN
VALUE "Comments", "MY-BASIC"
VALUE "CompanyName", "W. Renxin"
VALUE "FileDescription", "MY-BASIC interpreter"
VALUE "FileVersion", "1, 0, 0, 42"
VALUE "InternalName", "my_basic"
VALUE "LegalCopyright", "Copyright (C) 2011 - 2014 W. Renxin"
VALUE "LegalTrademarks", "MY-BASIC"
VALUE "OriginalFilename", "my_basic.exe"
VALUE "ProductName", "MY-BASIC"
VALUE "ProductVersion", "1, 0, 0, 42"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x804, 1200
END
END
#endif // 中文(中华人民共和国) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

16
resource/resource.h Normal file
View File

@ -0,0 +1,16 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by my_basic.rc
//
#define IDI_ICON_MAIN 101
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

7
sample/sample01.bas Normal file
View File

@ -0,0 +1,7 @@
' This script is an example of MY-BASIC
' Copyright (c) 2011 - 2014 W. Renxin. All rights reserved.
' For more information, see https://github.com/paladin-t/my_basic/
s$ = "hello "
s$ = s$ + "world"
PRINT s$ + "!"

17
sample/sample02.bas Normal file
View File

@ -0,0 +1,17 @@
' This script is an example of MY-BASIC
' Copyright (c) 2011 - 2014 W. Renxin. All rights reserved.
' For more information, see https://github.com/paladin-t/my_basic/
e = 50
PRINT "Primes in ", e, ": ", 2, ", "
FOR n = 3 TO e
m = 2
is = 1
WHILE m < n
IF n MOD m = 0 THEN is = 0 ELSE m = m + 1
IF is = 0 THEN EXIT
WEND
IF is = 1 THEN PRINT n, ", "
NEXT n

22
sample/sample03.bas Normal file
View File

@ -0,0 +1,22 @@
' This script is an example of MY-BASIC
' Copyright (c) 2011 - 2014 W. Renxin. All rights reserved.
' For more information, see https://github.com/paladin-t/my_basic/
PRINT "Input: "
INPUT ns$
n = VAL(ns$)
x = n * 2 - 1
a = 1 - 1 / 3
w = (x - 5) / 2 + 1
v = 100 / w
FOR y = 5 TO x STEP 2
iy = (y - 1) / 4
iy = FLOOR(iy)
IF iy = (y - 1) / 4 THEN a = a + 1 / y ELSE a = a - 1 / y
u = u + v
NEXT
a = a * 4
PRINT "PI = ", a

23
sample/sample04.bas Normal file
View File

@ -0,0 +1,23 @@
' This script is an example of MY-BASIC
' Copyright (c) 2011 - 2014 W. Renxin. All rights reserved.
' For more information, see https://github.com/paladin-t/my_basic/
BEGIN:
n = 10
DIM arr(n)
GOSUB CALC
GOSUB SHOW
END
CALC:
arr(0) = 1
FOR i = 1 TO n - 1
IF i = 1 THEN arr(i) = 1 ELSE arr(i) = arr(i - 1) + arr(i - 2)
NEXT
RETURN
SHOW:
FOR i = 0 TO n - 1
PRINT arr(i), ", "
NEXT
RETURN

433
shell/main.c Normal file
View File

@ -0,0 +1,433 @@
/*
** This source file is part of MY-BASIC
**
** For the latest info, see https://github.com/paladin-t/my_basic/
**
** Copyright (c) 2011 - 2014 W. Renxin
**
** 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
** the Software without restriction, including without limitation the rights to
** use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
** the Software, and to permit persons to whom the Software is furnished to do so,
** subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in all
** copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
** FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
** COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
** IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifdef _MSC_VER
# ifndef _CRT_SECURE_NO_WARNINGS
# define _CRT_SECURE_NO_WARNINGS
# endif /* _CRT_SECURE_NO_WARNINGS */
#endif /* _MSC_VER */
#ifdef _MSC_VER
# include <crtdbg.h>
# include <conio.h>
#else /* _MSC_VER */
# include <unistd.h>
#endif /* _MSC_VER */
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../core/my_basic.h"
#ifdef _MSC_VER
# pragma warning(disable : 4127)
# pragma warning(disable : 4996)
#endif /* _MSC_VER */
#define _MAX_LINE_LENGTH 256
#define _str_eq(__str1, __str2) (_strcmpi(__str1, __str2) == 0)
#define _LINE_INC_STEP 16
#define _NO_END(s) (MB_FUNC_OK == s || MB_FUNC_SUSPEND == s || MB_FUNC_WARNING == s || MB_FUNC_ERR == s || MB_FUNC_END == s)
typedef struct _code_line_t {
char** lines;
int count;
int size;
} _code_line_t;
static mb_interpreter_t* bas = 0;
static _code_line_t* c = 0;
static _code_line_t* _create_code(void) {
_code_line_t* result = (_code_line_t*)malloc(sizeof(_code_line_t));
result->count = 0;
result->size = _LINE_INC_STEP;
result->lines = (char**)malloc(sizeof(char*) * result->size);
return result;
}
static void _destroy_code(_code_line_t* code) {
int i = 0;
mb_assert(code);
for(i = 0; i < code->count; ++i) {
free(code->lines[i]);
}
free(code->lines);
free(code);
}
static void _clear_code(_code_line_t* code) {
int i = 0;
mb_assert(code);
for(i = 0; i < code->count; ++i) {
free(code->lines[i]);
}
code->count = 0;
}
static void _append_line(_code_line_t* code, char* txt) {
mb_assert(code && txt);
if(code->count + 1 == code->size) {
code->size += _LINE_INC_STEP;
code->lines = (char**)realloc(code->lines, sizeof(char*) * code->size);
}
code->lines[code->count++] = strdup(txt);
}
static char* _get_code(_code_line_t* code) {
char* result = 0;
int i = 0;
mb_assert(code);
result = (char*)malloc((_MAX_LINE_LENGTH + 2) * code->count + 1);
result[0] = '\0';
for(i = 0; i < code->count; ++i) {
result = strcat(result, code->lines[i]);
if(i != code->count - 1) {
result = strcat(result, "\r\n");
}
}
return result;
}
static void _set_code(_code_line_t* code, char* txt) {
char* cursor = 0;
char _c = '\0';
mb_assert(code);
if(!txt) {
return;
}
_clear_code(code);
cursor = txt;
do {
_c = *cursor;
if(_c == '\r' || _c == '\n' || _c == '\0') {
cursor[0] = '\0';
if(_c == '\r' && *(cursor + 1) == '\n') {
++cursor;
}
_append_line(code, txt);
txt = cursor + 1;
}
++cursor;
} while(_c);
}
static char* _load_file(const char* path) {
FILE* fp = 0;
char* result = 0;
long curpos = 0;
long l = 0;
mb_assert(path);
fp = fopen(path, "rb");
if(fp) {
curpos = ftell(fp);
fseek(fp, 0L, SEEK_END);
l = ftell(fp);
fseek(fp, curpos, SEEK_SET);
result = (char*)malloc((size_t)(l + 1));
mb_assert(result);
fread(result, 1, l, fp);
fclose(fp);
result[l] = '\0';
}
return result;
}
static int _save_file(const char* path, const char* txt) {
FILE* fp = 0;
mb_assert(path && txt);
fp = fopen(path, "wb");
if(fp) {
fwrite(txt, sizeof(char), strlen(txt), fp);
fclose(fp);
return 1;
}
return 0;
}
static int beep(mb_interpreter_t* s, void** l) {
int result = MB_FUNC_OK;
mb_assert(s && l);
mb_check(mb_attempt_func_begin(s, l));
mb_check(mb_attempt_func_end(s, l));
putchar('\a');
return result;
}
static void _on_error(mb_interpreter_t* s, mb_error_e e, char* m, int p, unsigned short row, unsigned short col, int abort_code) {
mb_unrefvar(s);
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);
}
}
static void _on_startup(void) {
c = _create_code();
mb_init();
mb_open(&bas);
mb_set_error_handler(bas, _on_error);
mb_reg_fun(bas, beep);
}
static void _on_exit(void) {
mb_close(&bas);
mb_dispose();
_destroy_code(c);
c = 0;
#if defined _MSC_VER && !defined _WIN64
if(0 != _CrtDumpMemoryLeaks()) { _asm { int 3 } }
#endif /* _MSC_VER && !_WIN64 */
}
static void _clear_screen(void) {
#ifdef _MSC_VER
system("cls");
#else /* _MSC_VER */
system("clear");
#endif /* _MSC_VER */
}
static int _new_program(void) {
_clear_code(c);
return mb_reset(&bas, false);
}
static void _list_program(const char* sn, const char* cn) {
long lsn = 0;
long lcn = 0;
mb_assert(sn && cn);
lsn = atoi(sn);
lcn = atoi(cn);
if(lsn == 0 && lcn == 0) {
char* txt = _get_code(c);
printf("%s\n", txt);
free(txt);
} else {
long i = 0;
long e = 0;
if(lsn < 1 || lsn > c->count) {
printf("Line number %ld out of bound.\n", lsn);
return;
}
if(lcn < 0) {
printf("Invalid line count %ld.\n", lcn);
return;
}
--lsn;
e = lcn ? lsn + lcn : c->count;
for(i = lsn; i < e; ++i) {
if(i >= c->count) {
break;
}
printf("%s\n", c->lines[i]);
}
}
}
static void _edit_program(const char* no) {
char line[_MAX_LINE_LENGTH];
long lno = 0;
mb_assert(no);
lno = atoi(no);
if(lno < 1 || lno > c->count) {
printf("Line number %ld out of bound.\n", lno);
return;
}
--lno;
memset(line, 0, _MAX_LINE_LENGTH);
printf("%ld]", lno + 1);
mb_gets(line, _MAX_LINE_LENGTH);
c->lines[lno] = (char*)realloc(c->lines[lno], strlen(line) + 1);
strcpy(c->lines[lno], line);
}
static void _load_program(const char* path) {
char* txt = _load_file(path);
if(txt) {
_new_program();
_set_code(c, txt);
free(txt);
if(c->count == 1) {
printf("Load done. %d line loaded.\n", c->count);
} else {
printf("Load done. %d lines loaded.\n", c->count);
}
} else {
printf("Cannot load file \"%s\"\n", path);
}
}
static void _save_program(const char* path) {
char* txt = _get_code(c);
if(!_save_file(path, txt)) {
printf("Cannot save file \"%s\"\n", path);
} else {
if(c->count == 1) {
printf("Save done. %d line saved.\n", c->count);
} else {
printf("Save done. %d lines saved.\n", c->count);
}
}
free(txt);
}
static void _kill_program(const char* path) {
if(!unlink(path)) {
printf("Delete file \"%s\" successfully.\n", path);
} else {
printf("Delete file \"%s\" failed.\n", path);
}
}
static void _show_tip(void) {
printf("MY-BASIC Interpreter Shell - %s.\n", mb_ver_string());
printf("Copyright (c) 2011 - 2014 W. Renxin. All Rights Reserved.\n");
printf("For more information, see https://github.com/paladin-t/my_basic/.\n");
printf("Input HELP and hint enter to view help information.\n");
}
static void _show_help(void) {
printf("Commands:\n");
printf(" CLS - Clear screen\n");
printf(" NEW - Clear current program\n");
printf(" RUN - Run current program\n");
printf(" BYE - Quit interpreter\n");
printf(" LIST - List current program\n");
printf(" Usage: LIST [l [n]], l is start line number, n is line count\n");
printf(" EDIT - Edit a line in current program\n");
printf(" Usage: EDIT n, n is line number\n");
printf(" LOAD - Load a file as current program\n");
printf(" Usage: LOAD *.*\n");
printf(" SAVE - Save current program to a file\n");
printf(" Usage: SAVE *.*\n");
printf(" KILL - Delete a file\n");
printf(" Usage: KILL *.*\n");
}
static int _do_line(void) {
int result = MB_FUNC_OK;
char line[_MAX_LINE_LENGTH];
char dup[_MAX_LINE_LENGTH];
mb_assert(bas);
memset(line, 0, _MAX_LINE_LENGTH);
printf("]");
mb_gets(line, _MAX_LINE_LENGTH);
memcpy(dup, line, _MAX_LINE_LENGTH);
strtok(line, " ");
if(_str_eq(line, "")) {
/* Do nothing */
} else if(_str_eq(line, "HELP")) {
_show_help();
} else if(_str_eq(line, "CLS")) {
_clear_screen();
} else if(_str_eq(line, "NEW")) {
result = _new_program();
} else if(_str_eq(line, "RUN")) {
char* txt = _get_code(c);
result = mb_reset(&bas, false);
result = mb_load_string(bas, txt);
free(txt);
result = mb_run(bas);
printf("\n");
} else if(_str_eq(line, "BYE")) {
result = MB_FUNC_BYE;
} else if(_str_eq(line, "LIST")) {
char* sn = line + strlen(line) + 1;
char* cn = 0;
strtok(sn, " ");
cn = sn + strlen(sn) + 1;
_list_program(sn, cn);
} else if(_str_eq(line, "EDIT")) {
char* no = line + strlen(line) + 1;
_edit_program(no);
} else if(_str_eq(line, "LOAD")) {
char* path = line + strlen(line) + 1;
_load_program(path);
} else if(_str_eq(line, "SAVE")) {
char* path = line + strlen(line) + 1;
_save_program(path);
} else if(_str_eq(line, "KILL")) {
char* path = line + strlen(line) + 1;
_kill_program(path);
} else {
_append_line(c, dup);
}
return result;
}
int main(int argc, char* argv[]) {
int status = 0;
#if defined _MSC_VER && !defined _WIN64
_CrtSetBreakAlloc(0);
#endif /* _MSC_VER && !_WIN64 */
atexit(_on_exit);
_on_startup();
if(argc == 1) {
_show_tip();
do {
status = _do_line();
} while(_NO_END(status));
} else if(argc == 2) {
if(mb_load_file(bas, argv[1]) == MB_FUNC_OK) {
mb_run(bas);
}
} else {
printf("Unknown arguments\n");
_show_tip();
}
return 0;
}