{
    The GNU BASIC RunTime.
    Copyright (C) Sandul Yura Valentinovich.
    (R) Wednesday, 5 March 2003 year.
    All rights reserved.
    This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option) any
later version.
    This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
details.
    You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc., 675
Mass Ave, Cambridge, MA 02139, USA.
}
Program GNUBasic;
Uses Crt,Dos;
Const
    MaxLines          = 10240;
    MaxWhiles         = 256;
    MaxFroms          = 256;
    MaxFiles          = 256;
    MaxDefFnS         = 256;
    MaxDefFnSArgs     = 64;
    MaxVars           = 768;
    MaxGoSubS         = 256;
    MaxANSIParameters = 256;
    SizeOfExecutable  = 48840;
Type
   BASICLine = Record
    Line        : String;
    LineNumber  : Word;
   end;
   WhileLoop = Record
    StartLine   : Word;
    EndLine     : Word;
    Conditional : String;
    IsFree      : Boolean;
   end;
   FromLoop = Record
    VarName     : String;
    StartLine   : Word;
    EndLine     : Word;
    BeginValue  : LongInt;
    EndValue    : LongInt;
    IsFree      : Boolean;
   end;
   BASICFile = Record
    FileMode    : Boolean;
    IsUse       : Boolean;
    WorkFile    : Text;
   end;
   VariableData = Record
    VarName     : String;
    StringValue : String;
    NumberValue : Real;
    ValueType   : Boolean;
   end;
Var
  Lines           : Array[1..MaxLines] Of BASICLine;
  BASICLinesCount : Word;
  Whiles          : Array[1..MaxWhiles] Of WhileLoop;
  Froms           : Array[1..MaxFroms] Of FromLoop;
  Files           : Array[1..MaxFiles] Of BASICFile;
  GoSubS          : Array[1..MaxGoSubS] Of Word;
  GoSubSCount     : Word;
  Vars            : Array[1..MaxVars] Of VariableData;
  VarsCount       : Word;
  DefFnS          : Array[1..MaxDefFnS] Of String;
  DefFnSArgs      : Array[1..MaxDefFnS] Of Array[1..MaxDefFnSArgs] Of VariableData;
  DefFnSArgsCount : Array[1..MaxDefFnS] Of Byte;
  DefFnSCount     : Word;
  CurrentDefFn    : Word;
  DefFnMode       : Boolean;
  CurrentLine     : Word;
  RunMode         : Boolean;
  TraceMode       : Boolean;
  NumStr          : Boolean;
  Error           : String;
  Parameters      : Array[1..MaxANSIParameters] Of Byte;
  ParametersCount : Byte;
  CursorColumn    : Byte;
  CursorRow       : Byte;
  CursorSaved     : Boolean;
  Mode            : Byte;
  NumberLine      : String;
  Number          : Word;
Function InMeaning(Var Line : String) : String; ForWard;
Function ParseInMeaning(Var Line : String) : String; ForWard;
Procedure Help;
 Function Pause : Boolean;
 Begin
  Write('Please press the ENTER key to continue or ESC to cancel.');
  Pause:=ReadKey=Chr(13);
  WriteLn;
 end;
Begin
 WriteLn;
 WriteLn('The personal interpretter of the BASIC programming language.');
 WriteLn('GNUBasic, Copyright (C) 2003 Sandul Yura Valentinovich.');
 WriteLn('(C) Monday, 5 May 2003 year.');
 WriteLn('All rights reserved.');
 WriteLn('GNUBasic comes with ABSOLUTELY NO WARRANTY; for details, see the GNU General');
 WriteLn('Public License, version 2.');
 WriteLn('    This is free software, and you are welcome to redistribute it under certain');
 WriteLn('conditions from the GNU General Public License.');
 WriteLn('***************************************************************');
 WriteLn;
 WriteLn('Statements:');
 WriteLn('        REM [Any symbols combination.]');
 WriteLn('        Insert comment to program.');
 WriteLn('        OPEN FileName$ FOR INPUT|OUTPUT|APPEND AS #FileNumber%');
 WriteLn('        Open file for work with it.');
 WriteLn('        CLOSE #FileNumber%');
 WriteLn('        Close file.');
 WriteLn('        PRINT [#FileNumber%,]Expression');
 WriteLn('        Output to file or screen.');
 WriteLn('        CLS');
 WriteLn('        Clear the screen.');
 WriteLn('        COLOR BackGroundColor%,ForeGroundColor%');
 WriteLn('        Set screen color.');
 If Not Pause Then Exit;
 WriteLn('        LOCATE Column%,Row%');
 WriteLn('        Move screen cursor.');
 WriteLn('        SOUND Frequency%,Duration%');
 WriteLn('        Play sound (duration set in miliseconds (1/1000 of second)).');
 WriteLn('        NAME FileName$ AS NewFileName$');
 WriteLn('        Rename file.');
 WriteLn('        MKDIR DirectoryName$');
 WriteLn('        Create directory.');
 WriteLn('        CHDIR DirectoryName$');
 WriteLn('        Change current directory.');
 WriteLn('        RMDIR DirectoryName$');
 WriteLn('        Remove directory.');
 WriteLn('        KILL FileMask$');
 WriteLn('        Delete files.');
 WriteLn('        FILES FileMask$');
 WriteLn('        Out files.');
 WriteLn('        SYSTEM');
 WriteLn('        Quit from interpretter.');
 WriteLn('        WINDOW (UpperColumn%,UpperRow%)-(LowerColumn%,LowerRow%)');
 WriteLn('        Redirect scree to window.');
 WriteLn('        LIST [LineNumber%[,EndLineNumber%]]');
 WriteLn('        Output program lines.');
 WriteLn('        DELETE LineNumber%[,EndLineNumber%]');
 WriteLn('        Delete program lines.');
 If Not Pause Then Exit;
 WriteLn('        SAVE FileName$');
 WriteLn('        Save current program into file.');
 WriteLn('        LOAD FileName$');
 WriteLn('        Load program from file.');
 WriteLn('        NEW');
 WriteLn('        Clear current program and reset interpretter.');
 WriteLn('        GO TO|SUB LineNumber%');
 WriteLn('        Run GO TO or GO SUB statement.');
 WriteLn('        RETURN');
 WriteLn('        Return from GO SUB subroutine.');
 WriteLn('        TRON');
 WriteLn('        Set trace mode to on.');
 WriteLn('        TROFF');
 WriteLn('        Set trace mode to off.');
 WriteLn('        RUN');
 WriteLn('        Run current program.');
 WriteLn('        END');
 WriteLn('        End current running program.');
 WriteLn('        LET VarName=Expression');
 WriteLn('        Set value for variable.');
 WriteLn('        WHILE Conditional');
 WriteLn('        WEND');
 WriteLn('        The WHILE loop.');
 WriteLn('        FROM VarName%=StartValue% TO EndValue%');
 If Not Pause Then Exit;
 WriteLn('        NEXT VarName%');
 WriteLn('        The FROM (like FOR) loop.');
 WriteLn('        EXIT WHILE|FROM');
 WriteLn('        Exit from current WHILE or FROM loop.');
 WriteLn('        IF Conditional THEN Statement[ ELSE Statement]');
 WriteLn('        The IF conditional operator.');
 WriteLn('        DEF FNName[(Arg[,Arg...])]=Expression');
 WriteLn('        Declare the user - defined function.');
 WriteLn('        HELP');
 WriteLn('        Output this help screen.');
 WriteLn('        SCREEN BW40|CO40|BW80|CO80|MONO');
 WriteLn('        Change screen mode.');
 WriteLn('System variables:');
 WriteLn('        DATE$');
 WriteLn('        Contain current date in format: MM-DD-YYYY.');
 WriteLn('        TIME$');
 WriteLn('        Contain current time in format: HH:MM:SS.');
 WriteLn('String functions:');
 WriteLn('        INKEY$');
 WriteLn('        If pressed any alphabetic or numeric key, then return it (one symbol');
 WriteLn('        length string). If pressed special keys (like F1 - F10), then return');
 WriteLn('        two - symbols string: CHR$(0)+CHR$(CodeOfKey%). If keys is not');
 WriteLn('        pressed, then return empty string.');
 WriteLn('        INPUT$[(#FileNumber%)]');
 If Not Pause Then Exit;
 WriteLn('        Perform input from keyboard or file.');
 WriteLn('        STR$(Value%)');
 WriteLn('        Number, converted to string.');
 WriteLn('        CHR$(Code%)');
 WriteLn('        Symbol on code.');
 WriteLn('        MID$(Line$,Start%,Count%)');
 WriteLn('        Part of Line$, startted on Start% symbol, length Count% symbols.');
 WriteLn('        DAYOFWEEK(Year%,Month%,Day%)');
 WriteLn('        Return name of day.');
 WriteLn('Numeric functions:');
 WriteLn('        LEN(Line$)');
 WriteLn('        Return length of line.');
 WriteLn('        INSTR(Line$,SubLine$)');
 WriteLn('        Return number of first occurence of SubLine$ in Line$.');
 WriteLn('        ASC(Line$)');
 WriteLn('        Return code of first symbol in line.');
 WriteLn('        CRC32(Line$)');
 WriteLn('        Return CRC-32 code of line.');
 WriteLn('        VAL(Value$)');
 WriteLn('        Convert string number to number.');
 WriteLn('        SQR(Value#)');
 WriteLn('        Return the square root of value.');
 WriteLn('        ABS(Value#)');
 WriteLn('        Return absolute value of Value#.');
 If Not Pause Then Exit;
 WriteLn('        INT(Value#)');
 WriteLn('        Return integer part of Value#.');
 WriteLn('        SIN(Value#)');
 WriteLn('        Return sine of Value#.');
 WriteLn('        COS(Value#)');
 WriteLn('        Return co - sine of Value#.');
 WriteLn('        EOF(#FileNumber%)');
 WriteLn('        If EOF, then return 1 (true), else return 0 (false).');
 WriteLn('Constans:');
 WriteLn('        PI=3.1415926535897932385,BLACK=0,BLUE=1,GREEN=2,CYAN=3,RED=4,MAGENTA=5');
 WriteLn('        BROWN=6,LIGHTGRAY=7,DARKGRAY=8,LIGHTBLUE=9,LIGHTGREEN=10,LIGHTCYAN=11');
 WriteLn('        LIGHTRED=12,LIGHTMAGENTA=13,YELLOW=14,WHITE=15,FALSE=0,TRUE=1');
 WriteLn('Operators:');
 WriteLn('        Value[!|@|#|$|%|&]      +       Value[!|@|#|$|%|&]');
 WriteLn('        Value[!|@|#|%|&]        -       Value[!|@|#|%|&]');
 WriteLn('        Value[!|@|#|%|&]        /       Value[!|@|#|%|&]');
 WriteLn('        Value[!|@|#|%|&]        \       Value[!|@|#|%|&]');
 WriteLn('        Value[!|@|#|%|&]        *       Value[!|@|#|%|&]');
 WriteLn('        Value[!|@|#|$|%|&]      =       Value[!|@|#|$|%|&]');
 WriteLn('        Value[!|@|#|$|%|&]      <       Value[!|@|#|$|%|&]');
 WriteLn('        Value[!|@|#|$|%|&]      >       Value[!|@|#|$|%|&]');
 WriteLn('        Value[!|@|#|$|%|&]      <=      Value[!|@|#|$|%|&]');
 WriteLn('        Value[!|@|#|$|%|&]      =<      Value[!|@|#|$|%|&]');
 WriteLn('        Value[!|@|#|$|%|&]      =>      Value[!|@|#|$|%|&]');
 If Not Pause Then Exit;
 WriteLn('        Value[!|@|#|$|%|&]      >=      Value[!|@|#|$|%|&]');
 WriteLn('        Value[!|@|#|$|%|&]      <>      Value[!|@|#|$|%|&]');
 WriteLn('        Value[!|@|#|$|%|&]      ><      Value[!|@|#|$|%|&]');
 WriteLn('        Value[!|@|#|%|&]        AND     Value[!|@|#|%|&]');
 WriteLn('        Value[!|@|#|%|&]        OR      Value[!|@|#|%|&]');
 WriteLn('        Value[!|@|#|%|&]        XOR     Value[!|@|#|%|&]');
 WriteLn('        Value[!|@|#|%|&]        MOD     Value[!|@|#|%|&]');
 WriteLn('                                NOT     Value[!|@|#|%|&]');
end;
Function IsLeapYear(Year : Word) : Boolean;
Begin
 IsLeapYear:=((Year Div 4)*4)=Year;
end;
Function MonthDay(Year : Word; Month : Byte) : Byte;
Begin
 Case Month Of
  1:  MonthDay:=31;
  2:  MonthDay:=28+Ord(IsLeapYear(Year));
  3:  MonthDay:=31;
  4:  MonthDay:=30;
  5:  MonthDay:=31;
  6:  MonthDay:=30;
  7:  MonthDay:=31;
  8:  MonthDay:=31;
  9:  MonthDay:=30;
  10: MonthDay:=31;
  11: MonthDay:=30;
  12: MonthDay:=31;
 end;
end;
Function MonthDays(Year : Word; Month : Byte) : Word;
Begin
 Case Month Of
  1:  MonthDays:=0;
  2:  MonthDays:=31;
  3:  MonthDays:=59+Ord(IsLeapYear(Year));
  4:  MonthDays:=90+Ord(IsLeapYear(Year));
  5:  MonthDays:=120+Ord(IsLeapYear(Year));
  6:  MonthDays:=151+Ord(IsLeapYear(Year));
  7:  MonthDays:=181+Ord(IsLeapYear(Year));
  8:  MonthDays:=212+Ord(IsLeapYear(Year));
  9:  MonthDays:=243+Ord(IsLeapYear(Year));
  10: MonthDays:=273+Ord(IsLeapYear(Year));
  11: MonthDays:=304+Ord(IsLeapYear(Year));
  12: MonthDays:=334+Ord(IsLeapYear(Year));
 end;
end;
Function DaysCount(Year : Word; Month,Day : Byte) : LongInt;
Begin
 DaysCount:=(LongInt(Year)*365)+(Year Div 4)+(Year Div 100)+MonthDays(Year,Month)+Day;
end;
Function DayOfWeek(Year : Word; Month,Day : Byte) : Byte;
Begin
 Case DaysCount(Year,Month,Day)-((DaysCount(Year,Month,Day) Div 7)*7) Of
  0: DayOfWeek:=6;
  1: DayOfWeek:=7;
  2: DayOfWeek:=1;
  3: DayOfWeek:=2;
  4: DayOfWeek:=3;
  5: DayOfWeek:=4;
  6: DayOfWeek:=5;
 end;
end;
Function CRC32(Line : String) : LongInt;
Var
  Crc32Table : Array[0..255] Of LongInt;
  CrcValue   : LongInt;
  Count      : Byte;
  Index      : Byte;
Begin
 For Index:=0 To 255 Do
 Begin
  CRCValue:=Index;
  For Count:=1 To 8 Do If Odd(CRCValue) Then CRCValue:=(CRCValue Div 2) XOr LongInt($EDB88320) Else CRCValue:=CRCValue Div 2;
  Crc32Table[Index]:=CRCValue;
 end;
 CRCValue:=LongInt($FFFFFFFF);
 For Index:=1 To Length(Line) Do CRCValue:=Crc32Table[Byte(CRCValue) XOr Ord(Line[Index])] XOr (CRCValue Div $100);
 CRC32:=CRCValue;
end;
Procedure SortLines;
Var
  Index      : Word;
  LineIndex  : Word;
  LineNumber : Word;
  LineData   : String;
