{
}
unit teapro91; { Copyright (c) 1997-2007 by D La Pierre Ballard }
{ Teapro9 uses the OpenTea technology to be simple and solid. }
{ Teapro9 uses the teaquad technology to find larger prime numbers. }
{ In today's world, we need computer software that actually works. }
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls,
Forms, Dialogs, Menus, StdCtrls, Math;
type
TForm1 = class(TForm)
MainMenu1: TMainMenu;
btn_start: TButton;
menu_help: TMenuItem;
edit_input: TEdit;
menu_file: TMenuItem;
menu_view: TMenuItem;
menu_About: TMenuItem;
menu_Variables: TMenuItem;
menu_ProgramCode: TMenuItem;
menu_debug: TMenuItem;
menu_open: TMenuItem;
menu_exit: TMenuItem;
label_show: TLabel;
Pause1: TMenuItem;
menu_generalhelp: TMenuItem;
menu_help_commands: TMenuItem;
menu_help_running: TMenuItem;
{ programmer functions }
function fnd_modulus(
const dp_number : double;
const dp_divisor : double) : double;
function fnb_comm_dift : boolean;
function fnb_comm_sift : boolean;
function fnb_more(const ps1 : string) : boolean;
function fnd_decimal_eval(const pbyte_1 : byte) : double;
function fni_decimal_eval(const pbyte_1 : byte) : integer;
function fns_eliminate_blanks(const ps_rec : string) : string;
function fns_from_double(
const pd_num : double;
const pbyte_commas : byte) : string;
function fns_link_literal_numbers(const ps_rec : string) : string;
function fns_link_literal_strings(const ps_rec : string) : string;
function fni_link_last_endi(const pi_rec : integer) : integer;
function fns_blank_escapes(const ps1 : string) : string;
function fni_pattern(const pi_char : integer) : integer;
function fns_string_eval(const pbyte_1 : byte) : string;
function fns_string_parse(const ps1 : string) : string;
function fns_subroutine(const pi_line : integer) : string;
function fns_tpline_format(const ps1 : string) : string;
function fns_tplines_to_show(const pi1, pi2 : integer) : string;
function fni_yesnocancel(const ps1 : string) : integer;
{ programmer procedures }
procedure sub_about;
procedure sub_commands_to_int;
procedure sub_debug;
procedure sub_double_from_string(
const ps1 : string;
var pe2 : double;
var pb3 : boolean);
procedure sub_error_in_prog_line(const ps1 : string;
const pi2 : integer);
procedure sub_more_or_halt(const ps1 : string);
procedure sub_get_program_name;
procedure sub_help_commands;
procedure sub_help_general;
procedure sub_help_running;
procedure sub_initialize;
procedure sub_tpprog_build_array;
procedure sub_tpline_perform_new;
procedure sub_tpline_process;
procedure sub_tpline_split(var s_rec1, s_rec2 : string);
procedure sub_format_lines;
procedure sub_link_first_parameter;
procedure sub_link_dift_sift;
procedure sub_link_variable_names;
procedure sub_link_subroutines;
procedure sub_memo_show(const ps1 : string; const pbyte_2 : byte);
procedure sub_old_to_new;
procedure sub_prog_process;
procedure sub_program_error(const ps1 : string);
procedure sub_store_decimal(const pbyte_1 : byte; const pd_1 : double);
procedure sub_store_string(const pbyte_1 : byte; const ps_1 : string);
procedure sub_terminate;
procedure sub_view_code;
procedure sub_validate_commands;
procedure sub_validate_variables;
procedure sub_validate_semicolon(const pbyte_1 : byte);
procedure sub_validate_variable(
const pi1 : integer;
const ps2 : string);
procedure sub_validate_append(const pi1 : integer);
procedure sub_variables;
procedure sub_variables_info;
{ command procedures below }
procedure sub_comm_array(const pbyte_1 : byte);
procedure sub_comm_dchs;
procedure sub_comm_dfac;
procedure sub_comm_dfak;
procedure sub_comm_dpks;
procedure sub_comm_dpow;
procedure sub_comm_dset;
procedure sub_comm_dsin(const pbyte_1 : byte);
procedure sub_comm_dsys;
procedure sub_comm_dtof;
procedure sub_comm_dtos(const pbyte_1 : byte);
procedure sub_comm_dtoi(const pbyte_1 : byte);
procedure sub_comm_ends;
procedure sub_comm_evar;
procedure sub_comm_file(const pbyte_1 : byte);
procedure sub_comm_finp;
procedure sub_comm_fout;
procedure sub_comm_frea;
procedure sub_comm_fwri;
procedure sub_comm_fsip;
procedure sub_comm_fapp(const pbyte_1 : byte);
procedure sub_comm_sapp;
procedure sub_comm_sbak;
procedure sub_comm_schd;
procedure sub_comm_schs;
procedure sub_comm_scnt;
procedure sub_comm_scod;
procedure sub_comm_sdat;
procedure sub_comm_sdel;
procedure sub_comm_sdot;
procedure sub_comm_scut;
procedure sub_comm_sfix(const pbyte_1 : byte);
procedure sub_comm_sinp(const pbyte_1 : byte);
procedure sub_comm_sins;
procedure sub_comm_sisc;
procedure sub_comm_sisd;
procedure sub_comm_sist;
procedure sub_comm_slen(const pbyte_1 : byte);
procedure sub_comm_slok;
procedure sub_comm_soff;
procedure sub_comm_sout(const pbyte_1 : byte);
procedure sub_comm_spar;
procedure sub_comm_spkd;
procedure sub_comm_sisp;
procedure sub_comm_srep;
procedure sub_comm_sset;
procedure sub_comm_ssor;
procedure sub_comm_ssys;
procedure sub_comm_sswp;
procedure sub_comm_stod;
procedure sub_comm_stoe;
procedure sub_comm_stoi(const pbyte_1 : byte);
procedure sub_comm_itod;
procedure sub_comm_itos;
{ end programmer functions and subroutines }
procedure menu_exitClick(Sender: TObject);
procedure FormActivate(Sender: TObject);
procedure btn_startClick(Sender: TObject);
procedure edit_inputKeyPress(Sender: TObject; var Key: Char);
procedure About1Click(Sender: TObject);
procedure menu_ProgramCodeClick(Sender: TObject);
procedure menu_VariablesClick(Sender: TObject);
procedure menu_debugClick(Sender: TObject);
procedure FormResize(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure menu_openClick(Sender: TObject);
procedure Pause1Click(Sender: TObject);
procedure menu_generalhelpClick(Sender: TObject);
procedure menu_help_commandsClick(Sender: TObject);
procedure menu_help_runningClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
const
{ programmer defined constants }
nl = Chr(10);
var
Form1: TForm1;
fs_tpprog_name : string;
fi_tpline_last : integer;
fd_total_lines : double;
fs_subr_name : string;
fi_max_length : integer;
fi_comment_ct : integer;
fi_subroutine_ct : integer;
fi_line : integer;
{ for input from edit_input }
fi_input : integer;
fs_input : string;
fb_string_input : boolean;
fb_program_loop : boolean;
fb_terminate : boolean;
fb_error : boolean;
{ debug }
fb_debug : boolean;
fsa_debug : array[1..16] of string;
{ these hold the variables for tpprog }
fea_var : array[1..2000] of double;
fsa_var : array[1..4000] of string;
fi_max_dvar : integer;
fi_max_svar : integer;
fea_array : array[1..8000] of double;
fsa_array : array[1..2000] of string;
fi_max_darray : integer;
fi_max_sarray : integer;
fi_dvar : integer;
fi_svar : integer;
fd_begin_time : double;
{ show on memo_show stack }
fsa_show : array[1..35] of string;
fi_show_lines : integer;
fb_show : boolean;
{ these hold the program and the linking }
fsa_tpline : array[1..15000] of string;
fs_tpline : string;
fi_tpline : integer;
fbytea_command : array[0..15000] of byte;
fia_link : array[1..15000] of integer;
fi_link : integer;
{ subroutine stack }
fia_sub : array[1..1000] of integer;
fii_sub : integer;
fi_max_sub : integer;
fia_primes : array[1..1000] of integer;
{ string dynamic memory stack }
fia_delta_s : array[1..1000] of integer;
fii_delta_s : integer;
fi_delta_s : integer;
fi_max_delta_s : integer;
{ decimal dynamic memory stack }
fia_delta_d : array[1..1000] of integer;
fii_delta_d : integer;
fi_delta_d : integer;
fi_max_delta_d : integer;
{ these hold the program information }
fi_prog_lines : integer;
fi_global_strings : integer;
fi_global_decimals : integer;
fi_literal_strings : integer;
fi_literal_decimals : integer;
{ untyped file processing }
fs_filename_1 : string;
fi_file_byte : integer;
implementation
{$R *.DFM}
procedure TForm1.sub_about;
{ updated 2007/01/20, 2007/01/19, 2006/08/24,
2005/09/07, 2005/04/29, 2005/03/29, 2005/03/22, 2004/04/17 }
var
sz : string;
begin
sz := '';
sz := sz
+ 'This computer program is the Teapro9 interpreter, '
+ 'teapro9.exe, build 364, 2007/10/16. '
+ 'which interprets the Teapro programming language. '
+ 'The Teapro programming language, '
+ 'was invented on 14-DEC-1997 and utilizes the '
+ 'OpenTea Technology. '
+ 'The Teapro9 interpreter was begun on 14-DEC-1997.' + nl + nl
+ 'The Teapro9 interpreter was programmed in '
+ 'Delphi 2.01, Developer Edition, '
+ 'copyright (c) 1983-1996, Borland International, Inc.' + nl + nl
+ 'The Teapro9 interpreter, teapro9.exe, may be used for free '
+ 'by anyone, but there is no warranty of any kind whatsoever '
+ 'on teapro9.exe.' + nl + nl
+ 'The Teapro programming language may be used for free '
+ 'by anyone, but there is no warranty of any kind whatsoever '
+ 'on Teapro.' + nl + nl
+ 'The Teapro programming language, teapro9.exe, '
+ 'the OpenTea Technology, and the teaquad method '
+ 'are all copyright (c) 1997-2007 '
+ 'by D La Pierre Ballard.' + nl + nl
+ 'Per the OpenTea technology Teapro is simple and solid. ' + nl + nl
+ 'In today''s world, we need computer software that actually works.'
+ nl + nl
+ 'Please e-mail your comments to: dlb@teapro.com' + nl + nl
+ 'Time at start='
+ DateTimeToStr(fd_begin_time) + nl
+ 'Lines done='
+ FloatToStrF(fd_total_lines, ffNumber, 16, 0) + nl
+ Application.Exename;
ShowMessage(sz);
end; { sub_about }
procedure TForm1.sub_tpline_process;
{ updated 2007/04/20, 2007/01/20, 2007/01/19 }
{ 2006/04/28, 2006/04/14, 2005/04/29, 2005/03/22, 2003/09/15 }
{ process the Teapro program }
var
iz : integer;
begin
{ if in input mode process the input }
if fb_string_input then sub_comm_sinp(5);
{ this is set to false when sub_terminate is called }
iz := 0;
fb_program_loop := true;
while fb_program_loop do
begin
{ inner loop }
Inc(iz);
if (iz > 1000) then
begin
Application.ProcessMessages;
iz := 0;
end;
fd_total_lines := fd_total_lines + 1;
if fb_debug then sub_debug;
{ perform the program line }
sub_tpline_perform_new;
{ increment to the next fi_tpline }
Inc(fi_tpline);
end; { fb_program_loop }
{ clear the edit_input }
edit_input.text := '';
end; { sub_tpline_process }
procedure TForm1.sub_tpline_perform_new;
{ updated 2007/04/15, 2007/04/14, 2007/01/19, 2006/06/02, 2006/05/12 }
{ 2006/04/29, 2006/04/14, 2005/06/20, 2005/03/22, 2004/10/19 }
{ perform the action, the new version }
var
s_string : string;
byte_command : byte;
begin
{ 12345678901234567890123 }
{ MOVE 12345n12345n12345n }
fs_tpline := fsa_tpline[fi_tpline];
byte_command := fbytea_command[fi_tpline];
fi_link := fia_link[fi_tpline];
{ Showmessage(fs_tpline + ' ' + IntToStr(byte_command)); }
{ s_commands := ''
+ 'DABS,DARC,DCH$,DDEC,DED$,DFAC,DIF1,'
+ 'DIFT,DINC,DLOG,DPK$,DPOW,DRAN,DROU,'
+ 'DSEC,DSET,DSIN,DTO$,DTOF,DTOI,DTRU,DWHI,'
+ 'ELSE,ENDI,ENDP,ENDS,ENDW,ESUB,XXXX,EVAR,'
+ 'ITO$,ITOD,'
+ '$APP,$BAK,$BES,$CH$,$CHD,$CLO,$CNT,$COD,$CUP,'
+ '$CUT,$DAT,$DEL,$DOT,$IF1,$IFT,$INP,$INS,$ISC,'
+ '$ISD,$ISP,$IST,$LEN,$LOK,$OFF,$OUT,$PAR,$PKD,'
+ '$REP,$SET,$SHO,$SOR,$SWP,$SYS,$TLO,$TOD,$TOI,'
+ '$TRB,$TRL,$TRR,$TUP,$WHI,'
+ 'FDAT,FDEL,FLEN,FREN,'
+ 'FINP,FOUT,'
+ 'FSIP,FAPP,FADD,'
+ 'FREA,FWRI,'
+ 'QAPP,QINP,QOUT,QSET,QTOI,'
+ 'XXXX,XXXX,XXXX,XXXX,XXXX,'
+ 'ARRZ,ARRB,ADDI,DSYS,DBAD,'
+ '$TOE,$HSH,DBUG,DFAK,GOTO,'
+ 'GTAG,SUBR,VARI';
}
Case byte_command of
1 : sub_store_decimal(6, Abs(fnd_decimal_eval(13))); { DABS }
2 : sub_comm_dsin(4); { DARC arc sine }
3 : sub_comm_dchs;
4 : { DDEC }
begin
if (fs_tpline[11] = 'D') then Inc(fi_link, fi_delta_d);
fea_var[fi_link] := fea_var[fi_link] - 1;
end;
5 : sub_comm_dtos(1); { DED$ }
6 : sub_comm_dfac;
7 : { DIF1 }
begin
if not fnb_comm_dift then Inc(fi_tpline);
end;
8 : { DIFT }
begin
if not fnb_comm_dift then fi_tpline := fi_link;
end;
9 : { DINC }
begin
if (fs_tpline[11] = 'D') then Inc(fi_link, fi_delta_d);
fea_var[fi_link] := fea_var[fi_link] + 1;
end;
10 : sub_comm_dsin(5); { log10 }
11 : sub_comm_dpks;
12 : sub_comm_dpow;
13 : sub_store_decimal(6, Random); { DRAN }
14 : sub_comm_dsin(1); { drou }
15 : { DSEC }
begin
{ 86400 = 60 * 60 * 24 and is the seconds / day }
sub_store_decimal(6, Now * 86400);
end;
16 : sub_comm_dset;
17 : sub_comm_dsin(3); { DSIN sine }
18 : sub_comm_dtos(0); { DTO$ }
19 : sub_comm_dtof; { DTOF }
20 : sub_comm_dtoi(1); { DTOI }
21 : sub_comm_dsin(2); { dtru }
22 : { DWHI }
begin
if not fnb_comm_dift then fi_tpline := fi_link;
end;
23 : { ELSE }
begin
fi_tpline := fi_link;
end;
24 : { ENDI }
begin
fi_tpline := fi_link;
end;
25 : sub_terminate;
26 : sub_comm_ends;
27 : { ENDW }
begin
fi_tpline := fi_link;
end;
28 : { ESUB }
begin
{ push into the sub stack where we have come from }
Inc(fii_sub);
if (fii_sub > fi_max_sub) then fi_max_sub := fii_sub;
fia_sub[fii_sub] := fi_tpline;
fi_tpline := fia_link[fi_tpline];
end;
30 : sub_comm_evar; { EVAR }
31 : sub_comm_itos;
32 : sub_comm_itod;
33 : sub_comm_sapp;
34 : sub_comm_sbak;
35 : sub_comm_sfix(3); { $BES }
36 : sub_comm_schs;
37 : sub_comm_schd;
38 : sub_comm_sfix(1); { $CLO }
39 : sub_comm_scnt;
40 : sub_comm_scod;
41 : sub_comm_sfix(2); { $CUP }
42 : sub_comm_scut;
43 : sub_comm_sdat;
44 : sub_comm_sdel;
45 : sub_comm_sdot;
46 : { $IF1 }
begin
if not fnb_comm_sift then Inc(fi_tpline);
end;
47 : { $IFT }
begin
if not fnb_comm_sift then fi_tpline := fi_link;
end;
48 : sub_comm_sinp(1); { $INP }
49 : sub_comm_sins;
50 : sub_comm_sisc;
51 : sub_comm_sisd;
52 : sub_comm_sisp;
53 : sub_comm_sist;
54 : sub_comm_slen(1); { $LEN }
55 : sub_comm_slok;
56 : sub_comm_soff;
57 : sub_comm_sout(1); { $OUT }
58 : sub_comm_spar;
59 : sub_comm_spkd;
60 : sub_comm_srep;
61 : sub_comm_sset;
62 : sub_comm_sout(2); { $SHO }
63 : sub_comm_ssor; { $SOR }
64 : sub_comm_sswp; { $SWP }
65 : sub_comm_ssys;
66 : sub_comm_sfix(7); { $TLO }
67 : sub_comm_stod;
68 : sub_comm_stoi(1); { $TOI }
69 : sub_comm_sfix(4); { $TRB }
70 : sub_comm_sfix(5); { $TRL }
71 : sub_comm_sfix(6); { $TRR }
72 : sub_comm_sfix(8); { $TUP }
73 : { $WHI }
begin
if not fnb_comm_sift then fi_tpline := fi_link;
end;
74 : sub_comm_file(1); { FDAT }
75 : sub_comm_file(2); { FDEL }
76 : sub_comm_file(3); { FLEN }
77 : sub_comm_file(4); { FREN }
78 : sub_comm_finp;
79 : sub_comm_fout;
80 : sub_comm_fsip;
81 : sub_comm_fapp(1); { FAPP }
82 : sub_comm_fapp(2); { FADD }
83 : sub_comm_frea;
84 : sub_comm_fwri;
95 : sub_comm_array(1); { ARRZ }
96 : sub_comm_array(2); { ARRB }
97 : sub_comm_dtoi(2); { ADDI }
98 : sub_comm_dsys; { DSYS }
99 : { DBAD }
begin
if fnb_comm_dift then
sub_program_error('bad data error');
end;
100: sub_comm_stoe; { $TOE }
101: sub_comm_slen(2); { $HSH }
102 : { DBUG }
begin
if fb_debug then fb_debug := false
else fb_debug := true;
end;
103: sub_comm_dfak; { DFAK }
104: fi_tpline := fi_link; { GOTO }
105: ;{ GTAG }
{ SUBR,VARI should not occur }
else
sub_debug;
end;
end; { sub_tpline_perform_new }
procedure TForm1.sub_debug;
{ updated 2003/12/15 }
var
s_out : string;
b_good : boolean;
iz, iy, ix : integer;
sz : string;
begin
if (fi_tpline < 1) then fi_tpline := 1;
{ move lines performed up one twice }
for iz := 1 to 15 do fsa_debug[iz] := fsa_debug[Succ(iz)];
fsa_debug[15] := IntToStr(fi_tpline) + ': '
+ fsa_tpline[fi_tpline];
{ prep dialog box output }
s_out := '';
for iz := 1 to 16 do
begin
if (Length(fsa_debug[iz]) > 0) then
s_out := s_out + fsa_debug[iz] + nl;
end;
{ get variables in fsa_tpline }
s_out := s_out + nl;
fs_tpline := fsa_tpline[fi_tpline];
for iz := 1 to Length(fs_tpline) do
begin
sz := Copy(fs_tpline, iz, 5);
b_good := true;
for iy := 1 to 5 do
begin
if (Pos(sz[iy], '0123456789') = 0) then b_good := false;
end;
if b_good then
begin
sz := fns_string_eval(iz);
if (Length(sz) > 50) then sz := Copy(sz, 1, 50);
s_out := s_out + Copy(fs_tpline, iz, 6) + '=' + sz + nl;
end;
end;
{ add on other information }
s_out := s_out
+ nl
+ fns_subroutine(fi_tpline)
+ ', fi_tpline=' + IntToStr(fi_tpline)
+ ', fi_link=' + IntToStr(fia_link[fi_tpline])
+ ', fi_delta_d=' + IntToStr(fi_delta_d)
+ ', fi_delta_s=' + IntToStr(fi_delta_s) + nl
+ 'global decimals='
+ IntToStr(fi_global_decimals + fi_literal_decimals)
+ ', global strings='
+ IntToStr(fi_global_strings + fi_literal_strings)
+ ', Lines done = '
+ FloatToStrF(fd_total_lines, ffNumber, 16, 0)
+ nl + nl
+ 'Yes=Continue, No=Variables, Ok=Code, Cancel=Debug off, '
+ 'Abort=End Program';
iz := MessageDlg(s_out, mtCustom, [mbYes,mbNo,mbOk,mbCancel,mbAbort], 0);
if (iz = mrNo) then sub_variables;
if (iz = mrOk) then sub_view_code;
if (iz = mrCancel) then fb_debug := false;
if (iz = mrAbort) then sub_terminate;
end; { sub_debug }
procedure TForm1.sub_program_error(const ps1 : string);
{ updated 2004/05/17 }
var
i_beg, i_end : integer;
iz : integer;
sz : string;
begin
sz := 'program error: ' + ps1 + ' in following line.' + nl
+ IntToStr(fi_tpline) + ': '
+ fsa_tpline[fi_tpline] + nl;
i_beg := fi_tpline - 8;
i_end := fi_tpline + 8;
sz := sz + nl + fns_tplines_to_show(i_beg, i_end);
sz := sz
+ 'ok = skip this line, '
+ 'yes = debug, '
+ 'abort = terminate the program.';
iz := MessageDlg(sz, mtCustom, [mbOk,mbYes,mbAbort], 0);
fb_error := true;
if (iz = mrAbort) then sub_terminate;
if (iz = mrYes) then sub_debug;
end; { sub_program_error }
procedure TForm1.sub_help_general;
{ updated 2006/06/11, 2006/06/09, 2004/04/24 }
var
iz : integer;
s_dashline : string;
sz : string;
b_more : boolean;
begin
s_dashline := nl + StringOfChar('-', 20) + nl;
b_more := true;
sz := '';
sz := sz
+ 'A Teapro program is a text file which has been '
+ 'created using any editor or word processor. '
+ 'The extension on the name of a Teapro program can be .tea '
+ 'or since it is a text file .txt will work too. '
+ 'The Teapro programming language is an extremely small '
+ 'and simple language which is '
+ 'interpreted rather than compiled. '
+ 'The Teapro9 interpreter, teapro9.exe, is small and uses '
+ 'few resources. '
+ 'However, complex programming can be done easily in '
+ 'Teapro since Teapro has very powerful '
+ 'string, number, file handling and control commands. '
+ 'A Teapro program may have as many as a total of '
+ '15000 lines of code. '
+ 'The Teapro language follows the OpenTea technology '
+ 'of simplicity, safety, and solidity.';
if b_more then b_more := fnb_more(sz);
sz := '';
sz := sz
+ 'A Teapro program consists of lines each of which '
+ 'has a Teapro command which is usually '
+ 'followed by some comma separated parameters. '
+ 'The parameters are variables, constants and operators. '
+ 'Variables can either be global or local. '
+ 'A global variable '
+ 'can be seen by all of the subroutines in the Teapro '
+ 'program. '
+ 'Local variables can be seen only in the subroutine '
+ 'in which they are defined. '
+ 'Global variables are defined at the top of a Teapro '
+ 'program. '
+ 'Local variables are defined at the top of the '
+ 'subroutine in which they are used. '
+ 'In both cases the '
+ 'command used to create the variables is VARI. '
+ s_dashline
+ 'There are two types of variables: string and decimal. '
+ 'Global string variables begin with "sg_" while global '
+ 'decimal variables begin with "dg_". '
+ 'Local string variables begin with "s_", '
+ 'and local decimal variables '
+ 'begin with "d_". '
+ 'In each case, the rest of the variable name can be '
+ 'letters or numbers. '
+ 'A variable name must be from 5 to '
+ '64 long. '
+ 'Variable names which overlap within a subroutine '
+ 'are not allowed. For example: d_byte and d_bytes '
+ 'cannot both be used in the same subroutine. '
+ s_dashline
+ 'In Teapro programs '
+ 'commands and variables may be upper or lower case since '
+ 'case is not significant. '
+ 'In the examples which follow upper case is used for '
+ 'emphasis for Teapro commands but variables are in lower case. '
+ 'Most Teapro programmers use all lower case. '
+ 'Spaces may be placed between the parameters to '
+ 'make the lines more readable. '
+ 'Indentation may be used for lines inside of control structures '
+ 'to make the appearance of the program better.';
if b_more then b_more := fnb_more(sz);
sz := '';
sz := sz
+ 'Here is a small Teapro program that uses the global decimal '
+ 'variable dg_count to count the number of times that the '
+ 'local variable string s_line is shown on the screen. '
+ 'The variable s_line is set to the string "Hello there" '
+ 'and is shown three '
+ 'times each time the subroutine sub_show is called. '
+ 'In the subroutine sub_show the local '
+ 'decimal variable d_decimal '
+ 'is used to count the number of times the while loop loops. '
+ 'The string is shown a total of six times and then the '
+ 'count is shown also. ' + nl + nl
+ 'VARI dg_count' + nl
+ 'sub_main' + nl
+ 'ENDP' + nl
+ 'SUBR sub_main' + nl
+ ' VARI s_string' + nl
+ ' dg_count = 0' + nl
+ ' sub_show' + nl
+ ' sub_show' + nl
+ ' $INP s_string, "The count is=" + dg_count' + nl
+ 'ENDS sub_main' + nl
+ 'SUBR sub_show' + nl
+ ' VARI s_line, d_decimal' + nl
+ ' s_line = "Hello there"' + nl
+ ' d_decimal = 0' + nl
+ ' DWHI d_decimal < 3' + nl
+ ' $OUT s_line' + nl
+ ' DINC d_decimal' + nl
+ ' DINC dg_count' + nl
+ ' ENDW' + nl
+ 'ENDS sub_show';
if b_more then b_more := fnb_more(sz);
sz := '';
sz := sz
+ 'In the examples and help showing the different '
+ 'commands in the Teapro programming language some rather general '
+ 'names are used for variables. '
+ 'Names like s_string, s_whole, s_part, s_new, and s_old '
+ 'are used for string variables. '
+ 'Names like d_decimal, d_long and d_byte '
+ 'are used for decimal variables. '
+ 'In some cases a variable used as a parameter in a Teapro '
+ 'command gives a value to be used when the command '
+ 'is performed, '
+ 'in some cases a variable recieves a value when '
+ 'the command is performed, and in '
+ 'some cases a variable both gives '
+ 'and recieves a value.'
+ s_dashline
+ 'String variables may be upto 60,000,000 bytes in length, '
+ 'if the memory of your computer will handle that. '
+ 'Trying to create a string longer than that will '
+ 'cause an error.'
+ s_dashline
+ 'Decimal numbers may be positive or negative with up to '
+ '15 digits and with the decimal point '
+ 'almost anywhere. '
+ 'Decimal literals ie. 123.45 or 5 or +1.5 or -12 etc. '
+ 'may be preceded by a plus + sign or a negative - sign. '
+ 'The + or - sign is considered to be part of the literal '
+ 'number. '
+ 'A numeric variable cannot be preceded by a + or - sign '
+ 'to change its sign.' + nl
+ 'proper is: d_any = d_any * d_dot * -1' + nl
+ 'improper is: d_any = d_any * - d_dot'
+ s_dashline
+ 'A literal value may be used for a parameter instead of a '
+ 'variable if that parameter '
+ 'gives a value to be used by the Teapro command rather '
+ 'than that that parameter receives a value.' + nl
+ 'String literals are enclosed in either double quotes '
+ 'ie. "string" or number signs ie. #string#.';
if b_more then b_more := fnb_more(sz);
sz := '';
sz := sz
+ 'Notice in the Teapro commands that in the command '
+ 'name movement is usually left to right. '
+ 'However, in the parameters of the '
+ 'command, movement is usually right to left. '
+ 'For example, consider the command $TOD.'
+ 'In the command name, it is string to decimal, left to right. '
+ 'In the parameters, $TOD d_decimal, s_string, '
+ 'the movement is from s_string to d_decimal '
+ 'or from right to left. '
+ 'This rule will help you '
+ 'to understand many of the Teapro commands.'
+ s_dashline
+ 'If the command is $APP,$OUT,$SHO, or $INP then the right '
+ 'most parameter may be a string append expression. '
+ 'A string assignment command is the same. '
+ 'A string append expression example is to use "c" + "at" '
+ 'instead of "cat". The terms in a string append expression '
+ 'may be string literals, string variables, decimal literals, '
+ 'or decimal variables.';
if b_more then b_more := fnb_more(sz);
sz := '';
sz := sz
+ 'One thing is very different in Teapro than in other '
+ 'languages: numerical assignment commands are evaluated '
+ 'strictly left to right in Teapro whereas in other languages '
+ 'the are evaluated as though they were algebraic expressions. '
+ 'In a decimal assigment line the terms on the right side of '
+ 'the equal sign may be literal decimals or variable decimals. '
+ 'A literal decimal number may have a plus sign '
+ 'or a minus sign '
+ 'in front to denote its sign.'
+ s_dashline
+ 'Comment lines can be added to a Teapro program by beginning '
+ 'them with a apostrophe, ie. ''. '
+ 'Blank lines can be used '
+ 'to make the Teapro program more readable. '
+ 'Comment lines and blank lines '
+ 'are completely ignored by the Teapro interpreter. '
+ s_dashline
+ 'In Teapro a serious program error such as a zero '
+ 'divide will bring up a dialog box to inform the '
+ 'user and to give the user the choice of trying to '
+ 'continue or aborting.';
if b_more then b_more := fnb_more(sz);
end; { sub_help_general }
procedure TForm1.sub_help_commands;
{ updated 2007/06/16, 2007/05/06 }
{ 2007/04/28, 2007/04/16, 2007/04/14, 2007/03/04, 2007/01/19 }
{ 2006/06/11, 2006/06/09, 2006/06/02, 2006/05/23, 2006/05/14 }
{ 2006/05/12, 2006/04/30, 2006/04/29, 2006/04/28, 2006/04/14 }
{ 2005/06/20, 2005/04/18, 2005/04/16, 2005/03/23, 2004/10/20 }
var
s_heading : string;
s_dashline : string;
sz : string;
b_more : boolean;
begin
s_dashline := nl + StringOfChar('-', 20) + nl;
s_heading := 'Teapro string commands';
b_more := true;
sz := s_heading;
sz := sz
+ s_dashline
+ 's_str1 = s_str2 + "string" + d_dec1 + -3' + nl
+ 'String assignment command. Append s_str2 and "string" '
+ 'and d_dec1 and -3 and put into s_str1. In the string '
+ 'assignment command the part to the right of the equal '
+ 'sign is a string append expression. '
+ 'Strings may be 60,000,000 bytes long.'
+ s_dashline
+ '$APP s_string1, s_string2 + s_string3' + nl
+ 'String append. In the string append command, the part '
+ 'to the right of the comma is a string append expression. '
+ 'Evaluate it and append it to the right side of s_string1.'
+ s_dashline
+ '$BAK d_byte, s_whole, d_start, s_part' + nl
+ 'Lookup string s_part in string s_whole starting at byte '
+ 'd_start looking backwardly and put the result in d_byte. '
+ 'If not found put zero in d_byte.'
+ s_dashline
+ '$BES s_new, s_old' + nl
+ 'Blank escape characters in s_old '
+ 'and store in s_new. '
+ 'Escape characters are < 32.'
+ s_dashline
+ '$CH$ s_new, s_char, d_long' + nl
+ 'Make string s_new from d_long of the first character '
+ 'of string s_char.'
+ s_dashline
+ '$CHD d_char, s_char' + nl
+ 'Put char number of first character of s_char into d_char.';
if b_more then b_more := fnb_more(sz);
sz := s_heading;
sz := sz
+ s_dashline
+ '$CLO s_new, s_old' + nl
+ 'Make s_old lower case and store in s_new.'
+ s_dashline
+ '$CNT d_count, s_string, s_find' + nl
+ 'Put count of occurrences of s_find in s_string into '
+ 'd_count. Occurrences cannot overlap.'
+ s_dashline
+ '$COD s_new, s_old' + nl
+ 'Code s_old to s_new. Code and decode are the same.'
+ s_dashline
+ '$CUP s_new, s_old' + nl
+ 'Make s_old upper case and store in s_new.'
+ s_dashline
+ '$CUT s_part, s_whole, d_start, d_long' + nl
+ 'Cut from s_whole at d_start for length d_long and '
+ 'put in s_part.'
+ s_dashline
+ '$DAT s_date' + nl
+ 'Put date and time string into s_date in format:' + nl
+ '25-SEP-1998 20:20:36 19980925202036';
if b_more then b_more := fnb_more(sz);
sz := s_heading;
sz := sz
+ s_dashline
+ '$DEL s_whole, d_start, d_long' + nl
+ 'Delete d_long bytes from s_whole at d_start'
+ s_dashline
+ '$DOT d_dot, s_string1, s_string2, d_count' + nl
+ 'Find dot = byte of occurrence d_count of s_string2 '
+ 'in s_string1. Occurrences cannot overlap. If not found '
+ 'put zero into d_dot.'
+ s_dashline
+ '$HSH d_hash, s_string' + nl
+ 'Find hash number d_hash for string s_string.'
+ s_dashline
+ '$IFT s_str1 > s_str2' + nl
+ '$IFT s_str1 > s_str2: d_dec1 = 3' + nl
+ 'If s_str1 is greater than s_str2 then perform the '
+ 'lines of the program until the matching ELSE or ENDi is found. '
+ 'Or, in the second case if the condition is true '
+ 'perform the non-control command beyond the colon.'
+ s_dashline
+ '$INP s_input, s_output' + nl
+ 'Output s_output and then input line from user into s_input. '
+ 'For security the maximum length of s_input is 100 bytes.'
+ s_dashline
+ '$INS s_whole, d_byte, s_part' + nl
+ 'Insert s_part into s_whole starting at d_byte. If d_byte '
+ '< 1 or d_byte > 1 plus length of s_whole then error.'
+ s_dashline
+ '$ISC d_yesno, s_string, s_char' + nl
+ 'String is made up of certain char. If s_string is made up of '
+ 'the first char of s_char then put 1 in d_yesno else 2.';
if b_more then b_more := fnb_more(sz);
sz := s_heading;
sz := sz
+ s_dashline
+ '$ISD d_yesno, s_number' + nl
+ 'If s_number can be converted to a decimal value put 1 '
+ 'in d_yesno. Otherwise put 2 in d_yesno.'
+ s_dashline
+ '$ISP d_yesno, s_string, s_pattern' + nl
+ 'String pattern char type compare of s_string and s_pattern. '
+ 'Char types: escapes, blank, punctuation, numbers, uppers, '
+ 'lowers, char > 126. If match put 1 in d_yesno else 2. '
+ '"123x?" matches "999z.". Lengths of the two must match too.'
+ s_dashline
+ '$IST d_yesno, s_string, s_type' + nl
+ 'String is made up of char type of first character of s_type. '
+ 'Char types: escapes, blank, punctuation, numbers, uppers, '
+ 'lowers, char > 126. If match put 1 in d_yesno else 2. '
+ '"12345" matches "9" and ",./[}" matches "*".'
+ s_dashline
+ '$LEN d_long, s_string' + nl
+ 'Put length of s_string into d_long.'
+ s_dashline
+ '$LOK d_byte, s_whole, d_start, s_part' + nl
+ 'Lookup string s_part in s_whole starting at byte '
+ 'd_start looking forward. If found put which byte in d_byte. '
+ 'If not found put zero in d_byte.'
+ s_dashline
+ '$OFF s_result, s_string, d_long' + nl
+ 'Cut off string end, put string of length d_long '
+ 'from end of s_string into s_result.';
if b_more then b_more := fnb_more(sz);
sz := s_heading;
sz := sz
+ s_dashline
+ '$OUT s_output' + nl
+ 'Output s_output which may be an append string. '
+ '$OUT drops to the next line before outputting. '
+ 'Characters < 32 are replaced with blanks.'
+ s_dashline
+ '$PAR s_toextract, s_csv, s_char, d_which' + nl
+ 'String parse. '
+ 'Extract string s_toextract from the character separated value '
+ 'string s_csv as indicated by number d_which. '
+ 'Strings in s_csv are separated by occurrences of s_char. '
+ 'The length of s_char must be 1. '
+ 'If d_which=1 return the string ending with the first '
+ 'occurrence of s_char in s_csv. '
+ 'if d_which=6 return the string ending with the sixth s_char.'
+ s_dashline
+ '$PKD d_yesno, d_number, s_packed' + nl
+ 'String packed to decimal. Change s_packed in '
+ 'packed decimal format to d_number. Decimal '
+ 'd_number will be a whole number. '
+ 'A packed number is also called BCD or binary coded decimal. '
+ 'If s_packed is valid put 1 in d_yesno else 2.'
+ s_dashline
+ '$REP s_whole, d_byte, s_part' + nl
+ 'Replace part of s_whole starting at d_byte with s_part. '
+ 'If d_byte < 1 '
+ 'or d_byte > 1 plus length of s_whole or s_part will not fit '
+ 'in s_whole then error.'
+ s_dashline
+ '$SHO s_output' + nl
+ 'Output s_output which may be a string append expression. '
+ '$SHO does not drop to the next line before outputting. '
+ 'Characters < 32 are replaced with blanks.';
if b_more then b_more := fnb_more(sz);
sz := s_heading;
sz := sz
+ s_dashline
+ '$SOR s_new, s_old, d_long' + nl
+ 'Sort lengths of d_long in s_old and put into s_new.'
+ s_dashline
+ '$SWP s_string, s_old, s_new' + nl
+ 'String swap. In s_string replace each occurrence of s_old with '
+ 's_new.'
+ s_dashline
+ '$SYS s_info, d_which' + nl
+ 'System or program information into s_info depending on d_which.'
+ nl
+ '1 = path and filename of this running Teapro9 interpreter' + nl
+ '2 = current subroutine'
+ s_dashline
+ '$TLO s_new, s_old' + nl
+ 'Trim low. Trim s_old and make lower case. Put into s_new.'
+ s_dashline
+ '$TOD d_number, s_number' + nl
+ 'String to decimal number. '
+ 'If string s_number can be converted to a valid decimal '
+ 'number put that number in d_number. If not give an error.'
+ s_dashline
+ '$TOE s_new, s_old, s_key, d_which' + nl
+ 'String to encoded. '
+ 'Encode s_old to s_new using keyword s_key. If d_which=1 '
+ 'encode, else decode.'
+ s_dashline
+ '$TOI d_index, s_string' + nl
+ 'String to index. Store the string s_string in the '
+ 'string array at index d_index. The string array has '
+ '2000 elements ranging from index 1 to index 2000.';
if b_more then b_more := fnb_more(sz);
sz := s_heading;
sz := sz
+ s_dashline
+ '$TRB s_new, s_old' + nl
+ 'Trim blanks and escape characters from both sides '
+ 'of s_old and store in s_new.'
+ s_dashline
+ '$TRL s_new, s_old' + nl
+ 'Trim blanks and escape characters from left side '
+ 'of s_old and store in s_new.'
+ s_dashline
+ '$TRR s_new, s_old' + nl
+ 'Trim blanks and escape characters from right side '
+ 'of s_old and store in s_new.'
+ s_dashline
+ '$TUP s_new, s_old' + nl
+ 'Trim upper case. Trim and make upper case s_old '
+ 'and store in s_new.'
+ s_dashline
+ '$WHI s_string1 > s_string2' + nl
+ 'String while. The while loop ends with ENDW. '
+ 'It continues looping while the comparison is true.'
+ s_dashline
+ 'ITO$ s_string, d_index' + nl
+ 'Index to string. Get the string at the index d_index '
+ 'from the string array and store it in s_string. '
+ 'The string array has 2000 elements ranging from index '
+ '1 to index 2000.'
+ s_dashline
+ 'ARRB' + nl
+ 'Blank string array of 2000 indexed strings. '
+ 'Use command ARRZ to zero the decimal array.';
if b_more then b_more := fnb_more(sz);
s_heading := 'Teapro decimal commands';
sz := s_heading;
sz := sz
+ s_dashline
+ 'd_dec1 = + d_dec2 - d_dec3 ? 3 * d_dec4 / d_dec5 % d_dec6 * -1 '
+ '@ 2'
+ nl + nl
+ 'Start with d_dec2, subtract d_dec3, truncate to 3 decimals, '
+ 'multiply by d_dec4, '
+ 'divide by d_dec5, do mod d_dec6, multiply by -1, '
+ 'round to 2 decimals '
+ 'and put the result in d_dec1.' + nl
+ 'Assignment arithmetic is evaluated left to right. '
+ 'Decimal variables or numeric literals are used. '
+ 'Decimal number literals may have a + or - sign. '
+ 'A data error brings up the Data Error dialog box.'
+ s_dashline
+ 'DABS d_result, d_number' + nl
+ 'Absolute value. Put absolute value of d_number '
+ 'into d_result.'
+ s_dashline
+ 'DARC d_radians, d_sine' + nl
+ 'Sine to radians. An sine of an angle is in '
+ 'd_sine. Put the angle in radians in d_radians.';
if b_more then b_more := fnb_more(sz);
sz := s_heading;
sz := sz
+ s_dashline
+ 'DBAD d_num1 > d_num2' + nl
+ 'Bad decimal variable value test. '
+ 'If the condition is true then bad. '
+ 'If bad then show the data error dialog box.'
+ s_dashline
+ 'DBUG' + nl
+ 'Toggles DEBUG on and off.'
+ s_dashline
+ 'DCH$ s_string, d_char, d_long' + nl
+ 'Make s_string from character d_char of length d_long.'
+ s_dashline
+ 'DDEC d_decimal' + nl
+ 'Decrement d_decimal by 1.';
if b_more then b_more := fnb_more(sz);
sz := s_heading;
sz := sz
+ s_dashline
+ 'DED$ s_number, d_number, d_long, d_places' + nl
+ 'Edit decimal number d_number into string of at least '
+ 'length d_long. The number of decimal places is d_places. '
+ 'The number is right justified in the string. '
+ 'Commas are inserted.'
+ s_dashline
+ 'DFAC d_factor, d_number' + nl
+ 'Factor or test for prime. '
+ 'Round d_number to an integer. '
+ 'Test d_number for its lowest integer factor. '
+ 'Put the lowest factor in d_factor. '
+ 'If d_factor is 1 then d_number is prime.'
+ s_dashline
+ 'DFAK d_factor, d_1quadpart, d_1quadmult' + nl
+ 'Factor or test for prime. '
+ 'Test d_number = d_1quadpart + d_1quadmult * d_1quadnum '
+ 'where d_1quadnum is 1 quadrillion or 1E15. '
+ 'Put the lowest factor in d_factor. '
+ 'If d_factor is 1 then d_number is prime. '
+ 'The teaquad method is used here.'
+ s_dashline
+ 'DIFT d_dec1 < d_dec2' + nl
+ 'DIFT d_dec1 < d_dec2: d_dec3 = 4' + nl
+ 'Begin an if block of lines which will end with endi. '
+ 'Or, put a colon and one non-control command to do if '
+ 'the if is true.'
+ s_dashline
+ 'DINC d_decimal' + nl
+ 'Increment d_decimal by 1.'
+ s_dashline
+ 'DLOG d_log, d_decimal' + nl
+ 'Find common logarithm base=10 of '
+ 'd_decimal and put into d_log.'
+ s_dashline
+ 'DPK$ s_packed, d_decimal, d_long' + nl
+ 'Decimal to packed format in string. Change d_decimal to '
+ 'a zero filled packed decimal string s_packed '
+ 'of length d_long. Decimal d_decimal is rounded to '
+ 'a whole number first. '
+ 'A packed number is also called BCD or binary coded decimal.';
if b_more then b_more := fnb_more(sz);
sz := s_heading;
sz := sz
+ s_dashline
+ 'DPOW d_result, d_number, d_power' + nl
+ 'Raise d_number to power d_power and put in d_result. '
+ 'd_number must be greater than zero.'
+ s_dashline
+ 'DRAN d_decimal' + nl
+ 'Put random decimal number between 0 and 1 in d_decimal.'
+ s_dashline
+ 'DROU d_dec1, d_dec2' + nl
+ 'Round d_dec2 and put into d_dec1. Round a decimal '
+ 'value of .5 away from zero.'
+ s_dashline
+ 'DSEC d_sec' + nl
+ 'Seconds since midnight of 30-DEC-1899 go into d_sec.'
+ s_dashline
+ 'DSIN d_sine, d_radians' + nl
+ 'Radians to the sine. An angle in radians is in '
+ 'd_radians. Put sine of that angle in d_sine.'
+ s_dashline
+ 'DSYS d_info, d_which' + nl
+ 'Decimal system info to d_info depending on d_which. '
+ 'If d_which=1 put total of string lengths in d_info. '
+ 'If d_which=2 put total lines run into d_info.'
+ s_dashline
+ 'DTO$ s_number, d_decimal, d_long, d_places' + nl
+ 'Make decimal d_decimal into a string of at least length '
+ 'd_long with the number of decimal places as d_places. '
+ 'The number is right justified in the string. '
+ 'No commas are inserted.';
if b_more then b_more := fnb_more(sz);
sz := s_heading;
sz := sz
+ s_dashline
+ 'DTOF s_field, d_decimal, d_long' + nl
+ 'Decimal to field. Convert decimal d_decimal to a string '
+ 'of length d_long beginning with + or -, right justified '
+ 'and zero filled.'
+ s_dashline
+ 'DTOI d_index, d_dec2' + nl
+ 'Decimal to index. Store the decimal d_dec2 in the '
+ 'decimal array at index d_index. The decimal array has '
+ '8000 elements ranging from index 1 to index 8000.'
+ s_dashline
+ 'DTRU d_dec1, d_dec2' + nl
+ 'Truncate d_dec2 and put in d_dec1. Variable d_dec1 '
+ 'will be an integer closer to zero than d_dec1.'
+ s_dashline
+ 'DWHI d_dec1 < d_dec2' + nl
+ 'Begin a while loop which will end with endw.'
+ s_dashline
+ 'ITOD d_dec1, d_index' + nl
+ 'Index to decimal. Get the decimal at the index '
+ 'd_index from the decimal array and store it in '
+ 'd_dec1. The decimal array has 8000 elements ranging '
+ 'from index 1 to index 8000.'
+ s_dashline
+ 'ADDI d_index, d_decimal' + nl
+ 'Decimal add to decimal array at index. '
+ 'Add the decimal d_decimal to the '
+ 'decimal array at index d_index. The decimal array has '
+ '8000 elements ranging from index 1 to index 8000.'
+ s_dashline
+ 'ARRZ' + nl
+ 'Zero the decimal array of 8000 indexed decimals. '
+ 'Use command ARRB to blank the string array.';
if b_more then b_more := fnb_more(sz);
sz := 'Teapro control commands';
sz := sz
+ s_dashline
+ 'DIFT, DWHI, $IFT, and $WHI' + nl
+ 'See these decimal and string commands.' + nl
+ 'ELSE : else is used in DIFT or $IFT blocks.' + nl
+ 'ENDI : ends an DIFT or a $IFT block.' + nl
+ 'ENDP : end of the program.' + nl
+ 'ENDS : end of the subroutine.' + nl
+ 'ENDW : end of a DWHI or $WHI block.' + nl
+ 'GOTO tag_loop : goto where GTAG tag_loop is.' + nl
+ 'GTAG tag_loop : line where GOTO tag_loop goes.' + nl
+ 'sub_main : exit to subroutine sub_main.' + nl
+ 'SUBR sub_main : beginning line of sub_main.';
if b_more then b_more := fnb_more(sz);
sz := 'Teapro file commands';
sz := sz
+ s_dashline
+ 'FDAT d_date, s_date, s_filename' + nl
+ 'Put the decimal file date in d_date. '
+ 'Put the string file date in s_date. '
+ 'If the file does not exist put in a 0 '
+ 'and a nothing.'
+ s_dashline
+ 'FDEL d_yes, s_filename' + nl
+ 'Delete the file named in s_filename. If deleted put '
+ '1 in d_yes else put 2 in d_yes.'
+ s_dashline
+ 'FLEN d_long, s_filename' + nl
+ 'Put the length of file s_filename into d_long. '
+ 'If the file cannot be accessed in -1.'
+ s_dashline
+ 'FREN d_yes, s_newname, s_oldname' + nl
+ 'Rename file s_oldname to s_newname. If renamed put'
+ '1 in d_yes else put 2 in d_yes.';
if b_more then b_more := fnb_more(sz);
sz := 'Teapro file processing commands';
sz := sz
+ s_dashline
+ 'FINP s_string, s_filename' + nl
+ 'File input, read the whole file s_filename '
+ 'into the string s_string.'
+ s_dashline
+ 'FOUT d_bytes, s_filename, s_string' + nl
+ 'File output, write the string s_string '
+ 'to make the whole file s_filename. The number of '
+ 'bytes written is put in d_bytes.'
+ s_dashline
+ 'FREA s_record, s_filename, d_byte, d_long' + nl
+ 'File get record, read s_filename at d_byte for '
+ 'length d_long and put in string s_record. '
+ 'Files begin at byte 1. d_long cannot be over 4096. '
+ 'String s_record may be shorter than d_long. '
+ 'Determine the success of FREA by the length of s_record. '
+ 'FREA and FWRI work well on any type of file.'
+ s_dashline
+ 'FWRI d_length, s_filename, d_byte, s_record' + nl
+ 'File put record, write s_record to file s_filename '
+ 'at d_byte and put the '
+ 'length written into d_length. Files begin '
+ 'at byte 1. s_record cannot be longer than 4096.';
if b_more then b_more := fnb_more(sz);
sz := 'Teapro file processing commands';
sz := sz
+ s_dashline
+ 'FSIP s_record, s_filename, d_byte' + nl
+ 'File sip, read variable length record s_record '
+ 'from file s_filename beginning at byte d_byte, '
+ 'remove LF or CRLF at end and put beginning of '
+ 'next record in d_byte. Length of record cannot '
+ 'be over 4096. If no record read put 0 in d_byte, '
+ 'but records can be zero length. '
+ 'You should put 1 in d_byte for first read. '
+ 'FSIP works only with files that have a '
+ 'LF or CRLF at the end of each record. '
+ 'LR means a line feed or char 10. '
+ 'CRLF means a char 13 and a char 10.'
+ s_dashline
+ 'FADD d_length, s_filename, s_line' + nl
+ 'Append line to file, write line s_line to end of file '
+ 's_filename putting on a LF. Total length written '
+ 'goes into d_length and cannot be over 4096.'
+ s_dashline
+ 'FAPP d_length, s_filename, s_line' + nl
+ 'Append line to file, write line s_line to end of file '
+ 's_filename putting on a CRLF. Total length written '
+ 'goes into d_length and cannot be over 4096.';
if b_more then b_more := fnb_more(sz);
sz := '';
sz := sz
+ 'the Teapro decimal assignment command and operators'
+ s_dashline
+ 'd_dec1 = 5 + d_dec2 / -3.14 - d_dec3 * 15.2' + nl
+ 'First, remember that the decimal assignment command '
+ 'evaluates the expression to the right of the equal sign '
+ 'strictly in left to right order and not as an algebraic '
+ 'expression as in other languages. '
+ 'Literal numbers may be preceded by a + or - sign. '
+ 'The following operators tell what to do with '
+ 'the term to the right '
+ 'of the operator with respect to the answer '
+ 'being calculated.'
+ s_dashline
+ '+ means to add the right term to the answer.' + nl
+ '- means to subtract the right term from the answer.' + nl
+ '* means to multiply the right term times the answer.' + nl
+ '/ means to divide the answer by the right term.' + nl
+ '% means to round the answer and the right term '
+ 'and find the mod which has the sign of the answer.' + nl
+ '\ means to round the answer and the right term '
+ 'and do an integer divide.' + nl
+ '@ means to round term1 to number of places in term2.' + nl
+ '? means to truncate term1 to number of places in term2.' + nl
+ 'A data error brings up the Data Error dialog box.';
if b_more then b_more := fnb_more(sz);
end; { sub_help_commands }
procedure TForm1.sub_help_running;
{ updated 2000/01/01 }
var
sz : string;
b_more : boolean;
begin
b_more := true;
sz := '';
sz := sz
+ 'This program is teapro9.exe. '
+ 'It is the Teapro9 interpreter Program that you must use to run '
+ 'a program written in the Teapro programming language. '
+ 'Both the Teapro9 interpreter program and the Teapro program should '
+ 'be in the same directory. '
+ 'Use any word processor to write your Teapro program. '
+ 'Save the program as a text file with the extension .tea. '
+ 'There are two ways to get this interpreter program to run '
+ 'that Teapro program. ' + nl + nl
+ '1. Run this Teapro9 interpreter Program '
+ 'and click File on the menu bar. '
+ 'Then choose: Open a Teapro Program. '
+ 'Then type in the name of the Teapro program and click Ok. '
+ 'Then click the Start Program button '
+ 'and this interpreter program '
+ 'will run that Teapro program. ' + nl + nl
+ '2. Setup this Teapro9 interpreter Program, teapro9.exe, on your '
+ 'Start Menu or as a Short Cut '
+ 'with the name of the Teapro program you wish to run as a '
+ 'parameter. '
+ 'For example, use for your command line the following: ' + nl
+ 'c:\test\teapro9.exe yourprog.tea' + nl
+ 'where both files are in the directory c:\test. '
+ 'Then use the Start Menu or the Short Cut '
+ 'to run this Teapro9 interpreter Program with the '
+ 'name of the Teapro program as a parameter as above. '
+ 'Click on the Start Program button to start the Teapro program.';
if b_more then b_more := fnb_more(sz);
end; { sub_help_running }
procedure TForm1.sub_comm_dchs;
{ updated 2003/04/26 }
{ to perform the command DCH$ }
var
sz : string;
i_parm2, i_parm3 : integer;
begin
{ 1234567890123456789012345 }
{ DCHS 00101n,00099n,00032n }
{ get parm2 and parm3 }
i_parm2 := fni_decimal_eval(13);
i_parm3 := fni_decimal_eval(20);
if (i_parm2 < 0) then i_parm3 := 0;
if (i_parm2 > 256) then i_parm3 := 0;
if (i_parm3 < 0) then i_parm3 := 0;
if (i_parm3 > fi_max_length) then
begin
sub_program_error('string too long');
end
else
begin
{ make the string }
sz := StringOfChar(Chr(i_parm2), i_parm3);
sub_store_string(6, sz);
end;
end; { sub_comm_dchs }
function TForm1.fnb_comm_dift : boolean;
{ updated 2003/09/15 }
{ perform command DIFT and DWHI }
var
char_op : char;
e_parm1, e_parm2 : double;
begin
{ get next Teapro program line }
fs_tpline := fsa_tpline[fi_tpline];
{ 123456789012345678901 }
{ DWHI 12345n>>12345n,3 }
e_parm1 := fnd_decimal_eval(6);
e_parm2 := fnd_decimal_eval(14);
Result := false;
char_op := fs_tpline[21];
Case char_op of
'1' : if (e_parm1 = e_parm2) then Result := true;
'2' : if (e_parm1 <> e_parm2) then Result := true;
'3' : if (e_parm1 < e_parm2) then Result := true;
'4' : if (e_parm1 > e_parm2) then Result := true;
'5' : if (e_parm1 >= e_parm2) then Result := true;
'6' : if (e_parm1 <= e_parm2) then Result := true;
end;
end; { fnb_comm_dift }
procedure TForm1.sub_comm_dset;
{ updated 2007/07/23 }
{ 2007/07/08, 2007/05/06, 2007/04/28, 2007/04/14, 2004/04/21 }
{ perform command DSET }
var
c_1 : comp;
c_2 : comp;
e_answer : double;
e_term : double;
char_op : char;
iy, iz : integer;
b_loop : boolean;
begin
{ dset 00201n=+00001n*00301p-00302p/00303p*00005n; }
{ 12345678901234567890123456789012345678901234567890 }
fb_error := false;
e_answer := 0;
iz := 13;
b_loop := true;
while b_loop do
begin
{ evaluate the decimal, iz is where the operator is }
iy := StrToIntDef(Copy(fs_tpline, Succ(iz), 5), -1);
if (iy = -1) then
begin
sub_program_error('bad variable link');
end
else
begin
if (fs_tpline[iz + 6] = 'D')
then e_term := fea_var[iy + fi_delta_d]
else if (fs_tpline[iz + 6] = 'G')
then e_term := fea_var[iy]
else e_term := iy;
char_op := fs_tpline[iz];
case char_op of
'%' : { modulus }
begin
{ the sign of e_answer prevails }
c_1 := e_answer;
c_2 := e_term;
if (c_2 > 0) then
begin
{ find mod }
e_answer := c_1 - Int(c_1 / c_2) * c_2;
end
else sub_program_error('zero mod');
end;
'*' : e_answer := e_answer * e_term;
'+' : e_answer := e_answer + e_term;
'-' : e_answer := e_answer - e_term;
'/' : { regular divide }
begin
{ division using decimals }
if (e_term <> 0) then e_answer := e_answer / e_term
else sub_program_error('zero divide');
end;
'\' : { integer divide }
begin
c_1 := e_answer;
c_2 := e_term;
if (c_2 <> 0) then e_answer := Int(c_1 / c_2)
else sub_program_error('zero integer divide');
end;
'^' : { exponentiation }
begin
{ if e_answer negative then e_term must be integer }
if (e_answer < 0) and (e_term <> floor(e_term)) then
e_answer := abs(e_answer);
if (e_answer = 0) or (e_term = 0) then
begin
e_answer := 1;
e_term := 1;
end;
e_answer := power(e_answer, e_term);
end;
'@' : { round to number of places }
begin
c_2 := power(10, int(abs(e_term) + 0.001));
c_1 := e_answer * c_2 + 0.499;
e_answer := c_1 / c_2;
end;
'?' : { truncate to number of places }
begin
c_2 := power(10, int(abs(e_term) + 0.001));
c_1 := int(e_answer * c_2 + 0.001);
e_answer := c_1 / c_2;
end;
end;
end;
Inc(iz, 7);
if fb_error or (fs_tpline[iz] = ';') then b_loop := false;
end;
{ store the answer }
if not fb_error then sub_store_decimal(6, e_answer);
end; { sub_comm_dset }
procedure TForm1.sub_comm_dfac;
{ updated 2007/01/19, 2005/04/29, 2005/03/22, 2004/10/11 }
{ find lowest factor greater than 1 }
var
d_parm2 : double;
d_try : double;
d_divisor : double;
c_answer : comp;
cz : comp;
b_error : boolean;
b_loop : boolean;
begin
{ 123456789012345678 }
{ DFAC 00101d,00102d }
cz := fnd_decimal_eval(13);
d_parm2 := cz;
Application.ProcessMessages;
b_error := false;
b_loop := true;
if (d_parm2 < 1) or (d_parm2 >= Power(10, 16)) then
begin
{ number out of range }
sub_program_error('dfac range is > 0 and < 9.0E15');
b_error := true;
b_loop := false;
end;
if b_loop then
begin
d_divisor := 1;
if (d_parm2 < 4) then b_loop := false;
end;
if b_loop then
begin
{ is c_answer even }
c_answer := d_parm2 / 2;
if (d_parm2 = c_answer * 2) then
begin
{ even number not prime }
b_loop := false;
d_divisor := 2;
end;
d_try := 3;
end;
while b_loop and fb_program_loop do
begin
{ dfac }
c_answer := d_parm2 / d_try;
if (d_parm2 <> c_answer * d_try) then
begin
d_try := d_try + 2;
{ prime? }
if (sqr(d_try) > d_parm2) then b_loop := false;
end
else
begin
{ not prime }
d_divisor := d_try;
b_loop := false;
end;
end;
if not b_error then sub_store_decimal(6, d_divisor);
end; { sub_comm_dfac }
procedure TForm1.sub_comm_dfak;
{ updated 2007/03/04, 2007/01/20 }
{ 2007/01/19, 2007/01/18, 2005/04/29, 2005/03/22, 2004/10/11 }
{ find lowest factor of parm2 + parm3 * 9quadrillion }
var
d_1quadpart : double;
d_1quadmult : double;
d_1quadnum : double;
d_factor : double;
d_root : double;
d_divisor : double;
d_modulus : double;
i_loop : integer;
cz : comp;
dz : double;
begin
{ 1234567890123456789012345 }
{ DFAK 00101d,00102d,00103d }
{ 1234567890123456 }
d_1quadnum := 1000000000000000.0;
d_factor := 1;
i_loop := 1;
Application.ProcessMessages;
cz := fnd_decimal_eval(13);
d_1quadpart := Abs(cz);
cz := fnd_decimal_eval(20);
d_1quadmult := Abs(cz);
{ d_1quadnum is factored by 2 }
dz := fnd_modulus(d_1quadpart, 2);
if (dz = 0) then
begin
d_factor := 2;
inc(i_loop);
end;
if (i_loop = 1) then
d_root := sqrt(d_1quadpart + d_1quadmult * d_1quadnum);
d_divisor := 3;
while (i_loop = 1) do
begin
d_modulus := fnd_modulus(fnd_modulus(d_1quadpart, d_divisor)
+ d_1quadmult * fnd_modulus(d_1quadnum, d_divisor), d_divisor);
if (d_modulus = 0) then
begin
Inc(i_loop);
d_factor := d_divisor;
end
else
begin
d_divisor := d_divisor + 2;
if (d_divisor > d_root) then Inc(i_loop);
end;
end;
sub_store_decimal(6, d_factor);
end; { sub_comm_dfak }
procedure TForm1.sub_comm_dpow;
{ updated 2007/07/23, 2007/07/08, 2004/04/21 }
var
d_number : double;
d_power : double;
d_result : double;
begin
{ 1234567890123456789012345 }
{ DPOW 00101d,00102d,12345d }
d_number := fnd_decimal_eval(13);
d_power := fnd_decimal_eval(20);
{ if d_number negative then d_power must be integer }
if (d_number < 0) and (d_power <> floor(d_power)) then
d_number := abs(d_number);
if (d_number = 0) or (d_power = 0) then
begin
d_number := 1;
d_power := 1;
end;
d_result := Power(d_number, d_power);
sub_store_decimal(6, d_result);
end; { sub_comm_dpow }
procedure TForm1.sub_comm_dsin(const pbyte_1 : byte);
{ updated 2003/09/14 }
var
b_negative : boolean;
dz : double;
cz : comp;
e_parm2 : double;
d_result : double;
b_error : boolean;
begin
{ 123456789012345678 }
{ DSIN 00101d,00102d }
e_parm2 := fnd_decimal_eval(13);
b_error := false;
if (pbyte_1 = 1) then
begin
{ drou round }
if (e_parm2 < 0) then
begin
b_negative := true;
e_parm2 := - e_parm2;
end
else b_negative := false;
cz := e_parm2;
if ((e_parm2 - cz) = 0.5) then cz := cz + 1;
if b_negative then cz := - cz;
d_result := cz;
end
else if (pbyte_1 = 2) then d_result := Int(e_parm2) { dtru truncate }
else if (pbyte_1 = 3) then d_result := Sin(e_parm2) { dsin sine }
else if (pbyte_1 = 4) then
begin
{ darc finding arcsine }
if (e_parm2 = 1) then d_result := PI / 2
else if (e_parm2 = -1) then d_result := -PI / 2
else if (e_parm2 < 1) and (e_parm2 > -1) then
d_result := ArcTan(e_parm2/sqrt(1-sqr(e_parm2)))
else
begin
sub_program_error('bad numbers in DSIN');
b_error := true;
end;
end
else if (pbyte_1 = 5) then
begin
{ dlog finding log10 }
if (e_parm2 > 0) then d_result := Log10(e_parm2)
else b_error := true;
end;
if not b_error then sub_store_decimal(6, d_result);
end; { sub_comm_dsin }
procedure TForm1.sub_comm_dtos(const pbyte_1 : byte);
{ updated 2006/05/02, 2004/09/25 }
{ perform decimal to string DTO$, DED$ }
var
e_number : double;
i_length : integer;
i_decimals : integer;
i_dot : integer;
i_right : integer;
s_number : string;
i_long : integer;
iy, iz : integer;
b_process : boolean;
begin
{ do we need to put commas in, pbyte_1=1 means DED$ }
{ 12345678901234567890123456789012 }
{ DTO$ 00101n,00401p,00010n,00011n }
e_number := fnd_decimal_eval(13);
i_length := fni_decimal_eval(20);
i_decimals := fni_decimal_eval(27);
if (i_length < 0) then i_length := 0;
if (i_decimals < 0) then i_decimals := 0;
if (i_decimals > 16) then i_decimals := 16;
if (i_decimals = 0) and (i_length = 0) then i_decimals := 16;
{ change number to string }
if (pbyte_1 = 1) then
begin
{ with commas }
s_number := Trim(FloatToStrF(e_number, ffNumber, 16, i_decimals))
end
else
begin
{ without commas }
s_number := Trim(FloatToStrF(e_number, ffFixed, 16, i_decimals));
end;
b_process := true;
{ do we have an E for exponential notation }
if (Pos('E', s_number) > 0) then
begin
{ add leading blanks if not long enought }
if (i_length > Length(s_number)) then
begin
iz := i_length - Length(s_number);
s_number := StringOfChar(' ', iz) + s_number;
end;
b_process := false;
end;
if b_process then
begin
{ make sure we have a decimal }
if (Pos('.', s_number) = 0) then
s_number := s_number + '.';
{ remove trailing zeros }
iz := Length(s_number);
while (s_number[iz] = '0') do Dec(iz);
s_number := Copy(s_number, 1, iz);
i_dot := Pos('.', s_number);
i_long := Length(s_number);
i_right := i_long - i_dot;
if (i_decimals > i_right) and (i_length > i_long) then
begin
iz := i_length - i_long;
iy := i_decimals - i_right;
if (iz > iy) then iz := iy;
{ add zeros on the right side }
s_number := s_number + StringOfChar('0', iz);
end;
{ remove a trailing decimal if needed }
i_long := Length(s_number);
if (s_number[i_long] = '.') then
s_number := Copy(s_number, 1, Pred(i_long));
{ make the string i_length long by adding blanks to the left }
if (Length(s_number) < i_length) then
begin
iz := i_length - Length(s_number);
s_number := StringOfChar(' ', iz) + s_number;
end;
end;
sub_store_string(6, s_number);
end; { sub_comm_dtos }
procedure TForm1.sub_comm_dtof;
{ updated 2004/05/17 }
{ decimal to field format ie. +00000137 }
var
e_parm2 : double;
i_parm3 : integer;
i_long : integer;
s_field : string;
co_number : comp;
iz : integer;
b_negative : boolean;
begin
fb_error := false;
{ 1234567890123456789012345 }
{ DPK$ 00101n,00401p,00010n }
e_parm2 := fnd_decimal_eval(13);
i_parm3 := fni_decimal_eval(20);
if (i_parm3 < 2) then sub_program_error('bad length DTOF');
if not fb_error then
begin
co_number := e_parm2;
if (co_number < 0) then
begin
b_negative := true;
co_number := - co_number;
end
else b_negative := false;
s_field := Trim(FloatToStrF(co_number, ffGeneral, 16, 4));
end;
{ is it too long }
if not fb_error then
if (Length(s_field) > Pred(i_parm3)) then
sub_program_error('bad length DTOF');
if not fb_error then
begin
{ make left part of string zero-filled }
s_field := StringOfChar('0', i_parm3 - Length(s_field))
+ s_field;
if b_negative then s_field[1] := '-'
else s_field[1] := '+';
sub_store_string(6, s_field);
end;
end; { sub_comm_dtof }
procedure TForm1.sub_comm_dpks;
{ updated 2003/10/05 }
{ perform decimal to packed format zero filled to string DPK$ }
{ packed format is also called BCD or binary coded decimal }
var
e_parm2 : double;
i_parm3 : integer;
i_long : integer;
s_packed : string;
co_number : comp;
iz : integer;
b_negative : boolean;
begin
fb_error := false;
{ 1234567890123456789012345 }
{ DPK$ 00101n,00401p,00010n }
e_parm2 := fnd_decimal_eval(13);
i_parm3 := fni_decimal_eval(20);
if (i_parm3 < 1) then sub_program_error('bad numbers DPK$');
if not fb_error then
begin
co_number := e_parm2;
if (co_number < 0) then
begin
b_negative := true;
co_number := - co_number;
end
else b_negative := false;
s_packed := Trim(FloatToStrF(co_number, ffGeneral, 16, 4));
end;
{ is it too long }
if not fb_error then
if (Length(s_packed) > i_parm3) then
sub_program_error('bad numbers DPK$');
if not fb_error then
begin
{ make left part of string zero-filled }
s_packed := StringOfChar('0', i_parm3 - Length(s_packed))
+ s_packed;
if b_negative then
begin
{ change to packed format }
i_long := Length(s_packed);
{ 1 at 49 changes to J at 74 }
iz := Ord(s_packed[i_long]) + 25;
{ I is 73 and a right brace is 125 }
if (iz = 73) then iz := 125;
s_packed[i_long] := Chr(iz);
end;
sub_store_string(6, s_packed);
end;
end; { sub_comm_dpks }
procedure TForm1.sub_comm_dtoi(const pbyte_1 : byte);
{ updated 2007/06/16, 2004/02/02 }
{ put or add a decimal into a pointed to address }
var
i_parm1 : integer;
e_parm2 : double;
begin
{ 123456789012345678 }
{ DTOI 00701D,00401D }
{ ADDI 00701d,00401d }
i_parm1 := fni_decimal_eval(6);
e_parm2 := fnd_decimal_eval(13);
{ validate and put }
{ put the value into the array at the index }
if (i_parm1 >= 1) and (i_parm1 <= fi_max_darray) then
begin
if (pbyte_1 = 1) then fea_array[i_parm1] := e_parm2
else fea_array[i_parm1] := fea_array[i_parm1] + e_parm2;
end
else sub_program_error('bad index=' + IntToStr(i_parm1));
end; { sub_comm_dtoi }
procedure TForm1.sub_comm_itod;
{ updated 2007/06/16, 2004/01/24 }
{ get a decimal by an index from an array }
var
i_parm2 : integer;
begin
{ 123456789012345678 }
{ ITOD 00701D,00401D }
i_parm2 := fni_decimal_eval(13);
{ get the decimal from the array by index }
if (i_parm2 >= 1) and (i_parm2 <= fi_max_darray) then
sub_store_decimal(6, fea_array[i_parm2])
else sub_program_error('bad index=' + IntToStr(i_parm2));
end; { sub_comm_itod }
procedure TForm1.sub_comm_sdat;
{ updated 2002/09/05 }
var
s_date : string;
begin
{ 12345678901 }
{ SDAT 00601D }
{ s_date }
s_date := UpperCase(FormatDateTime('dd-mmm-yyyy hh:nn:ss', Now))
+ ' ' + FormatDateTime('yyyymmddhhnnss', Now);
sub_store_string(6, s_date);
end; { sub_comm_sdat }
function TForm1.fnb_comm_sift : boolean;
{ updated 2000/01/01 }
var
char_op : char;
s_parm1, s_parm2 : string;
begin
{ get next Teapro program line }
fs_tpline := fsa_tpline[fi_tpline];
{ 123456789012345678901 }
{ $IFT 00101n<>00201n,1 }
{ get s1 }
s_parm1 := fns_string_eval(6);
{ get s2 }
s_parm2 := fns_string_eval(14);
Result := false;
char_op := fs_tpline[21];
Case char_op of
'1' : if (s_parm1 = s_parm2) then Result := true;
'2' : if (s_parm1 <> s_parm2) then Result := true;
'3' : if (s_parm1 < s_parm2) then Result := true;
'4' : if (s_parm1 > s_parm2) then Result := true;
'5' : if (s_parm1 >= s_parm2) then Result := true;
'6' : if (s_parm1 <= s_parm2) then Result := true;
end;
end; { fnb_comm_sift }
procedure TForm1.sub_comm_sout(const pbyte_1 : byte);
{ updated 2000/01/01 }
{ perform the $OUT command }
var
s_parm1 : string;
begin
{ 12345678901 }
{ $OUT 00101n }
{ $OUT "string" }
{ get the output string }
s_parm1 := fns_string_parse(Copy(fs_tpline, 6, 200));
{ show in memo_show }
sub_memo_show(s_parm1, pbyte_1);
end; { sub_comm_sout }
procedure TForm1.sub_comm_sisd;
{ updated 2004/09/25 }
{ $ISD, returns 1 if the string is a decimal value }
var
i_result : integer;
ez : double;
sz : string;
b_error : boolean;
begin
{ 123456789012345678 }
{ $ISD 00901D,00101S }
sz := Trim(fns_string_eval(13));
sub_double_from_string(sz, ez, b_error);
if b_error then i_result := 2
else i_result := 1;
sub_store_decimal(6, i_result);
end; { sub_comm_sisd }
procedure TForm1.sub_comm_stod;
{ updated 2003/11/23 }
{ perform the command $TOD, string to decimal }
var
b_error : boolean;
e_number : double;
s_number : string;
begin
{ 123456789012345678 }
{ $TOD 00901D,00101S }
s_number := fns_string_eval(13);
sub_double_from_string(s_number, e_number, b_error);
if not b_error then
sub_store_decimal(6, e_number)
else sub_program_error('$TOD not number="' + s_number + '"');
end; { sub_comm_stod }
procedure TForm1.sub_comm_spkd;
{ updated 2005/11/02, 2003/10/05 }
{ perform the command $PKD, packed formatted string to decimal }
{ packed format is also called BCD or binary coded decimal }
var
e_number : double;
s_parm3 : string;
i_long : integer;
b_negative : boolean;
b_error : boolean;
i_good : integer;
iz : integer;
begin
{ 1234567890123456789012345 }
{ $PKD 00901D,00101S,00101S }
s_parm3 := fns_string_eval(20);
s_parm3 := Trim(s_parm3);
i_long := Length(s_parm3);
if (i_long = 0) then
begin
s_parm3 := '0';
i_long := 1;
end;
{ what is the last char and do we need to change it }
iz := Ord(s_parm3[i_long]);
{ 48 is 0 and 57 is 9 }
b_negative := true;
if (iz >= 48) and (iz <= 57) then b_negative := false
{ 65 is A and 73 is I }
else if (iz >= 65) and (iz <= 73) then
begin
b_negative := false;
iz := iz - 16;
s_parm3[i_long] := Chr(iz);
end
{ 74 is J and 82 is R }
else if (iz >= 74) and (iz <= 82) then
begin
b_negative := true;
iz := iz - 25;
s_parm3[i_long] := Chr(iz);
end
{ a right brace is 125 which is negative zero }
else if (iz = 125) then
begin
b_negative := true;
s_parm3[i_long] := '0';
end
{ a left brace is 123 which is positive zero }
else if (iz = 123) then
begin
b_negative := false;
s_parm3[i_long] := '0';
end;
b_error := false;
if (i_long > 15) then b_error := true;
for iz := 1 to i_long do
begin
if (s_parm3[iz] < '0') or (s_parm3[iz] > '9') then
b_error := true;
end;
i_good := 2;
e_number := 0;
if not b_error then
begin
i_good := 1;
e_number := StrToFloat(s_parm3);
if b_negative then e_number := - e_number;
end;
sub_store_decimal(6, i_good);
if not b_error then sub_store_decimal(13, e_number);
end; { sub_comm_spkd }
procedure TForm1.sub_comm_stoi(const pbyte_1 : byte);
{ updated 2007/06/16, 2006/06/11, 2006/06/09, 2004/01/24 }
{ perform $toi, string to an array by index }
var
i_parm1 : integer;
s_parm2 : string;
begin
{ 123456789012345678 }
{ $TOI 00401D,00101S }
i_parm1 := fni_decimal_eval(6);
s_parm2 := fns_string_parse(Copy(fs_tpline, 13, 200));
{ validate and put }
{ put the string into the string array by index }
if (i_parm1 >= 1) and (i_parm1 <= fi_max_sarray) then
fsa_array[i_parm1] := s_parm2
else sub_program_error('bad index=' + IntToStr(i_parm1));
end; { sub_comm_stoi }
procedure TForm1.sub_comm_itos;
{ updated 2007/06/16, 2004/01/24 }
{ ito$, index to string }
var
{ 05-SEP-2002 }
i_parm2 : integer;
begin
{ 123456789012345678 }
{ ITO$ 00101S,00401D }
i_parm2 := fni_decimal_eval(13);
{ put the string from the string array by index into a string variable }
{ the string variable to put the string into may need fi_delta_s }
if (i_parm2 >= 1) and (i_parm2 <= fi_max_sarray) then
sub_store_string(6, fsa_array[i_parm2])
else sub_program_error('bad index=' + IntToStr(i_parm2));
end; { sub_comm_itos }
procedure TForm1.sub_comm_array(const pbyte_1 : byte);
{ updated 2007/06/16, 2004/01/24 }
{ either zero decimal array or blank string array }
var
iz : integer;
begin
if (pbyte_1 = 1) then
begin
{ ARRZ }
for iz := 1 to fi_max_darray do fea_array[iz] := 0;
end
else
begin
{ ARRB }
for iz := 1 to fi_max_sarray do fsa_array[iz] := '';
end;
end; { sub_comm_array }
procedure TForm1.sub_comm_sset;
{ updated 2002/11/22 }
{ perform the command $SET }
var
s_string : string;
begin
{ 1234567890123456789012345 }
{ $SET 00101n,00201n+00202s }
s_string := fns_string_parse(Copy(fs_tpline, 13, 99999));
sub_store_string(6, s_string);
end; { sub_comm_sset }
procedure TForm1.sub_comm_sapp;
{ updated 2003/10/10 }
{ append a string to another string }
var
s_parm1, s_parm2 : string;
begin
{ 123456789012345678 }
{ $APP 00101S,00401D }
{ get parm1 }
s_parm1 := fns_string_eval(6);
{ get parm2 }
s_parm2 := fns_string_parse(Copy(fs_tpline, 13, 99999));
if (Length(s_parm1) + Length(s_parm2) > fi_max_length) then
begin
sub_program_error('too long');
end
else sub_store_string(6, s_parm1 + s_parm2);
end; { sub_comm_sapp }
procedure TForm1.sub_comm_srep;
{ updated 2003/10/09 }
{ perform the command $REP to replace bytes in a string }
var
iz : integer;
i_parm2 : integer;
s_parm1, s_parm3 : string;
i_long1, i_long3 : integer;
b_error : boolean;
begin
{ 1234567890123456789012345 }
{ $REP 00101S,00401D,00201S }
{ get parm1 }
s_parm1 := fns_string_eval(6);
{ get parm2 }
i_parm2 := fni_decimal_eval(13);
{ get parm3 }
s_parm3 := fns_string_eval(20);
i_long1 := Length(s_parm1);
i_long3 := Length(s_parm3);
b_error := false;
if (i_parm2 < 1) or (i_parm2 > i_long1) then b_error := true;
if ((i_parm2 + i_long3 - 1) > i_long1) then b_error := true;
if not b_error then
begin
iz := 1;
while (iz <= i_long3) do
begin
s_parm1[i_parm2 + iz - 1] := s_parm3[iz];
Inc(iz);
end;
sub_store_string(6, s_parm1);
end
else sub_program_error('bad $REP');
end; { sub_comm_srep }
procedure TForm1.sub_comm_sswp;
{ updated 2007/01/19, 2005/04/29, 2005/03/22, 2004/06/29 }
{ string swap in s_parm1 replace each s_parm2 with s_parm3 }
var
s_parm1, s_parm2, s_parm3 : string;
i_long1, i_long2, i_long3 : integer;
i_byte : integer;
i_diff : integer;
b_loop : boolean;
b_changed : boolean;
begin
{ 1234567890123456789012345 }
{ $SWP 00101S,00401S,00201S }
{ get parm1 }
s_parm1 := fns_string_eval(6);
{ get parm2 }
s_parm2 := fns_string_eval(13);
{ get parm3 }
s_parm3 := fns_string_eval(20);
i_long1 := Length(s_parm1);
i_long2 := Length(s_parm2);
i_long3 := Length(s_parm3);
i_diff := i_long3 - i_long2;
b_changed := false;
b_loop := true;
if (i_long1 = 0) or (i_long2 = 0)
or (i_long1 < i_long2) then b_loop := false;
i_byte := 1;
while b_loop do
begin
if (Copy(s_parm1, i_byte, i_long2) = s_parm2) then
begin
if ((Length(s_parm1) + i_diff) > fi_max_length) then
begin
b_loop := false;
b_changed := false;
sub_program_error('too long');
end
else
begin
Application.ProcessMessages;
Delete(s_parm1, i_byte, i_long2);
if (i_long3 > 0) then Insert(s_parm3, s_parm1, i_byte);
i_byte := i_byte + i_long3 - 1;
b_changed := true;
end;
end;
Inc(i_byte);
if (i_byte > Length(s_parm1)) then b_loop := false;
end;
if b_changed then sub_store_string(6, s_parm1);
end; { sub_comm_sswp }
procedure TForm1.sub_comm_sins;
{ updated 2003/10/09 }
{ perform the command $INS to insert a string into another }
var
{ 26-APR-2003 }
s_parm1, s_parm3 : string;
i_parm2 : integer;
i_long1, i_long3 : integer;
s_result : string;
b_error : boolean;
begin
{ 1234567890123456789012345 }
{ $INS 00101S,00401D,00201S }
{ get parm1 }
s_parm1 := fns_string_eval(6);
{ get parm2 which is where to insert }
i_parm2 := fni_decimal_eval(13);
{ get parm3 which is the string to insert }
s_parm3 := fns_string_eval(20);
b_error := false;
i_long1 := Length(s_parm1);
i_long3 := Length(s_parm3);
if ((i_long1 + i_long3) > fi_max_length) then b_error := true
else if (i_parm2 > (i_long1 + 1)) then b_error := true
else if (i_parm2 < 1) then b_error := true
else if (i_long1 = 0) then s_result := s_parm3
else if (i_long3 = 0) then s_result := s_parm1
else if (i_parm2 = (i_long1 + 1)) then s_result := s_parm1 + s_parm3
else if (i_parm2 = 1) then s_result := s_parm3 + s_parm1
else
begin
s_result := s_parm1;
Insert(s_parm3, s_result, i_parm2);
end;
if b_error then sub_program_error('bad $ins')
else sub_store_string(6, s_result);
end; { sub_comm_sins }
procedure TForm1.sub_comm_sdel;
{ updated 2002/09/05 }
{ perform the command $DEL to delete a string from another string }
var
s_parm1 : string;
i_parm2, i_parm3 : integer;
begin
{ 1234567890123456789012345 }
{ $DEL 00101S,00401D,00402D }
{ get parm1 }
s_parm1 := fns_string_eval(6);
{ get parm2 which is where to begin to delete }
i_parm2 := fni_decimal_eval(13);
{ get parm3 which is how many bytes to delete }
i_parm3 := fni_decimal_eval(20);
{ delete }
if (i_parm2 > 0) and (i_parm2 <= Length(s_parm1)) then
begin
Delete(s_parm1, i_parm2, i_parm3);
sub_store_string(6, s_parm1);
end
else sub_program_error('bad number $DEL');
end; { sub_comm_sdel }
procedure TForm1.sub_comm_slen(const pbyte_1 : byte);
{ updated 2006/06/02, 2002/09/05 }
{ find length or hash of string }
var
s_parm2 : string;
i_long : integer;
i_byte : integer;
ix, iy, iz : integer;
d_result : double;
begin
{ 123456789012345678 }
{ $LEN 00401n,00101n }
{ get the string whose length we want }
s_parm2 := fns_string_eval(13);
i_long := Length(s_parm2);
{ 1=$LEN }
if (pbyte_1 = 1) then d_result := i_long
else
begin
{ 2=$HSH }
ix := 0;
iy := 0;
for i_byte := 1 to i_long do
begin
iz := Ord(s_parm2[i_byte]) + 1;
{ 1,000,000,000 }
ix := (ix + iz) mod 1000000000;
{ 701 is prime, 1,000,000 }
iy := (iy + ((i_byte - 1) mod 701 + 1) * iz) mod 1000000;
end;
{ 1,000,000 }
d_result := ix * 1000000.0 + iy;
end;
{ store the string length }
sub_store_decimal(6, d_result);
end; { sub_comm_slen }
procedure TForm1.sub_comm_sfix(const pbyte_1 : byte);
{ updated 2004/11/06 }
{ make a string in op3 upper or lower case put in op2 }
var
iz : integer;
sz : string;
begin
{ 123456789012345678 }
{ $CLO 00102S,00101S }
{ get the string we want to fix }
sz := fns_string_eval(13);
{ $CLO = 1
$CUP = 2
$BES = 3
$TRB = 4
$TRL = 5
$TRR = 6
$TLO = 7
$TUP = 8
}
if (pbyte_1 = 1) then sz := LowerCase(sz)
else if (pbyte_1 = 2) then sz := UpperCase(sz)
else if (pbyte_1 = 3) then sz := fns_blank_escapes(sz)
else if (pbyte_1 = 4) then sz := Trim(sz)
else if (pbyte_1 = 5) then sz := TrimLeft(sz)
else if (pbyte_1 = 6) then sz := TrimRight(sz)
else if (pbyte_1 = 7) then sz := Trim(LowerCase(sz))
else if (pbyte_1 = 8) then sz := Trim(UpperCase(sz));
{ store the new string }
sub_store_string(6, sz);
end; { sub_comm_sfix }
procedure TForm1.sub_comm_ssor;
{ updated 2007/01/19, 2005/04/29, 2005/03/22, 2003/09/15 }
{ string sort by lengths }
var
s_parm2 : string;
i_parm3 : integer;
s_1, s_2 : string;
i_1, i_2 : integer;
i_length : integer;
iz : integer;
b_sort : boolean;
begin
fb_error := false;
{ 1234567890123456789012345 }
{ $SOR 00401S,00001S,00101D }
{ get the sort length }
i_parm3 := fni_decimal_eval(20);
{ get the string we want to sort }
s_parm2 := fns_string_eval(13);
b_sort := true;
i_length := Length(s_parm2);
if (i_length mod i_parm3 > 0) then fb_error := true;
if (i_length <= i_parm3) then b_sort := false;
if b_sort and not fb_error then
begin
i_1 := 1;
while (i_1 < i_length) do
begin
{ $sor }
Application.ProcessMessages;
s_1 := Copy(s_parm2, i_1, i_parm3);
i_2 := i_1 + i_parm3;
while (i_2 <= i_length) do
begin
s_2 := Copy(s_parm2, i_2, i_parm3);
if (s_1 > s_2) then
begin
{ put s_2 into i_1 the position }
for iz := 1 to i_parm3 do
begin
s_parm2[i_1 + iz - 1] := s_2[iz];
s_parm2[i_2 + iz - 1] := s_1[iz];
end;
s_1 := s_2;
end;
Inc(i_2, i_parm3);
end;
Inc(i_1, i_parm3);
end;
end;
if fb_error then sub_program_error('bad numbers $SOR')
else
begin
{ store the sorted string }
sub_store_string(6, s_parm2);
end;
end; { sub_comm_ssor }
procedure TForm1.sub_comm_slok;
{ updated 2002/09/02 }
{ lookup string op5 in string op4 starting at op3 and put in op2 }
var
s_parm2, s_parm4 : string;
i_parm3 : integer;
i_long4, i_long2 : integer;
i_max2 : integer;
i_spot : integer;
iw, ix, iz : integer;
b_loop : boolean;
b_match : boolean;
b_process : boolean;
begin
{ 12345678901234567890123456789012 }
{ $LOK 00401D,00001S,00001N,00102S }
{ get the string we want to find }
s_parm4 := fns_string_eval(27);
{ get the starting point }
i_parm3 := fni_decimal_eval(20);
{ get the string we want to look in }
s_parm2 := fns_string_eval(13);
b_process := true;
i_long4 := Length(s_parm4);
i_long2 := Length(s_parm2);
i_max2 := Succ(i_long2 - i_long4);
if (i_parm3 < 1) or (i_parm3 > i_max2) then b_process := false;
if (i_long4 = 0) or (i_long4 > i_long2) then b_process := false;
i_spot := 0;
if b_process then
begin
{ ix is what we are looking for }
ix := i_parm3;
b_match := false;
b_loop := true;
while b_loop do
begin
if (s_parm4[1] = s_parm2[ix]) then
begin
b_match := true;
iw := Pred(ix);
for iz := 2 to i_long4 do
begin
if (s_parm4[iz] <> s_parm2[iw + iz])
then b_match := false;
end;
if b_match then
begin
b_loop := false;
i_spot := ix;
end;
end;
if not b_match then
begin
Inc(ix);
if (ix > i_max2) then b_loop := false;
end;
end;
end;
{ store the find answer }
sub_store_decimal(6, i_spot);
end; { sub_comm_slok }
procedure TForm1.sub_comm_scnt;
{ updated 2003/11/07 }
{ find count of occurrences of string in other string }
var
s_parm2, s_parm3 : string;
i_long3, i_long2 : integer;
i_max : integer;
i_count : integer;
iw, ix, iz : integer;
b_loop : boolean;
b_match : boolean;
b_process : boolean;
begin
{ 1234567890123456789012345 }
{ $CNT 00401D,00001S,00102S }
{ get the string we want to look in }
s_parm2 := fns_string_eval(13);
{ get the string we want to find }
s_parm3 := fns_string_eval(20);
b_process := true;
i_long3 := Length(s_parm3);
i_long2 := Length(s_parm2);
if (i_long3 = 0) or (i_long3 > i_long2) then b_process := false;
i_count := 0;
if b_process then
begin
{ ix is where we are looking }
ix := 1;
{ i_max is the maximum that ix can be }
i_max := Succ(i_long2 - i_long3);
b_match := false;
b_loop := true;
while b_loop do
begin
if (s_parm3[1] = s_parm2[ix]) then
begin
b_match := true;
iw := Pred(ix);
for iz := 2 to i_long3 do
begin
if (s_parm3[iz] <> s_parm2[iw + iz])
then b_match := false;
end;
if b_match then
begin
Inc(i_count);
{ so that occurrences cannot overlap }
ix := ix + Pred(i_long3);
end;
end;
Inc(ix);
if (ix > i_max) then b_loop := false;
end;
end;
{ store the count }
sub_store_decimal(6, i_count);
end; { sub_comm_scnt }
procedure TForm1.sub_comm_sbak;
{ updated 2002/09/05 }
{ lookup string op5 in string op4 starting at op3 and put in op2 }
var
s_parm2, s_parm4 : string;
i_parm3 : integer;
i_long4, i_long2 : integer;
ix, iz : integer;
b_loop : boolean;
b_match : boolean;
b_process : boolean;
begin
{ 12345678901234567890123456789012 }
{ $BAK 00401D,00001S,00001N,00102S }
{ get the string we want to find }
s_parm4 := fns_string_eval(27);
{ get the starting point }
i_parm3 := fni_decimal_eval(20);
{ get the string we want to look in }
s_parm2 := fns_string_eval(13);
b_process := true;
i_long4 := Length(s_parm4);
i_long2 := Length(s_parm2);
if (i_parm3 < 1) or (i_long4 = 0) then b_process := false;
if (i_long4 > i_long2) then b_process := false;
if b_process then
begin
{ ix must be small enough for s_parm2 to hold s_parm4 }
ix := Succ(i_long2 - i_long4);
if (ix > i_parm3) then ix := i_parm3;
b_match := false;
b_loop := true;
while b_loop do
begin
if (s_parm4[1] = s_parm2[ix]) then
begin
b_match := true;
for iz := 2 to i_long4 do
begin
if (s_parm4[iz] <> s_parm2[Pred(ix + iz)])
then b_match := false;
end;
if b_match then b_loop := false;
end;
if not b_match then
begin
Dec(ix);
if (ix < 1) then b_loop := false;
end;
end;
end
else ix := 0;
{ store the find answer }
sub_store_decimal(6, ix);
end; { sub_comm_sbak }
procedure TForm1.sub_comm_sinp(const pbyte_1 : byte);
{ updated 2006/06/11, 2005/03/23, 2004/01/18 }
{ perform the command $INP }
var
iz : integer;
sz : string;
begin
fb_string_input := false;
if (pbyte_1 = 1) then
begin
{ 123456789012345678 }
{ $INP 00101S,00201S }
{ get the input location into fi_input }
fi_input := StrToIntDef(Copy(fs_tpline, 6, 5), -1);
if (fi_input = -1) then
begin
sub_program_error('bad variable link');
end
else
begin
if (fs_tpline[11] = 'S') then Inc(fi_input, fi_delta_s);
{ output the prompt string }
sz := fns_string_parse(Copy(fs_tpline, 13, 200));
sub_memo_show(sz, 1);
{ set the values to drop out and to return to processing }
fb_program_loop := false;
fb_string_input := true;
edit_input.setfocus;
end;
end
else
begin
{ make sure there are no escape characters in fs_input }
fs_input := fns_blank_escapes(fs_input);
{ store the user input fs_input in fi_input }
fsa_var[fi_input] := fs_input;
{ add the user input to the memo_show }
iz := Length(Trim(fs_input));
if (iz > 0) then sub_memo_show(fs_input, 1);
end;
Application.ProcessMessages;
end; { sub_comm_sinp }
procedure TForm1.sub_comm_sisc;
{ updated 2003/10/28 }
{ is string made up of certain char }
var
i_result : integer;
s_parm2, s_parm3 : string;
i_long2, i_long3 : integer;
sz : string;
begin
{ 1234567890123456789012345 }
{ $isc 00101n,00099n,00032n }
{ parm2, parm3 }
s_parm2 := fns_string_eval(13);
s_parm3 := fns_string_eval(20);
i_long2 := Length(s_parm2);
i_long3 := Length(s_parm3);
i_result := 2;
if (i_long2 > 0) and (i_long3 > 0) then
begin
sz := StringOfChar(s_parm3[1], i_long2);
if (s_parm2 = sz) then i_result := 1;
end;
sub_store_decimal(6, i_result);
end; { sub_comm_sisc }
procedure TForm1.sub_comm_schs;
{ updated 2003/04/26 }
{ to perform the command $CH$ }
var
s_parm2 : string;
i_parm3 : integer;
i_char : integer;
sz : string;
begin
{ 1234567890123456789012345 }
{ $CH$ 00101n,00099n,00065n }
s_parm2 := fns_string_eval(13);
i_parm3 := fni_decimal_eval(20);
i_char := 32;
if (Length(s_parm2) = 0) then i_parm3 := 0
else i_char := Ord(s_parm2[1]);
if (i_parm3 < 0) then i_parm3 := 0;
if (i_parm3 > fi_max_length) then
begin
sub_program_error('string too long');
end
else
begin
{ make the string }
sz := StringOfChar(Chr(i_char), i_parm3);
sub_store_string(6, sz);
end;
end; { sub_comm_schs }
procedure TForm1.sub_comm_schd;
{ updated 2002/09/05 }
var
sz : string;
begin
{ 123456789012345678 }
{ $CHD 00401D,00101S }
sz := fns_string_eval(13);
if (Length(sz) = 0) then sz := Chr(0);
sub_store_decimal(6, Ord(sz[1]));
end; { sub_comm_schn }
procedure TForm1.sub_comm_scod;
{ updated 2006/01/17, 2003/12/25 }
{ encode a string }
var
s_parm2 : string;
i_char : integer;
i_long : integer;
iz : integer;
begin
{ 123456789012345678 }
{ $COD 00101n,00099n }
s_parm2 := fns_string_eval(13);
{ forty-seven }
i_long := Length(s_parm2);
for iz := 1 to i_long do
begin
i_char := Ord(s_parm2[iz]);
if (i_char > 32) and (i_char < 127) then
begin
Inc(i_char, 47);
if (i_char > 126) then Dec(i_char, 94);
s_parm2[iz] := Chr(i_char);
end;
end;
sub_store_string(6, s_parm2);
end; { sub_comm_scod }
procedure TForm1.sub_comm_stoe;
{ updated 2006/08/24, 2006/04/14 }
{ old toe a string }
var
s_parm2 : string;
s_parm3 : string;
i_bigprime : integer;
i_number : integer;
i_char : integer;
i_long : integer;
i_slip : integer;
i_which : integer;
cz : char;
iz : integer;
begin
{ 12345678901234567890123456789012 }
{ $TOE 00101n,00099n,00001n,00002n }
s_parm2 := fns_string_eval(13);
s_parm3 := fns_string_eval(20);
i_which := fni_decimal_eval(27);
if (i_which <> 1) then i_which := 2;
i_bigprime := 700000001;
s_parm3 := UpperCase(s_parm3);
if (Length(s_parm3) > 16) then s_parm3 := Copy(s_parm3, 1, 16);
{ change key to i_number }
i_number := 0;
i_long := Length(s_parm3);
for iz := 1 to i_long do
begin
cz := s_parm3[iz];
i_char := Ord(cz);
if ((cz >= '0') and (cz <= '9'))
or ((cz >= 'A') and (cz <= 'Z')) then
i_number := i_number * 10 + i_char;
if (i_number > i_bigprime) then i_number := i_number - i_bigprime;
end;
{ old toe }
i_long := Length(s_parm2);
for iz := 1 to i_long do
begin
{ get the next i_number }
i_number := (i_number * 3 + 35731) mod i_bigprime;
i_slip := (i_number div 103) mod 95 + 1;
i_char := Ord(s_parm2[iz]);
if (i_char >= 32) and (i_char <= 126) then
begin
if (i_which = 1) then i_char := i_char + i_slip
else i_char := i_char - i_slip;
if (i_char > 126) then Dec(i_char, 95)
else if (i_char < 32) then Inc(i_char, 95);
s_parm2[iz] := Chr(i_char);
end;
end;
sub_store_string(6, s_parm2);
end; { sub_comm_stoe }
procedure TForm1.sub_comm_spar;
{ updated 2002/09/05 }
{ extract a string from a character separated variable }
var
s_result : string;
s_parm2, s_parm3 : string;
i_parm4 : integer;
char_parm3 : char;
i_long : integer;
i_count : integer;
i_beg, i_end : integer;
iz : integer;
b_loop : boolean;
b_good : boolean;
begin
{ 12345678901234567890123456789012 }
{ spar 00101n,00099n,00032n,00022n }
{ parm2, parm3 and parm4 }
s_parm2 := fns_string_eval(13);
s_parm3 := fns_string_eval(20);
i_parm4 := fni_decimal_eval(27);
s_result := '';
b_good := true;
if (Length(s_parm2) = 0) then b_good := false;
if (Length(s_parm3) = 0) then b_good := false;
if b_good then
begin
char_parm3 := s_parm3[1];
i_long := Length(s_parm2);
if (s_parm2[i_long] <> char_parm3) then
begin
s_parm2 := s_parm2 + char_parm3;
Inc(i_long);
end;
i_beg := 1;
i_end := 0;
i_count := 0;
iz := 1;
b_loop := true;
while b_loop do
begin
if (s_parm2[iz] = char_parm3) then
begin
i_beg := Succ(i_end);
i_end := iz;
Inc(i_count);
if (i_count = i_parm4) then
begin
s_result := Copy(s_parm2, i_beg, i_end - i_beg);
b_loop := false;
end;
end;
Inc(iz);
if (iz > i_long) then b_loop := false;
end;
end;
sub_store_string(6, s_result);
end; { sub_comm_spar }
procedure TForm1.sub_comm_sdot;
{ updated 2006/05/12, 2003/11/07 }
{ find dot=byte of counted occurrence of string in other string }
var
s_parm2, s_parm3 : string;
i_parm4 : integer;
i_long3, i_long2 : integer;
i_max : integer;
i_count : integer;
i_dot : integer;
iw, ix, iz : integer;
b_loop : boolean;
b_match : boolean;
b_process : boolean;
begin
{ 12345678901234567890123456789012 }
{ $DOT 00401D,00001S,00001N,00102S }
{ get the string we want to look in }
s_parm2 := fns_string_eval(13);
{ get the string we want to find }
s_parm3 := fns_string_eval(20);
{ get the occurrence count of the string }
i_parm4 := fni_decimal_eval(27);
b_process := true;
i_long3 := Length(s_parm3);
i_long2 := Length(s_parm2);
if (i_parm4 < 1) or (i_parm4 > i_long2) then b_process := false;
if (i_long3 = 0) or (i_long3 > i_long2) then b_process := false;
i_dot := 0;
if b_process then
begin
{ ix is what we are looking for }
ix := 1;
{ i_max is the maximum that ix can be }
i_max := Succ(i_long2 - i_long3);
i_count := 0;
b_match := false;
b_loop := true;
while b_loop do
begin
if (s_parm3[1] = s_parm2[ix]) then
begin
b_match := true;
iw := Pred(ix);
for iz := 2 to i_long3 do
begin
if (s_parm3[iz] <> s_parm2[iw + iz])
then b_match := false;
end;
if b_match then
begin
Inc(i_count);
if (i_count = i_parm4) then
begin
b_loop := false;
i_dot := ix;
end;
{ so that occurrences cannot overlap }
ix := ix + Pred(i_long3);
end;
end;
Inc(ix);
if (ix > i_max) then b_loop := false;
end;
end;
{ store the find answer }
sub_store_decimal(6, i_dot);
end; { sub_comm_sdot }
procedure TForm1.sub_comm_sisp;
{ updated 2004/01/02 }
{ string is pattern of types }
var
i_result : integer;
s_parm2, s_parm3 : string;
i_long : integer;
i_byte : integer;
i_char1, i_char2 : integer;
iz : integer;
b_loop : boolean;
b_good : boolean;
begin
{ 1234567890123456789012345 }
{ $ISP 00101n,00099n,00032n }
{ parm2, parm3 and parm4 }
s_parm2 := fns_string_eval(13);
s_parm3 := fns_string_eval(20);
{ if i_result = 1 the strings have the same pattern }
i_result := 2;
b_good := true;
i_long := Length(s_parm2);
if (i_long <> Length(s_parm3)) then b_good := false;
if (i_long < 1) then b_good := false;
if b_good then
begin
i_result := 1;
i_byte := 1;
b_loop := true;
while b_loop do
begin
i_char1 := Ord(s_parm2[i_byte]);
i_char1 := fni_pattern(i_char1);
i_char2 := Ord(s_parm3[i_byte]);
i_char2 := fni_pattern(i_char2);
if (i_char1 <> i_char2) then
begin
i_result := 2;
b_loop := false;
end;
Inc(i_byte);
if (i_byte > i_long) then b_loop := false;
end;
end;
sub_store_decimal(6, i_result);
end; { sub_comm_sisp }
procedure TForm1.sub_comm_sist;
{ updated 2004/01/02 }
{ string is type of character }
var
i_result : integer;
s_parm2, s_parm3 : string;
i_long : integer;
i_byte : integer;
i_char1, i_char2 : integer;
iz : integer;
b_loop : boolean;
b_good : boolean;
begin
{ 1234567890123456789012345 }
{ $ist 00101n,00099n,00032n }
{ parm2, parm3 and parm4 }
s_parm2 := fns_string_eval(13);
s_parm3 := fns_string_eval(20);
{ if i_result = 1 the string is the same type }
i_result := 2;
b_good := true;
i_long := Length(s_parm2);
if (Length(s_parm3) < 1) then b_good := false;
if (i_long < 1) then b_good := false;
if b_good then
begin
i_char2 := Ord(s_parm3[1]);
i_char2 := fni_pattern(i_char2);
i_result := 1;
i_byte := 1;
b_loop := true;
while b_loop do
begin
i_char1 := Ord(s_parm2[i_byte]);
i_char1 := fni_pattern(i_char1);
if (i_char1 <> i_char2) then
begin
i_result := 2;
b_loop := false;
end;
Inc(i_byte);
if (i_byte > i_long) then b_loop := false;
end;
end;
sub_store_decimal(6, i_result);
end; { sub_comm_sist }
function TForm1.fni_pattern(const pi_char : integer) : integer;
{ updated 2002/11/07 }
var
i_result : integer;
begin
Case pi_char of
0 .. 31 : i_result := 1;
32 : i_result := 2;
33 .. 47 : i_result := 3;
48 .. 57 : i_result := 4;
58 .. 64 : i_result := 3;
65 .. 90 : i_result := 5;
91 .. 96 : i_result := 3;
97 .. 122 : i_result := 6;
123 .. 126 : i_result := 3;
else
i_result := 7;
end;
Result := i_result;
end; { fni_pattern }
procedure TForm1.sub_comm_scut;
{ updated 2004/03/04 }
{ cut part of a string to make another string }
var
s_parm2 : string;
i_parm3, i_parm4 : integer;
s_result : string;
i_length : integer;
b_good : boolean;
begin
{ 12345678901234567890123456789012 }
{ $CUT 00101n,00099n,00032n,00005n }
{ parm2, parm3 and parm4 }
s_parm2 := fns_string_eval(13);
i_parm3 := fni_decimal_eval(20);
i_parm4 := fni_decimal_eval(27);
s_result := '';
b_good := true;
i_length := Length(s_parm2);
if (i_length < 1) or (i_parm4 < 1) or (i_parm3 > i_length)
then b_good := false;
if (i_parm3 < 1) then i_parm3 := 1;
if b_good then s_result := Copy(s_parm2, i_parm3, i_parm4);
sub_store_string(6, s_result);
end; { sub_comm_scut }
procedure TForm1.sub_comm_soff;
{ updated 2003/05/27 }
{ cut off end of a string by length to make another string }
var
i_beg : integer;
i_length : integer;
s_parm2 : string;
i_parm3, i_parm4 : integer;
begin
{ 1234567890123456789012345 }
{ $OFF 00101n,00099n,00032n }
{ parm2 and parm3 }
s_parm2 := fns_string_eval(13);
i_parm3 := fni_decimal_eval(20);
i_beg := Length(s_parm2) - i_parm3 + 1;
if (i_beg < 1) then i_beg := 1;
i_length := Length(s_parm2) - i_beg + 1;
sub_store_string(6, Copy(s_parm2, i_beg, i_length));
end; { sub_comm_soff }
procedure TForm1.sub_comm_evar;
{ updated 2007/06/16, 2004/01/24 }
{ initialize variables, this line happens after last VARI command }
var
i_var_ct : integer;
begin
{ 123456789012345678 }
{ EVAR,00000N,00000N }
{ decimals }
{ i_var_ct is how many local decimals are in this subroutine }
i_var_ct := StrToIntDef(Copy(fs_tpline, 6, 5), 0);
{ fi_delta_d is how many decimals there are before this subroutine }
fi_delta_d := fia_delta_d[fii_delta_d];
Inc(fii_delta_d);
Inc(i_var_ct, fi_delta_d);
if (i_var_ct > fi_max_delta_d) then fi_max_delta_d := i_var_ct;
if (i_var_ct > fi_max_dvar) or (fii_delta_d > 1000) then
sub_program_error('too many decimals')
else fia_delta_d[fii_delta_d] := i_var_ct;
{ fii_delta_d is the index for fia_delta_d }
{ strings }
{ i_var_ct is how many local strings are in this subroutine }
i_var_ct := StrToIntDef(Copy(fs_tpline, 13, 5), 0);
{ fi_delta_s is how many strings there are before this subroutine }
fi_delta_s := fia_delta_s[fii_delta_s];
Inc(fii_delta_s);
Inc(i_var_ct, fi_delta_s);
if (i_var_ct > fi_max_delta_s) then fi_max_delta_s := i_var_ct;
if (i_var_ct > fi_max_svar) or (fii_delta_s > 1000) then
sub_program_error('too many strings')
else fia_delta_s[fii_delta_s] := i_var_ct;
{ fii_delta_s is the index for fia_delta_s }
end; { sub_comm_evar }
procedure TForm1.sub_comm_ends;
{ updated 2000/01/01 }
var
i_beg, i_end : integer;
iz : integer;
begin
{ decimals }
{ fi_delta_d is how many decimals there are before this subroutine }
i_beg := Succ(fi_delta_d);
i_end := fia_delta_d[fii_delta_d];
{ zero the places where the variables were }
for iz := i_beg to i_end do fea_var[iz] := 0;
Dec(fii_delta_d);
fi_delta_d := fia_delta_d[Pred(fii_delta_d)];
{ strings }
{ fi_delta_s is how many strings there are before this subroutine }
i_beg := Succ(fi_delta_s);
i_end := fia_delta_s[fii_delta_s];
{ set to nothing the strings where the variables were }
for iz := i_beg to i_end do fsa_var[iz] := '';
Dec(fii_delta_s);
fi_delta_s := fia_delta_s[Pred(fii_delta_s)];
{ pop from the stack where we return to }
fi_tpline := fia_sub[fii_sub];
Dec(fii_sub);
end; { sub_comm_ends }
procedure TForm1.sub_comm_ssys;
{ updated 2003/12/15 }
{ get various string program information }
var
i_parm2 : integer;
s_info : string;
begin
{ 123456789012345678 }
{ $SYS,00000N,00000N }
i_parm2 := fni_decimal_eval(13);
s_info := 'none';
{ application name and path }
if (i_parm2 = 1) then s_info := LowerCase(Application.ExeName);
{ current program subroutine }
if (i_parm2 = 2) then s_info := fns_subroutine(fi_tpline);
sub_store_string(6, s_info);
end; { sub_comm_ssys }
procedure TForm1.sub_comm_dsys;
{ updated 2007/06/16, 2006/04/30, 2004/06/19 }
{ get various numeric program information }
var
i_parm2 : integer;
d_info : double;
d_total : double;
i_long : integer;
iz : integer;
begin
{ 123456789012345678 }
{ $SYS,00000N,00000N }
i_parm2 := fni_decimal_eval(13);
d_info := 0;
{ memory used by strings }
if (i_parm2 = 1) then
begin
d_total := 0;
{ total string variables }
for iz := 1 to fi_max_svar do
begin
d_total := d_total + Length(fsa_var[iz]);
end;
{ total string array }
for iz := 1 to fi_max_sarray do
begin
d_total := d_total + Length(fsa_array[iz]);
end;
{ total run program and actual program strings }
for iz := 1 to 15000 do
begin
d_total := d_total + Length(fsa_tpline[iz]);
end;
d_info := d_total;
end;
{ total lines run }
if (i_parm2 = 2) then d_info := fd_total_lines;
sub_store_decimal(6, d_info);
end; { sub_comm_dsys }
function TForm1.fns_subroutine(const pi_line : integer) : string;
{ updated 2003/12/15 }
var
s_result : string;
sz : string;
i_line : integer;
iz : integer;
b_loop : boolean;
begin
s_result := 'none';
i_line := pi_line;
b_loop := true;
if (i_line < 1) or (i_line > fi_tpline_last) then b_loop := false;
while b_loop do
begin
sz := Copy(fsa_tpline[i_line], 1, 4);
if (sz = 'SUBR') then
begin
s_result := LowerCase(Copy(fsa_tpline[i_line], 6, 99));
iz := Pos(';', s_result);
if (iz > 0) then s_result := Copy(s_result, 1, Pred(iz));
b_loop := false;
end;
Dec(i_line);
if (i_line < 1) then b_loop := false;
end;
Result := s_result;
end; { fns_subroutine }
procedure TForm1.sub_comm_file(const pbyte_1 : byte);
{ updated 2006/06/02, 2006/05/23, 2004/04/08 }
{ put length of file in bytes in variable }
var
file_1 : file;
i_parm2 : integer;
s_filename1, s_filename2 : string;
i_long : integer;
ez : double;
sz : string;
iz : integer;
bz : boolean;
begin
if (pbyte_1 = 1) then { FDAT }
begin
{ 1234567890123456789012345 }
{ FDAT 00401n,00402n,00101n }
i_parm2 := StrToIntDef(Copy(fs_tpline, 13, 5), -1);
if (i_parm2 = -1) then
begin
sub_program_error('bad variable link');
end
else
begin
s_filename1 := fns_string_eval(20);
{ both parm1 and parm2 must receive values }
if (fs_tpline[18] = 'S') then Inc(i_parm2, fi_delta_s);
if (fs_tpline[11] = 'D') then Inc(fi_link, fi_delta_d);
ez := 0;
sz := '';
if FileExists(s_filename1) then
begin
ez := FileDateToDateTime(FileAge(s_filename1));
sz := UpperCase(FormatDateTime('dd-mmm-yyyy hh:nn:ss', ez));
end;
fea_var[fi_link] := ez;
fsa_var[i_parm2] := sz;
end;
end
else if (pbyte_1 = 2) then { FDEL }
begin
{ 123456789012345678 }
{ FDEL 00001n,00101n }
s_filename1 := fns_string_eval(13);
s_filename1 := Trim(s_filename1);
iz := Pos('*', s_filename1);
if (iz = 0) then iz := Pos('?', s_filename1);
{ get the name and delete the file }
bz := false;
if (iz = 0) then bz := DeleteFile(s_filename1);
if bz then iz := 1 else iz := 2;
{ save the results of fdel }
sub_store_decimal(6, iz);
end
else if (pbyte_1 = 3) then { FLEN }
begin
{ 123456789012345678 }
{ FLEN 00901p,00101n }
s_filename1 := fns_string_eval(13);
i_long := -1;
if FileExists(s_filename1) then
begin
AssignFile(file_1, s_filename1);
{$I-}
Reset(file_1, 1);
{ get the length of the file in bytes }
i_long := FileSize(file_1);
CloseFile(file_1);
{$I+}
if (IOResult <> 0) then i_long := -1;
end;
{ save the length of the file in bytes }
sub_store_decimal(6, i_long);
end
else if (pbyte_1 = 4) then { FREN }
begin
{ rename the file s_filename2 to s_filename1 }
{ 1234567890123456789012345 }
{ FREN 00001n,00101n,00102n }
s_filename1 := fns_string_eval(13);
s_filename2 := fns_string_eval(20);
s_filename1 := LowerCase(s_filename1);
bz := RenameFile(s_filename2, s_filename1);
if bz then iz := 1 else iz := 2;
{ save the results of fren }
sub_store_decimal(6, iz);
end;
end; { sub_comm_file }
procedure TForm1.sub_comm_frea;
{ updated 2003/09/15 }
{ record input from file fs_filename_1 }
var
file_1 : file;
chara_4096 : array[1..4096] of char;
i_bytes_read : integer;
i_byte : integer;
i_long : integer;
s_filename : string;
s_record : string;
iz : integer;
begin
{ 12345678901234567890123456789012 }
{ FREA 00901p,00101n,00902p,00072n }
{ FREA 00101n,00401p,00402p,00102n }
{ FREA s_rec1,s_filename1,nbyte1,nlong1 }
s_filename := fns_string_eval(13);
i_byte := fni_decimal_eval(20);
i_long := fni_decimal_eval(27);
s_record := '';
{ in Teapro the first byte 1 in Delphi it is 0 }
{ set FileMode to zero to make sure the file is read only }
if FileExists(s_filename) then
begin
AssignFile(file_1, s_filename);
{$I-}
FileMode := 0;
Reset(file_1, 1);
Seek(file_1, Pred(i_byte));
BlockRead(file_1, chara_4096, i_long, i_bytes_read);
CloseFile(file_1);
{$I+}
{ if no IO error }
if (IOResult = 0) then
begin
if (i_bytes_read < i_long) then i_long := i_bytes_read;
s_record := StringOfChar(' ', i_long);
for iz := 1 to i_long do s_record[iz] := chara_4096[iz];
end;
end;
sub_store_string(6, s_record);
end; { sub_comm_frea }
procedure TForm1.sub_comm_fwri;
{ updated 2003/09/15 }
{ record out to file file_1 }
var
file_1 : file;
chara_4096 : array[1..4096] of char;
i_file_length : integer;
i_bytes_written : integer;
i_byte : integer;
s_record : string;
s_filename : string;
iz : integer;
b_exists : boolean;
begin
{ 1234567890123456789012345 }
{ FWRI 00401p,00101n,00102n }
s_filename := fns_string_eval(13);
i_byte := fni_decimal_eval(20);
s_record := fns_string_eval(27);
{
showmessage('file=' + s_filename + '@');
showmessage(inttostr(i_byte) + ' @' + s_record + '@');
showmessage('record length=' + inttostr(length(s_record)));
}
{ in Teapro the first byte is 1 in Delphi it is 0 }
i_bytes_written := 0;
for iz := 1 to Length(s_record) do
chara_4096[iz] := s_record[iz];
s_filename := LowerCase(s_filename);
b_exists := FileExists(s_filename);
{ set FileMode to 1 for write only }
AssignFile(file_1, s_filename);
{$I-}
FileMode := 1;
if b_exists then Reset(file_1, 1)
else Rewrite(file_1, 1);
{ we cannot write beyond the length + 1 }
i_file_length := FileSize(file_1);
if (i_byte > Succ(i_file_length)) then i_byte := Succ(i_file_length);
Seek(file_1, Pred(i_byte));
BlockWrite(file_1, chara_4096, Length(s_record), i_bytes_written);
CloseFile(file_1);
{$I+}
{ faux line to get rid of IOResult }
if (IOResult <> 0) then iz := 0;
{ save the length written }
sub_store_decimal(6, i_bytes_written);
end; { sub_comm_fwri }
procedure TForm1.sub_comm_finp;
{ updated 2003/09/15 }
{ entire file input }
var
file_1 : file;
chara_4096 : array[1..4096] of char;
i_bytes_read : integer;
i_file_byte : integer;
i_file_length : integer;
s_filename : string;
s_data : string;
iz : integer;
b_loop : boolean;
b_open : boolean;
b_good : boolean;
begin
{ 123456789012345678 }
{ FINP 00901p,00101n }
s_filename := fns_string_eval(13);
s_data := '';
b_open := false;
b_good := FileExists(s_filename);
if b_good then
begin
{ open the file as an existing file }
{ set FileMode to zero to make sure the file is read only }
AssignFile(file_1, s_filename);
{$I-}
FileMode := 0;
Reset(file_1, 1);
{$I+}
if (IOResult = 0) then b_open := true
else b_good := false;
end;
if b_good then
begin
{ get the length of the file }
{$I-}
i_file_length := FileSize(file_1);
{$I+}
if (IOResult <> 0) then b_good := false;
end;
if b_good then
begin
if (i_file_length > fi_max_length) then
begin
b_good := false;
sub_program_error('file too big');
end;
end;
if b_good then
begin
s_data := StringOfChar(' ', i_file_length);
{ read the entire file into string sdata }
i_file_byte := 0;
b_loop := true;
while b_loop do
begin
{ finp }
Application.ProcessMessages;
{$I-}
Seek(file_1, i_file_byte);
BlockRead(file_1, chara_4096, 4096, i_bytes_read);
{$I+}
if (IOResult <> 0) then
begin
b_loop := false;
b_good := false;
end;
for iz := 1 to i_bytes_read do
s_data[i_file_byte + iz] := chara_4096[iz];
Inc(i_file_byte, i_bytes_read);
if (Succ(i_file_byte) >= i_file_length) then b_loop := false;
end;
end;
{ close the file if needed }
if b_open then CloseFile(file_1);
if not b_good then s_data := '';
sub_store_string(6, s_data);
end; { sub_comm_finp }
procedure TForm1.sub_comm_fout;
{ updated 2003/09/15 }
{ entire file output }
var
file_1 : file;
chara_4096 : array[1..4096] of char;
i_bytes_written : integer;
i_tbytes_written : integer;
i_string_byte : integer;
s_string : string;
s_record : string;
i_long : integer;
s_filename : string;
iz : integer;
b_loop : boolean;
b_open : boolean;
b_good : boolean;
begin
{ 1234567890123456789012345 }
{ FOUT 00401p,00101n,00102n }
s_filename := fns_string_eval(13);
s_string := fns_string_eval(20);
s_filename := LowerCase(s_filename);
i_long := Length(s_string);
i_tbytes_written := 0;
b_good := true;
b_open := false;
if b_good then
begin
AssignFile(file_1, s_filename);
{ open the file for write only }
{$I-}
FileMode := 1;
Rewrite(file_1, 1);
{$I+}
if (IOResult = 0) then b_open := true
else b_good := false;
end;
if b_good then
begin
i_string_byte := 1;
b_loop := true;
while b_loop do
begin
s_record := Copy(s_string, i_string_byte, 4096);
for iz := 1 to Length(s_record) do
chara_4096[iz] := s_record[iz];
{$I-}
Seek(file_1, Pred(i_string_byte));
BlockWrite(file_1, chara_4096, Length(s_record), i_bytes_written);
{$I+}
if (IOResult <> 0) then
begin
b_loop := false;
b_good := false;
end;
{ fout }
Application.ProcessMessages;
Inc(i_tbytes_written, i_bytes_written);
Inc(i_string_byte, i_bytes_written);
if (i_string_byte > i_long) then b_loop := false;
end;
end;
if b_open then CloseFile(file_1);
{ save the length written }
sub_store_decimal(6, i_tbytes_written);
end; { sub_comm_fout }
procedure TForm1.sub_comm_fsip;
{ updated 2005/04/16, 2003/09/15 }
{ read line from file fs_filename_1 }
var
file_1 : file;
chara_4096 : array[1..4096] of char;
s_char10 : string;
s_char13 : string;
i_bytes_read : integer;
i_oldbyte : integer;
i_newbyte : integer;
i_long : integer;
i_error : integer;
s_filename : string;
i_filelength : integer;
s_record : string;
b_good : boolean;
sz : string;
iz : integer;
begin
{ 1234567890123456789012345 }
{ FSIP 00901p,00101n,00902p }
{ FSIP s_reco,s_filename,d_byte }
s_filename := fns_string_eval(13);
i_oldbyte := fni_decimal_eval(20);
{ initialize }
s_char10 := Chr(10);
s_char13 := Chr(13);
i_newbyte := 0;
s_record := '';
i_bytes_read := 0;
if FileExists(s_filename) then b_good := true
else b_good := false;
if (i_oldbyte < 1) then b_good := false;
{ in Teapro the first byte 1 in Delphi it is 0 }
{ set FileMode to zero to make sure the file is read only }
if b_good then
begin
AssignFile(file_1, s_filename);
{$I-}
FileMode := 0;
Reset(file_1, 1);
i_filelength := FileSize(file_1);
if (i_oldbyte > i_filelength) then b_good := false;
if b_good then
begin
{ file begin at 0 in Delphi and at 1 in Teapro }
Seek(file_1, Pred(i_oldbyte));
BlockRead(file_1, chara_4096, 4096, i_bytes_read);
end;
CloseFile(file_1);
{$I+}
i_error := IOResult;
if (i_error > 0) then b_good := false;
if b_good then
begin
s_record := chara_4096;
s_record := Copy(s_record, 1, i_bytes_read);
i_newbyte := i_oldbyte + i_bytes_read;
{ look for a s_char10 = line feed }
i_long := Pos(s_char10, s_record);
if (i_long > 0) then
begin
{ s_char10 in i_long is s_char13 in i_long - 1 }
iz := i_long - 1;
sz := Copy(s_record, iz, 1);
if (sz = s_char13) then Dec(iz);
s_record := Copy(s_record, 1, iz);
i_newbyte := i_oldbyte + i_long;
end;
end;
end;
{ if no record was read }
if not b_good then i_newbyte := 0;
{ put the new position into the third parameter variable }
iz := StrToIntDef(Copy(fs_tpline, 20, 5), -1);
if (iz = -1) then
begin
sub_program_error('bad variable link');
end
else
begin
sub_store_decimal(20, i_newbyte);
{ put the string into the first parameter variable }
sub_store_string(6, s_record);
end;
end; { sub_comm_fsip }
procedure TForm1.sub_comm_fapp(const pbyte_1 : byte);
{ updated 2005/09/07, 2005/06/20, 2005/04/18, 2003/09/16 }
{ append line to file with lf or crlf added to end }
{ pbyte_1=1 means FAPP crlf }
{ pbyte_1=2 means FADD lf }
var
file_1 : file;
chara_4096 : array[1..4098] of char;
i_file_length : integer;
i_bytes_written : integer;
i_byte : integer;
s_record : string;
s_filename : string;
i_count : integer;
iz : integer;
b_loop : boolean;
b_error : boolean;
b_exists : boolean;
begin
{ 1234567890123456789012345 }
{ FAPP 00401p,00101n,00101n }
{ FADD 00401p,00101n,00101n }
s_filename := fns_string_eval(13);
s_record := fns_string_eval(20);
{ in Teapro the first file byte is 1 in Delphi it is 0 }
i_bytes_written := 0;
b_error := false;
if (Length(s_record) > 4096) then b_error := true;
if (pbyte_1 = 1) then
begin
s_record := s_record + Chr(13) + Chr(10);
end
else
begin
s_record := s_record + Chr(10);
end;
i_count := 0;
b_loop := true;
if b_error then b_loop := false;
while b_loop do
begin
{ chara_4096 is actually 4098 long }
for iz := 1 to Length(s_record) do
chara_4096[iz] := s_record[iz];
s_filename := LowerCase(s_filename);
b_exists := FileExists(s_filename);
{ set FileMode to 1 for write only }
AssignFile(file_1, s_filename);
{$I-}
FileMode := 1;
if b_exists then Reset(file_1, 1)
else Rewrite(file_1, 1);
i_file_length := FileSize(file_1);
i_byte := Succ(i_file_length);
Seek(file_1, Pred(i_byte));
BlockWrite(file_1, chara_4096, Length(s_record), i_bytes_written);
CloseFile(file_1);
{$I+}
if (IOResult > 0) then
begin
{ the record was not appended }
i_bytes_written := 0;
Inc(i_count);
if (i_count >= 10) then b_loop := false
{ FAPP or FADD }
else for iz := 0 to 1000 do Application.ProcessMessages;
end
{ the record was appended so we are done }
else b_loop := false;
end;
{ save the length written }
if not b_error then sub_store_decimal(6, i_bytes_written)
else sub_program_error('string > 4096');
end; { sub_comm_fapp }
function TForm1.fnd_decimal_eval(const pbyte_1 : byte) : double;
{ updated 2002/04/19 }
{ evaluate a number to a decimal }
var
i_value : integer;
c_z : char;
begin
{ C = single character }
{ D = local decimal }
{ G = global decimal }
{ N = literal number }
{ R = global string }
{ S = local string }
i_value := StrToIntDef(Copy(fs_tpline, pbyte_1, 5), -1);
if (i_value = -1) then
begin
sub_program_error('bad integer');
Result := 0;
end
else
begin
c_z := fs_tpline[pbyte_1 + 5];
Case c_z of
{ local variable }
'D' : Result := fea_var[i_value + fi_delta_d];
{ global variable }
'G' : Result := fea_var[i_value];
else
{ literal value }
Result := i_value;
end;
end;
end; { fnd_decimal_eval }
function TForm1.fni_decimal_eval(const pbyte_1 : byte) : integer;
{ updated 2004/03/03 }
{ evaluate a number to a decimal }
var
dz : double;
i_value : integer;
c_z : char;
i_result : integer;
begin
{ C = single character }
{ D = local decimal }
{ G = global decimal }
{ N = literal number }
{ R = global string }
{ S = local string }
i_value := StrToIntDef(Copy(fs_tpline, pbyte_1, 5), -1);
i_result := 0;
if (i_value = -1) then
begin
sub_program_error('bad integer');
end
else
begin
c_z := fs_tpline[pbyte_1 + 5];
Case c_z of
{ local variable }
'D' : dz := fea_var[i_value + fi_delta_d];
{ global variable }
'G' : dz := fea_var[i_value];
else
{ literal value }
dz := i_value;
end;
if (dz > MaxInt) then dz := MaxInt
else if (dz < -MaxInt) then dz := -MaxInt;
i_result := Round(dz);
end;
Result := i_result;
end; { fni_decimal_eval }
function TForm1.fnd_modulus(
const dp_number : double;
const dp_divisor : double) : double;
{ updated 2007/01/20, 2007/01/19 }
var
c_1 : comp;
c_2 : comp;
d_result : double;
begin
{ the sign of e_answer prevails }
c_1 := dp_number;
c_2 := Abs(dp_divisor);
d_result := 1;
if (c_2 > 0) then
begin
{ find mod }
d_result := c_1 - Int(c_1 / c_2) * c_2;
end
else sub_program_error('zero modulus');
Result := d_result;
end; { fnd_modulus }
function TForm1.fns_from_double(
const pd_num : double;
const pbyte_commas : byte) : string;
{ updated 2004/03/03 }
var
s_number : string;
iz : integer;
begin
{ pi2 is 1 to put in commas }
if (pbyte_commas = 1) then
s_number := FloatToStrF(pd_num, ffNumber, 16, 16)
else s_number := FloatToStrF(pd_num, ffFixed, 16, 16);
s_number := Trim(s_number);
{ not exponential and with decimal }
if (Pos('E', s_number) = 0) and (Pos('.', s_number) > 0) then
begin
iz := Length(s_number);
while (s_number[iz] = '0') do Dec(iz);
s_number := Copy(s_number, 1, iz);
{ take off a trailing decimal }
iz := Length(s_number);
if (s_number[iz] = '.') then s_number := Copy(s_number, 1, Pred(iz));
end;
Result := s_number;
end; { fns_from_double }
procedure TForm1.sub_double_from_string(
const ps1 : string;
var pe2 : double;
var pb3 : boolean);
{ updated 2004/09/25 }
{ convert a string to a double number }
var
s_digits : string;
s_number : string;
e_number : double;
s_test : string;
i_dot : integer;
b_loop : boolean;
b_negative : boolean;
b_enumber : boolean;
sz : string;
iy, iz : integer;
b_error : boolean;
begin
e_number := 0;
b_error := false;
b_negative := false;
s_digits := '0123456789';
s_number := UpperCase(Trim(ps1));
if (Length(s_number) = 0) then b_error := true;
if not b_error then
begin
if (s_number[1] = '+') then s_number := Copy(s_number, 2, 999)
else if (s_number[1] = '-') then
begin
s_number := Copy(s_number, 2, 999);
b_negative := true;
end;
end;
if (Length(s_number) = 0) then b_error := true;
if not b_error then
begin
if (Pos(s_number[1], '+-') > 0) then b_error := true;
end;
if not b_error then
begin
{ take out any commas ie. ,000}
b_loop := true;
while b_loop do
begin
iz := Pos(',', s_number);
if (iz = 0) then b_loop := false
else
begin
if (iz = 1) then b_error := true;
sz := Copy(s_number, Succ(iz), 3);
iy := StrToIntDef(sz, -1);
if (iy >= 0) then Delete(s_number, iz, 1)
else
begin
b_error := true;
b_loop := false;
end;
end;
end;
if (Length(s_number) = 0) then b_error := true;
end;
if not b_error then
begin
s_test := s_number;
{ validate the E part if any }
iz := Pos('E', s_test);
if (iz > 0) then
begin
if (iz < 4) or (Length(s_test) - iz < 1) then b_error := true;
if not b_error then
begin
{ sz is part following the E }