mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-10-23 21:11:40 +02:00

+ darwin/ppc64 support + val/str/read(ln)/write(ln) support for enums + simple cse at the node tree level + if-node simplify support + simple ssa support for memory locations + support for optional overflow/rangecheck boolean parameters for operators * a lot of unification of the ppc32/ppc64 code generators ........ r6380 | jonas | 2007-02-08 21:25:36 +0100 (Thu, 08 Feb 2007) | 4 lines Changed paths: M /branches/fpc_2_3/compiler/ncgld.pas M /branches/fpc_2_3/compiler/tgobj.pas A /branches/fpc_2_3/tests/webtbs/tw8283.pp + support for replacing the memory location of a temp (including local variables) with that of another temp to avoid unnecessary copies (mantis #8283) ........ r6381 | jonas | 2007-02-08 22:53:36 +0100 (Thu, 08 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/nflw.pas A /branches/fpc_2_3/tests/webtbs/tw8282.pp + simplify support for ifn (based on patch by Florian) ........ r6386 | peter | 2007-02-09 13:48:53 +0100 (Fri, 09 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/htypechk.pas M /branches/fpc_2_3/compiler/ncal.pas M /branches/fpc_2_3/compiler/symconst.pas * overflow,rangecheck optional parameters for operators, patch from 8281 ........ r6391 | jonas | 2007-02-09 23:52:13 +0100 (Fri, 09 Feb 2007) | 4 lines Changed paths: M /branches/fpc_2_3/compiler/powerpc/agppcgas.pas M /branches/fpc_2_3/compiler/powerpc64/cpunode.pas D /branches/fpc_2_3/compiler/powerpc64/nppcinl.pas M /branches/fpc_2_3/compiler/ppcgen/ngppcinl.pas * merged fsqrt(s) support to common powerpc unit, activate for ppc32 if -Op970 is used (still default for ppc64, since default cpu there is already ppc970) ........ r6394 | jonas | 2007-02-10 18:58:47 +0100 (Sat, 10 Feb 2007) | 4 lines Changed paths: M /branches/fpc_2_3/compiler/powerpc/cgcpu.pas M /branches/fpc_2_3/compiler/powerpc64/cgcpu.pas M /branches/fpc_2_3/compiler/ppcgen/cgppc.pas * adapted a_jmp_name for darwin/ppc64 * merged g_intf_wrapper for ppc32 and ppc64, and added darwin/ppc64 support to it ........ r6396 | jonas | 2007-02-10 20:16:06 +0100 (Sat, 10 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/cgobj.pas + darwin/ppc64 support for g_indirect_sym_load ........ r6397 | jonas | 2007-02-10 20:22:49 +0100 (Sat, 10 Feb 2007) | 4 lines Changed paths: M /branches/fpc_2_3/compiler/powerpc/cgcpu.pas M /branches/fpc_2_3/compiler/powerpc64/cgcpu.pas M /branches/fpc_2_3/compiler/ppcgen/cgppc.pas + darwin/ppc64 support to ppc64's fixref * moved ppc32 a_load_store to cgppc and use it for darwin/ppc64 as well (its relocatable symbols are only 32 bits large) ........ r6399 | jonas | 2007-02-10 22:02:37 +0100 (Sat, 10 Feb 2007) | 4 lines Changed paths: M /branches/fpc_2_3/compiler/systems.pas + system_x86_64_darwin identifier + set default source system for system_x86_64_darwin and system_powerpc64_darwin ........ r6404 | jonas | 2007-02-10 23:01:23 +0100 (Sat, 10 Feb 2007) | 5 lines Changed paths: M /branches/fpc_2_3/compiler/aasmdata.pas M /branches/fpc_2_3/compiler/aggas.pas M /branches/fpc_2_3/compiler/cgobj.pas M /branches/fpc_2_3/compiler/cgutils.pas M /branches/fpc_2_3/compiler/cresstr.pas M /branches/fpc_2_3/compiler/dbgdwarf.pas M /branches/fpc_2_3/compiler/dbgstabs.pas M /branches/fpc_2_3/compiler/ncgutil.pas M /branches/fpc_2_3/compiler/ogelf.pas M /branches/fpc_2_3/compiler/pdecvar.pas M /branches/fpc_2_3/compiler/pmodules.pas M /branches/fpc_2_3/compiler/symdef.pas M /branches/fpc_2_3/compiler/systems.pas + system_x86_64_darwin identifier + systems_darwin set which collects all darwin variants + added support for darwin/ppc64 and darwin/x86_64 where needed in the generic code ........ r6406 | jonas | 2007-02-10 23:24:32 +0100 (Sat, 10 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/cgobj.pas * ifdef cpu64 -> ifdef cpu64bit ........ r6409 | jonas | 2007-02-11 00:34:04 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/pdecvar.pas * fixed ppc64 compilation ........ r6413 | jonas | 2007-02-11 12:41:27 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/rtl/bsd/system.pp M /branches/fpc_2_3/rtl/darwin/powerpc/sig_cpu.inc M /branches/fpc_2_3/rtl/darwin/signal.inc + darwin/ppc64 support for signal routines ........ r6415 | jonas | 2007-02-11 13:54:53 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/systems/i_linux.pas * set abi of linux/ppc64 to abi_powerpc_sysv ........ r6416 | jonas | 2007-02-11 13:55:51 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/powerpc64/cputarg.pas M /branches/fpc_2_3/compiler/systems/i_bsd.pas M /branches/fpc_2_3/compiler/systems/t_bsd.pas + darwin/ppc64 source and target information ........ r6418 | jonas | 2007-02-11 14:19:55 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/rtl/powerpc64/math.inc * darwin/ppc64 compilation fixes ........ r6419 | jonas | 2007-02-11 14:22:22 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/powerpc/cgcpu.pas M /branches/fpc_2_3/compiler/powerpc64/cgcpu.pas M /branches/fpc_2_3/compiler/ppcgen/cgppc.pas * darwin/ppc64 needs the 32 bit version of a_loadaddr_ref_reg ........ r6420 | jonas | 2007-02-11 14:22:55 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/utils/fpcm/fpcmmain.pp + darwin/ppc64 support ........ r6426 | jonas | 2007-02-11 16:13:19 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/powerpc64/rappcgas.pas * fixed refaddr parsing for darwin/ppc64 ........ r6427 | jonas | 2007-02-11 16:14:21 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/powerpc/agppcgas.pas M /branches/fpc_2_3/compiler/powerpc64/agppcgas.pas A /branches/fpc_2_3/compiler/ppcgen/agppcutl.pas * moved ppc32/ppc64 assembler writer helpers to a common unit ........ r6430 | jonas | 2007-02-11 17:53:23 +0100 (Sun, 11 Feb 2007) | 4 lines Changed paths: D /branches/fpc_2_3/rtl/darwin/powerpc/sig_cpu.inc D /branches/fpc_2_3/rtl/darwin/powerpc/sighnd.inc A /branches/fpc_2_3/rtl/darwin/powerpc64 A /branches/fpc_2_3/rtl/darwin/powerpc64/sig_cpu.inc A /branches/fpc_2_3/rtl/darwin/powerpc64/sighnd.inc A /branches/fpc_2_3/rtl/darwin/ppcgen A /branches/fpc_2_3/rtl/darwin/ppcgen/ppchnd.inc (from /branches/fpc_2_3/rtl/darwin/powerpc/sighnd.inc:6422) A /branches/fpc_2_3/rtl/darwin/ppcgen/sig_ppc.inc (from /branches/fpc_2_3/rtl/darwin/powerpc/sig_cpu.inc:6422) M /branches/fpc_2_3/rtl/darwin/signal.inc * fixed ppc/ppc64 signal include handling (both real files are in ppcgen, dummies in powerpc and powerpc64 which include those files) (1st step because pre-commit filter can't handle replaced files) ........ r6431 | jonas | 2007-02-11 17:53:47 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: A /branches/fpc_2_3/rtl/darwin/powerpc/sig_cpu.inc A /branches/fpc_2_3/rtl/darwin/powerpc/sighnd.inc * second step of signal include patch ........ r6432 | jonas | 2007-02-11 19:00:12 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/systems/t_bsd.pas * changed darwin checks to use systems_darwin constant ........ r6433 | jonas | 2007-02-11 19:05:38 +0100 (Sun, 11 Feb 2007) | 3 lines Changed paths: M /branches/fpc_2_3/compiler/powerpc64/cgcpu.pas * handle non-multiple-of-4 offsets with 64 bit loads/stores for darwin/ppc64 ........ r6434 | jonas | 2007-02-11 19:05:56 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: D /branches/fpc_2_3/compiler/powerpc/agppcgas.pas D /branches/fpc_2_3/compiler/powerpc64/agppcgas.pas A /branches/fpc_2_3/compiler/ppcgen/agppcgas.pas (from /branches/fpc_2_3/compiler/ppcgen/agppcutl.pas:6427) D /branches/fpc_2_3/compiler/ppcgen/agppcutl.pas * completely merged ppc assembler writers ........ r6435 | jonas | 2007-02-11 19:06:40 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/rtl/darwin/console.pp M /branches/fpc_2_3/rtl/darwin/termiosproc.inc * fixed 64 bit compilation ........ r6436 | jonas | 2007-02-11 19:09:28 +0100 (Sun, 11 Feb 2007) | 3 lines Changed paths: M /branches/fpc_2_3/packages/extra/Makefile.fpc * universal interfaces aren't 64 bit ready yet -> only compile for darwin/ppc and darwin/i386 ........ r6438 | jonas | 2007-02-11 19:22:34 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: A /branches/fpc_2_3/tests/test/cg/obj/darwin/powerpc64 A /branches/fpc_2_3/tests/test/cg/obj/darwin/powerpc64/ctest.o A /branches/fpc_2_3/tests/test/cg/obj/darwin/powerpc64/tcext3.o A /branches/fpc_2_3/tests/test/cg/obj/darwin/powerpc64/tcext4.o A /branches/fpc_2_3/tests/test/cg/obj/darwin/powerpc64/tcext5.o + compiled for darwin/ppc64 ........ r6439 | jonas | 2007-02-11 20:24:42 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/ppcgen/cgppc.pas * patch from Thomas to fix linux/ppc64 ........ r6440 | jonas | 2007-02-11 20:25:15 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/systems.pas * fixed setting source OS for darwin/ppc64 ........ r6444 | florian | 2007-02-11 22:24:20 +0100 (Sun, 11 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/globtype.pas M /branches/fpc_2_3/compiler/nopt.pas M /branches/fpc_2_3/compiler/nutils.pas M /branches/fpc_2_3/compiler/optcse.pas M /branches/fpc_2_3/compiler/psub.pas + first node cse implementation ........ r6445 | jonas | 2007-02-11 22:30:07 +0100 (Sun, 11 Feb 2007) | 6 lines Changed paths: M /branches/fpc_2_3/compiler/cresstr.pas * hack to work around strange darwin/ppc64 linker bug: it seems to have problems if you put a global symbol at the end of a section without any data following (at least in case of the resource strings section) -> add dummy byte at the end for darwin/ppc64 (otherwise it messes up the address of the first symbol stub entry) ........ r6449 | jonas | 2007-02-11 23:23:44 +0100 (Sun, 11 Feb 2007) | 4 lines Changed paths: M /branches/fpc_2_3/compiler/systems/i_bsd.pas * cpupowerpc is defined for both ppc32 and ppc64 -> changed to cpupowerpc32 to avoid defining source wrongly on ppc64 ........ r6450 | jonas | 2007-02-11 23:26:34 +0100 (Sun, 11 Feb 2007) | 3 lines Changed paths: M /branches/fpc_2_3/compiler/ppcgen/ngppcset.pas * disable jump tables for darwin/ppc64 for now, don't work yet for some reason ........ r6451 | florian | 2007-02-11 23:54:37 +0100 (Sun, 11 Feb 2007) | 3 lines Changed paths: M /branches/fpc_2_3/compiler/ncal.pas M /branches/fpc_2_3/compiler/nutils.pas M /branches/fpc_2_3/compiler/optcse.pas * improved cse * better complexity calculation for subscript nodes with classes or interfaces ........ r6456 | jonas | 2007-02-12 19:33:22 +0100 (Mon, 12 Feb 2007) | 4 lines Changed paths: M /branches/fpc_2_3/compiler/nutils.pas + support for notn,shln,shrn,equaln,unequaln,gtn,gten,ltn,lten in node_cplexity() * mark muln,divn,modn as more complex ........ r6469 | jonas | 2007-02-13 15:56:01 +0100 (Tue, 13 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/optcse.pas * fixed when cross-compiling a 64 bit compiler from a 32 bit platform ........ r6471 | jonas | 2007-02-13 16:17:16 +0100 (Tue, 13 Feb 2007) | 3 lines Changed paths: M /branches/fpc_2_3/compiler/powerpc64/cputarg.pas * include stabs support (can work on darwin/ppc64, but doesn't work yet) ........ r6473 | jonas | 2007-02-13 16:45:48 +0100 (Tue, 13 Feb 2007) | 3 lines Changed paths: M /branches/fpc_2_3/compiler/powerpc64/cgcpu.pas M /branches/fpc_2_3/compiler/powerpc64/cpupara.pas * R2 is a volatile and usable register under darwin/ppc64 * R13 is a reserved non-volatile register under darwin/ppc64 (tls) ........ r6479 | jonas | 2007-02-13 20:40:50 +0100 (Tue, 13 Feb 2007) | 3 lines Changed paths: M /branches/fpc_2_3/compiler/systems/i_bsd.pas * maxCrecordalign seems to have to be 8 rather 4, in spite of what the ABI docs say (although they are contradictory to some extent) ........ r6487 | jonas | 2007-02-14 15:57:40 +0100 (Wed, 14 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/tests/webtbs/tw8153a.pp * fixed for darwin/ppc64 ........ r6488 | jonas | 2007-02-14 15:58:56 +0100 (Wed, 14 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/tests/webtbs/tw7851a.pp * fixed for darwin/ppc64 ........ r6494 | jonas | 2007-02-15 19:36:55 +0100 (Thu, 15 Feb 2007) | 3 lines Changed paths: M /branches/fpc_2_3/compiler/systems/i_bsd.pas * set default debug info for darwin/ppc64 to dwarf2 since it works better than stabs currently ........ r6500 | jonas | 2007-02-15 21:38:16 +0100 (Thu, 15 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/version.pas * updated version to 2.3.0 ........ r6505 | jonas | 2007-02-15 22:39:28 +0100 (Thu, 15 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/version.pas * changed version to 2.3.1 ........ r6511 | jonas | 2007-02-16 15:17:24 +0100 (Fri, 16 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/powerpc64/itcpugas.pas * system_powerpc_darwin -> system_powerpc64_darwin ........ r6546 | daniel | 2007-02-18 15:48:54 +0100 (Sun, 18 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/ncginl.pas M /branches/fpc_2_3/compiler/ncgld.pas M /branches/fpc_2_3/compiler/ncgrtti.pas M /branches/fpc_2_3/compiler/ncnv.pas M /branches/fpc_2_3/compiler/ninl.pas M /branches/fpc_2_3/compiler/nld.pas M /branches/fpc_2_3/compiler/nutils.pas M /branches/fpc_2_3/compiler/pinline.pas M /branches/fpc_2_3/rtl/inc/astrings.inc M /branches/fpc_2_3/rtl/inc/compproc.inc M /branches/fpc_2_3/rtl/inc/sstrings.inc M /branches/fpc_2_3/rtl/inc/text.inc M /branches/fpc_2_3/rtl/inc/wstrings.inc + Val/str/read/write support for enumeration types. ........ r6547 | daniel | 2007-02-18 17:01:20 +0100 (Sun, 18 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/rtl/inc/sstrings.inc * Fix val code that I broke. ........ r6571 | daniel | 2007-02-20 09:27:44 +0100 (Tue, 20 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/rtl/inc/astrings.inc M /branches/fpc_2_3/rtl/inc/sstrings.inc M /branches/fpc_2_3/rtl/inc/text.inc M /branches/fpc_2_3/rtl/inc/wstrings.inc * o2s -> ord2str, s2o -> str2ord ........ r6572 | daniel | 2007-02-20 09:33:30 +0100 (Tue, 20 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/ncgld.pas M /branches/fpc_2_3/compiler/ncgrtti.pas M /branches/fpc_2_3/compiler/ninl.pas M /branches/fpc_2_3/compiler/nld.pas * o2s -> ord2str, s2o -> str2ord ........ r6574 | daniel | 2007-02-20 12:07:58 +0100 (Tue, 20 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/rtl/inc/compproc.inc * o2s -> ord2str, s2o -> str2ord ........ r6578 | daniel | 2007-02-20 22:18:49 +0100 (Tue, 20 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/rtl/inc/text.inc * Change longint to valsint. ........ r6579 | daniel | 2007-02-20 22:29:09 +0100 (Tue, 20 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/ninl.pas * Handle ordinal currency types. ........ r6580 | jonas | 2007-02-20 22:29:11 +0100 (Tue, 20 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/ncgrtti.pas * fixed compilation for cpurequiresproperalignment ........ r6581 | jonas | 2007-02-20 22:30:21 +0100 (Tue, 20 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/ninl.pas * fixed typo ........ r6582 | daniel | 2007-02-20 22:36:19 +0100 (Tue, 20 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/ninl.pas * Set is_real to true. ........ r6590 | jonas | 2007-02-21 20:23:54 +0100 (Wed, 21 Feb 2007) | 2 lines Changed paths: M /branches/fpc_2_3/compiler/systems/i_bsd.pas * set tf_dwarf_only_local_labels for darwin/ppc64 git-svn-id: trunk@6720 -
1293 lines
30 KiB
PHP
1293 lines
30 KiB
PHP
{
|
|
This file is part of the Free Pascal run time library.
|
|
Copyright (c) 1999-2000 by the Free Pascal development team
|
|
|
|
See the file COPYING.FPC, included in this distribution,
|
|
for details about the copyright.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
**********************************************************************}
|
|
|
|
{****************************************************************************
|
|
subroutines for string handling
|
|
****************************************************************************}
|
|
|
|
procedure fpc_Shortstr_SetLength(var s:shortstring;len:SizeInt);[Public,Alias : 'FPC_SHORTSTR_SETLENGTH']; compilerproc;
|
|
begin
|
|
if Len>255 then
|
|
Len:=255;
|
|
s[0]:=chr(len);
|
|
end;
|
|
|
|
function fpc_shortstr_copy(const s : shortstring;index : SizeInt;count : SizeInt): shortstring;compilerproc;
|
|
begin
|
|
if count<0 then
|
|
count:=0;
|
|
if index>1 then
|
|
dec(index)
|
|
else
|
|
index:=0;
|
|
if index>length(s) then
|
|
count:=0
|
|
else
|
|
if count>length(s)-index then
|
|
count:=length(s)-index;
|
|
fpc_shortstr_Copy[0]:=chr(Count);
|
|
Move(s[Index+1],fpc_shortstr_Copy[1],Count);
|
|
end;
|
|
|
|
|
|
procedure delete(var s : shortstring;index : SizeInt;count : SizeInt);
|
|
begin
|
|
if index<=0 then
|
|
exit;
|
|
if (Index<=Length(s)) and (Count>0) then
|
|
begin
|
|
if Count>length(s)-Index then
|
|
Count:=length(s)-Index+1;
|
|
s[0]:=Chr(length(s)-Count);
|
|
if Index<=Length(s) then
|
|
Move(s[Index+Count],s[Index],Length(s)-Index+1);
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure insert(const source : shortstring;var s : shortstring;index : SizeInt);
|
|
var
|
|
cut,srclen,indexlen : SizeInt;
|
|
begin
|
|
if index<1 then
|
|
index:=1;
|
|
if index>length(s) then
|
|
index:=length(s)+1;
|
|
indexlen:=Length(s)-Index+1;
|
|
srclen:=length(Source);
|
|
if SizeInt(length(source)+length(s))>=sizeof(s) then
|
|
begin
|
|
cut:=SizeInt(length(source)+length(s))-sizeof(s)+1;
|
|
if cut>indexlen then
|
|
begin
|
|
dec(srclen,cut-indexlen);
|
|
indexlen:=0;
|
|
end
|
|
else
|
|
dec(indexlen,cut);
|
|
end;
|
|
move(s[Index],s[Index+srclen],indexlen);
|
|
move(Source[1],s[Index],srclen);
|
|
s[0]:=chr(index+srclen+indexlen-1);
|
|
end;
|
|
|
|
|
|
procedure insert(source : Char;var s : shortstring;index : SizeInt);
|
|
var
|
|
indexlen : SizeInt;
|
|
begin
|
|
if index<1 then
|
|
index:=1;
|
|
if index>length(s) then
|
|
index:=length(s)+1;
|
|
indexlen:=Length(s)-Index+1;
|
|
if (length(s)+1=sizeof(s)) and (indexlen>0) then
|
|
dec(indexlen);
|
|
move(s[Index],s[Index+1],indexlen);
|
|
s[Index]:=Source;
|
|
s[0]:=chr(index+indexlen);
|
|
end;
|
|
|
|
|
|
function pos(const substr : shortstring;const s : shortstring):SizeInt;
|
|
var
|
|
i,MaxLen : SizeInt;
|
|
pc : pchar;
|
|
begin
|
|
Pos:=0;
|
|
if Length(SubStr)>0 then
|
|
begin
|
|
MaxLen:=Length(s)-Length(SubStr);
|
|
i:=0;
|
|
pc:=@s[1];
|
|
while (i<=MaxLen) do
|
|
begin
|
|
inc(i);
|
|
if (SubStr[1]=pc^) and
|
|
(CompareChar(Substr[1],pc^,Length(SubStr))=0) then
|
|
begin
|
|
Pos:=i;
|
|
exit;
|
|
end;
|
|
inc(pc);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
{Faster when looking for a single char...}
|
|
function pos(c:char;const s:shortstring):SizeInt;
|
|
var
|
|
i : SizeInt;
|
|
pc : pchar;
|
|
begin
|
|
pc:=@s[1];
|
|
for i:=1 to length(s) do
|
|
begin
|
|
if pc^=c then
|
|
begin
|
|
pos:=i;
|
|
exit;
|
|
end;
|
|
inc(pc);
|
|
end;
|
|
pos:=0;
|
|
end;
|
|
|
|
|
|
function fpc_char_copy(c:char;index : SizeInt;count : SizeInt): shortstring;compilerproc;
|
|
begin
|
|
if (index=1) and (Count>0) then
|
|
fpc_char_Copy:=c
|
|
else
|
|
fpc_char_Copy:='';
|
|
end;
|
|
|
|
function pos(const substr : shortstring;c:char): SizeInt;
|
|
begin
|
|
if (length(substr)=1) and (substr[1]=c) then
|
|
Pos:=1
|
|
else
|
|
Pos:=0;
|
|
end;
|
|
|
|
|
|
{$ifdef IBM_CHAR_SET}
|
|
const
|
|
UpCaseTbl : shortstring[7]=#154#142#153#144#128#143#165;
|
|
LoCaseTbl : shortstring[7]=#129#132#148#130#135#134#164;
|
|
{$endif}
|
|
|
|
function upcase(c : char) : char;
|
|
{$IFDEF IBM_CHAR_SET}
|
|
var
|
|
i : longint;
|
|
{$ENDIF}
|
|
begin
|
|
if (c in ['a'..'z']) then
|
|
upcase:=char(byte(c)-32)
|
|
else
|
|
{$IFDEF IBM_CHAR_SET}
|
|
begin
|
|
i:=Pos(c,LoCaseTbl);
|
|
if i>0 then
|
|
upcase:=UpCaseTbl[i]
|
|
else
|
|
upcase:=c;
|
|
end;
|
|
{$ELSE}
|
|
upcase:=c;
|
|
{$ENDIF}
|
|
end;
|
|
|
|
|
|
function upcase(const s : shortstring) : shortstring;
|
|
var
|
|
i : longint;
|
|
begin
|
|
upcase[0]:=s[0];
|
|
for i := 1 to length (s) do
|
|
upcase[i] := upcase (s[i]);
|
|
end;
|
|
|
|
|
|
function lowercase(c : char) : char;overload;
|
|
{$IFDEF IBM_CHAR_SET}
|
|
var
|
|
i : longint;
|
|
{$ENDIF}
|
|
begin
|
|
if (c in ['A'..'Z']) then
|
|
lowercase:=char(byte(c)+32)
|
|
else
|
|
{$IFDEF IBM_CHAR_SET}
|
|
begin
|
|
i:=Pos(c,UpCaseTbl);
|
|
if i>0 then
|
|
lowercase:=LoCaseTbl[i]
|
|
else
|
|
lowercase:=c;
|
|
end;
|
|
{$ELSE}
|
|
lowercase:=c;
|
|
{$ENDIF}
|
|
end;
|
|
|
|
|
|
function lowercase(const s : shortstring) : shortstring; overload;
|
|
var
|
|
i : longint;
|
|
begin
|
|
lowercase [0]:=s[0];
|
|
for i:=1 to length(s) do
|
|
lowercase[i]:=lowercase (s[i]);
|
|
end;
|
|
|
|
|
|
const
|
|
HexTbl : array[0..15] of char='0123456789ABCDEF';
|
|
|
|
function hexstr(val : longint;cnt : byte) : shortstring;
|
|
var
|
|
i : longint;
|
|
begin
|
|
hexstr[0]:=char(cnt);
|
|
for i:=cnt downto 1 do
|
|
begin
|
|
hexstr[i]:=hextbl[val and $f];
|
|
val:=val shr 4;
|
|
end;
|
|
end;
|
|
|
|
function octstr(val : longint;cnt : byte) : shortstring;
|
|
var
|
|
i : longint;
|
|
begin
|
|
octstr[0]:=char(cnt);
|
|
for i:=cnt downto 1 do
|
|
begin
|
|
octstr[i]:=hextbl[val and 7];
|
|
val:=val shr 3;
|
|
end;
|
|
end;
|
|
|
|
|
|
function binstr(val : longint;cnt : byte) : shortstring;
|
|
var
|
|
i : longint;
|
|
begin
|
|
binstr[0]:=char(cnt);
|
|
for i:=cnt downto 1 do
|
|
begin
|
|
binstr[i]:=char(48+val and 1);
|
|
val:=val shr 1;
|
|
end;
|
|
end;
|
|
|
|
|
|
function hexstr(val : int64;cnt : byte) : shortstring;
|
|
var
|
|
i : longint;
|
|
begin
|
|
hexstr[0]:=char(cnt);
|
|
for i:=cnt downto 1 do
|
|
begin
|
|
hexstr[i]:=hextbl[val and $f];
|
|
val:=val shr 4;
|
|
end;
|
|
end;
|
|
|
|
|
|
function octstr(val : int64;cnt : byte) : shortstring;
|
|
var
|
|
i : longint;
|
|
begin
|
|
octstr[0]:=char(cnt);
|
|
for i:=cnt downto 1 do
|
|
begin
|
|
octstr[i]:=hextbl[val and 7];
|
|
val:=val shr 3;
|
|
end;
|
|
end;
|
|
|
|
|
|
function binstr(val : int64;cnt : byte) : shortstring;
|
|
var
|
|
i : longint;
|
|
begin
|
|
binstr[0]:=char(cnt);
|
|
for i:=cnt downto 1 do
|
|
begin
|
|
binstr[i]:=char(48+val and 1);
|
|
val:=val shr 1;
|
|
end;
|
|
end;
|
|
|
|
|
|
function hexstr(val : pointer) : shortstring;
|
|
var
|
|
i : longint;
|
|
v : ptrint;
|
|
begin
|
|
v:=ptrint(val);
|
|
hexstr[0]:=chr(sizeof(pointer)*2);
|
|
for i:=sizeof(pointer)*2 downto 1 do
|
|
begin
|
|
hexstr[i]:=hextbl[v and $f];
|
|
v:=v shr 4;
|
|
end;
|
|
end;
|
|
|
|
|
|
function space (b : byte): shortstring;
|
|
begin
|
|
space[0] := chr(b);
|
|
FillChar (Space[1],b,' ');
|
|
end;
|
|
|
|
|
|
{*****************************************************************************
|
|
Str() Helpers
|
|
*****************************************************************************}
|
|
|
|
procedure fpc_shortstr_SInt(v : valSInt;len : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_SINT']; compilerproc;
|
|
begin
|
|
int_str(v,s);
|
|
if length(s)<len then
|
|
s:=space(len-length(s))+s;
|
|
end;
|
|
|
|
procedure fpc_shortstr_UInt(v : valUInt;len : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_UINT']; compilerproc;
|
|
begin
|
|
int_str(v,s);
|
|
if length(s)<len then
|
|
s:=space(len-length(s))+s;
|
|
end;
|
|
|
|
{$ifndef CPU64}
|
|
|
|
procedure fpc_shortstr_qword(v : qword;len : longint;out s : shortstring);[public,alias:'FPC_SHORTSTR_QWORD']; compilerproc;
|
|
begin
|
|
int_str(v,s);
|
|
if length(s)<len then
|
|
s:=space(len-length(s))+s;
|
|
end;
|
|
|
|
|
|
procedure fpc_shortstr_int64(v : int64;len : longint;out s : shortstring);[public,alias:'FPC_SHORTSTR_INT64']; compilerproc;
|
|
begin
|
|
int_str(v,s);
|
|
if length(s)<len then
|
|
s:=space(len-length(s))+s;
|
|
end;
|
|
|
|
{$endif CPU64}
|
|
|
|
|
|
{ fpc_shortstr_sInt must appear before this file is included, because }
|
|
{ it's used inside real2str.inc and otherwise the searching via the }
|
|
{ compilerproc name will fail (JM) }
|
|
|
|
{$I real2str.inc}
|
|
|
|
procedure fpc_shortstr_float(d : ValReal;len,fr,rt : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_FLOAT']; compilerproc;
|
|
begin
|
|
str_real(len,fr,d,treal_type(rt),s);
|
|
end;
|
|
|
|
procedure fpc_shortstr_enum(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out s:shortstring);[public,alias:'FPC_SHORTSTR_ENUM'];compilerproc;
|
|
|
|
type Ptypeinfo=^Ttypeinfo;
|
|
Ttypeinfo=record
|
|
kind:byte;
|
|
name:shortstring;
|
|
end;
|
|
|
|
Penuminfo=^Tenuminfo;
|
|
Tenuminfo={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
|
|
ordtype:byte;
|
|
minvalue,maxvalue:longint;
|
|
basetype:pointer;
|
|
namelist:shortstring;
|
|
end;
|
|
|
|
Tsorted_array={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
|
|
o:longint;
|
|
s:Pstring;
|
|
end;
|
|
|
|
var e:Penuminfo;
|
|
p:Pstring;
|
|
l,h,m:cardinal;
|
|
sorted_array:^Tsorted_array;
|
|
i,spaces:byte;
|
|
|
|
label error;
|
|
|
|
begin
|
|
if Pcardinal(ord2strindex)^=0 then
|
|
begin
|
|
{The compiler did generate a lookup table.}
|
|
with Penuminfo(Pbyte(typinfo)+2+length(Ptypeinfo(typinfo)^.name))^ do
|
|
begin
|
|
if (ordinal<minvalue) or (ordinal>maxvalue) then
|
|
goto error; {Invalid ordinal value for this enum.}
|
|
dec(ordinal,minvalue);
|
|
end;
|
|
{Get the address of the string.}
|
|
p:=Pshortstring((PPpointer(ord2strindex)+1+ordinal)^);
|
|
if p=nil then
|
|
goto error; {Invalid ordinal value for this enum.}
|
|
s:=p^;
|
|
end
|
|
else
|
|
begin
|
|
{The compiler did generate a sorted array of (ordvalue,Pstring) tuples.}
|
|
sorted_array:=pointer(Pcardinal(ord2strindex)+2);
|
|
{Use a binary search to get the string.}
|
|
l:=0;
|
|
h:=(Pcardinal(ord2strindex)+1)^-1;
|
|
repeat
|
|
m:=(l+h) div 2;
|
|
if ordinal>sorted_array[m].o then
|
|
l:=m+1
|
|
else if ordinal<sorted_array[m].o then
|
|
h:=m-1
|
|
else
|
|
break;
|
|
if l>h then
|
|
goto error; {Ordinal value not found? Kaboom.}
|
|
until false;
|
|
s:=sorted_array[m].s^;
|
|
end;
|
|
{Pad the string with spaces if necessary.}
|
|
if len>length(s) then
|
|
begin
|
|
spaces:=len-length(s);
|
|
for i:=1 to spaces do
|
|
s[length(s)+i]:=' ';
|
|
inc(byte(s[0]),spaces);
|
|
end;
|
|
exit;
|
|
error:
|
|
{Call runtime error in a central place, this saves space.}
|
|
runerror(107);
|
|
end;
|
|
|
|
{ also define alias for internal use in the system unit }
|
|
procedure fpc_shortstr_enum(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out s:shortstring);external name 'FPC_SHORTSTR_ENUM';
|
|
|
|
procedure fpc_shortstr_currency(c : currency; len,f : SizeInt; out s : shortstring);[public,alias:'FPC_SHORTSTR_CURRENCY']; compilerproc;
|
|
const
|
|
MinLen = 8; { Minimal string length in scientific format }
|
|
|
|
var
|
|
buf : array[1..19] of char;
|
|
i,j,k,reslen,tlen,sign,r,point : longint;
|
|
ic : qword;
|
|
begin
|
|
{ default value for length is -32767 }
|
|
if len=-32767 then
|
|
len:=25;
|
|
if PInt64(@c)^ >= 0 then
|
|
begin
|
|
ic:=QWord(PInt64(@c)^);
|
|
sign:=0;
|
|
end
|
|
else
|
|
begin
|
|
sign:=1;
|
|
ic:=QWord(-PInt64(@c)^);
|
|
end;
|
|
{ converting to integer string }
|
|
tlen:=0;
|
|
repeat
|
|
Inc(tlen);
|
|
buf[tlen]:=Chr(ic mod 10 + $30);
|
|
ic:=ic div 10;
|
|
until ic = 0;
|
|
{ calculating:
|
|
reslen - length of result string,
|
|
r - rounding or appending zeroes,
|
|
point - place of decimal point }
|
|
reslen:=tlen;
|
|
if f <> 0 then
|
|
Inc(reslen); { adding decimal point length }
|
|
if f < 0 then
|
|
begin
|
|
{ scientific format }
|
|
Inc(reslen,5); { adding length of sign and exponent }
|
|
if len < MinLen then
|
|
len:=MinLen;
|
|
r:=reslen-len;
|
|
if reslen < len then
|
|
reslen:=len;
|
|
if r > 0 then
|
|
begin
|
|
reslen:=len;
|
|
point:=tlen - r;
|
|
end
|
|
else
|
|
point:=tlen;
|
|
end
|
|
else
|
|
begin
|
|
{ fixed format }
|
|
Inc(reslen, sign);
|
|
{ prepending fractional part with zeroes }
|
|
while tlen < 5 do
|
|
begin
|
|
Inc(reslen);
|
|
Inc(tlen);
|
|
buf[tlen]:='0';
|
|
end;
|
|
{ Currency have 4 digits in fractional part }
|
|
r:=4 - f;
|
|
point:=f;
|
|
if point <> 0 then
|
|
begin
|
|
if point > 4 then
|
|
point:=4;
|
|
Inc(point);
|
|
end;
|
|
Dec(reslen,r);
|
|
end;
|
|
|
|
{ rounding string if r > 0 }
|
|
if r > 0 then
|
|
begin
|
|
i:=1;
|
|
k:=0;
|
|
for j:=0 to r do
|
|
begin
|
|
buf[i]:=chr(ord(buf[i]) + k);
|
|
if buf[i] >= '5' then
|
|
k:=1
|
|
else
|
|
k:=0;
|
|
Inc(i);
|
|
if i>tlen then
|
|
break;
|
|
end;
|
|
end;
|
|
|
|
{ preparing result string }
|
|
if reslen<len then
|
|
reslen:=len;
|
|
if reslen>High(s) then
|
|
begin
|
|
if r < 0 then
|
|
Inc(r, reslen - High(s));
|
|
reslen:=High(s);
|
|
end;
|
|
SetLength(s,reslen);
|
|
j:=reslen;
|
|
if f<0 then
|
|
begin
|
|
{ writing power of 10 part }
|
|
if PInt64(@c)^ = 0 then
|
|
k:=0
|
|
else
|
|
k:=tlen-5;
|
|
if k >= 0 then
|
|
s[j-2]:='+'
|
|
else
|
|
begin
|
|
s[j-2]:='-';
|
|
k:=-k;
|
|
end;
|
|
s[j]:=Chr(k mod 10 + $30);
|
|
Dec(j);
|
|
s[j]:=Chr(k div 10 + $30);
|
|
Dec(j,2);
|
|
s[j]:='E';
|
|
Dec(j);
|
|
end;
|
|
{ writing extra zeroes if r < 0 }
|
|
while r < 0 do
|
|
begin
|
|
s[j]:='0';
|
|
Dec(j);
|
|
Inc(r);
|
|
end;
|
|
{ writing digits and decimal point }
|
|
for i:=r + 1 to tlen do
|
|
begin
|
|
Dec(point);
|
|
if point = 0 then
|
|
begin
|
|
s[j]:='.';
|
|
Dec(j);
|
|
end;
|
|
s[j]:=buf[i];
|
|
Dec(j);
|
|
end;
|
|
{ writing sign }
|
|
if sign = 1 then
|
|
begin
|
|
s[j]:='-';
|
|
Dec(j);
|
|
end;
|
|
{ writing spaces }
|
|
while j > 0 do
|
|
begin
|
|
s[j]:=' ';
|
|
Dec(j);
|
|
end;
|
|
end;
|
|
|
|
{
|
|
Array Of Char Str() helpers
|
|
}
|
|
|
|
procedure fpc_chararray_sint(v : valsint;len : SizeInt;out a:array of char);compilerproc;
|
|
var
|
|
ss : shortstring;
|
|
maxlen : SizeInt;
|
|
begin
|
|
int_str(v,ss);
|
|
if length(ss)<len then
|
|
ss:=space(len-length(ss))+ss;
|
|
if length(ss)<high(a)+1 then
|
|
maxlen:=length(ss)
|
|
else
|
|
maxlen:=high(a)+1;
|
|
move(ss[1],pchar(@a)^,maxlen);
|
|
end;
|
|
|
|
|
|
procedure fpc_chararray_uint(v : valuint;len : SizeInt;out a : array of char);compilerproc;
|
|
var
|
|
ss : shortstring;
|
|
maxlen : SizeInt;
|
|
begin
|
|
int_str(v,ss);
|
|
if length(ss)<len then
|
|
ss:=space(len-length(ss))+ss;
|
|
if length(ss)<high(a)+1 then
|
|
maxlen:=length(ss)
|
|
else
|
|
maxlen:=high(a)+1;
|
|
move(ss[1],pchar(@a)^,maxlen);
|
|
end;
|
|
|
|
|
|
{$ifndef CPU64}
|
|
|
|
procedure fpc_chararray_qword(v : qword;len : SizeInt;out a : array of char);compilerproc;
|
|
var
|
|
ss : shortstring;
|
|
maxlen : SizeInt;
|
|
begin
|
|
int_str(v,ss);
|
|
if length(ss)<len then
|
|
ss:=space(len-length(ss))+ss;
|
|
if length(ss)<high(a)+1 then
|
|
maxlen:=length(ss)
|
|
else
|
|
maxlen:=high(a)+1;
|
|
move(ss[1],pchar(@a)^,maxlen);
|
|
end;
|
|
|
|
|
|
procedure fpc_chararray_int64(v : int64;len : SizeInt;out a : array of char);compilerproc;
|
|
var
|
|
ss : shortstring;
|
|
maxlen : SizeInt;
|
|
begin
|
|
int_str(v,ss);
|
|
if length(ss)<len then
|
|
ss:=space(len-length(ss))+ss;
|
|
if length(ss)<high(a)+1 then
|
|
maxlen:=length(ss)
|
|
else
|
|
maxlen:=high(a)+1;
|
|
move(ss[1],pchar(@a)^,maxlen);
|
|
end;
|
|
|
|
{$endif CPU64}
|
|
|
|
|
|
procedure fpc_chararray_Float(d : ValReal;len,fr,rt : SizeInt;out a : array of char);compilerproc;
|
|
var
|
|
ss : shortstring;
|
|
maxlen : SizeInt;
|
|
begin
|
|
str_real(len,fr,d,treal_type(rt),ss);
|
|
if length(ss)<high(a)+1 then
|
|
maxlen:=length(ss)
|
|
else
|
|
maxlen:=high(a)+1;
|
|
move(ss[1],pchar(@a)^,maxlen);
|
|
end;
|
|
|
|
{$ifdef FPC_HAS_STR_CURRENCY}
|
|
procedure fpc_chararray_Currency(c : Currency;len,fr : SizeInt;out a : array of char);compilerproc;
|
|
var
|
|
ss : shortstring;
|
|
maxlen : SizeInt;
|
|
begin
|
|
str(c:len:fr,ss);
|
|
if length(ss)<high(a)+1 then
|
|
maxlen:=length(ss)
|
|
else
|
|
maxlen:=high(a)+1;
|
|
move(ss[1],pchar(@a)^,maxlen);
|
|
end;
|
|
{$endif FPC_HAS_STR_CURRENCY}
|
|
|
|
{*****************************************************************************
|
|
Val() Functions
|
|
*****************************************************************************}
|
|
|
|
Function InitVal(const s:shortstring;out negativ:boolean;out base:byte):ValSInt;
|
|
var
|
|
Code : SizeInt;
|
|
begin
|
|
{Skip Spaces and Tab}
|
|
code:=1;
|
|
while (code<=length(s)) and (s[code] in [' ',#9]) do
|
|
inc(code);
|
|
{Sign}
|
|
negativ:=false;
|
|
case s[code] of
|
|
'-' : begin
|
|
negativ:=true;
|
|
inc(code);
|
|
end;
|
|
'+' : inc(code);
|
|
end;
|
|
{Base}
|
|
base:=10;
|
|
if code<=length(s) then
|
|
begin
|
|
case s[code] of
|
|
'$',
|
|
'X',
|
|
'x' : begin
|
|
base:=16;
|
|
inc(code);
|
|
end;
|
|
'%' : begin
|
|
base:=2;
|
|
inc(code);
|
|
end;
|
|
'&' : begin
|
|
Base:=8;
|
|
inc(code);
|
|
end;
|
|
'0' : begin
|
|
if (code < length(s)) and (s[code+1] in ['x', 'X']) then
|
|
begin
|
|
inc(code, 2);
|
|
base := 16;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
{ strip leading zeros }
|
|
while ((code < length(s)) and (s[code] = '0')) do begin
|
|
inc(code);
|
|
end;
|
|
InitVal:=code;
|
|
end;
|
|
|
|
|
|
Function fpc_Val_SInt_ShortStr(DestSize: SizeInt; Const S: ShortString; out Code: ValSInt): ValSInt; [public, alias:'FPC_VAL_SINT_SHORTSTR']; compilerproc;
|
|
var
|
|
u, temp, prev, maxPrevValue, maxNewValue: ValUInt;
|
|
base : byte;
|
|
negative : boolean;
|
|
begin
|
|
fpc_Val_SInt_ShortStr := 0;
|
|
Temp:=0;
|
|
Code:=InitVal(s,negative,base);
|
|
if Code>length(s) then
|
|
exit;
|
|
maxPrevValue := ValUInt(MaxUIntValue) div ValUInt(Base);
|
|
if (base = 10) then
|
|
maxNewValue := MaxSIntValue + ord(negative)
|
|
else
|
|
maxNewValue := MaxUIntValue;
|
|
while Code<=Length(s) do
|
|
begin
|
|
case s[Code] of
|
|
'0'..'9' : u:=Ord(S[Code])-Ord('0');
|
|
'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
|
|
'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
|
|
#0 : break;
|
|
else
|
|
u:=16;
|
|
end;
|
|
Prev := Temp;
|
|
Temp := Temp*ValUInt(base);
|
|
If (u >= base) or
|
|
(ValUInt(maxNewValue-u) < Temp) or
|
|
(prev > maxPrevValue) Then
|
|
Begin
|
|
fpc_Val_SInt_ShortStr := 0;
|
|
Exit
|
|
End;
|
|
Temp:=Temp+u;
|
|
inc(code);
|
|
end;
|
|
code := 0;
|
|
fpc_Val_SInt_ShortStr := ValSInt(Temp);
|
|
If Negative Then
|
|
fpc_Val_SInt_ShortStr := -fpc_Val_SInt_ShortStr;
|
|
If Not(Negative) and (base <> 10) Then
|
|
{sign extend the result to allow proper range checking}
|
|
Case DestSize of
|
|
1: fpc_Val_SInt_ShortStr := shortint(fpc_Val_SInt_ShortStr);
|
|
2: fpc_Val_SInt_ShortStr := smallint(fpc_Val_SInt_ShortStr);
|
|
{$ifdef cpu64}
|
|
4: fpc_Val_SInt_ShortStr := longint(fpc_Val_SInt_ShortStr);
|
|
{$endif cpu64}
|
|
End;
|
|
end;
|
|
|
|
{ we need this for fpc_Val_SInt_Ansistr and fpc_Val_SInt_WideStr because }
|
|
{ we have to pass the DestSize parameter on (JM) }
|
|
Function int_Val_SInt_ShortStr(DestSize: SizeInt; Const S: ShortString; out Code: ValSInt): ValSInt; [external name 'FPC_VAL_SINT_SHORTSTR'];
|
|
|
|
|
|
Function fpc_Val_UInt_Shortstr(Const S: ShortString; out Code: ValSInt): ValUInt; [public, alias:'FPC_VAL_UINT_SHORTSTR']; compilerproc;
|
|
var
|
|
u, prev : ValUInt;
|
|
base : byte;
|
|
negative : boolean;
|
|
begin
|
|
fpc_Val_UInt_Shortstr:=0;
|
|
Code:=InitVal(s,negative,base);
|
|
If Negative or (Code>length(s)) Then
|
|
Exit;
|
|
while Code<=Length(s) do
|
|
begin
|
|
case s[Code] of
|
|
'0'..'9' : u:=Ord(S[Code])-Ord('0');
|
|
'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
|
|
'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
|
|
#0 : break;
|
|
else
|
|
u:=16;
|
|
end;
|
|
prev := fpc_Val_UInt_Shortstr;
|
|
If (u>=base) or
|
|
(ValUInt(MaxUIntValue-u) div ValUInt(Base)<prev) then
|
|
begin
|
|
fpc_Val_UInt_Shortstr:=0;
|
|
exit;
|
|
end;
|
|
fpc_Val_UInt_Shortstr:=fpc_Val_UInt_Shortstr*ValUInt(base) + u;
|
|
inc(code);
|
|
end;
|
|
code := 0;
|
|
end;
|
|
|
|
|
|
{$ifndef CPU64}
|
|
|
|
Function fpc_val_int64_shortstr(Const S: ShortString; out Code: ValSInt): Int64; [public, alias:'FPC_VAL_INT64_SHORTSTR']; compilerproc;
|
|
|
|
var u, temp, prev : qword;
|
|
base : byte;
|
|
negative : boolean;
|
|
|
|
const maxint64=qword($7fffffffffffffff);
|
|
maxqword=qword($ffffffffffffffff);
|
|
|
|
begin
|
|
fpc_val_int64_shortstr := 0;
|
|
Temp:=0;
|
|
Code:=InitVal(s,negative,base);
|
|
if Code>length(s) then
|
|
exit;
|
|
|
|
while Code<=Length(s) do
|
|
begin
|
|
case s[Code] of
|
|
'0'..'9' : u:=Ord(S[Code])-Ord('0');
|
|
'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
|
|
'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
|
|
#0 : break;
|
|
else
|
|
u:=16;
|
|
end;
|
|
Prev:=Temp;
|
|
Temp:=Temp*Int64(base);
|
|
If (u >= base) or
|
|
((base = 10) and
|
|
(maxint64-temp+ord(negative) < u)) or
|
|
((base <> 10) and
|
|
(qword(maxqword-temp) < u)) or
|
|
(prev > maxqword div qword(base)) Then
|
|
Begin
|
|
fpc_val_int64_shortstr := 0;
|
|
Exit
|
|
End;
|
|
Temp:=Temp+u;
|
|
inc(code);
|
|
end;
|
|
code:=0;
|
|
fpc_val_int64_shortstr:=int64(Temp);
|
|
If Negative Then
|
|
fpc_val_int64_shortstr:=-fpc_val_int64_shortstr;
|
|
end;
|
|
|
|
|
|
Function fpc_val_qword_shortstr(Const S: ShortString; out Code: ValSInt): QWord; [public, alias:'FPC_VAL_QWORD_SHORTSTR']; compilerproc;
|
|
|
|
var u, prev: QWord;
|
|
base : byte;
|
|
negative : boolean;
|
|
|
|
const maxqword=qword($ffffffffffffffff);
|
|
|
|
begin
|
|
fpc_val_qword_shortstr:=0;
|
|
Code:=InitVal(s,negative,base);
|
|
If Negative or (Code>length(s)) Then
|
|
Exit;
|
|
while Code<=Length(s) do
|
|
begin
|
|
case s[Code] of
|
|
'0'..'9' : u:=Ord(S[Code])-Ord('0');
|
|
'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
|
|
'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
|
|
#0 : break;
|
|
else
|
|
u:=16;
|
|
end;
|
|
prev := fpc_val_qword_shortstr;
|
|
If (u>=base) or
|
|
((QWord(maxqword-u) div QWord(base))<prev) then
|
|
Begin
|
|
fpc_val_qword_shortstr := 0;
|
|
Exit
|
|
End;
|
|
fpc_val_qword_shortstr:=fpc_val_qword_shortstr*QWord(base) + u;
|
|
inc(code);
|
|
end;
|
|
code := 0;
|
|
end;
|
|
|
|
{$endif CPU64}
|
|
|
|
const
|
|
{$ifdef FPC_HAS_TYPE_EXTENDED}
|
|
valmaxexpnorm=4932;
|
|
{$else}
|
|
{$ifdef FPC_HAS_TYPE_DOUBLE}
|
|
valmaxexpnorm=308;
|
|
{$else}
|
|
{$ifdef FPC_HAS_TYPE_SINGLE}
|
|
valmaxexpnorm=38;
|
|
{$else}
|
|
{$error Unknown floating point precision }
|
|
{$endif}
|
|
{$endif}
|
|
{$endif}
|
|
|
|
Function fpc_Val_Real_ShortStr(const s : shortstring; out Code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_SHORTSTR']; compilerproc;
|
|
var
|
|
hd,
|
|
esign,sign : valreal;
|
|
exponent,i : SizeInt;
|
|
flags : byte;
|
|
begin
|
|
fpc_Val_Real_ShortStr:=0.0;
|
|
code:=1;
|
|
exponent:=0;
|
|
esign:=1;
|
|
flags:=0;
|
|
sign:=1;
|
|
while (code<=length(s)) and (s[code] in [' ',#9]) do
|
|
inc(code);
|
|
if code<=length(s) then
|
|
case s[code] of
|
|
'+' : inc(code);
|
|
'-' : begin
|
|
sign:=-1;
|
|
inc(code);
|
|
end;
|
|
end;
|
|
while (Code<=Length(s)) and (s[code] in ['0'..'9']) do
|
|
begin
|
|
{ Read integer part }
|
|
flags:=flags or 1;
|
|
fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*10+(ord(s[code])-ord('0'));
|
|
inc(code);
|
|
end;
|
|
{ Decimal ? }
|
|
if (length(s)>=code) and (s[code]='.') then
|
|
begin
|
|
hd:=1.0;
|
|
inc(code);
|
|
while (length(s)>=code) and (s[code] in ['0'..'9']) do
|
|
begin
|
|
{ Read fractional part. }
|
|
flags:=flags or 2;
|
|
fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*10+(ord(s[code])-ord('0'));
|
|
hd:=hd*10.0;
|
|
inc(code);
|
|
end;
|
|
fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr/hd;
|
|
end;
|
|
{ Again, read integer and fractional part}
|
|
if flags=0 then
|
|
begin
|
|
fpc_Val_Real_ShortStr:=0.0;
|
|
exit;
|
|
end;
|
|
{ Exponent ? }
|
|
if (length(s)>=code) and (upcase(s[code])='E') then
|
|
begin
|
|
inc(code);
|
|
if Length(s) >= code then
|
|
if s[code]='+' then
|
|
inc(code)
|
|
else
|
|
if s[code]='-' then
|
|
begin
|
|
esign:=-1;
|
|
inc(code);
|
|
end;
|
|
if (length(s)<code) or not(s[code] in ['0'..'9']) then
|
|
begin
|
|
fpc_Val_Real_ShortStr:=0.0;
|
|
exit;
|
|
end;
|
|
while (length(s)>=code) and (s[code] in ['0'..'9']) do
|
|
begin
|
|
exponent:=exponent*10;
|
|
exponent:=exponent+ord(s[code])-ord('0');
|
|
inc(code);
|
|
end;
|
|
end;
|
|
{ evaluate sign }
|
|
{ (before exponent, because the exponent may turn it into a denormal) }
|
|
fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*sign;
|
|
|
|
{ Calculate Exponent }
|
|
hd:=1.0;
|
|
{ the magnitude range maximum (normal) is lower in absolute value than the }
|
|
{ the magnitude range minimum (denormal). E.g. an extended value can go }
|
|
{ up to 1E4932, but "down" to 1E-4951. So make sure that we don't try to }
|
|
{ calculate 1E4951 as factor, since that would overflow and result in 0. }
|
|
if (exponent>valmaxexpnorm-2) then
|
|
begin
|
|
for i:=1 to valmaxexpnorm-2 do
|
|
hd:=hd*10.0;
|
|
if esign>0 then
|
|
fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*hd
|
|
else
|
|
fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr/hd;
|
|
dec(exponent,valmaxexpnorm-2);
|
|
hd:=1.0;
|
|
end;
|
|
for i:=1 to exponent do
|
|
hd:=hd*10.0;
|
|
if esign>0 then
|
|
fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*hd
|
|
else
|
|
fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr/hd;
|
|
|
|
{ Not all characters are read ? }
|
|
if length(s)>=code then
|
|
begin
|
|
fpc_Val_Real_ShortStr:=0.0;
|
|
exit;
|
|
end;
|
|
{ success ! }
|
|
code:=0;
|
|
end;
|
|
|
|
function fpc_val_enum_shortstr(str2ordindex:pointer;const s:shortstring;out code:valsint):longint; [public, alias:'FPC_VAL_ENUM_SHORTSTR']; compilerproc;
|
|
|
|
type Tsorted_array={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
|
|
o:longint;
|
|
s:Pstring;
|
|
end;
|
|
|
|
var l,h,m:cardinal;
|
|
sorted_array:^Tsorted_array;
|
|
spaces:byte;
|
|
t:shortstring;
|
|
|
|
label error;
|
|
|
|
begin
|
|
{Val for numbers accepts spaces at the start, so lets do the same
|
|
for enums. Skip spaces at the start of the string.}
|
|
spaces:=1;
|
|
while (spaces<=length(s)) and (s[spaces]=' ') do
|
|
inc(spaces);
|
|
t:=upcase(copy(s,spaces,255));
|
|
sorted_array:=pointer(Pcardinal(str2ordindex)+1);
|
|
{Use a binary search to get the string.}
|
|
l:=1;
|
|
h:=Pcardinal(str2ordindex)^;
|
|
repeat
|
|
m:=(l+h) div 2;
|
|
if t>upcase(sorted_array[m-1].s^) then
|
|
l:=m+1
|
|
else if t<upcase(sorted_array[m-1].s^) then
|
|
h:=m-1
|
|
else
|
|
break;
|
|
if l>h then
|
|
goto error;
|
|
until false;
|
|
fpc_val_enum_shortstr:=sorted_array[m-1].o;
|
|
exit;
|
|
error:
|
|
{Not found. Find first error position. Take care of the string length.}
|
|
code:=1;
|
|
while (code<=length(s)) and (s[code]=sorted_array[m].s^[code]) do
|
|
inc(code);
|
|
if code>length(s) then
|
|
code:=length(s)+1;
|
|
inc(code,spaces-1); {Add skipped spaces again.}
|
|
{The result of val in case of error is undefined, don't assign a function
|
|
result.}
|
|
end;
|
|
|
|
{Redeclare fpc_val_enum_shortstr for internal use in the system unit.}
|
|
function fpc_val_enum_shortstr(str2ordindex:pointer;const s:shortstring;out code:valsint):longint;external name 'FPC_VAL_ENUM_SHORTSTR';
|
|
|
|
function fpc_Val_Currency_ShortStr(const s : shortstring; out Code : ValSInt): currency; [public, alias:'FPC_VAL_CURRENCY_SHORTSTR']; compilerproc;
|
|
const
|
|
MaxInt64 : Int64 = $7FFFFFFFFFFFFFFF;
|
|
Int64Edge : Int64 = ($7FFFFFFFFFFFFFFF - 10) div 10;
|
|
Int64Edge2 : Int64 = $7FFFFFFFFFFFFFFF div 10;
|
|
var
|
|
res : Int64;
|
|
i,j,power,sign,len : longint;
|
|
FracOverflow : boolean;
|
|
begin
|
|
fpc_Val_Currency_ShortStr:=0;
|
|
res:=0;
|
|
len:=Length(s);
|
|
Code:=1;
|
|
sign:=1;
|
|
power:=0;
|
|
while True do
|
|
if Code > len then
|
|
exit
|
|
else
|
|
if s[Code] in [' ', #9] then
|
|
Inc(Code)
|
|
else
|
|
break;
|
|
{ Read sign }
|
|
case s[Code] of
|
|
'+' : Inc(Code);
|
|
'-' : begin
|
|
sign:=-1;
|
|
inc(code);
|
|
end;
|
|
end;
|
|
{ Read digits }
|
|
FracOverflow:=False;
|
|
i:=0;
|
|
while Code <= len do
|
|
begin
|
|
case s[Code] of
|
|
'0'..'9':
|
|
begin
|
|
j:=Ord(s[code])-Ord('0');
|
|
{ check overflow }
|
|
if (res <= Int64Edge) or (res <= (MaxInt64 - j) div 10) then
|
|
begin
|
|
res:=res*10 + j;
|
|
Inc(i);
|
|
end
|
|
else
|
|
if power = 0 then
|
|
{ exit if integer part overflow }
|
|
exit
|
|
else
|
|
begin
|
|
if not FracOverflow and (j >= 5) and (res < MaxInt64) then
|
|
{ round if first digit of fractional part overflow }
|
|
Inc(res);
|
|
FracOverflow:=True;
|
|
end;
|
|
end;
|
|
'.':
|
|
begin
|
|
if power = 0 then
|
|
begin
|
|
power:=1;
|
|
i:=0;
|
|
end
|
|
else
|
|
exit;
|
|
end;
|
|
else
|
|
break;
|
|
end;
|
|
Inc(Code);
|
|
end;
|
|
if (i = 0) and (power = 0) then
|
|
exit;
|
|
if power <> 0 then
|
|
power:=i;
|
|
power:=4 - power;
|
|
{ Exponent? }
|
|
if Code <= len then
|
|
if s[Code] in ['E', 'e'] then
|
|
begin
|
|
Inc(Code);
|
|
if Code > len then
|
|
exit;
|
|
i:=1;
|
|
case s[Code] of
|
|
'+':
|
|
Inc(Code);
|
|
'-':
|
|
begin
|
|
i:=-1;
|
|
Inc(Code);
|
|
end;
|
|
end;
|
|
{ read exponent }
|
|
j:=0;
|
|
while Code <= len do
|
|
if s[Code] in ['0'..'9'] then
|
|
begin
|
|
if j > 4951 then
|
|
exit;
|
|
j:=j*10 + (Ord(s[code])-Ord('0'));
|
|
Inc(Code);
|
|
end
|
|
else
|
|
exit;
|
|
power:=power + j*i;
|
|
end
|
|
else
|
|
exit;
|
|
|
|
if power > 0 then
|
|
begin
|
|
for i:=1 to power do
|
|
if res <= Int64Edge2 then
|
|
res:=res*10
|
|
else
|
|
exit;
|
|
end
|
|
else
|
|
for i:=1 to -power do
|
|
begin
|
|
if res <= MaxInt64 - 5 then
|
|
Inc(res, 5);
|
|
res:=res div 10;
|
|
end;
|
|
res:=res*sign;
|
|
fpc_Val_Currency_ShortStr:=PCurrency(@res)^;
|
|
Code:=0;
|
|
end;
|
|
|
|
|
|
Procedure SetString (Out S : Shortstring; Buf : PChar; Len : SizeInt);
|
|
begin
|
|
If Len > High(S) then
|
|
Len := High(S);
|
|
SetLength(S,Len);
|
|
If Buf<>Nil then
|
|
begin
|
|
Move (Buf[0],S[1],Len);
|
|
end;
|
|
end;
|
|
|