Begin
 For Index:=1 To BASICLinesCount Do For LineIndex:=Index To BASICLinesCount Do If Lines[Index].LineNumber>Lines[LineIndex].LineNumber Then
 Begin
  LineData:=Lines[Index].Line;
  LineNumber:=Lines[Index].LineNumber;
  Lines[Index].Line:=Lines[LineIndex].Line;
  Lines[Index].LineNumber:=Lines[LineIndex].LineNumber;
  Lines[LineIndex].LineNumber:=LineNumber;
  Lines[LineIndex].Line:=LineData;
 end;
end;
Procedure WriteANSILine(Line : String);
 Procedure WriteSymbol(Symbol : Char);
 Var
   Index        : Byte;
   ErrorInteger : Integer;
  Procedure ClearParameters;
  Var
    ParameterIndex : Byte;
  Begin
   For ParameterIndex:=1 To MaxANSIParameters Do Parameters[ParameterIndex]:=0;
   ParametersCount:=0;
   NumberLine:=''
  end;
 Begin
  Case Mode Of
  0: Case Symbol Of
     #27: Mode:=1;
     Else Write(Symbol);
     end;
  1: Case Symbol Of
     '[': Mode:=2;
     Else
      Begin
       Mode:=0;
       WriteSymbol(Symbol);
      end;
     end;
  2: Case Symbol Of
     '0'..'9':
     Begin
      Mode:=3;
      ClearParameters;
      ParametersCount:=1;
      NumberLine:='';
      Number:=0;
      WriteSymbol(Symbol);
     end;
     's':
     Begin
      CursorColumn:=WhereX;
      CursorRow:=WhereY;
      CursorSaved:=True;
      ClearParameters;
      Mode:=0;
     end;
     'u':
     Begin
      If CursorSaved Then
      Begin
       GoToXY(CursorColumn,CursorRow);
       CursorColumn:=0;
       CursorRow:=0;
       CursorSaved:=False;
      end;
      ClearParameters;
      Mode:=0;
     end;
     'H','f':
     Begin
      For Index:=1 To 2 Do If Parameters[Index]=0 Then Parameters[Index]:=1;
      GoToXY(Parameters[2],Parameters[1]);
      ClearParameters;
      Mode:=0;
     end;
     'J':
     Begin
      ClrScr;
      ClearParameters;
      Mode:=0;
     end;
     'A':
     Begin
      If Parameters[1]=0 Then Parameters[1]:=1;
      GoToXY(WhereX,WhereY-Parameters[1]);
      ClearParameters;
      Mode:=0;
     end;
     'B':
     Begin
      If Parameters[1]=0 Then Parameters[1]:=1;
      GoToXY(WhereX,WhereY+Parameters[1]);
      ClearParameters;
      Mode:=0;
     end;
     'C':
     Begin
      If Parameters[1]=0 Then Parameters[1]:=1;
      GoToXY(WhereX+Parameters[1],WhereY);
      ClearParameters;
      Mode:=0;
     end;
     'D':
     Begin
      If Parameters[1]=0 Then Parameters[1]:=1;
      GoToXY(WhereX-Parameters[1],WhereY);
      ClearParameters;
      Mode:=0;
     end;
     'K':
     Begin
      ClrEol;
      ClearParameters;
      Mode:=0;
     end;
     'm':
     Begin
      If ParametersCount=0 Then NormVideo Else For Index:=1 To ParametersCount Do Case Parameters[Index] Of
      00: NormVideo;
      01: HighVideo;
      04: TextAttr:=(TextAttr And $F8) Or Blue;
      05: TextAttr:=TextAttr Or $80;
      07:
      Begin
       Number:=(TextAttr And $77);
       TextAttr:=(TextAttr And $88) Or ((Number Div $10) And $07);
       TextAttr:=TextAttr Or ((Number*$10) And $70);
       Number:=0;
      end;
      08: TextAttr:=TextAttr And $88;
      30: TextColor(Black);
      31: TextColor(Red);
      32: TextColor(Green);
      33: TextColor(Brown);
      34: TextColor(Blue);
      35: TextColor(Magenta);
      36: TextColor(Cyan);
      37: TextColor(LightGray);
      40: TextBackGround(Black);
      41: TextBackGround(Red);
      42: TextBackGround(Green);
      43: TextBackGround(Brown);
      44: TextBackGround(Blue);
      45: TextBackGround(Magenta);
      46: TextBackGround(Cyan);
      47: TextBackGround(LightGray);
      end;
      ClearParameters;
      Mode:=0;
     end;
     Else
      Begin
       Mode:=0;
       WriteSymbol(Symbol);
      end;
     end;
  3: Case Symbol Of
     '0'..'9': NumberLine:=NumberLine+Symbol;
     ';':
     Begin
      If NumberLine<>'' Then
      Begin
       If Length(NumberLine)>2 Then NumberLine:=Copy(NumberLine,1,2);
       Val(NumberLine,Number,ErrorInteger);
       NumberLine:='';
       If Number>255 Then Number:=255;
       If ParametersCount<MaxANSIParameters Then
       Begin
        Parameters[ParametersCount]:=Number;
        Inc(ParametersCount);
       end;
      end Else
      Begin
       Mode:=2;
       WriteSymbol(Symbol);
      end;
     end;
     Else
      Begin
       If NumberLine<>'' Then
        Begin
         If Length(NumberLine)>2 Then NumberLine:=Copy(NumberLine,1,2);
         Val(NumberLine,Number,ErrorInteger);
         NumberLine:='';
         If Number>255 Then Number:=255;
         If ParametersCount<MaxANSIParameters Then Parameters[ParametersCount]:=Number;
        end;
       Mode:=2;
       WriteSymbol(Symbol);
      end;
     end;
  end;
 end;
Var
  LineIndex : Byte;
Begin
 For LineIndex:=1 To Length(Line) Do WriteSymbol(Line[LineIndex]);
 WriteSymbol(Chr(13));
 WriteSymbol(Chr(10));
end;
Function Trim(LineToTrim : String) : String;
Begin
 While LineToTrim<>'' Do If Ord(LineToTrim[1])<33 Then Delete(LineToTrim,1,1) Else Break;
 While LineToTrim<>'' Do If Ord(LineToTrim[Length(LineToTrim)])<33 Then Delete(LineToTrim,Length(LineToTrim),1) Else Break;
 Trim:=LineToTrim;
end;
Function InName(Var Line : String) : String;
Var
  OutName : String;
Begin
 Line:=Trim(Line);
 OutName:='';
 While Line<>'' Do
 Case UpCase(Line[1]) Of
 'A'..'Z':
  Begin
   OutName:=OutName+UpCase(Line[1]);
   Delete(Line,1,1);
  end;
 '0'..'9':
  Begin
   OutName:=OutName+Copy(Line,1,1);
   Delete(Line,1,1);
  end;
 Else Break;
 end;
 If OutName='' Then Error:='Syntax error' Else InName:=OutName;
end;
Function InNumber(Var Line : String) : Real;
Var
  OutNumber    : String;
  PointPresent : Boolean;
  Value        : Real;
  ErrorInteger : Integer;
Begin
 Line:=Trim(Line);
 OutNumber:='';
 PointPresent:=False;
 While Line<>'' Do
 Case Line[1] Of
 '0'..'9':
  Begin
   OutNumber:=OutNumber+Copy(Line,1,1);
   Delete(Line,1,1);
  end;
 '.':
  Begin
   Delete(Line,1,1);
   If (Line='') Or (OutNumber='') Or (Not ((Ord(Line[1])>(Ord('0')-1)) And (Ord(Line[1])<(Ord('9')+1)))) Or PointPresent Then
   Begin
    Error:='Invalid number';
    Exit;
   end;
   PointPresent:=True;
   OutNumber:=OutNumber+'.';
  end;
 Else Break;
 end;
 If OutNumber='' Then Error:='Syntax error' Else
 Begin
  Val(OutNumber,Value,ErrorInteger);
  If ErrorInteger<>0 Then Error:='Invalid number' Else InNumber:=Value;
 end;
end;
Function NumberToString(Value : Real) : String;
Var
  OutValue : String;
Begin
 If Value=Trunc(Value) Then Str(Trunc(Value),OutValue) Else Str(Value:255:15,OutValue);
 OutValue:=Trim(OutValue);
 If Pos('.',OutValue)>0 Then While OutValue<>'' Do If Copy(OutValue,Length(OutValue),1)='0' Then Delete(OutValue,Length(OutValue),1) Else Break;
 NumberToString:=OutValue;
end;
Function StringToNumber(Value : String) : Real;
Var
  OutValue     : Real;
  ErrorInteger : Integer;
Begin
 Val(Value,OutValue,ErrorInteger);
 If ErrorInteger<>0 Then Error:='Invalid number' Else StringToNumber:=OutValue;
end;
Function Calculate(Var Line : String) : String;
Var
  Result     : String;
  Value      : String;
  TempNumStr : Boolean;
  Action     : String;
  TempLine   : String;
Begin
 Result:=InMeaning(Line);
 If Error<>'' Then Exit;
 Line:=Trim(Line);
 While Line<>'' Do
 Case UpCase(Line[1]) Of
 '+':
  Begin
   Delete(Line,1,1);
   TempNumStr:=NumStr;
   Value:=InMeaning(Line);
   If Error<>'' Then Exit;
   If TempNumStr<>NumStr Then
   Begin
    Error:='Type mismatch';
    Exit;
   end;
   If NumStr Then Result:=Result+Value Else Result:=NumberToString(StringToNumber(Result)+StringToNumber(Value));
   If Error<>'' Then Exit;
  end;
 '-':
  Begin
   Delete(Line,1,1);
   If NumStr Then
   Begin
    Error:='Type mismatch';
    Exit;
   end;
   Value:=InMeaning(Line);
   If Error<>'' Then Exit;
   If NumStr Then
   Begin
    Error:='Type mismatch';
    Exit;
   end;
   Result:=NumberToString(StringToNumber(Result)-StringToNumber(Value));
   If Error<>'' Then Exit;
  end;
 '/','\':
  Begin
   Delete(Line,1,1);
   If NumStr Then
   Begin
    Error:='Type mismatch';
    Exit;
   end;
   Value:=InMeaning(Line);
   If Error<>'' Then Exit;
   If NumStr Then
   Begin
    Error:='Type mismatch';
    Exit;
   end;
   If StringToNumber(Value)=0.0 Then
   Begin
    Error:='Divide by zero';
    Exit;
   end;
   Result:=NumberToString(StringToNumber(Result)/StringToNumber(Value));
   If Error<>'' Then Exit;
  end;
 '*':
  Begin
   Delete(Line,1,1);
   If NumStr Then
   Begin
    Error:='Type mismatch';
    Exit;
   end;
   Value:=InMeaning(Line);
   If Error<>'' Then Exit;
   If NumStr Then
   Begin
    Error:='Type mismatch';
    Exit;
   end;
   Result:=NumberToString(StringToNumber(Result)*StringToNumber(Value));
   If Error<>'' Then Exit;
  end;
 '=':
  Begin
   Delete(Line,1,1);
   Line:=Trim(Line);
   If Line='' Then
   Begin
    Error:='Syntax error';
    Exit;
   end;
   Case Line[1] Of
   '<':
    Begin
     Delete(Line,1,1);
     TempNumStr:=NumStr;
     Value:=InMeaning(Line);
     If Error<>'' Then Exit;
     If NumStr<>TempNumStr Then
     Begin
      Error:='Type mismacth';
      Exit;
     end;
     If NumStr Then
     Begin
      If Result<=Value Then Result:='-1' Else Result:='0';
     end Else
     Begin
      If StringToNumber(Result)<=StringToNumber(Value) Then Result:='-1' Else Result:='0';
     end;
    end;
   '>':
    Begin
     Delete(Line,1,1);
     TempNumStr:=NumStr;
     Value:=InMeaning(Line);
     If Error<>'' Then Exit;
     If NumStr<>TempNumStr Then
     Begin
      Error:='Type mismacth';
      Exit;
     end;
     If NumStr Then
     Begin
      If Result>=Value Then Result:='-1' Else Result:='0';
     end Else
     Begin
      If StringToNumber(Result)>=StringToNumber(Value) Then Result:='-1' Else Result:='0';
     end;
    end;
   Else
    Begin
     TempNumStr:=NumStr;
     Value:=InMeaning(Line);
     If Error<>'' Then Exit;
     If NumStr<>TempNumStr Then
     Begin
      Error:='Type mismacth';
      Exit;
     end;
     If NumStr Then
     Begin
      If Result=Value Then Result:='-1' Else Result:='0';
     end Else
     Begin
      If StringToNumber(Result)=StringToNumber(Value) Then Result:='-1' Else Result:='0';
     end;
    end;
   end;
   NumStr:=False;
  end;
 '<':
  Begin
   Delete(Line,1,1);
   Line:=Trim(Line);
   If Line='' Then
   Begin
    Error:='Syntax error';
    Exit;
   end;
   Case Line[1] Of
   '>':
    Begin
     Delete(Line,1,1);
     TempNumStr:=NumStr;
     Value:=InMeaning(Line);
     If Error<>'' Then Exit;
     If NumStr<>TempNumStr Then
     Begin
      Error:='Type mismacth';
      Exit;
     end;
     If NumStr Then
     Begin
      If Result<>Value Then Result:='-1' Else Result:='0';
     end Else
     Begin
      If StringToNumber(Result)<>StringToNumber(Value) Then Result:='-1' Else Result:='0';
     end;
    end;
   '=':
    Begin
     Delete(Line,1,1);
     TempNumStr:=NumStr;
     Value:=InMeaning(Line);
     If Error<>'' Then Exit;
     If NumStr<>TempNumStr Then
     Begin
      Error:='Type mismacth';
      Exit;
     end;
     If NumStr Then
     Begin
      If Result<=Value Then Result:='-1' Else Result:='0';
     end Else
     Begin
      If StringToNumber(Result)<=StringToNumber(Value) Then Result:='-1' Else Result:='0';
     end;
    end;
   Else
    Begin
     TempNumStr:=NumStr;
     Value:=InMeaning(Line);
     If Error<>'' Then Exit;
     If NumStr<>TempNumStr Then
     Begin
      Error:='Type mismacth';
      Exit;
     end;
     If NumStr Then
     Begin
      If Result<Value Then Result:='-1' Else Result:='0';
     end Else
     Begin
      If StringToNumber(Result)<StringToNumber(Value) Then Result:='-1' Else Result:='0';
     end;
    end;
   end;
   NumStr:=False;
  end;
 '>':
  Begin
   Delete(Line,1,1);
   Line:=Trim(Line);
   If Line='' Then
   Begin
    Error:='Syntax error';
    Exit;
   end;
   Case Line[1] Of
   '<':
    Begin
     Delete(Line,1,1);
     TempNumStr:=NumStr;
     Value:=InMeaning(Line);
     If Error<>'' Then Exit;
     If NumStr<>TempNumStr Then
     Begin
      Error:='Type mismacth';
      Exit;
     end;
     If NumStr Then
     Begin
      If Result<>Value Then Result:='-1' Else Result:='0';
     end Else
     Begin
      If StringToNumber(Result)<>StringToNumber(Value) Then Result:='-1' Else Result:='0';
     end;
    end;
   '=':
    Begin
     Delete(Line,1,1);
     TempNumStr:=NumStr;
     Value:=InMeaning(Line);
     If Error<>'' Then Exit;
     If NumStr<>TempNumStr Then
     Begin
      Error:='Type mismacth';
      Exit;
     end;
     If NumStr Then
     Begin
      If Result>=Value Then Result:='-1' Else Result:='0';
     end Else
     Begin
      If StringToNumber(Result)>=StringToNumber(Value) Then Result:='-1' Else Result:='0';
     end;
    end;
   Else
    Begin
     TempNumStr:=NumStr;
     Value:=InMeaning(Line);
     If Error<>'' Then Exit;
     If NumStr<>TempNumStr Then
     Begin
      Error:='Type mismacth';
      Exit;
     end;
     If NumStr Then
     Begin
      If Result>Value Then Result:='-1' Else Result:='0';
     end Else
     Begin
      If StringToNumber(Result)>StringToNumber(Value) Then Result:='-1' Else Result:='0';
     end;
    end;
   end;
   NumStr:=False;
  end;
 'A'..'Z':
  Begin
   TempLine:=Line;
   Action:=InName(Line);
   If Error<>'' Then Exit;
   If Action='AND' Then
   Begin
    If NumStr Then
    Begin
     Error:='Type mismatch';
     Exit;
    end;
    Value:=InMeaning(Line);
    If Error<>'' Then Exit;
    If NumStr Then
    Begin
     Error:='Type mismatch';
     Exit;
    end;
    Result:=NumberToString(Trunc(StringToNumber(Result)) And Trunc(StringToNumber(Value)));
   end Else If Action='OR' Then
   Begin
    If NumStr Then
    Begin
     Error:='Type mismatch';
     Exit;
    end;
    Value:=InMeaning(Line);
    If Error<>'' Then Exit;
    If NumStr Then
    Begin
     Error:='Type mismatch';
     Exit;
    end;
    Result:=NumberToString(Trunc(StringToNumber(Result)) Or Trunc(StringToNumber(Value)));
   end Else If Action='XOR' Then
   Begin
    If NumStr Then
    Begin
     Error:='Type mismatch';
     Exit;
    end;
    Value:=InMeaning(Line);
    If Error<>'' Then Exit;
    If NumStr Then
    Begin
     Error:='Type mismatch';
     Exit;
    end;
    Result:=NumberToString(Trunc(StringToNumber(Result)) XOr Trunc(StringToNumber(Value)));
   end Else If Action='MOD' Then
   Begin
    If NumStr Then
    Begin
     Error:='Type mismatch';
     Exit;
    end;
    Value:=InMeaning(Line);
    If Error<>'' Then Exit;
    If NumStr Then
    Begin
     Error:='Type mismatch';
     Exit;
    end;
    Result:=NumberToString(Trunc(StringToNumber(Result)) Mod Trunc(StringToNumber(Value)));
   end Else
   Begin
    Line:=TempLine;
    Break;
   end;
  end;
 Else Break;
 end;
 Calculate:=Result;
end;
Function InDefFn(FnName : String; FnType : Boolean; Var Line : String) : String;
Var
  OldDefFnMode : Boolean;
  DefFnName    : String;
  DefFnType    : Boolean;
  ArgName      : String;
  ArgType      : Boolean;
  WorkLine     : String;
  Index        : Word;
  Result       : String;
Begin
 If DefFnSCount=0 Then
 Begin
  Error:='User - defined functions is not declare';
  Exit;
 end;
 For Index:=1 To DefFnSCount+1 Do
 Begin
  If Index=DefFnSCount+1 Then
  Begin
   Error:='User - defined function is not declare';
   Exit;
  end;
  WorkLine:=DefFnS[Index];
  DefFnName:=InName(WorkLine);
  If Error<>'' Then Exit;
  WorkLine:=Trim(WorkLine);
  If WorkLine='' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  DefFnType:=False;
  Case WorkLine[1] Of
  '$':
   Begin
    Delete(WorkLine,1,1);
    DefFnType:=True;
   end;
  '!': Delete(WorkLine,1,1);
  '@': Delete(WorkLine,1,1);
  '#': Delete(WorkLine,1,1);
  '%': Delete(WorkLine,1,1);
  '&': Delete(WorkLine,1,1);
  end;
  If (DefFnName=FnName) And (DefFnType=FnType) Then Break;
 end;
 WorkLine:=Trim(WorkLine);
 If CurrentDefFn=MaxDefFnS Then
 Begin
  Error:='Too many calculated user - defined functions';
  Exit;
 end;
 Inc(CurrentDefFn);
 For Index:=1 To MaxDefFnSArgs Do
 Begin
  DefFnSArgs[CurrentDefFn,Index].VarName:='';
  DefFnSArgs[CurrentDefFn,Index].StringValue:='';
  DefFnSArgs[CurrentDefFn,Index].NumberValue:=0.0;
  DefFnSArgs[CurrentDefFn,Index].ValueType:=False;
 end;
 DefFnSArgsCount[CurrentDefFn]:=0;
 If Copy(WorkLine,1,1)='(' Then
 Begin
  Delete(WorkLine,1,1);
  WorkLine:=Trim(WorkLine);
  If WorkLine='' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  DefFnSArgsCount[CurrentDefFn]:=1;
  While WorkLine<>'' Do
  Begin
   ArgName:=InName(WorkLine);
   If Error<>'' Then Exit;
   WorkLine:=Trim(WorkLine);
   If WorkLine='' Then
   Begin
    Error:='Syntax error';
    Exit;
   end;
   ArgType:=False;
   Case WorkLine[1] Of
   '$':
    Begin
     Delete(WorkLine,1,1);
     ArgType:=True;
    end;
   '!': Delete(WorkLine,1,1);
   '@': Delete(WorkLine,1,1);
   '#': Delete(WorkLine,1,1);
   '%': Delete(WorkLine,1,1);
   '&': Delete(WorkLine,1,1);
   end;
   DefFnSArgs[CurrentDefFn,DefFnSArgsCount[CurrentDefFn]].VarName:=ArgName;
   DefFnSArgs[CurrentDefFn,DefFnSArgsCount[CurrentDefFn]].ValueType:=ArgType;
   WorkLine:=Trim(WorkLine);
   If WorkLine='' Then
   Begin
    Error:='Syntax error';
    Exit;
   end;
   Case WorkLine[1] Of
   ',':
    Begin
     Delete(WorkLine,1,1);
     If DefFnSArgsCount[CurrentDefFn]=MaxDefFnSArgs Then
     Begin
      Error:='Too many arguments for user - defined function';
      Exit;
     end;
     Inc(DefFnSArgsCount[CurrentDefFn]);
    end;
   ')':
    Begin
     Delete(WorkLine,1,1);
     WorkLine:=Trim(WorkLine);
     Break;
    end;
   Else
    Begin
     Error:='Syntax error';
     Exit;
    end;
   end;
  end;
  Line:=Trim(Line);
  If Copy(Line,1,1)<>'(' Then
  Begin
   Error:='Syntax error in call user - defined function';
   Exit;
  end;
  Delete(Line,1,1);
  Line:=Trim(Line);
  Index:=1;
  If Line='' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  While Line<>'' Do
  Begin
   Result:=Calculate(Line);
   If Error<>'' Then Exit;
   If DefFnSArgs[CurrentDefFn,Index].ValueType<>NumStr Then
   Begin
    Error:='Argument type mismatch';
    Exit;
   end;
   If NumStr Then
   DefFnSArgs[CurrentDefFn,Index].StringValue:=Result
   Else
   DefFnSArgs[CurrentDefFn,Index].NumberValue:=StringToNumber(Result);
   Line:=Trim(Line);
   If Line='' Then
   Begin
    Error:='Syntax error';
    Exit;
   end;
   Case Line[1] Of
   ',':
    Begin
     Delete(Line,1,1);
     If Index=DefFnSArgsCount[CurrentDefFn] Then
     Begin
      Error:='Argument - count mismatch';
      Exit;
     end;
     Inc(Index);
    end;
   ')':
    Begin
     Delete(Line,1,1);
     If Index<>DefFnSArgsCount[CurrentDefFn] Then
     Begin
      Error:='Argument - count mismatch';
      Exit;
     end;
     Break;
    end;
   end;
  end;
 end;
 If Copy(WorkLine,1,1)<>'=' Then
 Begin
  Error:='Syntax error';
  Exit;
 end;
 Delete(WorkLine,1,1);
 OldDefFnMode:=DefFnMode;
 DefFnMode:=True;
 Result:=Calculate(WorkLine);
 If Error<>'' Then Exit;
 If NumStr<>FnType Then
 Begin
  Error:='Type mismatch';
  Exit;
 end;
 DefFnMode:=OldDefFnMode;
 For Index:=1 To MaxDefFnSArgs Do
 Begin
  DefFnSArgs[CurrentDefFn,Index].VarName:='';
  DefFnSArgs[CurrentDefFn,Index].StringValue:='';
  DefFnSArgs[CurrentDefFn,Index].NumberValue:=0.0;
  DefFnSArgs[CurrentDefFn,Index].ValueType:=False;
 end;
 DefFnSArgsCount[CurrentDefFn]:=0;
 Dec(CurrentDefFn);
 InDefFn:=Result;
end;
Procedure SetVar(VarName : String; VarType : Boolean; VarValue : String);
Var
  Index  : Word;
  WorkDT : DateTime;
Begin
 If (VarName='DATE') And VarType Then
 Begin
  If Length(VarValue)<>10 Then
  Begin
   Error:='Invalid date';
   Exit;
  end;
  WorkDT.Year:=Trunc(StringToNumber(Copy(VarValue,7,2)));
  If Error<>'' Then Exit;
  If (WorkDT.Year<1980) Or (WorkDT.Year>2099) Then
  Begin
   Error:='Invalid year number';
   Exit;
  end;
  WorkDT.Month:=Trunc(StringToNumber(Copy(VarValue,1,2)));
  If Error<>'' Then Exit;
  If (WorkDT.Month<1) Or (WorkDT.Month>12) Then
  Begin
   Error:='Invalid month number';
   Exit;
  end;
  WorkDT.Day:=Trunc(StringToNumber(Copy(VarValue,4,2)));
  If Error<>'' Then Exit;
  If (WorkDT.Day<1) Or (WorkDT.Day>MonthDay(WorkDT.Year,WorkDT.Month)) Then
  Begin
   Error:='Invalid day number';
   Exit;
  end;
  SetDate(WorkDT.Year,WorkDT.Month,WorkDT.Day);
 end Else If (VarName='TIME') And VarType Then
 Begin
  If Length(VarValue)<>8 Then
  Begin
   Error:='Invalid date';
   Exit;
  end;
  WorkDT.Hour:=Trunc(StringToNumber(Copy(VarValue,1,2)));
  If Error<>'' Then Exit;
  If (WorkDT.Hour<0) Or (WorkDT.Hour>23) Then
  Begin
   Error:='Invalid hour value';
   Exit;
  end;
  WorkDT.Min:=Trunc(StringToNumber(Copy(VarValue,4,2)));
  If Error<>'' Then Exit;
  If (WorkDT.Min<0) Or (WorkDT.Min>59) Then
  Begin
   Error:='Invalid minute value';
   Exit;
  end;
  WorkDT.Sec:=Trunc(StringToNumber(Copy(VarValue,7,2)));
  If Error<>'' Then Exit;
  If (WorkDT.Sec<0) Or (WorkDT.Sec>59) Then
  Begin
   Error:='Invalid second value';
   Exit;
  end;
  SetTime(WorkDT.Hour,WorkDT.Min,WorkDT.Sec,0);
 end Else
 Begin
  If VarsCount=0 Then
  Begin
   Inc(VarsCount);
   If VarType Then Vars[VarsCount].StringValue:=VarValue Else Vars[VarsCount].NumberValue:=StringToNumber(VarValue);
   Vars[VarsCount].ValueType:=VarType;
   Vars[VarsCount].VarName:=VarName;
  end Else
  Begin
   For Index:=1 To MaxVars+1 Do
   Begin
    If Index=MaxVars+1 Then
    Begin
     If VarsCount=MaxVars Then
     Begin
      Error:='Too many variables';
      Exit;
     end;
     Inc(VarsCount);
     If VarType Then Vars[VarsCount].StringValue:=VarValue Else Vars[VarsCount].NumberValue:=StringToNumber(VarValue);
     Vars[VarsCount].ValueType:=VarType;
     Vars[VarsCount].VarName:=VarName;
     Exit;
    end;
    If (Vars[Index].VarName=VarName) And (Vars[Index].ValueType=VarType) Then Break;
   end;
   If VarType Then Vars[Index].StringValue:=VarValue Else Vars[Index].NumberValue:=StringToNumber(VarValue);
  end;
 end;
end;
Function InVar(VarName : String; VarType : Boolean) : String;
Var
  Index : Word;
Begin
 If DefFnMode Then
 Begin
  If DefFnSArgsCount[CurrentDefFn]=0 Then
  Begin
   DefFnMode:=False;
   InVar:=InVar(VarName,VarType);
   DefFnMode:=True;
  end Else
  Begin
   For Index:=1 To DefFnSArgsCount[CurrentDefFn]+1 Do
   Begin
    If Index=DefFnSArgsCount[CurrentDefFn]+1 Then
    Begin
     DefFnMode:=False;
     InVar:=InVar(VarName,VarType);
     DefFnMode:=True;
     Exit;
    end;
    If (DefFnSArgs[CurrentDefFn,Index].VarName=VarName) And (DefFnSArgs[CurrentDefFn,Index].ValueType=VarType) Then Break;
   end;
   If VarType Then InVar:=DefFnSArgs[CurrentDefFn,Index].StringValue Else InVar:=NumberToString(DefFnSArgs[CurrentDefFn,Index].NumberValue);
  end;
 end Else
 Begin
  If VarsCount=0 Then
  Begin
   If VarType Then
   Begin
    SetVar(VarName,True,'');
    InVar:='';
   end Else
   Begin
    SetVar(VarName,False,'0.0');
    InVar:='0.0';
   end;
  end Else
  Begin
   For Index:=1 To MaxVars+1 Do
   Begin
    If Index=MaxVars+1 Then
    Begin
     If VarType Then
     Begin
      SetVar(VarName,True,'');
      InVar:='';
     end Else
     Begin
      SetVar(VarName,False,'0.0');
      InVar:='0.0';
     end;
     Exit;
    end;
    If (Vars[Index].VarName=VarName) And (Vars[Index].ValueType=VarType) Then Break;
   end;
   If VarType Then InVar:=Vars[Index].StringValue Else InVar:=NumberToString(Vars[Index].NumberValue);
  end;
 end;
end;
Function InMeaning(Var Line : String) : String;
Var
  Result : String;
  Value  : String;
  Name   : String;
  WorkDT : DateTime;
Begin
 Line:=Trim(Line);
 If Line='' Then
 Begin
  Error:='Syntax error';
  Exit;
 end;
 Case UpCase(Line[1]) Of
 '0'..'9':
  Begin
   InMeaning:=NumberToString(InNumber(Line));
   NumStr:=False;
  end;
 '-':
  Begin
   Delete(Line,1,1);
   Result:=Calculate(Line);
   If Error<>'' Then Exit;
   If NumStr Then
   Begin
    Error:='Type mismatch';
    Exit;
   end;
   InMeaning:=NumberToString(0.0-StringToNumber(Result));
  end;
 '+':
  Begin
   Delete(Line,1,1);
   Result:=Calculate(Line);
   If Error<>'' Then Exit;
   If NumStr Then
   Begin
    Error:='Type mismatch';
    Exit;
   end;
   InMeaning:=NumberToString(0.0+StringToNumber(Result));
  end;
 'A'..'Z':
  Begin
   Name:=InName(Line);
   If Error<>'' Then Exit;
   Line:=Trim(Line);
   NumStr:=False;
   If Line<>'' Then
   Case Line[1] Of
   '$':
    Begin
     Delete(Line,1,1);
     NumStr:=True;
    end;
   '!': Delete(Line,1,1);
   '@': Delete(Line,1,1);
   '#': Delete(Line,1,1);
   '%': Delete(Line,1,1);
   '&': Delete(Line,1,1);
   end;
   Line:=Trim(Line);
   If Name='NOT' Then
   Begin
    Result:=Calculate(Line);
    If Error<>'' Then Exit;
    If NumStr Then
    Begin
     Error:='Type mismatch';
     Exit;
    end;
    InMeaning:=NumberToString(Not Trunc(StringToNumber(Result)));
   end Else If NumStr Then
   Begin
    If Name='INKEY' Then
    Begin
     If KeyPressed Then
     Begin
      Result:=ReadKey;
      If Ord(Result[1])=0 Then InMeaning:=Chr(0)+ReadKey Else InMeaning:=Result;
     end Else InMeaning:='';
    end Else If Name='DATE' Then
    Begin
     GetDate(WorkDT.Year,WorkDT.Month,WorkDT.Day,WorkDT.Hour);
     Str(WorkDT.Month,Result);
     If Length(Result)<2 Then Result:='0'+Result;
     Str(WorkDT.Day,Value);
     If Length(Value)<2 Then Value:='0'+Value;
     Result:=Result+'-'+Value+'-';
     Str(WorkDT.Year,Value);
     InMeaning:=Result+Value;
    end Else If Name='TIME' Then
    Begin
     GetTime(WorkDT.Hour,WorkDT.Min,WorkDT.Sec,WorkDT.Year);
     Str(WorkDT.Hour,Result);
     If Length(Result)<2 Then Result:='0'+Result;
     Str(WorkDT.Min,Value);
     If Length(Value)<2 Then Value:='0'+Value;
     Result:=Result+':'+Value+':';
     Str(WorkDT.Sec,Value);
     If Length(Value)<2 Then Value:='0'+Value;
     InMeaning:=Result+Value;
    end Else If Name='INPUT' Then
    Begin
     If Copy(Line,1,1)='(' Then
     Begin
      Delete(Line,1,1);
      Line:=Trim(Line);
      If Copy(Line,1,1)<>'#' Then
      Begin
       Error:='Syntax error';
       Exit;
      end;
      Delete(Line,1,1);
      Result:=Calculate(Line);
      If Error<>'' Then Exit;
      If NumStr Then
      Begin
       Error:='Type mismatch';
       Exit;
      end;
      Line:=Trim(Line);
      If Copy(Line,1,1)<>')' Then
      Begin
       Error:='Syntax error';
       Exit;
      end;
      Delete(Line,1,1);
      If (Trunc(StringToNumber(Result))<1) Or (Trunc(StringToNumber(Result))>MaxFiles) Then
      Begin
       Error:='Invalid file number';
       Exit;
      end;
      If Not Files[Trunc(StringToNumber(Result))].IsUse Then
      Begin
       Error:='Invalid file number';
       Exit;
      end;
      If Not Files[Trunc(StringToNumber(Result))].FileMode Then
      Begin
       Error:='Bad file mode';
       Exit;
      end;
      ReadLn(Files[Trunc(StringToNumber(Result))].WorkFile,Result);
      If IOResult<>0 Then
      Begin
       Error:='Cannot read from file';
       Exit;
      end;
      NumStr:=True;
      InMeaning:=Result;
     end Else
     Begin
      ReadLn(Result);
      InMeaning:=Result;
     end;
    end Else If Name='STR' Then
    Begin
     If Copy(Line,1,1)<>'(' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     Result:=Calculate(Line);
     If Error<>'' Then Exit;
     If NumStr Then
     Begin
      Error:='Type mismatch';
      Exit;
     end;
     Line:=Trim(Line);
     If Copy(Line,1,1)<>')' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     NumStr:=True;
     InMeaning:=NumberToString(StringToNumber(Result));
    end Else If Name='CHR' Then
    Begin
     If Copy(Line,1,1)<>'(' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     Result:=Calculate(Line);
     If Error<>'' Then Exit;
     If NumStr Then
     Begin
      Error:='Type mismatch';
      Exit;
     end;
     Line:=Trim(Line);
     If Copy(Line,1,1)<>')' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     NumStr:=True;
     InMeaning:=Chr(Trunc(StringToNumber(Result)));
    end Else If Name='MID' Then
    Begin
     If Copy(Line,1,1)<>'(' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     Name:=Calculate(Line);
     If Error<>'' Then Exit;
     If Not NumStr Then
     Begin
      Error:='Type mismatch';
      Exit;
     end;
     Line:=Trim(Line);
     If Copy(Line,1,1)<>',' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     Result:=Calculate(Line);
     If Error<>'' Then Exit;
     If NumStr Then
     Begin
      Error:='Type mismatch';
      Exit;
     end;
     Line:=Trim(Line);
     If Copy(Line,1,1)<>',' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     Value:=Calculate(Line);
     If Error<>'' Then Exit;
     If NumStr Then
     Begin
      Error:='Type mismatch';
      Exit;
     end;
     Line:=Trim(Line);
     If Copy(Line,1,1)<>')' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     NumStr:=True;
     InMeaning:=Copy(Name,Trunc(StringToNumber(Result)),Trunc(StringToNumber(Value)));
    end Else If Name='DAYOFWEEK' Then
    Begin
     If Copy(Line,1,1)<>'(' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     Name:=Calculate(Line);
     If Error<>'' Then Exit;
     If NumStr Then
     Begin
      Error:='Type mismatch';
      Exit;
     end;
     Line:=Trim(Line);
     If Copy(Line,1,1)<>',' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     Result:=Calculate(Line);
     If Error<>'' Then Exit;
     If NumStr Then
     Begin
      Error:='Type mismatch';
      Exit;
     end;
     Line:=Trim(Line);
     If Copy(Line,1,1)<>',' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     Value:=Calculate(Line);
     If Error<>'' Then Exit;
     If NumStr Then
     Begin
      Error:='Type mismatch';
      Exit;
     end;
     Line:=Trim(Line);
     If Copy(Line,1,1)<>')' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     NumStr:=True;
     If (Trunc(StringToNumber(Name))<1980) Or (Trunc(StringToNumber(Name))>2099) Then
     Begin
      Error:='Invalid year';
      Exit;
     end;
     If (Trunc(StringToNumber(Result))<1) Or (Trunc(StringToNumber(Result))>12) Then
     Begin
      Error:='Invalid month';
      Exit;
     end;
     If (Trunc(StringToNumber(Value))<1) Or (Trunc(StringToNumber(Value))>MonthDay(Trunc(StringToNumber(Name)),Trunc(StringToNumber(Result)))) Then
     Begin
      Error:='Invalid day';
      Exit;
     end;
     Case DayOfWeek(Trunc(StringToNumber(Name)),Trunc(StringToNumber(Result)),Trunc(StringToNumber(Value))) Of
     1: InMeaning:='Monday';
     2: InMeaning:='Tuesday';
     3: InMeaning:='Wednesday';
     4: InMeaning:='Thursday';
     5: InMeaning:='Friday';
     6: InMeaning:='Saturday';
     7: InMeaning:='Sunday';
     end;
    end Else If Copy(Name,1,2)='FN' Then InMeaning:=InDefFn(Name,True,Line) Else InMeaning:=InVar(Name,True);
   end Else
   Begin
    If Name='PI' Then InMeaning:='3.1415926535897932385' Else
    If Name='BLACK' Then InMeaning:='0' Else
    If Name='BLUE' Then InMeaning:='1' Else
    If Name='GREEN' Then InMeaning:='2' Else
    If Name='CYAN' Then InMeaning:='3' Else
    If Name='RED' Then InMeaning:='4' Else
    If Name='MAGENTA' Then InMeaning:='5' Else
    If Name='BROWN' Then InMeaning:='6' Else
    If Name='LIGHTGRAY' Then InMeaning:='7' Else
    If Name='DARKGRAY' Then InMeaning:='8' Else
    If Name='LIGHTBLUE' Then InMeaning:='9' Else
    If Name='LIGHTGREEN' Then InMeaning:='10' Else
    If Name='LIGHTCYAN' Then InMeaning:='11' Else
    If Name='LIGHTRED' Then InMeaning:='12' Else
    If Name='LIGHTMAGENTA' Then InMeaning:='13' Else
    If Name='YELLOW' Then InMeaning:='14' Else
    If Name='WHITE' Then InMeaning:='15' Else
    If Name='FALSE' Then InMeaning:='0' Else
    If Name='TRUE' Then InMeaning:='-1' Else
    If Name='LEN' Then
    Begin
     If Copy(Line,1,1)<>'(' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     Result:=Calculate(Line);
     If Error<>'' Then Exit;
     If Not NumStr Then
     Begin
      Error:='Type mismatch';
      Exit;
     end;
     Line:=Trim(Line);
     If Copy(Line,1,1)<>')' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     NumStr:=False;
     InMeaning:=NumberToString(Length(Result));
    end Else If Name='INSTR' Then
    Begin
     If Copy(Line,1,1)<>'(' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     Result:=Calculate(Line);
     If Error<>'' Then Exit;
     If Not NumStr Then
     Begin
      Error:='Type mismatch';
      Exit;
     end;
     Line:=Trim(Line);
     If Copy(Line,1,1)<>',' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     Value:=Calculate(Line);
     If Error<>'' Then Exit;
     If Not NumStr Then
     Begin
      Error:='Type mismatch';
      Exit;
     end;
     Line:=Trim(Line);
     If Copy(Line,1,1)<>')' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     NumStr:=False;
     InMeaning:=NumberToString(Pos(Value,Result));
    end Else If Name='ASC' Then
    Begin
     If Copy(Line,1,1)<>'(' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     Result:=Calculate(Line);
     If Error<>'' Then Exit;
     If Not NumStr Then
     Begin
      Error:='Type mismatch';
      Exit;
     end;
     Line:=Trim(Line);
     If Copy(Line,1,1)<>')' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     NumStr:=False;
     If Result='' Then Error:='Illegal function call' Else InMeaning:=NumberToString(Ord(Result[1]));
    end Else If Name='CRC32' Then
    Begin
     If Copy(Line,1,1)<>'(' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     Result:=Calculate(Line);
     If Error<>'' Then Exit;
     If Not NumStr Then
     Begin
      Error:='Type mismatch';
      Exit;
     end;
     Line:=Trim(Line);
     If Copy(Line,1,1)<>')' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     NumStr:=False;
     InMeaning:=NumberToString(CRC32(Result));
    end Else If Name='VAL' Then
    Begin
     If Copy(Line,1,1)<>'(' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     Result:=Calculate(Line);
     If Error<>'' Then Exit;
     If Not NumStr Then
     Begin
      Error:='Type mismatch';
      Exit;
     end;
     Line:=Trim(Line);
     If Copy(Line,1,1)<>')' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     NumStr:=False;
     InMeaning:=NumberToString(StringToNumber(Result));
    end Else If Name='SQR' Then
    Begin
     If Copy(Line,1,1)<>'(' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     Result:=Calculate(Line);
     If Error<>'' Then Exit;
     If NumStr Then
     Begin
      Error:='Type mismatch';
      Exit;
     end;
     Line:=Trim(Line);
     If Copy(Line,1,1)<>')' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     InMeaning:=NumberToString(Sqrt(StringToNumber(Result)));
    end Else If Name='ABS' Then
    Begin
     If Copy(Line,1,1)<>'(' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     Result:=Calculate(Line);
     If Error<>'' Then Exit;
     If NumStr Then
     Begin
      Error:='Type mismatch';
      Exit;
     end;
     Line:=Trim(Line);
     If Copy(Line,1,1)<>')' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     InMeaning:=NumberToString(Abs(StringToNumber(Result)));
    end Else If Name='INT' Then
    Begin
     If Copy(Line,1,1)<>'(' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     Result:=Calculate(Line);
     If Error<>'' Then Exit;
     If NumStr Then
     Begin
      Error:='Type mismatch';
      Exit;
     end;
     Line:=Trim(Line);
     If Copy(Line,1,1)<>')' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     InMeaning:=NumberToString(Trunc(StringToNumber(Result)));
    end Else If Name='SIN' Then
    Begin
     If Copy(Line,1,1)<>'(' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     Result:=Calculate(Line);
     If Error<>'' Then Exit;
     If NumStr Then
     Begin
      Error:='Type mismatch';
      Exit;
     end;
     Line:=Trim(Line);
     If Copy(Line,1,1)<>')' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     InMeaning:=NumberToString(Sin(StringToNumber(Result)));
    end Else If Name='COS' Then
    Begin
     If Copy(Line,1,1)<>'(' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     Result:=Calculate(Line);
     If Error<>'' Then Exit;
     If NumStr Then
     Begin
      Error:='Type mismatch';
      Exit;
     end;
     Line:=Trim(Line);
     If Copy(Line,1,1)<>')' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     InMeaning:=NumberToString(Cos(StringToNumber(Result)));
    end Else If Name='EOF' Then
    Begin
     If Copy(Line,1,1)<>'(' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     Line:=Trim(Line);
     If Copy(Line,1,1)<>'#' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     Result:=Calculate(Line);
     If Error<>'' Then Exit;
     If NumStr Then
     Begin
      Error:='Type mismatch';
      Exit;
     end;
     Line:=Trim(Line);
     If Copy(Line,1,1)<>')' Then
     Begin
      Error:='Syntax error';
      Exit;
     end;
     Delete(Line,1,1);
     If (Trunc(StringToNumber(Result))<1) Or (Trunc(StringToNumber(Result))>MaxFiles) Then
     Begin
      Error:='Invalid file number';
      Exit;
     end;
     If Not Files[Trunc(StringToNumber(Result))].IsUse Then
     Begin
      Error:='Invalid file number';
      Exit;
     end;
     If EoF(Files[Trunc(StringToNumber(Result))].WorkFile) Then InMeaning:='-1' Else InMeaning:='0';
    end Else If Copy(Name,1,2)='FN' Then InMeaning:=InDefFn(Name,False,Line) Else InMeaning:=InVar(Name,False);
   end;
  end;
 '"':
  Begin
   Delete(Line,1,1);
   If Pos('"',Line)=0 Then
   Begin
    Error:='Syntax error';
    Exit;
   end;
   InMeaning:=Copy(Line,1,Pos('"',Line)-1);
   Line:=Copy(Line,Pos('"',Line)+1,255);
   NumStr:=True;
  end;
 '(':
  Begin
   Delete(Line,1,1);
   InMeaning:=Calculate(Line);
   If Error<>'' Then Exit;
   Line:=Trim(Line);
   If Copy(Line,1,1)<>')' Then Error:='Syntax error' Else Delete(Line,1,1);
  end;
 end;
end;
Function ParseCalculate(Var Line : String) : String;
Var
  Result     : String;
  Value      : String;
  Action     : String;
  TempLine   : String;
Begin
 Result:=ParseInMeaning(Line);
 If Error<>'' Then Exit;
 Line:=Trim(Line);
 While Line<>'' Do
 Case UpCase(Line[1]) Of
 '+':
  Begin
   Delete(Line,1,1);
   Value:=ParseInMeaning(Line);
   If Error<>'' Then Exit;
   Result:=Result+'+'+Value;
  end;
 '-':
  Begin
   Delete(Line,1,1);
   Value:=ParseInMeaning(Line);
   If Error<>'' Then Exit;
   Result:=Result+'-'+Value;
  end;
 '/','\':
  Begin
   Delete(Line,1,1);
   Value:=ParseInMeaning(Line);
   If Error<>'' Then Exit;
   Result:=Result+'/'+Value;
  end;
 '*':
  Begin
   Delete(Line,1,1);
   Value:=ParseInMeaning(Line);
   If Error<>'' Then Exit;
   Result:=Result+'*'+Value;
  end;
 '=':
  Begin
   Delete(Line,1,1);
   Line:=Trim(Line);
   If Line='' Then
   Begin
    Error:='Syntax error';
    Exit;
   end;
   Case Line[1] Of
   '<':
    Begin
     Delete(Line,1,1);
     Value:=ParseInMeaning(Line);
     If Error<>'' Then Exit;
     Result:=Result+'<='+Value;
    end;
   '>':
    Begin
     Delete(Line,1,1);
     Value:=ParseInMeaning(Line);
     If Error<>'' Then Exit;
     Result:=Result+'=>'+Value;
    end;
   Else
    Begin
     Value:=ParseInMeaning(Line);
     If Error<>'' Then Exit;
     Result:=Result+'='+Value;
    end;
   end;
  end;
 '<':
  Begin
   Delete(Line,1,1);
   Line:=Trim(Line);
   If Line='' Then
   Begin
    Error:='Syntax error';
    Exit;
   end;
   Case Line[1] Of
   '>':
    Begin
     Delete(Line,1,1);
     Value:=ParseInMeaning(Line);
     If Error<>'' Then Exit;
     Result:=Result+'<>'+Value;
    end;
   '=':
    Begin
     Delete(Line,1,1);
     Value:=ParseInMeaning(Line);
     If Error<>'' Then Exit;
     Result:=Result+'<='+Value;
    end;
   Else
    Begin
     Value:=ParseInMeaning(Line);
     If Error<>'' Then Exit;
     Result:=Result+'<'+Value;
    end;
   end;
  end;
 '>':
  Begin
   Delete(Line,1,1);
   Line:=Trim(Line);
   If Line='' Then
   Begin
    Error:='Syntax error';
    Exit;
   end;
   Case Line[1] Of
   '<':
    Begin
     Delete(Line,1,1);
     Value:=ParseInMeaning(Line);
     If Error<>'' Then Exit;
     Result:=Result+'<>'+Value;
    end;
   '=':
    Begin
     Delete(Line,1,1);
     Value:=ParseInMeaning(Line);
     If Error<>'' Then Exit;
     Result:=Result+'=>'+Value;
    end;
   Else
    Begin
     Value:=ParseInMeaning(Line);
     If Error<>'' Then Exit;
     Result:=Result+'>'+Value;
    end;
   end;
  end;
 'A'..'Z':
  Begin
   TempLine:=Line;
   Action:=InName(Line);
   If Error<>'' Then Exit;
   If Action='AND' Then
   Begin
    Value:=ParseInMeaning(Line);
    If Error<>'' Then Exit;
    Result:=Result+' And '+Value;
   end Else If Action='OR' Then
   Begin
    Value:=ParseInMeaning(Line);
    If Error<>'' Then Exit;
    Result:=Result+' Or '+Value;
   end Else If Action='XOR' Then
   Begin
    Value:=ParseInMeaning(Line);
    If Error<>'' Then Exit;
    Result:=Result+' XOr '+Value;
   end Else If Action='MOD' Then
   Begin
    Value:=ParseInMeaning(Line);
    If Error<>'' Then Exit;
    Result:=Result+' Mod '+Value;
   end Else
   Begin
    Line:=TempLine;
    Break;
   end;
  end;
 Else Break;
 end;
 ParseCalculate:=Result;
end;
Function ParseInMeaning(Var Line : String) : String;
Var
  Result : String;
  Value  : String;
  Name   : String;
Begin
 Line:=Trim(Line);
 If Line='' Then
 Begin
  Error:='Syntax error';
  Exit;
 end;
 Case UpCase(Line[1]) Of
 '0'..'9': ParseInMeaning:=NumberToString(InNumber(Line));
 '-':
  Begin
   Delete(Line,1,1);
   Result:=ParseCalculate(Line);
   If Error<>'' Then Exit;
   ParseInMeaning:='-'+Result;
  end;
 '+':
  Begin
   Delete(Line,1,1);
   Result:=ParseCalculate(Line);
   If Error<>'' Then Exit;
   ParseInMeaning:=Result;
  end;
 'A'..'Z':
  Begin
   Result:=InName(Line);
   If Error<>'' Then Exit;
   Line:=Trim(Line);
   If Result='NOT' Then
   Begin
    Result:=ParseCalculate(Line);
    If Error<>'' Then Exit;
    ParseInMeaning:='Not '+Result;
   end Else
   Begin
    If Line<>'' Then
    Case Line[1] Of
    '$':
     Begin
      Delete(Line,1,1);
      Result:=Result+'$';
     end;
    '!': Delete(Line,1,1);
    '@': Delete(Line,1,1);
    '#': Delete(Line,1,1);
    '%': Delete(Line,1,1);
    '&': Delete(Line,1,1);
    end;
    Line:=Trim(Line);
    If Copy(Line,1,1)='(' Then
    Begin
     Delete(Line,1,1);
     Result:=Result+'(';
     Line:=Trim(Line);
     While Line<>'' Do
     Begin
      If Copy(Line,1,1)='#' Then
      Begin
       Delete(Line,1,1);
       Result:=Result+'#';
      end;
      Value:=ParseCalculate(Line);
      If Error<>'' Then Exit;
      Result:=Result+Value;
      Line:=Trim(Line);
      If Line='' Then
      Begin
       Error:='Syntax error';
       Exit;
      end;
      Case Line[1] Of
      ')':
       Begin
        Delete(Line,1,1);
        Result:=Result+')';
        Break;
       end;
      ',':
       Begin
        Delete(Line,1,1);
        Result:=Result+',';
       end;
      Else
       Begin
        Error:='Syntax error';
        Exit;
       end;
      end;
     end;
    end;
    ParseInMeaning:=Result;
   end;
  end;
 '"':
  Begin
   Delete(Line,1,1);
   If Pos('"',Line)=0 Then
   Begin
    Error:='Syntax error';
    Exit;
   end;
   ParseInMeaning:='"'+Copy(Line,1,Pos('"',Line)-1)+'"';
   Line:=Copy(Line,Pos('"',Line)+1,255);
  end;
 '(':
  Begin
   Delete(Line,1,1);
   Result:=ParseCalculate(Line);
   If Error<>'' Then Exit;
   Line:=Trim(Line);
   If Copy(Line,1,1)<>')' Then Error:='Syntax error' Else
   Begin
    Delete(Line,1,1);
    ParseInMeaning:='('+Result+')';
   end;
  end;
 end;
end;
Procedure ClearAll(ClearLines : Boolean);
Var
  Index    : Word;
  SubIndex : Word;
Begin
 If ClearLines Then
 Begin
  For Index:=1 To MaxLines Do
  Begin
   Lines[Index].Line:='';
   Lines[Index].LineNumber:=0;
  end;
  BASICLinesCount:=0;
 end;
 For Index:=1 To MaxWhiles Do
 Begin
  Whiles[Index].StartLine:=0;
  Whiles[Index].EndLine:=0;
  Whiles[Index].Conditional:='';
  Whiles[Index].IsFree:=True;
 end;
 For Index:=1 To MaxFroms Do
 Begin
  Froms[Index].StartLine:=0;
  Froms[Index].EndLine:=0;
  Froms[Index].BeginValue:=0;
  Froms[Index].EndLine:=0;
  Froms[Index].IsFree:=True;
 end;
 For Index:=1 To MaxFiles Do
 Begin
  If Files[Index].IsUse Then Close(Files[Index].WorkFile);
  Files[Index].FileMode:=False;
  Files[Index].IsUse:=False;
 end;
 For Index:=1 To MaxGoSubS Do GoSubS[Index]:=0;
 GoSubSCount:=0;
 For Index:=1 To MaxVars Do
 Begin
  Vars[Index].VarName:='';
  Vars[Index].StringValue:='';
  Vars[Index].NumberValue:=0.0;
  Vars[Index].ValueType:=False;
 end;
 VarsCount:=0;
 For Index:=1 To MaxDefFnS Do
 Begin
  DefFnS[Index]:='';
  For SubIndex:=1 To MaxDefFnSArgs Do
  Begin
   DefFnSArgs[Index,SubIndex].VarName:='';
   DefFnSArgs[Index,SubIndex].StringValue:='';
   DefFnSArgs[Index,SubIndex].NumberValue:=0.0;
   DefFnSArgs[Index,SubIndex].ValueType:=False;
  end;
  DefFnSArgsCount[Index]:=0;
 end;
 DefFnSCount:=0;
 CurrentDefFn:=0;
 DefFnMode:=False;
 CurrentLine:=0;
 RunMode:=False;
 TraceMode:=False;
 NumStr:=False;
 Error:='';
 For Index:=1 To MaxANSIParameters Do Parameters[Index]:=0;
 ParametersCount:=0;
 CursorColumn:=0;
 CursorRow:=0;
 CursorSaved:=False;
 Mode:=0;
 NumberLine:='';
 Number:=0;
end;
Function FindLine(LineNumber : Word) : Word;
Var
  Index : Word;
Begin
 If BASICLinesCount=0 Then Error:='Line not found' Else
 Begin
  For Index:=1 To BASICLinesCount+1 Do
  Begin
   If Index=BASICLinesCount+1 Then
   Begin
    Error:='Line not found';
    Exit;
   end;
   If Lines[Index].LineNumber=LineNumber Then Break;
  end;
  FindLine:=Index;
 end;
end;
Function ParseRunLine(Var Line : String) : String;
Var
  Name      : String;
  Result    : String;
  Value     : String;
  Meaning   : String;
Begin
 Name:=InName(Line);
 If Error<>'' Then Exit;
 Line:=Trim(Line);
 If Name='REM' Then
 Begin
  If Line<>'' Then ParseRunLine:='Rem '+Line Else ParseRunLine:='Rem';
 end Else If Name='OPEN' Then
 Begin
  Name:=ParseCalculate(Line);
  If Error<>'' Then Exit;
  Result:=InName(Line);
  If Error<>'' Then Exit;
  If Result<>'FOR' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Result:=InName(Line);
  If Error<>'' Then Exit;
  If (Result<>'INPUT') And (Result<>'OUTPUT') And (Result<>'APPEND') Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Value:=InName(Line);
  If Error<>'' Then Exit;
  If Value<>'AS' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Line:=Trim(Line);
  If Copy(Line,1,1)<>'#' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Delete(Line,1,1);
  If Result='INPUT' Then Result:='InPut';
  If Result='OUTPUT' Then Result:='OutPut';
  If Result='APPEND' Then Result:='Append';
  ParseRunLine:='Open '+Name+' For '+Result+' As #'+ParseCalculate(Line);
 end Else If Name='CLOSE' Then
 Begin
  If Copy(Line,1,1)<>'#' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Delete(Line,1,1);
  ParseRunLine:='Close #'+ParseCalculate(Line);
 end Else If Name='PRINT' Then
 Begin
  If Copy(Line,1,1)='#' Then
  Begin
   Delete(Line,1,1);
   Value:=ParseCalculate(Line);
   If Error<>'' Then Exit;
   Line:=Trim(Line);
   If Copy(Line,1,1)<>',' Then
   Begin
    Error:='Syntax error';
    Exit;
   end;
   Delete(Line,1,1);
   ParseRunLine:='Print #'+Value+','+ParseCalculate(Line);
  end Else ParseRunLine:='Print '+ParseCalculate(Line);
 end Else If Name='CLS' Then ParseRunLine:='Cls' Else If Name='COLOR' Then
 Begin
  Result:=ParseCalculate(Line);
  If Error<>'' Then Exit;
  Line:=Trim(Line);
  If Copy(Line,1,1)<>',' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Delete(Line,1,1);
  ParseRunLine:='Color '+Result+','+ParseCalculate(Line);
 end Else If Name='LOCATE' Then
 Begin
  Result:=ParseCalculate(Line);
  If Error<>'' Then Exit;
  Line:=Trim(Line);
  If Copy(Line,1,1)<>',' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Delete(Line,1,1);
  ParseRunLine:='Locate '+Result+','+ParseCalculate(Line);
 end Else If Name='SOUND' Then
 Begin
  Result:=ParseCalculate(Line);
  If Error<>'' Then Exit;
  Line:=Trim(Line);
  If Copy(Line,1,1)<>',' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Delete(Line,1,1);
  ParseRunLine:='Sound '+Result+','+ParseCalculate(Line);
 end Else If Name='NAME' Then
 Begin
  Result:=ParseCalculate(Line);
  If Error<>'' Then Exit;
  Value:=InName(Line);
  If Error<>'' Then Exit;
  If Value<>'AS' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  ParseRunLine:='Name '+Result+' As '+ParseCalculate(Line);
 end Else If Name='MKDIR' Then ParseRunLine:='MkDir '+ParseCalculate(Line) Else
 If Name='CHDIR' Then ParseRunLine:='ChDir '+ParseCalculate(Line) Else
 If Name='RMDIR' Then ParseRunLine:='RmDir '+ParseCalculate(Line) Else
 If Name='KILL' Then ParseRunLine:='Kill '+ParseCalculate(Line) Else
 If Name='FILES' Then ParseRunLine:='Files '+ParseCalculate(Line) Else
 If Name='SYSTEM' Then ParseRunLine:='System' Else If Name='WINDOW' Then
 Begin
  If Copy(Line,1,1)<>'(' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Delete(Line,1,1);
  Name:=ParseCalculate(Line);
  If Error<>'' Then Exit;
  Line:=Trim(Line);
  If Copy(Line,1,1)<>',' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Delete(Line,1,1);
  Result:=ParseCalculate(Line);
  If Error<>'' Then Exit;
  Line:=Trim(Line);
  If Copy(Line,1,1)<>')' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Delete(Line,1,1);
  Line:=Trim(Line);
  If Copy(Line,1,1)<>'-' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Delete(Line,1,1);
  Line:=Trim(Line);
  If Copy(Line,1,1)<>'(' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Delete(Line,1,1);
  Value:=ParseCalculate(Line);
  If Error<>'' Then Exit;
  Line:=Trim(Line);
  If Copy(Line,1,1)<>',' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Delete(Line,1,1);
  Meaning:=ParseCalculate(Line);
  If Error<>'' Then Exit;
  Line:=Trim(Line);
  If Copy(Line,1,1)<>')' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Delete(Line,1,1);
  ParseRunLine:='Window ('+Name+','+Result+')-('+Value+','+Meaning+')';
 end Else If Name='LIST' Then
 Begin
  If Line='' Then ParseRunLine:='List' Else
  Begin
   Result:=ParseCalculate(Line);
   If Error<>'' Then Exit;
   Line:=Trim(Line);
   If Copy(Line,1,1)=',' Then
   Begin
    Delete(Line,1,1);
    ParseRunLine:='List '+Result+','+ParseCalculate(Line);
   end Else ParseRunLine:='List '+Result;
  end;
 end Else If Name='DELETE' Then
 Begin
  Result:=ParseCalculate(Line);
  If Error<>'' Then Exit;
  Line:=Trim(Line);
  If Copy(Line,1,1)=',' Then
  Begin
   Delete(Line,1,1);
   ParseRunLine:='Delete '+Result+','+ParseCalculate(Line);
  end Else ParseRunLine:='Delete '+Result;
 end Else If Name='SAVE' Then ParseRunLine:='Save '+ParseCalculate(Line) Else
 If Name='LOAD' Then ParseRunLine:='Load '+ParseCalculate(Line) Else
 If Name='NEW' Then ParseRunLine:='New' Else If Name='GO' Then
 Begin
  Name:=InName(Line);
  If Error<>'' Then Exit;
  If Name='TO' Then ParseRunLine:='Go To '+ParseCalculate(Line) Else
  If Name='SUB' Then ParseRunLine:='Go Sub '+ParseCalculate(Line) Else Error:='Syntax error';
 end Else If Name='RETURN' Then ParseRunLine:='Return' Else
 If Name='TRON' Then ParseRunLine:='TrOn' Else
 If Name='TROFF' Then ParseRunLine:='TrOff' Else
 If Name='RUN' Then ParseRunLine:='Run' Else
 If Name='END' Then ParseRunLine:='End' Else
 If Name='LET' Then
 Begin
  Result:=InName(Line);
  If Error<>'' Then Exit;
  Line:=Trim(Line);
  If Line='' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Case Line[1] Of
  '$':
   Begin
    Delete(Line,1,1);
    Result:=Result+'$';
   end;
  '!': Delete(Line,1,1);
  '@': Delete(Line,1,1);
  '#': Delete(Line,1,1);
  '%': Delete(Line,1,1);
  '&': Delete(Line,1,1);
  end;
  Line:=Trim(Line);
  If Copy(Line,1,1)<>'=' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Delete(Line,1,1);
  ParseRunLine:='Let '+Result+'='+ParseCalculate(Line);
 end Else
 If Name='WHILE' Then ParseRunLine:='While '+ParseCalculate(Line) Else
 If Name='WEND' Then ParseRunLine:='WEnd' Else If Name='FROM' Then
 Begin
  Name:=InName(Line);
  If Error<>'' Then Exit;
  Line:=Trim(Line);
  If Line='' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Case Line[1] Of
  '$':
   Begin
    Error:='Variable type mismatch';
    Exit;
   end;
  '!': Delete(Line,1,1);
  '@': Delete(Line,1,1);
  '#': Delete(Line,1,1);
  '%': Delete(Line,1,1);
  '&': Delete(Line,1,1);
  end;
  Line:=Trim(Line);
  If Copy(Line,1,1)<>'=' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Delete(Line,1,1);
  Result:=ParseCalculate(Line);
  If Error<>'' Then Exit;
  Value:=InName(Line);
  If Error<>'' Then Exit;
  If Value<>'TO' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  ParseRunLine:='From '+Name+'='+Result+' To '+ParseCalculate(Line);
 end Else If Name='NEXT' Then
 Begin
  Name:=InName(Line);
  If Error<>'' Then Exit;
  Line:=Trim(Line);
  If Line<>'' Then
  Case Line[1] Of
  '$':
   Begin
    Error:='Variable type mismatch';
    Exit;
   end;
  '!': Delete(Line,1,1);
  '@': Delete(Line,1,1);
  '#': Delete(Line,1,1);
  '%': Delete(Line,1,1);
  '&': Delete(Line,1,1);
  end;
  ParseRunLine:='Next '+Name;
 end Else If Name='EXIT' Then
 Begin
  Name:=InName(Line);
  If Error<>'' Then Exit;
  If Name='WHILE' Then ParseRunLine:='Exit While' Else
  If Name='FROM' Then ParseRunLine:='Exit From' Else
  Error:='Syntax error';
 end Else If Name='IF' Then
 Begin
  Result:='If '+ParseCalculate(Line);
  If Error<>'' Then Exit;
  Name:=InName(Line);
  If Error<>'' Then Exit;
  If Name<>'THEN' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Result:=Result+' Then '+ParseRunLine(Line);
  If Error<>'' Then Exit;
  Line:=Trim(Line);
  If Line<>'' Then
  Begin
   Name:=InName(Line);
   If Error<>'' Then Exit;
   If Name<>'ELSE' Then
   Begin
    Error:='Syntax error';
    Exit;
   end;
   ParseRunLine:=Result+' Else '+ParseRunLine(Line);
  end Else ParseRunLine:=Result;
 end Else If Name='DEF' Then
 Begin
  Result:=InName(Line);
  If Error<>'' Then Exit;
  If Copy(Result,1,2)<>'FN' Then
  Begin
   Error:='User - defined function name must be beginning on FN';
   Exit;
  end;
  Line:=Trim(Line);
  Case Line[1] Of
  '$':
   Begin
    Delete(Line,1,1);
    Result:=Result+'$';
   end;
  '!': Delete(Line,1,1);
  '@': Delete(Line,1,1);
  '#': Delete(Line,1,1);
  '%': Delete(Line,1,1);
  '&': Delete(Line,1,1);
  end;
  Line:=Trim(Line);
  If Copy(Line,1,1)='(' Then
  Begin
   Delete(Line,1,1);
   Result:=Result+'(';
   Line:=Trim(Line);
   If Line='' Then
   Begin
    Error:='Syntax error';
    Exit;
   end;
   While Line<>'' Do
   Begin
    Name:=InName(Line);
    If Error<>'' Then Exit;
    Result:=Result+Name;
    Line:=Trim(Line);
    If Line='' Then
    Begin
     Error:='Syntax error';
     Exit;
    end;
    Case Line[1] Of
    '$':
     Begin
      Delete(Line,1,1);
      Result:=Result+'$';
     end;
    '!': Delete(Line,1,1);
    '@': Delete(Line,1,1);
    '#': Delete(Line,1,1);
    '%': Delete(Line,1,1);
    '&': Delete(Line,1,1);
    end;
    Line:=Trim(Line);
    If Line='' Then
    Begin
     Error:='Syntax error';
     Exit;
    end;
    Case Line[1] Of
    ')':
     Begin
      Delete(Line,1,1);
      Result:=Result+')';
      Line:=Trim(Line);
      Break;
     end;
    ',':
     Begin
      Delete(Line,1,1);
      Result:=Result+',';
     end;
    end;
   end;
  end;
  If Copy(Line,1,1)<>'=' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Delete(Line,1,1);
  ParseRunLine:='Def '+Result+'='+ParseCalculate(Line);
 end Else If Name='HELP' Then ParseRunLine:='Help' Else If Name='SCREEN' Then
 Begin
  Name:=InName(Line);
  If Error<>'' Then Exit;
  If Name='BW40' Then ParseRunLine:='Screen Bw40' Else
  If Name='CO40' Then ParseRunLine:='Screen Co40' Else
  If Name='BW80' Then ParseRunLine:='Screen Bw80' Else
  If Name='CO80' Then ParseRunLine:='Screen Co80' Else
  If Name='MONO' Then ParseRunLine:='Screen Mono' Else Error:='Syntax error';
 end Else Error:='Unknown statement';
end;
Procedure DeleteLine(LineNumber : Word);
Var
  Index  : Word;
  Number : Word;
Begin
 Number:=FindLine(LineNumber);
 If Error<>'' Then Exit;
 Lines[Number].Line:='';
 Lines[Number].LineNumber:=0;
 If Number<BASICLinesCount Then
 For Index:=Number To BASICLinesCount-1 Do
 Begin
  Lines[Index].Line:=Lines[Index+1].Line;
  Lines[Index].LineNumber:=Lines[Index+1].LineNumber;
  Lines[Index+1].Line:='';
  Lines[Index+1].LineNumber:=0;
 end;
 Dec(BASICLinesCount);
end;
Procedure RunLine(Var Line : String);
Var
  Name        : String;
  Result      : String;
  Value       : String;
  Meaning     : String;
  FromVarName : String;
  Number      : Real;
  Num         : Real;
  Find        : SearchRec;
  WorkFile    : Text;
  WorkDT      : DateTime;
  Index       : Word;
  SubIndex    : Word;
  WorkIndex   : Word;
  WhilesCount : Word;
  FromsCount  : Word;
  VarType     : Boolean;
  IfElse      : Boolean;
Begin
 Name:=InName(Line);
 If Error<>'' Then Exit;
 Line:=Trim(Line);
 If Name='REM' Then Exit Else If Name='OPEN' Then
 Begin
  Name:=Calculate(Line);
  If Error<>'' Then Exit;
  If Not NumStr Then
  Begin
   Error:='Type mismatch';
   Exit;
  end;
  Result:=InName(Line);
  If Error<>'' Then Exit;
  If Result<>'FOR' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Result:=InName(Line);
  If Error<>'' Then Exit;
  If (Result<>'INPUT') And (Result<>'OUTPUT') And (Result<>'APPEND') Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Value:=InName(Line);
  If Error<>'' Then Exit;
  If Value<>'AS' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Line:=Trim(Line);
  If Copy(Line,1,1)<>'#' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Delete(Line,1,1);
  Value:=Calculate(Line);
  If Error<>'' Then Exit;
  If NumStr Then
  Begin
   Error:='Type mismatch';
   Exit;
  end;
  Number:=StringToNumber(Value);
  If Error<>'' Then Exit;
  If (Trunc(Number)<1) Or (Trunc(Number)>MaxFiles) Then
  Begin
   Error:='Invalid file number';
   Exit;
  end;
  If Files[Trunc(Number)].IsUse Then
  Begin
   Error:='File already open';
   Exit;
  end;
  If Result='INPUT' Then Files[Trunc(Number)].FileMode:=True Else Files[Trunc(Number)].FileMode:=False;
  Files[Trunc(Number)].IsUse:=True;
  Assign(Files[Trunc(Number)].WorkFile,Name);
  If Result='INPUT' Then ReSet(Files[Trunc(Number)].WorkFile) Else
  If Result='OUTPUT' Then ReWrite(Files[Trunc(Number)].WorkFile) Else
  If Result='APPEND' Then Append(Files[Trunc(Number)].WorkFile);
  If IOResult<>0 Then Error:='Cannot open file';
 end Else If Name='CLOSE' Then
 Begin
  If Copy(Line,1,1)<>'#' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Delete(Line,1,1);
  Result:=Calculate(Line);
  If Error<>'' Then Exit;
  If NumStr Then
  Begin
   Error:='Type mismatch';
   Exit;
  end;
  Number:=StringToNumber(Result);
  If Error<>'' Then Exit;
  If (Trunc(Number)<1) Or (Trunc(Number)>MaxFiles) Then
  Begin
   Error:='Invalid file number';
   Exit;
  end;
  If Not Files[Trunc(Number)].IsUse Then
  Begin
   Error:='File already closed';
   Exit;
  end;
  Files[Trunc(Number)].FileMode:=False;
  Files[Trunc(Number)].IsUse:=False;
  Close(Files[Trunc(Number)].WorkFile);
  If IOResult<>0 Then Error:='Cannot close file';
 end Else If Name='PRINT' Then
 Begin
  If Copy(Line,1,1)='#' Then
  Begin
   Delete(Line,1,1);
   Value:=Calculate(Line);
   If Error<>'' Then Exit;
   If NumStr Then
   Begin
    Error:='Type mismatch';
    Exit;
   end;
   Number:=StringToNumber(Value);
   If Error<>'' Then Exit;
   If (Trunc(Number)<1) Or (Trunc(Number)>MaxFiles) Then
   Begin
    Error:='Invalid file number';
    Exit;
   end;
   If Not Files[Trunc(Number)].IsUse Then
   Begin
    Error:='Invalid file number';
    Exit;
   end;
   If Files[Trunc(Number)].FileMode Then
   Begin
    Error:='Bad file mode';
    Exit;
   end;
   Line:=Trim(Line);
   If Copy(Line,1,1)<>',' Then
   Begin
    Error:='Syntax error';
    Exit;
   end;
   Delete(Line,1,1);
   Result:=Calculate(Line);
   If Error<>'' Then Exit;
   WriteLn(Files[Trunc(Number)].WorkFile,Result);
   If IOResult<>0 Then Error:='Cannot write to file';
  end Else
  Begin
   Result:=Calculate(Line);
   If Error<>'' Then Exit;
   WriteANSILine(Result);
  end;
 end Else If Name='CLS' Then ClrScr Else If Name='COLOR' Then
 Begin
  Result:=Calculate(Line);
  If Error<>'' Then Exit;
  If NumStr Then
  Begin
   Error:='Type mismacth';
   Exit;
  end;
  Number:=StringToNumber(Result);
  If Error<>'' Then Exit;
  Line:=Trim(Line);
  If Copy(Line,1,1)<>',' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Delete(Line,1,1);
  Result:=Calculate(Line);
  If Error<>'' Then Exit;
  If NumStr Then
  Begin
   Error:='Type mismacth';
   Exit;
  end;
  Num:=StringToNumber(Result);
  If Error<>'' Then Exit;
  TextBackGround(Trunc(Number));
  TextColor(Trunc(Num));
 end Else If Name='LOCATE' Then
 Begin
  Result:=Calculate(Line);
  If Error<>'' Then Exit;
  If NumStr Then
  Begin
   Error:='Type mismacth';
   Exit;
  end;
  Number:=StringToNumber(Result);
  If Error<>'' Then Exit;
  Line:=Trim(Line);
  If Copy(Line,1,1)<>',' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Delete(Line,1,1);
  Result:=Calculate(Line);
  If Error<>'' Then Exit;
  If NumStr Then
  Begin
   Error:='Type mismacth';
   Exit;
  end;
  Num:=StringToNumber(Result);
  If Error<>'' Then Exit;
  GoToXY(Trunc(Number),Trunc(Num));
 end Else If Name='SOUND' Then
 Begin
  Result:=Calculate(Line);
  If Error<>'' Then Exit;
  If NumStr Then
  Begin
   Error:='Type mismacth';
   Exit;
  end;
  Number:=StringToNumber(Result);
  If Error<>'' Then Exit;
  Line:=Trim(Line);
  If Copy(Line,1,1)<>',' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Delete(Line,1,1);
  Result:=Calculate(Line);
  If Error<>'' Then Exit;
  If NumStr Then
  Begin
   Error:='Type mismacth';
   Exit;
  end;
  Num:=StringToNumber(Result);
  If Error<>'' Then Exit;
  Sound(Trunc(Number));
  Delay(Trunc(Num));
  NoSound;
 end Else If Name='NAME' Then
 Begin
  Result:=Calculate(Line);
  If Error<>'' Then Exit;
  If Not NumStr Then
  Begin
   Error:='Type mismatch';
   Exit;
  end;
  Value:=InName(Line);
  If Error<>'' Then Exit;
  If Value<>'AS' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Value:=Calculate(Line);
  If Error<>'' Then Exit;
  If Not NumStr Then
  Begin
   Error:='Type mismatch';
   Exit;
  end;
  Assign(WorkFile,Result);
  Rename(WorkFile,Value);
  If IOResult<>0 Then Error:='Cannot rename file';
 end Else If Name='MKDIR' Then
 Begin
  Result:=Calculate(Line);
  If Error<>'' Then Exit;
  If Not NumStr Then
  Begin
   Error:='Type mismacth';
   Exit;
  end;
  MkDir(Result);
  If IOResult<>0 Then Error:='Cannot make directory';
 end Else If Name='CHDIR' Then
 Begin
  Result:=Calculate(Line);
  If Error<>'' Then Exit;
  If Not NumStr Then
  Begin
   Error:='Type mismacth';
   Exit;
  end;
  ChDir(Result);
  If IOResult<>0 Then Error:='Cannot change directory';
 end Else If Name='RMDIR' Then
 Begin
  Result:=Calculate(Line);
  If Error<>'' Then Exit;
  If Not NumStr Then
  Begin
   Error:='Type mismacth';
   Exit;
  end;
  RmDir(Result);
  If IOResult<>0 Then Error:='Cannot remove directory';
 end Else If Name='KILL' Then
 Begin
  Result:=Calculate(Line);
  If Error<>'' Then Exit;
  If Not NumStr Then
  Begin
   Error:='Type mismacth';
   Exit;
  end;
  FindFirst(Result,AnyFile,Find);
  If DosError=18 Then
  Begin
   Error:='File not found';
   Exit;
  end;
  Repeat
   Assign(WorkFile,Find.Name);
   Erase(WorkFile);
   If IOResult<>0 Then
   Begin
    Error:='Cannot delete file';
    Exit;
   end;
   FindNext(Find);
  Until DosError=18;
 end Else If Name='FILES' Then
 Begin
  Result:=Calculate(Line);
  If Error<>'' Then Exit;
  If Not NumStr Then
  Begin
   Error:='Type mismacth';
   Exit;
  end;
  FindFirst(Result,AnyFile,Find);
  If DosError=18 Then
  Begin
   Error:='File not found';
   Exit;
  end;
  WriteLn('Name.        Size.      Date.           Time.    Attribute.');
  Number:=0.0;
  Repeat
   Number:=Number+Find.Size;
   Result:=Find.Name;
   While Length(Result)<13 Do Result:=Result+' ';
   Value:=NumberToString(Find.Size);
   While Length(Value)<10 Do Value:=' '+Value;
   Result:=Result+Value+' ';
   UnPackTime(Find.Time,WorkDT);
   Case DayOfWeek(WorkDT.Year,WorkDT.Month,WorkDT.Day) Of
   1: Result:=Result+'Mon';
   2: Result:=Result+'Tue';
   3: Result:=Result+'Wed';
   4: Result:=Result+'Thu';
   5: Result:=Result+'Fri';
   6: Result:=Result+'Sat';
   7: Result:=Result+'Sun';
   end;
   Value:=NumberToString(WorkDT.Day);
   If Length(Value)<2 Then Value:=' '+Value;
   Result:=Result+' '+Value+' ';
   Case WorkDT.Month Of
    1: Result:=Result+'Jan';
    2: Result:=Result+'Feb';
    3: Result:=Result+'Mar';
    4: Result:=Result+'Apr';
    5: Result:=Result+'May';
    6: Result:=Result+'Jun';
    7: Result:=Result+'Jul';
    8: Result:=Result+'Aug';
    9: Result:=Result+'Sep';
   10: Result:=Result+'Oct';
   11: Result:=Result+'Nov';
   12: Result:=Result+'Dec';
   end;
   Result:=Result+' '+NumberToString(WorkDT.Year)+' ';
   Value:=NumberToString(WorkDT.Hour);
   If Length(Value)<2 Then Value:='0'+Value;
   Result:=Result+Value+':';
   Value:=NumberToString(WorkDT.Min);
   If Length(Value)<2 Then Value:='0'+Value;
   Result:=Result+Value+':';
   Value:=NumberToString(WorkDT.Sec);
   If Length(Value)<2 Then Value:='0'+Value;
   Result:=Result+Value+' ';
   If (Find.Attr And ReadOnly)<>0 Then Value:='R' Else Value:=' ';
   If (Find.Attr And Hidden)<>0 Then Value:=Value+'H' Else Value:=Value+' ';
   If (Find.Attr And SysFile)<>0 Then Value:=Value+'S' Else Value:=Value+' ';
   If (Find.Attr And VolumeID)<>0 Then Value:=Value+'V' Else Value:=Value+' ';
   If (Find.Attr And Directory)<>0 Then Value:=Value+'D' Else Value:=Value+' ';
   If (Find.Attr And Archive)<>0 Then Value:=Value+'A' Else Value:=Value+' ';
   WriteLn(Result+Value);
   FindNext(Find);
  Until DosError=18;
  WriteLn('    Total size of files: '+NumberToString(Number)+' bytes.');
  WriteLn('      Current disk size: '+NumberToString(DiskSize(0))+' bytes.');
  WriteLn('Current disk free space: '+NumberToString(DiskFree(0))+' bytes.');
 end Else If Name='SYSTEM' Then Halt Else If Name='WINDOW' Then
 Begin
  If Copy(Line,1,1)<>'(' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Delete(Line,1,1);
  Name:=Calculate(Line);
  If Error<>'' Then Exit;
  If NumStr Then
  Begin
   Error:='Type mismacth';
   Exit;
  end;
  Line:=Trim(Line);
  If Copy(Line,1,1)<>',' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Delete(Line,1,1);
  Result:=Calculate(Line);
  If Error<>'' Then Exit;
  If NumStr Then
  Begin
   Error:='Type mismacth';
   Exit;
  end;
  Line:=Trim(Line);
  If Copy(Line,1,1)<>')' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Delete(Line,1,1);
  Line:=Trim(Line);
  If Copy(Line,1,1)<>'-' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Delete(Line,1,1);
  Line:=Trim(Line);
  If Copy(Line,1,1)<>'(' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Delete(Line,1,1);
  Value:=Calculate(Line);
  If Error<>'' Then Exit;
  If NumStr Then
  Begin
   Error:='Type mismacth';
   Exit;
  end;
  Line:=Trim(Line);
  If Copy(Line,1,1)<>',' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Delete(Line,1,1);
  Meaning:=Calculate(Line);
  If Error<>'' Then Exit;
  If NumStr Then
  Begin
   Error:='Type mismacth';
   Exit;
  end;
  Line:=Trim(Line);
  If Copy(Line,1,1)<>')' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Delete(Line,1,1);
  Window(Trunc(StringToNumber(Name)),Trunc(StringToNumber(Result)),Trunc(StringToNumber(Value)),Trunc(StringToNumber(Meaning)));
 end Else If Name='LIST' Then
 Begin
  If Line='' Then
  Begin
   For Index:=1 To BASICLinesCount Do
   Begin
    Result:=NumberToString(Lines[Index].LineNumber);
    While Length(Result)<Length(NumberToString(MaxLines)) Do Result:=' '+Result;
    WriteLn(Result+' '+Lines[Index].Line);
   end;
  end Else
  Begin
   Result:=Calculate(Line);
   If Error<>'' Then Exit;
   If NumStr Then
   Begin
    Error:='Type mismatch';
    Exit;
   end;
   Number:=FindLine(Trunc(StringToNumber(Result)));
   If Error<>'' Then Exit;
   Line:=Trim(Line);
   If Copy(Line,1,1)=',' Then
   Begin
    Delete(Line,1,1);
    Result:=Calculate(Line);
    If Error<>'' Then Exit;
    If NumStr Then
    Begin
     Error:='Type mismatch';
     Exit;
    end;
    Num:=FindLine(Trunc(StringToNumber(Result)));
    If Error<>'' Then Exit;
    If Num<Number Then
    Begin
     Error:='Invalid line number range';
     Exit;
    end;
    For Index:=Trunc(Number) To Trunc(Num) Do
    Begin
     Result:=NumberToString(Lines[Index].LineNumber);
     While Length(Result)<Length(NumberToString(MaxLines)) Do Result:=' '+Result;
     WriteLn(Result+' '+Lines[Index].Line);
    end;
   end Else
   Begin
    Result:=NumberToString(Lines[Trunc(Number)].LineNumber);
    While Length(Result)<Length(NumberToString(MaxLines)) Do Result:=' '+Result;
    WriteLn(Result+' '+Lines[Trunc(Number)].Line);
   end;
  end;
 end Else If Name='DELETE' Then
 Begin
  Result:=Calculate(Line);
  If Error<>'' Then Exit;
  If NumStr Then
  Begin
   Error:='Type mismatch';
   Exit;
  end;
  Line:=Trim(Line);
  If Copy(Line,1,1)=',' Then
  Begin
   Delete(Line,1,1);
   Value:=Calculate(Line);
   If Error<>'' Then Exit;
   If NumStr Then
   Begin
    Error:='Type mismatch';
    Exit;
   end;
   If StringToNumber(Value)<StringToNumber(Result) Then
   Begin
    Error:='Invalid line number range';
    Exit;
   end;
   For Index:=Trunc(StringToNumber(Result)) To Trunc(StringToNumber(Value)) Do
   Begin
    DeleteLine(Index);
    If Error<>'' Then Exit;
   end;
  end Else DeleteLine(Trunc(StringToNumber(Result)));
 end Else If Name='SAVE' Then
 Begin
  If BASICLinesCount=0 Then
  Begin
   Error:='Nothing to save';
   Exit;
  end;
  Result:=Calculate(Line);
  If Error<>'' Then Exit;
  If Not NumStr Then
  Begin
   Error:='Type mismacth';
   Exit;
  end;
  Assign(WorkFile,Result);
  ReWrite(WorkFile);
  If IOResult<>0 Then
  Begin
   Error:='Cannot open file';
   Exit;
  end;
  For Index:=1 To BASICLinesCount Do
  Begin
   Result:=NumberToString(Lines[Index].LineNumber);
   While Length(Result)<Length(NumberToString(MaxLines)) Do Result:=' '+Result;
   WriteLn(WorkFile,Result+' '+Lines[Index].Line);
   If IOResult<>0 Then
   Begin
    Close(WorkFile);
    Erase(WorkFile);
    Error:='Cannot write to file';
    Exit;
   end;
  end;
  Close(WorkFile);
 end Else If Name='LOAD' Then
 Begin
  Result:=Calculate(Line);
  If Error<>'' Then Exit;
  If Not NumStr Then
  Begin
   Error:='Type mismacth';
   Exit;
  end;
  Assign(WorkFile,Result);
  ReSet(WorkFile);
  If IOResult<>0 Then
  Begin
   Error:='Cannot open file';
   Exit;
  end;
  ClearAll(True);
  SubIndex:=0;
  While Not EoF(WorkFile) Do
  Begin
   ReadLn(WorkFile,Result);
   If IOResult<>0 Then
   Begin
    Close(WorkFile);
    ClearAll(True);
    Error:='Cannot read from file';
    Exit;
   end;
   If SubIndex=MaxLines Then
   Begin
    Close(WorkFile);
    ClearAll(True);
    Error:='Too many BASIC lines in file at line: '+NumberToString(SubIndex);
    Exit;
   end;
   Inc(SubIndex);
   Result:=Trim(Result);
   Index:=Trunc(InNumber(Result));
   If Error<>'' Then
   Begin
    Close(WorkFile);
    ClearAll(True);
    Exit;
   end;
   If (Index<1) Or (Index>MaxLines) Then
   Begin
    Close(WorkFile);
    ClearAll(True);
    Error:='Invalid line number in file at line: '+NumberToString(SubIndex);
    Exit;
   end;
   Result:=Trim(Result);
   If Result='' Then
   Begin
    Close(WorkFile);
    ClearAll(True);
    Error:='Invalid line in file at line: '+NumberToString(SubIndex);
    Exit;
   end;
   If Not ((Ord(UpCase(Result[1]))>(Ord('A')-1)) And (Ord(UpCase(Result[1]))<(Ord('Z')+1))) Then
   Begin
    Close(WorkFile);
    ClearAll(True);
    Error:='Invalid line in file at line: '+NumberToString(SubIndex);
    Exit;
   end;
   Result:=ParseRunLine(Result);
   If Error<>'' Then
   Begin
    Close(WorkFile);
    ClearAll(True);
    Error:=Error+' in file at line: '+NumberToString(SubIndex);
    Exit;
   end;
   If BASICLinesCount=0 Then
   Begin
    Inc(BASICLinesCount);
    Lines[BASICLinesCount].Line:=Result;
    Lines[BASICLinesCount].LineNumber:=Index;
   end Else
   Begin
    For WorkIndex:=1 To BASICLinesCount+1 Do
    Begin
     If WorkIndex=BASICLinesCount+1 Then
     Begin
      If BASICLinesCount=MaxLines Then
      Begin
       Close(WorkFile);
       ClearAll(True);
       Error:='Too many BASIC lines in file at line: '+NumberToString(SubIndex);
       Exit;
      end;
      Inc(BASICLinesCount);
      Lines[BASICLinesCount].Line:=Result;
      Lines[BASICLinesCount].LineNumber:=Index;
      SortLines;
      Break;
     end;
     If Lines[WorkIndex].LineNumber=Index Then
     Begin
      Lines[WorkIndex].Line:=Result;
      Break;
     end;
    end;
   end;
  end;
  Close(WorkFile);
 end Else If Name='NEW' Then ClearAll(True) Else If Name='GO' Then
 Begin
  If Not RunMode Then
  Begin
   Error:='Cannot execute GO TO or GO SUB statement without program running';
   Exit;
  end;
  Name:=InName(Line);
  If Error<>'' Then Exit;
  Result:=Calculate(Line);
  If Error<>'' Then Exit;
  If NumStr Then
  Begin
   Error:='Type mismatch';
   Exit;
  end;
  Index:=FindLine(Trunc(StringToNumber(Result)));
  If Error<>'' Then Exit;
  If Name='TO' Then CurrentLine:=Index-1 Else If Name='SUB' Then
  Begin
   If GoSubSCount=MaxGoSubS Then
   Begin
    Error:='Too many GO SUB''s';
    Exit;
   end;
   Inc(GoSubSCount);
   GoSubS[GoSubSCount]:=CurrentLine;
   CurrentLine:=Index-1;
  end Else Error:='Syntax error';
 end Else If Name='RETURN' Then
 Begin
  If Not RunMode Then
  Begin
   Error:='Cannot execute RETURN statement without program running';
   Exit;
  end;
  If GoSubSCount=0 Then
  Begin
   Error:='RETURN without GO SUB';
   Exit;
  end;
  CurrentLine:=GoSubS[GoSubSCount];
  GoSubS[GoSubSCount]:=0;
  Dec(GoSubSCount);
 end Else If Name='TRON' Then
 Begin
  TraceMode:=True;
  WriteLn('Trace mode is on.');
 end Else If Name='TROFF' Then
 Begin
  TraceMode:=False;
  WriteLn('Trace mode is off.');
 end Else If Name='RUN' Then
 Begin
  If RunMode Then
  Begin
   Error:='Program already running';
   Exit;
  end;
  If BASICLinesCount=0 Then
  Begin
   Error:='Nothing to run';
   Exit;
  end;
  RunMode:=True;
  CurrentLine:=1;
  Repeat
   If TraceMode Then Write('['+NumberToString(Lines[CurrentLine].LineNumber)+']');
   Result:=Lines[CurrentLine].Line;
   RunLine(Result);
   If Error<>'' Then Exit;
   Inc(CurrentLine);
  Until (CurrentLine>BASICLinesCount) Or (Not RunMode);
  RunMode:=False;
  CurrentLine:=0;
 end Else If Name='END' Then
 Begin
  If Not RunMode Then
  Begin
   Error:='Cannot end not running program';
   Exit;
  end;
  RunMode:=False;
 end Else If Name='DEF' Then
 Begin
  If DefFnSCount=MaxDefFnS Then
  Begin
   Error:='Too many user - defined functions';
   Exit;
  end;
  Inc(DefFnSCount);
  Result:=InName(Line);
  If Error<>'' Then Exit;
  If Copy(Result,1,2)<>'FN' Then
  Begin
   Error:='User - defined function name must be beginning on FN';
   Exit;
  end;
  Line:=Trim(Line);
  Case Line[1] Of
  '$':
   Begin
    Delete(Line,1,1);
    Result:=Result+'$';
   end;
  '!': Delete(Line,1,1);
  '@': Delete(Line,1,1);
  '#': Delete(Line,1,1);
  '%': Delete(Line,1,1);
  '&': Delete(Line,1,1);
  end;
  Line:=Trim(Line);
  If Copy(Line,1,1)='(' Then
  Begin
   Delete(Line,1,1);
   Result:=Result+'(';
   Line:=Trim(Line);
   If Line='' Then
   Begin
    Error:='Syntax error';
    Exit;
   end;
   While Line<>'' Do
   Begin
    Name:=InName(Line);
    If Error<>'' Then Exit;
    Result:=Result+Name;
    Line:=Trim(Line);
    If Line='' Then
    Begin
     Error:='Syntax error';
     Exit;
    end;
    Case Line[1] Of
    '$':
     Begin
      Delete(Line,1,1);
      Result:=Result+'$';
     end;
    '!': Delete(Line,1,1);
    '@': Delete(Line,1,1);
    '#': Delete(Line,1,1);
    '%': Delete(Line,1,1);
    '&': Delete(Line,1,1);
    end;
    Line:=Trim(Line);
    If Line='' Then
    Begin
     Error:='Syntax error';
     Exit;
    end;
    Case Line[1] Of
    ')':
     Begin
      Delete(Line,1,1);
      Result:=Result+')';
      Line:=Trim(Line);
      Break;
     end;
    ',':
     Begin
      Delete(Line,1,1);
      Result:=Result+',';
     end;
    end;
   end;
  end;
  If Copy(Line,1,1)<>'=' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Delete(Line,1,1);
  DefFnS[DefFnSCount]:=Result+'='+ParseCalculate(Line);
 end Else If Name='LET' Then
 Begin
  Name:=InName(Line);
  If Error<>'' Then Exit;
  Line:=Trim(Line);
  If Line='' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  VarType:=False;
  Case Line[1] Of
  '$':
   Begin
    Delete(Line,1,1);
    VarType:=True;
   end;
  '!': Delete(Line,1,1);
  '@': Delete(Line,1,1);
  '#': Delete(Line,1,1);
  '%': Delete(Line,1,1);
  '&': Delete(Line,1,1);
  end;
  Line:=Trim(Line);
  If Copy(Line,1,1)<>'=' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Delete(Line,1,1);
  Result:=Calculate(Line);
  If Error<>'' Then Exit;
  If NumStr<>VarType Then
  Begin
   Error:='Type mismatch';
   Exit;
  end;
  SetVar(Name,VarType,Result);
 end Else If Name='WHILE' Then
 Begin
  If Not RunMode Then
  Begin
   Error:='Cannot execute WHILE loop without program running';
   Exit;
  end;
  For Index:=1 To MaxWhiles+1 Do
  Begin
   If Index=MaxWhiles+1 Then
   Begin
    Error:='Too many WHILE''s';
    Exit;
   end;
   If Whiles[Index].IsFree Then Break;
  end;
  WhilesCount:=0;
  For SubIndex:=CurrentLine+1 To BASICLinesCount+1 Do
  Begin
   If SubIndex=BASICLinesCount+1 Then
   Begin
    Error:='WHILE without WEND';
    Exit;
   end;
   Value:=Lines[SubIndex].Line;
   Value:=InName(Value);
   If Error<>'' Then Exit;
   If Value='WHILE' Then Inc(WhilesCount) Else
   If Value='WEND' Then If WhilesCount=0 Then Break Else Dec(WhilesCount);
  end;
  If Line='' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Value:=Line;
  Value:=Calculate(Value);
  If Error<>'' Then Exit;
  If NumStr Then
  Begin
   Error:='Type mismatch';
   Exit;
  end;
  If StringToNumber(Value)<>0.0 Then
  Begin
   Whiles[Index].StartLine:=CurrentLine;
   Whiles[Index].EndLine:=SubIndex;
   Whiles[Index].Conditional:=ParseCalculate(Line);
   If Error<>'' Then Exit;
   Whiles[Index].IsFree:=False;
  end Else CurrentLine:=SubIndex;
 end Else If Name='WEND' Then
 Begin
  If Not RunMode Then
  Begin
   Error:='Cannot execute WHILE loop without program running';
   Exit;
  end;
  For Index:=1 To MaxWhiles+1 Do
  Begin
   If Index=MaxWhiles+1 Then
   Begin
    Error:='WEND without WHILE';
    Exit;
   end;
   If Not Whiles[Index].IsFree Then If Whiles[Index].EndLine=CurrentLine Then Break;
  end;
  Value:=Whiles[Index].Conditional;
  Value:=Calculate(Value);
  If Error<>'' Then Exit;
  If NumStr Then
  Begin
   Error:='Type mismatch';
   Exit;
  end;
  If StringToNumber(Value)<>0.0 Then CurrentLine:=Whiles[Index].StartLine Else
  Begin
   Whiles[Index].StartLine:=0;
   Whiles[Index].EndLine:=0;
   Whiles[Index].Conditional:='';
   Whiles[Index].IsFree:=True;
  end;
 end Else If Name='FROM' Then
 Begin
  If Not RunMode Then
  Begin
   Error:='Cannot execute the FROM loop without program running';
   Exit;
  end;
  FromVarName:=InName(Line);
  If Error<>'' Then Exit;
  Line:=Trim(Line);
  If Line='' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Case Line[1] Of
  '$':
   Begin
    Error:='Variable type mismatch';
    Exit;
   end;
  '!': Delete(Line,1,1);
  '@': Delete(Line,1,1);
  '#': Delete(Line,1,1);
  '%': Delete(Line,1,1);
  '&': Delete(Line,1,1);
  end;
  Line:=Trim(Line);
  If Copy(Line,1,1)<>'=' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Delete(Line,1,1);
  Result:=Calculate(Line);
  If Error<>'' Then Exit;
  If NumStr Then
  Begin
   Error:='Type mismatch';
   Exit;
  end;
  Value:=InName(Line);
  If Error<>'' Then Exit;
  If Value<>'TO' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Value:=Calculate(Line);
  If Error<>'' Then Exit;
  If NumStr Then
  Begin
   Error:='Type mismatch';
   Exit;
  end;
  For Index:=1 To MaxFroms+1 Do
  Begin
   If Index=MaxFroms+1 Then
   Begin
    Error:='Too many FROM''s';
    Exit;
   end;
   If Froms[Index].IsFree Then Break;
  end;
  FromsCount:=0;
  For SubIndex:=CurrentLine+1 To BASICLinesCount+1 Do
  Begin
   If SubIndex=BASICLinesCount+1 Then
   Begin
    Error:='FROM without NEXT';
    Exit;
   end;
   Name:=Lines[SubIndex].Line;
   Name:=InName(Name);
   If Error<>'' Then Exit;
   If Name='FROM' Then Inc(WhilesCount) Else
   If Name='NEXT' Then
   Begin
    Name:=Lines[SubIndex].Line;
    Meaning:=InName(Name);
    If Error<>'' Then Exit;
    Meaning:=InName(Name);
    If Error<>'' Then Exit;
    If (FromsCount=0) And (Meaning=FromVarName) Then Break Else Dec(FromsCount);
   end;
  end;
  If StringToNumber(Value)>=StringToNumber(Result) Then
  Begin
   Froms[Index].VarName:=FromVarName;
   Froms[Index].StartLine:=CurrentLine;
   Froms[Index].EndLine:=SubIndex;
   Froms[Index].BeginValue:=Trunc(StringToNumber(Result));
   Froms[Index].EndValue:=Trunc(StringToNumber(Value));
   Froms[Index].IsFree:=False;
   SetVar(FromVarName,False,Result);
  end Else CurrentLine:=SubIndex;
 end Else If Name='NEXT' Then
 Begin
  If Not RunMode Then
  Begin
   Error:='Cannot execute the FROM loop without program running';
   Exit;
  end;
  FromVarName:=InName(Line);
  If Error<>'' Then Exit;
  Line:=Trim(Line);
  If Line<>'' Then
  Case Line[1] Of
  '$':
   Begin
    Error:='Variable type mismatch';
    Exit;
   end;
  '!': Delete(Line,1,1);
  '@': Delete(Line,1,1);
  '#': Delete(Line,1,1);
  '%': Delete(Line,1,1);
  '&': Delete(Line,1,1);
  end;
  For Index:=1 To MaxFroms+1 Do
  Begin
   If Index=MaxFroms+1 Then
   Begin
    Error:='NEXT without FROM';
    Exit;
   end;
   If Not Froms[Index].IsFree Then If (Froms[Index].EndLine=CurrentLine) And (Froms[Index].VarName=FromVarName) Then Break;
  end;
  Result:=InVar(FromVarName,False);
  If StringToNumber(Result)=Froms[Index].EndValue Then
  Begin
   Froms[Index].VarName:='';
   Froms[Index].StartLine:=0;
   Froms[Index].EndLine:=0;
   Froms[Index].BeginValue:=0;
   Froms[Index].EndValue:=0;
   Froms[Index].IsFree:=True;
  end Else
  Begin
   SetVar(FromVarName,False,NumberToString(StringToNumber(Result)+1));
   CurrentLine:=Froms[Index].StartLine;
  end;
 end Else If Name='EXIT' Then
 Begin
  If Not RunMode Then
  Begin
   Error:='Cannot EXIT from loop without program is running';
   Exit;
  end;
  Name:=InName(Line);
  If Error<>'' Then Exit;
  If Name='WHILE' Then
  Begin
   For Index:=1 To MaxWhiles+1 Do
   Begin
    If Index=MaxWhiles+1 Then
    Begin
     Error:='EXIT WHILE without WHILE';
     Exit;
    end;
    If Not Whiles[Index].IsFree Then
    If (CurrentLine>=Whiles[Index].StartLine) And (CurrentLine<=Whiles[Index].EndLine) Then Break;
   end;
   CurrentLine:=Whiles[Index].EndLine;
   Whiles[Index].StartLine:=0;
   Whiles[Index].EndLine:=0;
   Whiles[Index].Conditional:='';
   Whiles[Index].IsFree:=True;
  end Else If Name='FROM' Then
  Begin
   For Index:=1 To MaxFroms+1 Do
   Begin
    If Index=MaxFroms+1 Then
    Begin
     Error:='EXIT FROM without FROM';
     Exit;
    end;
    If Not Froms[Index].IsFree Then
    If (CurrentLine<=Froms[Index].StartLine) And (CurrentLine>=Froms[Index].EndLine) And (Froms[Index].VarName=FromVarName) Then Break;
   end;
   CurrentLine:=Froms[Index].EndLine;
   Froms[Index].VarName:='';
   Froms[Index].StartLine:=0;
   Froms[Index].EndLine:=0;
   Froms[Index].BeginValue:=0;
   Froms[Index].EndValue:=0;
   Froms[Index].IsFree:=True;
  end Else Error:='Syntax error';
 end Else If Name='IF' Then
 Begin
  Result:=Calculate(Line);
  If Error<>'' Then Exit;
  If NumStr Then
  Begin
   Error:='Type mismatch';
   Exit;
  end;
  Value:=InName(Line);
  If Error<>'' Then Exit;
  If Value<>'THEN' Then
  Begin
   Error:='Syntax error';
   Exit;
  end;
  Name:=ParseRunLine(Line);
  If Error<>'' Then Exit;
  IfElse:=False;
  Line:=Trim(Line);
  If Line<>'' Then
  Begin
   IfElse:=True;
   Value:=InName(Line);
   If Error<>'' Then Exit;
   If Value<>'ELSE' Then
   Begin
    Error:='Syntax error';
    Exit;
   end;
   Meaning:=ParseRunLine(Line);
   If Error<>'' Then Exit;
  end;
  If StringToNumber(Result)<>0.0 Then RunLine(Name) Else If IfElse Then RunLine(Meaning);
 end Else If Name='HELP' Then Help Else If Name='SCREEN' Then
 Begin
  Name:=InName(Line);
  If Error<>'' Then Exit;
  If Name='BW40' Then TextMode(Bw40) Else
  If Name='CO40' Then TextMode(Co40) Else
  If Name='BW80' Then TextMode(Bw80) Else
  If Name='CO80' Then TextMode(Co80) Else
  If Name='MONO' Then TextMode(Mono) Else Error:='Syntax error';
 end Else Error:='Unknown statement';
end;
Procedure Main;
Var
  BASICLine     : String;
  LineNumber    : Word;
  Index         : Word;
  WorkFile      : File;
  FileAttribute : Word;
  LineLength    : Byte;
  Count         : LongInt;
  LineCount     : Word;
Begin
 If (Lo(DOSVersion)<3) And (Hi(DOSVersion)<30) Then
 Begin
  WriteLn('This program required DOS version 3.30 or above.');
  Exit;
 end;
 WriteLn('Loading program lines. Please waith...');
 ClearAll(True);
 Assign(WorkFile,ParamStr(0));
 GetFAttr(WorkFile,FileAttribute);
 SetFAttr(WorkFile,0);
 ReSet(WorkFile,1);
 If IOResult<>0 Then
 Begin
  SetFAttr(WorkFile,FileAttribute);
  WriteLn('Cannot open program file ('+ParamStr(0)+'.).');
  Exit;
 end;
 LineCount:=0;
 Seek(WorkFile,SizeOfExecutable);
 If IOResult<>0 Then
 Begin
  Close(WorkFile);
  SetFAttr(WorkFile,FileAttribute);
  WriteLn('Cannot seek program file ('+ParamStr(0)+'.).');
  Exit;
 end;
 Repeat
  BlockRead(WorkFile,LineLength,1,Count);
  If IOResult<>0 Then
  Begin
   Close(WorkFile);
   SetFAttr(WorkFile,FileAttribute);
   WriteLn('Cannot read from program file ('+ParamStr(0)+'.).');
   Exit;
  end;
  If Count=0 Then Break;
  BlockRead(WorkFile,Ptr(Seg(BASICLine),Ofs(BASICLine)+1)^,LineLength,Count);
  If IOResult<>0 Then
  Begin
   Close(WorkFile);
   SetFAttr(WorkFile,FileAttribute);
   WriteLn('Cannot read from program file ('+ParamStr(0)+'.).');
   Exit;
  end;
  BASICLine[0]:=Chr(LineLength);
  If LineCount=MaxLines Then
  Begin
   Close(WorkFile);
   SetFAttr(WorkFile,FileAttribute);
   WriteLn('Too many BASIC lines.');
   Exit;
  end;
  Inc(LineCount);
  BASICLine:=Trim(BASICLine);
  LineNumber:=Trunc(InNumber(BASICLine));
  If Error<>'' Then
  Begin
   Close(WorkFile);
   SetFAttr(WorkFile,FileAttribute);
   WriteLn(Error+'.');
   Exit;
  end;
  If (LineNumber<1) Or (LineNumber>MaxLines) Then
  Begin
   Close(WorkFile);
   SetFAttr(WorkFile,FileAttribute);
   WriteLn('Invalid line number.');
   Exit;
  end;
  BASICLine:=Trim(BASICLine);
  If BASICLine='' Then
  Begin
   Close(WorkFile);
   SetFAttr(WorkFile,FileAttribute);
   WriteLn('Invalid line.');
   Exit;
  end;
  If Not ((Ord(UpCase(BASICLine[1]))>(Ord('A')-1)) And (Ord(UpCase(BASICLine[1]))<(Ord('Z')+1))) Then
  Begin
   Close(WorkFile);
   SetFAttr(WorkFile,FileAttribute);
   WriteLn('Invalid line.');
   Exit;
  end;
  BASICLine:=ParseRunLine(BASICLine);
  If Error<>'' Then
  Begin
   Close(WorkFile);
   SetFAttr(WorkFile,FileAttribute);
   WriteLn(Error+'.');
   Exit;
  end;
  If BASICLinesCount=0 Then
  Begin
   Inc(BASICLinesCount);
   Lines[BASICLinesCount].Line:=BASICLine;
   Lines[BASICLinesCount].LineNumber:=LineNumber;
  end Else
  Begin
   For Index:=1 To BASICLinesCount+1 Do
   Begin
    If Index=BASICLinesCount+1 Then
    Begin
     If BASICLinesCount=MaxLines Then
     Begin
      Close(WorkFile);
      SetFAttr(WorkFile,FileAttribute);
      WriteLn('Too many BASIC lines.');
      Exit;
     end;
     Inc(BASICLinesCount);
     Lines[BASICLinesCount].Line:=BASICLine;
     Lines[BASICLinesCount].LineNumber:=LineNumber;
     SortLines;
     Break;
    end;
    If Lines[Index].LineNumber=LineNumber Then
    Begin
     Lines[Index].Line:=BASICLine;
     Break;
    end;
   end;
  end;
 Until False;
 Close(WorkFile);
 SetFAttr(WorkFile,FileAttribute);
 WriteLn('Running...');
 If BASICLinesCount=0 Then
 Begin
  WriteLn('Nothing to run.');
  Exit;
 end;
 RunMode:=True;
 CurrentLine:=1;
 Repeat
  If TraceMode Then Write('['+NumberToString(Lines[CurrentLine].LineNumber)+']');
  BASICLine:=Lines[CurrentLine].Line;
  RunLine(BASICLine);
  If Error<>'' Then Break;
  Inc(CurrentLine);
 Until (CurrentLine>BASICLinesCount) Or (Not RunMode);
 If Error<>'' Then WriteLn('FATAL! Error: '+Error+'.');
end;
Begin
 WriteLn;
 WriteLn('GNUBasic Run - Time, Copyright (C) 2003 Sandul Yura Valentinovich.');
 WriteLn('(C) Wednesday, 5 March 2003 year.');
 WriteLn('All rights reserved.');
 WriteLn('GNUBasic comes with ABSOLUTELY NO WARRANTY; for details, see the GNU General');
 WriteLn('Public License, version 2. This is free software, and you are welcome to');
 WriteLn('redistribute it under certain conditions from the GNU General Public License.');
 WriteLn('***************************************************************');
 WriteLn;
 Main;
end.